Added object duplication and grid snapping

This commit is contained in:
Gyedo Jeon 2009-10-07 22:09:31 +00:00
parent d1d8685fe5
commit 47b9e90b4c
5 changed files with 101 additions and 18 deletions

View File

@ -19,6 +19,7 @@ class LevelEditorBase(DirectObject):
""" Base Class for Panda3D LevelEditor """ """ Base Class for Panda3D LevelEditor """
def __init__(self): def __init__(self):
#loadPrcFileData('startup', 'window-type none') #loadPrcFileData('startup', 'window-type none')
self.currentFile = None
self.actionEvents = [] self.actionEvents = []
self.objectMgr = ObjectMgr(self) self.objectMgr = ObjectMgr(self)
self.fileMgr = FileMgr(self) self.fileMgr = FileMgr(self)
@ -130,9 +131,14 @@ class LevelEditorBase(DirectObject):
base.direct.deselectAll() base.direct.deselectAll()
self.objectMgr.reset() self.objectMgr.reset()
def save(self, fileName): def save(self):
if self.currentFile:
self.fileMgr.saveToFile(self.currentFile)
def saveAs(self, fileName):
self.fileMgr.saveToFile(fileName) self.fileMgr.saveToFile(fileName)
def load(self, fileName): def load(self, fileName):
self.reset() self.reset()
self.fileMgr.loadFromFile(fileName) self.fileMgr.loadFromFile(fileName)
self.currentFile = fileName

View File

@ -49,6 +49,18 @@ class LevelEditorUI(WxAppShell):
menuItem = self.menuFile.Insert(2, -1 , "&Save") menuItem = self.menuFile.Insert(2, -1 , "&Save")
self.Bind(wx.EVT_MENU, self.onSave, menuItem) self.Bind(wx.EVT_MENU, self.onSave, menuItem)
menuItem = self.menuFile.Insert(3, -1 , "Save &As")
self.Bind(wx.EVT_MENU, self.onSaveAs, menuItem)
self.menuEdit = wx.Menu()
self.menuBar.Insert(1, self.menuEdit, "&Edit")
menuItem = self.menuEdit.Append(-1, "&Duplicate")
self.Bind(wx.EVT_MENU, self.onDuplicate, menuItem)
self.gridSnapMenuItem = self.menuEdit.Append(-1, "&Grid Snap", kind = wx.ITEM_CHECK)
self.Bind(wx.EVT_MENU, self.toggleGridSnap, self.gridSnapMenuItem)
def createInterface(self): def createInterface(self):
self.createMenu() self.createMenu()
@ -132,7 +144,22 @@ class LevelEditorUI(WxAppShell):
dialog.Destroy() dialog.Destroy()
def onSave(self, evt): def onSave(self, evt):
if self.editor.currentFile is None:
self.onSaveAs(evt)
else:
self.editor.save()
def onSaveAs(self, evt):
dialog = wx.FileDialog(None, "Choose a file", os.getcwd(), "", "*.py", wx.SAVE) dialog = wx.FileDialog(None, "Choose a file", os.getcwd(), "", "*.py", wx.SAVE)
if dialog.ShowModal() == wx.ID_OK: if dialog.ShowModal() == wx.ID_OK:
self.editor.save(dialog.GetPath()) self.editor.saveAs(dialog.GetPath())
dialog.Destroy() dialog.Destroy()
def onDuplicate(self, evt):
self.editor.objectMgr.duplicateSelected()
def toggleGridSnap(self, evt):
if self.gridSnapMenuItem.IsChecked():
base.direct.manipulationControl.fGridSnap = 1
else:
base.direct.manipulationControl.fGridSnap = 0

View File

@ -56,8 +56,6 @@ class ObjectHandler:
b.reparentTo(objNP) b.reparentTo(objNP)
a.removeNode() a.removeNode()
base.direct.select(objNP)
def createPanda(self): def createPanda(self):
pandaActor = PandaActor() pandaActor = PandaActor()
return pandaActor return pandaActor

View File

