def __init__(self, holder=None): SCObject.__init__(self) self.SerialNum = SCMenu.SerialNum SCMenu.SerialNum += 1 node = hidden.attachNewNode('SCMenu%s' % self.SerialNum) NodePath.__init__(self, node) # if 'None', this menu is a top-level menu (it's not under anything) self.setHolder(holder) self.FinalizeTaskName = 'SCMenu%s_Finalize' % self.SerialNum self.ActiveMemberSwitchTaskName = ('SCMenu%s_SwitchActiveMember' % self.SerialNum) self.bg = loader.loadModel(self.BackgroundModelName) def findNodes(names, model=self.bg): results = [] for name in names: # if name is a tuple we need to look for the first match for nm in makeTuple(name): node = model.find('**/%s' % nm) if not node.isEmpty(): results.append(node) break return results # Maya doesn't allow nodes to be named 'top' so it's named # 'top1' in the Pirates model (self.bgTop, self.bgBottom, self.bgLeft, self.bgRight, self.bgMiddle, self.bgTopLeft, self.bgBottomLeft, self.bgTopRight, self.bgBottomRight) = findNodes([('top', 'top1'), 'bottom', 'left', 'right', 'middle', 'topLeft', 'bottomLeft', 'topRight', 'bottomRight']) # give the bg frame a render order that puts it behind the rest # of our children self.bg.reparentTo(self, -1) # the member elements in this menu # note that our member list should be manipulated by applying # list operations to 'self' self.__members = [] # Each menu can have a maximum of one 'active' member ('active' # being interpreted based on the member's element type; menu holders # show their menu when active, etc.) self.activeMember = None self.activeCandidate = None self.fadeIval = None # initialized; only used for horizonal centering self.width = 1 # to prevent recursive invalidates from members self.inFinalize = 0
def __init__(self, holder=None): SCObject.__init__(self) self.SerialNum = SCMenu.SerialNum SCMenu.SerialNum += 1 node = hidden.attachNewNode('SCMenu%s' % self.SerialNum) NodePath.__init__(self, node) self.setHolder(holder) self.FinalizeTaskName = 'SCMenu%s_Finalize' % self.SerialNum self.ActiveMemberSwitchTaskName = 'SCMenu%s_SwitchActiveMember' % self.SerialNum self.bg = loader.loadModel(self.BackgroundModelName) def findNodes(names, model=self.bg): results = [] for name in names: for nm in makeTuple(name): node = model.find('**/%s' % nm) if not node.isEmpty(): results.append(node) break return results self.bgTop, self.bgBottom, self.bgLeft, self.bgRight, self.bgMiddle, self.bgTopLeft, self.bgBottomLeft, self.bgTopRight, self.bgBottomRight = findNodes( [('top', 'top1'), 'bottom', 'left', 'right', 'middle', 'topLeft', 'bottomLeft', 'topRight', 'bottomRight']) self.bg.reparentTo(self, -1) self.__members = [] self.activeMember = None self.activeCandidate = None self.fadeIval = None self.width = 1 self.inFinalize = 0
def enterVisible(self): SCObject.enterVisible(self) self.privScheduleFinalize() # tell our members that they're visible now for member in self: if member.isViewable(): if not member.isVisible(): member.enterVisible() # we are just becoming visible, so reset our child fade flag self.childHasFaded = 0 # if a sibling menu has already faded in, don't fade in again alreadyFaded = 0 parentMenu = None if self.holder is not None: if self.holder.parentMenu is not None: parentMenu = self.holder.parentMenu alreadyFaded = parentMenu.childHasFaded if SCMenu.WantFade: if alreadyFaded: self.fadeFunc(1.) else: self.stopFade() self.fadeIval = LerpFunctionInterval( self.fadeFunc, fromData=0., toData=1., duration=SCMenu.FadeDuration) self.fadeIval.play() if parentMenu is not None: parentMenu.childHasFaded = 1
def enterVisible(self): SCObject.enterVisible(self) self.privScheduleFinalize() for member in self: if member.isViewable(): if not member.isVisible(): member.enterVisible() self.childHasFaded = 0 alreadyFaded = 0 parentMenu = None if self.holder is not None: if self.holder.parentMenu is not None: parentMenu = self.holder.parentMenu alreadyFaded = parentMenu.childHasFaded if SCMenu.WantFade: if alreadyFaded: self.fadeFunc(1.0) else: self.stopFade() self.fadeIval = LerpFunctionInterval( self.fadeFunc, fromData=0.0, toData=1.0, duration=SCMenu.FadeDuration) self.fadeIval.play() if parentMenu is not None: parentMenu.childHasFaded = 1
def invalidate(self): SCObject.invalidate(self) parentMenu = self.getParentMenu() if parentMenu is not None: if not parentMenu.isFinalizing(): parentMenu.invalidate() return
def destroy(self): if self.isActive(): self.exitActive() SCObject.destroy(self) if hasattr(self, 'button'): self.button.destroy() del self.button self.parentMenu = None self.detachNode()
def exitVisible(self): SCObject.exitVisible(self) self.stopFade() self.privCancelFinalize() self.__cancelActiveMemberSwitch() self.__setActiveMember(None) for member in self: if member.isVisible(): member.exitVisible()
def exitVisible(self): SCObject.exitVisible(self) self.stopFade() self.privCancelFinalize() self.__cancelActiveMemberSwitch() # if there is a member that is active, deactive it self.__setActiveMember(None) # tell all of our visible members that they're about to # not be visible anymore for member in self: if member.isVisible(): member.exitVisible()
def __init__(self, parentMenu = None): SCObject.__init__(self) self.SerialNum = SCElement.SerialNum SCElement.SerialNum += 1 node = hidden.attachNewNode('SCElement%s' % self.SerialNum) NodePath.__init__(self, node) self.FinalizeTaskName = 'SCElement%s_Finalize' % self.SerialNum self.parentMenu = parentMenu self.__active = 0 self.__viewable = 1 self.lastWidth = 0 self.lastHeight = 0 self.setDimensions(0, 0) self.padX = 0.25 self.padZ = 0.1
def invalidate(self): """ Call this if something has changed and we should reconstruct ourselves: - member added - member removed - member visibility state change etc. """ SCObject.invalidate(self) # If we're visible, we need to spawn a task to rebuild our menu # before we render. We could rebuild the menu immediately, but # that would get expensive if there are many consecutive member # adds and/or removes. if self.isVisible(): self.privScheduleFinalize()
def finalize(self, dbArgs={}): if not self.isDirty(): return SCObject.finalize(self) if hasattr(self, 'button'): self.button.destroy() del self.button halfHeight = self.height / 2.0 textX = 0 if dbArgs.has_key('text_align'): if dbArgs['text_align'] == TextNode.ACenter: textX = self.width / 2.0 args = { 'text': self.getDisplayText(), 'frameColor': (0, 0, 0, 0), 'rolloverColor': self.getColorScheme().getRolloverColor() + (1, ), 'pressedColor': self.getColorScheme().getPressedColor() + (1, ), 'text_font': OTPGlobals.getInterfaceFont(), 'text_align': TextNode.ALeft, 'text_fg': self.getColorScheme().getTextColor() + (1, ), 'text_pos': (textX, -.25 - halfHeight, 0), 'relief': DGG.FLAT, 'pressEffect': 0 } args.update(dbArgs) rolloverColor = args['rolloverColor'] pressedColor = args['pressedColor'] del args['rolloverColor'] del args['pressedColor'] btn = DirectButton(parent=self, frameSize=(0, self.width, -self.height, 0), **args) btn.frameStyle[DGG.BUTTON_ROLLOVER_STATE].setColor(*rolloverColor) btn.frameStyle[DGG.BUTTON_DEPRESSED_STATE].setColor(*pressedColor) btn.updateFrameStyle() btn.bind(DGG.ENTER, self.onMouseEnter) btn.bind(DGG.EXIT, self.onMouseLeave) btn.bind(DGG.B1PRESS, self.onMouseClick) self.button = btn self.lastWidth = self.width self.lastHeight = self.height self.validate()
def destroy(self): self.stopFade() SCObject.destroy(self) del self.bgTop del self.bgBottom del self.bgLeft del self.bgRight del self.bgMiddle del self.bgBottomLeft del self.bgTopRight del self.bgBottomRight self.bg.removeNode() del self.bg self.holder = None for member in self.__members: member.destroy() del self.__members self.removeNode() taskMgr.remove(self.FinalizeTaskName) taskMgr.remove(self.ActiveMemberSwitchTaskName)
def invalidateAll(self): SCObject.invalidateAll(self) if self.menu is not None: self.menu.invalidateAll()
def exitVisible(self): SCObject.exitVisible(self) self.privCancelFinalize()
def enterVisible(self): SCObject.enterVisible(self) self.privScheduleFinalize()
def finalizeAll(self): SCObject.finalizeAll(self) for member in self: member.finalizeAll()
def invalidateAll(self): SCObject.invalidateAll(self) for member in self: member.invalidateAll()
def privSetSettingsRef(self, settingsRef): SCObject.privSetSettingsRef(self, settingsRef) for member in self: member.privSetSettingsRef(settingsRef)
def privSetSettingsRef(self, settingsRef): SCObject.privSetSettingsRef(self, settingsRef) # propogate the settings reference to our children for member in self: member.privSetSettingsRef(settingsRef)
def finalize(self): if not self.isDirty(): return self.inFinalize = 1 SCObject.finalize(self) if __debug__: # make sure all of our members know that we are their parent menu # (who's yo daddy?) for member in self: assert member.getParentMenu() is self # we aren't interested in members that aren't viewable. # build a list of viewable members. Also parent viewable # members to us, parent non-viewable members to hidden. visibleMembers = [] for member in self: if member.isViewable(): visibleMembers.append(member) member.reparentTo(self) else: member.reparentTo(hidden) # if this is the active member, deactivate it if self.activeMember is member: self.__setActiveMember(None) # survey the members to find out their ideal dimensions, and # determine the maximum dimensions maxWidth = 0. maxHeight = 0. for member in visibleMembers: width, height = member.getMinDimensions() maxWidth = max(maxWidth, width) maxHeight = max(maxHeight, height) # make sure that we cover our parent menu all the way out past its # right edge holder = self.getHolder() if holder is not None: # how wide do we need to be to cover our parent menu? widthToCover = holder.getMinSubmenuWidth() maxWidth = max(maxWidth, widthToCover) # all of the menu members will be at least as big as the biggest # member, in each dimension memberWidth, memberHeight = maxWidth, maxHeight # Store this so that we can do horizonal centering self.width = maxWidth # put the members in the right place, and tell them what size # they should be for i in range(len(visibleMembers)): member = visibleMembers[i] member.setPos(0, 0, -i * maxHeight) member.setDimensions(memberWidth, memberHeight) member.finalize() if len(visibleMembers) > 0: z1 = visibleMembers[0].getZ(aspect2d) visibleMembers[0].setZ(-maxHeight) z2 = visibleMembers[0].getZ(aspect2d) visibleMembers[0].setZ(0) actualHeight = (z2 - z1) * len(visibleMembers) # keep the menu from going off the bottom of the screen bottomZ = self.getZ(aspect2d) + actualHeight if bottomZ < -1.: overlap = bottomZ - (-1.) self.setZ(aspect2d, self.getZ(aspect2d) - overlap) # keep the menu from going off the top of the screen if self.getZ(aspect2d) > 1.: self.setZ(aspect2d, 1.) # set up the background frame sX = memberWidth sZ = memberHeight * len(visibleMembers) self.bgMiddle.setScale(sX, 1, sZ) self.bgTop.setScale(sX, 1, 1) self.bgBottom.setScale(sX, 1, 1) self.bgLeft.setScale(1, 1, sZ) self.bgRight.setScale(1, 1, sZ) self.bgBottomLeft.setZ(-sZ) self.bgBottom.setZ(-sZ) self.bgTopRight.setX(sX) self.bgRight.setX(sX) self.bgBottomRight.setX(sX) self.bgBottomRight.setZ(-sZ) # scale the border wrt aspect2d # note: changing the Y-scale from literal '1' wrt parent # is not necessary and was causing visibility problems sB = .15 self.bgTopLeft.setSx(aspect2d, sB) self.bgTopLeft.setSz(aspect2d, sB) self.bgBottomRight.setSx(aspect2d, sB) self.bgBottomRight.setSz(aspect2d, sB) self.bgBottomLeft.setSx(aspect2d, sB) self.bgBottomLeft.setSz(aspect2d, sB) self.bgTopRight.setSx(aspect2d, sB) self.bgTopRight.setSz(aspect2d, sB) self.bgTop.setSz(aspect2d, sB) self.bgBottom.setSz(aspect2d, sB) self.bgLeft.setSx(aspect2d, sB) self.bgRight.setSx(aspect2d, sB) r, g, b = self.getColorScheme().getFrameColor() a = self.getColorScheme().getAlpha() self.bg.setColorScale(r, g, b, a) # if we have an active member, reparent it to us, so that # it and its children show up over the rest of the menu elements if self.activeMember is not None: self.activeMember.reparentTo(self) self.validate() self.inFinalize = 0
def privSetSettingsRef(self, settingsRef): SCObject.privSetSettingsRef(self, settingsRef) if self.menu is not None: self.menu.privSetSettingsRef(settingsRef)
def invalidate(self): SCObject.invalidate(self) if self.isVisible(): self.privScheduleFinalize()
def finalizeAll(self): SCObject.finalizeAll(self) if self.menu is not None: self.menu.finalizeAll()
def finalize(self): if not self.isDirty(): return self.inFinalize = 1 SCObject.finalize(self) visibleMembers = [] for member in self: if member.isViewable(): visibleMembers.append(member) member.reparentTo(self) else: member.reparentTo(hidden) if self.activeMember is member: self.__setActiveMember(None) maxWidth = 0.0 maxHeight = 0.0 for member in visibleMembers: width, height = member.getMinDimensions() maxWidth = max(maxWidth, width) maxHeight = max(maxHeight, height) holder = self.getHolder() if holder is not None: widthToCover = holder.getMinSubmenuWidth() maxWidth = max(maxWidth, widthToCover) memberWidth, memberHeight = maxWidth, maxHeight self.width = maxWidth for i in xrange(len(visibleMembers)): member = visibleMembers[i] member.setPos(0, 0, -i * maxHeight) member.setDimensions(memberWidth, memberHeight) member.finalize() if len(visibleMembers) > 0: z1 = visibleMembers[0].getZ(aspect2d) visibleMembers[0].setZ(-maxHeight) z2 = visibleMembers[0].getZ(aspect2d) visibleMembers[0].setZ(0) actualHeight = (z2 - z1) * len(visibleMembers) bottomZ = self.getZ(aspect2d) + actualHeight if bottomZ < -1.0: overlap = bottomZ - -1.0 self.setZ(aspect2d, self.getZ(aspect2d) - overlap) if self.getZ(aspect2d) > 1.0: self.setZ(aspect2d, 1.0) sX = memberWidth sZ = memberHeight * len(visibleMembers) self.bgMiddle.setScale(sX, 1, sZ) self.bgTop.setScale(sX, 1, 1) self.bgBottom.setScale(sX, 1, 1) self.bgLeft.setScale(1, 1, sZ) self.bgRight.setScale(1, 1, sZ) self.bgBottomLeft.setZ(-sZ) self.bgBottom.setZ(-sZ) self.bgTopRight.setX(sX) self.bgRight.setX(sX) self.bgBottomRight.setX(sX) self.bgBottomRight.setZ(-sZ) sB = 0.15 self.bgTopLeft.setSx(aspect2d, sB) self.bgTopLeft.setSz(aspect2d, sB) self.bgBottomRight.setSx(aspect2d, sB) self.bgBottomRight.setSz(aspect2d, sB) self.bgBottomLeft.setSx(aspect2d, sB) self.bgBottomLeft.setSz(aspect2d, sB) self.bgTopRight.setSx(aspect2d, sB) self.bgTopRight.setSz(aspect2d, sB) self.bgTop.setSz(aspect2d, sB) self.bgBottom.setSz(aspect2d, sB) self.bgLeft.setSx(aspect2d, sB) self.bgRight.setSx(aspect2d, sB) r, g, b = self.getColorScheme().getFrameColor() a = self.getColorScheme().getAlpha() self.bg.setColorScale(r, g, b, a) if self.activeMember is not None: self.activeMember.reparentTo(self) self.validate() self.inFinalize = 0