From a3b8ed2062162b0b088683442c6b4dc6d6fc2c51 Mon Sep 17 00:00:00 2001 From: Mark Mine Date: Wed, 11 Jul 2001 21:50:23 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/gui/DirectButton.py | 18 ++-- direct/src/gui/DirectFrame.py | 156 +++++++++++++++++++++++++++ direct/src/gui/DirectGui.py | 1 + direct/src/gui/DirectGuiBase.py | 150 +++++++++++++++++++++----- direct/src/gui/DirectGuiGlobals.py | 45 ++++---- direct/src/gui/DirectGuiTest.py | 4 +- direct/src/gui/DirectLabel.py | 162 ++++------------------------- direct/src/gui/OnscreenImage.py | 2 +- 8 files changed, 333 insertions(+), 205 deletions(-) create mode 100644 direct/src/gui/DirectFrame.py diff --git a/direct/src/gui/DirectButton.py b/direct/src/gui/DirectButton.py index c975c73755..174c108b71 100644 --- a/direct/src/gui/DirectButton.py +++ b/direct/src/gui/DirectButton.py @@ -1,20 +1,21 @@ -from DirectLabel import * +from DirectFrame import * -class DirectButton(DirectLabel): +class DirectButton(DirectFrame): """ DirectButton(parent) - Create a DirectGuiWidget which responds to mouse clicks and execute a callback function if defined """ def __init__(self, parent = guiTop, **kw): - # Inherits from DirectLabel - # A Direct Label can have: + # Inherits from DirectFrame + # A Direct Frame can have: # - A background texture (pass in path to image, or Texture Card) # - A midground geometry item (pass in geometry) # - A foreground text Node (pass in text string or Onscreen Text) # For a direct button: - # Each of these has 4 states (ready, press, rollover, disabled) - # The same object can be used for all four states or each + # Each button has 4 states (ready, press, rollover, disabled) + # The same image/geom/text can be used for all four states or each # state can have a different text/geom/image + # State transitions happen automatically based upon mouse interaction # Responds to click event and calls command if None optiondefs = ( # Define type of DirectGuiWidget @@ -34,11 +35,10 @@ class DirectButton(DirectLabel): ('pressEffect', 1, INITOPT), ) # Merge keyword options with default options - self.defineoptions(kw, optiondefs, - dynamicGroups = ('text', 'geom', 'image')) + self.defineoptions(kw, optiondefs) # Initialize superclasses - DirectLabel.__init__(self, parent) + DirectFrame.__init__(self, parent) # If specifed, add scaling to the pressed state to make it look # like the button is moving when you press it diff --git a/direct/src/gui/DirectFrame.py b/direct/src/gui/DirectFrame.py new file mode 100644 index 0000000000..50d0b48dbb --- /dev/null +++ b/direct/src/gui/DirectFrame.py @@ -0,0 +1,156 @@ +from DirectGuiBase import * + +class DirectFrame(DirectGuiWidget): + def __init__(self, parent = guiTop, **kw): + # Inherits from DirectGuiWidget + # A Direct Frame can have: + # - A background texture (pass in path to image, or Texture Card) + # - A midground geometry item (pass in geometry) + # - A foreground text Node (pass in text string or Onscreen Text) + # Each of these has 1 or more states + # The same object can be used for all states or each + # state can have a different text/geom/image (for radio button + # and check button indicators, for example + optiondefs = ( + # Define type of DirectGuiWidget + ('pgFunc', PGItem, None), + ('numStates', 1, None), + # Frame can have: + # A background texture + ('image', None, self.setImage), + # A midground geometry item + ('geom', None, self.setGeom), + # A foreground text node + ('text', None, self.setText), + ) + # Merge keyword options with default options + self.defineoptions(kw, optiondefs, + dynamicGroups = ('text', 'geom', 'image')) + + # Initialize superclasses + DirectGuiWidget.__init__(self, parent) + + # Call option initialization functions + self.initialiseoptions(DirectFrame) + + def setText(self): + # Determine if user passed in single string or a sequence + if self['text'] == None: + textList = (None,) * self['numStates'] + elif type(self['text']) == types.StringType: + # If just passing in a single string, make a tuple out of it + textList = (self['text'],) * self['numStates'] + else: + # Otherwise, hope that the user has passed in a tuple/list + textList = self['text'] + # Create/destroy components + for i in range(self['numStates']): + component = 'text' + `i` + # If fewer items specified than numStates, + # just repeat last item + try: + text = textList[i] + except IndexError: + text = textList[-1] + + if self.hascomponent(component): + if text == None: + # Destroy component + self.destroycomponent(component) + else: + self[component + '_text'] = text + else: + if text == None: + return + else: + self.createcomponent( + component, (), 'text', + OnscreenText.OnscreenText, + (), parent = self.stateNodePath[i], + text = text, scale = 1, + sort = TEXT_SORT_INDEX, + mayChange = 1) + + def setGeom(self): + # Determine argument type + if self['geom'] == None: + # Passed in None + geomList = (None,) * self['numStates'] + elif isinstance(self['geom'], NodePath): + # Passed in a single node path, make a tuple out of it + geomList = (self['geom'],) * self['numStates'] + else: + # Otherwise, hope that the user has passed in a tuple/list + geomList = self['geom'] + # Create/destroy components + for i in range(self['numStates']): + component = 'geom' + `i` + # If fewer items specified than numStates, + # just repeat last item + try: + geom = geomList[i] + except IndexError: + geom = geomList[-1] + + if self.hascomponent(component): + if geom == None: + # Destroy component + self.destroycomponent(component) + else: + self[component + '_geom'] = geom + else: + if geom == None: + return + else: + self.createcomponent( + component, (), 'geom', + OnscreenGeom.OnscreenGeom, + (), parent = self.stateNodePath[i], + geom = geom, scale = 1, + sort = GEOM_SORT_INDEX) + + def setImage(self): + # Determine argument type + arg = self['image'] + if arg == None: + # Passed in None + imageList = (None,) * self['numStates'] + elif type(arg) == types.StringType: + # Passed in a single node path, make a tuple out of it + imageList = (arg,) * self['numStates'] + else: + # Otherwise, hope that the user has passed in a tuple/list + if ((len(arg) == 2) and + (type(arg[0]) == types.StringType) and + (type(arg[1]) == types.StringType)): + # Its a model/node pair of strings + image = (arg,) * self['numStates'] + else: + # Assume its a list of node paths + imageList = arg + # Create/destroy components + for i in range(self['numStates']): + component = 'image' + `i` + # If fewer items specified than numStates, + # just repeat last item + try: + image = imageList[i] + except IndexError: + image = imageList[-1] + + if self.hascomponent(component): + if image == None: + # Destroy component + self.destroycomponent(component) + else: + self[component + '_image'] = image + else: + if image == None: + return + else: + self.createcomponent( + component, (), 'image', + OnscreenImage.OnscreenImage, + (), parent = self.stateNodePath[i], + image = image, scale = 1, + sort = IMAGE_SORT_INDEX) diff --git a/direct/src/gui/DirectGui.py b/direct/src/gui/DirectGui.py index 57adc2b5f6..f77724237a 100644 --- a/direct/src/gui/DirectGui.py +++ b/direct/src/gui/DirectGui.py @@ -6,6 +6,7 @@ __builtin__.guiTop = aspect2d.attachNewNode(PGTop('DirectGuiTop')) guiTop.node().setMouseWatcher(base.mouseWatcher.node()) # Direct Gui Classes +from DirectFrame import * from DirectButton import * from DirectLabel import * diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 5cccddba75..217abfc51c 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -1,4 +1,6 @@ from DirectGuiGlobals import * +from DirectGeometry import ROUND_TO + """ Base class for all Direct Gui items. Handles composite widgets and command line argument parsing. @@ -89,7 +91,7 @@ class DirectGuiBase(PandaObject): # Default id of all gui object, subclasses should override this self.guiId = 'guiObject' # List of all active hooks - self.hookDict = {} + self._hookDict = {} # To avoid doing things redundantly during initialisation self.fInit = 1 # Mapping from each megawidget option to a list of information @@ -141,6 +143,9 @@ class DirectGuiBase(PandaObject): # no components with this group have been created. # self._dynamicGroups = () + def __del__(self): + print 'Bye' + def defineoptions(self, keywords, optionDefs, dynamicGroups = ()): """ defineoptions(keywords, optionDefs, dynamicGroups = {}) """ # Create options, providing the default value and the method @@ -592,8 +597,11 @@ class DirectGuiBase(PandaObject): def destroy(self): # Clean out any hooks - for event in self.hookDict.keys(): + for event in self._hookDict.keys(): self.ignore(event) + del(self._optionInfo) + del(self._hookDict) + del(self.__componentInfo) def bind(self, event, command): """ @@ -605,7 +613,7 @@ class DirectGuiBase(PandaObject): gEvent = event + self.guiId self.accept(gEvent, command) # Keep track of all events you're accepting - self.hookDict[gEvent] = command + self._hookDict[gEvent] = command def unbind(self, event): """ @@ -614,11 +622,20 @@ class DirectGuiBase(PandaObject): # Need to tack on gui item specific id gEvent = event + self.guiId self.ignore(gEvent) - if self.hookDict.has_key(gEvent): - del(self.hookDict[gEvent]) + if self._hookDict.has_key(gEvent): + del(self._hookDict[gEvent]) +def toggleGuiGridSnap(): + DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid + +def setGuiGridSpacing(spacing): + DirectGuiWidget.gridSpacing = spacing class DirectGuiWidget(DirectGuiBase, NodePath): + # Toggle if you wish widget's to snap to grid when draggin + snapToGrid = 0 + gridSpacing = 0.05 + def __init__(self, parent = guiTop, **kw): # Direct gui widgets are node paths # Direct gui widgets have: @@ -633,20 +650,20 @@ class DirectGuiWidget(DirectGuiBase, NodePath): # - Can position/scale them optiondefs = ( # Widget's constructor - ('pgFunc', PGItem, None), - ('numStates', 1, None), - ('invertedFrames', (), None), + ('pgFunc', PGItem, None), + ('numStates', 1, None), + ('invertedFrames', (), None), # Widget's initial state - ('state', NORMAL, self.setState), + ('state', NORMAL, self.setState), # Widget's frame characteristics - ('relief', FLAT, self.setRelief), - ('borderWidth', (.1,.1), self.setBorderWidth), - ('frameSize', None, self.setFrameSize), - ('frameColor', (1,1,1,1), self.setFrameColor), - ('pad', (.25,.15), self.resetFrameSize), + ('relief', FLAT, self.setRelief), + ('borderWidth', (.1,.1), self.setBorderWidth), + ('frameSize', None, self.setFrameSize), + ('frameColor', (.8,.8,.8,1), self.setFrameColor), + ('pad', (.25,.15), self.resetFrameSize), # Initial pos/scale of the widget - ('pos', None, INITOPT), - ('scale', None, INITOPT), + ('pos', None, INITOPT), + ('scale', None, INITOPT), ) # Merge keyword options with default options self.defineoptions(kw, optiondefs) @@ -677,8 +694,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): else: apply(self.setScale, self['scale']) # Initialize names - self.guiItem.setName(self.guiId) - self.setName(self.guiId + 'NodePath') + self.setName(self.guiId) # Create self.stateNodePath = [] for i in range(self['numStates']): @@ -690,6 +706,14 @@ class DirectGuiWidget(DirectGuiBase, NodePath): # For holding bounds info self.ll = Point3(0) self.ur = Point3(0) + + # Is drag and drop enabled? + if base.config.GetBool('direct-gui-edit', 0): + self.enableEdit() + + # Bind destroy hook + self.bind(DESTROY, self.destroy) + # Call option initialization functions self.initialiseoptions(DirectGuiWidget) @@ -699,6 +723,63 @@ class DirectGuiWidget(DirectGuiBase, NodePath): if not self['frameSize']: self.setFrameSize() + def enableEdit(self): + self.bind(B2PRESS, self.editStart) + self.bind(B2RELEASE, self.editStop) + self.bind(PRINT, self.printConfig) + mb = ModifierButtons(base.mouseWatcherNode.getModifierButtons()) + mb.addButton(KeyboardButton.alt()) + base.mouseWatcherNode.setModifierButtons(mb) + + def disableEdit(self): + self.unbind(B2PRESS) + self.unbind(B2RELEASE) + self.unbind(PRINT) + mb = ModifierButtons(base.mouseWatcherNode.getModifierButtons()) + mb.removeButton(KeyboardButton.alt()) + base.mouseWatcherNode.setModifierButtons(mb) + + def editStart(self, event): + taskMgr.removeTasksNamed('guiEditTask') + vWidget2render2d = self.getPos(render2d) + vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1]) + editVec = Vec3(vWidget2render2d - vMouse2render2d) + if base.mouseWatcherNode.getModifierButtons().isDown( + KeyboardButton.alt()): + t = taskMgr.spawnMethodNamed(self.guiScaleTask, 'guiEditTask') + t.refPos = vWidget2render2d + t.editVecLen = editVec.length() + t.initScale = self.getScale() + else: + t = taskMgr.spawnMethodNamed(self.guiDragTask, 'guiEditTask') + t.editVec = editVec + + def guiScaleTask(self, state): + mwn = base.mouseWatcherNode + if mwn.hasMouse(): + vMouse2render2d = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1]) + newEditVecLen = Vec3(state.refPos - vMouse2render2d).length() + self.setScale(state.initScale * (newEditVecLen/state.editVecLen)) + return Task.cont + + def guiDragTask(self, state): + mwn = base.mouseWatcherNode + if mwn.hasMouse(): + vMouse2render2d = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1]) + newPos = vMouse2render2d + state.editVec + self.setPos(render2d, newPos) + if DirectGuiWidget.snapToGrid: + newPos = self.getPos() + newPos.set( + ROUND_TO(newPos[0], DirectGuiWidget.gridSpacing), + ROUND_TO(newPos[1], DirectGuiWidget.gridSpacing), + ROUND_TO(newPos[2], DirectGuiWidget.gridSpacing)) + self.setPos(newPos) + return Task.cont + + def editStop(self, event): + taskMgr.removeTasksNamed('guiEditTask') + def setState(self): if type(self['state']) == type(0): self.guiItem.setActive(self['state']) @@ -744,24 +825,29 @@ class DirectGuiWidget(DirectGuiBase, NodePath): def setRelief(self, fSetStyle = 1): relief = self['relief'] + # Convert None, and string arguments if relief == None: - for i in range(self['numStates']): - self.frameStyle[i].setType(PGFrameStyle.TNone) - elif (relief == FLAT) or (relief == 'flat'): - for i in range(self['numStates']): - self.frameStyle[i].setType(FLAT) - elif (relief == RAISED) or (relief == 'raised'): + relief = PGFrameStyle.TNone + elif type(relief) == types.StringType: + # Convert string to frame style int + relief = FrameStyleDict[relief] + # Set style + if relief == RAISED: for i in range(self['numStates']): if i in self['invertedFrames']: self.frameStyle[1].setType(SUNKEN) else: self.frameStyle[i].setType(RAISED) - elif (relief == SUNKEN) or (relief == 'sunken'): + elif relief == SUNKEN: for i in range(self['numStates']): if i in self['invertedFrames']: self.frameStyle[1].setType(RAISED) else: self.frameStyle[i].setType(SUNKEN) + else: + for i in range(self['numStates']): + self.frameStyle[i].setType(relief) + # Apply styles self.updateFrameStyle() def setFrameColor(self): @@ -777,7 +863,21 @@ class DirectGuiWidget(DirectGuiBase, NodePath): self.updateFrameStyle() def destroy(self): + # Destroy children + for child in self.getChildrenAsList(): + messenger.send(DESTROY + child.getName()) + # Call superclass destruction method (clears out hooks) DirectGuiBase.destroy(self) # Get rid of node path self.removeNode() + def printConfig(self, indent = 0): + space = ' ' * indent + print space + self.guiId + print space + 'Pos: ' + `self.getPos()` + print space + 'Scale: ' + `self.getScale()` + # Print out children info + for child in self.getChildrenAsList(): + messenger.send(PRINT + child.getName(), [indent + 2]) + + diff --git a/direct/src/gui/DirectGuiGlobals.py b/direct/src/gui/DirectGuiGlobals.py index a569ce14ae..c9c73b037c 100644 --- a/direct/src/gui/DirectGuiGlobals.py +++ b/direct/src/gui/DirectGuiGlobals.py @@ -33,36 +33,27 @@ DISABLED = 'disabled' FLAT = PGFrameStyle.TFlat RAISED = PGFrameStyle.TBevelOut SUNKEN = PGFrameStyle.TBevelIn +GROOVE = PGFrameStyle.TGroove +RIDGE = PGFrameStyle.TRidge -# Use to extract common prefix of mouse click, press, and release events -def getGenericMouseEvent(event, mouse): - if mouse == 1: - mb = MouseButton.one() - elif mouse == 2: - mb = MouseButton.two() - elif mouse == 3: - mb = MouseButton.three() - if event == 'click': - eventFunc = PGButton().getClickEvent - elif event == 'press': - eventFunc = PGButton().getPressEvent - elif event == 'release': - eventFunc = PGButton().getReleaseEvent - eventString = eventFunc(mb) - return eventString[:eventString.rfind('-') + 1] +FrameStyleDict = {'flat' : FLAT, 'raised' : RAISED, 'sunken': SUNKEN, + 'groove' : GROOVE, 'ridge' : RIDGE + } # User can bind commands to these gui events -ENTER = 'enter-' -EXIT = 'exit-' -B1CLICK = getGenericMouseEvent('click', 1) -B2CLICK = getGenericMouseEvent('click', 2) -B3CLICK = getGenericMouseEvent('click', 3) -B1PRESS = getGenericMouseEvent('press', 1) -B2PRESS = getGenericMouseEvent('press', 2) -B3PRESS = getGenericMouseEvent('press', 3) -B1RELEASE = getGenericMouseEvent('release', 1) -B2RELEASE = getGenericMouseEvent('release', 2) -B3RELEASE = getGenericMouseEvent('release', 3) +DESTROY = 'destroy-' +PRINT = 'print-' +ENTER = PGButton.getEnterPrefix() +EXIT = PGButton.getExitPrefix() +B1CLICK = PGButton.getClickPrefix() + MouseButton.one().getName() + '-' +B2CLICK = PGButton.getClickPrefix() + MouseButton.two().getName() + '-' +B3CLICK = PGButton.getClickPrefix() + MouseButton.three().getName() + '-' +B1PRESS = PGButton.getPressPrefix() + MouseButton.one().getName() + '-' +B2PRESS = PGButton.getPressPrefix() + MouseButton.two().getName() + '-' +B3PRESS = PGButton.getPressPrefix() + MouseButton.three().getName() + '-' +B1RELEASE = PGButton.getReleasePrefix() + MouseButton.one().getName() + '-' +B2RELEASE = PGButton.getReleasePrefix() + MouseButton.two().getName() + '-' +B3RELEASE = PGButton.getReleasePrefix() + MouseButton.three().getName() + '-' # For setting the sorting order of a widget's visible components IMAGE_SORT_INDEX = 10 diff --git a/direct/src/gui/DirectGuiTest.py b/direct/src/gui/DirectGuiTest.py index 3664e71039..2d6c13df0e 100644 --- a/direct/src/gui/DirectGuiTest.py +++ b/direct/src/gui/DirectGuiTest.py @@ -42,7 +42,7 @@ def ouch(db): db.lerpPos(Point3(newX, 0, newZ), 1.0, task = 'runAway', blendType = 'easeOut') -dl = DirectLabel(image = 'phase_4/maps/middayskyB.jpg') +dl = DirectFrame(image = 'phase_4/maps/middayskyB.jpg') dl.setScale(.5) # Create a button with a background image, smiley as a geometry element, @@ -69,7 +69,7 @@ for i in range(10): db.bind(EXIT, lambda x, db = db: expand(db)) db.bind(B1PRESS, lambda x, db = db: ouch(db)) # Pop up placer when button 2 is pressed - db.bind(B2PRESS, lambda x, db = db: db.place()) + db.bind(B3PRESS, lambda x, db = db: db.place()) # To get rid of button and clear out hooks call: # db.destroy() diff --git a/direct/src/gui/DirectLabel.py b/direct/src/gui/DirectLabel.py index 543908269e..4763dc5b2a 100644 --- a/direct/src/gui/DirectLabel.py +++ b/direct/src/gui/DirectLabel.py @@ -1,156 +1,36 @@ -from DirectGuiBase import * +from DirectFrame import * -class DirectLabel(DirectGuiWidget): +class DirectLabel(DirectFrame): + """ + DirectLabel(parent) - Create a DirectGuiWidget which has multiple + states. User explicitly chooses a state to display + """ def __init__(self, parent = guiTop, **kw): - # Inherits from DirectGuiWidget - # A Direct Label can have: + # Inherits from DirectFrame + # A Direct Frame can have: # - A background texture (pass in path to image, or Texture Card) # - A midground geometry item (pass in geometry) # - A foreground text Node (pass in text string or Onscreen Text) - # Each of these has 1 or more states - # The same object can be used for all states or each - # state can have a different text/geom/image (for radio button - # and check button indicators, for example + # For a direct label: + # Each label has 1 or more states + # The same image/geom/text can be used for all states or each + # state can have a different text/geom/image + # State transitions happen under user control optiondefs = ( # Define type of DirectGuiWidget - ('pgFunc', PGItem, None), - ('numStates', 1, None), - # Label can have: - # A background texture - ('image', None, self.setImage), - # A midground geometry item - ('geom', None, self.setGeom), - # A foreground text node - ('text', None, self.setText), + ('pgFunc', PGItem, None), + ('numStates', 1, None), + ('activeState', 0, self.setActiveState), ) # Merge keyword options with default options - self.defineoptions(kw, optiondefs, - dynamicGroups = ('text', 'geom', 'image')) + self.defineoptions(kw, optiondefs) # Initialize superclasses - DirectGuiWidget.__init__(self, parent) + DirectFrame.__init__(self, parent) # Call option initialization functions self.initialiseoptions(DirectLabel) - def setText(self): - # Determine if user passed in single string or a sequence - if self['text'] == None: - textList = (None,) * self['numStates'] - elif type(self['text']) == types.StringType: - # If just passing in a single string, make a tuple out of it - textList = (self['text'],) * self['numStates'] - else: - # Otherwise, hope that the user has passed in a tuple/list - textList = self['text'] - # Create/destroy components - for i in range(self['numStates']): - component = 'text' + `i` - # If fewer items specified than numStates, - # just repeat last item - try: - text = textList[i] - except IndexError: - text = textList[-1] - - if self.hascomponent(component): - if text == None: - # Destroy component - self.destroycomponent(component) - else: - self[component + '_text'] = text - else: - if text == None: - return - else: - self.createcomponent( - component, (), 'text', - OnscreenText.OnscreenText, - (), parent = self.stateNodePath[i], - text = text, scale = 1, - sort = TEXT_SORT_INDEX, - mayChange = 1) - - def setGeom(self): - # Determine argument type - if self['geom'] == None: - # Passed in None - geomList = (None,) * self['numStates'] - elif isinstance(self['geom'], NodePath): - # Passed in a single node path, make a tuple out of it - geomList = (self['geom'],) * self['numStates'] - else: - # Otherwise, hope that the user has passed in a tuple/list - geomList = self['geom'] - # Create/destroy components - for i in range(self['numStates']): - component = 'geom' + `i` - # If fewer items specified than numStates, - # just repeat last item - try: - geom = geomList[i] - except IndexError: - geom = geomList[-1] - - if self.hascomponent(component): - if geom == None: - # Destroy component - self.destroycomponent(component) - else: - self[component + '_geom'] = geom - else: - if geom == None: - return - else: - self.createcomponent( - component, (), 'geom', - OnscreenGeom.OnscreenGeom, - (), parent = self.stateNodePath[i], - geom = geom, scale = 1, - sort = GEOM_SORT_INDEX) - - def setImage(self): - # Determine argument type - arg = self['image'] - if arg == None: - # Passed in None - imageList = (None,) * self['numStates'] - elif type(arg) == types.StringType: - # Passed in a single node path, make a tuple out of it - imageList = (arg,) * self['numStates'] - else: - # Otherwise, hope that the user has passed in a tuple/list - if ((len(arg) == 2) and - (type(arg[0]) == types.StringType) and - (type(arg[1]) == types.StringType)): - # Its a model/node pair of strings - image = (arg,) * self['numStates'] - else: - # Assume its a list of node paths - imageList = arg - # Create/destroy components - for i in range(self['numStates']): - component = 'image' + `i` - # If fewer items specified than numStates, - # just repeat last item - try: - image = imageList[i] - except IndexError: - image = imageList[-1] - - if self.hascomponent(component): - if image == None: - # Destroy component - self.destroycomponent(component) - else: - self[component + '_image'] = image - else: - if image == None: - return - else: - self.createcomponent( - component, (), 'image', - OnscreenImage.OnscreenImage, - (), parent = self.stateNodePath[i], - image = image, scale = 1, - sort = IMAGE_SORT_INDEX) + def setActiveState(self): + """ setActiveState - change label to specifed state """ + self.guiItem.setState(self['activeState']) diff --git a/direct/src/gui/OnscreenImage.py b/direct/src/gui/OnscreenImage.py index 0bf35da6ad..a00bf11ab2 100644 --- a/direct/src/gui/OnscreenImage.py +++ b/direct/src/gui/OnscreenImage.py @@ -57,7 +57,7 @@ class OnscreenImage(PandaObject, NodePath): node = model.find(image[1]) if node: self.assign(node) - self.reparentTo(parent, sort) + self.copyTo(parent, sort) else: print 'OnscreenImage: node %s not found' % image[1] return