@ -57,7 +57,7 @@ class ObjectMgr:
self.lastUidMod = 0 self.lastUidMod = 0
return newUid return newUid
def addNewObject(self, typeName, uid = None, model = None, parent=None): def addNewObject(self, typeName, uid = None, model = None, parent=None, fSelectObject=True):
""" function to add new obj to the scene """ """ function to add new obj to the scene """
if parent is None: if parent is None:
parent = render parent = render
@ -93,9 +93,8 @@ class ObjectMgr:
if uid is None: if uid is None:
uid = self.genUniqueId() uid = self.genUniqueId()
isLoadingArea = False
else: else:
isLoadingArea = True fSelectObject = False
# populate obj data using default values # populate obj data using default values
properties = {} properties = {}
@ -106,7 +105,7 @@ class ObjectMgr:
self.objects[uid] = [uid, newobj, objDef, model, properties] self.objects[uid] = [uid, newobj, objDef, model, properties]
self.npIndex[NodePath(newobj)] = uid self.npIndex[NodePath(newobj)] = uid
if not isLoadingArea: if fSelectObject:
base.direct.select(newobj) base.direct.select(newobj)
return newobj return newobj
@ -235,12 +234,8 @@ class ObjectMgr:
np.setSy(float(self.editor.ui.objectPropertyUI.propSY.getValue())) np.setSy(float(self.editor.ui.objectPropertyUI.propSY.getValue()))
np.setSz(float(self.editor.ui.objectPropertyUI.propSZ.getValue())) np.setSz(float(self.editor.ui.objectPropertyUI.propSZ.getValue()))
def updateObjectModel(self, event, obj): def updateObjectModel(self, model, obj, fSelectObject=True):
""" replace object's model """ """ replace object's model """
model = event.GetString()
if model is None:
return
if obj[OG.OBJ_MODEL] != model: if obj[OG.OBJ_MODEL] != model:
base.direct.deselectAll() base.direct.deselectAll()
@ -270,7 +265,15 @@ class ObjectMgr:
obj[OG.OBJ_MODEL] = model obj[OG.OBJ_MODEL] = model
self.npIndex[NodePath(newobj)] = obj[OG.OBJ_UID] self.npIndex[NodePath(newobj)] = obj[OG.OBJ_UID]
base.direct.select(newobj) if fSelectObject:
base.direct.select(newobj)
def updateObjectModelFromUI(self, event, obj):
""" replace object's model with one selected from UI """
model = event.GetString()
if model is not None:
self.updateObjectModel(model, obj)
def updateObjectProperty(self, event, obj, propName): def updateObjectProperty(self, event, obj, propName):
""" """
@ -329,7 +332,7 @@ class ObjectMgr:
# now update object prop value and call update function # now update object prop value and call update function
self.updateObjectPropValue(obj, propName, val) self.updateObjectPropValue(obj, propName, val)
def updateObjectPropValue(self, obj, propName, val): def updateObjectPropValue(self, obj, propName, val, fSelectObject=True):
""" """
Update object property value and Update object property value and
call update function if defined. call update function if defined.
@ -368,6 +371,9 @@ class ObjectMgr:
# finally call update function # finally call update function
func(**kwargs) func(**kwargs)
if fSelectObject:
base.direct.select(obj[OG.OBJ_NP])
def updateObjectProperties(self, nodePath, propValues): def updateObjectProperties(self, nodePath, propValues):
""" """
When a saved level is loaded, When a saved level is loaded,
@ -418,4 +424,50 @@ class ObjectMgr:
self.traverse(render) self.traverse(render)
return self.saveData return self.saveData
def duplicateObject(self, nodePath, parent=None):
obj = self.findObjectByNodePath(nodePath)
if obj is None:
return None
objDef = obj[OG.OBJ_DEF]
if parent is None:
parent = nodePath.getParent()
newObjNP = self.addNewObject(objDef.name, parent=parent, fSelectObject = False)
# copy transform data
newObjNP.setPos(obj[OG.OBJ_NP].getPos())
newObjNP.setHpr(obj[OG.OBJ_NP].getHpr())
newObjNP.setScale(obj[OG.OBJ_NP].getScale())
newObj = self.findObjectByNodePath(NodePath(newObjNP))
if newObj is None:
return None
# copy model info
self.updateObjectModel(obj[OG.OBJ_MODEL], newObj, fSelectObject=False)
# copy other properties
for key in obj[OG.OBJ_PROP]:
self.updateObjectPropValue(newObj, key, obj[OG.OBJ_PROP][key], fSelectObject=False)
return newObjNP
def duplicateChild(self, nodePath, parent):
children = nodePath.findAllMatches('=OBJRoot')
for childNP in children:
newChildObjNP = self.duplicateObject(childNP, parent)
if newChildObjNP is not None:
self.duplicateChild(childNP, newChildObjNP)
def duplicateSelected(self):
selectedNPs = base.direct.selected.getSelectedAsList()
duplicatedNPs = []
for nodePath in selectedNPs:
newObjNP = self.duplicateObject(nodePath)
if newObjNP is not None:
self.duplicateChild(nodePath, newObjNP)
duplicatedNPs.append(newObjNP)
base.direct.deselectAll()
print duplicatedNPs
for newNodePath in duplicatedNPs:
base.direct.select(newNodePath, fMultiSelect = 1)

View File

@ -173,7 +173,7 @@ class ObjectPropertyUI(ScrolledPanel):
propUI.bindFunc(self.editor.objectMgr.onEnterObjectPropUI, propUI.bindFunc(self.editor.objectMgr.onEnterObjectPropUI,
self.editor.objectMgr.onLeaveObjectPropUI, self.editor.objectMgr.onLeaveObjectPropUI,
lambda p0=None, p1=obj: self.editor.objectMgr.updateObjectModel(p0, p1)) lambda p0=None, p1=obj: self.editor.objectMgr.updateObjectModelFromUI(p0, p1))
for key in objDef.properties.keys(): for key in objDef.properties.keys():
propDef = objDef.properties[key] propDef = objDef.properties[key]