class CommonObjectEditor( ObjectEditor ): #a generic property grid def initWidget( self, container, objectContainer ): self.grid = PropertyEditor(container) self.grid.propertyChanged.connect( self.onPropertyChanged ) return self.grid def setTarget( self, target ): self.target = target self.grid.setTarget( target ) def refresh( self ): self.grid.refreshAll() def unload( self ): self.grid.clear() self.target = None def onPropertyChanged( self, obj, id, value ): pass
class CommonObjectEditor(ObjectEditor): #a generic property grid def initWidget(self, container, objectContainer): self.grid = PropertyEditor(container) self.grid.propertyChanged.connect(self.onPropertyChanged) return self.grid def setTarget(self, target): self.target = target self.grid.setTarget(target) def refresh(self): self.grid.refreshAll() def unload(self): self.grid.clear() self.target = None def onPropertyChanged(self, obj, id, value): pass
class SerializableEditorInstance(object): def __init__(self, id): self.id = id self.targetNode = None self.targetAsset = None self.container = None self.body = None self.dataDirty = False def createWidget(self, container): self.container = container self.container.setCallbackOnClose(self.onClose) self.toolbar = self.container.addToolBar() self.toolbar.setIconSize(QtCore.QSize(16, 16)) self.actionSave = self.toolbar.addAction(getIcon('save'), 'Save') self.actionLocate = self.toolbar.addAction(getIcon('search-2'), 'Locate') self.actionSave.setEnabled(False) self.actionSave.triggered.connect(self.onActionSave) self.actionLocate.triggered.connect(self.onActionLocate) self.window = window = self.container.addWidgetFromFile( _getModulePath('SerializableEditor.ui')) self.scroll = scroll = addWidgetWithLayout( QtGui.QScrollArea(window.containerProperty), window.containerProperty) scroll.verticalScrollBar().setStyleSheet('width:4px') scroll.setWidgetResizable(True) self.propertyEditor = PropertyEditor(scroll) scroll.setWidget(self.propertyEditor) self.propertyEditor.propertyChanged.connect(self.onPropertyChanged) def setTarget(self, targetNode): self.targetNode = targetNode data = _MOCK.loadAsset(targetNode.getPath()) if data: asset, luaAssetNode = data self.targetAsset = asset self.propertyEditor.setTarget(asset) else: self.targetAsset = None self.propertyEditor.setTarget(None) def refresh(self): self.propertyEditor.refreshAll() def hasTarget(self, targetNode): return self.targetNode == targetNode def resetData(self): if self.targetAsset and self.targetNode: path = self.targetNode.getAbsFilePath() _MOCK.deserializeFromFile(self.targetAsset, path) self.actionSave.setEnabled(False) self.dataDirty = False def saveData(self): if self.targetAsset: path = self.targetNode.getAbsFilePath() _MOCK.serializeToFile(self.targetAsset, path) self.actionSave.setEnabled(False) self.dataDirty = False def onActionSave(self): self.saveData() def onActionLocate(self): if self.targetNode: browser = app.getModule('asset_browser') if browser: browser.locateAsset(self.targetNode) def onPropertyChanged(self, id, value): self.dataDirty = True self.actionSave.setEnabled(True) def onClose(self): if self.dataDirty: res = requestConfirm('data modified!', 'save scene before close?') if res == None: #cancel return False elif res == True: #save self.onActionSave() elif res == False: #no save self.resetData() self.parentModule.removeInstance(self) return True
class EntityEditor( ObjectEditor, SceneObjectEditorMixin ): #a generic property grid def initWidget( self, container, objectContainer ): self.header = EntityHeader( container ) self.grid = PropertyEditor( self.header ) self.header.layout().addWidget( self.grid ) self.grid.setContext( 'scene_editor' ) self.grid.propertyChanged.connect( self.onPropertyChanged ) self.header.buttonEdit .clicked .connect ( self.onEditProto ) self.header.buttonGoto .clicked .connect ( self.onGotoProto ) self.header.buttonUnlink .clicked .connect ( self.onUnlinkProto ) self.initFieldContextMenu( self.grid ) self.initFoldState() self.initAnimatorButton() return self.header def setTarget( self, target ): if not target.components: return introspector = self.getIntrospector() self.target = target self.grid.setTarget( target ) if isMockInstance( target, 'Entity' ): if target['__proto_history']: self.container.setProperty( 'proto', True ) else: self.container.setProperty( 'proto', False ) self.container.repolish() #setup prefab tool protoState = target['PROTO_INSTANCE_STATE'] if protoState: self.header.containerPrefab.show() protoPath = getProtoPath( target ) self.header.labelPrefabPath.setText( protoPath ) else: self.header.containerPrefab.hide() #add component editors for com in target.getSortedComponentList( target ).values(): if com.FLAG_INTERNAL: continue editor = introspector.addObjectEditor( com, context_menu = 'component_context', editor_class = ComponentEditor ) container = editor.getContainer() self.buttonAddComponent = buttonAddComponent = QtGui.QToolButton() buttonAddComponent.setObjectName( 'ButtonIntrospectorAddComponent' ) buttonAddComponent.setText( 'Add Component ...' ) buttonAddComponent.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed ) buttonAddComponent.clicked.connect( self.onButtonAddComponent ) introspector.addWidget( self.buttonAddComponent ) self.restoreFoldState() self.updateAnimatorButton() def onButtonAddComponent( self ): requestSearchView( info = 'select component type to create', context = 'component_creation', on_selection = lambda obj: app.doCommand( 'scene_editor/create_component', name = obj ) ) def onPropertyChanged( self, obj, id, value ): if _MOCK.markProtoInstanceOverrided( obj, id ): self.grid.refershFieldState( id ) if id == 'name': signals.emit( 'entity.renamed', obj, value ) elif id == 'layer': signals.emit( 'entity.renamed', obj, value ) elif id == 'visible': signals.emit( 'entity.visible_changed', obj ) signals.emit( 'entity.modified', obj, 'introspector' ) def onPropertyReset( self, obj, id ): self.grid.refershFieldState( id ) if id == 'name': signals.emit( 'entity.renamed', obj, obj.getName( obj ) ) elif id == 'layer': signals.emit( 'entity.renamed', obj, obj.getName( obj ) ) elif id == 'visible': signals.emit( 'entity.visible_changed', obj ) signals.emit( 'entity.modified', obj, 'introspector' ) def onGotoProto( self ): assetBrowser = app.getModule( 'asset_browser' ) if assetBrowser: assetBrowser.locateAsset( getProtoPath(self.target) ) def onEditProto( self ): path = getProtoPath( self.target ) assetNode = app.getAssetLibrary().getAssetNode( path ) if assetNode: assetNode.edit() def onUnlinkProto( self ): app.doCommand( 'scene_editor/unlink_proto', entity = self.target ) def onUnlinkPrefab( self ): app.doCommand( 'scene_editor/unlink_prefab', entity = self.target ) self.header.containerPrefab.hide() def onPushPrefab( self ): app.doCommand( 'scene_editor/push_prefab', entity = self.target ) def onPullPrefab( self ): app.doCommand( 'scene_editor/pull_prefab', entity = self.target ) def refresh( self ): self.grid.refreshAll() def unload( self ): self.target = None self.grid.clear()
class EntityEditor( ObjectEditor, SceneObjectEditorMixin ): #a generic property grid def initWidget( self, container, objectContainer ): self.header = EntityHeader( container ) self.grid = PropertyEditor( self.header ) self.header.layout().addWidget( self.grid ) self.grid.setContext( 'scene_editor' ) self.grid.propertyChanged.connect( self.onPropertyChanged ) self.header.buttonEdit .clicked .connect ( self.onEditProto ) self.header.buttonGoto .clicked .connect ( self.onGotoProto ) self.header.buttonUnlink .clicked .connect ( self.onUnlinkProto ) self.initFieldContextMenu( self.grid ) self.initFoldState() self.initAnimatorButton() return self.header def setTarget( self, target ): if not target.components: return introspector = self.getIntrospector() self.target = target self.grid.setTarget( target ) if isMockInstance( target, 'Entity' ): if target['__proto_history']: self.container.setProperty( 'proto', True ) else: self.container.setProperty( 'proto', False ) self.container.repolish() #setup prefab tool protoState = target['PROTO_INSTANCE_STATE'] if protoState: self.header.containerPrefab.show() protoPath = getProtoPath( target ) self.header.labelPrefabPath.setText( protoPath ) else: self.header.containerPrefab.hide() #add component editors for com in target.getSortedComponentList( target ).values(): if com.FLAG_INTERNAL: continue editor = introspector.addObjectEditor( com, context_menu = 'component_context', editor_class = ComponentEditor ) container = editor.getContainer() self.buttonAddComponent = buttonAddComponent = QtGui.QToolButton() buttonAddComponent.setObjectName( 'ButtonIntrospectorAddComponent' ) buttonAddComponent.setText( 'Add Component ...' ) buttonAddComponent.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed ) buttonAddComponent.clicked.connect( self.onButtonAddComponent ) introspector.addWidget( self.buttonAddComponent ) self.restoreFoldState() self.updateAnimatorButton() def onButtonAddComponent( self ): requestSearchView( info = 'select component type to create', context = 'component_creation', on_selection = lambda obj: app.doCommand( 'scene_editor/create_component', name = obj ) ) def onPropertyChanged( self, obj, id, value ): if _MOCK.markProtoInstanceOverrided( obj, id ): self.grid.refershFieldState( id ) if id == 'name': signals.emit( 'entity.renamed', obj, value ) elif id == 'layer': signals.emit( 'entity.renamed', obj, value ) elif id == 'visible': signals.emit( 'entity.visible_changed', obj ) signals.emit( 'entity.modified', obj, 'introspector' ) def onPropertyReset( self, obj, id ): self.grid.refershFieldState( id ) if id == 'name': signals.emit( 'entity.renamed', obj, obj.getName( obj ) ) elif id == 'layer': signals.emit( 'entity.renamed', obj, obj.getName( obj ) ) elif id == 'visible': signals.emit( 'entity.visible_changed', obj ) signals.emit( 'entity.modified', obj, 'introspector' ) def onGotoProto( self ): assetBrowser = app.getModule( 'asset_browser' ) if assetBrowser: assetBrowser.locateAsset( getProtoPath(self.target) ) def onEditProto( self ): path = getProtoPath( self.target ) assetNode = app.getAssetLibrary().getAssetNode( path ) if assetNode: assetNode.edit() def onUnlinkProto( self ): app.doCommand( 'scene_editor/unlink_proto', entity = self.target ) def onUnlinkPrefab( self ): app.doCommand( 'scene_editor/unlink_prefab', entity = self.target ) self.header.containerPrefab.hide() def onPushPrefab( self ): app.doCommand( 'scene_editor/push_prefab', entity = self.target ) def onPullPrefab( self ): app.doCommand( 'scene_editor/pull_prefab', entity = self.target ) def refresh( self ): self.grid.refreshAll() def unload( self ): self.target = None self.grid.clear()
class SerializableEditorInstance( object ): def __init__(self, id): self.id = id self.targetNode = None self.targetAsset = None self.container = None self.body = None self.dataDirty = False def createWidget( self, container ): self.container = container self.container.setCallbackOnClose( self.onClose ) self.toolbar = self.container.addToolBar() self.toolbar.setIconSize( QtCore.QSize( 16, 16 ) ) self.actionSave = self.toolbar.addAction( getIcon( 'save' ), 'Save' ) self.actionLocate = self.toolbar.addAction( getIcon( 'search-2' ), 'Locate' ) self.actionSave.setEnabled( False ) self.actionSave.triggered.connect( self.onActionSave ) self.actionLocate.triggered.connect( self.onActionLocate ) self.window = window = self.container.addWidgetFromFile( _getModulePath('SerializableEditor.ui') ) self.scroll = scroll = addWidgetWithLayout( QtGui.QScrollArea( window.containerProperty ), window.containerProperty ) scroll.verticalScrollBar().setStyleSheet('width:4px') scroll.setWidgetResizable( True ) self.propertyEditor = PropertyEditor( scroll ) scroll.setWidget( self.propertyEditor ) self.propertyEditor.propertyChanged.connect( self.onPropertyChanged ) def setTarget(self, targetNode): self.targetNode = targetNode data = _MOCK.loadAsset( targetNode.getPath() ) if data: asset, luaAssetNode = data self.targetAsset = asset self.propertyEditor.setTarget( asset ) else: self.targetAsset = None self.propertyEditor.setTarget( None ) def refresh( self ): self.propertyEditor.refreshAll() def hasTarget( self, targetNode ): return self.targetNode == targetNode def resetData( self ): if self.targetAsset and self.targetNode: path = self.targetNode.getAbsFilePath() _MOCK.deserializeFromFile( self.targetAsset, path ) self.actionSave.setEnabled( False ) self.dataDirty = False def saveData( self ): if self.targetAsset: path = self.targetNode.getAbsFilePath() _MOCK.serializeToFile( self.targetAsset, path ) self.actionSave.setEnabled( False ) self.dataDirty = False def onActionSave( self ): self.saveData() def onActionLocate( self ): if self.targetNode: browser = app.getModule( 'asset_browser' ) if browser: browser.locateAsset( self.targetNode ) def onPropertyChanged( self, id, value ): self.dataDirty = True self.actionSave.setEnabled( True ) def onClose( self ): if self.dataDirty: res = requestConfirm( 'data modified!', 'save scene before close?' ) if res == None: #cancel return False elif res == True: #save self.onActionSave() elif res == False: #no save self.resetData() self.parentModule.removeInstance( self ) return True