from panda3d.core import Vec3, Vec4, Point3, TextNode, VBase4, NodePath from direct.gui.DirectGui import DirectFrame, DirectButton, DirectLabel, DirectScrolledList, DirectCheckButton from direct.gui import DirectGuiGlobals from direct.showbase import DirectObject from direct.showbase import PythonUtil from direct.task.Task import Task from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer from toontown.parties import PartyGlobals from toontown.parties.PartyInfo import PartyInfo from toontown.parties import PartyUtils class PartyEditorGridElement(DirectButton): notify = directNotify.newCategory('PartyEditorGridElement') def __init__(self, partyEditor, id, isDecoration, checkSoldOutAndPaidStatusAndAffordability, **kw): self.partyEditor = partyEditor self.id = id self.isDecoration = isDecoration self.checkSoldOutAndPaidStatusAndAffordability = checkSoldOutAndPaidStatusAndAffordability if self.isDecoration: self._name = TTLocalizer.PartyDecorationNameDict[self.id]['editor'] colorList = ((1.0, 1.0, 1.0, 1.0), (0.0, 0.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 1.0)) self.geom = self.partyEditor.partyPlanner.gui.find('**/%s' % PartyGlobals.DecorationInformationDict[self.id]['gridAsset']) else: self._name = TTLocalizer.PartyActivityNameDict[self.id]['editor'] colorList = ((1.0, 1.0, 1.0, 1.0), (0.0, 1.0, 0.0, 1.0), (1.0, 1.0, 0.0, 1.0), (0.5, 0.5, 0.5, 1.0)) self.geom = self.partyEditor.partyPlanner.gui.find('**/%s' % PartyGlobals.ActivityInformationDict[self.id]['gridAsset']) optiondefs = (('geom', self.geom, None), ('geom_scale', 1.0, None), ('geom_color', colorList[0], None), ('geom1_color', colorList[0], None), ('geom2_color', colorList[0], None), ('geom3_color', colorList[0], None), ('relief', None, None)) self.defineoptions(kw, optiondefs) DirectButton.__init__(self, self.partyEditor.parent) self.initialiseoptions(PartyEditorGridElement) self.setName('%sGridElement' % self._name) self.bind(DirectGuiGlobals.B1PRESS, self.clicked) self.bind(DirectGuiGlobals.B1RELEASE, self.released) self.bind(DirectGuiGlobals.ENTER, self.mouseEnter) self.bind(DirectGuiGlobals.EXIT, self.mouseExit) self.uprightNodePath = NodePath('%sUpright' % self._name) self.uprightNodePath.reparentTo(self) rollOverZOffset = self.getGridSize()[1] / 30.0 self.rolloverTitle = DirectLabel(relief=None, parent=self.uprightNodePath, pos=Point3(0.0, 0.0, rollOverZOffset), text=self._name, text_fg=(1.0, 1.0, 1.0, 1.0), text_shadow=(0.0, 0.0, 0.0, 1.0), text_scale=0.075) self.rolloverTitle.stash() self.stash() self.overValidSquare = False self.lastValidPosition = None self.setColorScale(0.9, 0.9, 0.9, 0.7) self.setTransparency(True) self.mouseOverTrash = False self.centerGridSquare = None return def getCorrectRotation(self): r = self.getR() if r == 90.0: r = 270.0 elif r == 270.0: r = 90.0 if self.id == PartyGlobals.ActivityIds.PartyCannon: return PartyUtils.convertDegreesToPartyGrid(r + 180.0) return PartyUtils.convertDegreesToPartyGrid(r) def getDecorationTuple(self, x, y): return (self.id, self.centerGridSquare.x, PartyGlobals.PartyEditorGridSize[1] - 1 - self.centerGridSquare.y, self.getCorrectRotation()) def getActivityTuple(self, x, y): return (self.id, self.centerGridSquare.x, PartyGlobals.PartyEditorGridSize[1] - 1 - self.centerGridSquare.y, self.getCorrectRotation()) def attach(self, mouseEvent): PartyEditorGridElement.notify.debug('attached grid element %s' % self._name) taskMgr.remove('gridElementDragTask%s' % self._name) vWidget2render2d = self.getPos(render2d) vMouse2render2d = Point3(mouseEvent.getMouse()[0], 0, mouseEvent.getMouse()[1]) taskMgr.add(self.elementDragTask, 'gridElementDragTask%s' % self._name) self.unstash() self.rolloverTitle.unstash() self.uprightNodePath.reparentTo(self) self.setPosHprToDefault() def elementDragTask(self, state): mwn = base.mouseWatcherNode if mwn.hasMouse(): vMouse2render2d = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1]) newPos = vMouse2render2d if newPos[0] > PartyGlobals.PartyEditorGridBounds[0][0] and newPos[0] < PartyGlobals.PartyEditorGridBounds[1][0] and newPos[2] < PartyGlobals.PartyEditorGridBounds[0][1] and newPos[2] > PartyGlobals.PartyEditorGridBounds[1][1]: centerGridSquare = self.snapToGrid(newPos) if centerGridSquare is not None: self.centerGridSquare = centerGridSquare if not self.overValidSquare: self.setOverValidSquare(True) if self.mouseOverTrash: self.setOverTrash(False) return Task.cont if self.id != PartyGlobals.ActivityIds.PartyClock and newPos[0] > PartyGlobals.PartyEditorTrashBounds[0][0] and newPos[0] < PartyGlobals.PartyEditorTrashBounds[1][0] and newPos[2] < PartyGlobals.PartyEditorTrashBounds[0][1] and newPos[2] > PartyGlobals.PartyEditorTrashBounds[1][1]: if not self.mouseOverTrash: self.setOverTrash(True) elif self.mouseOverTrash: self.setOverTrash(False) self.setPos(render2d, newPos) if self.overValidSquare: self.setOverValidSquare(False) return Task.cont def setOverTrash(self, value): self.mouseOverTrash = value if value: self.partyEditor.trashCanButton['state'] = DirectGuiGlobals.DISABLED self.setColorScale(1.0, 0.0, 0.0, 1.0) else: self.partyEditor.trashCanButton['state'] = DirectGuiGlobals.NORMAL self.setColorScale(0.9, 0.9, 0.9, 0.7) def setOverValidSquare(self, value): self.overValidSquare = value if value: self.setColorScale(1.0, 1.0, 1.0, 1.0) else: self.setColorScale(0.9, 0.9, 0.9, 0.7) def removeFromGrid(self): if self.centerGridSquare is not None: self.partyEditor.partyEditorGrid.removeElement(self.centerGridSquare, self.getGridSize()) self.setOverValidSquare(False) self.lastValidPosition = None self.stash() return def snapToGrid(self, newPos): gridSquare = self.getGridSquareFromPosition(newPos) if gridSquare == None: self.setPosHprToDefault() self.setPos(render2d, newPos) return elif not self.partyEditor.partyEditorGrid.checkGridSquareForAvailability(gridSquare, self.getGridSize()): self.setPos(render2d, newPos) return self.setPosHprBasedOnGridSquare(gridSquare) return gridSquare def getGridSize(self): if self.isDecoration: return PartyGlobals.DecorationInformationDict[self.id]['gridsize'] else: return PartyGlobals.ActivityInformationDict[self.id]['gridsize'] def setPosHprToDefault(self): self.setR(0.0) self.uprightNodePath.setR(0.0) def setPosHprBasedOnGridSquare(self, gridSquare): gridPos = gridSquare.getPos() if self.getGridSize()[0] % 2 == 0: gridPos.setX(gridPos[0] + PartyGlobals.PartyEditorGridSquareSize[0] / 2.0) if self.getGridSize()[1] % 2 == 0: gridPos.setZ(gridPos[2] + PartyGlobals.PartyEditorGridSquareSize[1] / 2.0) if self.id != PartyGlobals.ActivityIds.PartyFireworks: if gridPos[0] > PartyGlobals.PartyEditorGridCenter[0] + PartyGlobals.PartyEditorGridRotateThreshold: self.setR(90.0) self.uprightNodePath.setR(-90.0) elif gridPos[0] < PartyGlobals.PartyEditorGridCenter[0] - PartyGlobals.PartyEditorGridRotateThreshold: self.setR(270.0) self.uprightNodePath.setR(-270.0) elif gridPos[2] < PartyGlobals.PartyEditorGridCenter[1] - PartyGlobals.PartyEditorGridRotateThreshold: self.setR(180.0) self.uprightNodePath.setR(-180.0) else: self.setR(0.0) self.uprightNodePath.setR(0.0) else: self.setR(270.0) self.uprightNodePath.setR(-270.0) self.setPos(render2d, gridPos) self.lastValidPosition = gridPos def getGridSquareFromPosition(self, newPos): localX = newPos[0] - PartyGlobals.PartyEditorGridBounds[0][0] localY = newPos[2] - PartyGlobals.PartyEditorGridBounds[1][1] x = int(localX / PartyGlobals.PartyEditorGridSquareSize[0]) y = int(localY / PartyGlobals.PartyEditorGridSquareSize[1]) y = PartyGlobals.PartyEditorGridSize[1] - 1 - y return self.partyEditor.partyEditorGrid.getGridSquare(x, y) def detach(self, mouseEvent): taskMgr.remove('gridElementDragTask%s' % self._name) self.rolloverTitle.stash() if self.overValidSquare: self.partyEditor.partyEditorGrid.registerNewElement(self, self.centerGridSquare, self.getGridSize()) self.partyEditor.updateCostsAndBank() self.partyEditor.handleMutuallyExclusiveActivities() elif self.lastValidPosition is not None: if self.mouseOverTrash: self.partyEditor.trashCanButton['state'] = DirectGuiGlobals.NORMAL self.lastValidPosition = None self.partyEditor.updateCostsAndBank() self.stash() else: self.setPos(render2d, self.lastValidPosition) self.setOverValidSquare(True) self.partyEditor.partyEditorGrid.registerNewElement(self, self.centerGridSquare, self.getGridSize()) self.partyEditor.updateCostsAndBank() self.partyEditor.handleMutuallyExclusiveActivities() else: self.stash() self.checkSoldOutAndPaidStatusAndAffordability() return def placeInPartyGrounds(self, desiredXY = None): self.centerGridSquare = self.partyEditor.partyEditorGrid.getClearGridSquare(self.getGridSize(), desiredXY) if self.centerGridSquare is not None: self.setOverValidSquare(True) self.unstash() self.setPosHprBasedOnGridSquare(self.centerGridSquare) self.partyEditor.partyEditorGrid.registerNewElement(self, self.centerGridSquare, self.getGridSize()) self.partyEditor.updateCostsAndBank() self.partyEditor.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsPartyGrounds self.checkSoldOutAndPaidStatusAndAffordability() return True else: return False return def clicked(self, mouseEvent): PartyEditorGridElement.notify.debug('clicked grid element %s' % self._name) if self.centerGridSquare is not None: self.attach(mouseEvent) self.partyEditor.partyEditorGrid.removeElement(self.centerGridSquare, self.getGridSize()) return def released(self, mouseEvent): PartyEditorGridElement.notify.debug('released grid element %s' % self._name) self.detach(mouseEvent) def mouseEnter(self, mouseEvent): parent = self.getParent() self.reparentTo(parent) self.rolloverTitle.unstash() def mouseExit(self, mouseEvent): self.rolloverTitle.stash() def destroy(self): self.unbind(DirectGuiGlobals.B1PRESS) self.unbind(DirectGuiGlobals.B1RELEASE) self.unbind(DirectGuiGlobals.ENTER) self.unbind(DirectGuiGlobals.EXIT) DirectButton.destroy(self)