diff --git a/direct/src/directutil/DirectCameraControl.py b/direct/src/directutil/DirectCameraControl.py index e05979ef41..3a2a37bb48 100644 --- a/direct/src/directutil/DirectCameraControl.py +++ b/direct/src/directutil/DirectCameraControl.py @@ -143,7 +143,7 @@ class DirectCameraControl(PandaObject): def centerCamNow(self, chan): self.centerCamIn(chan, 0.) - def centerCamIn(self, chan,t): + def centerCamIn(self, chan, t): # Chan is a display region context taskMgr.removeTasksNamed('manipulateCamera') markerToCam = self.coaMarker.getPos( chan.camera ) diff --git a/direct/src/directutil/DirectGeometry.py b/direct/src/directutil/DirectGeometry.py index 12fec10e6f..f84a2e7404 100644 --- a/direct/src/directutil/DirectGeometry.py +++ b/direct/src/directutil/DirectGeometry.py @@ -42,6 +42,9 @@ class LineNodePath(NodePath): def setColor( self, *_args ): apply( self.lineSegs.setColor, _args ) + def setVertex( self, *_args): + apply( self.lineSegs.setVertex, _args ) + def setVertexColor( self, vertex, *_args ): apply( self.lineSegs.setVertexColor, (vertex,) + _args ) @@ -51,8 +54,8 @@ class LineNodePath(NodePath): def getNumVertices( self ): return self.lineSegs.getNumVertices() - def getVertex( self ): - return self.lineSegs.getVertex() + def getVertex( self, index ): + return self.lineSegs.getVertex(index) def getVertexColor( self ): return self.lineSegs.getVertexColor() diff --git a/direct/src/directutil/DirectGrid.py b/direct/src/directutil/DirectGrid.py index c4ecbf491f..c5976a9e08 100644 --- a/direct/src/directutil/DirectGrid.py +++ b/direct/src/directutil/DirectGrid.py @@ -1,9 +1,134 @@ -from PandaObject import * - -class DirectGrid(NodePath): - def __init__(self, parent = None): - NodePath.__init__(self) - if parent is None: - parent = hidden - self.assign(parent.attachNewNode( NamedNode('grid') )) - +from PandaObject import * +from DirectGeometry import * + +class DirectGrid(NodePath,PandaObject): + def __init__(self, direct): + # Initialize superclass + NodePath.__init__(self) + self.assign(hidden.attachNewNode( NamedNode('DirectGrid'))) + + # Record handle to direct session + self.direct = direct + + # Load up grid parts to initialize grid object + # Polygon used to mark grid plane + self.gridBack = loader.loadModel('misc/gridBack') + self.gridBack.reparentTo(self) + self.gridBack.setColor(0.5,0.5,0.5,0.5) + + # Grid Lines + self.lines = self.attachNewNode(NamedNode('gridLines')) + self.minorLines = LineNodePath(self.lines) + self.minorLines.lineNode.setName('minorLines') + self.minorLines.setColor(VBase4(0.3,0.55,1,1)) + self.minorLines.setThickness(1) + + self.majorLines = LineNodePath(self.lines) + self.majorLines.lineNode.setName('majorLines') + self.majorLines.setColor(VBase4(0.3,0.55,1,1)) + self.majorLines.setThickness(5) + + self.centerLines = LineNodePath(self.lines) + self.centerLines.lineNode.setName('centerLines') + self.centerLines.setColor(VBase4(1,0,0,0)) + self.centerLines.setThickness(3) + + # Small marker to hilight snap-to-grid point + self.snapMarker = loader.loadModel('misc/sphere') + self.snapMarker.node().setName('gridSnapMarker') + self.snapMarker.reparentTo(self) + self.snapMarker.setColor(1,0,0,1) + self.snapMarker.setScale(0.3) + self.snapPos = Point3(0) + + # Initialize Grid characteristics + self.fXyzSnap = 1 + self.gridSize = 100.0 + self.gridSpacing = 5.0 + self.enable() + + def enable(self): + self.reparentTo(render) + self.accept('selectedNodePath', self.selectGridBackParent) + self.updateGrid() + + def disable(self): + self.reparentTo(hidden) + self.ignore('selectedNodePath') + + def selectGridBackParent(self, nodePath): + if nodePath.getNodePathName() == 'GridBack': + self.direct.select(self) + + def updateGrid(self): + # Update grid lines based upon current grid spacing and grid size + # First reset existing grid lines + self.minorLines.reset() + self.majorLines.reset() + self.centerLines.reset() + + # Now redraw lines + numLines = math.ceil(self.gridSize/self.gridSpacing) + scaledSize = numLines * self.gridSpacing + + center = self.centerLines + minor = self.minorLines + major = self.majorLines + for i in range(-numLines,numLines + 1): + if i == 0: + center.moveTo(i * self.gridSpacing, -scaledSize, 0) + center.drawTo(i * self.gridSpacing, scaledSize, 0) + center.moveTo(-scaledSize, i * self.gridSpacing, 0) + center.drawTo(scaledSize, i * self.gridSpacing, 0) + else: + if (i % 5) == 0: + major.moveTo(i * self.gridSpacing, -scaledSize, 0) + major.drawTo(i * self.gridSpacing, scaledSize, 0) + major.moveTo(-scaledSize, i * self.gridSpacing, 0) + major.drawTo(scaledSize, i * self.gridSpacing, 0) + else: + minor.moveTo(i * self.gridSpacing, -scaledSize, 0) + minor.drawTo(i * self.gridSpacing, scaledSize, 0) + minor.moveTo(-scaledSize, i * self.gridSpacing, 0) + minor.drawTo(scaledSize, i * self.gridSpacing, 0) + + center.create() + minor.create() + major.create() + self.gridBack.setScale(scaledSize) + + def roundTo(self, value, divisor): + return round(value/float(divisor)) * divisor + + def setXyzSnap(self, fSnap): + self.fXyzSnap = fSnap + + def getXyzSnap(self): + return self.fXyzSnap + + def snapToGrid(self, point): + if self.fXyzSnap: + self.snapPos.set( + roundTo(point[0], self.gridSpacing), + roundTo(point[1], self.gridSpacing), + roundTo(point[2], self.gridSpacing)) + else: + self.snapPos.assign(point) + + # Move snap marker to this point + self.snapMarker.setPos(self.snapPos) + + # Return the hit point + return self.snapPos + + def setGridSpacing(self, spacing): + self.gridSpacing = spacing + self.updateGrid() + + def getGridSpacing(self): + return self.gridSpacing + + def setSize(self, size): + # Set size of grid back and redraw lines + self.gridSize = size + self.updateGrid() diff --git a/direct/src/directutil/DirectSession.py b/direct/src/directutil/DirectSession.py index 524cc9141d..81473cc5ec 100644 --- a/direct/src/directutil/DirectSession.py +++ b/direct/src/directutil/DirectSession.py @@ -2,6 +2,7 @@ from PandaObject import * from DirectCameraControl import * from DirectManipulation import * from DirectSelection import * +from DirectGrid import * from DirectGeometry import * import OnscreenText @@ -20,6 +21,8 @@ class DirectSession(PandaObject): self.cameraControl = DirectCameraControl(self) self.manipulationControl = DirectManipulationControl(self) self.useObjectHandles() + self.grid = DirectGrid(self) + self.grid.disable() # Initialize the collection of selected nodePaths self.selected = SelectedNodePaths(self) @@ -72,10 +75,9 @@ class DirectSession(PandaObject): self.cameraControl.updateCoa(coa) # Adjust widgets size - self.widget.setScale(dnp.getRadius()) - # This is the additional scaling factor used to grow and - # shrink the widget - self.widget.setScalingFactor(1.0) + # This uses the additional scaling factor used to grow and + # shrink the widget + self.widget.setScalingFactor(dnp.getRadius()) # Spawn task to have object handles follow the selected object taskMgr.removeTasksNamed('followSelectedNodePath') diff --git a/direct/src/leveleditor/LevelEditor.py b/direct/src/leveleditor/LevelEditor.py new file mode 100644 index 0000000000..14e7a24428 --- /dev/null +++ b/direct/src/leveleditor/LevelEditor.py @@ -0,0 +1,3310 @@ +from PandaObject import * +from PieMenu import * +from OnscreenText import * +from whrandom import * + + +class LevelEditor(NodePath, PandaObject): + def __init__(self,direct): + # Initialize superclass + NodePath.__init__(self) + self.assign(hidden.attachNewNode( NamedNode('LevelEditor'))) + + # Record handle to direct session + self.direct = direct + # Make sure direct is running + self.direct.enable() + + # Create level editor dictionaries + # This dictionary stores information about new objects added + # to the level + self.levelDictionary = {} + # This dictionary stores information about module hooks, + # grouped by level + self.hooksDictionary = {} + # This dictionary stores information about clickBoxLists, + # grouped by level + self.clickBoxDictionary = {} + # This dictionary stores information about the various + # pie menus in use + self.pieMenuDictionary = {} + # This dictionary stores all the different color palettes + self.colorPaletteDictionary = {} + # This dictionary stores info about current and possible + # object attributes + self.attributeDictionary = {} + # This dictionary stores pleasing style combinations + self.styleDictionary = {} + + # DNAStorage instance for storing level DNA info + self.dnaStore = DNAStorage() + self.dnaStore.loadDNAFile('dna/storage.dna', + getDefaultCoordinateSystem()) + + # Top level DNA Data Object + self.levelObjectsDNA = DNAData('LevelObjects') + + # Create top level node + self.levelObjects = self.attachNewNode(NamedNode('LevelObjects')) + + # Create a top level group + self.createTopLevelGroup() + + # Set used to iterate over module categories + self.categorySet = [] + + self.selectedLevelObject = None + self.targetDNAObject = None + self.activeMenu = None + + # Plane for intersection tests with wall + self.wallIntersectionPlane = Plane(Vec3.up(), Point3(0)) + + # Get a handle to the grid + self.grid = self.direct.grid + self.showGrid(0) + + #self.levelMap = loader.loadModel('LevelEditor/level-map.egg') + self.levelMap = hidden.attachNewNode(NamedNode('level-map')) + self.levelMap.reparentTo(self) + self.levelMap.getBottomArc().setTransition(TransparencyTransition(1)) + self.levelMap.setColor(Vec4(1,1,1,.4)) + self.levelMap.hide() + + self.hitPt = Point3(0) + self.offset = Point3(0) + self.crankOrigin = Point3(0) + self.crankDir = Vec3(0) + + self.hprSnap = 1 + self.snapAngle = 90.0 + self.lastAngle = 0.0 + + # Create buttons and pie menus + # MRM + #self.initializeLevelEditorButtons() + # Initialize styles + self.initializeStyleDictionary() + # Initialize pie Menus (this depends on the style dictionary) + self.initializePieMenus() + + base.cam.node().setNear(5.0) + base.cam.node().setFar(10000) + self.direct.camera.setPos(0,0,10) + + # Default is to use the toontown central color palette + self.editToontownCentral() + + self.enable() + + def initializeAttributeDictionary(self): + + # Retrieve lists of available attributes from DNAStorage object + # Cornices + attributeList = self.getCatalogCodesSuffix('cornice', '_ur') + # MRM: What does this do? + # attributeList addFirst: 'none' + self.attributeDictionary['corniceTextures'] = attributeList + self.attributeDictionary['corniceTexture'] = attributeList[1] + self.attributeDictionary['corniceOrienation'] = '_ur' + + # Doors + attributeList = self.getCatalogCodesSuffix('door', '_ur') + self.attributeDictionary['doorTextures'] = attributeList + self.attributeDictionary['doorTexture'] = attributeList[1] + self.attributeDictionary['doorOrienation'] = '_ur' + + # FlatBuildings + self.attributeDictionary['buildingHeight'] = 20.0 + + # Props + attributeList = self.getCatalogCodes('prop') + self.attributeDictionary['propTypes'] = attributeList + self.attributeDictionary['propType'] = attributeList[1] + + # Walls + attributeList = self.getCatalogCodesSuffix('wall', '_ur') + self.attributeDictionary['wallTextures'] = attributeList + self.attributeDictionary['wallTexture'] = attributeList[1] + self.attributeDictionary['wallOrienation'] = '_ur' + self.attributeDictionary['wallWidth'] = 15.0 + + # Windows + attributeList = self.getCatalogCodesSuffix('window', '_ur') + self.attributeDictionary['windowTextures'] = attributeList + self.attributeDictionary['windowTexture'] = attributeList[1] + self.attributeDictionary['windowOrienation'] = '_ur' + self.attributeDictionary['numWindows'] = 0 + + def getActiveColor(self): + return self.attributeDictionary['activeColor'] + + def setActiveColor(self, color): + self.attributeDictionary['activeColor'] = color + + def getBuildingHeight(self): + return self.attributeDictionary['buildingHeight'] + + def setBuildingHeight(self, height): + self.attributeDictionary['buildingHeight'] = height + + def getCategorySet(self): + return self.categorySet + + def getClickBoxDictionary(self): + return self.clickBoxDictionary + + def getCorniceColor(self): + return self.attributeDictionary['corniceColor'] + + def getCorniceColors(self): + return self.attributeDictionary['corniceColors'] + + def getCorniceTexture(self): + return self.attributeDictionary['corniceTexture'] + + def setCorniceTexture(self, dnaString): + self.attributeDictionary['corniceTexture'] = dnaString + + def getCorniceTextures(self): + return self.attributeDictionary['corniceTextures'] + + def getDnaStore(self): + return self.dnaStore + + def getDoorColor(self): + return self.attributeDictionary['doorColor'] + + def getDoorColors(self): + return self.attributeDictionary['doorColors'] + + def getDoorTexture(self): + return self.attributeDictionary['doorTexture'] + + def setDoorTexture(self,dnaString): + self.attributeDictionary['doorTexture'] = dnaString + + def getDoorTextures(self): + return self.attributeDictionary['doorTextures'] + + def getGrid(self): + return self.grid + + def getGroupNum(self): + return self.groupNum + + def setGroupNum(self,num): + self.groupNum = num + + def setGroupParent(self,nodePath): + parentDNA = self.getDNAGroup(nodePath) + if parentDNA: + self.groupParent = nodePath + self.groupParentDNA = parentDNA + + def getHooksDictionary(self): + return self.hooksDictionary + + def getLevelDictionary(self): + return self.levelDictionary + + def getLevelMap(self): + return self.levelMap + + def getLevelObjects(self): + return self.levelObjects + + def getLevelObjectsDNA(self): + return self.levelObjectsDNA + + def getNumWindows(self): + return self.attributeDictionary.get('numWindows', 0) + + def setNumWindows(self, numWindows): + self.attributeDictionary['numWindows'] = numWindows + + def printWallStyle(self): + if self.selectedLevelObject: + dnaObject = self.selectedLevelObject['DNA'] + if dnaObject.getClassType().eq(DNAFlatBuilding.getClassType()): + self.printWallStyleFor(dnaObject) + + def printWallStyleFor(self, DNAFlatBuilding): + wall = self.getLastWall(DNAFlatBuilding) + cornice = self.getCornice(DNAFlatBuilding) + self.printWallStyleWith(wall, cornice) + + def printWallStyleWith(self, wall, cornice): + if wall: + print 'self.addStyle(styleCount = styleCount + 1)' + print 'wallTexture: ', self.getDNAString(wall) + print 'wallColor: #(', wall.getColor(), ')' + window = self.getWindow(wall,0) + if window & (window.getCount() > 0): + print 'windowTexture: ', self.getDNAString(window) + print 'windowColor: #(', window.getColor(), ')' + else: + print 'windowTexture: None' + print 'windowColor: None' + if cornice: + print 'corniceTexture: ', self.getDNAString(cornice) + print 'corniceColor: #(', cornice.getColor(), ')' + else: + print'corniceTexture: None' + print'corniceColor: None' + + def printWallStyleForBldgWall(self, DNAFlatBuilding,wallNum): + if (DNAFlatBuilding.getClassType().eq(DNAFlatBuilding.getClassType())): + wall = self.getWall(DNAFlatBuilding, wallNum) + cornice = self.getCornice(DNAFlatBuilding) + self.printWallStyleWith(wall,cornice) + + def getPropType(self): + return self.attributeDictionary['propType'] + + def setPropType(self,dnaString): + self.attributeDictionary['propType'] = dnaString + + def getPropTypes(self): + return self.attributeDictionary['propTypes'] + + def getSelectedLevelObject(self): + return self.selectedLevelObject + + def getSnapAngle(self): + return self.snapAngle + + def setSnapAngle(self, aFloat): + self.snapAngle = aFloat + + def getWallColor(self): + return self.attributeDictionary['wallColor'] + + def setWallColor(self,aColor): + self.attributeDictionary['wallColor'] = aColor + + def getWallColors(self): + return self.attributeDictionary['wallColors'] + + def getWallMenu(self): + return wallMenu + + def getWallTexture(self): + return self.attributeDictionary['wallTexture'] + + def getWallTexture(self, dnaString): + self.attributeDictionary['wallTexture'] = dnaString + + def getWallTextures(self): + return self.attributeDictionary['wallTextures'] + + def getWallWidth(self): + return self.attributeDictionary['wallWidth'] + + def setWallWidthVal(self,aFloat): + self.attributeDictionary['wallWidth'] = aFloat + + def setWallWidthString(self, width): + if width == 'fiveFt': + self.setWallWidthVal(5.0) + elif width == 'tenFt': + self.setWallWidthVal(10.0) + elif width == 'fifteenFt': + self.setWallWidthVal(10.0) + elif width == 'twentyFt': + self.setWallWidthVal(10.0) + elif width == 'twentyFiveFt': + self.setWallWidthVal(10.0) + + def getWindowColor(self): + return self.attributeDictionary['windowColor'] + + def getWindowColors(self): + return self.attributeDictionary['windowColors'] + + def getWindowTexture(self): + return self.attributeDictionary['windowTexture'] + + def setWindowTexture(self,dnaString): + self.attributeDictionary['windowTexture'] = dnaString + + def getWindowTextures(self): + return self.attributeDictionary['windowTextures'] + + def acceptArrowKeys(self): + # Accept arrow key events for swinging piece around + self.accept('left', self.keyboardXformNodePath, ['left']) + self.accept('right', self.keyboardXformNodePath, ['right']) + self.accept('up', self.keyboardXformNodePath, ['up']) + self.accept('down', self.keyboardXformNodePath, ['down']) + + def keyboardXformNodePath(self,x): + pass + + def activateLandmarkButtons(self): + # Switch menus to reveal street menu + self.mainMenuDisable() + self.categoryEnable('toon_landmark') + + def activatePropButtons(self): + # Switch menus to reveal street menu + self.mainMenuDisable() + self.categoryEnable('prop') + + def activateStreetModuleButtons(self): + # Switch menus to reveal street menu + self.mainMenuDisable() + self.categoryEnable('street') + + def activateVizObjectsButtons(self): + # Switch menus to reveal viz region menu + #self.mainMenuDisable() + #self.clickBoxDictionary['vizRegionButtons'].enable() + self.accept('addVizRegion', self.addVizRegion) + self.accept('addCollisionSphere', self.addCollisionSphere) + self.grid.setGridSpacing(10.0) + + def activateWallModuleButtons(self): + # Switch menus to reveal street menu + self.mainMenuDisable() + self.categoryEnable('wall') + + def addHook(self, hook, function): + self.accept(hook, function, [hook]) + + def allMenuDisable(self): + self.mainMenuDisable() + self.gridMenuDisable() + self.subMenuDisable() + self.dnaMenuDisable() + + def categoryDisable(self, categoryName): + clickBoxList = self.clickBoxDictionary.set(categoryName,None) + if clickBoxList: + clickBoxList.disable() + + hooks = self.hooksDictionary.get(categoryName, None) + if hooks: + for hook in hooks: + self.ignore(hook) + + # Do any category specific disabilizaton here + if categoryName == 'wall': + clickBoxList = self.clickBoxDictionary.get('wallWidths',None) + if clickBoxList: + clickBoxList.disable() + hooks = self.hooksDictionary.get('wallWidths', None) + if hooks: + for hook in hooks: + self.ignore(hook) + + # Clear out space and insert hooks + self.ignore('space') + self.ignore('insert') + + def categoryEnable(self,categoryName): + # First activate this category's main buttons + """ + clickBoxList = self.clickBoxDictionary.get(categoryName,None) + if clickBoxList: + clickBoxList.enable() + """ + # Now activate hooks and any supplemental actions + if categoryName == 'street': + # activate street module hooks + hooks = self.hooksDictionary.get(categoryName,None) + if hooks: + for hook in hooks: + self.addHook(hook,self.addStreetModule) + elif categoryName == 'wall': + # Activate wall module hooks + hooks = self.hooksDictionary.get(categoryName,None) + if hooks: + for hook in hooks: + self.addHook(hook, self.addFlatBuilding) + """ + # Also activate wall width buttons and hooks + clickBoxList = self.clickBoxDictionary.get('wallWidths', None) + if clickBoxList: + clickBoxList.enable() + """ + hooks = self.hooksDictionary.get('wallWidths',None) + if hooks: + for hook in hooks: + self.addHook(hook,self.wallWidthSym) + elif categoryName == 'toon_landmark': + # activate landmark hooks + hooks = self.hooksDictionary.get(categoryName,None) + if hooks: + for hook in hooks: + self.addHook(hook,self.addLandmark) + elif categoryName == 'prop': + # activate prop hooks + hooks = self.hooksDictionary.get(categoryName,None) + if hooks: + for hook in hooks: + self.addHook(hook,self.addProp) + + def destroy(self): + self.disable() + self.removeNode() + + def disable(self): + self.direct.deselectAll() + self.allMenuDisable() + self.hide() + self.grid.ignore('insert') + self.ignore('mainMenuEnable') + self.ignore('preRemoveNodePath') + self.ignore('preSelectNodePath') + self.ignore('setGroupParent') + self.ignore('isolateNodePath') + self.ignore('reparentNodePath') + self.ignore('createNewLevelGroup') + self.ignore('showAll') + self.ignore('setNodePathName') + self.ignore('p') + self.disableManipulation() + + def disableManipulation(self): + # Ignore arrow keys + self.ignoreArrowKeys() + + # Disable handling of mouse events + self.ignore('handleMouse1') + self.ignore('handleMouse1Up') + self.ignore('handleMouse3') + self.ignore('handleMouse3Up') + + def dnaMenuDisable(self): + # Disable DNA menu + self.clickBoxDictionary['groupButton'].disable() + self.ignore('createNewLevelGroup') + self.clickBoxDictionary['saveButton'].disable() + self.ignore('outputDNA:') + self.clickBoxDictionary['mapButton'].disable() + self.ignore('toggleMapViz') + + def dnaMenuEnable(self): + # Enable DNA menu + self.clickBoxDictionary['groupButton'].enable() + self.accept('createNewLevelGroup', self.createNewLevelGroup) + self.clickBoxDictionary['saveButton'].enable() + self.accept('outputDNA', self.outputDNA) + self.clickBoxDictionary['mapButton'].enable() + self.accept('toggleMapViz', self.toggleMapViz) + + def editDonaldsDock(self): + self.levelMap.setPos(-900.0,-300.0,0.0) + self.useDonaldsDockColors() + self.styleDictionary = ( + self.attributeDictionary['donaldsDockStyleDictionary']) + self.pieMenuDictionary['styleMenu'] = ( + self.pieMenuDictionary['donaldsDockStyleMenu']) + self.attributeDictionary['streetTexture'] = 'street_street_dock_tex' + self.attributeDictionary['sidewalkTexture'] = ( + 'street_sidewalk_dock_tex') + + def editToontownCentral(self): + self.levelMap.setPos(0.0,0.0,0.0) + self.useToontownCentralColors() + self.styleDictionary = ( + self.attributeDictionary['toontownCentralStyleDictionary']) + self.pieMenuDictionary['styleMenu'] = ( + self.pieMenuDictionary['toontownCentralStyleMenu']) + self.attributeDictionary['streetTexture'] = 'street_street_tex' + self.attributeDictionary['sidewalkTexture'] = 'street_sidewalk_tex' + + def enable(self): + #self.allMenuDisable() + #self.mainMenuEnable() + #self.gridMenuEnable() + #self.dnaMenuEnable() + self.show() + self.accept('mainMenuEnable', self.mainMenuEnable) + self.accept('preRemoveNodePath', self.preRemoveNodePath) + self.accept('preSelectNodePath', self.preSelectNodePath) + self.accept('toggleMapViz', self.toggleMapViz) + self.accept('setGroupParent', self.setGroupParent) + self.accept('isolateNodePath', self.isolateNodePath) + self.accept('reparentNodePath', self.reparentNodePath) + self.accept('createNewLevelGroup', self.createNewLevelGroup) + self.accept('setNodePathName', self.setNodePathName) + self.accept('showAll', self.showAll) + self.accept('p',self.plantSelectedNodePath) + self.enableManipulation() + + def enableManipulation(self): + # Enable interactive placement of a nodePath + # Turn off camera control + base.disableMouse() + + # Update arrow key events for swinging selected around + # using the keyboard + self.acceptArrowKeys() + + # Handle mouse events for moving object around + self.accept('handleMouse1',self.levelHandleMouse1) + self.accept('handleMouse1Up',self.levelHandleMouse1Up) + self.accept('handleMouse3',self.levelHandleMouse3) + self.accept('handleMouse3Up',self.levelHandleMouse3Up) + + def gridMenuDisable(self): + self.clickBoxDictionary['gridMenuButtons'].disable() + self.ignore('showGrid') + self.ignore('xyzSnap') + self.ignore('hprSnap') + + def gridMenuEnable(self): + # Enable grid menu + self.clickBoxDictionary['gridMenuButtons'].enable() + self.accept('showGrid', self.showGrid) + self.accept('xyzSnap', self.xyzSnap) + self.accept('hprSnap', self.hprSnap) + + def ignoreArrowKeys(self): + # Accept arrow key events for swinging piece around + self.ignore('left') + self.ignore('right') + self.ignore('up') + self.ignore('down') + + def mainMenuDisable(self): + self.clickBoxDictionary['mainMenuButtons'].disable() + self.ignore('activateWallModuleButtons') + self.ignore('activateStreetModuleButtons') + self.ignore('activateLandmarkButtons') + self.ignore('activatePropButtons') + + def mainMenuEnable(self): + # Make sure all submenus are hidden + self.subMenuDisable() + # Now enable main menu + self.clickBoxDictionary['mainMenuButtons'].enable + self.accept('activateWallModuleButtons', self.activateWallModuleButtons) + self.accept('activateStreetModuleButtons', self.activateStreetModuleButtons) + self.accept('activateLandmarkButtons', self.activateLandmarkButtons) + self.accept('activatePropButtons', self.activatePropButtons) + + def subMenuDisable(self): + for category in self.categorySet: + self.categoryDisable(category) + + def useDonaldsDockColors(self): + self.attributeDictionary['wallColors'] = ( + self.colorPaletteDictionary['donaldsDockWallColors']) + self.attributeDictionary['wallColor'] = ( + self.attributeDictionary['wallColors'][1]) + self.pieMenuDictionary['wallColorMenu'] = ( + self.pieMenuDictionary['donaldsDockWallColors']) + + self.attributeDictionary['windowColors'] = ( + self.colorPaletteDictionary['donaldsDockWindowColors']) + self.attributeDictionary['windowColor'] = ( + self.attributeDictionary['windowColors'][1]) + self.pieMenuDictionary['windowColorMenu'] = ( + self.pieMenuDictionary['donaldsDockWindowColors']) + + self.attributeDictionary['doorColors'] = ( + self.colorPaletteDictionary['donaldsDockDoorColors']) + self.attributeDictionary['doorColor'] = ( + self.attributeDictionary['doorColors'][1]) + self.pieMenuDictionary['doorColorMenu'] = ( + self.pieMenuDictionary['donaldsDockDoorColors']) + + self.attributeDictionary['corniceColors'] = ( + self.colorPaletteDictionary['donaldsDockCorniceColors']) + self.attributeDictionary['corniceColor'] = ( + self.attributeDictionary['corniceColors'][1]) + self.pieMenuDictionary['corniceColorMenu'] = ( + self.pieMenuDictionary['donaldsDockCorniceColors']) + + def useToontownCentralColors(self): + self.attributeDictionary['wallColors'] = ( + self.colorPaletteDictionary['toontownCentralWallColors']) + self.attributeDictionary['wallColor'] = ( + self.attributeDictionary['wallColors'][1]) + self.pieMenuDictionary['wallColorMenu'] = ( + self.pieMenuDictionary['toontownCentralWallColors']) + + self.attributeDictionary['windowColors'] = ( + self.colorPaletteDictionary['toontownCentralWindowColors']) + self.attributeDictionary['windowColor'] = ( + self.attributeDictionary['windowColors'][1]) + self.pieMenuDictionary['windowColorMenu'] = ( + self.pieMenuDictionary['toontownCentralWindowColors']) + + self.attributeDictionary['doorColors'] = ( + self.colorPaletteDictionary['toontownCentralDoorColors']) + self.attributeDictionary['doorColor'] = ( + self.attributeDictionary['doorColors'][1]) + self.pieMenuDictionary['doorColorMenu'] = ( + self.pieMenuDictionary['toontownCentralDoorColors']) + + self.attributeDictionary['corniceColors'] = ( + self.colorPaletteDictionary['toontownCentralCorniceColors']) + self.attributeDictionary['corniceColor'] = ( + self.attributeDictionary['corniceColors'][1]) + self.pieMenuDictionary['corniceColorMenu'] = ( + self.pieMenuDictionary['toontownCentralCorniceColors']) + + def vizMenuDisable(self): + self.clickBoxDictionary['vizRegionButtons'].disable() + self.ignore('addVizRegion') + self.ignore('addCollisionSphere') + self.grid.setGridSpacing(5.0) + + def addCollisionSphere(self): + sphere = self.vizRegion.attachNewNode(NamedNode('vizSphere')) + instance = self.vizSphere.instanceTo(sphere) + instance.setScale(20.0 * math.sqrt(2)) + if (self.vizRegion.getNumChildren() > 1): + sphere.setPos(vizRegion.getChild(vizRegion.getNumChildren() - 2), + 40.0,0.0,0.0) + else: + sphere.setPos(0,0,0) + self.selectNodePath(sphere) + + def addVizRegion(self): + self.vizRegionCount = self.vizRegionCount + 1 + self.vizRegion = self.vizObjects.attachNewNode( + NamedNode('vizRegion' + `self.vizRegionCount`)) + self.addCollisionSphere() + # Start with region selected + self.selectNodePath(vizRegion) + + def setHprSnap(self,flag): + self.hprSnap = flag + + def isolateNodePath(self,aNodePath): + # First show everything in level + self.levelObjects.showAllDescendants() + render.hideCollisionSolids() + aNodePath.hideSiblings() + + def levelHandleMouse1(self): + selectedNodePath = self.direct.selected.last + if selectedNodePath: + self.followMouseStart(selectedNodePath) + + def levelHandleMouse1Up(self): + self.followMouseStop() + + def levelHandleMouse3(self): + # If nothing selected, just return + if not self.direct.selected.last: + return + # Otherwise, find its dictionary entry + self.selectedLevelObject = ( + self.getLevelObject(self.direct.selected.last)) + + # If not None, determine interaction type + if self.selectedLevelObject: + selectedObjectDNA = self.selectedLevelObject['DNA'] + + # Interaction type depends on selected object's class + objClass = selectedObjectDNA.getClassType() + if objClass.eq(DNAFlatBuilding.getClassType()): + # Where are we hitting the building? + hitPt = Point3(0) + if self.getWallIntersectionPoint(hitPt): + xPt = hitPt[0] + zPt = hitPt[2] + # Which wall are we pointing at (if any) + wallNum = self.getWallNum(selectedObjectDNA, zPt) + # How wide is the selected wall? + wallWidth = selectedObjectDNA.getWidth() + # Menu mode depends on where we are pointing + if (zPt > self.getWallHeights(selectedObjectDNA)[-1:]): + menuMode = 'cornice' + else: + if (xPt < 0.0): + menuMode = 'window' + elif (xPt > wallWidth): + menuMode = 'misc' + elif ((xPt >= 0.0) & (xPt <= wallWidth)): + menuMode = 'wall' + if menuMode == 'wall': + if wallNum != -1: + selectedWall = ( + self.getWall(selectedObjectDNA, wallNum)) + # Default is wall type menu + menuType = 'wall' + target = selectedWall + # If alt, switch to wall orientation menu + if self.direct.fAlt: + menuType = 'orientation' + # If control, switch to wall color menu + if self.direct.fControl: + menuType = 'wallColor' + else: + target = None + elif menuMode == 'window': + if wallNum != -1: + selectedWall = ( + self.getWall(selectedObjectDNA, wallNum)) + # Default is window type menu + menuType = 'window' + target = self.getWindow(selectedWall,0) + # If alt, switch to window orientation menu + if self.direct.fAlt: + menuType = 'upOrientation' + if self.direct.fShift: + menuType = 'numWindows' + target = selectedWall + if self.direct.fControl: + menuType = 'windowColor' + elif menuMode == 'cornice': + menuType = 'cornice' + target = self.getCornice(selectedObjectDNA) + if self.direct.fAlt: + menuType = 'upOrientation' + if self.direct.fControl: + menuType = 'corniceColor' + elif menuMode == 'misc': + menuType = 'wallWidth' + target = selectedObjectDNA + if ((wallNum != -1) & (self.direct.fAlt)): + menuType = 'style' + target = self.getWall(selectedObjectDNA,wallNum) + else: + target = None + elif objClass.eq(DNALandmarkBuilding.getClassType()): + menuType = 'door' + target = self.getDoor(selectedObjectDNA) + if self.direct.fAlt: + menuType = 'upOrientation' + if self.direct.fControl: + menuType = 'doorColor' + elif objClass.eq(DNAProp.getClassType()): + menuType = 'propType' + target = selectedObjectDNA + if self.direct.fControl: + menuType = 'propColor' + # Now spawn apropriate menu task + if (target | (menuType == 'cornice')): + self.spawnMenuTask(menuType, target) + + def levelHandleMouse3Up(self): + if self.activeMenu: + self.activeMenu.removePieMenuTask() + + def preSelectNodePath(self, aNodePath): + taskMgr.removeTasksNamed('preselectNodePath') + t = Task.Task(self.preSelectNodePathTask) + t.aNodePath = aNodePath + t.initState = t.hidden = aNodePath.isHidden() + t.count = 0 + t.uponDeath = self.preSelectDone + #taskMgr.spawnTaskNamed(t, 'preselectNodePath') + + def preSelectNodePathTask(self, state): + aNodePath = state.aNodePath + initState = state.initState + hidden = state.hidden + count = t.count + if (t.count < 4): + if hidden: + aNodePath.show() + else: + aNodePath.hide() + t.count = count + 1 + t.hidden = not t.hidden + return Task.cont + else: + return Task.done + + def preSelectDone(self,state): + if state.initState: + state.aNodePath.hide() + else: + state.aNodePath.show() + + def showAll(self): + self.levelObjects.showAllDescendants() + render.hideCollisionSolids() + + def showGrid(self,flag): + if flag: + self.grid.show() + else: + self.grid.hide() + + def spawnMenuTask(self, menu, aDNAObject): + # Record the starting window code and targetDNAObject + # This will be used by pieMenu action selector + self.targetDNAObject = aDNAObject + # What kind of menu is it? + if menu == 'wall': + self.activeMenu = self.pieMenuDictionary['wallMenu'] + state = self.getDNAString(aDNAObject) + elif menu == 'window': + self.activeMenu = self.pieMenuDictionary['windowMenu'] + state = self.getDNAString(aDNAObject) + elif menu == 'orientation': + self.activeMenu = self.pieMenuDictionary['orientationMenu'] + dnaString = self.getDNAString(aDNAObject) + state = dnaString[-3:] + elif menu == 'upOrientation': + self.activeMenu = self.pieMenuDictionary['upOrientationMenu'] + if aDNAObject: + dnaString = self.getDNAString(aDNAObject) + state = dnaString[-3:] + else: + state = None + elif menu == 'numWindows': + self.activeMenu = self.pieMenuDictionary['numWindowsMenu'] + state = self.getWindow(aDNAObject, 0).getCount() + elif menu == 'cornice': + self.activeMenu = self.pieMenuDictionary['corniceMenu'] + if aDNAObject: + state = self.getDNAString(aDNAObject) + else: + state = None + elif menu == 'door': + self.activeMenu = self.pieMenuDictionary['doorMenu'] + state = self.getDNAString(aDNAObject) + elif menu == 'wallWidth': + self.activeMenu = self.pieMenuDictionary['wallWidthMenu'] + state = aDNAObject.getWidth() + elif menu == 'wallColor': + self.activeMenu = self.pieMenuDictionary['wallColorMenu'] + self.activeColors = self.getWallColors() + state = aDNAObject.getColor() + elif menu == 'windowColor': + self.activeMenu = self.pieMenuDictionary['windowColorMenu'] + self.activeColors = self.getWindowColors() + state = aDNAObject.getColor() + elif menu == 'doorColor': + self.activeMenu = self.pieMenuDictionary['doorColorMenu'] + self.activeColors = self.getDoorColors() + state = aDNAObject.getColor() + elif menu == 'corniceColor': + self.activeMenu = self.pieMenuDictionary['corniceColorMenu'] + self.activeColors = self.getCorniceColors() + state = aDNAObject.getColor() + elif menu == 'propColor': + self.activeMenu = self.pieMenuDictionary['wallColorMenu'] + self.activeColors = self.getWallColors() + state = aDNAObject.getColor() + elif menu == 'propType': + self.activeMenu = self.pieMenuDictionary['propTypesMenu'] + state = self.getDNAString(aDNAObject) + elif menu == 'style': + self.activeMenu = self.pieMenuDictionary['styleMenu'] + state = 1 + + # Store initial state in case you need to restore it on menu cancel + self.activeMenu.setInitialState(state) + + # Spawn the menu task + self.activeMenu.spawnPieMenuTask() + + def toggleMapViz(self, flag): + if flag: + self.levelMap.show() + else: + self.levelMap.hide() + + def setXyzSnap(self, flag): + self.grid.setXyzSnap(flag) + if flag: + self.autoPositionGrid() + + def addStyle(self, dictionary, key, wallTexture, wallColor, windowTexture, + windowColor, corniceTexture, corniceColor): + style = {} + style['wallTexture'] = wallTexture + color = VBase4(wallColor) + style['wallColor'] = color + style['windowTexture'] = windowTexture + color = VBase4(windowColor) + style['windowColor'] = color + style['corniceTexture'] = corniceTexture + color = None + if corniceColor: + color = VBase4(corniceColor) + style['corniceColor'] = color + dictionary['key'] = style + + def createColorMenu(self, menuName, colorArray): + # Create the new one + numberNodes = [] + + # Add in common grey scale colors + adjustedColorArray = ( + [VBase4(1,1,1,1)] + + colorArray + + [VBase4(0.75, 0.75, 0.75, 1.0 ), + VBase4(0.5, 0.5, 0.5, 1.0), + VBase4(0.25, 0.25, 0.25, 1.0)] + ) + + for i in range(len(adjustedColorArray)): + node = OnscreenText(' ', 0.0, 0.0) + numberNodes.append(node) + node.setColor(adjustedColorArray[i]) + numItems = len(numberNodes) + + # Attach it to hidden for now + newColorMenu = hidden.attachNewNode(NamedNode(menuName + 'Menu')) + + # Attach the color chips to the new menu and adjust sizes + radius = 0.7 + angle = deg2Rad(360.0/float(numItems)) + for i in range (numItems): + # Get the node + node = numberNodes[i] + node.setScale(node.getScale() * 2.0) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width / self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the wallColorMenu + node.reparentTo(newColorMenu) + + # Scale the whole shebang down by 0.5 + newColorMenu.setScale(0.5) + + # Store menu and colors in appropriate dictionarys + self.pieMenuDictionary[menuName] = ( + PieMenu(self.direct, newColorMenu, self.updateColorIndex)) + self.colorPaletteDictionary[menuName] = adjustedColorArray + + def createColorMenus(self): + self.createColorMenu('toontownCentralWallColors', [ + VBase4((193.0/255.0), (187.0/255.0), (163.0/255.0), 1.0), + VBase4((208.0/255.0), (232.0/255.0), (113.0/255.0), 1.0), + VBase4((230.0/255.0), (144.0/255.0), (86.0/255.0), 1.0), + VBase4((232.0/255.0), (137.0/255.0), (112.0/255.0), 1.0), + VBase4((232.0/255.0), (160.0/255.0), (113.0/255.0), 1.0), + VBase4((240.0/255.0), (90.0/255.0), (90.0/255.0), 1.0), + VBase4((254.0/255.0), (176.0/255.0), (124.0/255.0), 1.0), + VBase4((255.0/255.0), (106.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (180.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (213.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (225.0/255.0), (205.0/255.0), 1.0), + VBase4((255.0/255.0), (234.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (255.0/255.0), (151.0/255.0), 1.0), + VBase4((55.0/255.0), (244.0/255.0), (70.0/255.0), 1.0), + VBase4((27.0/255.0), (203.0/255.0), (56.0/255.0), 1.0), + VBase4((53.0/255.0), (185.0/255.0), (78.0/255.0), 1.0) + ]) + + self.createColorMenu('toontownCentralWindowColors', [ + VBase4((101.0/255.0), (156.0/255.0), (170.0/255.0), 1.0), + VBase4((150.0/255.0), (254.0/255.0), (124.0/255.0), 1.0), + VBase4((232.0/255.0), (160.0/255.0), (113.0/255.0), 1.0), + VBase4((255.0/255.0), (128.0/255.0), (96.0/255.0), 1.0), + VBase4((255.0/255.0), (151.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (160.0/255.0), (96.0/255.0), 1.0), + VBase4((255.0/255.0), (234.0/255.0), (151.0/255.0), 1.0), + VBase4((33.0/255.0), (200.0/255.0), (133.0/255.0), 1.0), + VBase4((69.0/255.0), (255.0/255.0), (106.0/255.0), 1.0), + VBase4((82.0/255.0), (170.0/255.0), (152.0/255.0), 1.0) + ]) + + self.createColorMenu('toontownCentralDoorColors', [ + VBase4((190.0/255.0), (202.0/255.0), (141.0/255.0), 1.0), + VBase4((206.0/255.0), (155.0/255.0), (122.0/255.0), 1.0), + VBase4((255.0/255.0), (151.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (160.0/255.0), (96.0/255.0), 1.0), + VBase4((255.0/255.0), (223.0/255.0), (96.0/255.0), 1.0) + ]) + + self.createColorMenu('toontownCentralCorniceColors', [ + VBase4((113.0/255.0), (232.0/255.0), (160.0/255.0), 1.0), + VBase4((240.0/255.0), (182.0/255.0), (168.0/255.0), 1.0), + VBase4((255.0/255.0), (191.0/255.0), (96.0/255.0), 1.0), + VBase4((255.0/255.0), (255.0/255.0), (151.0/255.0), 1.0), + VBase4((53.0/255.0), (185.0/255.0), (78.0/255.0), 1.0), + VBase4((201.0/255.0), (91.0/255.0), (48.0/255.0), 1.0), + VBase4((193.0/255.0), (187.0/255.0), (163.0/255.0), 1.0), + VBase4((208.0/255.0), (232.0/255.0), (113.0/255.0), 1.0), + VBase4((230.0/255.0), (144.0/255.0), (86.0/255.0), 1.0), + VBase4((232.0/255.0), (137.0/255.0), (112.0/255.0), 1.0), + VBase4((232.0/255.0), (160.0/255.0), (113.0/255.0), 1.0), + VBase4((240.0/255.0), (90.0/255.0), (90.0/255.0), 1.0), + VBase4((254.0/255.0), (176.0/255.0), (124.0/255.0), 1.0), + VBase4((255.0/255.0), (106.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (180.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (213.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (225.0/255.0), (205.0/255.0), 1.0), + VBase4((255.0/255.0), (234.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (255.0/255.0), (151.0/255.0), 1.0), + VBase4((55.0/255.0), (244.0/255.0), (70.0/255.0), 1.0), + VBase4((27.0/255.0), (203.0/255.0), (56.0/255.0), 1.0), + VBase4((53.0/255.0), (185.0/255.0), (78.0/255.0), 1.0) + ]) + + self.createColorMenu('donaldsDockWallColors', [ + VBase4((106.0/255.0), (63.0/255.0), (63.0/255.0), 1.0), + VBase4((160.0/255.0), (120.0/255.0), (60.0/255.0), 1.0), + VBase4((162.0/255.0), (61.0/255.0), (81.0/255.0), 1.0), + VBase4((182.0/255.0), (126.0/255.0), (88.0/255.0), 1.0), + VBase4((192.0/255.0), (115.0/255.0), (114.0/255.0), 1.0), + VBase4((206.0/255.0), (122.0/255.0), (122.0/255.0), 1.0), + VBase4((222.0/255.0), (176.0/255.0), (108.0/255.0), 1.0), + VBase4((236.0/255.0), (39.0/255.0), (39.0/255.0), 1.0), + VBase4((43.0/255.0), (116.0/255.0), (58.0/255.0), 1.0), + VBase4((92.0/255.0), (116.0/255.0), (56.0/255.0), 1.0) + ]) + + self.createColorMenu('donaldsDockWindowColors', [ + VBase4((0.0/255.0), (156.0/255.0), (93.0/255.0), 1.0), + VBase4((164.0/255.0), (238.0/255.0), (116.0/255.0), 1.0), + VBase4((202.0/255.0), (120.0/255.0), (120.0/255.0), 1.0), + VBase4((210.0/255.0), (210.0/255.0), (102.0/255.0), 1.0), + VBase4((224.0/255.0), (109.0/255.0), (109.0/255.0), 1.0), + VBase4((232.0/255.0), (87.0/255.0), (116.0/255.0), 1.0), + VBase4((255.0/255.0), (128.0/255.0), (96.0/255.0), 1.0) + ]) + + self.createColorMenu('donaldsDockDoorColors', [ + VBase4((115.0/255.0), (136.0/255.0), (115.0/255.0), 1.0), + VBase4((132.0/255.0), (156.0/255.0), (132.0/255.0), 1.0), + VBase4((152.0/255.0), (172.0/255.0), (138.0/255.0), 1.0), + VBase4((202.0/255.0), (120.0/255.0), (120.0/255.0), 1.0), + VBase4((220.0/255.0), (123.0/255.0), (59.0/255.0), 1.0), + VBase4((224.0/255.0), (109.0/255.0), (109.0/255.0), 1.0), + VBase4((232.0/255.0), (87.0/255.0), (87.0/255.0), 1.0), + VBase4((255.0/255.0), (151.0/255.0), (151.0/255.0), 1.0) + ]) + + self.createColorMenu('donaldsDockCorniceColors', [ + VBase4((146.0/255.0), (98.0/255.0), (86.0/255.0), 1.0), + VBase4((151.0/255.0), (255.0/255.0), (234.0/255.0), 1.0), + VBase4((192.0/255.0), (114.0/255.0), (114.0/255.0), 1.0), + VBase4((194.0/255.0), (145.0/255.0), (73.0/255.0), 1.0), + VBase4((240.0/255.0), (182.0/255.0), (168.0/255.0), 1.0), + VBase4((193.0/255.0), (187.0/255.0), (163.0/255.0), 1.0), + VBase4((208.0/255.0), (232.0/255.0), (113.0/255.0), 1.0), + VBase4((230.0/255.0), (144.0/255.0), (86.0/255.0), 1.0), + VBase4((232.0/255.0), (137.0/255.0), (112.0/255.0), 1.0), + VBase4((232.0/255.0), (160.0/255.0), (113.0/255.0), 1.0), + VBase4((240.0/255.0), (90.0/255.0), (90.0/255.0), 1.0), + VBase4((254.0/255.0), (176.0/255.0), (124.0/255.0), 1.0), + VBase4((255.0/255.0), (106.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (180.0/255.0), (69.0/255.0), 1.0), + VBase4((255.0/255.0), (213.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (225.0/255.0), (205.0/255.0), 1.0), + VBase4((255.0/255.0), (234.0/255.0), (151.0/255.0), 1.0), + VBase4((255.0/255.0), (255.0/255.0), (151.0/255.0), 1.0), + VBase4((55.0/255.0), (244.0/255.0), (70.0/255.0), 1.0), + VBase4((27.0/255.0), (203.0/255.0), (56.0/255.0), 1.0), + VBase4((53.0/255.0), (185.0/255.0), (78.0/255.0), 1.0) + ]) + # Use the toontown color set + self.useToontownCentralColors() + + def createCorniceMenu(self): + # Get the currently available window options + numItems = len(self.getCorniceTextures()) + + newCorniceMenu = hidden.attachNewNode(NamedNode('corniceMenu')) + + # Attach an empty node for first item + newCorniceMenu.attachNewNode(NamedNode('no cornice')) + + angle = deg2Rad(360.0/numItems) + # Note: start at 2 to skip first item (none) + for i in range(1, numItems): + # Get the node + node = self.dnaStore.findNode(self.getCorniceTextures()[i]) + + # Add it to the window menu + path = node.instanceTo(newCorniceMenu) + + # Place menu nodes in a circle, offset each in X and Z + # by half node width/height (.5 * path scale) + path.setPos(0.75 * math.cos(i * angle), + 0.0, + (0.75 * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + path.setScale(0.5) + + # Scale the whole shebang down by 0.5 + newCorniceMenu.setScale(0.5) + + return newCorniceMenu + + def createDoorMenu(self): + # Get the currently available door options + numItems = len(self.getDoorTextures()) + + newDoorMenu = hidden.attachNewNode(NamedNode('doorMenu')) + + angle = deg2Rad(360.0/float(numItems)) + for i in range(numItems): + # Get the node + node = self.dnaStore.findNode(self.getDoorTextures()[i]) + + # Add it to the door menu + path = node.instanceTo(newDoorMenu) + + # Place menu nodes in a circle, offset each in X and Z + # by half node width/height (.5 * path scale) + path.setPos(0.75 * math.cos(i * angle) - 0.025, + 0.0, + ((0.75 * + (self.direct.chan.width/ + self.direct.chan.height) * + math.sin(i * angle)) - 0.025)) + path.setScale(0.05) + + # Scale the whole shebang down by 0.5 + newDoorMenu.setScale(0.5) + + return newDoorMenu + + def createNumWindowsMenu(self): + + numberNodes = [] + for i in range(4): + node = OnscreenText(`i`, 0.0, 0.0) + numberNodes.append(node) + numItems = len(numberNodes) + + newNumWindowsMenu = hidden.attachNewNode(NamedNode('numWindowsMenu')) + + radius = 0.7 + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + # Get the node + node = numberNodes[i] + node.setScale(node.getScale() * 4.0) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the numWindowsMenu + node.reparentTo(newNumWindowsMenu) + + # Scale the whole shebang down by 0.5 + newNumWindowsMenu.setScale(0.5) + + return newNumWindowsMenu + + def createOrientationMenu(self): + newOrientationMenu = hidden.attachNewNode(NamedNode('orientationMenu')) + + radius = 0.5 + + node = OnscreenText('UR',radius,radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newOrientationMenu) + + node = OnscreenText('UL',-radius,radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newOrientationMenu) + + node = OnscreenText('DL',-radius, -radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newOrientationMenu) + + node = OnscreenText('DR',radius,-radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newOrientationMenu) + + # Scale the whole shebang down by radius + newOrientationMenu.setScale(radius) + + return newOrientationMenu + + def createPropTypesMenu(self): + numItems = len(self.getPropTypes()) + + propNodes = [] + for i in range (numItems): + node = OnscreenText(self.getPropTypes()[i],0,0) + propNodes.append(node) + + newPropTypeMenu = hidden.attachNewNode(NamedNode('propTypeMenu')) + + radius = 0.7 + angle = deg2Rad(360.0/numItems) + for i in range (numItems): + # Get the node + node = propNodes[i] + node.setScale(node.getScale()) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the propTypeMenu + node.reparentTo(newPropTypeMenu) + + # Scale the whole shebang down by 0.5 + newPropTypeMenu.setScale(0.5) + + return newPropTypeMenu + + def createStyleMenu(self): + numberNodes = [] + for i in range(13): + node = OnscreenText(`i`,0,0) + numberNodes.append(node) + numItems = len(numberNodes) + + newStyleMenu = hidden.attachNewNode(NamedNode('styleMenu')) + + radius = 0.7 + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + # Get the node + node = numberNodes[i] + node.setScale(node.getScale()* 4.0) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the styleMenu + node.reparentTo(newStyleMenu) + + # Scale the whole shebang down by 0.5 + newStyleMenu.setScale(0.5) + + return newStyleMenu + + def createStyleMenuWith(self, dictionary): + numberNodes = [] + numItems = len(dictionary) + for i in range(numItems): + node = OnscreenText(`i`,0,0) + numberNodes.append(node) + + newStyleMenu = hidden.attachNewNode(NamedNode('styleMenu')) + + radius = 0.7 + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + # Get the node + node = numberNodes[i] + node.setScale(node.getScale()* 3.0) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the styleMenu + node.reparentTo(newStyleMenu) + + # Scale the whole shebang down by 0.5 + newStyleMenu.setScale(0.5) + + return newStyleMenu + + def createUpOrientationMenu(self): + newUpOrientationMenu = ( + hidden.attachNewNode(NamedNode('upOrientationMenu'))) + + radius = 0.5 + + node = OnscreenText('UR',radius, radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newUpOrientationMenu) + + node = OnscreenText('UL',-radius, radius) + node.setScale(node.getScale() * 3.0) + node.reparentTo(newUpOrientationMenu) + + node = newUpOrientationMenu.attachNewNode(NamedNode('hiddenNode')) + node.setScale(node.getScale() * 3.0) + + node = newUpOrientationMenu.attachNewNode(NamedNode('hiddenNode')) + node.setScale(node.getScale() * 3.0) + + # Scale the whole shebang down by radius + newUpOrientationMenu.setScale(radius) + + return newUpOrientationMenu + + def createWallMenu(self): + numItems = len(self.getWallTextures()) + + newWallMenu = hidden.attachNewNode(NamedNode('wallMenu')) + + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + node = self.dnaStore.findNode(self.getWallTextures()[i]) + path = node.instanceTo(newWallMenu) + # Place menu nodes in a circle, offset each in X and Z by + # half node width/height (.5 * path scale) + path.setPos(0.75 * math.cos(i * angle) - 0.15, + 0.0, + (0.75 * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle) - 0.15)) + path.setScale(0.3) + + # Scale the whole shebang down by 0.5 + newWallMenu.setScale(0.5) + return newWallMenu + + def createWallWidthMenu(self): + numberNodes = [] + for i in range(5): + node = OnscreenText(`(i * 5)`,0,0) + numberNodes.append(node) + numItems = len(numberNodes) + + newWallWidthMenu = hidden.attachNewNode(NamedNode('wallWidthMenu')) + + radius = 0.7 + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + # Get the node + node = numberNodes[i] + node.setScale(node.getScale()* 4.0) + + # Reposition it + node.setXY(radius * math.cos(i * angle), + (radius * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle))) + + # Add it to the wallWidthMenu + node.reparentTo(newWallWidthMenu) + + # Scale the whole shebang down by 0.5 + newWallWidthMenu.setScale(0.5) + + return newWallWidthMenu + + def createWindowMenu(self): + # Get the currently available window options + numItems = len(self.getWindowTextures()) + + newWindowMenu = hidden.attachNewNode(NamedNode('windowMenu')) + + angle = deg2Rad(360.0/numItems) + for i in range(numItems): + # Get the node + node = self.dnaStore.findNode(self.getWindowTextures()[i]) + + # Add it to the window menu + path = node.instanceTo(newWindowMenu) + + # Place menu nodes in a circle, offset each in X and Z by + # half node width/height (.5 * path scale) + path.setPos(0.75 * math.cos(i * angle) - 0.05, + 0.0, + (0.75 * + (self.direct.chan.width/self.direct.chan.height) * + math.sin(i * angle) - 0.05)) + path.setScale(0.1) + + # Scale the whole shebang down by 0.5 + newWindowMenu.setScale(0.5) + + return newWindowMenu + + def initializeDonaldsDockStyleDictionary(self): + dictionary = {} + styleCount = 0 + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_bricks_ur', + Vec4(0.627, 0.470,0.235,1.0), + 'window_sm_shuttered_ur', + Vec4(1.0, 0.501, 0.376, 1.0), + 'cornice_stone_ur', + Vec4(0.760, 0.568, 0.286, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_board_ur', + Vec4(0.713,0.494,0.345,1.0 ), + 'window_porthole_ur', + Vec4(1.0, 0.501, 0.376, 1.0), + 'cornice_shingles_ur', + Vec4(0.572, 0.384, 0.337, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_board_ur', + Vec4(0.925,0.152,0.152,1.0 ), + 'window_sm_round_ur', + Vec4(0.643, 0.933, 0.454, 1.0), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_board_ur', + Vec4(0.925, 0.152, 0.152, 1.0 ), + 'window_porthole_ur', + Vec4(0.0, 0.611, 0.364, 1.0), + 'cornice_shingles_ur', + Vec4(0.760, 0.568, 0.286, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_board_ur', + Vec4(0.713,0.494,0.345,1.0), + 'window_sm_square_ur', + Vec4(0.823, 0.823, 0.400, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_lg_rock_ur', + Vec4(0.752, 0.450, 0.447, 1.0), + 'window_sm_round_ur', + Vec4(0.823, 0.823, 0.400, 1.0), + 'cornice_brick_ur', + Vec4(0.760, 0.568, 0.286, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_red_ur', + Vec4(0.415, 0.933, 0.454, 1.0 ), + 'cornice_marble_ur', + Vec4(0.643, 0.933, 0.454, 1.0), + 'cornice_marble_ur', + Vec4(0.643, 0.933, 0.454, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_sm_wood_ur', + Vec4(0.713, 0.494, 0.345, 1.0 ), + 'window_sm_shuttered_ur', + Vec4(0.878, 0.427, 0.427, 1.0 ), + 'cornice_shingles_ur', + Vec4(0.760, 0.568, 0.286, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_bricks_ur', + Vec4(0.168, 0.454, 0.227, 1.0 ), + 'window_sm_round_ur', + Vec4(0.643, 0.933, 0.454, 1.0), + 'cornice_horizontal_ur', + Vec4(0.752, 0.447, 0.447, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_sm_wood_ur', + Vec4(0.713, 0.494, 0.345, 1.0 ), + 'window_porthole_ur', + Vec4(1.0, 0.501, 0.376, 1.0 ), + 'cornice_shingles_ur', + Vec4(0.75, 0.75, 0.75, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_md_red_ur', + Vec4(0.415, 0.247, 0.247, 1.0 ), + 'window_sm_round_ur', + Vec4(0.643, 0.933, 0.454, 1.0 ), + 'cornice_dental_ur', + Vec4(0.572, 0.384, 0.337, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount , + 'wall_md_board_ur', + Vec4(0.925, 0.152, 0.152, 1.0 ), + 'window_porthole_ur', + Vec4(0.0, 0.611, 0.364, 1.0 ), + 'cornice_shingles_ur', + Vec4(0.941, 0.713, 0.658, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall_lg_brick_dr', + Vec4(0.168, 0.454, 0.227, 1.0 ), + 'window_md_curtains_ur', + Vec4(0.75, 0.75, 0.75, 1.0 ), + 'cornice_dental_ur', + Vec4(0.5, 0.5, 0.5, 1.0 )) + + # Store this dictionary in the self.attributeDictionary + self.attributeDictionary['donaldsDockStyleDictionary'] = dictionary + + def initializeLandmarkButtons(self): + # Initialize Hooks and Buttons for the wall type buttons + landmarkTypes = self.getCatalogCodes('toon_landmark') + methodArray = [] + for landmark in landmarkTypes: + methodArray.append( + [landmark[15:len(landmark)], landmark]) + + hooksSet = self.hooksDictionary.get('toon_landmark',[]) + for pair in methodArray: + hooksSet.append(pair[1]) + self.hooksDictionary['toon_landmark'] = hooksSet + + # Create wall module buttons + # First get rid of any existing buttons + buttons = self.clickBoxDictionary.get('toon_landmark', None) + if buttons: + buttons.disable() + buttons = ClickBoxList(methodArray, 0.95, 0.90) + buttons.addButtonWithText('back',self.mainMenuEnable) + buttons.alignRight() + buttons.setScale(0.06) + buttons.setColor(0.6, 0.6, 0.6, 0.8) + self.clickBoxDictionary['landmarkSym'] = buttons + + self.categorySet.append(landmarkSym) + + def initializeLevelEditorButtons(self): + newClickBoxObject = ToggleBoxList( + [('Show Grid', self.showGrid, 0) + ('XYZ Snap', self.xyzSnap, 1), + ('HPR Snap', self.hprSnap, 1)], + -0.95, 0.90) + newClickBoxObject.alignLeft() + newClickBoxObject.setScale(0.06) + newClickBoxObject.makeAllWideAsWidest() + newClickBoxObject.enable() + self.clickBoxDictionary['gridMenuButtons'] = newClickBoxObject + + newClickBoxObject = ClickBoxList( + [('Street modules', self.activateStreetModuleButtons), + ('Toon Walls', self.activateWallModuleButtons), + ('Landmark bldgs', self.activateLandmarkButtons), + ('Props', self.activatePropButtons)], + 0.95, 0.90) + newClickBoxObject.setColor(0.5, 0.5, 0.5, 0.5) + newClickBoxObject.setScale(0.06) + newClickBoxObject.alignRight() + self.clickBoxDictionary['mainMenuButtons'] = newClickBoxObject + + newClickBoxObject = ClickBox( + 'New Group', 0.3, 0.3, -0.95, -0.9, + self.createNewLevelGroup, 0) + newClickBoxObject.nodePath().node().setCardColor(Point4(1,1,1,.5)) + newClickBoxObject.setScale(0.05) + self.clickBoxDictionary['groupButton'] = newClickBoxObject + + newClickBoxObject = ClickBox( + 'Save DNA', 0.3, 0.3, -0.7, -0.9, + self.outputDNA, ['toontown.dna'],0) + newClickBoxObject.nodePath().node().setCardColor(Point4(1,1,1,.5)) + newClickBoxObject.setScale(0.05) + self.clickBoxDictionary['saveButton'] = newClickBoxObject + + newClickBoxObject = ToggleBox( + 'Level Map', 0.3, 0.3, -0.47, -0.9, + self.toggleMapViz, [], 0) + newClickBoxObject.nodePath().node().setCardColor(Point4(1,1,1,.5)) + newClickBoxObject.setButtonState(0) + newClickBoxObject.setScale(0.05) + self.clickBoxDictionary['mapButton'] = newClickBoxObject + + self.dnaMenuEnable() + + # Initialize module Dictionary with pointers to module + # node paths and create module buttons + self.initializeStreetButtons() + self.initializeWallButtons() + self.initializeLandmarkButtons() + self.initializePropButtons() + + def initializePieMenus(self): + # Clear out any old menus just in case + for key in self.pieMenuDictionary.keys(): + oldMenu = self.pieMenuDictionary[key] + oldMenu.reparentTo(hidden) + oldMenu.removeNode() + + # Get list of available attributes + self.initializeAttributeDictionary() + + # Create pop-up pie menus + self.pieMenuDictionary['wallMenu'] = ( + PieMenu(self.direct, self.createWallMenu(), self.updateWallTextureNum)) + + self.pieMenuDictionary['windowMenu'] = ( + PieMenu(self.direct, self.createWindowMenu(), self.updateWindowTextureNum)) + + menu = PieMenu(self.direct, self.createOrientationMenu(), + self.updateOrientationNum) + # Clear angle offset on this menu + menu.setItemOffset(0.0) + self.pieMenuDictionary['orientationMenu'] = menu + + menu = PieMenu(self.direct, self.createUpOrientationMenu(), + self.updateOrientationNum) + # Clear angle offset on this menu + menu.setItemOffset(0.0) + self.pieMenuDictionary['upOrientationMenu'] = menu + + self.pieMenuDictionary['numWindowsMenu'] = ( + PieMenu(self.direct, self.createNumWindowsMenu(), + self.updateNumWindows)) + self.pieMenuDictionary['corniceMenu'] = ( + PieMenu(self.direct,self.createCorniceMenu(), + self.updateCorniceTextureNum)) + self.pieMenuDictionary['doorMenu'] = ( + PieMenu(self.direct,self.createDoorMenu(), + self.updateDoorTextureNum)) + self.pieMenuDictionary['wallWidthMenu'] = ( + PieMenu(self.direct,self.createWallWidthMenu(), + self.updateWallWidthSF)) + self.pieMenuDictionary['propTypesMenu'] = ( + PieMenu(self.direct,self.createPropTypesMenu(), + self.updatePropNum)) + self.pieMenuDictionary['toontownCentralStyleMenu'] = ( + PieMenu(self.direct,self.createStyleMenuWith( + self.attributeDictionary['toontownCentralStyleDictionary']), + self.updateWallStyleNum)) + self.pieMenuDictionary['donaldsDockStyleMenu'] = ( + PieMenu(self.direct,self.createStyleMenuWith( + self.attributeDictionary['donaldsDockStyleDictionary']), + self.updateWallStyleNum)) + self.pieMenuDictionary['styleMenu'] = ( + self.pieMenuDictionary['toontownCentralStyleMenu']) + # Create several differnt color palette menus + self.createColorMenus() + + def initializeStyleDictionary(self): + self.initializeToontownCentralStyleDictionary() + self.initializeDonaldsDockStyleDictionary() + self.styleDictionary = ( + self.attributeDictionary['toontownCentralStyleDictionary']) + + def initializeToontownCentralStyleDictionary(self): + + dictionary = {} + styleCount = 0 + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + 'window=sm=pointed_ur', + Vec4(0.396, 0.611, 0.666, 1.0 ), + 'cornice=stone_ur', + Vec4(1.0, 1.0, 0.592, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=lg=brick_ur', + Vec4(1.0, 0.705, 0.270, 1.0 ), + 'window=sm=round_ur', + Vec4(0.588, 0.996, 0.486, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=lg=brick_ur', + Vec4(1.0, 0.415, 0.270, 1.0 ), + 'window=porthole_ur', + Vec4(0.129, 0.784, 0.521, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=sm=cement_ur', + Vec4(1.0, 0.882, 0.803, 1.0 ), + 'window=sm=round_ur', + Vec4(0.270, 1.0, 0.415, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=dental_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + 'window=md=curved_ur', + Vec4(1.0, 0.627, 0.376, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=lg=brick_ur', + Vec4(0.901, 0.564, 0.337, 1.0 ), + 'window=sm=round_ur', + Vec4(0.588, 0.996, 0.486, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(0.996, 0.690, 0.486, 1.0 ), + 'window=porthole_ur', + Vec4(0.909, 0.627, 0.443, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=sm=brick_ur', + Vec4(1.0, 0.835, 0.592, 1.0 ), + 'window=sm=pointed_ur', + Vec4(1.0, 0.627, 0.376, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=yellow_ur', + Vec4(0.901, 0.564, 0.337, 1.0 ), + 'window=sm=pointed_ur', + Vec4(0.321, 0.666, 0.596, 1.0 ), + 'cornice=stone_ur', + Vec4(0.941, 0.713, 0.658, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(0.815, 0.909, 0.443, 1.0 ), + 'window=sm=round_ur', + Vec4(0.588, 0.996, 0.486, 1.0 ), + 'cornice=stone_ur', + Vec4(1.0, 1.0, 0.592, 1.0)) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=dental_ur', + Vec4(0.909, 0.627, 0.443, 1.0 ), + 'window=sm=round_ur', + Vec4(0.588, 0.996, 0.486, 1.0 ), + None, + None) + + + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(1.0, 0.882, 0.803, 1.0 ), + 'window=sm=curved_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(1.0, 0.882, 0.803, 1.0 ), + 'window=porthole_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + None, + None) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=pillars_ur', + Vec4(1.0, 0.882, 0.803, 1.0 ), + 'window=sm=round_ur', + Vec4(0.588, 0.996, 0.486, 1.0 ), + 'cornice=stone_ur', + Vec4(1.0, 1.0, 1.0, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=bricks_ur', + Vec4(1.0,0.835, 0.592, 1.0 ), + 'window=sm=shuttered_ur', + Vec4(1.0, 1.0, 1.0, 1.0 ), + 'cornice=marble_ur', + Vec4(1.0, 1.0, 0.592, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=yellow_ur', + Vec4(1.0, 0.835, 0.592, 1.0 ), + 'window=sm=shuttered_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + 'cornice=dental_ur', + Vec4(1.0, 1.0, 0.592, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=yellow_ur', + Vec4(1.0, 0.835, 0.592, 1.0 ), + 'window=sm=round_ur', + Vec4(1.0, 0.627, 0.376, 1.0 ), + 'cornice=dental_ur', + Vec4(1.0, 0.749, 0.376, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(dictionary, styleCount, + 'wall=md=yellow_ur', + Vec4(1.0,0.917, 0.592, 1.0 ), + 'window=sm=pointed_ur', + Vec4(1.0, 1.0, 1.0, 1.0 ), + 'cornice=marble_ur', + Vec4(0.443, 0.909, 0.627, 1.0 )) + + styleCount = styleCount + 1 + self.addStyle(self.styleDictionary, styleCount, + 'wall=md=yellow_ur', + Vec4(1.0, 0.917, 0.592, 1.0 ), + 'window=sm=curved_ur', + Vec4(1.0, 0.627, 0.376, 1.0 ), + None, + None) + + self.attributeDictionary['toontownCentralStyleDictionary'] = dictionary + + #XXXX + + def addDNAGroup(self,dnaGroup): + # Add hook to allow placement of a new dna Group of this type + # by simply hitting the space bar + # First clear out old hooks just to be safe + self.ignore('insert') + # Now add new hook + self.accept('insert', self.initNewDNAGroupWithParent, + [dnaGroup, self.groupParent]) + + # Now add the first copy of this Group + self.initDNAGroupWithParent(dnaGroup,self.groupParent) + + def addDNAGroupType(self, dnaGroup, type): + # Add hook to allow placement of a new dna Group of this type + # by simply hitting the space bar + # First clear out old hooks just to be safe + self.ignore('insert') + # Now add new hook + self.accept('insert', + self.addFlatBuilding, + [type]) + # First clear out old hooks just to be safe + self.ignore('space') + self.accept('space', + initNewDNAGroupWithParentType, + [dnaGroup, self.groupParent, type]) + + # Now add the first copy of this Group + self.initDNAGroupWithParentType(dnaGroup, self.groupParent, type) + + def addDNAGroupTypeMethod(self, dnaGroup, type, method): + + # Add hook to allow placement of a new dna Group of this type + # by simply hitting the space bar + # First clear out old hooks just to be safe + self.ignore('insert') + + # Now add new hooks + # Insert key generates random version + self.accept('insert', method, [type]) + + # Space bar creates a copy + self.ignore('space') + self.accept('space', self.initNewDNAGroupWithParentType, + [dnaGroup, self.groupParent, type]) + + # Now add the first copy of this Group + self.initDNAGroupWithParentType(dnaGroup, self.groupParent, type) + + def addFlatBuilding(self, buildingType): + # Create new building + newDNAFlatBuilding = DNAFlatBuilding(buildingType) + + # Select walls + if buildingType == 'random20': + selectedType = self.selectBuildingType('twenty') + elif buildingType == 'random30': + selectedType = self.selectBuildingType('thirty') + else: + selectedType = buildingType + + if selectedType == 'toonTenTen': + self.setBuildingHeight(20.0) + newDNAFlatBuilding.add(self.createWall(10.0)) + newDNAFlatBuilding.add(self.createWall(10.0)) + elif selectedType == 'toonTwenty': + self.setBuildingHeight(20.0) + newDNAFlatBuilding.add(self.createWall(20.0)) + elif selectedType == 'toonTenTwenty': + self.setBuildingHeight(30.0) + newDNAFlatBuilding(self.createWall(10.0)) + newDNAFlatBuilding(self.createWall(20.0)) + elif selectedType == 'toonTwentyTen': + self.setBuildingHeight(30.0) + newDNAFlatBuilding(self.createWall(20.0)) + newDNAFlatBuilding(self.createWall(10.0)) + elif selectedType == 'toonTenTenTen': + self.setBuildingHeight(30.0) + newDNAFlatBuilding(self.createWall(10.0)) + newDNAFlatBuilding(self.createWall(10.0)) + newDNAFlatBuilding(self.createWall(10.0)) + elif selectedType == 'toonTenTwenty': + newDNAFlatBuilding(self.createWall(10.0)) + newDNAFlatBuilding(self.createWall(20.0)) + elif selectedType == 'toonTwentyTen': + newDNAFlatBuilding(self.createWall(20.0)) + newDNAFlatBuilding(self.createWall(10.0)) + elif selectedType == 'toonThirty': + newDNAFlatBuilding(self.createWall(30.0)) + + # Pick a style for this building + self.setRandomBuildingStyle(newDNAFlatBuilding) + + # Initialize its position and hpr + newDNAFlatBuilding.setPos(VBase3(0)) + newDNAFlatBuilding.setHpr(VBase3(0)) + + # Now place new building in the world + self.addDNAGroupTypeMethod(newDNAFlatBuilding,buildingType, + self.addFlatBuilding) + + def addLandmark(self, landmarkType): + newDNALandmarkBuilding = DNALandmarkBuilding(landmarkType) + newDNALandmarkBuilding.setCode(self.getDNACode(landmarkType)) + newDNALandmarkBuilding.setPos(VBase3(0)) + newDNALandmarkBuilding.setHpr(VBase3(self.lastAngle,0.0,0.0)) + newDNADoor = self.createDoor(self.doorTexture) + newDNALandmarkBuilding.add(newDNADoor) + # Now place new building in the world + self.addDNAGroup(newDNALandmarkBuilding) + + def addObject(self, aNodePath, dnaGroup): + # Add specified node path to the scene dictionary + objectDictionary = {} + objectDictionary['nodePath'] = aNodePath + objectDictionary['DNA'] = dnaGroup + self.levelDictionary[aNodePath.node().this] = objectDictionary + return objectDictionary + + def addProp(self, newPropType): + newDNAProp = DNAProp(newPropType) + newDNAProp.setCode(self.getDNACode(newPropType)) + newDNAProp.setPos(VBase3(0)) + newDNAProp.setHpr(VBase3(self.lastAngle,0.0,0.0)) + # Now place new building in the world + self.addDNAGroup(newDNAProp) + self.propType(newPropType) + + def addStreetModule(self, streetType): + newDNAStreet = DNAStreet(streetType) + newDNAStreet.setCode(self.getDNACode(streetType)) + newDNAStreet.setPos(VBase3(0)) + newDNAStreet.setHpr(VBase3(self.lastAngle, 0.0, 0.0)) + newDNAStreet.setStreetTexture( + self.getDNACode(self.attributeDictionary['streetTexture'])) + newDNAStreet.setSidewalkTexture( + self.getDNACode(self.attributeDictionary['sidewalkTexture'])) + # Now place new building in the world + self.addDNAGroup(newDNAStreet) + + def addWall(self, dnaString, height): + # Create the DNA for this wall + newDNAWall = self.createWallWithDNA(dnaString, height) + # Pick a default window + newDNAWindows = DNAWindows() + self.windowTexture(self.getRandomWindowTexture()) + newDNAWindows.setCode(self.getDNACode(self.windowTexture)) + newDNAWindows.setCount(self.getRandomNumWindows(height)) + # MRM Need to randomize + newDNAWindows.setColor(self.getWallColors()) + newDNAWall.add(newDNAWindows) + return newDNAWall + + def createCornice(self,dnaString): + newDNACornice = DNACornice() + newDNACornice.setCode(self.getDNACode(dnaString)) + # MRM Need to randomize + newDNACornice.setColor(self.getCorniceColors()) + return newDNACornice + + def createDoor(self, dnaString): + newDNADoor = DNADoor() + newDNADoor.setCode(self.getDNACode(dnaString)) + # MRM Need to randomize + newDNADoor.setColor(self.getDoorColors()) + return newDNADoor + + def createNewLevelGroup(self): + newGroupParentDNA = DNAGroup('group=' + `self.groupNum`) + # Add it to the level objects + self.groupParentDNA.add(newGroupParentDNA) + + # Make the new one be the current one + self.groupParentDNA = newGroupParentDNA + + newGroupParent = self.groupParentDNA.traverse( + self.groupParent, self.dnaStore) + + self.groupParent = newGroupParent + + self.groupNum = self.groupNum + 1 + + # Add it to the level dictionary + self.addObject(self.groupParent, self.groupParentDNA) + + def createTopLevelGroup(self): + # Create a new top level group + self.groupParentDNA = DNAGroup('rootNode') + self.groupNum = 0 + + # Add it to the level objects + self.levelObjectsDNA.add(self.groupParentDNA) + self.groupParent = self.groupParentDNA.traverse( + self.levelObjects, self.dnaStore) + + # Add it to the level dictionary + self.addObject(self.groupParent, self.groupParentDNA) + + def createWall(self, height): + return self.createWallWithDNA(self.getWallTexture(), height) + + def createWallWithDNA(self, dnaString, height): + # Create a new DNAWall using default attributes + # Create the DNA for this wall + newDNAWall = DNAWall() + newDNAWall.setCode(self.getDNACode(dnaString)) + newDNAWall.setHeight(height) + newDNAWall.setColor(self.getWallColor()) + + # Pick a default window + newDNAWindows = DNAWindows() + newDNAWindows.setCode(self.getDNACode(self.windowTexture)) + newDNAWindows.setCount(1) + newDNAWindows.setColor(self.windowColor) + newDNAWall.add(newDNAWindows) + + return newDNAWall + + def createWindows(self, numWindows): + newDNAWindows = DNAWindows() + newDNAWindows.setCode(self.getDNACode(self.windowTexture)) + newDNAWindows.setCount(numWindows) + newDNAWindows.setColor(self.windowColor) + return newDNAWindows + + def getCatalogCodes(self, category): + numCodes = self.dnaStore.getNumCatalogCodes(category) + codes = [] + for i in range(numCodes): + codes.append(self.dnaStore.getCatalogCode(category, i)) + return codes + + def getCatalogCodesSuffix(self, category, suffix): + codes = self.getCatalogCodes(category) + orientedCodes = [] + for code in codes: + if code[-3:] == suffix: + orientedCodes.append(code) + return orientedCodes + + def getCornice(self, aDNAFlatBuilding): + lastWall = self.getLastWall(aDNAFlatBuilding) + if lastWall: + for i in range(lastWall.getNumChildren()): + child = lastWall[i] + if child.getClassType().eq(DNACornice.getClassType()): + return child + # Not found + return None + + def getDNACode(self, dnaString): + dnaCode = self.dnaStore.findCode(dnaString) + if dnaCode == 0: + print 'getDNACode Error!' + return dnaCode + + def getDNAGroup(self, aNodePath): + dict = self.getLevelObject(aNodePath) + if dict: + return dict['DNA'] + else: + return None + + def getDNAString(self, aDNAObject): + return (self.dnaStore.findStringFromCode(aDNAObject.getCode())) + + def getDoor(self, aDNAGroup): + for i in range(aDNAGroup.getNumChildren()): + child = aDNAGroup[i] + # MRM CLASS INFO? + if child.getClassType().eq(DNADoor.getClassType()): + return child + # Not found + return None + + def getLastWall(self, aDNAFlatBuilding): + lastWall = None + for i in range(aDNAFlatBuilding.getNumChildren()): + child = aDNAFlatBuilding[i] + if child.getClassType().eq(DNAWall.getClassType()): + lastWall = child + return lastWall + + def getLevelObject(self, aNodePath): + # Given a node path, find the corresponding level object + # in the levelDictionary, if none exists, return 0 + return self.levelDictionary.get(aNodePath.node().this, None) + + def getRandomCorniceTexture(self): + chance = 100 * random() + if (chance < 20): + textures = self.getCorniceTextures() + len = len(textures) + index = randint(0,len) + return textures[index] + else: + return None + + def rounded(self,val): + return int(round(val)) + + def getRandomNumWindows(self, height): + h = rounded(height) + if h == 10: + # Only return 0 25% of the time + if rounded(self.getWallWidth()) == 5: + return randint(1,3) + else: + return randint(0,3) + elif h == 20: + if rounded(self.getWallWidth()) == 5: + return randint(1,3) + else: + return randint(0,4) + elif h == 30: + if rounded(self.getWallWidth()) == 5: + return randint(1,3) + else: + return randint(0,4) + + + def getRandomDictionaryEntry(self,dict): + numKeys = len(dict) + if numKeys > 0: + keys = dict.keys() + key = keys[randint(0,numKeys - 1)] + return dict[key] + else: + return None + + def getRandomStyle(self): + return self.getRandomDictionaryEntry(styleDictionary) + + def getRandomWallTexture(self): + return self.getWallTextures()[ + randint(0, len(self.getWallTextures()) - 1)] + + def getRandomWallWidth(self): + chance = randint(0,100) + if chance <= 15: + return 5.0 + elif (chance > 15) & (chance <= 30): + return 10.0 + elif (chance > 30) & (chance <= 65): + return 15.0 + elif (chance > 65) & (chance <= 85): + return 20.0 + elif (chance > 85): + return 25.0 + + def getRandomWindowTexture(self): + wt = self.getWindowTextures() + return wt[randint(9, len(wt) -1 )] + + def getWall(self, aDNAGroup, wallNum): + wallCount = 0 + for i in range(aDNAGroup.getNumChildren()): + child = aDNAGroup[i] + if child.getClassType().eq(DNAWall.getClassType()): + if wallCount == wallNum: + return child + wallCount = wallCount + 1 + # Not found + return None + + def getWallHeights(self, aDNAFlatBuilding): + heightList = [] + heightTotal = 0.0 + + # Compute wall heights + for i in range(aDNAFlatBuilding.getNumChildren()): + child = aDNAFlatBuilding[i] + if child.getClassType().eq(DNAWall.getClassType()): + heightTotal = heightTotal + child.getHeight() + heightList.add(heightTotal) + return heightList + + def getWallNum(self, aDNAFlatBuilding, zPt): + if zPt < 0: + return -1 + heightList = self.getWallHeights(aDNAFlatBuilding) + wallNum = 0 + for height in heightList: + if zPt < height: + return wallNum + wallNum = wallNum + 1 + return -1 + + def getWindow(self, aDNAGroup, windowNum): + windowCount = 0 + for i in range(aDNAGroup.getNumChildren()): + child = aDNAGroup[i] + if (child.getClassType().eq(DNAWindow.getClassType()) | + child.getClassType().eq(DNAWindows.getClassType())): + if windowCount == windowNum: + return child + windowCount = windowCount + 1 + # Not found + return None + + def initDNAGroupWithParent(self, dnaGroup, parent): + # Create the geometry + # If it is a flat building, update building DNA to current wall width + if (dnaGroup.getClassType().eq(DNAFlatBuilding.getClassType)): + dnaGroup.setWidth(self.getWallWidth()) + newNodePath = dnaGroup.traverse(parent,self.dnaStore) + # Add it to the level dictionary + self.addObject(newNodePath, dnaGroup) + # Add it to the top level DNA Group + self.groupParentDNA.add(dnaGroup) + + # Place the new node path at the current grid origin + newNodePath.setPos(grid,0,0,0) + # Initialize angle to match last object + newNodePath.setH(self.lastAngle) + + # Select the instance + self.selectNodePath(newNodePath) + + # Now move the grid to get ready for the next group + self.autoPositionGrid() + + # Update dictionary + dnaGroup.setPos(newNodePath.getPos()) + dnaGroup.setHpr(newNodePath.getHpr()) + + def initDNAGroupWithParentType(self, dnaGroup, parent, type): + # Create the geometry + # If it is a flat building, update building DNA to current wall width + if dnaGroup.getClassType().eq(DNAFlatBuilding.getClassType()): + dnaGroup.setWidth(self.getWallWidth()) + newNodePath = dnaGroup.traverse(parent, self.dnaStore) + # Add it to the level dictionary + self.addObject(newNodePath, dnaGroup) + # Add it to the top level DNA Group + self.groupParentDNA.add(dnaGroup) + + # Place the new node path at the current grid origin + newNodePath.setPos(self.grid,0,0,0) + # Initialize angle to match last object + newNodePath.setH(self.lastAngle) + + # Select the instance + self.selectNodePath(newNodePath) + + # Now move the grid to get ready for the next group + self.autoPositionGrid() + + # Update dictionary + dnaGroup.setPos(newNodePath.getPos()) + dnaGroup.setHpr(newNodePath.getHpr()) + + def initNewDNAGroupWithParent(self, dnaGroup, rootNode): + # Reflect currently selected prop type + if dnaGroup.getClassType().eq(DNAProp.getClassType()): + self.updatePropType(dnaGroup,self.propType) + + # Create a new copy of dnaGroup's class + # Extract group's class using __class__ + # Call that class's constructor passing in dnaGroup to make a copy + self.initDNAGroupWithParent(dnaGroup.__class__(dnaGroup), self.groupParent) + # Initialize + if dnaGroup.getClassType().eq(DNAProp.getClassType()): + objectType = self.getDNAString(dnaGroup) + if objectType != 'prop_sphere': + # Update props placement to reflect current mouse position + # Where is the mouse relative to the grid? + self.grid.getMouseIntersectionPoint(self.hitPt, 0) + self.direct.selected.last.setPos(self.grid, self.hitPt) + dnaGroup.setPos(self.direct.selected.last.getPos()) + + def initNewDNAGroupWithParentType(self, dnaGroup, rootNode, type): + # Create a new dna Group of the same type a dnaGroup + newDNAGroup = dnaGroup.__class__(dnaGroup) + if dnaGroup.getClassType().eq(DNAProp.getClassType()): + self.updatePropType(newDNAGroup,self.propType) + + self.initDNAGroupWithParentType(newDNAGroup, self.groupParent, type) + + def loadDNAFile(self, filename): + # Out with the old, in with the new + self.resetLevel() + # Get rid of default group and root node + self.preRemoveNodePath(self.groupParent) + self.removeNodePath(self.groupParent) + + # Clear self.dnaStore + self.dnaStore.resetDNAGroups() + + # Now load in new file + self.groupParent = self.dnaStore.loadDNAFile(filename) + + # Make sure the topmost level object gets put under level objects dna + self.groupParentDNA = self.dnaStore.findDNAGroup(self.groupParent.getBottomArc()) + self.levelObjectsDNA.add(self.groupParentDNA) + + # No level objects node found, just add the whole thing + self.groupParent.reparentTo(self.levelObjects) + + if 0: + newLevelObjects = nodePath.find('**/LevelObjects') + if newLevelObjects.isEmpty(): + # No level objects node found, just add the whole thing + nodePath.reparentTo(self.levelObjects) + else: + # There is a LevelObjects node, add its children + # Before reparenting children, try to set groupNum to something reasonable + self.groupNum = newLevelObjects.getNumChildren() + # Go ahead and get rid of the default parent (since there is probably one in the dnafile + self.preRemoveNodePath(self.groupParent) + self.removeNodePath(self.groupParent) + + # Now add the children from the DNA File + children = newLevelObjects.getChildren() + for i in range(children.getNumPaths()): + children.getPath(i).reparentTo(self.levelObjects) + # Now create a new top level group with next group number + self.createTopLevelGroup() + + # Add these objects to the levelDictionary + numPaths = self.dnaStore.getNumNodeRelations() + for pathNum in range(numPaths): + relation = self.dnaStore.getNodeRelationAt(pathNum) + if relation: + newNodePath = NodePath(relation) + group = self.dnaStore.findDNAGroup(relation) + if newNodePath.isSingleton(): + print 'Singleton!!' + else: + self.addObject(newNodePath, group) + else: + print'blah' + + self.createNewLevelGroup() + + def outputDNA(self,filename): + print 'Saving DNA to: ', filename + self.levelObjectsDNA.writeDna(Filename(filename),Notify.out(),self.dnaStore) + + def preRemoveNodePath(self, aNodePath): + # Remove nodePath's DNA from its parent + dnaGroup = self.getDNAGroup(aNodePath) + if dnaGroup: + parentDNAGroup = self.getDNAGroup((aNodePath.getParent())) + if parentDNAGroup: + parentDNAGroup.remove(dnaGroup) + + def printVizRegions(self): + if self.direct.selected.last: + self.printVizRegionsOf(self.direct.selected.last) + + def printVizRegionsOf(self, aNodePath): + # Print out commands to create viz regions + print 'To Be Supplied' + + def removeCornices(self, aDNAGroup): + while self.removeDNAObjectOfClass(DNACornice,self.getLastWall(aDNAGroup)): + pass + + def removeDNAObjectFrom(self, aDNAGroup, objectClass): + # Remove the first object of that type you come across + for i in range(aDNAGroup.getNumChildren()): + child = aDNAGroup[i] + if child.getClassType().eq(objectClass): + aDNAGroup.remove(child) + return 1 + # None found + return 0 + + def removeDNAObjectOfClass(self, objectClass, aDNAGroup): + # Remove the first object of that type you come across + for i in range(aDNAGroup.getNumChildren()): + child = aDNAGroup[i] + if child.getClassType.eq(objectClass): + aDNAGroup.remove(child) + return 1 + # None found + return 0 + + def removeLevelObject(self, aNodePath): + # Remove specified node path from the scene dictionary + nodePathHandle = aNodePath.this + del(self.levelDictionary[nodePathHandle]) + # Get rid of its visible representation + aNodePath.removeNode() + + def removeNodePath(self, aNodePath): + # Remove specified node path from the scene dictionary + nodePathHandle = aNodePath.this + del(self.levelDictionary[nodePathHandle]) + # Get rid of its visible representation + aNodePath.removeNode() + + def removeWindows(self, aDNAGroup): + while self.removeDNAObjectOfClass(DNAWindow, aDNAGroup): + pass + while self.removeDNAObjectOfClass(DNAWindows, aDNAGroup): + pass + + def reparentNodePath(self, aNodePath): + selectedDNAObject = self.getDNAGroup(aNodePath) + if not selectedDNAObject: + return 0 + parent = aNodePath.getParent() + if not parent: + return 0 + parentDNAObject = self.getDNAGroup(parent) + if not parentDNAObject: + return 0 + if self.groupParent & self.groupParentDNA: + # Everybody seems happy, move it + aNodePath.reparentTo(self.groupParent) + parentDNAObject.remove(selectedDNAObject) + self.groupParentDNA.add(selectedDNAObject) + return 1 + + def reparentSelectedNodePath(self): + selectedNodePath = self.direct.selected.last + if not selectedNodePath: + return 0 + return self.reparentNodePath(selectedNodePath) + + def replaceLevelObject(self, levelObject): + # Get the DNA for this object + dnaGroup = levelObject['DNA'] + + # Get to current node path and its parent + oldNodePath = levelObject['nodePath'] + parent = oldNodePath.getParent() + + # Traverse the dna to create the new node path + newNodePath = dnaGroup.traverse(parent, self.dnaStore) + self.selectNodePath(newNodePath) + + # Add it to the levelObjects dictionary + self.selectedLevelObject = self.addObject(newNodePath, dnaGroup) + + # Now get rid of the old level object + self.removeNodePath(oldNodePath) + + def replaceLevelObjectNodePath(self, levelObject): + # Get and reuse the DNA for this object + dnaGroup = levelObject['DNA'] + + # Get to current node path and its parent + oldNodePath = levelObject['nodePath'] + parent = oldNodePath.getParent() + + # Traverse the dna to create the new node path + newNodePath = dnaGroup.traverse(parent, self.dnaStore) + self.selectNodePath(newNodePath) + + # Add it to the levelObjects dictionary + self.selectedLevelObject = self.addObject(newNodePath, dnaGroup) + + # Now get rid of the old level object + self.removeNodePath(oldNodePath) + + def selectBuildingType(self, heightType): + chance = randint(0,100) + if heightType == 'twenty': + if chance <= 65: + return 'toonTenTen' + else: + return 'toonTwenty' + else: + if chance <= 40: + return 'toonTenTwenty' + elif (chance > 40) & (chance <= 70): + return 'toonTwentyTen' + elif (chance > 70) & (chance <= 90): + return 'toonTenTenTen' + else: + return 'toonThirty' + + def setGroupName(self, aNodePath, aName): + aDNAGroup = self.getDNAGroup(aNodePath) + if aDNAGroup: + aNodePath.setName(aName) + aDNAGroup.setName(aName) + + def setNodePathName(self, aNodePath, aName): + levelObject = self.getLevelObject(aNodePath) + if levelObject: + levelObjectDNA = levelObject['DNA'] + aNodePath.setName(aName) + levelObjectDNA.setName(aName) + self.replaceLevelObject(levelObject) + + def setRandomBuildingStyle(self, aDNAFlatBuilding): + self.setWallWidthVal(self.getRandomWallWidth()) + aDNAFlatBuilding.setWidth(self.getWallWidth()) + style = self.getRandomStyle() + for i in range(aDNAFlatBuilding.getNumChildren()): + child = aDNAFlatBuilding[i] + if child.getClassType.eq(DNAWall): + self.setWallStyle(child, style) + if randint(0,100) < 40: + style = self.getRandomStyle() + + # Randomly add cornice + if randint(0,100) < 40: + self.removeCornices(aDNAFlatBuilding) + else: + if not style['corniceTexture']: + self.removeCornices(aDNAFlatBuilding) + else: + aDNACornice = self.getCornice(aDNAFlatBuilding) + if not aDNACornice: + aDNACornice = DNACornice() + aDNACornice.setCode(self.dnaStore.findCode(style['corniceTexture'])) + aDNACornice.setColor(style['corniceColor']) + lastWall = self.getLastWall(aDNAFlatBuilding) + lastWall.add(aDNACornice) + + def setRandomNumWindows(self, aDNAWall, numWindows): + window = self.getWindow(aDNAWall, 0) + window.setCount(numWindows) + + def setWallStyle(self, aDNAWall, style): + aDNAWall.setCode(self.dnaStore,style['wallTexture']) + aDNAWall.setColor(style['wallColor']) + aDNAWindows = self.getWindow(aDNAWall, 0) + aDNAWindows.setCount(self.getRandomNumWindows(aDNAWall.getHeight())) + aDNAWindows.setCode(self.dnaStore.findCode(style['windowTexture'])) + aDNAWindows.setColor(style['windowColor']) + + def setWallStyle(self, aDNAWall, styleNum): + self.setWallStyle(aDNAWall, self.styleDictionary[styleNum]) + + def updateColorIndex(self, colorIndex): + if colorIndex < 0: + self.updateObjColor(self.targetDNAObject,self.activeMenu.getInitialState()) + else: + self.updateObjColor(self.targetDNAObject,self.activeColors[colorIndex]) + + def updateObjColor(self, aDNAObject, color): + aDNAObject.setColor(color) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.setActiveColor(color) + + def updateCorniceTextureNum(self, corniceNumber): + self.updateObjCorniceTexture(self.targetDNAObject, corniceNumber) + + def updateObjCorniceTexture(self, aDNACornice, corniceTextureNumber): + # Which wall texture was picked by the user? + if (corniceTextureNumber < 0): + dnaString = self.activeMenu.getInitialState() + else: + dnaString = self.getCorniceTextures()[corniceTextureNumber] + + # Now update the texture on the cornice with that texture + self.updateCorniceTextureDNA(aDNACornice, dnaString) + + def updateCorniceTextureDNA(self, aDNACornice, dnaString): + # Get the currently selected DNA Group + aDNAGroup = self.selectedLevelObject['DNA'] + + if dnaString == None: + # Remove any existing cornices + self.removeCornices(aDNAGroup) + # Clear out target DNA Object + self.targetDNAObject = None + else: + # Change the cornice type + if aDNACornice: + # Change existing one + aDNACornice.setCode(self.dnaStore.findCode(dnaString)) + else: + lastWall = self.getLastWall(aDNAGroup) + if lastWall: + # No cornice exists, add a new one + newDNACornice = self.createCornice(dnaString) + lastWall.add(newDNACornice) + # Update target DNA Object + self.targetDNAObject = newDNACornice + + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.corniceTexture(dnaString) + + def updateDNAPosHpr(self, aNodePath): + if aNodePath: + dnaGroup = self.getDNAGroup(aNodePath) + if dnaGroup: + if not(dnaGroup.getClassType().eq(DNAGroup.getClassType())): + dnaGroup.setPos(aNodePath.getPos()) + dnaGroup.setHpr(aNodePath.getHpr()) + + def updateDoorTextureNum(self, doorTextureNumber): + self.updateObjDoorTexture(self.targetDNAObject, doorTextureNumber) + + def updateObjDoorTexture(self, aDNADoor, doorTextureNumber): + # Which door texture was picked by the user? + if doorTextureNumber < 0: + dnaString = self.activeMenu.getInitialState() + else: + dnaString = self.doorTextures()[doorTextureNumber] + + # Now update the texture on the door with that texture + self.updateDoorTextureDNA(aDNADoor, dnaString) + + def updateDoorTextureDNA(self, aDNADoor ,dnaString): + aDNADoor.setCode(self.dnaStore.findCode(dnaString)) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.doorTexture(dnaString) + + def updateNumWindows(self, numWindows): + if numWindows < 0: + self.updateObjNumWindows(self.targetDNAObject, + self.activeMenu.getInitialState()) + else: + self.updateObjNumWindows(self.targetDNAObject,numWindows) + + def updateObjNumWindows(self, aDNAWall, numWindows): + # remove any existing windows + self.removeWindows(aDNAWall) + + # Add the newly specified number of windows + newDNAWindows = self.createWindows(numWindows) + aDNAWall.add(newDNAWindows) + + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + + self.setNumWindows(numWindows) + + def updateOrientationNum(self, orientationNumber): + remappedOrientationNumber = orientationNumber + + # Remap lower menu values for Door's and Cornices' + # (only have upper orientations) + if ((self.targetDNAObject.getClassType().eq(DNADoor.getClassType())) | + (self.targetDNAObject.getClassType().eq(DNACornice.getClassType()))): + if (orientationNumber == 2): + remappedOrientationNumber = 0 + elif (orientationNumber == 3): + remappedOrientationNumber = 1 + + self.updateOrientation(self.targetDNAObject, remappedOrientationNumber) + + def updateOrientation(self, aDNAObject, orientationNumber): + if self.activeMenu.getInitialState() == None: + return None + currString = self.getDNAString(aDNAObject) + + # Strip off current suffix + newString = currString[:-3] + + if orientationNumber == 0: + dnaString = newString + '_ur' + elif orientationNumber == 1: + dnaString = newString + '_ul' + elif orientationNumber == 2: + dnaString = newString + '_dr' + elif orientationNumber == 3: + dnaString = newString + '_dl' + else: + self.activeMenu.getInitialState() + + if newString != currString: + objClass = aDNAObject.getClassType() + if objClass == DNAWall.getClassType(): + self.updateWallTextureDNA(aDNAObject, dnaString) + elif objClass == DNACornice.getClassType(): + self.updateCorniceTextureDNA(aDNAObject, dnaString) + elif objClass == DNADoor.getClassType(): + self.updateDoorTextureDNA(aDNAObject, dnaString) + elif objClass == DNAWindow.getClassType(): + self.updateWindowTextureDNA(aDNAObject, dnaString) + elif objClass == DNAWindows.getClassType(): + self.updateWindowTextureDNA(aDNAObject, dnaString) + + def updatePropNum(self,propNumber): + self.updatePropType(self.targetDNAObject, propNumber) + + def updatePropType(self, aDNAProp, propNumber): + # Which propType was picked by the user? + if (propNumber < 0): + dnaString = self.activeMenu.getInitialState() + else: + dnaString = self.propTypes[propNumber] + + # Now update the texture on the wall with that texture + self.updatePropDNA(aDNAProp,dnaString) + + def updatePropDNA(self, aDNAProp, dnaString): + aDNAProp.setCode(self.dnaStore.findCode(dnaString)) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.propType(dnaString) + + def updateRandomNumWindows(self, aDNAFlatBuilding): + for i in range(aDNAFlatBuilding.getNumChildren()): + child = aDNAFlatBuilding[i] + if child.getClassType().eq(DNAWall.getClassType): + self.setRandomNumWindows( + child, + self.getRandomNumWindows(child.getHeight())) + + def updateWallColor(self, aDNAWall, color): + aDNAWall.setColor(color) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObject(self.selectedLevelObject) + + def updateWallOrientationNum(self, wallOrientationNumber): + self.updateWallOrientation(self.targetDNAObject, wallOrientationNumber) + + def updateWallOrientation(self, aDNAWall, wallOrientationNumber): + currString = self.getDNAString(aDNAWall) + + # Strip off current suffix + newString = currString[:-3] + if wallOrientationNumber == 0: + dnaString = newString + '_ur' + elif wallOrientationNumber == 1: + dnaString = newString + '_ul' + elif wallOrientationNumber == 2: + dnaString = newString + '_dr' + elif wallOrientationNumber == 3: + dnaString = newString + '_dl' + else: + self.activeMenu.getInitialState() + + if newString != currString: + self.updateWallTextureDNA(aDNAWall, dnaString) + + def updateWallStyleNum(self, styleNum): + if styleNum < 0: + self.setWallStyle(self.targetDNAObject, 1) + else: + self.setWallStyle(self.targetDNAObject, (1 + styleNum)) + self.replaceLevelObjectNodePath(self.selectedLevelObject) + + def updateWallTextureNum(self, wallTextureNumber): + self.updateObjWallTextureNum(self.targetDNAObject, wallTextureNumber) + + def updateObjWallTextureNum(self, aDNAWall, wallTextureNumber): + # Which wall texture was picked by the user? + if wallTextureNumber < 0: + dnaString = self.activeMenu.getInitialState() + else: + dnaString = self.getWallTextures()[wallTextureNumber] + + # Now update the texture on the wall with that texture + self.updateWallTextureDNA(aDNAWall, dnaString) + + def updateWallTextureDNA(self, aDNAWall, dnaString): + aDNAWall.setCode(self.dnaStore.findCode(dnaString)) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.setWallTexture(dnaString) + + def updateWallWidthSF(self, scaleFactor): + if (scaleFactor < 0): + self.updateWallWidth(self.targetDNAObject, + (self.activeMenu.getInitialState())) + else: + self.updateWallWidth(self.targetDNAObject, + (scaleFactor + 1) * 5.0) + + def updateWallWidth(self, aDNAWall, width): + aDNAWall.setWidth(width) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.setWallWidthVal(width) + self.autoPositionGrid() + + def updateWindowTextureNum(self, windowTextureNumber): + self.updateObjWindowTexture(self.targetDNAObject, + windowTextureNumber) + + def updateObjWindowTexture(self, aDNAWindow, windowTextureNumber): + # Which window texture was picked by the user? + if windowTextureNumber < 0: + dnaString = self.activeMenu.getInitialState() + else: + dnaString = self.getWindowTextures()[windowTextureNumber] + + # Now update the texture on the window with that texture + self.updateWindowTextureDNA(aDNAWindow, dnaString) + + def updateWindowTextureDNA(self, aDNAWindow, dnaString): + aDNAWindow.setCode(self.dnaStore.findCode(dnaString)) + # Replace object in levelObjects dictionary and scene graph + self.replaceLevelObjectNodePath(self.selectedLevelObject) + self.windowTexture(dnaString) + + def roundTo(self, value, divisor): + return round(value/float(divisor)) * divisor + + def autoPositionGrid(self): + # Move grid to prepare for placement of next object + selectedNode = direct.selected.last + if selectedNode: + dnaGroup = self.getDNAGroup(selectedNode) + groupClass = dnaGroup.getClassType().getName() + deltaPos = VBase3(20,0,0) + deltaHpr = VBase3(0) + if groupClass == 'DNAFlatBuilding': + deltaPos.setX(self.getWallWidth()) + elif groupClass == 'DNAStreet': + objectType = self.getDNAString(dnaGroup) + if objectType == 'street_5x20': + deltaPos.setX(5.0) + elif objectType == 'street_10x20': + deltaPos.setX(10.0) + elif objectType == 'street_20x20': + deltaPos.setX(20.0) + elif objectType == 'street_40x20': + deltaPos.setX(40.0) + elif objectType == 'street_80x20': + deltaPos.setX(80.0) + elif objectType == 'street_5x40': + deltaPos.setX(5.0) + elif objectType == 'street_10x40': + deltaPos.setX(10.0) + elif objectType == 'street_20x40': + deltaPos.setX(20.0) + elif objectType == 'street_30x40': + deltaPos.setX(30.0) + elif objectType == 'street_40x40': + deltaPos.setX(40.0) + elif objectType == 'street_80x40': + deltaPos.setX(80.0) + elif objectType == 'street_angle_30': + deltaPos.setX(30.0) + elif objectType == 'street_angle_45': + deltaPos.setX(30.0) + elif objectType == 'street_angle_60': + deltaPos.setX(30.0) + elif objectType == 'street_inner_corner': + deltaPos.setX(20.0) + elif objectType == 'street_outer_corner': + deltaPos.setX(20.0) + elif objectType == 'street_full_corner': + deltaPos.setX(40.0) + elif objectType == 'street_t_intersection': + deltaPos.setX(40.0) + elif objectType == 'street_y_intersection': + deltaPos.setX(30.0) + elif objectType == 'street_street_20x20': + deltaPos.setX(20.0) + elif objectType == 'street_street_40x40': + deltaPos.setX(40.0) + elif objectType == 'street_sidewalk_20x20': + deltaPos.setX(20.0) + elif objectType == 'street_sidewalk_40x40': + eltaPos.setX(40.0) + elif groupClass == 'DNALandmarkBuilding': + objectType = self.getDNAString(dnaGroup) + if objectType == 'toon_landmark_building_01': + deltaPos.setX(25.0) + elif objectType == 'toon_landmark_building_02': + deltaPos.setX(15.0) + elif objectType == 'toon_landmark_building_03': + deltaPos.setX(20.0) + elif groupClass == 'DNAProp': + objectType = self.getDNAString(dnaGroup) + if objectType == 'prop_sphere': + deltaPos.setX(40.0) + + # Position grid for placing next object + # Eventually we need to setHpr too + self.grid.setPos(selectedNode, deltaPos) + if self.grid.getXyzSnap(): + # Tighten up grid position + pos = self.grid.getPos() + roundVal = roundTo(self.grid.getGridSpacing(), 1) + x = roundTo(pos[0], roundVal) + y = roundTo(pos[1], roundVal) + z = rountTo(pos[2], roundVal) + self.grid.setPos(x,y,z) + + # Also move the camera + taskMgr.removeTasksNamed('autoMoveDelay') + handlesToCam = self.direct.widget.getPos(self.direct.camera) + handlesToCam = handlesToCam * ( self.direct.chan.near/handlesToCam[1]) + if ((abs(handlesToCam[0]) > (self.direct.chan.nearWidth * 0.4)) | + (abs(handlesToCam[2]) > (self.direct.chan.nearHeight * 0.4))): + taskMgr.removeTasksNamed('manipulateCamera') + self.direct.cameraControl.centerCamIn(self.direct.chan, 0.5) + + def plantSelectedNodePath(self): + # Move grid to prepare for placement of next object + selectedNode = direct.selected.last + if selectedNode: + # Where is the mouse relative to the grid? + # MRM NEEDED + self.getMouseIntersectionPoint(self.hitPt, 0) + selectedNode.setPos(self.grid, self.hitPt) + dnaGroup = self.getDNAGroup(selectedNode) + if dnaGroup: + # Update props placement to reflect current mouse position + dnaGroup.setPos(direct.selected.last.getPos()) + + def resetLevel(self): + # Clear out all objects + self.direct.deselectAll() + children = self.levelObjects.getChildren() + for i in range(children.getNumPaths()): + path = children.getPath(i) + path.reparentTo(hidden) + path.remove() + + # Create fresh DNA Object + self.levelObjectsDNA = DNAData('LevelObjects') + + # Create new levelDictionary + self.levelDictionary = {} + + # Create root node + self.createTopLevelGroup() + + self.grid.setPosHpr(0,0,0,0,0,0) + + def selectNodePath(self, aNodePath): + # Method to handle the select event. + # MRM: THis or message? + self.direct.select(aNodePath) + # Update selectedLevelObject + self.selectedLevelObject = self.getLevelObject(aNodePath) + + def getWallIntersectionPoint(self, intersectionPoint): + # Find point of intersection between grid plane and line from cam through mouse + # Don't do anything if nothing selected + selectedNode = direct.selected.last + if not selectedNode: + return 0 + + chan = self.direct.chan + mouseX = chan.mouseX + mouseY = chan.mouseY + nearX = math.tan(deg2Rad(chan.fovH)/2.0) * mouseX * chan.near + nearZ = math.tan(deg2Rad(chan.fovV)/2.0) * mouseY * chan.near + + mCam2Grid = chan.camera.getMat(selectedNode) + mouseOrigin = Point3(0) + mouseOrigin.assign(mCam2Grid.getRow3(3)) + mouseDir = Vec3(0) + mouseDir.set(nearX, chan.near, nearZ) + mouseDir.assign(mCam2Grid.xformVec(mouseDir)) + + return self.wallIntersectionPlane.intersectsLine(intersectionPoint, mouseOrigin, mouseDir) + +""" + + def initializePropButtons(self): + # Initialize Hooks and Buttons for the wall type buttons + newPtopTypes = self.getCatalogCodes('prop') + methodArray = [] + for + newPtopTypes collect: [ :prop | + { prop copyFrom: 5 to: prop size . prop asSymbol } ]. + + hooksSet = self.hooksDictionary['prop ifAbsent: [ Set new. ]. + methodArray do: [ :pair | hooksSet add: (pair at: 2) ]. + self.hooksDictionary['prop'] = hooksSet. + + # Create wall module buttons + # First get rid of any existing buttons + self.clickBoxDictionary['prop ifPresent: [ :clickBoxList | clickBoxList disable ]. + buttons = ClickBoxList new table: methodArray x: 0.95 y: 0.90. + buttons addButtonWithText: 'back' event: #mainMenuEnable. + buttons alignRight. + buttons.setScale(0.06. + buttons.setColor(0.6 g: 0.6 b: 0.6 a: 0.8. + self.clickBoxDictionary['prop'] = buttons. + + self.categorySet add: #prop. +! ! + +!Level methodsFor: 'initialization' stamp: 'panda 00/00/0000 00:00'! +initializeStreetButtons + | streetTypes methodArray hooksSet buttons | + # Initialize Hooks and Buttons for the wall type buttons + streetTypes = self.getCatalogCodes(#street. + methodArray = + streetTypes collect: [ :street | { street copyFrom: 8 to: street size . street asSymbol } ]. + + hooksSet = self.hooksDictionary['street ifAbsent: [ Set new. ]. + methodArray do: [ :pair | hooksSet add: (pair at: 2) ]. + self.hooksDictionary['street'] = hooksSet. + + # Create wall module buttons + # First get rid of any existing buttons + self.clickBoxDictionary['street ifPresent: [ :clickBoxList | clickBoxList disable ]. + buttons = ClickBoxList new table: methodArray x: 0.95 y: 0.90. + buttons addButtonWithText: 'back' event: #mainMenuEnable. + buttons alignRight. + buttons.setScale(0.06. + buttons.setColor(0.6 g: 0.6 b: 0.6 a: 0.8. + self.clickBoxDictionary['street'] = buttons. + + self.categorySet add: #street. +! ! + +!Level methodsFor: 'initialization' stamp: 'panda 00/00/0000 00:00'! +initializeWallButtons + | methodArray hooksSet buttons | + + # Initialize Hooks and Buttons for the wall type buttons + methodArray = { + { 'Random 20' . #random20 } . + { 'Random 30' . #random30 } . + { '10-10' . #toonTenTen } . + { '20' . #toonTwenty } . + { '10-20' . #toonTenTwenty } . + { '20-10' . #toonTwentyTen } . + { '10-10-10' . #toonTenTenTen } . + { '30' . #toonThirty } }. + + hooksSet = self.hooksDictionary['wall ifAbsent: [ Set new. ]. + methodArray do: [ :pair | hooksSet add: (pair at: 2) ]. + self.hooksDictionary['wall'] = hooksSet. + + # Create wall module buttons + # First get rid of any existing buttons + self.clickBoxDictionary['wall ifPresent: [ :clickBoxList | clickBoxList disable ]. + buttons = ClickBoxList new table: methodArray x: 0.95 y: 0.90. + buttons addButtonWithText: 'back' event: #mainMenuEnable. + buttons.setColor(0.6 g: 0.6 b: 0.6 a: 0.8. + buttons.setScale(0.06. + buttons alignRight. + buttons makeAllWideAsWidest. + self.clickBoxDictionary['wall'] = buttons. + + # Initialize Hooks and Buttons for the wall width buttons + methodArray = { { '5 ft' . #fiveFt } . + { '10 ft' . #tenFt } . + { '15 ft' . #fifteenFt } . + { '20 ft' . #twentyFt } . + { '25 ft' . #twentyFiveFt } }. + + hooksSet = self.hooksDictionary['wallWidths ifAbsent: [ Set new. ]. + methodArray do: [ :pair | hooksSet add: (pair at: 2) ]. + self.hooksDictionary['wallWidths'] = hooksSet. + + # Create wall width buttons + # First get rid of any existing buttons + self.clickBoxDictionary['wallWidths ifPresent: [ :clickBoxList | clickBoxList disable ]. + buttons = ClickBoxList new table: methodArray x: 0.95 y: -0.40. + buttons.setColor(0.6 g: 0.6 b: 0.6 a: 0.8. + buttons.setScale(0.06. + buttons alignRight. + self.clickBoxDictionary['wallWidths'] = buttons. + + self.categorySet add: #wall. +! ! + + + def clearHighlightedObjects(self): + highlightedObjects getChildren forEachPathPerform: #removeNode.! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +followMouse: aNodePath + # Plant target object on grid at cursor projection point + | roundVal | + roundVal = (self.grid gridSpacing roundTo: 1). + (self.grid getMouseIntersectionPoint: self.hitPt ) ifTrue: [ + self.grid xyzSnap ifTrue: [ + aNodePath setPos: self.grid + x: (((self.hitPt at: 0) + (self.offset at: 0)) roundTo: roundVal) + y: (((self.hitPt at: 1) + (self.offset at: 1)) roundTo: roundVal) + z: (((self.hitPt at: 2) + (self.offset at: 2)) roundTo: roundVal). + ] + ifFalse: [ + aNodePath setPos: self.grid pos: (self.hitPt + self.offset). + ]. + ] +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +followMouseStart: aNodePath + | gridToObjectHandles hitPtToObjectHandles | + + # Where is the mouse relative to the grid? + self.grid getMouseIntersectionPoint: self.hitPt. + + # Record crank origin + self.crankOrigin operatorAssign: (direct selectedNodePath getPos: self.grid). + + # Record the offset + self.offset = self.crankOrigin - self.hitPt. + # Init crankDir + self.crankDir operatorAssign: self.offset negated. + self.crankDir normalize. + # Compute crankAngle + startAngle = self.getCrankAngle. + startH = direct selectedNodePath getH. + + # Transform hitPt into object handles space to determine manipulation mode + # Where is the mouse relative to the widget? + Don't snap to grid since we want to test hitPt relative to widget + self.grid getMouseIntersectionPoint: self.hitPt xyzSnap: 0. + gridToObjectHandles = self.grid getMat: direct objectHandles. + hitPtToObjectHandles = (Vec3 new: (gridToObjectHandles xformPoint: self.hitPt)) length. + + # Are we inside rotation ring? + ((hitPtToObjectHandles > 0.8) and: [(hitPtToObjectHandles < 1.2)]) + ifTrue: [[[true] taskWhileTrue: [ self.mouseCrank: aNodePath]] + spawnTaskNamed: #levelMouseCrank.] + ifFalse: [[[true] taskWhileTrue: [ self.followMouse: aNodePath]] + spawnTaskNamed: #levelFollowMouse.] + +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +followMouseStop + | selectedNode | + # Stop moving object + Task removeTasksNamed: #levelFollowMouse. + Task removeTasksNamed: #levelMouseCrank. + + # Move grid to line up with object + selectedNode = direct selectedNodePath. + selectedNode notNone ifTrue: [ + self.updateDNAPosHpr: selectedNode. + # Position grid for placing next object + self.autoPositionGrid. + ]. + +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +getCrankAngle + | newAngle | + self.crankDir normalize. + # Just look at Y component (equiv to dot product with (0 1 0) + newAngle = (self.crankDir at: 1) arcCos radiansToDegrees. + ((self.crankDir at: 0) > 0.0) ifTrue: [ newAngle = newAngle negated. ]. + # Force it to 0 to 360.0 range + return newAngle + 180.0. +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +highlightNodePath: aNodePath + | pose highlightedNode | + # First clear out old highlighted nodes + self.clearHighlightedObjects. + # Place an instance of the object under the highlightedObjects node + highlightedNode = aNodePath instanceTo: highlightedObjects. + pose = aNodePath getMat: self.levelObjects. + highlightedNode setMat: self.levelObjects mat: pose. + ! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +keyboardRotateNodePath: aNodePath key: arrowDirection + | pos hpr scale | + pos = aNodePath getPos. + scale = aNodePath getScale. + self.lastAngle = self.lastAngle + (arrowDirection caseOf: { [#left]->[ 90.0 ] . + [#right]->[ -90.0 ] . + [#up]->[ 90.0 ] . + [#down]->[ -90.0 ] }). + (self.lastAngle < -180.0) ifTrue: [ self.lastAngle = self.lastAngle + 360.0 ]. + (self.lastAngle > 180.0) ifTrue: [ self.lastAngle = self.lastAngle - 360.0 ]. + hpr = VBase3 new: self.lastAngle y: 0.0 z: 0.0. + + aNodePath setPosHprScale: pos hpr: hpr scale: scale. + + # Refresh DNA + self.updateDNAPosHpr: aNodePath. + # Position grid for placing next object + self.autoPositionGrid. + +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +keyboardTranslateNodePath: aNodePath key: arrowDirection + | pos deltaMove gridToCamera xAxis zAxis camXAxis xxDot xzDot | + + gridToCamera = self.grid getMat: chanCenter camera. + xAxis = Vec3 right. + zAxis = Vec3 up. + camXAxis = gridToCamera xformVec: xAxis. + xxDot = camXAxis dot: xAxis. + xzDot = camXAxis dot: zAxis. + + # get current object position + pos = aNodePath getPos: self.grid. + + # what is the current grid spacing? + deltaMove = self.grid gridSpacing. + + # Add or subtract the specified delta + (xxDot abs > xzDot abs) ifTrue: [ + (xxDot < 0.0) ifTrue: [ deltaMove = deltaMove negated. ]. + arrowDirection caseOf: { [#left]->[ pos setX: ((pos at: 0) - deltaMove) ] . + [#right]->[ pos setX: ((pos at: 0) + deltaMove) ] . + [#up]->[ pos setY: ((pos at: 1) + deltaMove) ] . + [#down]->[ pos setY: ((pos at: 1) - deltaMove) ] } + ] + ifFalse: [ + (xzDot < 0.0) ifTrue: [ deltaMove = deltaMove negated. ]. + arrowDirection caseOf: { [#left]->[ pos setY: ((pos at: 1) + deltaMove) ] . + [#right]->[ pos setY: ((pos at: 1) - deltaMove) ] . + [#up]->[ pos setX: ((pos at: 0) + deltaMove) ] . + [#down]->[ pos setX: ((pos at: 0) - deltaMove) ] } + ]. + + # Move it + aNodePath setPos: self.grid pos: pos. + + # Refresh DNA + self.updateDNAPosHpr: aNodePath. + # Position grid for placing next object + self.autoPositionGrid. + +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +keyboardXformNodePath: arrowDirection + (direct fControl) ifTrue: [ + direct selectedNodePaths + valuesDo: [ :np | self.keyboardRotateNodePath: np key: arrowDirection ]. + ] + ifFalse: [ + direct selectedNodePaths + valuesDo: [ :np | self.keyboardTranslateNodePath: np key: arrowDirection ]. + ]. +! ! + +!Level methodsFor: 'object operations' stamp: 'panda 00/00/0000 00:00'! +mouseCrank: aNodePath + # Rotate object about its origin, based upon current mouse position + # Positive X axis of object is rotated to line up with current Crank Dir + (or closest snapAngle degree angle if HPR Snap is on + (self.grid getMouseIntersectionPoint: self.hitPt ) + ifTrue: [self.crankDir = self.hitPt - self.crankOrigin. + ((self.crankDir length) > 1.0) + ifTrue: [ | deltaAngle newH | + deltaAngle = (self.getCrankAngle - startAngle). + newH = startH + deltaAngle. + self.hprSnap ifTrue: [ newH = newH roundTo: self.snapAngle. ]. + aNodePath setH: newH. + # record angle (used for placing new instance) + self.lastAngle = newH. + ]. + ]. +! ! +""" diff --git a/direct/src/leveleditor/PieMenu.py b/direct/src/leveleditor/PieMenu.py new file mode 100644 index 0000000000..14b8888800 --- /dev/null +++ b/direct/src/leveleditor/PieMenu.py @@ -0,0 +1,111 @@ +from PandaObject import * +from DirectGeometry import * + +class PieMenu(NodePath, PandaObject): + def __init__(self, direct, menu, action = None, fUpdateOnlyOnChange = 1): + NodePath.__init__(self) + # Become the menu + self.assign(menu) + # Initialize instance variables + self.direct = direct + self.numItems = self.getNumChildren() + self.degreesPerItem = 360.0/self.numItems + self.sfx = self.getSx() + self.sfz = self.getSz() + # Record target and action + self.action = action + self.initialState = None + # Marking lines + self.lines = LineNodePath(self) + self.lines.setColor(VBase4(1)) + self.lines.setThickness(1) + # Set flags + self.fUpdateOnlyOnChange = fUpdateOnlyOnChange + self.itemOffset = 0 + + def performAction(self, value): + if action: + action(value) + + def removePieMenuTask(self): + taskMgr.removeTasksNamed('pieMenuTask') + self.reparentTo(hidden) + self.lines.reset() + + def spawnPieMenuTask(self): + # Make sure no errant tasks lying around + taskMgr.removeTasksNamed('pieMenuTask') + + # Where did the user press the button? + self.originX = self.direct.chan.mouseX + self.originY = self.direct.chan.mouseY + + # Pop up menu + self.reparentTo(render2d) + self.setPos(self.originX,0.0,self.originY) + + # Start drawing the selection line + self.lines.reset() + self.lines.moveTo(0,0,0) + self.lines.drawTo(0,0,0) + self.lines.create() + + # Spawn task to update line and select new texture + self.currItem = -1 + t = Task.Task(self.pieMenuTask) + taskMgr.spawnTaskNamed(t, 'pieMenuTask') + + def pieMenuTask(self,state): + mouseX = self.direct.chan.mouseX + mouseY = self.direct.chan.mouseY + deltaX = mouseX - self.originX + deltaY = mouseY - self.originY + + # Update the line + self.lines.setVertex(1,(deltaX/sfx),0.0,(deltaY / sfz)) + + # How far from starting point has user moved the cursor? + if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)): + # In the center + if self.fUpdateOnlyOnChange: + # Only do this when things change + if (self.currItem != -1): + self.performAction(-1) + else: + # Alway let use know mouse is in the center + self.performAction(-1) + + self.currItem = -1 + # Interacting with menu + # subtract half a slice to effectively center item + menuAngle = rad2Deg(math.atan2(deltaY, deltaX)) + self.itemOffset + if menuAngle < 0.0: + menuAngle = menuAngle + 360.0 + menuAngle = menuAngle % 360.0 + newItem = math.floor(menuAngle / self.degreesPerItem) + + if self.fUpdateOnlyOnChange: + if (self.currItem != newItem): + self.performAction(newItem) + else: + self.performAction(newItem) + self.currItem = newItem + # Continue task + return Task.cont + + def setInitialState(self,state): + self.initialState = state + + def getInitialState(self): + return self.initialState + + def setItemOffset(self,newOffset): + self.itemOffset = newOffset + + def setNumItems(self,num): + self.numItems = num + self.degreesPerItem = 360.0 / self.numItems + self.itemOffset = self.degreesPerItem / 2.0 + + def setUpdateOnlyOnChange(self,flag): + self.fUpdateOnlyOnChange = flag diff --git a/direct/src/leveleditor/Sources.pp b/direct/src/leveleditor/Sources.pp new file mode 100644 index 0000000000..a03ea8c336 --- /dev/null +++ b/direct/src/leveleditor/Sources.pp @@ -0,0 +1,3 @@ +// For now, since we are not installing Python files, this file can +// remain empty. + diff --git a/direct/src/showbase/OnscreenText.py b/direct/src/showbase/OnscreenText.py index 72adb06420..5f3b452751 100644 --- a/direct/src/showbase/OnscreenText.py +++ b/direct/src/showbase/OnscreenText.py @@ -15,7 +15,7 @@ class OnscreenText(PandaObject, NodePath): NodePath.__init__(self) # make a text node - textNode = TextNode() + self.textNode = textNode = TextNode() textNode.setBillboard(0) textNode.setTextColor(0.0, 0.0, 0.0, 1.0) textNode.setCardColor(1.0, 1.0, 1.0, 1.0) @@ -51,3 +51,6 @@ class OnscreenText(PandaObject, NodePath): """ # render2d has x across and z up self.setPos(x, 0.0, y) + + def setColor(self, color): + self.textNode.setCardColor(color[0],color[1],color[2],color[3])