Poodletooth-iLand/panda/direct/leveleditor/ObjectPropertyUI.py
Master Jumblespeed d882959bfa switch to remote
2015-05-18 22:11:33 -04:00

651 lines
25 KiB
Python
Executable file

"""
UI for object property control
"""
import wx
import os
import math
from wx.lib.embeddedimage import PyEmbeddedImage
from wx.lib.scrolledpanel import ScrolledPanel
from wx.lib.agw.cubecolourdialog import *
from direct.wxwidgets.WxSlider import *
from pandac.PandaModules import *
import ObjectGlobals as OG
import AnimGlobals as AG
#----------------------------------------------------------------------
Key = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAA3NCSVQICAjb4U/gAAABIElE"
"QVQokZWSMW7CQBBFZ2Z3sQ02Ni4sOS6QiLgO5yBXIMcJ1KENje8QLESH7F3FVFQIIS3eTWGJ"
"VE7Iq6Z4+tL8GVRSwmPQg94fKiIOBoNer2et/U1FRER8X6+LonBdFwB4l+p53mq1qqRUUsZx"
"nKYpBwDOuRACEQGgaRoAYETn8/l4PL4uFkqp/X6fZRlnjO12u7KqENEa43keADDGvuo6Go0A"
"wPd9YkxrzY0x4/FYKlXX9eVymc1mjIiIgiD43G4BwFprmgYRubU2DMPnySTw/ev1+pSmRISI"
"SZJ8bDan06ksSyLiQmDXCfr9fp7nb8vldDp9mc9d1/1R27XaClscxzkcDlEUhcOhvt06U1uE"
"EMaYtpbOXlu01vf5Hz/wDRuDdIDl5WtQAAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
class AnimFileDrop(wx.FileDropTarget):
def __init__(self, editor):
wx.FileDropTarget.__init__(self)
self.editor = editor
def OnDropFiles(self, x, y, filenames):
obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
if obj is None:
return
objDef = obj[OG.OBJ_DEF]
if not objDef.actor:
return
objNP = obj[OG.OBJ_NP]
for filename in filenames:
name = os.path.basename(filename)
animName = Filename.fromOsSpecific(filename).getFullpath()
if name.endswith('.mb') or\
name.endswith('.ma'):
self.editor.convertMaya(animName, self.editor.ui.protoPaletteUI.addNewItem, obj, isAnim=True)
return
if animName not in objDef.anims:
objDef.anims.append(animName)
objNP.loadAnims({name:animName})
objNP.loop(name)
obj[OG.OBJ_ANIM] = animName
self.editor.ui.objectPropertyUI.updateProps(obj)
class ObjectPropUI(wx.Panel):
"""
Base class for ObjectPropUIs,
It consists of label area and ui area.
"""
def __init__(self, parent, label):
wx.Panel.__init__(self, parent)
self.parent = parent
self.labelPane = wx.Panel(self)
self.label = wx.StaticText(self.labelPane, label=label)
self.labelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.labelSizer.Add(self.label)
bmpKey = Key.GetBitmap()
self.setKeyButton = wx.BitmapButton(self.labelPane, -1, bmpKey, size = (15,15),style = wx.BU_AUTODRAW)
self.labelSizer.Add(self.setKeyButton)
self.labelPane.SetSizer(self.labelSizer)
self.uiPane = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.labelPane)
sizer.Add(self.uiPane, 1, wx.EXPAND, 0)
self.SetSizer(sizer)
self.setKeyButton.Bind(wx.EVT_BUTTON, self.onKey)
def onKey(self,evt):
self.parent = wx.GetTopLevelParent(self)
if self.parent.editor.mode == self.parent.editor.ANIM_MODE:
obj= self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
objUID = obj[OG.OBJ_UID]
propertyName = self.label.GetLabelText()
value = self.getValue()
frame = self.parent.editor.ui.animUI.curFrame
if (objUID, propertyName) in self.parent.editor.animMgr.keyFramesInfo:
for i in range(len(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])):
if self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i][AG.FRAME] == frame:
del self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i]
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)].append([frame, value, [], []])
#sort keyFrameInfo list by the order of frame number
sortKeyList = self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)]
for i in range(0, len(sortKeyList)-1):
for j in range(i+1, len(sortKeyList)):
if sortKeyList[i][AG.FRAME]>sortKeyList[j][AG.FRAME]:
temp = sortKeyList[i]
sortKeyList[i] = sortKeyList[j]
sortKeyList[j] = temp
self.parent.editor.animMgr.generateSlope(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])
else:
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)] = [[frame, value, [], []]]
exist = False
for keyFrame in self.parent.editor.animMgr.keyFrames:
if frame == keyFrame:
exist = True
break
if exist == False:
self.parent.editor.animMgr.keyFrames.append(frame)
self.parent.editor.ui.animUI.OnPropKey()
else:
self.parent.editor.ui.animUI.OnPropKey()
else:
evt.Skip()
def setValue(self, value):
self.ui.SetValue(value)
def getValue(self):
return self.ui.GetValue()
def bindFunc(self, inFunc, outFunc, valFunc = None):
self.ui.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.ui.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
if valFunc:
self.ui.Bind(self.eventType, valFunc)
class ObjectPropUIEntry(ObjectPropUI):
""" UI for string value properties """
def __init__(self, parent, label):
ObjectPropUI.__init__(self, parent, label)
self.ui = wx.TextCtrl(self.uiPane, -1)
self.eventType = wx.EVT_TEXT_ENTER
self.Layout()
def setValue(self, value):
self.ui.SetValue(str(value))
class ObjectPropUISlider(ObjectPropUI):
""" UI for float value properties """
def __init__(self, parent, label, value, minValue, maxValue):
ObjectPropUI.__init__(self, parent, label)
self.ui = WxSlider(self.uiPane, -1, value, minValue, maxValue,
pos = (0,0), size=(140, -1),
style=wx.SL_HORIZONTAL | wx.SL_LABELS)
self.ui.Enable()
self.Layout()
def bindFunc(self, inFunc, outFunc, valFunc = None):
self.ui.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.ui.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
self.ui.textValue.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.ui.textValue.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
if valFunc:
self.ui.bindFunc(valFunc)
class ObjectPropUISpinner(ObjectPropUI):
""" UI for int value properties """
def __init__(self, parent, label, value, minValue, maxValue):
ObjectPropUI.__init__(self, parent, label)
self.ui = wx.SpinCtrl(self.uiPane, -1, "", min=minValue, max=maxValue, initial=value)
self.eventType = wx.EVT_SPIN
self.Layout()
class ObjectPropUICheck(ObjectPropUI):
def __init__(self, parent, label, value):
ObjectPropUI.__init__(self, parent, label)
self.ui = wx.CheckBox(self.uiPane, -1, "", size=(50, 30))
self.setValue(value)
self.eventType = wx.EVT_CHECKBOX
self.Layout()
class ObjectPropUIRadio(ObjectPropUI):
def __init__(self, parent, label, value, valueList):
ObjectPropUI.__init__(self, parent, label)
self.ui = wx.RadioBox(self.uiPane, -1, "", choices=valueList, majorDimension=1, style=wx.RA_SPECIFY_COLS)
self.setValue(value)
self.eventType = wx.EVT_RADIOBOX
self.Layout()
def setValue(self, value):
self.ui.SetStringSelection(value)
def getValue(self):
return self.ui.GetStringSelection()
class ObjectPropUICombo(ObjectPropUI):
def __init__(self, parent, label, value, valueList, obj=None, callBack=None):
ObjectPropUI.__init__(self, parent, label)
self.ui = wx.Choice(self.uiPane, -1, choices=valueList)
if callBack is not None:
button = wx.Button(self.labelPane, -1, 'Update', size = (100, 18))
button.Bind(wx.EVT_BUTTON, lambda p0=None, p1=obj, p2=self: callBack(p0, p1, p2))
self.labelSizer.Add(button)
self.setValue(value)
self.eventType = wx.EVT_CHOICE
self.Layout()
def setValue(self, value):
self.ui.SetStringSelection(value)
def getValue(self):
return self.ui.GetStringSelection()
def setItems(self, valueList):
self.ui.SetItems(valueList)
class ObjectPropUITime(wx.Panel):
def __init__(self, parent, label, value):
wx.Panel.__init__(self, parent)
self.parent = parent
self.labelPane = wx.Panel(self)
self.label = wx.StaticText(self.labelPane, label=label)
self.labelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.labelSizer.Add(self.label)
self.labelPane.SetSizer(self.labelSizer)
self.uiPane = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.labelPane)
sizer.Add(self.uiPane, 1, wx.EXPAND, 0)
self.SetSizer(sizer)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
self.uiAmPm = wx.Choice(self.uiPane, -1, choices=['AM', 'PM'])
self.uiHour = wx.Choice(self.uiPane, -1, choices=[str(x) for x in range(1, 13)])
self.uiMin = wx.Choice(self.uiPane, -1, choices=[str(x) for x in range(0, 60, 15)])
hSizer.Add(self.uiAmPm)
hSizer.Add(self.uiHour)
hSizer.Add(self.uiMin)
self.uiPane.SetSizer(hSizer)
self.setValue(value)
self.eventType = wx.EVT_CHOICE
self.Layout()
def setValue(self, value):
hourVal = int(math.floor(value))
minVal = [0, 15, 30, 45][int((value - hourVal) * 4)]
if hourVal > 11:
ampmStr = 'PM'
hourVal = hourVal - 12
else:
ampmStr = 'AM'
if hourVal == 0:
hourVal = 12
self.uiAmPm.SetStringSelection(ampmStr)
self.uiHour.SetStringSelection(str(hourVal))
self.uiMin.SetStringSelection(str(minVal))
def getValue(self):
ampmStr = self.uiAmPm.GetStringSelection()
hourVal = int(self.uiHour.GetStringSelection())
if hourVal == 12:
hourVal = 0
if ampmStr == 'PM':
hourVal += 12
minVal = float(self.uiMin.GetStringSelection())
value = float(hourVal) + minVal / 60.0
return value
def bindFunc(self, inFunc, outFunc, valFunc = None):
self.uiAmPm.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.uiAmPm.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
self.uiHour.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.uiHour.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
self.uiMin.Bind(wx.EVT_ENTER_WINDOW, inFunc)
self.uiMin.Bind(wx.EVT_LEAVE_WINDOW, outFunc)
if valFunc:
self.uiAmPm.Bind(self.eventType, valFunc)
self.uiHour.Bind(self.eventType, valFunc)
self.uiMin.Bind(self.eventType, valFunc)
class ColorPicker(CubeColourDialog):
def __init__(self, parent, colourData=None, style=CCD_SHOW_ALPHA, alpha = 255, updateCB=None, exitCB=None):
self.updateCB=updateCB
CubeColourDialog.__init__(self, parent, colourData, style)
self.okButton.Hide()
self.cancelButton.Hide()
self._colour.alpha = alpha
self.alphaSpin.SetValue(self._colour.alpha)
self.DrawAlpha()
if exitCB:
self.Bind(wx.EVT_CLOSE, exitCB)
def SetPanelColours(self):
self.oldColourPanel.RefreshColour(self._oldColour)
self.newColourPanel.RefreshColour(self._colour)
if self.updateCB:
self.updateCB(self._colour.r, self._colour.g, self._colour.b, self._colour.alpha)
class ObjectPropertyUI(ScrolledPanel):
def __init__(self, parent, editor):
self.editor = editor
self.colorPicker = None
self.lastColorPickerPos = None
self.lastPropTab = None
ScrolledPanel.__init__(self, parent)
parentSizer = wx.BoxSizer(wx.VERTICAL)
parentSizer.Add(self, 1, wx.EXPAND, 0)
parent.SetSizer(parentSizer); parent.Layout()
self.SetDropTarget(AnimFileDrop(self.editor))
def clearPropUI(self):
sizer = self.GetSizer()
if sizer is not None:
self.lastPropTab = self.nb.GetCurrentPage().GetName()
sizer.Remove(self.propPane)
self.propPane.Destroy()
self.SetSizer(None)
self.Layout()
self.SetupScrolling(self, scroll_y = True, rate_y = 20)
def colorPickerExitCB(self, evt=None):
self.lastColorPickerPos = self.colorPicker.GetPosition()
self.colorPicker.Destroy()
self.colorPicker = None
def colorPickerUpdateCB(self, rr, gg, bb, aa):
r = rr / 255.0
g = gg / 255.0
b = bb / 255.0
a = aa / 255.0
self.propCR.setValue(r)
self.propCG.setValue(g)
self.propCB.setValue(b)
self.propCA.setValue(a)
self.editor.objectMgr.updateObjectColor(r, g, b, a)
def onColorSlider(self, evt):
r = float(self.editor.ui.objectPropertyUI.propCR.getValue())
g = float(self.editor.ui.objectPropertyUI.propCG.getValue())
b = float(self.editor.ui.objectPropertyUI.propCB.getValue())
a = float(self.editor.ui.objectPropertyUI.propCA.getValue())
if self.colorPicker:
evtObj = evt.GetEventObject()
if evtObj == self.propCR.ui or\
evtObj == self.propCR.ui.textValue:
self.colorPicker.redSpin.SetValue(r * 255)
self.colorPicker.AssignColourValue('r', r * 255, 255, 0)
elif evtObj == self.propCG.ui or\
evtObj == self.propCG.ui.textValue:
self.colorPicker.greenSpin.SetValue(g * 255)
self.colorPicker.AssignColourValue('g', g * 255, 255, 0)
elif evtObj == self.propCB.ui or\
evtObj == self.propCB.ui.textValue:
self.colorPicker.blueSpin.SetValue(b * 255)
self.colorPicker.AssignColourValue('b', b * 255, 255, 0)
else:
self.colorPicker._colour.alpha = a * 255
self.colorPicker.alphaSpin.SetValue(self.colorPicker._colour.alpha)
self.colorPicker.DrawAlpha()
self.editor.objectMgr.updateObjectColor(r, g, b, a)
def openColorPicker(self, evt, colourData, alpha):
if self.colorPicker:
self.lastColorPickerPos = self.colorPicker.GetPosition()
self.colorPicker.Destroy()
self.colorPicker = ColorPicker(self, colourData, alpha=alpha, updateCB=self.colorPickerUpdateCB, exitCB=self.colorPickerExitCB)
self.colorPicker.GetColourData().SetChooseFull(True)
self.colorPicker.Show()
if self.lastColorPickerPos:
self.colorPicker.SetPosition(self.lastColorPickerPos)
def updateProps(self, obj, movable=True):
self.clearPropUI()
self.propPane = wx.Panel(self)
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(self.propPane, 1, wx.EXPAND, 0)
self.SetSizer(mainSizer)
self.nb = wx.Notebook(self.propPane, style=wx.NB_BOTTOM)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.nb, 1, wx.EXPAND)
self.propPane.SetSizer(sizer)
self.transformPane = wx.Panel(self.nb, -1, name='Transform')
self.nb.AddPage(self.transformPane, 'Transform')
self.propX = ObjectPropUIEntry(self.transformPane, 'X')
self.propY = ObjectPropUIEntry(self.transformPane, 'Y')
self.propZ = ObjectPropUIEntry(self.transformPane, 'Z')
self.propH = ObjectPropUISlider(self.transformPane, 'H', 0, 0, 360)
self.propP = ObjectPropUISlider(self.transformPane, 'P', 0, 0, 360)
self.propR = ObjectPropUISlider(self.transformPane, 'R', 0, 0, 360)
self.propSX = ObjectPropUIEntry(self.transformPane, 'SX')
self.propSY = ObjectPropUIEntry(self.transformPane, 'SY')
self.propSZ = ObjectPropUIEntry(self.transformPane, 'SZ')
transformProps = [self.propX, self.propY, self.propZ, self.propH, self.propP, self.propR,
self.propSX, self.propSY, self.propSZ]
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.AddMany(transformProps)
self.transformPane.SetSizer(sizer)
for transformProp in transformProps:
transformProp.bindFunc(self.editor.objectMgr.onEnterObjectPropUI,
self.editor.objectMgr.onLeaveObjectPropUI,
self.editor.objectMgr.updateObjectTransform)
if not movable:
for transformProp in transformProps:
transformProp.ui.Disable()
self.lookPane = wx.Panel(self.nb, -1, name='Look')
self.nb.AddPage(self.lookPane, 'Look')
objNP = obj[OG.OBJ_NP]
objRGBA = obj[OG.OBJ_RGBA]
self.propCR = ObjectPropUISlider(self.lookPane, 'CR', objRGBA[0], 0, 1)
self.propCG = ObjectPropUISlider(self.lookPane, 'CG', objRGBA[1], 0, 1)
self.propCB = ObjectPropUISlider(self.lookPane, 'CB', objRGBA[2], 0, 1)
self.propCA = ObjectPropUISlider(self.lookPane, 'CA', objRGBA[3], 0, 1)
colorProps = [self.propCR, self.propCG, self.propCB, self.propCA]
for colorProp in colorProps:
colorProp.ui.bindFunc(self.onColorSlider)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.AddMany(colorProps)
button = wx.Button(self.lookPane, -1, 'Color Picker', (0,0), (140, 20))
_colourData = wx.ColourData()
_colourData.SetColour(wx.Colour(objRGBA[0] * 255, objRGBA[1] * 255, objRGBA[2] * 255))
button.Bind(wx.EVT_BUTTON, lambda p0=None, p1=_colourData, p2=objRGBA[3] * 255: self.openColorPicker(p0, p1, p2))
sizer.Add(button)
if self.colorPicker:
self.openColorPicker(None, _colourData, objRGBA[3] * 255)
objDef = obj[OG.OBJ_DEF]
if objDef.updateModelFunction is not None or (objDef.model is not None and len(objDef.models) > 0):
defaultModel = obj[OG.OBJ_MODEL]
if defaultModel is None:
defaultModel = ''
if len(objDef.models) == 0:
modelList = ''
else:
modelList = objDef.models
propUI = ObjectPropUICombo(self.lookPane, 'model', defaultModel, modelList, obj, callBack=objDef.updateModelFunction)
sizer.Add(propUI)
propUI.bindFunc(self.editor.objectMgr.onEnterObjectPropUI,
self.editor.objectMgr.onLeaveObjectPropUI,
lambda p0=None, p1=obj: self.editor.objectMgr.updateObjectModelFromUI(p0, p1))
animList = objDef.animDict.get(obj[OG.OBJ_MODEL])
if len(objDef.anims) > 0 or animList:
if animList is None:
animList = objDef.anims
propUI = ObjectPropUICombo(self.lookPane, 'anim', obj[OG.OBJ_ANIM], animList)
sizer.Add(propUI)
propUI.bindFunc(self.editor.objectMgr.onEnterObjectPropUI,
self.editor.objectMgr.onLeaveObjectPropUI,
lambda p0=None, p1=obj: self.editor.objectMgr.updateObjectAnimFromUI(p0, p1))
self.lookPane.SetSizer(sizer)
self.propsPane = wx.Panel(self.nb, -1, name='Properties')
self.nb.AddPage(self.propsPane, 'Properties')
sizer = wx.BoxSizer(wx.VERTICAL)
propNames = objDef.orderedProperties[:]
for key in objDef.properties.keys():
if key not in propNames:
propNames.append(key)
for key in propNames:
# handling properties mask
propMask = BitMask32()
for modeKey in objDef.propertiesMask.keys():
if key in objDef.propertiesMask[modeKey]:
propMask |= modeKey
if not propMask.isZero():
if (self.editor.mode & propMask).isZero():
continue
propDef = objDef.properties[key]
propType = propDef[OG.PROP_TYPE]
propDataType = propDef[OG.PROP_DATATYPE]
value = obj[OG.OBJ_PROP].get(key)
if propType == OG.PROP_UI_ENTRY:
propUI = ObjectPropUIEntry(self.propsPane, key)
propUI.setValue(value)
sizer.Add(propUI)
elif propType == OG.PROP_UI_SLIDE:
if len(propDef) <= OG.PROP_RANGE:
continue
propRange = propDef[OG.PROP_RANGE]
if value is None:
continue
if propDataType != OG.PROP_FLOAT:
value = float(value)
propUI = ObjectPropUISlider(self.propsPane, key, value, propRange[OG.RANGE_MIN], propRange[OG.RANGE_MAX])
sizer.Add(propUI)
elif propType == OG.PROP_UI_SPIN:
if len(propDef) <= OG.PROP_RANGE:
continue
propRange = propDef[OG.PROP_RANGE]
if value is None:
continue
propUI = ObjectPropUISpinner(self.propsPane, key, value, propRange[OG.RANGE_MIN], propRange[OG.RANGE_MAX])
sizer.Add(propUI)
elif propType == OG.PROP_UI_CHECK:
if value is None:
continue
propUI = ObjectPropUICheck(self.propsPane, key, value)
sizer.Add(propUI)
elif propType == OG.PROP_UI_RADIO:
if len(propDef) <= OG.PROP_RANGE:
continue
propRange = propDef[OG.PROP_RANGE]
if value is None:
continue
if propDataType != OG.PROP_STR:
for i in range(len(propRange)):
propRange[i] = str(propRange[i])
value = str(value)
propUI = ObjectPropUIRadio(self.propsPane, key, value, propRange)
sizer.Add(propUI)
elif propType == OG.PROP_UI_COMBO:
if len(propDef) <= OG.PROP_RANGE:
continue
propRange = propDef[OG.PROP_RANGE]
if value is None:
continue
if propDataType != OG.PROP_STR:
for i in range(len(propRange)):
propRange[i] = str(propRange[i])
value = str(value)
propUI = ObjectPropUICombo(self.propsPane, key, value, propRange)
sizer.Add(propUI)
elif propType == OG.PROP_UI_COMBO_DYNAMIC:
if len(propDef) <= OG.PROP_DYNAMIC_KEY:
continue
propDynamicKey = propDef[OG.PROP_DYNAMIC_KEY]
if propDynamicKey == OG.PROP_MODEL:
dynamicRangeKey = obj[OG.OBJ_MODEL]
else:
dynamicRangeKey = obj[OG.OBJ_PROP].get(propDynamicKey)
if dynamicRangeKey is None:
self.editor.objectMgr.updateObjectPropValue(obj, key, propDef[OG.PROP_DEFAULT], fUndo=False)
continue
propRange = propDef[OG.PROP_RANGE].get(dynamicRangeKey)
if propRange is None:
self.editor.objectMgr.updateObjectPropValue(obj, key, propDef[OG.PROP_DEFAULT], fUndo=False)
continue
if value is None:
continue
if propDataType != OG.PROP_STR:
for i in range(len(propRange)):
propRange[i] = str(propRange[i])
value = str(value)
if value not in propRange:
value = propRange[0]
self.editor.objectMgr.updateObjectPropValue(obj, key, value, fUndo=False)
propUI = ObjectPropUICombo(self.propsPane, key, value, propRange)
sizer.Add(propUI)
elif propType == OG.PROP_UI_TIME:
if value is None:
continue
propUI = ObjectPropUITime(self.propsPane, key, value)
sizer.Add(propUI)
else:
# unspported property type
continue
propUI.bindFunc(self.editor.objectMgr.onEnterObjectPropUI,
self.editor.objectMgr.onLeaveObjectPropUI,
lambda p0=None, p1=obj, p2=key: self.editor.objectMgr.updateObjectProperty(p0, p1, p2))
self.propsPane.SetSizer(sizer);
self.Layout()
self.SetupScrolling(self, scroll_y = True, rate_y = 20)
if self.lastPropTab == 'Transform':
self.nb.SetSelection(0)
elif self.lastPropTab == 'Look':
self.nb.SetSelection(1)
elif self.lastPropTab == 'Properties':
self.nb.SetSelection(2)