mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
Added feature to import Maya file, undo/redo for object deletion
This commit is contained in:
parent
c62725336f
commit
f8fe9ef9f6
@ -1,8 +1,20 @@
|
|||||||
|
import ObjectGlobals as OG
|
||||||
|
|
||||||
class ActionBase(Functor):
|
class ActionBase(Functor):
|
||||||
""" Base class for user actions """
|
""" Base class for user actions """
|
||||||
|
|
||||||
def __init__(self, function, *args, **kargs):
|
def __init__(self, function, *args, **kargs):
|
||||||
Functor.__init__(self, function, *args, **kargs)
|
Functor.__init__(self, function, *args, **kargs)
|
||||||
|
self.result = None
|
||||||
|
|
||||||
|
def _do__call__(self, *args, **kargs):
|
||||||
|
self.saveStatus()
|
||||||
|
self.result = Functor._do__call__(self, *args, **kargs)
|
||||||
|
return self.result
|
||||||
|
|
||||||
|
def saveStatus(self):
|
||||||
|
# save object status for undo here
|
||||||
|
pass
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
print "undo method is not defined for this action"
|
print "undo method is not defined for this action"
|
||||||
@ -43,19 +55,92 @@ class ActionMgr:
|
|||||||
class ActionAddNewObj(ActionBase):
|
class ActionAddNewObj(ActionBase):
|
||||||
""" Action class for adding new object """
|
""" Action class for adding new object """
|
||||||
|
|
||||||
def __init__(self, function, *args, **kargs):
|
def __init__(self, editor, *args, **kargs):
|
||||||
|
self.editor = editor
|
||||||
|
function = self.editor.objectMgr.addNewObject
|
||||||
ActionBase.__init__(self, function, *args, **kargs)
|
ActionBase.__init__(self, function, *args, **kargs)
|
||||||
self.np = None
|
|
||||||
|
|
||||||
def _do__call__(self, *args, **kargs):
|
|
||||||
self.np = ActionBase._do__call__(self, *args, **kargs)
|
|
||||||
return self.np
|
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
if self.np is None:
|
if self.result is None:
|
||||||
print "Can't undo this"
|
print "Can't undo this"
|
||||||
else:
|
else:
|
||||||
base.direct.removeAllSelected()
|
base.direct.deselect(self.result)
|
||||||
base.le.objectMgr.deselectAll()
|
base.direct.removeNodePath(self.result)
|
||||||
base.direct.removeNodePath(self.np)
|
self.result = None
|
||||||
self.np = None
|
|
||||||
|
class ActionDeleteObj(ActionBase):
|
||||||
|
""" Action class for deleting object """
|
||||||
|
|
||||||
|
def __init__(self, editor, *args, **kargs):
|
||||||
|
self.editor = editor
|
||||||
|
function = base.direct.removeAllSelected
|
||||||
|
ActionBase.__init__(self, function, *args, **kargs)
|
||||||
|
self.selectedUIDs = []
|
||||||
|
self.hierarchy = {}
|
||||||
|
self.objInfos = {}
|
||||||
|
|
||||||
|
def saveStatus(self):
|
||||||
|
selectedNPs = base.direct.selected.getSelectedAsList()
|
||||||
|
def saveObjStatus(np, isRecursive=True):
|
||||||
|
obj = self.editor.objectMgr.findObjectByNodePath(np)
|
||||||
|
if obj:
|
||||||
|
uid = obj[OG.OBJ_UID]
|
||||||
|
if not isRecursive:
|
||||||
|
self.selectedUIDs.append(uid)
|
||||||
|
objNP = obj[OG.OBJ_NP]
|
||||||
|
self.objInfos[uid] = obj
|
||||||
|
parentNP = objNP.getParent()
|
||||||
|
if parentNP == render:
|
||||||
|
self.hierarchy[uid] = None
|
||||||
|
else:
|
||||||
|
parentObj = self.editor.objectMgr.findObjectByNodePath(parentNP)
|
||||||
|
if parentObj:
|
||||||
|
self.hierarchy[uid] = parentObj[OG.OBJ_UID]
|
||||||
|
|
||||||
|
for child in np.getChildren():
|
||||||
|
if child.hasTag('OBJRoot'):
|
||||||
|
saveObjStatus(child)
|
||||||
|
|
||||||
|
for np in selectedNPs:
|
||||||
|
saveObjStatus(np, False)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if len(self.hierarchy.keys()) == 0 or\
|
||||||
|
len(self.objInfos.keys()) == 0:
|
||||||
|
print "Can't undo this"
|
||||||
|
else:
|
||||||
|
def restoreObject(uid, parentNP):
|
||||||
|
obj = self.objInfos[uid]
|
||||||
|
objDef = obj[OG.OBJ_DEF]
|
||||||
|
objModel = obj[OG.OBJ_MODEL]
|
||||||
|
objProp = obj[OG.OBJ_PROP]
|
||||||
|
objRGBA = obj[OG.OBJ_RGBA]
|
||||||
|
self.editor.objectMgr.addNewObject(objDef.name,
|
||||||
|
uid,
|
||||||
|
obj[OG.OBJ_MODEL],
|
||||||
|
parentNP)
|
||||||
|
self.editor.objectMgr.updateObjectColor(objRGBA[0], objRGBA[1], objRGBA[2], objRGBA[3], uid)
|
||||||
|
self.editor.objectMgr.updateObjectProperties(uid, objProp)
|
||||||
|
|
||||||
|
while (len(self.hierarchy.keys()) > 0):
|
||||||
|
for uid in self.hierarchy.keys():
|
||||||
|
if self.hierarchy[uid] is None:
|
||||||
|
parentNP = None
|
||||||
|
restoreObject(uid, parentNP)
|
||||||
|
del self.hierarchy[uid]
|
||||||
|
else:
|
||||||
|
parentObj = self.editor.objectMgr.findObjectById(self.hierarchy[uid])
|
||||||
|
if parentObj:
|
||||||
|
parentNP = parentObj[OG.OBJ_NP]
|
||||||
|
restoreObject(uid, parentNP)
|
||||||
|
del self.hierarchy[uid]
|
||||||
|
|
||||||
|
base.direct.deselectAll()
|
||||||
|
for uid in self.selectedUIDs:
|
||||||
|
obj = self.editor.objectMgr.findObjectById(uid)
|
||||||
|
if obj:
|
||||||
|
base.direct.select(obj[OG.OBJ_NP], fMultiSelect=1)
|
||||||
|
|
||||||
|
self.selecteUIDs = []
|
||||||
|
self.hierarchy = {}
|
||||||
|
self.objInfos = {}
|
||||||
|
@ -16,6 +16,7 @@ from ObjectMgr import *
|
|||||||
from FileMgr import *
|
from FileMgr import *
|
||||||
from ActionMgr import *
|
from ActionMgr import *
|
||||||
from ProtoPalette import *
|
from ProtoPalette import *
|
||||||
|
from MayaConverter import *
|
||||||
|
|
||||||
class LevelEditorBase(DirectObject):
|
class LevelEditorBase(DirectObject):
|
||||||
""" Base Class for Panda3D LevelEditor """
|
""" Base Class for Panda3D LevelEditor """
|
||||||
@ -110,6 +111,7 @@ class LevelEditorBase(DirectObject):
|
|||||||
('DIRECT-delete', self.handleDelete),
|
('DIRECT-delete', self.handleDelete),
|
||||||
('preRemoveNodePath', self.removeNodePathHook),
|
('preRemoveNodePath', self.removeNodePathHook),
|
||||||
('DIRECT_selectedNodePath_fMulti_fTag', self.selectedNodePathHook),
|
('DIRECT_selectedNodePath_fMulti_fTag', self.selectedNodePathHook),
|
||||||
|
('DIRECT_deselectedNodePath', self.deselectAll),
|
||||||
('DIRECT_deselectAll', self.deselectAll),
|
('DIRECT_deselectAll', self.deselectAll),
|
||||||
('LE-Undo', self.actionMgr.undo),
|
('LE-Undo', self.actionMgr.undo),
|
||||||
('LE-Redo', self.actionMgr.redo),
|
('LE-Redo', self.actionMgr.redo),
|
||||||
@ -140,20 +142,22 @@ class LevelEditorBase(DirectObject):
|
|||||||
base.direct.selected.last = None
|
base.direct.selected.last = None
|
||||||
|
|
||||||
def handleDelete(self):
|
def handleDelete(self):
|
||||||
reply = wx.MessageBox("Do you want to delete selected?", "Delete?",
|
action = ActionDeleteObj(self)
|
||||||
wx.YES_NO | wx.ICON_QUESTION)
|
self.actionMgr.push(action)
|
||||||
if reply == wx.YES:
|
action()
|
||||||
base.direct.removeAllSelected()
|
## reply = wx.MessageBox("Do you want to delete selected?", "Delete?",
|
||||||
self.objectMgr.deselectAll()
|
## wx.YES_NO | wx.ICON_QUESTION)
|
||||||
else:
|
## if reply == wx.YES:
|
||||||
# need to reset COA
|
## base.direct.removeAllSelected()
|
||||||
dnp = base.direct.selected.last
|
## else:
|
||||||
# Update camera controls coa to this point
|
## # need to reset COA
|
||||||
# Coa2Camera = Coa2Dnp * Dnp2Camera
|
## dnp = base.direct.selected.last
|
||||||
mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(base.direct.camera)
|
## # Update camera controls coa to this point
|
||||||
row = mCoa2Camera.getRow(3)
|
## # Coa2Camera = Coa2Dnp * Dnp2Camera
|
||||||
coa = Vec3(row[0], row[1], row[2])
|
## mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(base.direct.camera)
|
||||||
base.direct.cameraControl.updateCoa(coa)
|
## row = mCoa2Camera.getRow(3)
|
||||||
|
## coa = Vec3(row[0], row[1], row[2])
|
||||||
|
## base.direct.cameraControl.updateCoa(coa)
|
||||||
|
|
||||||
def selectedNodePathHook(self, nodePath, fMultiSelect = 0, fSelectTag = 1):
|
def selectedNodePathHook(self, nodePath, fMultiSelect = 0, fSelectTag = 1):
|
||||||
# handle unpickable nodepath
|
# handle unpickable nodepath
|
||||||
@ -163,7 +167,7 @@ class LevelEditorBase(DirectObject):
|
|||||||
|
|
||||||
self.objectMgr.selectObject(nodePath)
|
self.objectMgr.selectObject(nodePath)
|
||||||
|
|
||||||
def deselectAll(self):
|
def deselectAll(self, np=None):
|
||||||
self.objectMgr.deselectAll()
|
self.objectMgr.deselectAll()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
@ -221,3 +225,15 @@ class LevelEditorBase(DirectObject):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def convertMaya(self, modelname, obj=None, isAnim=False):
|
||||||
|
if obj and isAnim:
|
||||||
|
mayaConverter = MayaConverter(self.ui, self, modelname, obj, isAnim)
|
||||||
|
else:
|
||||||
|
reply = wx.MessageBox("Is it an animation file?", "Animation?",
|
||||||
|
wx.YES_NO | wx.ICON_QUESTION)
|
||||||
|
if reply == wx.YES:
|
||||||
|
mayaConverter = MayaConverter(self.ui, self, modelname, None, True)
|
||||||
|
else:
|
||||||
|
mayaConverter = MayaConverter(self.ui, self, modelname, None, False)
|
||||||
|
mayaConverter.Show()
|
||||||
|
@ -20,7 +20,7 @@ class PandaTextDropTarget(wx.TextDropTarget):
|
|||||||
self.editor = editor
|
self.editor = editor
|
||||||
|
|
||||||
def OnDropText(self, x, y, text):
|
def OnDropText(self, x, y, text):
|
||||||
action = ActionAddNewObj(self.editor.objectMgr.addNewObject, text)
|
action = ActionAddNewObj(self.editor, text)
|
||||||
self.editor.actionMgr.push(action)
|
self.editor.actionMgr.push(action)
|
||||||
action()
|
action()
|
||||||
|
|
||||||
|
154
direct/src/leveleditor/MayaConverter.py
Executable file
154
direct/src/leveleditor/MayaConverter.py
Executable file
@ -0,0 +1,154 @@
|
|||||||
|
from direct.wxwidgets.WxAppShell import *
|
||||||
|
import os, re, shutil
|
||||||
|
|
||||||
|
from ObjectPaletteBase import *
|
||||||
|
|
||||||
|
CLOSE_STDIN = "<CLOSE STDIN>"
|
||||||
|
|
||||||
|
class Process:
|
||||||
|
def __init__(self, parent, cmd, end_callback):
|
||||||
|
self.process = wx.Process(parent)
|
||||||
|
self.process.Redirect()
|
||||||
|
self.process.pid = wx.Execute(cmd, wx.EXEC_ASYNC|wx.EXEC_MAKE_GROUP_LEADER, self.process)
|
||||||
|
self.b = []
|
||||||
|
if self.process.pid:
|
||||||
|
#what was up with wx.Process.Get*Stream names?
|
||||||
|
self.process._stdin_ = self.process.GetOutputStream()
|
||||||
|
self.process._stdout_ = self.process.GetInputStream()
|
||||||
|
self.process._stderr_ = self.process.GetErrorStream()
|
||||||
|
self.process.Bind(wx.EVT_END_PROCESS, end_callback)
|
||||||
|
return
|
||||||
|
raise StartupError
|
||||||
|
|
||||||
|
def Poll(self, input=''):
|
||||||
|
if (input or self.b) and self.process and self.process._stdin_:
|
||||||
|
if self.b or len(input) > 512:
|
||||||
|
if input:
|
||||||
|
#if we don't chop up our input into resonably sized chunks,
|
||||||
|
#some platforms (like Windows) will send some small number
|
||||||
|
#of bytes per .write() call (sometimes 2 in the case of
|
||||||
|
#Windows).
|
||||||
|
self.b.extend([input[i:i+512] for i in xrange(0, len(input), 512)])
|
||||||
|
input = self.b.pop(0)
|
||||||
|
self.process._stdin_.write(input)
|
||||||
|
if hasattr(self.process._stdin_, "LastWrite"):
|
||||||
|
y = self.process._stdin_.LastWrite()
|
||||||
|
if y != len(input):
|
||||||
|
self.b.insert(0, input[y:])
|
||||||
|
x = []
|
||||||
|
for s in (self.process._stderr_, self.process._stdout_):
|
||||||
|
if s and s.CanRead():
|
||||||
|
x.append(s.read())
|
||||||
|
else:
|
||||||
|
x.append('')
|
||||||
|
return x
|
||||||
|
|
||||||
|
def CloseInp(self):
|
||||||
|
if self.process and self.process._stdin_:
|
||||||
|
self.process.CloseOutput()
|
||||||
|
self.process._stdin_ = None
|
||||||
|
|
||||||
|
def Kill(self, ks='SIGKILL'):
|
||||||
|
errors = {wx.KILL_BAD_SIGNAL: "KILL_BAD_SIGNAL",
|
||||||
|
wx.KILL_ACCESS_DENIED: "KILL_ACCESS_DENIED",
|
||||||
|
wx.KILL_ERROR: "KILL_ERROR"}
|
||||||
|
if self.process:
|
||||||
|
if ks == CLOSE_STDIN:
|
||||||
|
self.CloseInp()
|
||||||
|
return 1, None
|
||||||
|
elif wx.Process.Exists(self.process.pid):
|
||||||
|
signal = getattr(wx, ks)
|
||||||
|
r = wx.Process.Kill(self.process.pid, signal, flags=wx.KILL_CHILDREN)
|
||||||
|
else:
|
||||||
|
r = 65535
|
||||||
|
self.CloseInp()
|
||||||
|
return 1, None
|
||||||
|
|
||||||
|
if r not in (wx.KILL_OK, wx.KILL_NO_PROCESS, 65535):
|
||||||
|
return 0, (self.process.pid, signal, errors.get(r, "UNKNOWN_KILL_ERROR %s"%r))
|
||||||
|
else:
|
||||||
|
return 1, None
|
||||||
|
|
||||||
|
class MayaConverter(wx.Dialog):
|
||||||
|
def __init__(self, parent, editor, mayaFile, obj = None, isAnim=False):
|
||||||
|
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Maya Converter",
|
||||||
|
pos=wx.DefaultPosition, size=(300, 200))
|
||||||
|
|
||||||
|
self.editor = editor
|
||||||
|
self.obj = obj
|
||||||
|
self.isAnim = isAnim
|
||||||
|
|
||||||
|
self.mainPanel = wx.Panel(self, -1)
|
||||||
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
sizer.Add(self.mainPanel, 1, wx.EXPAND, 0)
|
||||||
|
self.SetSizer(sizer)
|
||||||
|
|
||||||
|
self.output = wx.TextCtrl(self.mainPanel, -1, style = wx.TE_MULTILINE, pos = (0, 0), size = (100, 400))
|
||||||
|
sizer2 = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
sizer2.Add(self.output, 1, wx.EXPAND, 0)
|
||||||
|
self.mainPanel.SetSizer(sizer2)
|
||||||
|
|
||||||
|
if self.isAnim:
|
||||||
|
if self.obj:
|
||||||
|
command = 'maya2egg -a chan %s -o %s.anim.egg'%(mayaFile, mayaFile)
|
||||||
|
self.process = Process(self, command, lambda p0=None, p1=mayaFile: self.onProcessEnded(p0, p1))
|
||||||
|
else:
|
||||||
|
command = 'maya2egg -a model %s -o %s.model.egg'%(mayaFile, mayaFile)
|
||||||
|
self.process = Process(self, command, lambda p0=None, p1=mayaFile: self.onModelProcessEnded(p0, p1))
|
||||||
|
else:
|
||||||
|
command = 'maya2egg %s -o %s.egg'%(mayaFile, mayaFile)
|
||||||
|
self.process = Process(self, command, lambda p0=None, p1=mayaFile: self.onProcessEnded(p0, p1))
|
||||||
|
|
||||||
|
self.timer = wx.Timer(self, -1)
|
||||||
|
self.Bind(wx.EVT_TIMER, self.onPoll, self.timer)
|
||||||
|
self.timer.Start(100)
|
||||||
|
|
||||||
|
def onPoll(self, evt):
|
||||||
|
if self.process:
|
||||||
|
for i in self.process.Poll():
|
||||||
|
self.output.AppendText(i)
|
||||||
|
|
||||||
|
def onModelProcessEnded(self, evt, mayaFile):
|
||||||
|
self.process.CloseInp()
|
||||||
|
for i in self.process.Poll():
|
||||||
|
self.output.AppendText(i)
|
||||||
|
self.process = None
|
||||||
|
command = 'maya2egg -a chan %s -o %s.anim.egg'%(mayaFile, mayaFile)
|
||||||
|
self.process = Process(self, command, lambda p0 = None, p1=mayaFile: self.onProcessEnded(p0, p1))
|
||||||
|
|
||||||
|
def onProcessEnded(self, evt, mayaFile):
|
||||||
|
self.process.CloseInp()
|
||||||
|
for i in self.process.Poll():
|
||||||
|
self.output.AppendText(i)
|
||||||
|
|
||||||
|
self.output.AppendText('Converting %s is finished\n'%mayaFile)
|
||||||
|
self.process = None
|
||||||
|
|
||||||
|
name = os.path.basename(mayaFile)
|
||||||
|
if self.isAnim:
|
||||||
|
if self.obj:
|
||||||
|
objDef = self.obj[OG.OBJ_DEF]
|
||||||
|
objNP = self.obj[OG.OBJ_NP]
|
||||||
|
animName = "%s.anim.egg"%mayaFile
|
||||||
|
if animName not in objDef.anims:
|
||||||
|
objDef.anims.append(animName)
|
||||||
|
name = os.path.basename(animName)
|
||||||
|
objNP.loadAnims({name:animName})
|
||||||
|
objNP.loop(name)
|
||||||
|
self.obj[OG.OBJ_ANIM] = animName
|
||||||
|
self.editor.ui.objectPropertyUI.updateProps(self.obj)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
modelName = "%s.model.egg"%mayaFile
|
||||||
|
animName = "%s.anim.egg"%mayaFile
|
||||||
|
itemData = ObjectBase(name=name, model=modelName, anims=[animName], actor=True)
|
||||||
|
else:
|
||||||
|
modelName = "%s.egg"%mayaFile
|
||||||
|
itemData = ObjectBase(name=name, model=modelName, actor=False)
|
||||||
|
|
||||||
|
self.editor.protoPalette.add(itemData)
|
||||||
|
|
||||||
|
newItem = self.editor.ui.protoPaletteUI.tree.AppendItem(self.editor.ui.protoPaletteUI.root, name)
|
||||||
|
self.editor.ui.protoPaletteUI.tree.SetItemPyData(newItem, itemData)
|
||||||
|
self.editor.ui.protoPaletteUI.tree.ScrollTo(newItem)
|
||||||
|
|
@ -58,7 +58,7 @@ class ObjectMgr:
|
|||||||
self.lastUidMod = 0
|
self.lastUidMod = 0
|
||||||
return newUid
|
return newUid
|
||||||
|
|
||||||
def addNewObject(self, typeName, uid = None, model = None, parent=None, fSelectObject=True):
|
def addNewObject(self, typeName, uid = None, model = None, parent=None, anim = 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
|
||||||
@ -105,7 +105,6 @@ class ObjectMgr:
|
|||||||
except:
|
except:
|
||||||
newobj = loader.loadModel(Filename.fromOsSpecific(model).getFullpath())
|
newobj = loader.loadModel(Filename.fromOsSpecific(model).getFullpath())
|
||||||
|
|
||||||
anim = ''
|
|
||||||
i = 0
|
i = 0
|
||||||
for i in range(len(objDef.anims)):
|
for i in range(len(objDef.anims)):
|
||||||
animFile = objDef.anims[i]
|
animFile = objDef.anims[i]
|
||||||
@ -114,9 +113,14 @@ class ObjectMgr:
|
|||||||
if i < len(objDef.animNames):
|
if i < len(objDef.animNames):
|
||||||
animName = objDef.animNames[i]
|
animName = objDef.animNames[i]
|
||||||
newAnim = newobj.loadAnims({animName:animFile})
|
newAnim = newobj.loadAnims({animName:animFile})
|
||||||
if i == 0:
|
|
||||||
anim = animFile
|
if anim:
|
||||||
newobj.loop(animName)
|
if anim == animFile:
|
||||||
|
newobj.loop(animName)
|
||||||
|
else:
|
||||||
|
if i == 0:
|
||||||
|
anim = animFile
|
||||||
|
newobj.loop(animName)
|
||||||
|
|
||||||
if newobj is None:
|
if newobj is None:
|
||||||
return None
|
return None
|
||||||
@ -151,6 +155,11 @@ class ObjectMgr:
|
|||||||
del self.objects[uid]
|
del self.objects[uid]
|
||||||
del self.npIndex[nodePath]
|
del self.npIndex[nodePath]
|
||||||
|
|
||||||
|
# remove children also
|
||||||
|
for child in nodePath.getChildren():
|
||||||
|
if child.hasTag('OBJRoot'):
|
||||||
|
self.removeObjectByNodePath(child)
|
||||||
|
|
||||||
def findObjectById(self, uid):
|
def findObjectById(self, uid):
|
||||||
return self.objects.get(uid)
|
return self.objects.get(uid)
|
||||||
|
|
||||||
@ -290,7 +299,8 @@ class ObjectMgr:
|
|||||||
base.direct.deselectAll()
|
base.direct.deselectAll()
|
||||||
|
|
||||||
objNP = obj[OG.OBJ_NP]
|
objNP = obj[OG.OBJ_NP]
|
||||||
|
objRGBA = obj[OG.OBJ_RGBA]
|
||||||
|
|
||||||
# load new model
|
# load new model
|
||||||
newobj = loader.loadModel(model)
|
newobj = loader.loadModel(model)
|
||||||
newobj.setTag('OBJRoot','1')
|
newobj.setTag('OBJRoot','1')
|
||||||
@ -306,6 +316,9 @@ class ObjectMgr:
|
|||||||
newobj.setHpr(objNP.getHpr())
|
newobj.setHpr(objNP.getHpr())
|
||||||
newobj.setScale(objNP.getScale())
|
newobj.setScale(objNP.getScale())
|
||||||
|
|
||||||
|
# copy RGBA data
|
||||||
|
self.updateObjectColor(objRGBA[0], objRGBA[1], objRGBA[2], objRGBA[3], newobj)
|
||||||
|
|
||||||
# delete old geom
|
# delete old geom
|
||||||
del self.npIndex[NodePath(objNP)]
|
del self.npIndex[NodePath(objNP)]
|
||||||
objNP.removeNode()
|
objNP.removeNode()
|
||||||
@ -474,6 +487,7 @@ class ObjectMgr:
|
|||||||
np = obj[OG.OBJ_NP]
|
np = obj[OG.OBJ_NP]
|
||||||
objDef = obj[OG.OBJ_DEF]
|
objDef = obj[OG.OBJ_DEF]
|
||||||
objModel = obj[OG.OBJ_MODEL]
|
objModel = obj[OG.OBJ_MODEL]
|
||||||
|
objAnim = obj[OG.OBJ_ANIM]
|
||||||
objProp = obj[OG.OBJ_PROP]
|
objProp = obj[OG.OBJ_PROP]
|
||||||
objRGBA = obj[OG.OBJ_RGBA]
|
objRGBA = obj[OG.OBJ_RGBA]
|
||||||
|
|
||||||
@ -482,10 +496,17 @@ class ObjectMgr:
|
|||||||
else:
|
else:
|
||||||
parentStr = "None"
|
parentStr = "None"
|
||||||
|
|
||||||
if objModel is None:
|
if objModel:
|
||||||
self.saveData.append("\nobjects['%s'] = objectMgr.addNewObject('%s', '%s', None, %s)"%(uid, objDef.name, uid, parentStr))
|
modelStr = "'%s'"%objModel
|
||||||
else:
|
else:
|
||||||
self.saveData.append("\nobjects['%s'] = objectMgr.addNewObject('%s', '%s', '%s', %s)"%(uid, objDef.name, uid, objModel, parentStr))
|
modelStr = "None"
|
||||||
|
|
||||||
|
if objAnim:
|
||||||
|
animStr = "'%s'"%objAnim
|
||||||
|
else:
|
||||||
|
animStr = "None"
|
||||||
|
|
||||||
|
self.saveData.append("\nobjects['%s'] = objectMgr.addNewObject('%s', '%s', %s, %s, %s)"%(uid, objDef.name, uid, modelStr, parentStr, animStr))
|
||||||
self.saveData.append("if objects['%s']:"%uid)
|
self.saveData.append("if objects['%s']:"%uid)
|
||||||
self.saveData.append(" objects['%s'].setPos(%s)"%(uid, np.getPos()))
|
self.saveData.append(" objects['%s'].setPos(%s)"%(uid, np.getPos()))
|
||||||
self.saveData.append(" objects['%s'].setHpr(%s)"%(uid, np.getHpr()))
|
self.saveData.append(" objects['%s'].setHpr(%s)"%(uid, np.getHpr()))
|
||||||
@ -505,6 +526,10 @@ class ObjectMgr:
|
|||||||
if obj is None:
|
if obj is None:
|
||||||
return None
|
return None
|
||||||
objDef = obj[OG.OBJ_DEF]
|
objDef = obj[OG.OBJ_DEF]
|
||||||
|
objModel = obj[OG.OBJ_MODEL]
|
||||||
|
objAnim = obj[OG.OBJ_ANIM]
|
||||||
|
objRGBA = obj[OG.OBJ_RGBA]
|
||||||
|
|
||||||
if parent is None:
|
if parent is None:
|
||||||
parent = nodePath.getParent()
|
parent = nodePath.getParent()
|
||||||
|
|
||||||
@ -521,6 +546,9 @@ class ObjectMgr:
|
|||||||
# copy model info
|
# copy model info
|
||||||
self.updateObjectModel(obj[OG.OBJ_MODEL], newObj, fSelectObject=False)
|
self.updateObjectModel(obj[OG.OBJ_MODEL], newObj, fSelectObject=False)
|
||||||
|
|
||||||
|
# copy anim info
|
||||||
|
self.updateObjectAnim(obj[OG.OBJ_ANIM], newObj, fSelectObject=False)
|
||||||
|
|
||||||
# copy other properties
|
# copy other properties
|
||||||
for key in obj[OG.OBJ_PROP]:
|
for key in obj[OG.OBJ_PROP]:
|
||||||
self.updateObjectPropValue(newObj, key, obj[OG.OBJ_PROP][key])
|
self.updateObjectPropValue(newObj, key, obj[OG.OBJ_PROP][key])
|
||||||
|
@ -38,11 +38,8 @@ class ObjectPaletteBase:
|
|||||||
"""
|
"""
|
||||||
You can insert item to obj palette tree.
|
You can insert item to obj palette tree.
|
||||||
|
|
||||||
'item' is the name to be inserted, it can be either a group or obj.
|
'item' is the object to be inserted, it can be either a group or obj.
|
||||||
If item is a group 'obj' will be None.
|
|
||||||
'parentName' is the name of parent under where this item will be inserted.
|
'parentName' is the name of parent under where this item will be inserted.
|
||||||
'data' is used in recursive searching.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if type(self.data) != dict:
|
if type(self.data) != dict:
|
||||||
return None
|
return None
|
||||||
|
@ -29,6 +29,11 @@ class AnimFileDrop(wx.FileDropTarget):
|
|||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
name = os.path.basename(filename)
|
name = os.path.basename(filename)
|
||||||
animName = Filename.fromOsSpecific(filename).getFullpath()
|
animName = Filename.fromOsSpecific(filename).getFullpath()
|
||||||
|
if name.endswith('.mb') or\
|
||||||
|
name.endswith('.ma'):
|
||||||
|
self.editor.convertMaya(animName, obj, isAnim=True)
|
||||||
|
return
|
||||||
|
|
||||||
if animName not in objDef.anims:
|
if animName not in objDef.anims:
|
||||||
objDef.anims.append(animName)
|
objDef.anims.append(animName)
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ class FileDrop(wx.FileDropTarget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
modelname = Filename.fromOsSpecific(filename).getFullpath()
|
modelname = Filename.fromOsSpecific(filename).getFullpath()
|
||||||
|
if modelname.endswith('.mb') or\
|
||||||
|
modelname.endswith('.ma'):
|
||||||
|
self.editor.convertMaya(modelname)
|
||||||
|
return
|
||||||
itemData = ObjectBase(name=name, model=modelname, actor=True)
|
itemData = ObjectBase(name=name, model=modelname, actor=True)
|
||||||
self.editor.protoPalette.add(itemData)
|
self.editor.protoPalette.add(itemData)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user