class SceneGraphEditor(SceneEditorModule): def __init__(self): super(SceneGraphEditor, self).__init__() self.sceneDirty = False self.activeSceneNode = None self.refreshScheduled = False self.previewing = False self.workspaceState = None def getName(self): return 'scenegraph_editor' def getDependency(self): return ['scene_editor', 'mock'] def onLoad(self): #UI self.windowTitle = 'Scenegraph' self.container = self.requestDockWindow('SceneGraphEditor', title='Scenegraph', size=(200, 200), minSize=(200, 200), dock='left') #Components self.treeFilter = self.container.addWidget(GenericTreeFilter( self.container), expanding=False) self.tree = self.container.addWidget( SceneGraphTreeWidget(self.container, sorting=True, editable=True, multiple_selection=True, drag_mode='internal')) self.treeFilter.setTargetTree(self.tree) self.tree.module = self self.tool = self.addToolBar('scene_graph', self.container.addToolBar()) self.delegate = MOAILuaDelegate(self) self.delegate.load(getModulePath('SceneGraphEditor.lua')) self.entityCreatorMenu = self.addMenu('main/scene/entity_create', {'label': 'Create Entity'}) self.componentCreatorMenu = self.addMenu('main/scene/component_create', {'label': 'Create Component'}) #menu self.addMenuItem('main/file/open_scene', dict(label='Open Scene', shortcut='ctrl+shift+o')) self.addMenuItem('main/file/close_scene', dict(label='Close Scene', shortcut='Ctrl+W')) self.addMenuItem('main/scene/save_scene', dict(label='Save', shortcut='Ctrl+S')) self.addMenuItem('main/scene/locate_scene_asset', dict(label='Locate Scene Asset')) self.addMenu('main/scene/----') self.addMenu('component_context', dict(label='Selected Component')) self.addMenuItem('component_context/remove_component', dict(label='Remove')) self.addMenuItem('component_context/----') self.addMenuItem('component_context/copy_component', dict(label='Copy')) self.addMenuItem('component_context/paste_component', dict(label='Paste Component Here')) self.addMenuItem('component_context/----') self.addMenuItem('component_context/move_component_up', dict(label='Move Up')) self.addMenuItem('component_context/move_component_down', dict(label='Move Down')) self.addMenuItem('component_context/----') self.addMenuItem('component_context/edit_component_alias', dict(label='Edit Alias')) self.addMenu('main/entity', dict(label='Entity')) self.addMenuItem('main/entity/add_empty_entity', dict(label='Create Empty', shortcut='ctrl+alt+N')) self.addMenuItem('main/entity/add_entity', dict(label='Create', shortcut='ctrl+shift+N')) self.addMenuItem('main/entity/----') self.addMenuItem('main/entity/group_entity', dict(label='Group Entites', shortcut='ctrl+G')) self.addMenuItem( 'main/entity/create_group', dict(label='Create Empty Group', shortcut='ctrl+shift+G')) self.addMenuItem('main/entity/----') self.addMenuItem( 'main/entity/load_prefab', dict(label='Load Prefab', shortcut='ctrl+alt+shift+N')) self.addMenuItem( 'main/entity/load_prefab_in_container', dict(label='Load Prefab In Container', shortcut='ctrl+shift+=')) self.addMenuItem('main/entity/----') self.addMenuItem('main/entity/remove_entity', dict(label='Remove')) self.addMenuItem('main/entity/clone_entity', dict(label='Clone', shortcut='ctrl+d')) self.addMenuItem('main/entity/----') self.addMenuItem('main/entity/add_component', dict(label='Add Component', shortcut='ctrl+alt+=')) self.addMenuItem('main/entity/assign_layer', dict(label='Assign Layer', shortcut='ctrl+alt+L')) self.addMenuItem('main/entity/toggle_visibility', dict(label='Toggle Visibility', shortcut='ctrl+/')) self.addMenuItem('main/entity/freeze_entity_pivot', dict(label='Freeze Pivot')) self.addMenuItem('main/entity/----') self.addMenuItem('main/find/find_entity', dict(label='Find In Scene', shortcut='ctrl+f')) self.addMenuItem('main/find/find_entity_in_group', dict(label='Find In Group', shortcut='ctrl+shift+f')) self.addMenuItem('main/find/find_entity_group', dict(label='Find Group', shortcut='ctrl+alt+f')) #Toolbars self.addTool('scene_graph/select_scene', label='Select Scene', icon='settings') self.addTool('scene_graph/----') self.addTool('scene_graph/create_group', label='+ Group', icon='add_folder') self.addTool('scene_graph/----') self.addTool('scene_graph/make_proto', label='Convert To Proto', icon='proto_make') self.addTool('scene_graph/create_proto_instance', label='Create Proto Instance', icon='proto_instantiate') self.addTool('scene_graph/create_proto_container', label='Create Proto Container', icon='proto_container') self.addTool('scene_graph/----') self.addTool('scene_graph/fold_all', label='F') self.addTool('scene_graph/unfold_all', label='U') self.addTool('scene_graph/refresh_tree', label='R') # self.addTool( 'scene_graph/load_prefab', label = '+ P' ) # self.addTool( 'scene_graph/save_prefab', label = '>>P' ) self.addTool('scene/refresh', label='refresh', icon='refresh') #SIGNALS signals.connect('moai.clean', self.onMoaiClean) signals.connect('scene.clear', self.onSceneClear) signals.connect('scene.change', self.onSceneChange) signals.connect('selection.changed', self.onSelectionChanged) signals.connect('selection.hint', self.onSelectionHint) signals.connect('preview.start', self.onPreviewStart) signals.connect('preview.stop', self.onPreviewStop) # signals.connect( 'animator.start', self.onAnimatorStart ) # signals.connect( 'animator.stop' , self.onAnimatorStop ) signals.connect('entity.added', self.onEntityAdded) signals.connect('entity.removed', self.onEntityRemoved) signals.connect('entity.renamed', self.onEntityRenamed) signals.connect('entity.modified', self.onEntityModified) signals.connect('entity.visible_changed', self.onEntityVisibleChanged) signals.connect('entity.pickable_changed', self.onEntityPickableChanged) signals.connect('prefab.unlink', self.onPrefabUnlink) signals.connect('prefab.relink', self.onPrefabRelink) signals.connect('proto.unlink', self.onPrefabUnlink) signals.connect('proto.relink', self.onPrefabRelink) signals.connect('app.ready', self.postAppReady) signals.connect('component.added', self.onComponentAdded) signals.connect('component.removed', self.onComponentRemoved) signals.connect('project.presave', self.preProjectSave) registerSearchEnumerator(sceneObjectSearchEnumerator) registerSearchEnumerator(entityNameSearchEnumerator) registerSearchEnumerator(componentNameSearchEnumerator) registerSearchEnumerator(layerNameSearchEnumerator) def onStart(self): self.refreshCreatorMenu() def postAppReady(self): self.openPreviousScene() def openPreviousScene(self): previousScene = self.getConfig('previous_scene', None) if previousScene: node = self.getAssetLibrary().getAssetNode(previousScene) if node: node.edit() def onStop(self): if self.activeSceneNode: self.setConfig('previous_scene', self.activeSceneNode.getNodePath()) else: self.setConfig('previous_scene', False) def onSetFocus(self): self.container.show() self.container.raise_() self.container.setFocus() def getActiveScene(self): return self.delegate.safeCallMethod('editor', 'getScene') def getActiveSceneRootGroup(self): scene = self.delegate.safeCallMethod('editor', 'getScene') if scene: return scene.rootGroup else: return None def openScene(self, node, protoNode=None): if self.activeSceneNode == node: if self.getModule('scene_view'): self.getModule('scene_view').setFocus() if protoNode: self.delegate.safeCallMethod('editor', 'locateProto', protoNode.getPath()) if self.getModule('scene_view'): self.getModule('scene_view').focusSelection() else: if not self.closeScene(): return if self.getModule('scene_view'): self.getModule('scene_view').makeCanvasCurrent() self.activeSceneNode = node signals.emitNow('scene.pre_open', node) scene = self.delegate.safeCallMethod('editor', 'openScene', node.getPath()) if not scene: #todo: raise something alertMessage( 'error', '%s\n\nfailed to open scene, see console for detailed information.' % node.getPath()) return False signals.emitNow('scene.open', self.activeSceneNode, scene) self.setFocus() self.editingProtoNode = protoNode self.loadWorkspaceState(False) self.delegate.safeCallMethod('editor', 'postOpenScene') def closeScene(self): if not self.activeSceneNode: return True if self.sceneDirty: res = requestConfirm('scene modified!', 'save scene before close?') if res == True: #save self.saveScene() elif res == None: #cancel return elif res == False: #no save pass self.markSceneDirty(False) self.tree.clear() self.getApp().clearCommandStack('scene_editor') self.getSelectionManager().removeSelection(self.getActiveScene()) signals.emitNow('scene.close', self.activeSceneNode) self.delegate.safeCallMethod('editor', 'closeScene') self.activeSceneNode = None return True def onSceneClear(self): # self.tree.clear() pass def markSceneDirty(self, dirty=True): if not self.previewing: self.sceneDirty = dirty def saveWorkspaceState(self): self.retainWorkspaceState() treeFoldState = self.workspaceState['tree_state'] containerFoldState = self.workspaceState['container_state'] entityLockState = self.workspaceState['entity_lock_state'] self.activeSceneNode.setMetaData('tree_state', treeFoldState) self.activeSceneNode.setMetaData('container_state', containerFoldState) self.activeSceneNode.setMetaData('entity_lock_state', entityLockState) def loadWorkspaceState(self, restoreState=True): treeFoldState = self.activeSceneNode.getMetaData('tree_state', None) containerFoldState = self.activeSceneNode.getMetaData( 'container_state', None) entityLockState = self.activeSceneNode.getMetaData( 'entity_lock_state', None) self.workspaceState = { 'tree_state': treeFoldState, 'container_state': containerFoldState, 'entity_lock_state': entityLockState } if restoreState: self.restoreWorkspaceState() def retainWorkspaceState(self): #tree node foldstate treeFoldState = self.tree.saveFoldState() #save introspector foldstate introspectorFoldState = self.delegate.safeCallMethod( 'editor', 'saveIntrospectorFoldState') entityLockState = self.delegate.safeCallMethod('editor', 'saveEntityLockState') self.workspaceState = { 'tree_state': treeFoldState, 'container_state': introspectorFoldState, 'entity_lock_state': entityLockState } def restoreWorkspaceState(self): if not self.workspaceState: return treeState = self.workspaceState.get('tree_state', None) if treeState: self.tree.loadFoldState(treeState) containerState = self.workspaceState.get('container_state', None) if containerState: self.delegate.safeCallMethod('editor', 'loadIntrospectorFoldState', containerState) lockState = self.workspaceState.get('entity_lock_state', None) if lockState: self.delegate.safeCallMethod('editor', 'loadEntityLockState', lockState) def onSceneChange(self): self.tree.hide() self.tree.rebuild() self.restoreWorkspaceState() self.tree.refreshAllContent() self.tree.verticalScrollBar().setValue(0) self.tree.show() if self.editingProtoNode: self.delegate.safeCallMethod('editor', 'locateProto', self.editingProtoNode.getPath()) self.editingProtoNode = None if self.getModule('scene_view'): self.getModule('scene_view').focusSelection() def saveScene(self): if not self.activeSceneNode: return self.markSceneDirty(False) signals.emitNow('scene.save') self.delegate.safeCallMethod('editor', 'saveScene', self.activeSceneNode.getAbsFilePath()) signals.emitNow('scene.saved') self.saveWorkspaceState() def refreshScene(self): if not self.activeSceneNode: return if self.previewing: return self.refreshScheduled = False node = self.activeSceneNode self.retainWorkspaceState() if self.delegate.safeCallMethod('editor', 'refreshScene'): self.restoreWorkspaceState() self.refreshCreatorMenu() def scheduleRefreshScene(self): if not self.activeSceneNode: return self.refreshScheduled = True def refreshCreatorMenu(self): def addEntityMenuItem(name): if name == '----': self.entityCreatorMenu.addChild('----') return self.entityCreatorMenu.addChild({ 'name': 'create_entity_' + name, 'label': name, 'command': 'scene_editor/create_entity', 'command_args': dict(name=name) }) def addComponentMenuItem(name): if name == '----': self.componentCreatorMenu.addChild('----') return self.componentCreatorMenu.addChild({ 'name': 'create_component_' + name, 'label': name, 'command': 'scene_editor/create_component', 'command_args': dict(name=name) }) self.entityCreatorMenu.clear() self.componentCreatorMenu.clear() registry = _MOCK.getEntityRegistry() #entity keys = sorted(registry.keys()) addEntityMenuItem('Entity') addEntityMenuItem('----') for entityName in sorted(registry.keys()): if entityName != 'Entity': addEntityMenuItem(entityName) #component registry = _MOCK.getComponentRegistry() for comName in sorted(registry.keys()): addComponentMenuItem(comName) def needUpdate(self): return True def onUpdate(self): if self.refreshScheduled: self.refreshScene() def preProjectSave(self, prj): if self.activeSceneNode: _MOCK.game.previewingScene = self.activeSceneNode.getNodePath() def onMoaiClean(self): self.tree.clear() def onTool(self, tool): name = tool.name if name == 'fold_all': self.tree.foldAllItems() elif name == 'unfold_all': self.tree.expandAllItems() elif name == 'refresh_tree': self.tree.rebuild() elif name == 'refresh': self.scheduleRefreshScene() elif name == 'make_proto': self.makeProto() elif name == 'create_proto_instance': requestSearchView(info='select a proto to instantiate', context='asset', type='proto', on_selection=lambda obj: self.doCommand( 'scene_editor/create_proto_instance', proto=obj.getNodePath())) elif name == 'create_proto_container': requestSearchView( info='select a proto to create contained instance', context='asset', type='proto', on_selection=lambda obj: self.doCommand( 'scene_editor/create_proto_container', proto=obj.getNodePath())) elif name == 'create_group': self.doCommand('scene_editor/entity_group_create') elif name == 'group_entity': self.doCommand('scene_editor/group_entities') elif name == 'select_scene': self.doCommand('scene_editor/select_scene') def onMenu(self, menu): name = menu.name if name == 'close_scene': if self.previewing: alertMessage('Warning', 'Stop previewing before closing scene') return self.closeScene() elif name == 'open_scene': if self.previewing: alertMessage('Warning', 'Stop previewing before opening scene') return requestSearchView(info='select scene to open', context='asset', type='scene', on_selection=self.openScene) elif name == 'save_scene': if self.previewing: alertMessage('Warning', 'Stop previewing before saving') return self.saveScene() elif name == 'locate_scene_asset': if self.activeSceneNode: assetBrowser = self.getModule('asset_browser') if assetBrowser: assetBrowser.selectAsset(self.activeSceneNode) elif name == 'add_entity': requestSearchView(info='select entity type to create', context='entity_creation', on_selection=lambda obj: self.doCommand( 'scene_editor/create_entity', name=obj)) elif name == 'add_component': requestSearchView(info='select component type to create', context='component_creation', on_selection=lambda obj: self.doCommand( 'scene_editor/create_component', name=obj)) elif name == 'add_empty_entity': self.doCommand('scene_editor/create_entity', name='Entity') elif name == 'load_prefab': requestSearchView(info='select a perfab node to instantiate', context='asset', type='prefab', on_selection=lambda obj: self.doCommand( 'scene_editor/create_prefab_entity', prefab=obj.getNodePath())) elif name == 'load_prefab_in_container': requestSearchView( info='select a perfab node to instantiate( PefabContainer )', context='asset', type='prefab', on_selection=lambda obj: self.doCommand( 'scene_editor/create_prefab_container', prefab=obj.getNodePath())) elif name == 'remove_entity': self.doCommand('scene_editor/remove_entity') elif name == 'clone_entity': self.doCommand('scene_editor/clone_entity') elif name == 'find_entity': requestSearchView( info='search for entity in current scene', context='scene', type='entity', on_selection=lambda x: self.selectEntity(x, focus_tree=True), on_test=self.selectEntity) elif name == 'find_entity_in_group': requestSearchView( info='search for entity in current entity group', context='scene', type='entity_in_group', on_selection=lambda x: self.selectEntity(x, focus_tree=True), on_test=self.selectEntity) elif name == 'find_entity_group': requestSearchView( info='search for group in current scene', context='scene', type='group', on_selection=lambda x: self.selectEntity(x, focus_tree=True), on_test=self.selectEntity) elif name == 'create_group': self.doCommand('scene_editor/entity_group_create') elif name == 'remove_component': context = menu.getContext() if context: self.doCommand('scene_editor/remove_component', target=context) elif name == 'copy_component': context = menu.getContext() if context: self.doCommand('scene_editor/copy_component', target=context) elif name == 'edit_component_alias': context = menu.getContext() if context: oldAlias = context._alias or '' alias = requestString('Edit Alias', 'Enter Alias:', oldAlias) if alias != None: if not alias: alias = False self.doCommand('scene_editor/rename_component', target=context, alias=alias) elif name == 'assign_layer': if not self.tree.getSelection(): return requestSearchView(info='select layer to assign', context='scene_layer', type=_MOCK.Entity, on_selection=self.assignEntityLayer) elif name == 'toggle_visibility': self.doCommand('scene_editor/toggle_entity_visibility') elif name == 'freeze_entity_pivot': self.doCommand('scene_editor/freeze_entity_pivot') def onSelectionChanged(self, selection, key): if key != 'scene': return if self.tree.syncSelection: self.tree.blockSignals(True) self.tree.selectNode(None) for e in selection: self.tree.selectNode(e, add=True) self.tree.blockSignals(False) def selectEntity(self, target, **option): if option.get('focus_tree', False): self.tree.setFocus() self.changeSelection(target) ##----------------------------------------------------------------## def renameEntity(self, target, name): #TODO:command pattern target.setName(target, name) signals.emit('entity.modified', target) def addEntityNode(self, entity): self.tree.addNode(entity, expanded=False) self.tree.setNodeExpanded(entity, False) def removeEntityNode(self, entity): self.tree.removeNode(entity) def assignEntityLayer(self, layerName): #TODO:command pattern if not layerName: return self.doCommand('scene_editor/assign_layer', target=layerName) def onSelectionHint(self, selection): if selection._entity: self.changeSelection(selection._entity) else: self.changeSelection(selection) def onPreviewStart(self): if not self.activeSceneNode: return self.retainWorkspaceState() self.delegate.safeCallMethod('editor', 'retainScene') self.delegate.safeCallMethod('editor', 'startScenePreview') self.previewing = True def onPreviewStop(self): if not self.activeSceneNode: return self.changeSelection(None) self.tree.clear() self.delegate.safeCallMethod('editor', 'stopScenePreview') self.previewing = False if self.delegate.safeCallMethod('editor', 'restoreScene'): self.restoreWorkspaceState() def onAnimatorStart(self): self.retainWorkspaceState() self.delegate.safeCallMethod('editor', 'retainScene') def onAnimatorStop(self): self.tree.clear() self.delegate.safeCallMethod('editor', 'clearScene') if self.delegate.safeCallMethod('editor', 'restoreScene'): self.restoreWorkspaceState() ##----------------------------------------------------------------## def updateEntityPriority(self): if not self.activeSceneNode: return self.markSceneDirty() def onEntityRenamed(self, entity, newname): self.tree.refreshNodeContent(entity) self.markSceneDirty() def onEntityVisibleChanged(self, entity): self.tree.refreshNodeContent(entity) def onEntityPickableChanged(self, entity): self.tree.refreshNodeContent(entity) def onEntityAdded(self, entity, context=None): if context == 'new': self.setFocus() pnode = entity.parent if pnode: self.tree.setNodeExpanded(pnode, True) self.tree.setFocus() self.tree.editNode(entity) self.tree.selectNode(entity) signals.emit('scene.update') self.markSceneDirty() def onEntityRemoved(self, entity): signals.emit('scene.update') self.markSceneDirty() def onEntityModified(self, entity, context=None): self.markSceneDirty() ##----------------------------------------------------------------## def onComponentAdded(self, com, entity): signals.emit('scene.update') self.markSceneDirty() def onComponentRemoved(self, com, entity): signals.emit('scene.update') self.markSceneDirty() ##----------------------------------------------------------------## def onPrefabUnlink(self, entity): self.tree.refreshNodeContent(entity, updateChildren=True) def onPrefabRelink(self, entity): self.tree.refreshNodeContent(entity, updateChildren=True) def createPrefab(self, targetPrefab): selection = self.getSelection() if not selection: return if len(selection) > 1: return alertMessage( 'multiple entities cannot be converted into prefab') target = selection[0] self.doCommand('scene_editor/create_prefab', entity=target, prefab=targetPrefab.getNodePath(), file=targetPrefab.getAbsFilePath()) def makeProto(self): selection = self.getSelection() if not selection: return if len(selection) > 1: return alertMessage( 'multiple entities cannot be converted into Proto') target = selection[0] if not target: return if requestConfirm('convert proto', 'Convert this Entity into Proto?'): self.doCommand('scene_editor/make_proto', entity=target) self.tree.refreshNodeContent(target) def createProtoInstance(self): pass ##----------------------------------------------------------------## def onCopyEntity(self): entityGroupData = self.delegate.callMethod( 'editor', 'makeSceneSelectionCopyData') if not entityGroupData: return False clip = QtGui.QApplication.clipboard() mime = QtCore.QMimeData() text = '' for s in self.getSelection(): if text == '': text = text + s.name else: text = text + '\n' + s.name mime.setText(text) mime.setData(GII_MIME_ENTITY_DATA, entityGroupData.encode('utf-8')) clip.setMimeData(mime) return True def onPasteEntity(self): clip = QtGui.QApplication.clipboard() mime = clip.mimeData() if mime.hasFormat(GII_MIME_ENTITY_DATA): data = mime.data(GII_MIME_ENTITY_DATA) self.doCommand('scene_editor/paste_entity', data=str(data).decode('utf-8')) ##----------------------------------------------------------------## def onCopyComponent(self): entityGroupData = self.delegate.callMethod('editor', 'makeEntityCopyData') if not entityGroupData: return False clip = QtGui.QApplication.clipboard() mime = QtCore.QMimeData() text = '' for s in self.getSelection(): if text == '': text = text + s.name else: text = text + '\n' + s.name mime.setText(text) mime.setData(GII_MIME_ENTITY_DATA, str(entityGroupData)) clip.setMimeData(mime) return True def onPasteComponent(self): clip = QtGui.QApplication.clipboard() mime = clip.mimeData() if mime.hasFormat(GII_MIME_ENTITY_DATA): data = mime.data(GII_MIME_ENTITY_DATA) self.doCommand('scene_editor/paste_entity', data=str(data))
class AnimatorView(SceneEditorModule): name = "animator" dependency = ["scene_editor", "mock"] def onLoad(self): # UI self.windowTitle = "Animator" self.window = self.requestDockWindow( "AnimatorView", title="Animator", size=(120, 120), minSize=(120, 120), dock="bottom" ) self.widget = AnimatorWidget() self.window.addWidget(self.widget) self.toolbarTarget = self.addToolBar("animator_target", self.widget.toolbarTarget) self.toolbarClips = self.addToolBar("animator_clips", self.widget.toolbarClips) self.toolbarPlay = self.addToolBar("animator_play", self.widget.toolbarPlay) self.toolbarTrack = self.addToolBar("animator_track", self.widget.toolbarTrack) # self.toolbarEdit = self.addToolBar( 'animator_play', self.widget.toolbarEdit ) signals.connect("scene.close", self.onSceneClose) signals.connect("scene.save", self.preSceneSave) signals.connect("scene.saved", self.postSceneSave) # addWidgetWithLaytut( toolbar, # self.widget.containerEditTool ) self.addTool("animator_target/change_context", label="Change Context", icon="in") self.addTool("animator_target/save_data", label="Save Data", icon="save") self.addTool("animator_clips/add_clip_group", label="add group", icon="add_folder") self.addTool("animator_clips/add_clip", label="add", icon="add") self.addTool("animator_clips/remove_clip", label="remove", icon="remove") self.addTool("animator_clips/clone_clip", label="clone", icon="clone") self.addTool("animator_play/goto_start", label="to start", icon="rewind") # self.addTool( 'animator_play/prev_key', label = 'prev key', icon = 'previous' ) self.addTool("animator_play/stop", label="stop", icon="stop") self.addTool("animator_play/play", label="play", icon="play", type="check") # self.addTool( 'animator_play/next_key', label = 'next key', icon = 'next' ) self.addTool("animator_play/goto_end", label="to end", icon="fast_forward") self.addTool("animator_play/----") self.addTool("animator_play/toggle_repeat", label="toggle repeat", icon="repeat", type="check") # SIGNALS self.addTool("animator_track/add_track_group", label="add group", icon="add_folder") self.addTool("animator_track/add_track", label="add", icon="add") self.addTool("animator_track/remove_track", label="remove", icon="remove") # signals.connect("selection.changed", self.onSceneSelectionChanged) self.delegate = MOAILuaDelegate(self) self.delegate.load(_getModulePath("AnimatorView.lua")) self.widget.setOwner(self) # playback self.previewing = False self.setEditing(False) self.targetAnimator = None self.targetClip = None self.targetAnimatorData = None self.currentTrack = None self.previewing = False self.previewLoop = False self.previewTime = 0.0 self.previewStep = 1.0 / 60.0 self.previewTimer = QtCore.QTimer(self.widget) self.previewTimer.setInterval(1000.0 / 65) self.previewTimer.stop() self.previewTimer.timeout.connect(self.onPreviewTimer) def onStart(self): pass def setEditing(self, editing): self.widget.timeline.setEnabled(editing) self.widget.treeTracks.setEnabled(editing) self.findTool("animator_play").setEnabled(editing) self.findTool("animator_track").setEnabled(editing) self.findTool("animator_clips/add_clip_group").setEnabled(editing) self.findTool("animator_clips/add_clip").setEnabled(editing) self.findTool("animator_clips/remove_clip").setEnabled(editing) self.findTool("animator_clips/clone_clip").setEnabled(editing) def setTargetAnimator(self, target): self.saveAnimatorData() if target == self.targetAnimator: return if self.previewing: self.stopPreview() self.targetAnimator = target self.targetClip = None self.delegate.callMethod("view", "setTargetAnimator", target) self.targetAnimatorData = self.delegate.callMethod("view", "getTargetAnimatorData") self.widget.rebuild() if self.targetAnimator: self.setEditing(True) signals.emit("animator.start") else: self.setEditing(False) signals.emit("animator.stop") path = self.delegate.callMethod("view", "getTargetAnimatorDataPath") if path: self.window.setWindowTitle("Animator - %s" % path) else: self.window.setWindowTitle("Animator") clip = self.delegate.callMethod("view", "getPreviousTargeClip", target) self.enableTool("animator_play", False) self.enableTool("animator_track", False) if clip: self.widget.treeClips.selectNode(clip) else: self.widget.treeClips.selectFirstItem() self.applyTime(0, True) def setTargetClip(self, clip): wasPreviewing = self.previewing if self.previewing: self.stopPreview() self.targetClip = clip self.delegate.callMethod("view", "setTargetClip", clip) self.widget.rebuildTimeline() self.enableTool("animator_play", bool(clip)) self.enableTool("animator_track", bool(clip)) self.applyTime(0, True) if wasPreviewing: self.startPreview() def setCurrentTrack(self, track): self.currentTrack = track self.delegate.callMethod("view", "setCurrentTrack", track) def getClipList(self): if self.targetAnimatorData: clipList = self.targetAnimatorData.clips return [clip for clip in clipList.values()] else: return [] def getRootClipGroup(self): if self.targetAnimatorData: return self.targetAnimatorData.getRootGroup(self.targetAnimatorData) def getTrackList(self): if self.targetClip: trackList = self.targetClip.getTrackList(self.targetClip) return [track for track in trackList.values()] else: return [] def getMarkerList(self): if self.targetClip: markerList = self.targetClip.getMarkerList(self.targetClip) return [track for track in markerList.values()] else: return [] def getClipRoot(self): if self.targetClip: return self.targetClip.getRoot(self.targetClip) else: return None def addClip(self): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand( "scene_editor/animator_add_clip", animator_data=self.targetAnimatorData, parent_group=targetGroup ) clip = cmd.getResult() if clip: self.widget.addClip(clip, True) return clip def addClipGroup(self): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand( "scene_editor/animator_add_clip_group", animator_data=self.targetAnimatorData, parent_group=targetGroup ) group = cmd.getResult() if group: self.widget.addClip(group, True) return group def removeClipNode(self): for clip in self.widget.treeClips.getSelection(): if self.doCommand( "scene_editor/animator_remove_clip_node", animator_data=self.targetAnimatorData, target_node=clip ): self.widget.removeClip(clip) def cloneClipNode(self): if not self.targetClip: return result = [] for clip in self.widget.treeClips.getSelection(): cmd = self.doCommand( "scene_editor/animator_clone_clip_node", animator_data=self.targetAnimatorData, target_node=clip ) if cmd: cloned = cmd.getResult() self.widget.addClip(cloned) result.append(cloned) return result def onObjectEdited(self, obj): if self.targetClip: self.delegate.callMethod("view", "clearPreviewState") self.delegate.callMethod("view", "markClipDirty") def onSceneSelectionChanged(self, selection, key): if key != "scene": return # find animator component # self.findTargetAnimator() def findTargetAnimator(self): target = self.delegate.callMethod("view", "findTargetAnimator") self.setTargetAnimator(target) return target def checkTargetAnimator(self): if not self.targetAnimator: alertMessage("No Animator", "No Animator Selected", "question") return False return True def addMarker(self): if not self.targetClip: return cmd = self.doCommand( "scene_editor/animator_add_marker", target_clip=self.targetClip, target_pos=self.widget.getCursorPos() ) if cmd: marker = cmd.getResult() self.widget.addMarker(marker) def addKeyForField(self, target, fieldId): if not self.checkTargetAnimator(): return if not self.targetClip: self.addClip() # alertMessage( 'No Clip', 'You need to select a Clip first', 'question' ) # return False keys = self.delegate.callMethod("view", "addKeyForField", target, fieldId) if keys: for key in keys.values(): self.widget.addKey(key, True) def addKeyForEvent(self, target, eventId): pass def addCustomAnimatorTrack(self, target, trackClasId): if not self.checkTargetAnimator(): return track = self.delegate.callMethod("view", "addCustomAnimatorTrack", target, trackClasId) if track: self.widget.addTrack(track) def addKeyForSelectedTracks(self): # TODO: command selectedTracks = self.widget.getTrackSelection() for track in selectedTracks: keys = self.delegate.callMethod("view", "addKeyForSelectedTrack", track) if keys: for key in keys.values(): self.widget.addKey(key, True) def removeSelectedKeys(self): # TODO: command selectedKeys = self.widget.getKeySelection() for key in selectedKeys: self.widget.removeKey(key) def cloneSelectedKeys(self): # TODO: command selectedKeys = self.widget.getKeySelection() cloned = [] for key in selectedKeys: clonedKey = self.delegate.callMethod("view", "cloneKey", key) if clonedKey: cloned.append(clonedKey) for clonedKey in cloned: self.widget.addKey(clonedKey, False) def onKeyRemoving(self, key): if self.delegate.callMethod("view", "removeKey", key) != False: return True def onTimelineKeyChanged(self, key, pos, length): self.delegate.callMethod("view", "updateTimelineKey", key, pos, length) def onTimelineKeyCurveValueChanged(self, key, value): self.delegate.callMethod("view", "updateTimelineKeyCurveValue", key, value) def onTimelineKeyTweenModeChanged(self, key, mode): self.delegate.callMethod("view", "updateTimelineKeyTweenMode", key, mode) def onTimelineKeyBezierPointChanged(self, key, bpx0, bpy0, bpx1, bpy1): self.delegate.callMethod("view", "updateTimelineKeyBezierPoint", key, bpx0, bpy0, bpx1, bpy1) def onTimelineMarkerChanged(self, marker, pos): self.delegate.callMethod("view", "updateTimelineMarker", marker, pos) def renameTrack(self, track, name): self.delegate.callMethod("view", "renameTrack", track, name) def renameClip(self, clip, name): self.delegate.callMethod("view", "renameClip", clip, name) def onTool(self, tool): name = tool.name if name == "change_context": target0 = self.targetAnimator target1 = self.findTargetAnimator() if (not target0) and (not target1): alertMessage("No Animator", "No Animator found in selected entity scope", "question") elif name == "save_data": self.saveAnimatorData() elif name == "add_clip": if self.checkTargetAnimator(): self.addClip() elif name == "add_clip_group": if self.checkTargetAnimator(): self.addClipGroup() elif name == "remove_clip": if self.checkTargetAnimator(): self.removeClipNode() elif name == "clone_clip": if self.checkTargetAnimator(): self.cloneClipNode() elif name == "add_track_group": group = self.delegate.callMethod("view", "addTrackGroup") if group: self.widget.addTrack(group, True) elif name == "remove_track": for track in self.widget.treeTracks.getSelection(): self.delegate.callMethod("view", "removeTrack", track) self.widget.removeTrack(track) # preview elif name == "goto_start": self.gotoStart() elif name == "goto_end": self.gotoEnd() elif name == "play": if tool.getValue(): self.startPreview() else: self.stopPreview(False) elif name == "stop": self.stopPreview(True) elif name == "toggle_repeat": self.delegate.callMethod("view", "togglePreviewRepeat", tool.getValue()) def getActiveSceneView(self): return self.getModule("scene_view") # preview def startPreview(self): self.saveAnimatorData() if self.delegate.callMethod("view", "startPreview", self.previewTime): self.widget.setCursorMovable(False) self.previewing = True self.findTool("animator_play/play").setValue(True) self.previewTimer.start() self.getApp().setMinimalMainLoopBudget() def stopPreview(self, rewind=False): if self.previewing: self.delegate.callMethod("view", "stopPreview") self.getApp().resetMainLoopBudget() self.widget.setCursorMovable(True) self.previewing = False self.findTool("animator_play/play").setValue(False) self.previewTimer.stop() signals.emit("entity.modified", None, "") if rewind: self.gotoStart() def onPreviewTimer(self): playing, currentTime = self.delegate.callMethod("view", "doPreviewStep") self.previewTime = currentTime self.getActiveSceneView().forceUpdate() self.widget.setCursorPos(self.previewTime) if not playing: self.stopPreview() # signals.emit( 'entity.modified', None , '' ) def gotoStart(self): if self.previewing: self.delegate.callMethod("view", "applyTime", 0) else: self.widget.setCursorPos(0, True) def gotoEnd(self): if self.previewing: self.delegate.callMethod("view", "applyTime", 10) else: self.widget.setCursorPos(10, True) def applyTime(self, t, syncCursor=False): self.previewTime = self.delegate.callMethod("view", "applyTime", t) self.getActiveSceneView().forceUpdate() signals.emit("entity.modified", None, "") if syncCursor: self.widget.setCursorPos(t) def saveAnimatorData(self): if not self.targetAnimator: return self.delegate.callMethod("view", "saveData") def preSceneSave(self): if self.targetAnimator: self.delegate.callMethod("view", "restoreEntityState") def postSceneSave(self): if self.targetAnimator: self.applyTime(self.previewTime) def onSceneClose(self, scene): self.setTargetAnimator(None) def refreshTimeline(self): self.widget.rebuildTimeline() def refreshClipList(self): self.widget.rebuildClipList() def refreshAll(self): self.widget.rebuild()
class AnimatorView( SceneEditorModule ): name = 'animator' dependency = [ 'scene_editor', 'mock' ] def onLoad( self ): #UI self.windowTitle = 'Animator' self.window = self.requestDockWindow( 'AnimatorView', title = 'Animator', size = (120,120), minSize = (120,120), dock = 'bottom' ) self.widget = AnimatorWidget() self.window.addWidget( self.widget ) self.toolbarTarget = self.addToolBar( 'animator_target', self.widget.toolbarTarget ) self.toolbarClips = self.addToolBar( 'animator_clips', self.widget.toolbarClips ) self.toolbarPlay = self.addToolBar( 'animator_play', self.widget.toolbarPlay ) self.toolbarTrack = self.addToolBar( 'animator_track', self.widget.toolbarTrack ) # self.toolbarEdit = self.addToolBar( 'animator_play', self.widget.toolbarEdit ) signals.connect( 'scene.close', self.onSceneClose ) signals.connect( 'scene.save', self.preSceneSave ) signals.connect( 'scene.saved', self.postSceneSave ) # addWidgetWithLaytut( toolbar, # self.widget.containerEditTool ) self.addTool( 'animator_target/change_context', label = 'Change Context', icon = 'in' ) self.addTool( 'animator_target/save_data', label = 'Save Data', icon = 'save' ) self.addTool( 'animator_clips/add_clip_group', label = 'add group', icon = 'add_folder' ) self.addTool( 'animator_clips/add_clip', label = 'add', icon = 'add' ) self.addTool( 'animator_clips/remove_clip', label = 'remove', icon = 'remove' ) self.addTool( 'animator_clips/clone_clip', label = 'clone', icon = 'clone' ) self.addTool( 'animator_play/goto_start', label = 'to start', icon = 'rewind' ) # self.addTool( 'animator_play/prev_key', label = 'prev key', icon = 'previous' ) self.addTool( 'animator_play/stop', label = 'stop', icon = 'stop' ) self.addTool( 'animator_play/play', label = 'play', icon = 'play', type = 'check' ) # self.addTool( 'animator_play/next_key', label = 'next key', icon = 'next' ) self.addTool( 'animator_play/goto_end', label = 'to end', icon = 'fast_forward' ) self.addTool( 'animator_play/toggle_repeat', label = 'toggle repeat', icon = 'repeat', type = 'check' ) self.comboPreviewSpeed = QtGui.QComboBox() self.comboPreviewSpeed.addItems([ e[0] for e in PREVIEW_SPEED_OPTIONS ] ) self.comboPreviewSpeed.setCurrentIndex( 4 ) #1x self.comboPreviewSpeed.currentIndexChanged.connect( self.onPreviewSpeedChange ) self.addTool( 'animator_play/preview_speed', widget = self.comboPreviewSpeed ) #SIGNALS self.addTool( 'animator_track/locate_target', label = 'locate', icon = 'find' ) self.addTool( 'animator_track/----' ) self.addTool( 'animator_track/add_track_group', label = 'add group', icon = 'add_folder' ) self.addTool( 'animator_track/add_track', label = 'add', icon = 'add' ) self.addTool( 'animator_track/remove_track', label = 'remove', icon = 'remove' ) # signals.connect( 'selection.changed', self.onSceneSelectionChanged ) self.delegate = MOAILuaDelegate( self ) self.delegate.load( _getModulePath( 'AnimatorView.lua' ) ) self.widget.setOwner( self ) #playback self.previewing = False self.setEditing( False ) self.targetAnimator = None self.targetClip = None self.targetAnimatorData = None self.currentTrack = None self.previewing = False self.previewLoop = False self.previewTime = 0.0 self.previewStep = 1.0/60.0 self.previewTimer = QtCore.QTimer( self.widget ) self.previewTimer.setInterval( 1000.0/65 ) self.previewTimer.stop() self.previewTimer.timeout.connect( self.onPreviewTimer ) def onStart( self ): pass def setEditing( self, editing ): self.widget.timeline.setEnabled( editing ) self.widget.treeTracks.setEnabled( editing ) self.findTool( 'animator_play' ).setEnabled( editing ) self.findTool( 'animator_track' ).setEnabled( editing ) self.findTool( 'animator_clips/add_clip_group').setEnabled( editing ) self.findTool( 'animator_clips/add_clip' ).setEnabled( editing ) self.findTool( 'animator_clips/remove_clip' ).setEnabled( editing ) self.findTool( 'animator_clips/clone_clip' ).setEnabled( editing ) def setTargetAnimator( self, target ): self.saveAnimatorData() if target == self.targetAnimator: return if self.previewing: self.stopPreview() self.targetAnimator = target self.targetClip = None self.delegate.callMethod( 'view', 'setTargetAnimator', target ) self.targetAnimatorData = self.delegate.callMethod( 'view', 'getTargetAnimatorData' ) self.widget.rebuild() if self.targetAnimator: self.setEditing( True ) signals.emit( 'animator.start' ) else: self.setEditing( False ) signals.emit( 'animator.stop' ) path = self.delegate.callMethod( 'view', 'getTargetAnimatorDataPath' ) if path: self.window.setWindowTitle( 'Animator - %s' % path ) else: self.window.setWindowTitle( 'Animator' ) clip = self.delegate.callMethod( 'view', 'getPreviousTargeClip', target ) self.enableTool( 'animator_play' , False ) self.enableTool( 'animator_track', False ) if clip: self.widget.treeClips.selectNode( clip ) else: self.widget.treeClips.selectFirstItem() self.applyTime( 0, True ) def setTargetClip( self, clip ): wasPreviewing = self.previewing if self.previewing: self.stopPreview() self.targetClip = clip self.delegate.callMethod( 'view', 'setTargetClip', clip ) self.widget.rebuildTimeline() self.enableTool( 'animator_play' , bool( clip ) ) self.enableTool( 'animator_track', bool( clip ) ) self.applyTime( 0, True ) if wasPreviewing: self.startPreview() def setCurrentTrack( self, track ): self.currentTrack = track self.delegate.callMethod( 'view', 'setCurrentTrack', track ) def getTargetClipLength( self ): return self.delegate.callMethod( 'view', 'getTargetClipLength' ) def getClipList( self ): if self.targetAnimatorData: clipList = self.targetAnimatorData.clips return [ clip for clip in clipList.values() ] else: return [] def getRootClipGroup( self ): if self.targetAnimatorData: return self.targetAnimatorData.getRootGroup( self.targetAnimatorData ) def getTrackList( self ): if self.targetClip: trackList = self.targetClip.getTrackList( self.targetClip ) return [ track for track in trackList.values() ] else: return [] def getMarkerList( self ): if self.targetClip: markerList = self.targetClip.getMarkerList( self.targetClip ) return [ track for track in markerList.values() ] else: return [] def getClipRoot( self ): if self.targetClip: return self.targetClip.getRoot( self.targetClip ) else: return None def addClip( self ): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand( 'scene_editor/animator_add_clip', animator_data = self.targetAnimatorData, parent_group = targetGroup ) clip = cmd.getResult() if clip: self.widget.addClip( clip, True ) return clip def addClipGroup( self ): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand( 'scene_editor/animator_add_clip_group', animator_data = self.targetAnimatorData, parent_group = targetGroup ) group = cmd.getResult() if group: self.widget.addClip( group, True ) return group def removeClipNode( self ): for clip in self.widget.treeClips.getSelection(): if self.doCommand( 'scene_editor/animator_remove_clip_node', animator_data = self.targetAnimatorData, target_node = clip ): self.widget.removeClip( clip ) def cloneClipNode( self ): if not self.targetClip: return result = [] for clip in self.widget.treeClips.getSelection(): cmd = self.doCommand( 'scene_editor/animator_clone_clip_node', animator_data = self.targetAnimatorData, target_node = clip ) if cmd: cloned = cmd.getResult() self.widget.addClip( cloned ) result.append( cloned ) return result def onObjectEdited( self, obj ): if self.targetClip: self.delegate.callMethod( 'view', 'clearPreviewState' ) self.delegate.callMethod( 'view', 'markClipDirty' ) def onSceneSelectionChanged( self, selection, key ): if key != 'scene': return #find animator component # self.findTargetAnimator() def findTargetAnimator( self ): target = self.delegate.callMethod( 'view', 'findTargetAnimator' ) self.setTargetAnimator( target ) return target def checkTargetAnimator( self ): if not self.targetAnimator: alertMessage( 'No Animator', 'No Animator Selected', 'question' ) return False return True def addMarker( self ): if not self.targetClip: return cmd = self.doCommand( 'scene_editor/animator_add_marker' , target_clip = self.targetClip, target_pos = self.widget.getCursorPos() ) if cmd: marker = cmd.getResult() self.widget.addMarker( marker ) def addKeyForField( self, target, fieldId ): if not self.checkTargetAnimator(): return if not self.targetClip: self.addClip() # alertMessage( 'No Clip', 'You need to select a Clip first', 'question' ) # return False keys = self.delegate.callMethod( 'view', 'addKeyForField', target, fieldId ) if keys: for key in keys.values(): self.widget.addKey( key, True ) def addKeyForEvent( self, target, eventId ): pass def addCustomAnimatorTrack( self, target, trackClasId ): if not self.checkTargetAnimator(): return track = self.delegate.callMethod( 'view', 'addCustomAnimatorTrack', target, trackClasId ) if track: self.widget.addTrack( track ) def addKeyForSelectedTracks( self ): #TODO: command selectedTracks = self.widget.getTrackSelection() for track in selectedTracks: keys = self.delegate.callMethod( 'view', 'addKeyForSelectedTrack', track ) if keys: for key in keys.values(): self.widget.addKey( key, True ) def removeSelectedKeys( self ): #TODO: command selectedKeys = self.widget.getKeySelection() for key in selectedKeys: self.widget.removeKey( key ) def cloneSelectedKeys( self ): #TODO: command selectedKeys = self.widget.getKeySelection() cloned = [] for key in selectedKeys: clonedKey = self.delegate.callMethod( 'view', 'cloneKey', key ) if clonedKey: cloned.append( clonedKey ) for clonedKey in cloned: self.widget.addKey( clonedKey, False ) def onKeyRemoving( self, key ): if self.delegate.callMethod( 'view', 'removeKey', key ) != False: return True def onMarkerRemoving( self, marker ): if self.delegate.callMethod( 'view', 'removeMarker', marker ) != False: return True def onClipLengthChanging( self, t1 ): if self.delegate.callMethod( 'view', 'setTargetClipLength', t1 ) != False: return True def onTimelineKeyChanged( self, key, pos, length ): self.delegate.callMethod( 'view', 'updateTimelineKey', key, pos, length ) def onTimelineKeyCurveValueChanged( self, key, value ): self.delegate.callMethod( 'view', 'updateTimelineKeyCurveValue', key, value ) def onTimelineKeyTweenModeChanged( self, key, mode ): self.delegate.callMethod( 'view', 'updateTimelineKeyTweenMode', key, mode ) def onTimelineKeyBezierPointChanged( self, key, bpx0, bpy0, bpx1, bpy1 ): self.delegate.callMethod( 'view', 'updateTimelineKeyBezierPoint', key, bpx0, bpy0, bpx1, bpy1 ) def onTimelineMarkerChanged( self, marker, pos ): self.delegate.callMethod( 'view', 'updateTimelineMarker', marker, pos ) def toggleTrackActive( self, track ): #TODO: command # self.module.doCommand( 'scene_editor/toggle_entity_visibility', target = node ) self.delegate.callMethod( 'view', 'toggleTrackActive', track ) def renameTrack( self, track, name ): self.delegate.callMethod( 'view', 'renameTrack', track, name ) def renameClip( self, clip, name ): self.delegate.callMethod( 'view', 'renameClip', clip, name ) def onTool( self, tool ): name = tool.name if name == 'change_context': target0 = self.targetAnimator target1 = self.findTargetAnimator() if ( not target0 ) and ( not target1 ): alertMessage( 'No Animator', 'No Animator found in selected entity scope', 'question' ) elif name == 'save_data': self.saveAnimatorData() elif name == 'add_clip': if self.checkTargetAnimator(): self.addClip() elif name == 'add_clip_group': if self.checkTargetAnimator(): self.addClipGroup() elif name == 'remove_clip': if self.checkTargetAnimator(): self.removeClipNode() elif name == 'clone_clip': if self.checkTargetAnimator(): self.cloneClipNode() elif name == 'add_track_group': group = self.delegate.callMethod( 'view', 'addTrackGroup' ) if group: self.widget.addTrack( group, True ) elif name == 'remove_track': for track in self.widget.treeTracks.getSelection(): self.delegate.callMethod( 'view', 'removeTrack', track ) self.widget.removeTrack( track ) elif name == 'locate_target': for track in self.widget.treeTracks.getSelection(): sceneGraphEditor = self.getModule( 'scenegraph_editor') if sceneGraphEditor: targetEntity = self.delegate.callMethod( 'view', 'findTrackEntity', track ) if targetEntity: sceneGraphEditor.selectEntity( targetEntity, focus_tree = True ) #pass return #preview elif name == 'goto_start': self.gotoStart() elif name == 'goto_end': self.gotoEnd() elif name == 'play': if tool.getValue(): self.startPreview() else: self.stopPreview( False ) elif name == 'stop': self.stopPreview( True ) elif name == 'toggle_repeat': self.delegate.callMethod( 'view', 'togglePreviewRepeat', tool.getValue() ) def getActiveSceneView( self ): return self.getModule( 'scene_view' ) #preview def startPreview( self ): self.saveAnimatorData() if self.delegate.callMethod( 'view', 'startPreview', self.previewTime ): self.widget.setCursorMovable( False ) self.previewing = True self.findTool( 'animator_play/play' ).setValue( True ) self.previewTimer.start() self.getApp().setMinimalMainLoopBudget() def stopPreview( self, rewind = False ): if self.previewing: self.delegate.callMethod( 'view', 'stopPreview' ) self.getApp().resetMainLoopBudget() self.widget.setCursorMovable( True ) self.previewing = False self.findTool( 'animator_play/play' ).setValue( False ) self.previewTimer.stop() signals.emit( 'entity.modified', None , '' ) if rewind: self.gotoStart() def onPreviewTimer( self ): playing, currentTime = self.delegate.callMethod( 'view', 'doPreviewStep' ) self.previewTime = currentTime self.getActiveSceneView().forceUpdate() self.widget.setCursorPos( self.previewTime ) if not playing: self.stopPreview() # signals.emit( 'entity.modified', None , '' ) def gotoStart( self ): if self.previewing: self.delegate.callMethod( 'view', 'applyTime', 0 ) else: self.widget.setCursorPos( 0, True ) def gotoEnd( self ): if self.previewing: self.delegate.callMethod( 'view', 'applyTime', 10 ) else: self.widget.setCursorPos( 10, True ) def applyTime( self, t, syncCursor = False ): self.previewTime = self.delegate.callMethod( 'view', 'applyTime', t ) self.getActiveSceneView().forceUpdate() signals.emit( 'entity.modified', None , '' ) if syncCursor: self.widget.setCursorPos( t ) def saveAnimatorData( self ): if not self.targetAnimator: return self.delegate.callMethod( 'view', 'saveData' ) def preSceneSave( self ): if self.targetAnimator: self.delegate.callMethod( 'view', 'restoreEntityState' ) def postSceneSave( self ): if self.targetAnimator: self.applyTime( self.previewTime ) def onSceneClose( self, scene ): self.setTargetAnimator( None ) def onPreviewSpeedChange( self, index ): label, throttle = PREVIEW_SPEED_OPTIONS[ index ] self.delegate.callMethod( 'view', 'setPreviewThrottle', throttle ) def refreshTimeline( self ): self.widget.rebuildTimeline() def refreshClipList( self ): self.widget.rebuildClipList() def refreshAll( self ): self.widget.rebuild()
class DeckCanvasEditor(SceneEditorModule): name = 'deckcanvas_editor' dependency = ['mock'] def onLoad(self): self.mainToolBar = self.addToolBar( 'deckcanvas_tools', self.getMainWindow().requestToolBar('deckcanvas_tools')) self.addTool('deckcanvas_tools/tool_pen', widget=SceneToolButton('deckcanvas_pen', label='Deck Canvas Editor', icon='deckcanvas/pen')) self.addTool('deckcanvas_tools/toggle_item_bounds_visible', label='Toggle Item Bounds', icon='deckcanvas/layer', type='check') self.findTool('deckcanvas_tools/toggle_item_bounds_visible').setValue( True) self.delegate = MOAILuaDelegate(self) self.delegate.load(_getModulePath('DeckCanvasEditor.lua')) signals.connect('selection.changed', self.onSelectionChanged) self.toolWindow = self.requestToolWindow('DeckCanvasEditor', title='DeckCanvas', size=(120, 40), minSize=(120, 40)) self.targetCanvas = None def onStart(self): self.setEditActive(True) def onSetFocus(self): self.getModule('scene_editor').setFocus() self.container.show() self.container.setFocus() def updateSelection(self): target = self.delegate.callMethod('editor', 'findTargetDeckCanvas') self.setTargetCanvas(target) def onSelectionChanged(self, selection, key): if key == 'scene': self.updateSelection() elif key == 'asset': decks = [] for node in selection: if node.getType().startswith('deck2d.'): decks.append(node.getNodePath()) self.delegate.callMethod('editor', 'changeDeckSelection', decks) def setEditActive(self, active): self.enableTool('deckcanvas_tools/tool_pen', active) def setTargetCanvas(self, canvas): self.delegate.callMethod('editor', 'setTargetCanvas', canvas) self.targetCanvas = canvas # if not self.targetCanvas: # self.setEditActive( False ) # return # self.setEditActive( True ) def showToolWindow(self): # self.toolWindow.show() self.getModule('scene_view').setFocus() def hideToolWindow(self): # self.toolWindow.hide() pass def startPenTool(self): self.delegate.callMethod('editor', 'startPenTool') def onTool(self, tool): name = tool.name if name == 'toggle_item_bounds_visible': _MOCK.setDeckCanvasItemBoundsVisible(bool(tool.getValue())) signals.emit('scene.update')
class AnimatorView(SceneEditorModule): name = 'animator' dependency = ['scene_editor', 'mock'] def onLoad(self): #UI self.windowTitle = 'Animator' self.window = self.requestDockWindow('AnimatorView', title='Animator', size=(120, 120), minSize=(120, 120), dock='bottom', icon='play') self.widget = AnimatorWidget() self.window.addWidget(self.widget) self.toolbarTarget = self.addToolBar('animator_target', self.widget.toolbarTarget) self.toolbarClips = self.addToolBar('animator_clips', self.widget.toolbarClips) self.toolbarPlay = self.addToolBar('animator_play', self.widget.toolbarPlay) self.toolbarTrack = self.addToolBar('animator_track', self.widget.toolbarTrack) self.toolbarClipTree = self.addToolBar('animator_clip_tree', self.widget.toolbarClipTree) # self.toolbarEdit = self.addToolBar( 'animator_play', self.widget.toolbarEdit ) signals.connect('scene.close', self.onSceneClose) signals.connect('scene.save', self.preSceneSave) signals.connect('scene.saved', self.postSceneSave) # addWidgetWithLaytut( toolbar, # self.widget.containerEditTool ) self.addTool('animator_target/find_animator', label='Find Animator', icon='find') self.addTool('animator_target/change_animator', label='Edit Selected Animator', icon='in') # self.addTool( 'animator_target/close_animator', label = 'Close Animator', icon = 'in' ) self.addTool('animator_target/----') self.addTool('animator_target/save_data', label='Save Data', icon='save') self.addTool('animator_target/----') self.addTool('animator_target/extra', label='Extra', icon='dots') # self.addTool('animator_clips/add_clip_group', label='add group', icon='add_folder') self.addTool('animator_clips/add_clip', label='add', icon='add') self.addTool('animator_clips/add_clip_tree', label='add tree', icon='add_clip_tree') # self.addTool( 'animator_clips/add_clip_list', label = 'add list', icon = 'add_clip_list' ) self.addTool('animator_clips/----') self.addTool('animator_clips/remove_clip', label='remove', icon='remove') self.addTool('animator_clips/clone_clip', label='clone', icon='clone') # self.addTool('animator_play/goto_start', label='to start', icon='rewind') self.addTool('animator_play/stop', label='stop', icon='stop') self.addTool('animator_play/play', label='play', icon='play', type='check') self.addTool('animator_play/goto_end', label='to end', icon='fast_forward') self.addTool('animator_play/toggle_repeat', label='toggle repeat', icon='repeat', type='check') self.comboPreviewSpeed = QtWidgets.QComboBox() self.comboPreviewSpeed.addItems([e[0] for e in PREVIEW_SPEED_OPTIONS]) self.comboPreviewSpeed.setCurrentIndex(4) #1x self.comboPreviewSpeed.currentIndexChanged.connect( self.onPreviewSpeedChange) self.addTool('animator_play/preview_speed', widget=self.comboPreviewSpeed) # self.addTool('animator_clip_tree/stop_tree', label='stop', icon='stop') self.addTool('animator_clip_tree/play_tree', label='play', icon='play', type='check') self.addTool('animator_clip_tree/----', ) self.addTool('animator_clip_tree/add_clip_tree_node', label='Add node', icon='add') self.addTool('animator_clip_tree/remove_clip_tree_node', label='Remove node', icon='remove') #SIGNALS self.addTool('animator_track/fold_tracks', label='fold all', icon='collapse') self.addTool('animator_track/unfold_tracks', label='unfold all', icon='expand') self.addTool('animator_track/----') self.addTool('animator_track/locate_target', label='locate', icon='find') self.addTool('animator_track/retarget', label='retarget', icon='compose') self.addTool('animator_track/----') self.addTool('animator_track/add_track_group', label='add group', icon='add_folder') self.addTool('animator_track/add_track', label='add', icon='add') self.addTool('animator_track/remove_track', label='remove', icon='remove') # self.addShortcut(self.widget, 'Space', self.togglePreview) self.addShortcut(self.widget, 'shift+Space', self.restartPreview) self.addShortcut(self.widget, 'Escape', self.resetPreview) signals.connect('selection.changed', self.onSceneSelectionChanged) self.delegate = MOAILuaDelegate(self) self.delegate.load(_getModulePath('AnimatorView.lua')) self.widget.setOwner(self) #playback self.previewing = False self.setEditing(False) self.setReadOnly(False) self.targetAnimator = None self.targetClip = None self.targetAnimatorData = None self.currentTrack = None self.previewing = False self.previewLoop = False self.previewTime = 0.0 self.previewStep = 1.0 / 60.0 self.previewTimer = QtCore.QTimer() self.previewTimer.setTimerType(Qt.PreciseTimer) # self.previewTimer = self.addTimer() self.previewTimer.setInterval(1000.0 / 65) self.previewTimer.stop() self.previewTimer.timeout.connect(self.onPreviewTimer) # self.previewTimer.onTick = self.onPreviewTimer def onStart(self): pass def setEditing(self, editing): self.widget.timeline.setEnabled(editing) self.widget.treeTracks.setEnabled(editing) self.findTool('animator_play').setEnabled(editing) self.findTool('animator_track').setEnabled(editing) self.findTool('animator_clips/add_clip_group').setEnabled(editing) self.findTool('animator_clips/add_clip_tree').setEnabled(editing) self.findTool('animator_clips/add_clip').setEnabled(editing) self.findTool('animator_clips/remove_clip').setEnabled(editing) self.findTool('animator_clips/clone_clip').setEnabled(editing) def setReadOnly(self, readonly): self.readOnly = readonly #TODO def setTargetAnimator(self, target): self.saveAnimatorData() if target == self.targetAnimator: return if self.previewing: self.stopPreview() self.targetAnimator = target self.targetClip = None self.delegate.callMethod('view', 'setTargetAnimator', target) self.targetAnimatorData = self.delegate.callMethod( 'view', 'getTargetAnimatorData') self.widget.rebuild() if self.targetAnimator: self.setEditing(True) signals.emit('animator.start') else: self.setEditing(False) signals.emit('animator.stop') path = self.delegate.callMethod('view', 'getTargetAnimatorDataPath') if path: self.window.setWindowTitle('Animator - %s' % path) else: self.window.setWindowTitle('Animator') clip = self.delegate.callMethod('view', 'getPreviousTargeClip', target) self.enableTool('animator_play', False) self.enableTool('animator_track', False) if clip: self.widget.treeClips.selectNode(clip) else: self.widget.treeClips.selectFirstItem() self.applyTime(0, True) def setTargetClip(self, clip): wasPreviewing = self.previewing if self.previewing: self.stopPreview() self.targetClip = clip self.delegate.callMethod('view', 'setTargetClip', clip) self.widget.rebuildTimeline() self.widget.rebuildClipTree() self.enableTool('animator_play', bool(clip)) self.enableTool('animator_track', bool(clip)) self.applyTime(0, True) if wasPreviewing: self.startPreview() def setCurrentTrack(self, track): self.currentTrack = track self.delegate.callMethod('view', 'setCurrentTrack', track) def getTargetClipLength(self): return self.delegate.callMethod('view', 'getTargetClipLength') def getClipList(self): if self.targetAnimatorData: clipList = self.targetAnimatorData.clips return [clip for clip in list(clipList.values())] else: return [] def getRootClipGroup(self): if self.targetAnimatorData: return self.targetAnimatorData.getRootGroup( self.targetAnimatorData) def getTrackList(self): if self.targetClip: trackList = self.targetClip.getTrackList(self.targetClip) return [track for track in list(trackList.values())] else: return [] def getMarkerList(self): if self.targetClip: markerList = self.targetClip.getMarkerList(self.targetClip) return [track for track in list(markerList.values())] else: return [] def getClipRoot(self): if self.targetClip: return self.targetClip.getRoot(self.targetClip) else: return None def getClipTreeRoot(self): if self.targetClip and isMockInstance(self.targetClip, 'AnimatorClipTree'): return self.targetClip.getTreeRoot(self.targetClip) def addClip(self): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand('scene_editor/animator_add_clip', animator_data=self.targetAnimatorData, parent_group=targetGroup) clip = cmd.getResult() clip.setFixedLength(clip, 3) if clip: self.widget.addClip(clip, True) return clip def addClipTree(self): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand('scene_editor/animator_add_clip_tree', animator_data=self.targetAnimatorData, parent_group=targetGroup) clip = cmd.getResult() if clip: self.widget.addClip(clip, True) return clip def addClipGroup(self): if not self.targetAnimatorData: return targetGroup = self.widget.getCurrentClipGroup() cmd = self.doCommand('scene_editor/animator_add_clip_group', animator_data=self.targetAnimatorData, parent_group=targetGroup) group = cmd.getResult() if group: self.widget.addClip(group, True) return group def removeClipNode(self): for clip in self.widget.treeClips.getSelection(): if self.doCommand('scene_editor/animator_remove_clip_node', animator_data=self.targetAnimatorData, target_node=clip): self.widget.removeClip(clip) def cloneClipNode(self): if not self.targetClip: return result = [] for clip in self.widget.treeClips.getSelection(): cmd = self.doCommand('scene_editor/animator_clone_clip_node', animator_data=self.targetAnimatorData, target_node=clip) if cmd: cloned = cmd.getResult() self.widget.addClip(cloned, True) result.append(cloned) return result def onObjectEdited(self, obj): if self.targetClip: self.delegate.callMethod('view', 'clearPreviewState') self.delegate.callMethod('view', 'markClipDirty') self.refreshPreview() def onSceneSelectionChanged(self, selection, key): if key != 'scene': return #find animator component # self.findTargetAnimator() def findTargetAnimator(self): target = self.delegate.callMethod('view', 'findTargetAnimator') self.setTargetAnimator(target) return target def checkTargetAnimator(self): if not self.targetAnimator: alertMessage('No Animator', 'No Animator Selected', 'question') return False return True def addMarker(self): if not self.targetClip: return cmd = self.doCommand('scene_editor/animator_add_marker', target_clip=self.targetClip, target_pos=self.widget.getCursorPos()) if cmd: marker = cmd.getResult() self.widget.addMarker(marker) def addKeyForField(self, target, fieldId): if not self.checkTargetAnimator(): return if not self.targetClip: self.addClip() # alertMessage( 'No Clip', 'You need to select a Clip first', 'question' ) # return False keys = self.delegate.callMethod('view', 'addKeyForField', target, fieldId) if keys: for key in list(keys.values()): self.widget.addKey(key, True) def addKeyForEvent(self, target, eventId): pass def addCustomAnimatorTrack(self, target, trackClasId): if not self.checkTargetAnimator(): return track = self.delegate.callMethod('view', 'addCustomAnimatorTrack', target, trackClasId) if track: self.widget.addTrack(track) def addKeyForSelectedTracks(self): #TODO: command selectedTracks = self.widget.getTrackSelection() for track in selectedTracks: keys = self.delegate.callMethod('view', 'addKeyForSelectedTrack', track) if keys: for key in list(keys.values()): self.widget.addKey(key, True) def removeSelectedKeys(self): #TODO: command selectedKeys = self.widget.getKeySelection() for key in selectedKeys: self.widget.removeKey(key) def cloneSelectedKeys(self): #TODO: command selectedKeys = self.widget.getKeySelection() cloned = [] for key in selectedKeys: clonedKey = self.delegate.callMethod('view', 'cloneKey', key) if clonedKey: cloned.append(clonedKey) for clonedKey in cloned: keyItem = self.widget.addKey(clonedKey, False) keyItem.fitIntoNextEmptySpan() def onKeyRemoving(self, key): if self.delegate.callMethod('view', 'removeKey', key) != False: self.refreshPreview() return True def onMarkerRemoving(self, marker): if self.delegate.callMethod('view', 'removeMarker', marker) != False: return True def onClipLengthChanging(self, t1): if self.delegate.callMethod('view', 'setTargetClipLength', t1) != False: self.refreshPreview() return True def onTimelineKeyChanged(self, key, pos, length): self.delegate.callMethod('view', 'updateTimelineKey', key, pos, length) self.refreshPreview() def onTimelineKeyCurveValueChanged(self, key, value): self.delegate.callMethod('view', 'updateTimelineKeyCurveValue', key, value) self.refreshPreview() def onTimelineKeyTweenModeChanged(self, key, mode): self.delegate.callMethod('view', 'updateTimelineKeyTweenMode', key, mode) self.refreshPreview() def onTimelineKeyBezierPointChanged(self, key, bpx0, bpy0, bpx1, bpy1): self.delegate.callMethod('view', 'updateTimelineKeyBezierPoint', key, bpx0, bpy0, bpx1, bpy1) self.refreshPreview() def onTimelineMarkerChanged(self, marker, pos): self.delegate.callMethod('view', 'updateTimelineMarker', marker, pos) def toggleTrackActive(self, track): #TODO: command # self.module.doCommand( 'scene_editor/toggle_entity_visibility', target = node ) self.delegate.callMethod('view', 'toggleTrackActive', track) self.refreshPreview() self.refreshPreview() def renameTrack(self, track, name): self.delegate.callMethod('view', 'renameTrack', track, name) def renameClip(self, clip, name): self.delegate.callMethod('view', 'renameClip', clip, name) def createClipTreeNode(self, nodeTypeName): if not self.targetClip: return None contextNode = self.widget.treeClipTree.getFirstSelection() cmd = self.doCommand('scene_editor/animator_add_clip_tree_node', context_node=contextNode, parent_tree=self.targetClip, node_type=nodeTypeName) node = cmd.getResult() if node: self.widget.addClipTreeNode(node, True) return node def listClipTreeNodeTypes(self, typeId, context, option): contextNode = self.widget.treeClipTree.getFirstSelection() parentTree = self.targetClip if not contextNode: contextNode = parentTree.getTreeRoot(parentTree) res = _MOCK_EDIT.requestAvailAnimatorClipTreeNodeTypes(contextNode) entries = [] for n in list(res.values()): entry = (n, n, 'AnimatorClipTreeNode', 'animator_clip_tree/' + n) entries.append(entry) return entries def retargetTrack(self, entity): for track in self.widget.treeTracks.getSelection(): cmd = self.doCommand('scene_editor/animator_retarget_track', target_track=track, target_entity=entity, animator=self.targetAnimator) self.widget.treeTracks.refreshNodeContent(track) self.delegate.callMethod('view', 'clearPreviewState') self.delegate.callMethod('view', 'markClipDirty') self.refreshPreview() def selectAnimatorEntity(self, com): entity = com._entity if not entity: return self.changeSelection(entity) self.findTargetAnimator() def openTargetContextMenu(self): menu = QtWidgets.QMenu("Animator Target Context") itemAddKey = menu.addAction('Relocate Targets') itemAddKey.triggered.connect(self.onRelocateTargets) menu.exec_(QtGui.QCursor.pos()) def onRelocateTargets(self): if not self.targetAnimator: return self.delegate.callMethod('view', 'relocateTargets') def onTool(self, tool): name = tool.name if name == 'find_animator': requestSearchView(context='scene', type=_MOCK.Animator, on_selection=self.selectAnimatorEntity) elif name == 'change_animator': target0 = self.targetAnimator target1 = self.findTargetAnimator() if (not target0) and (not target1): alertMessage('No Animator', 'No Animator found in selected entity scope', 'question') elif name == 'save_data': self.saveAnimatorData() elif name == 'extra': self.openTargetContextMenu() elif name == 'add_clip': if self.checkTargetAnimator(): self.addClip() elif name == 'add_clip_tree': if self.checkTargetAnimator(): self.addClipTree() elif name == 'add_clip_group': if self.checkTargetAnimator(): self.addClipGroup() elif name == 'remove_clip': if self.checkTargetAnimator(): self.removeClipNode() elif name == 'clone_clip': if self.checkTargetAnimator(): self.cloneClipNode() elif name == 'add_track_group': group = self.delegate.callMethod('view', 'addTrackGroup') if group: self.widget.addTrack(group, True) elif name == 'remove_track': for track in self.widget.treeTracks.getSelection(): self.delegate.callMethod('view', 'removeTrack', track) self.widget.removeTrack(track) self.refreshPreview() elif name == 'fold_tracks': self.widget.treeTracks.foldAllItems() elif name == 'unfold_tracks': self.widget.treeTracks.expandAllItems() elif name == 'locate_target': for track in self.widget.treeTracks.getSelection(): sceneGraphEditor = self.getModule('scenegraph_editor') if sceneGraphEditor: targetEntity = self.delegate.callMethod( 'view', 'findTrackEntity', track) if targetEntity: sceneGraphEditor.selectEntity(targetEntity, focus_tree=True) #pass return elif name == 'retarget': requestSearchView( info='retarget animator track to...', context='scene', type='entity', multiple_selection=False, on_selection=self.retargetTrack, ) elif name == 'add_clip_tree_node': requestSearchView(info='adding AnimatorClipTree node...', context='clip_tree_node', type=None, multiple_selection=False, on_selection=self.createClipTreeNode, on_search=self.listClipTreeNodeTypes) elif name == 'remove_clip_tree_node': for node in self.widget.treeClipTree.getSelection(): if node.isVirtual(node): continue self.doCommand('scene_editor/animator_remove_clip_tree_node', target_node=node) self.widget.rebuildClipTree() self.refreshPreview() #preview elif name == 'goto_start': self.gotoStart() elif name == 'goto_end': self.gotoEnd() elif name == 'play': if tool.getValue(): self.startPreview() else: self.stopPreview(False) elif name == 'stop': self.stopPreview(True) elif name == 'play_tree': if tool.getValue(): self.startPreview() else: self.stopPreview(False) elif name == 'stop_tree': self.stopPreview(True) elif name == 'toggle_repeat': self.delegate.callMethod('view', 'togglePreviewRepeat', tool.getValue()) def getActiveSceneView(self): return self.getModule('scene_view') #preview def togglePreview(self): if self.previewing: self.stopPreview() else: self.startPreview() def restartPreview(self): self.stopPreview(True) self.startPreview() def resetPreview(self): self.stopPreview(True) def startPreview(self): # self.saveAnimatorData() #WHY?????? if self.delegate.callMethod('view', 'startPreview', self.previewTime): self.widget.setCursorMovable(False) self.previewing = True self.findTool('animator_play/play').setValue(True) self.findTool('animator_clip_tree/play_tree').setValue(True) self.previewTimer.start() self.getApp().setMinimalMainLoopBudget() def stopPreview(self, rewind=False): if self.previewing: self.delegate.callMethod('view', 'stopPreview') self.getApp().resetMainLoopBudget() self.widget.setCursorMovable(True) self.previewing = False self.findTool('animator_play/play').setValue(False) self.findTool('animator_clip_tree/play_tree').setValue(False) self.previewTimer.stop() signals.emit('entity.modified', None, '') if rewind: self.gotoStart() def onPreviewTimer(self): playing, currentTime = self.delegate.callMethod( 'view', 'doPreviewStep') self.previewTime = currentTime self.getActiveSceneView().forceUpdate() self.widget.setCursorPos(self.previewTime) if not playing: self.stopPreview() def gotoStart(self): if self.previewing: self.delegate.callMethod('view', 'applyTime', 0) else: self.widget.setCursorPos(0, True) def gotoEnd(self): if self.previewing: self.delegate.callMethod('view', 'applyTime', 10) else: self.widget.setCursorPos(10, True) def applyTime(self, t, syncCursor=False): self.previewTime = self.delegate.callMethod('view', 'applyTime', t) # self.getActiveSceneView().scheduleUpdate() self.getActiveSceneView().forceUpdate() # signals.emit( 'entity.modified', None , '' ) if syncCursor: self.widget.setCursorPos(t) def saveAnimatorData(self): if not self.targetAnimator: return self.delegate.callMethod('view', 'saveData') def preSceneSave(self): if self.targetAnimator: self.delegate.callMethod('view', 'restoreEntityState') def postSceneSave(self): if self.targetAnimator: self.refreshPreview() def onSceneClose(self, scene): self.setTargetAnimator(None) def onPreviewSpeedChange(self, index): label, throttle = PREVIEW_SPEED_OPTIONS[index] self.delegate.callMethod('view', 'setPreviewThrottle', throttle) def refreshPreview(self): self.applyTime(self.previewTime) self.applyTime(self.previewTime) def refreshTimeline(self): self.widget.rebuildTimeline() def refreshClipList(self): self.widget.rebuildClipList() def refreshAll(self): self.widget.rebuild()
class SceneGraphEditor( SceneEditorModule ): def __init__(self): super( SceneGraphEditor, self ).__init__() self.sceneDirty = False self.activeSceneNode = None self.refreshScheduled = False self.previewing = False self.workspaceState = None def getName( self ): return 'scenegraph_editor' def getDependency( self ): return [ 'scene_editor', 'mock' ] def onLoad( self ): #UI self.windowTitle = 'Scenegraph' self.container = self.requestDockWindow( 'SceneGraphEditor', title = 'Scenegraph', size = (200,200), minSize = (200,200), dock = 'left' ) #Components self.treeFilter = self.container.addWidget( GenericTreeFilter( self.container ), expanding = False ) self.tree = self.container.addWidget( SceneGraphTreeWidget( self.container, sorting = True, editable = True, multiple_selection = True, drag_mode = 'internal' ) ) self.treeFilter.setTargetTree( self.tree ) self.tree.module = self self.tool = self.addToolBar( 'scene_graph', self.container.addToolBar() ) self.delegate = MOAILuaDelegate( self ) self.delegate.load( getModulePath( 'SceneGraphEditor.lua' ) ) self.entityCreatorMenu=self.addMenu( 'main/scene/entity_create', { 'label':'Create Entity' } ) self.componentCreatorMenu=self.addMenu( 'main/scene/component_create', { 'label':'Create Component' } ) #menu self.addMenuItem( 'main/file/open_scene', dict( label = 'Open Scene', shortcut = 'ctrl+shift+o' ) ) self.addMenuItem( 'main/file/close_scene', dict( label = 'Close Scene', shortcut = 'Ctrl+W' ) ) self.addMenuItem( 'main/scene/save_scene', dict( label = 'Save', shortcut = 'Ctrl+S' ) ) self.addMenuItem( 'main/scene/locate_scene_asset', dict( label = 'Locate Scene Asset' ) ) self.addMenu( 'main/scene/----' ) self.addMenu( 'component_context', dict( label = 'Selected Component' ) ) self.addMenuItem( 'component_context/remove_component', dict( label = 'Remove' ) ) self.addMenuItem( 'component_context/----' ) self.addMenuItem( 'component_context/copy_component', dict( label = 'Copy' ) ) self.addMenuItem( 'component_context/paste_component', dict( label = 'Paste Component Here' ) ) self.addMenuItem( 'component_context/----' ) self.addMenuItem( 'component_context/move_component_up', dict( label = 'Move Up' ) ) self.addMenuItem( 'component_context/move_component_down', dict( label = 'Move Down' ) ) self.addMenu( 'main/entity', dict( label = 'Entity' ) ) self.addMenuItem( 'main/entity/add_empty_entity', dict( label = 'Create Empty', shortcut = 'ctrl+alt+N' ) ) self.addMenuItem( 'main/entity/add_entity', dict( label = 'Create', shortcut = 'ctrl+shift+N' ) ) self.addMenuItem( 'main/entity/----' ) self.addMenuItem( 'main/entity/group_entity', dict( label = 'Group Entites', shortcut = 'ctrl+G' ) ) self.addMenuItem( 'main/entity/create_group', dict( label = 'Create Empty Group', shortcut = 'ctrl+shift+G' ) ) self.addMenuItem( 'main/entity/----' ) self.addMenuItem( 'main/entity/load_prefab', dict( label = 'Load Prefab', shortcut = 'ctrl+alt+shift+N' ) ) self.addMenuItem( 'main/entity/load_prefab_in_container', dict( label = 'Load Prefab In Container', shortcut = 'ctrl+shift+=' ) ) self.addMenuItem( 'main/entity/----' ) self.addMenuItem( 'main/entity/remove_entity', dict( label = 'Remove' ) ) self.addMenuItem( 'main/entity/clone_entity', dict( label = 'Clone', shortcut = 'ctrl+d' ) ) self.addMenuItem( 'main/entity/----' ) self.addMenuItem( 'main/entity/add_component', dict( label = 'Add Component', shortcut = 'ctrl+alt+=' ) ) self.addMenuItem( 'main/entity/assign_layer', dict( label = 'Assign Layer', shortcut = 'ctrl+alt+L' ) ) self.addMenuItem( 'main/entity/toggle_visibility', dict( label = 'Toggle Visibility', shortcut = 'ctrl+/' ) ) self.addMenuItem( 'main/entity/freeze_entity_pivot', dict( label = 'Freeze Pivot' ) ) self.addMenuItem( 'main/entity/----' ) self.addMenuItem( 'main/find/find_entity', dict( label = 'Find In Scene', shortcut = 'ctrl+f' ) ) self.addMenuItem( 'main/find/find_entity_in_group', dict( label = 'Find In Group', shortcut = 'ctrl+shift+f' ) ) self.addMenuItem( 'main/find/find_entity_group', dict( label = 'Find Group', shortcut = 'ctrl+alt+f' ) ) #Toolbars self.addTool( 'scene_graph/select_scene', label ='Select Scene', icon = 'settings' ) self.addTool( 'scene_graph/----' ) self.addTool( 'scene_graph/create_group', label ='+ Group', icon = 'add_folder' ) self.addTool( 'scene_graph/----' ) self.addTool( 'scene_graph/make_proto', label = 'Convert To Proto', icon = 'proto_make' ) self.addTool( 'scene_graph/create_proto_instance', label = 'Create Proto Instance', icon = 'proto_instantiate' ) self.addTool( 'scene_graph/create_proto_container', label = 'Create Proto Container', icon = 'proto_container' ) self.addTool( 'scene_graph/----' ) self.addTool( 'scene_graph/fold_all', label = 'F' ) self.addTool( 'scene_graph/unfold_all', label = 'U' ) self.addTool( 'scene_graph/refresh_tree', label = 'R' ) # self.addTool( 'scene_graph/load_prefab', label = '+ P' ) # self.addTool( 'scene_graph/save_prefab', label = '>>P' ) self.addTool( 'scene/refresh', label = 'refresh', icon='refresh' ) #SIGNALS signals.connect( 'moai.clean', self.onMoaiClean ) signals.connect( 'scene.clear', self.onSceneClear ) signals.connect( 'scene.change', self.onSceneChange ) signals.connect( 'selection.changed', self.onSelectionChanged ) signals.connect( 'selection.hint', self.onSelectionHint ) signals.connect( 'preview.start', self.onPreviewStart ) signals.connect( 'preview.stop' , self.onPreviewStop ) # signals.connect( 'animator.start', self.onAnimatorStart ) # signals.connect( 'animator.stop' , self.onAnimatorStop ) signals.connect( 'entity.added', self.onEntityAdded ) signals.connect( 'entity.removed', self.onEntityRemoved ) signals.connect( 'entity.renamed', self.onEntityRenamed ) signals.connect( 'entity.modified', self.onEntityModified ) signals.connect( 'entity.visible_changed', self.onEntityVisibleChanged ) signals.connect( 'entity.pickable_changed', self.onEntityPickableChanged ) signals.connect( 'prefab.unlink', self.onPrefabUnlink ) signals.connect( 'prefab.relink', self.onPrefabRelink ) signals.connect( 'proto.unlink', self.onPrefabUnlink ) signals.connect( 'proto.relink', self.onPrefabRelink ) signals.connect( 'app.ready', self.postAppReady ) signals.connect( 'component.added', self.onComponentAdded ) signals.connect( 'component.removed', self.onComponentRemoved ) signals.connect( 'project.presave', self.preProjectSave ) registerSearchEnumerator( sceneObjectSearchEnumerator ) registerSearchEnumerator( entityNameSearchEnumerator ) registerSearchEnumerator( componentNameSearchEnumerator ) registerSearchEnumerator( layerNameSearchEnumerator ) def onStart( self ): self.refreshCreatorMenu() def postAppReady( self ): self.openPreviousScene() def openPreviousScene( self ): previousScene = self.getConfig( 'previous_scene', None ) if previousScene: node = self.getAssetLibrary().getAssetNode( previousScene ) if node: node.edit() def onStop( self ): if self.activeSceneNode: self.setConfig( 'previous_scene', self.activeSceneNode.getNodePath() ) else: self.setConfig( 'previous_scene', False ) def onSetFocus( self ): self.container.show() self.container.raise_() self.container.setFocus() def getActiveScene( self ): return self.delegate.safeCallMethod( 'editor', 'getScene' ) def getActiveSceneRootGroup( self ): scene = self.delegate.safeCallMethod( 'editor', 'getScene' ) if scene: return scene.rootGroup else: return None def openScene( self, node, protoNode = None ): if self.activeSceneNode == node: if self.getModule('scene_view'): self.getModule('scene_view').setFocus() if protoNode: self.delegate.safeCallMethod( 'editor', 'locateProto', protoNode.getPath() ) if self.getModule('scene_view'): self.getModule('scene_view').focusSelection() else: if not self.closeScene(): return if self.getModule('scene_view'): self.getModule('scene_view').makeCanvasCurrent() self.activeSceneNode = node signals.emitNow( 'scene.pre_open', node ) scene = self.delegate.safeCallMethod( 'editor', 'openScene', node.getPath() ) if not scene: #todo: raise something alertMessage( 'error', '%s\n\nfailed to open scene, see console for detailed information.' % node.getPath() ) return False signals.emitNow( 'scene.open', self.activeSceneNode, scene ) self.setFocus() self.editingProtoNode = protoNode self.loadWorkspaceState( False ) self.delegate.safeCallMethod( 'editor', 'postOpenScene' ) def closeScene( self ): if not self.activeSceneNode: return True if self.sceneDirty: res = requestConfirm( 'scene modified!', 'save scene before close?' ) if res == True: #save self.saveScene() elif res == None: #cancel return elif res == False: #no save pass self.markSceneDirty( False ) self.tree.clear() self.getApp().clearCommandStack( 'scene_editor' ) self.getSelectionManager().removeSelection( self.getActiveScene() ) signals.emitNow( 'scene.close', self.activeSceneNode ) self.delegate.safeCallMethod( 'editor', 'closeScene' ) self.activeSceneNode = None return True def onSceneClear( self ): # self.tree.clear() pass def markSceneDirty( self, dirty = True ): if not self.previewing: self.sceneDirty = dirty def saveWorkspaceState( self ): self.retainWorkspaceState() treeFoldState = self.workspaceState['tree_state'] containerFoldState = self.workspaceState['container_state'] entityLockState = self.workspaceState['entity_lock_state'] self.activeSceneNode.setMetaData( 'tree_state', treeFoldState ) self.activeSceneNode.setMetaData( 'container_state', containerFoldState ) self.activeSceneNode.setMetaData( 'entity_lock_state', entityLockState ) def loadWorkspaceState( self, restoreState = True ): treeFoldState = self.activeSceneNode.getMetaData( 'tree_state', None ) containerFoldState = self.activeSceneNode.getMetaData( 'container_state', None ) entityLockState = self.activeSceneNode.getMetaData( 'entity_lock_state', None ) self.workspaceState = { 'tree_state' : treeFoldState, 'container_state' : containerFoldState, 'entity_lock_state' : entityLockState } if restoreState: self.restoreWorkspaceState() def retainWorkspaceState( self ): #tree node foldstate treeFoldState = self.tree.saveFoldState() #save introspector foldstate introspectorFoldState = self.delegate.safeCallMethod( 'editor', 'saveIntrospectorFoldState' ) entityLockState = self.delegate.safeCallMethod( 'editor', 'saveEntityLockState' ) self.workspaceState = { 'tree_state' : treeFoldState, 'container_state' : introspectorFoldState, 'entity_lock_state' : entityLockState } def restoreWorkspaceState( self ): if not self.workspaceState: return treeState = self.workspaceState.get( 'tree_state', None ) if treeState: self.tree.loadFoldState( treeState ) containerState = self.workspaceState.get( 'container_state', None ) if containerState: self.delegate.safeCallMethod( 'editor', 'loadIntrospectorFoldState', containerState ) lockState = self.workspaceState.get( 'entity_lock_state', None ) if lockState: self.delegate.safeCallMethod( 'editor', 'loadEntityLockState', lockState ) def onSceneChange( self ): self.tree.hide() self.tree.rebuild() self.restoreWorkspaceState() self.tree.refreshAllContent() self.tree.verticalScrollBar().setValue( 0 ) self.tree.show() if self.editingProtoNode: self.delegate.safeCallMethod( 'editor', 'locateProto', self.editingProtoNode.getPath() ) self.editingProtoNode = None if self.getModule('scene_view'): self.getModule('scene_view').focusSelection() def saveScene( self ): if not self.activeSceneNode: return self.markSceneDirty( False ) signals.emitNow( 'scene.save' ) self.delegate.safeCallMethod( 'editor', 'saveScene', self.activeSceneNode.getAbsFilePath() ) signals.emitNow( 'scene.saved' ) self.saveWorkspaceState() def refreshScene( self ): if not self.activeSceneNode: return if self.previewing: return self.refreshScheduled = False node = self.activeSceneNode self.retainWorkspaceState() if self.delegate.safeCallMethod( 'editor', 'refreshScene' ): self.restoreWorkspaceState() self.refreshCreatorMenu() def scheduleRefreshScene( self ): if not self.activeSceneNode: return self.refreshScheduled = True def refreshCreatorMenu( self ): def addEntityMenuItem( name ): if name == '----': self.entityCreatorMenu.addChild( '----' ) return self.entityCreatorMenu.addChild({ 'name' : 'create_entity_'+name, 'label' : name, 'command' : 'scene_editor/create_entity', 'command_args' : dict( name = name ) }) def addComponentMenuItem( name ): if name == '----': self.componentCreatorMenu.addChild( '----' ) return self.componentCreatorMenu.addChild({ 'name' : 'create_component_'+name, 'label' : name, 'command' : 'scene_editor/create_component', 'command_args' : dict( name = name ) }) self.entityCreatorMenu.clear() self.componentCreatorMenu.clear() registry = _MOCK.getEntityRegistry() #entity keys = sorted( registry.keys() ) addEntityMenuItem( 'Entity' ) addEntityMenuItem( '----' ) for entityName in sorted( registry.keys() ): if entityName!='Entity': addEntityMenuItem( entityName ) #component registry = _MOCK.getComponentRegistry() for comName in sorted( registry.keys() ): addComponentMenuItem( comName ) def needUpdate( self ): return True def onUpdate( self ): if self.refreshScheduled: self.refreshScene() def preProjectSave( self, prj ): if self.activeSceneNode: _MOCK.game.previewingScene = self.activeSceneNode.getNodePath() def onMoaiClean( self ): self.tree.clear() def onTool( self, tool ): name = tool.name if name == 'fold_all': self.tree.foldAllItems() elif name == 'unfold_all': self.tree.expandAllItems() elif name == 'refresh_tree': self.tree.rebuild() elif name == 'refresh': self.scheduleRefreshScene() elif name == 'make_proto': self.makeProto() elif name == 'create_proto_instance': requestSearchView( info = 'select a proto to instantiate', context = 'asset', type = 'proto', on_selection = lambda obj: self.doCommand( 'scene_editor/create_proto_instance', proto = obj.getNodePath() ) ) elif name == 'create_proto_container': requestSearchView( info = 'select a proto to create contained instance', context = 'asset', type = 'proto', on_selection = lambda obj: self.doCommand( 'scene_editor/create_proto_container', proto = obj.getNodePath() ) ) elif name == 'create_group': self.doCommand( 'scene_editor/entity_group_create' ) elif name == 'group_entity': self.doCommand( 'scene_editor/group_entities' ) elif name == 'select_scene': self.doCommand( 'scene_editor/select_scene' ) def onMenu( self, menu ): name = menu.name if name == 'close_scene': if self.previewing: alertMessage( 'Warning', 'Stop previewing before closing scene' ) return self.closeScene() elif name == 'open_scene': if self.previewing: alertMessage( 'Warning', 'Stop previewing before opening scene' ) return requestSearchView( info = 'select scene to open', context = 'asset', type = 'scene', on_selection = self.openScene ) elif name == 'save_scene': if self.previewing: alertMessage( 'Warning', 'Stop previewing before saving' ) return self.saveScene() elif name == 'locate_scene_asset': if self.activeSceneNode: assetBrowser = self.getModule( 'asset_browser' ) if assetBrowser: assetBrowser.selectAsset( self.activeSceneNode ) elif name == 'add_entity': requestSearchView( info = 'select entity type to create', context = 'entity_creation', on_selection = lambda obj: self.doCommand( 'scene_editor/create_entity', name = obj ) ) elif name == 'add_component': requestSearchView( info = 'select component type to create', context = 'component_creation', on_selection = lambda obj: self.doCommand( 'scene_editor/create_component', name = obj ) ) elif name == 'add_empty_entity': self.doCommand( 'scene_editor/create_entity', name = 'Entity' ) elif name == 'load_prefab': requestSearchView( info = 'select a perfab node to instantiate', context = 'asset', type = 'prefab', on_selection = lambda obj: self.doCommand( 'scene_editor/create_prefab_entity', prefab = obj.getNodePath() ) ) elif name == 'load_prefab_in_container': requestSearchView( info = 'select a perfab node to instantiate( PefabContainer )', context = 'asset', type = 'prefab', on_selection = lambda obj: self.doCommand( 'scene_editor/create_prefab_container', prefab = obj.getNodePath() ) ) elif name == 'remove_entity': self.doCommand( 'scene_editor/remove_entity' ) elif name == 'clone_entity': self.doCommand( 'scene_editor/clone_entity' ) elif name == 'find_entity': requestSearchView( info = 'search for entity in current scene', context = 'scene', type = 'entity', on_selection = lambda x: self.selectEntity( x, focus_tree = True ) , on_test = self.selectEntity ) elif name == 'find_entity_in_group': requestSearchView( info = 'search for entity in current entity group', context = 'scene', type = 'entity_in_group', on_selection = lambda x: self.selectEntity( x, focus_tree = True ) , on_test = self.selectEntity ) elif name == 'find_entity_group': requestSearchView( info = 'search for group in current scene', context = 'scene', type = 'group', on_selection = lambda x: self.selectEntity( x, focus_tree = True ) , on_test = self.selectEntity ) elif name == 'create_group': self.doCommand( 'scene_editor/entity_group_create' ) elif name == 'remove_component': context = menu.getContext() if context: self.doCommand( 'scene_editor/remove_component', target = context ) elif name == 'copy_component': context = menu.getContext() if context: self.doCommand( 'scene_editor/copy_component', target = context ) elif name == 'assign_layer': if not self.tree.getSelection(): return requestSearchView( info = 'select layer to assign', context = 'scene_layer', type = _MOCK.Entity, on_selection = self.assignEntityLayer ) elif name == 'toggle_visibility': self.doCommand( 'scene_editor/toggle_entity_visibility' ) elif name == 'freeze_entity_pivot': self.doCommand( 'scene_editor/freeze_entity_pivot' ) def onSelectionChanged( self, selection, key ): if key != 'scene': return if self.tree.syncSelection: self.tree.blockSignals( True ) self.tree.selectNode( None ) for e in selection: self.tree.selectNode( e, add = True) self.tree.blockSignals( False ) def selectEntity( self, target, **option ): if option.get( 'focus_tree', False ): self.tree.setFocus() self.changeSelection( target ) ##----------------------------------------------------------------## def renameEntity( self, target, name ): #TODO:command pattern target.setName( target, name ) signals.emit( 'entity.modified', target ) def addEntityNode( self, entity ): self.tree.addNode( entity, expanded = False ) self.tree.setNodeExpanded( entity, False ) def removeEntityNode( self, entity ): self.tree.removeNode( entity ) def assignEntityLayer( self, layerName ): #TODO:command pattern if not layerName: return self.doCommand( 'scene_editor/assign_layer', target = layerName ) def onSelectionHint( self, selection ): if selection._entity: self.changeSelection( selection._entity ) else: self.changeSelection( selection ) def onPreviewStart( self ): if not self.activeSceneNode: return self.retainWorkspaceState() self.delegate.safeCallMethod( 'editor', 'retainScene' ) self.delegate.safeCallMethod( 'editor', 'startScenePreview' ) self.previewing = True def onPreviewStop( self ): if not self.activeSceneNode: return self.changeSelection( None ) self.tree.clear() self.delegate.safeCallMethod( 'editor', 'stopScenePreview' ) self.previewing = False if self.delegate.safeCallMethod( 'editor', 'restoreScene' ): self.restoreWorkspaceState() def onAnimatorStart( self ): self.retainWorkspaceState() self.delegate.safeCallMethod( 'editor', 'retainScene' ) def onAnimatorStop( self ): self.tree.clear() self.delegate.safeCallMethod( 'editor', 'clearScene' ) if self.delegate.safeCallMethod( 'editor', 'restoreScene' ): self.restoreWorkspaceState() ##----------------------------------------------------------------## def updateEntityPriority( self ): if not self.activeSceneNode: return self.markSceneDirty() def onEntityRenamed( self, entity, newname ): self.tree.refreshNodeContent( entity ) self.markSceneDirty() def onEntityVisibleChanged( self, entity ): self.tree.refreshNodeContent( entity ) def onEntityPickableChanged( self, entity ): self.tree.refreshNodeContent( entity ) def onEntityAdded( self, entity, context = None ): if context == 'new': self.setFocus() pnode = entity.parent if pnode: self.tree.setNodeExpanded( pnode, True ) self.tree.setFocus() self.tree.editNode( entity ) self.tree.selectNode( entity ) signals.emit( 'scene.update' ) self.markSceneDirty() def onEntityRemoved( self, entity ): signals.emit( 'scene.update' ) self.markSceneDirty() def onEntityModified( self, entity, context = None ): self.markSceneDirty() ##----------------------------------------------------------------## def onComponentAdded( self, com, entity ): signals.emit( 'scene.update' ) self.markSceneDirty() def onComponentRemoved( self, com, entity ): signals.emit( 'scene.update' ) self.markSceneDirty() ##----------------------------------------------------------------## def onPrefabUnlink( self, entity ): self.tree.refreshNodeContent( entity, updateChildren = True ) def onPrefabRelink( self, entity ): self.tree.refreshNodeContent( entity, updateChildren = True ) def createPrefab( self, targetPrefab ): selection = self.getSelection() if not selection: return if len( selection ) > 1: return alertMessage( 'multiple entities cannot be converted into prefab' ) target = selection[0] self.doCommand( 'scene_editor/create_prefab', entity = target, prefab = targetPrefab.getNodePath(), file = targetPrefab.getAbsFilePath() ) def makeProto( self ): selection = self.getSelection() if not selection: return if len( selection ) > 1: return alertMessage( 'multiple entities cannot be converted into Proto' ) target = selection[0] if not target: return if requestConfirm( 'convert proto', 'Convert this Entity into Proto?' ): self.doCommand( 'scene_editor/make_proto', entity = target ) self.tree.refreshNodeContent( target ) def createProtoInstance( self ): pass ##----------------------------------------------------------------## def onCopyEntity( self ): entityGroupData = self.delegate.callMethod( 'editor', 'makeSceneSelectionCopyData' ) if not entityGroupData: return False clip = QtGui.QApplication.clipboard() mime = QtCore.QMimeData() text = '' for s in self.getSelection(): if text == '': text = text + s.name else: text = text + '\n' + s.name mime.setText( text ) mime.setData( GII_MIME_ENTITY_DATA, entityGroupData.encode('utf-8') ) clip.setMimeData( mime ) return True def onPasteEntity( self ): clip = QtGui.QApplication.clipboard() mime = clip.mimeData() if mime.hasFormat( GII_MIME_ENTITY_DATA ): data = mime.data( GII_MIME_ENTITY_DATA ) self.doCommand( 'scene_editor/paste_entity', data = str(data).decode('utf-8') ) ##----------------------------------------------------------------## def onCopyComponent( self ): entityGroupData = self.delegate.callMethod( 'editor', 'makeEntityCopyData' ) if not entityGroupData: return False clip = QtGui.QApplication.clipboard() mime = QtCore.QMimeData() text = '' for s in self.getSelection(): if text == '': text = text + s.name else: text = text + '\n' + s.name mime.setText( text ) mime.setData( GII_MIME_ENTITY_DATA, str(entityGroupData) ) clip.setMimeData( mime ) return True def onPasteComponent( self ): clip = QtGui.QApplication.clipboard() mime = clip.mimeData() if mime.hasFormat( GII_MIME_ENTITY_DATA ): data = mime.data( GII_MIME_ENTITY_DATA ) self.doCommand( 'scene_editor/paste_entity', data = str(data) )