I dont know if this will help any one be able to use the LevelEditor but i combinded two files of the levelEditor and then opened it with note pad and this is the writing i got.
Ok, it wont let me post it so PM me if u want to see it.
[code][size=7]
from pandac.PandaModules import *
from direct.directbase.DirectStart import *
from direct.showbase.DirectObject import DirectObject
from PieMenu import *
import direct.gui.DirectGuiGlobals as DGG
from direct.showbase.TkGlobal import *
from direct.directtools.DirectUtil import *
from direct.directtools.DirectGeometry import *
from direct.tkwidgets.SceneGraphExplorer import *
from tkMessageBox import showinfo
from tkFileDialog import *
from Tkinter import *
#from whrandom import *
from random import *
from direct.tkwidgets import Floater
from direct.tkwidgets import VectorWidgets
import string
import os
import getopt
import sys
#import whrandom
import random
import types
from direct.task import Task
import Pmw
import builtin
[gjeon] to control avatar movement in drive mode
from direct.controls import ControlManager
from direct.controls import GravityWalker
from direct.controls import NonPhysicsWalker
from direct.interval.LerpInterval import LerpFunctionInterval
from otp.avatar import LocalAvatar
from toontown.toon import RobotToon
from otp.otpbase import OTPGlobals
Force direct and tk to be on
base.startDirect(fWantDirect = 1, fWantTk = 1)
visualizeZones = base.config.GetBool(“visualize-zones”, 0)
dnaDirectory = Filename.expandFrom(base.config.GetString(“dna-directory”, “$TTMODELS/src/dna”))
fUseCVS = base.config.GetBool(“level-editor-use-cvs”, 1)
useSnowTree = base.config.GetBool(“use-snow-tree”, 0)
Colors used by all color menus
DEFAULT_COLORS = [
Vec4(1, 1, 1, 1),
Vec4(0.75, 0.75, 0.75, 1.0),
Vec4(0.5, 0.5, 0.5, 1.0),
Vec4(0.25, 0.25, 0.25, 1.0)
]
The list of items with color attributes
COLOR_TYPES = [‘wall_color’, ‘window_color’,
‘window_awning_color’, ‘sign_color’, ‘door_color’,
‘door_awning_color’, ‘cornice_color’,
‘prop_color’]
The list of dna components maintained in the style attribute dictionary
DNA_TYPES = [‘wall’, ‘window’, ‘sign’, ‘door_double’, ‘door_single’, ‘cornice’, ‘toon_landmark’,
‘prop’, ‘street’]
BUILDING_TYPES = [‘10_10’, ‘20’, ‘10_20’, ‘20_10’, ‘10_10_10’,
‘4_21’, ‘3_22’, ‘4_13_8’, ‘3_13_9’, ‘10’,
‘12_8’, ‘13_9_8’, ‘4_10_10’, ‘4_10’, ‘4_20’,
]
BUILDING_HEIGHTS = [10, 14, 20, 24, 25, 30]
NUM_WALLS = [1, 2, 3]
LANDMARK_SPECIAL_TYPES = [’’, ‘hq’, ‘gagshop’, ‘clotheshop’, ‘petshop’, ‘kartshop’]
OBJECT_SNAP_POINTS = {
‘street_5x20’: [(Vec3(5.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_10x20’: [(Vec3(10.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_20x20’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_30x20’: [(Vec3(30.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_40x20’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_80x20’: [(Vec3(80.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_5x40’: [(Vec3(5.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_10x40’: [(Vec3(10.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_20x40’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_20x40_15’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_30x40’: [(Vec3(30.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_40x40’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_20x60’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_40x60’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_40x40_15’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_80x40’: [(Vec3(80.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_angle_30’: [(Vec3(0), Vec3(-30, 0, 0)),
(Vec3(0), Vec3(0))],
‘street_angle_45’: [(Vec3(0), Vec3(-45, 0, 0)),
(Vec3(0), Vec3(0))],
‘street_angle_60’: [(Vec3(0), Vec3(-60, 0, 0)),
(Vec3(0), Vec3(0))],
‘street_inner_corner’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_outer_corner’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_full_corner’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_tight_corner’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_tight_corner_mirror’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_double_corner’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_curved_corner’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_curved_corner_15’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_t_intersection’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_y_intersection’: [(Vec3(30.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_street_20x20’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_street_40x40’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_sidewalk_20x20’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_sidewalk_40x40’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_divided_transition’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_divided_40x70’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_divided_transition_15’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_divided_40x70_15’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_stairs_40x10x5’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_4way_intersection’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_incline_40x40x5’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_square_courtyard’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_70’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_70_exit’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_90’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_90_exit’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_70_15’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_70_15_exit’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_90_15’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_courtyard_90_15_exit’: [(Vec3(0.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_50_transition’: [(Vec3(10.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_20x50’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_40x50’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_keyboard_10x40’: [(Vec3(10.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_keyboard_20x40’: [(Vec3(20.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_keyboard_40x40’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
‘street_sunken_40x40’: [(Vec3(40.0, 0, 0), Vec3(0)),
(Vec3(0), Vec3(0))],
}
NEIGHBORHOOD DATA
If you run this from the command line you can pass in the hood codes
you want to load. For example:
ppython LevelEditor.py DD TT BR
if sys.argv[1:]:
try:
opts, pargs = getopt.getopt(sys.argv[1:], ‘’)
hoods = pargs
except Exception, e:
print e
If you do not run from the command line, we just load all of them
or you can hack this up for your own purposes.
else:
hoodString = base.config.GetString(‘level-editor-hoods’,
‘TT DD BR DG DL MM CC CL CM CS GS GZ OZ’)
hoods = string.split(hoodString)
The list of neighborhoods to edit
hoodIds = {‘TT’: ‘toontown_central’,
‘DD’: ‘donalds_dock’,
‘MM’: ‘minnies_melody_land’,
‘BR’: ‘the_burrrgh’,
‘DG’: ‘daisys_garden’,
‘DL’: ‘donalds_dreamland’,
‘CC’: ‘cog_hq_bossbot’,
‘CL’: ‘cog_hq_lawbot’,
‘CM’: ‘cog_hq_cashbot’,
‘CS’: ‘cog_hq_sellbot’,
‘GS’: ‘goofy_speedway’,
‘OZ’: ‘outdoor_zone’,
‘GZ’: ‘golf_zone’,
}
Init neighborhood arrays
NEIGHBORHOODS = []
NEIGHBORHOOD_CODES = {}
for hoodId in hoods:
if hoodIds.has_key(hoodId):
hoodName = hoodIds[hoodId]
NEIGHBORHOOD_CODES[hoodName] = hoodId
NEIGHBORHOODS.append(hoodName)
else:
print 'Error: no hood defined for: ', hoodId
Load DNA
try:
if dnaLoaded:
pass
except NameError:
print "Loading LevelEditor for hoods: ", hoods
# DNAStorage instance for storing level DNA info
# We need to use the __builtin__.foo syntax, not the
# __builtins__["foo"] syntax, since this file runs at the top
# level.
__builtin__.DNASTORE = DNASTORE = DNAStorage()
# Load the generic storage files
loadDNAFile(DNASTORE, 'dna/storage.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_4/dna/storage.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_5/dna/storage_town.dna', CSDefault, 1)
# loadDNAFile(DNASTORE, 'phase_5.5/dna/storage_estate.dna', CSDefault, 1)
# loadDNAFile(DNASTORE, 'phase_5.5/dna/storage_house_interior.dna', CSDefault, 1)
# Load all the neighborhood specific storage files
if 'TT' in hoods:
loadDNAFile(DNASTORE, 'phase_4/dna/storage_TT.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_4/dna/storage_TT_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_5/dna/storage_TT_town.dna', CSDefault, 1)
if 'DD' in hoods:
loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_DD_town.dna', CSDefault, 1)
if 'MM' in hoods:
loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_MM_town.dna', CSDefault, 1)
if 'BR' in hoods:
loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_BR_town.dna', CSDefault, 1)
if 'DG' in hoods:
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DG_town.dna', CSDefault, 1)
if 'DL' in hoods:
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL_sz.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_8/dna/storage_DL_town.dna', CSDefault, 1)
if 'CS' in hoods:
loadDNAFile(DNASTORE, 'phase_9/dna/storage_CS.dna', CSDefault, 1)
if 'GS' in hoods:
loadDNAFile(DNASTORE, 'phase_4/dna/storage_GS.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_4/dna/storage_GS_sz.dna', CSDefault, 1)
if 'OZ' in hoods:
loadDNAFile(DNASTORE, 'phase_6/dna/storage_OZ.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_OZ_sz.dna', CSDefault, 1)
if 'GZ' in hoods:
loadDNAFile(DNASTORE, 'phase_6/dna/storage_GZ.dna', CSDefault, 1)
loadDNAFile(DNASTORE, 'phase_6/dna/storage_GZ_sz.dna', CSDefault, 1)
if 'CC' in hoods:
loadDNAFile(DNASTORE, 'phase_12/dna/storage_CC_sz.dna', CSDefault, 1)
__builtin__.dnaLoaded = 1
Precompute class types for type comparisons
DNA_CORNICE = DNACornice.getClassType()
DNA_DOOR = DNADoor.getClassType()
DNA_FLAT_DOOR = DNAFlatDoor.getClassType()
DNA_FLAT_BUILDING = DNAFlatBuilding.getClassType()
DNA_NODE = DNANode.getClassType()
DNA_GROUP = DNAGroup.getClassType()
DNA_VIS_GROUP = DNAVisGroup.getClassType()
DNA_LANDMARK_BUILDING = DNALandmarkBuilding.getClassType()
DNA_NODE = DNANode.getClassType()
DNA_PROP = DNAProp.getClassType()
DNA_SIGN = DNASign.getClassType()
DNA_SIGN_BASELINE = DNASignBaseline.getClassType()
DNA_SIGN_TEXT = DNASignText.getClassType()
DNA_SIGN_GRAPHIC = DNASignGraphic.getClassType()
DNA_STREET = DNAStreet.getClassType()
DNA_WALL = DNAWall.getClassType()
DNA_WINDOWS = DNAWindows.getClassType()
DNA Utility functions (possible class extensions?)
def DNARemoveChildren(dnaObject):
“”" Utility function to delete all the children of a DNANode “”"
children = []
for i in range(dnaObject.getNumChildren()):
children.append(dnaObject.at(i))
for child in children:
dnaObject.remove(child)
DNASTORE.removeDNAGroup(child)
def DNARemoveChildOfClass(dnaNode, classType, childNum = 0):
“”" Remove the nth object of that type you come across “”"
childCount = 0
for i in range(dnaNode.getNumChildren()):
child = dnaNode.at(i)
if DNAClassEqual(child, classType):
if childCount == childNum:
dnaNode.remove(child)
DNASTORE.removeDNAGroup(child)
return 1
childCount = childCount + 1
# None found
return 0
def DNARemoveAllChildrenOfClass(dnaNode, classType):
“”" Remove the objects of that type “”"
children = []
for i in range(dnaNode.getNumChildren()):
child=dnaNode.at(i)
if DNAClassEqual(child, classType):
children.append(child)
for child in children:
dnaNode.remove(child)
DNASTORE.removeDNAGroup(child)
def DNAGetChildren(dnaNode, classType=None):
“”" Return the objects of that type “”"
children = []
for i in range(dnaNode.getNumChildren()):
child=dnaNode.at(i)
if ((not classType)
or DNAClassEqual(child, classType)):
children.append(child)
return children
def DNAGetChild(dnaObject, type = DNA_NODE, childNum = 0):
childCount = 0
for i in range(dnaObject.getNumChildren()):
child = dnaObject.at(i)
if DNAClassEqual(child, type):
if childCount == childNum:
return child
childCount = childCount + 1
# Not found
return None
def DNAGetChildRecursive(dnaObject, type = DNA_NODE, childNum = 0):
childCount = 0
for i in range(dnaObject.getNumChildren()):
child = dnaObject.at(i)
if DNAClassEqual(child, type):
if childCount == childNum:
return child
childCount = childCount + 1
else:
child = DNAGetChildRecursive(child, type, childNum-childCount)
if child:
return child
# Not found
return None
def DNAGetChildOfClass(dnaNode, classType):
for i in range(dnaNode.getNumChildren()):
child = dnaNode.at(i)
if DNAClassEqual(child, classType):
return child
# Not found
return None
def DNAGetClassType(dnaObject):
return dnaObject.class.getClassType()
def DNAClassEqual(dnaObject, classType):
return DNAGetClassType(dnaObject).eq(classType)
def DNAIsDerivedFrom(dnaObject, classType):
return DNAGetClassType(dnaObject).isDerivedFrom(classType)
def DNAGetWallHeights(aDNAFlatBuilding):
“”" Get a list of wall heights for a given flat building “”"
# Init variables
heightList = []
offsetList = []
offset = 0.0
# Compute wall heights
for i in range(aDNAFlatBuilding.getNumChildren()):
child = aDNAFlatBuilding.at(i)
if DNAClassEqual(child, DNA_WALL):
height = child.getHeight()
heightList.append(height)
offsetList.append(offset)
offset = offset + height
return heightList, offsetList
def DNAGetBaselineString(baseline):
s=""
for i in range(baseline.getNumChildren()):
child = baseline.at(i)
if DNAClassEqual(child, DNA_SIGN_TEXT):
s=s+child.getLetters()
elif DNAClassEqual(child, DNA_SIGN_GRAPHIC):
s=s+’[’+child.getCode()+’]’
return s
def DNASetBaselineString(baseline, text):
# TODO: Instead of removing all the text and replacing it,
# replace each text item and then add or remove at the end.
# This should allow inlined graphics to stay in place.
# end of todo.
DNARemoveAllChildrenOfClass(baseline, DNA_SIGN_TEXT)
# We can't just blindly iterate through the text, because it might
# be utf-8 encoded, meaning some characters are represented using
# multi-byte sequences. Instead, create a TextNode and use it to
# iterate through the characters of the text.
t = TextNode('')
t.setText(text)
for i in range(t.getNumChars()):
ch = t.getEncodedChar(i)
text=DNASignText("text")
text.setLetters(ch)
baseline.add(text)
class LevelEditor(NodePath, DirectObject):
“”“Class used to create a Toontown LevelEditor object”""
# Init the list of callbacks:
selectedNodePathHookHooks=[]
deselectedNodePathHookHooks=[]
# Primary variables:
# DNAData: DNA object holding DNA info about level
# DNAToplevel: Top level DNA Node, all DNA objects descend from this node
# NPToplevel: Corresponding Node Path
# DNAParent: Current DNA Node that new objects get added to
# NPParent: Corresponding Node Path
# DNAVisGroup: Current DNAVisGroup that new objects get added to
# NPVisGroup: Corresponding Node Path
# selectedDNARoot: DNA Node of currently selected object
# selectedNPRoot: Corresponding Node Path
# DNATarget: Subcomponent being modified by Pie Menu
def __init__(self, hoods = hoods):
# Make the level editor a node path so that you can show/hide
# The level editor separately from loading/saving the top level node
# Initialize superclass
NodePath.__init__(self)
# Become the new node path
self.assign(hidden.attachNewNode('LevelEditor'))
# Enable replaceSelected by default:
self.replaceSelectedEnabled=1
self.removeHookList=[self.landmarkBlockRemove]
# Start block ID at 0 (it will be incremented before use (to 1)):
self.landmarkBlock=0
# Create ancillary objects
# Style manager for keeping track of styles/colors
self.styleManager = LevelStyleManager()
# Load neighborhood maps
self.createLevelMaps()
# Marker for showing next insertion point
self.createInsertionMarker()
# Create level Editor Panel
self.panel = LevelEditorPanel(self)
# Used to store whatever edges and points are loaded in the level
self.edgeDict = {}
self.np2EdgeDict = {}
self.pointDict = {}
self.point2edgeDict = {}
self.cellDict = {}
self.visitedPoints = []
self.visitedEdges = []
self.zoneLabels = []
# Initialize LevelEditor variables DNAData, DNAToplevel, NPToplevel
# DNAParent, NPParent, groupNum, lastAngle
# Pass in the new toplevel group and don't clear out the old
# toplevel group (since it doesn't exist yet)
self.reset(fDeleteToplevel = 0, fCreateToplevel = 1)
# The list of events the level editor responds to
self.actionEvents = [
# Node path events
('preRemoveNodePath', self.removeNodePathHook),
# Actions in response to DIRECT operations
('DIRECT_selectedNodePath', self.selectedNodePathHook),
('DIRECT_deselectedNodePath', self.deselectedNodePathHook),
('DIRECT_manipulateObjectCleanup', self.updateSelectedPose),
('DIRECT_nodePathSetName', self.setName),
('DIRECT_activeParent', self.setActiveParent),
('DIRECT_reparent', self.reparent),
('RGBPanel_setColor', self.setColor),
# Actions in response to Level Editor Panel operations
('SGE_Add Group', self.addGroup),
('SGE_Add Vis Group', self.addVisGroup),
# Actions in response to Pie Menu interaction
('select_building_style_all', self.setBuildingStyle),
('select_building_type', self.setBuildingType),
('select_building_width', self.setBuildingWidth),
('select_cornice_color', self.setDNATargetColor),
('select_cornice_orientation', self.setDNATargetOrientation),
('select_cornice_texture', self.setDNATargetCode, ['cornice']),
('select_sign_color', self.setDNATargetColor),
('select_sign_orientation', self.setDNATargetOrientation),
('select_sign_texture', self.setDNATargetCode, ['sign']),
('select_baseline_style', self.panel.setSignBaselineStyle),
('select_door_color', self.setDNATargetColor),
('select_door_orientation', self.setDNATargetOrientation),
('select_door_single_texture', self.setDNATargetCode, ['door']),
('select_door_double_texture', self.setDNATargetCode, ['door']),
('select_door_awning_texture', self.setDNATargetCode,
['door_awning']),
('select_door_awning_color', self.setDNATargetColor),
('select_window_color', self.setDNATargetColor),
('select_window_count', self.setWindowCount),
('select_window_orientation', self.setDNATargetOrientation),
('select_window_texture', self.setDNATargetCode, ['windows']),
('select_window_awning_texture', self.setDNATargetCode,
['window_awning']),
('select_window_awning_color', self.setDNATargetColor),
('select_wall_style', self.setWallStyle),
('select_wall_color', self.setDNATargetColor),
('select_wall_orientation', self.setDNATargetOrientation),
('select_wall_texture', self.setDNATargetCode, ['wall']),
('select_toon_landmark_texture', self.setDNATargetCode,
['landmark']),
('select_toon_landmark_door_color', self.setDNATargetColor),
('select_toon_landmark_door_orientation',
self.setDNATargetOrientation),
('select_landmark_door_texture', self.setDNATargetCode,
['landmark_door']),
('select_street_texture', self.setDNATargetCode, ['street']),
('select_prop_texture', self.setDNATargetCode, ['prop']),
('select_prop_color', self.setDNATargetColor),
# Hot key actions
('a', self.autoPositionGrid),
('j', self.jumpToInsertionPoint),
('arrow_left', self.keyboardXformSelected, ['left', 'xlate']),
('arrow_right', self.keyboardXformSelected, ['right', 'xlate']),
('arrow_up', self.keyboardXformSelected, ['up','xlate']),
('arrow_down', self.keyboardXformSelected, ['down','xlate']),
('control-arrow_left', self.keyboardXformSelected, ['left', 'rotate']),
('control-arrow_right', self.keyboardXformSelected, ['right', 'rotate']),
('control-arrow_up', self.keyboardXformSelected, ['up', 'rotate']),
('control-arrow_down', self.keyboardXformSelected, ['down', 'rotate']),
('shift-s', self.placeSuitPoint),
('shift-c', self.placeBattleCell),
('k', self.addToLandmarkBlock),
('shift-k', self.toggleShowLandmarkBlock),
('%', self.pdbBreak),
('page_up', self.pageUp),
('page_down', self.pageDown),
]
self.overrideEvents = [
('page_up', base.direct),
('page_down', base.direct)
]
# Initialize state
# Make sure direct is running
base.direct.enable()
# And only the appropriate handles are showing
base.direct.widget.disableHandles(['x-ring', 'x-disc',
'y-ring', 'y-disc',
'z-post'])
# Initialize camera
base.camLens.setNear(1.0)
base.camLens.setFar(3000)
base.direct.camera.setPos(0, -10, 10)
# Initialize drive mode
self.configureDriveModeCollisionData()
# Init visibility variables
self.__zoneId = None
# Hide (disable) grid initially
self.showGrid(0)
# Create variable for vis groups panel
self.vgpanel = None
# Start off enabled
self.enable()
# SUIT POINTS
# Create a sphere model to show suit points
self.suitPointMarker = loader.loadModel('models/misc/sphere')
self.suitPointMarker.setScale(0.25)
# Initialize the suit points
self.startSuitPoint = None
self.endSuitPoint = None
self.currentSuitPointType = DNASuitPoint.STREETPOINT
# BATTLE CELLS
self.battleCellMarker = loader.loadModel('models/misc/sphere')
self.battleCellMarker.setName('battleCellMarker')
self.battleCellMarker.setScale(1)
self.currentBattleCellType = "20w 20l"
# Update panel
# Editing the first hood id on the list
self.outputFile = None
self.setEditMode(NEIGHBORHOODS[0])
# Start of with first item in lists
self.panel.streetSelector.selectitem(0)
self.panel.streetSelector.invoke()
self.panel.toonBuildingSelector.selectitem(0)
self.panel.toonBuildingSelector.invoke()
self.panel.landmarkBuildingSelector.selectitem(0)
self.panel.landmarkBuildingSelector.invoke()
self.panel.propSelector.selectitem(0)
self.panel.propSelector.invoke()
# Start off with 20 foot buildings
self.panel.twentyFootButton.invoke()
# Update scene graph explorer
self.panel.sceneGraphExplorer.update()
# Karting
# the key is the barricade number, the data is a two element list,
# first number is the first bldg group that uses this
# the second is the last bldg group that uses this
self.outerBarricadeDict = {}
self.innerBarricadeDict = {}
# [gjeon] to find out currently moving camera in maya mode
self.mouseMayaCamera = False
# [gjeon] to find out drive mode stat
self.fDrive = False
# [gjeon] to control drive mode
self.controlManager = None
self.avatar = None
self.fov = 60
self.isPageUp=0
self.isPageDown=0
# ENABLE/DISABLE
def enable(self):
""" Enable level editing and show level """
# Make sure level is visible
self.reparentTo(base.direct.group)
self.show()
# [gjeon] Ignore overridden events
for event in self.overrideEvents:
event[1].ignore(event[0])
# Add all the action events
for event in self.actionEvents:
if len(event) == 3:
self.accept(event[0], event[1], event[2])
else:
self.accept(event[0], event[1])
# Enable mouse interaction (pie menus)
self.enableMouse()
# Spawn task to keep insertion marker aligned with grid
self.spawnInsertionMarkerTask()
def disable(self):
""" Disable level editing and hide level """
# Deselect everything as a precaution
base.direct.deselectAll()
# Hide the level
self.reparentTo(hidden)
# Ignore the hooks
for eventPair in self.actionEvents:
self.ignore(eventPair[0])
# These are added outside of actionEvents list
self.ignore('insert')
self.ignore('space')
# Disable Pie Menu mouse interaction
self.disableMouse()
# Remove insertion marker task
taskMgr.remove('insertionMarkerTask')
def reset(self, fDeleteToplevel = 1, fCreateToplevel = 1,
fUpdateExplorer = 1):
"""
Reset level and re-initialize main class variables
Pass in the new top level group
"""
# Reset path markers
self.resetPathMarkers()
# Reset battle cell markers
self.resetBattleCellMarkers()
if fDeleteToplevel:
# First destroy existing scene-graph/DNA hierarchy
self.deleteToplevel()
# Clear DNASTORE
DNASTORE.resetDNAGroups()
# Reset DNA VIS Groups
DNASTORE.resetDNAVisGroups()
DNASTORE.resetSuitPoints()
DNASTORE.resetBattleCells()
# Create fresh DNA DATA
self.DNAData = DNAData('level_data')
# Create new toplevel node path and DNA
if fCreateToplevel:
self.createToplevel(DNANode('level'))
# Initialize variables
# Reset grid
base.direct.grid.setPosHprScale(0, 0, 0, 0, 0, 0, 1, 1, 1)
# The selected DNA Object/NodePath
self.selectedDNARoot = None
self.selectedNPRoot = None
self.selectedSuitPoint = None
self.lastLandmarkBuildingDNA = None
self.showLandmarkBlockToggleGroup = None
# Set active target (the subcomponent being modified)
self.DNATarget = None
self.DNATargetParent = None
# Set count of groups added to level
self.setGroupNum(0)
# Heading angle of last object added to level
self.setLastAngle(0.0)
# Last wall and building modified using pie menus
self.lastSign = None
self.lastWall = None
self.lastBuilding = None
# Code of last selected object (for autopositionGrid)
self.snapList = []
# Last menu used
self.activeMenu = None
# For highlighting suit paths
self.visitedPoints = []
self.visitedEdges = []
# Update scene graph explorer
if fUpdateExplorer:
self.panel.sceneGraphExplorer.update()
self.outputFile = None
self.panel["title"] = 'Level Editor: No file loaded'
def deleteToplevel(self):
# Destory old toplevel node path and DNA
# First the toplevel DNA
self.DNAData.remove(self.DNAToplevel)
# Then the toplevel Node Path
self.NPToplevel.removeNode()
def createToplevel(self, dnaNode, nodePath = None):
# When you create a new level, data is added to this node
# When you load a DNA file, you replace this node with the new data
self.DNAToplevel = dnaNode
self.DNAData.add(self.DNAToplevel)
if nodePath:
# Node path given, use it
self.NPToplevel = nodePath
self.NPToplevel.reparentTo(self)
else:
# No node path given, traverse
self.NPToplevel = self.DNAToplevel.traverse(self, DNASTORE, 1)
# Update parent pointers
self.DNAParent = self.DNAToplevel
self.NPParent = self.NPToplevel
self.VGParent = None
# Add toplevel node path for suit points
self.suitPointToplevel = self.NPToplevel.attachNewNode('suitPoints')
def destroy(self):
""" Disable level editor and destroy node path """
self.disable()
self.removeNode()
self.panel.destroy()
if self.vgpanel:
self.vgpanel.destroy()
def useDirectFly(self):
""" Disable player camera controls/enable direct camera control """
# Turn off collision traversal
self.traversalOff()
# Turn on collisions
self.collisionsOff()
# Turn on visiblity
self.visibilityOff()
base.camera.wrtReparentTo(render)
# Reset cam
base.camera.iPos(base.cam)
base.cam.iPosHpr()
# Renable mouse
self.enableMouse()
base.direct.enable()
# [gjeon] disable avatar and controlManager
if (self.avatar):
self.avatar.reparentTo(hidden)
self.avatar.stopUpdateSmartCamera()
if (self.controlManager):
self.controlManager.disable()
self.fDrive = False
def lerpCameraP(self, p, time):
"""
lerp the camera P over time (used by the battle)
"""
taskMgr.remove('cam-p-lerp')
if self.avatar:
self.avatar.stopUpdateSmartCamera()
def setCamP(p):
base.camera.setP(p)
if self.isPageUp:
fromP = 36.8699
elif self.isPageDown:
fromP = -27.5607
else:
fromP = 0
self.camLerpInterval = LerpFunctionInterval(setCamP,
fromData=fromP, toData=p, duration=time,
name='cam-p-lerp')
self.camLerpInterval.start()
def clearPageUpDown(self):
if self.isPageDown or self.isPageUp:
self.lerpCameraP(0, 0.6)
self.isPageDown = 0
self.isPageUp = 0
#self.setCameraPositionByIndex(self.cameraIndex)
if self.avatar:
self.avatar.startUpdateSmartCamera()
def pageUp(self):
if not self.isPageUp:
self.lerpCameraP(36.8699, 0.6)
self.isPageDown = 0
self.isPageUp = 1
#self.setCameraPositionByIndex(self.cameraIndex)
else:
self.clearPageUpDown()
def pageDown(self):
if not self.isPageDown:
self.lerpCameraP(-27.5607, 0.6)
self.isPageUp = 0
self.isPageDown = 1
#self.setCameraPositionByIndex(self.cameraIndex)
else:
self.clearPageUpDown()
def useDriveMode(self):
""" Lerp down to eye level then switch to Drive mode """
# create avatar and set it's location to the camera
if (self.avatar == None):
#self.avatar = RobotToon.RobotToon()
self.avatar = LEAvatar(None, None, None)
base.localAvatar = self.avatar
self.avatar.doId = 0
self.avatar.robot = RobotToon.RobotToon()
self.avatar.robot.reparentTo(self.avatar)
self.avatar.setHeight(self.avatar.robot.getHeight())
self.avatar.setName("The Inspector")
self.avatar.robot.loop('neutral')
self.avatar.setPos(base.camera.getPos())
self.avatar.reparentTo(render)
pos = base.direct.camera.getPos()
pos.setZ(4.0)
hpr = base.direct.camera.getHpr()
hpr.set(hpr[0], 0.0, 0.0)
t = base.direct.camera.lerpPosHpr(pos, hpr, 1.0, blendType = ‘easeInOut’,
task = ‘manipulateCamera’)
# Note, if this dies an unatural death, this could screw things up
# t.uponDeath = self.switchToDriveMode
self.switchToDriveMode(None)
self.fDrive = True
#[gjeon] deselect
base.direct.selected.deselect(base.direct.selected.last)
def switchToDriveMode(self, state):
""" Disable direct camera manipulation and enable player drive mode """
#base.direct.minimumConfiguration()
#base.direct.manipulationControl.disableManipulation()
# Update vis data
self.initVisibilityData()
# Switch to drive mode
base.useDrive()
# Move cam up and back
base.cam.setPos(0, -5, 4)
# And move down and forward to compensate
base.camera.setPos(base.camera, 0, 5, -4)
# Make sure we’re where we want to be
pos = base.direct.camera.getPos()
pos.setZ(0.0)
hpr = base.direct.camera.getHpr()
hpr.set(hpr[0], 0.0, 0.0)
# Fine tune the drive mode
base.mouseInterface.node().setPos(pos)
base.mouseInterface.node().setHpr(hpr)
base.mouseInterface.node().setForwardSpeed(0)
base.mouseInterface.node().setReverseSpeed(0)
base.camera.wrtReparentTo(self.avatar)
base.camera.setHpr(0, 0, 0)
#base.camera.setPos(0, 0, 0)
base.camera.setPos(0, -11.8125, 3.9375)
base.camLens.setFov(VBase2(60, 46.8265))
#self.initializeSmartCameraCollisions()
#self._smartCamEnabled = False
# Turn on collisions
if self.panel.fColl.get():
self.collisionsOn()
# Turn on visiblity
if self.panel.fVis.get():
self.visibilityOn()
# Turn on collision traversal
if self.panel.fColl.get() or self.panel.fVis.get():
self.traversalOn()
if (self.controlManager == None):
# create player movement controls,camera controls, and avatar
self.controlManager = ControlManager.ControlManager()
avatarRadius = 1.4
floorOffset = OTPGlobals.FloorOffset
reach = 4.0
#walkControls=GravityWalker.GravityWalker(gravity = -32.1740 * 2.0)
walkControls=NonPhysicsWalker.NonPhysicsWalker()
walkControls.setWallBitMask(OTPGlobals.WallBitmask)
walkControls.setFloorBitMask(OTPGlobals.FloorBitmask)
walkControls.initializeCollisions(self.cTrav, self.avatar,
avatarRadius, floorOffset, reach)
self.controlManager.add(walkControls, "walk")
self.controlManager.use("walk", self)
# set speeds after adding controls to the control manager
self.controlManager.setSpeeds(
OTPGlobals.ToonForwardSpeed,
OTPGlobals.ToonJumpForce,
OTPGlobals.ToonReverseSpeed,
OTPGlobals.ToonRotateSpeed
)
else:
self.controlManager.enable()
self.avatarAnimTask = taskMgr.add(self.avatarAnimate, 'avatarAnimTask', 24)
self.avatar.startUpdateSmartCamera()
self.avatarMoving = 0
#--------------------------------------------------------------------------
# Function: animate avatar model based on if it is moving
# Parameters: none
# Changes:
# Returns:
#--------------------------------------------------------------------------
def avatarAnimate(self,task=None):
if (self.controlManager):
moving = self.controlManager.currentControls.speed or self.controlManager.currentControls.slideSpeed or self.controlManager.currentControls.rotationSpeed
if (moving and
self.avatarMoving == 0):
self.clearPageUpDown()
# moving, play walk anim
if (self.controlManager.currentControls.speed < 0 or
self.controlManager.currentControls.rotationSpeed):
self.avatar.robot.loop('walk')
else:
self.avatar.robot.loop('run')
self.avatarMoving = 1
elif (moving == 0 and
self.avatarMoving == 1):
# no longer moving, play neutral anim
self.avatar.robot.loop('neutral')
self.avatarMoving = 0
return Task.cont
def configureDriveModeCollisionData(self):
"""
Set up the local avatar for collisions
"""
# Set up the collision sphere
# This is a sphere on the ground to detect barrier collisions
self.cSphere = CollisionSphere(0.0, 0.0, 0.0, 1.5)
self.cSphereNode = CollisionNode('cSphereNode')
self.cSphereNode.addSolid(self.cSphere)
self.cSphereNodePath = camera.attachNewNode(self.cSphereNode)
self.cSphereNodePath.hide()
self.cSphereBitMask = BitMask32.bit(0)
self.cSphereNode.setFromCollideMask(self.cSphereBitMask)
self.cSphereNode.setIntoCollideMask(BitMask32.allOff())
# Set up the collison ray
# This is a ray cast from your head down to detect floor polygons
self.cRay = CollisionRay(0.0, 0.0, 6.0, 0.0, 0.0, -1.0)
self.cRayNode = CollisionNode('cRayNode')
self.cRayNode.addSolid(self.cRay)
self.cRayNodePath = camera.attachNewNode(self.cRayNode)
self.cRayNodePath.hide()
self.cRayBitMask = BitMask32.bit(1)
self.cRayNode.setFromCollideMask(self.cRayBitMask)
self.cRayNode.setIntoCollideMask(BitMask32.allOff())
# set up wall collision mechanism
self.pusher = CollisionHandlerPusher()
self.pusher.setInPattern("enter%in")
self.pusher.setOutPattern("exit%in")
# set up floor collision mechanism
self.lifter = CollisionHandlerFloor()
self.lifter.setInPattern("on-floor")
self.lifter.setOutPattern("off-floor")
self.floorOffset = 0.1
self.lifter.setOffset(self.floorOffset)
# Limit our rate-of-fall with the lifter.
# If this is too low, we actually "fall" off steep stairs
# and float above them as we go down. I increased this
# from 8.0 to 16.0 to prevent this
self.lifter.setMaxVelocity(16.0)
# set up the collision traverser
self.cTrav = CollisionTraverser("LevelEditor")
self.cTrav.setRespectPrevTransform(1)
# activate the collider with the traverser and pusher
#self.pusher.addCollider(self.cSphereNodePath, base.camera, base.drive.node())
#self.lifter.addCollider(self.cRayNodePath, base.camera, base.drive.node())
# A map of zone ID's to a list of nodes that are visible from
# that zone.
self.nodeDict = {}
# A map of zone ID's to the particular node that corresponds
# to that zone.
self.zoneDict = {}
# A list of all visible nodes
self.nodeList = []
# Flag for bootstrapping visibility
self.fVisInit = 0
def traversalOn(self):
base.cTrav = self.cTrav
def traversalOff(self):
base.cTrav = 0
def collisionsOff(self):
self.cTrav.removeCollider(self.cSphereNodePath)
def collisionsOn(self):
self.collisionsOff()
self.cTrav.addCollider(self.cSphereNodePath, self.pusher)
def toggleCollisions(self):
if self.panel.fColl.get():
self.collisionsOn()
self.traversalOn()
else:
self.collisionsOff()
if (not (self.panel.fColl.get() or self.panel.fVis.get())):
self.traversalOff()
def initVisibilityData(self):
# First make sure everything is shown
self.showAllVisibles()
# A map of zone ID's to a list of nodes that are visible from
# that zone.
self.nodeDict = {}
# A map of zone ID's to the particular node that corresponds
# to that zone.
self.zoneDict = {}
# A list of all visible nodes
self.nodeList = []
# NOTE: this should change to find the groupnodes in
# the dna storage instead of searching through the tree
for i in range(DNASTORE.getNumDNAVisGroups()):
groupFullName = DNASTORE.getDNAVisGroupName(i)
groupName = self.extractGroupName(groupFullName)
zoneId = int(groupName)
self.nodeDict[zoneId] = []
self.zoneDict[zoneId] = self.NPToplevel.find("**/" + groupName)
# TODO: we only need to look from the top of the hood
# down one level to find the vis groups as an optimization
groupNode = self.NPToplevel.find("**/" + groupFullName)
if groupNode.isEmpty():
print "Could not find visgroup"
self.nodeList.append(groupNode)
for j in range(DNASTORE.getNumVisiblesInDNAVisGroup(i)):
visName = DNASTORE.getVisibleName(i, j)
visNode = self.NPToplevel.find("**/" + visName)
self.nodeDict[zoneId].append(visNode)
# Rename the floor polys to have the same name as the
# visgroup they are in... This makes visibility possible.
self.renameFloorPolys(self.nodeList)
# Init vis flag
self.fVisInit = 1
def extractGroupName(self, groupFullName):
# The Idea here is that group names may have extra flags associated
# with them that tell more information about what is special about
# the particular vis zone. A normal vis zone might just be "13001",
# but a special one might be "14356:safe_zone" or
# "345:safe_zone:exit_zone"... These are hypotheticals. The main
# idea is that there are colon separated flags after the initial
# zone name.
return(string.split(groupFullName, ":", 1)[0])
def renameFloorPolys(self, nodeList):
for i in nodeList:
# Get all the collision nodes in the vis group
collNodePaths = i.findAllMatches("**/+CollisionNode")
numCollNodePaths = collNodePaths.getNumPaths()
visGroupName = i.node().getName()
for j in range(numCollNodePaths):
collNodePath = collNodePaths.getPath(j)
bitMask = collNodePath.node().getIntoCollideMask()
if bitMask.getBit(1):
# Bit 1 is the floor collision bit. This renames
# all floor collision polys to the same name as their
# visgroup.
collNodePath.node().setName(visGroupName)
def hideAllVisibles(self):
for i in self.nodeList:
i.hide()
def showAllVisibles(self):
for i in self.nodeList:
i.show()
i.clearColor()
def visibilityOn(self):
self.visibilityOff()
# Accept event
self.accept("on-floor", self.enterZone)
# Add collider
self.cTrav.addCollider(self.cRayNodePath, self.lifter)
# Reset lifter
self.lifter.clear()
# Reset flag
self.fVisInit = 1
def visibilityOff(self):
self.ignore("on-floor")
self.cTrav.removeCollider(self.cRayNodePath)
self.showAllVisibles()
def toggleVisibility(self):
if self.panel.fVis.get():
self.visibilityOn()
self.traversalOn()
else:
self.visibilityOff()
if (not (self.panel.fColl.get() or self.panel.fVis.get())):
self.traversalOff()
def enterZone(self, newZone):
return
"""
Puts the toon in the indicated zone. newZone may either be a
CollisionEntry object as determined by a floor polygon, or an
integer zone id. It may also be None, to indicate no zone.
"""
# First entry into a zone, hide everything
if self.fVisInit:
self.hideAllVisibles()
self.fVisInit = 0
# Get zone id
if isinstance(newZone, CollisionEntry):
# Get the name of the collide node
try:
newZoneId = int(newZone.getIntoNode().getName())
except:
newZoneId = 0
else:
newZoneId = newZone
# Ensure we have vis data
assert self.nodeDict
# Hide the old zone (if there is one)
if self.__zoneId != None:
for i in self.nodeDict[self.__zoneId]:
i.hide()
# Show the new zone
if newZoneId != None:
for i in self.nodeDict[newZoneId]:
i.show()
# Make sure we changed zones
if newZoneId != self.__zoneId:
if self.panel.fVisZones.get():
# Set a color override on our zone to make it obvious what
# zone we're in.
if self.__zoneId != None:
self.zoneDict[self.__zoneId].clearColor()
if newZoneId != None:
self.zoneDict[newZoneId].setColor(0, 0, 1, 1, 100)
# The new zone is now old
self.__zoneId = newZoneId
def enableMouse(self):
""" Enable Pie Menu interaction (and disable player camera control) """
# Turn off player camera control
base.disableMouse()
# Handle mouse events for pie menus
self.accept('DIRECT-mouse3', self.levelHandleMouse3)
self.accept('DIRECT-mouse3Up', self.levelHandleMouse3Up)
def disableMouse(self):
""" Disable Pie Menu interaction """
# Disable handling of mouse events
self.ignore('DIRECT-mouse3')
self.ignore('DIRECT-mouse3Up')
# LEVEL OBJECT MANAGEMENT FUNCTIONS
def findDNANode(self, nodePath):
""" Find node path's DNA Object in DNAStorage (if any) """
if nodePath:
return DNASTORE.findDNAGroup(nodePath.node())
else:
return None
def replaceSelected(self):
if self.replaceSelectedEnabled:
# Update visible geometry using new DNA
newRoot = self.replace(self.selectedNPRoot, self.selectedDNARoot)
# Reselect node path and respawn followSelectedNodePathTask
base.direct.select(newRoot)
def replace(self, nodePath, dnaNode):
""" Replace a node path with the results of a DNANode traversal """
# Find node path's parent
parent = nodePath.getParent()
dnaParent = dnaNode.getParent()
# Get rid of the old node path and remove its DNA and
# node relations from the DNA Store
self.remove(dnaNode, nodePath)
# Traverse the old (modified) dna to create the new node path
newNodePath = dnaNode.traverse(parent, DNASTORE, 1)
# Add it back to the dna parent
dnaParent.add(dnaNode)
# Update scene graph explorer
# self.panel.sceneGraphExplorer.update()
# Return new node path
return newNodePath
def remove(self, dnaNode, nodePath):
"""
Delete DNA and Node relation from DNA Store and remove the node
path from the scene graph.
"""
# First delete DNA and node relation from the DNA Store
if dnaNode:
# Get DNANode's parent
parentDNANode = dnaNode.getParent()
if parentDNANode:
# Remove DNANode from its parent
parentDNANode.remove(dnaNode)
# Delete DNA and associated Node Relations from DNA Store
DNASTORE.removeDNAGroup(dnaNode)
if nodePath:
# Next deselect nodePath to avoid having bad node paths in the dict
base.direct.deselect(nodePath)
# Now you can get rid of the node path
nodePath.removeNode()
def removeNodePathHook(self, nodePath):
dnaNode = self.findDNANode(nodePath)
# Does the node path correspond to a DNA Object
if dnaNode:
for hook in self.removeHookList:
hook(dnaNode, nodePath)
# Get DNANode's parent
parentDNANode = dnaNode.getParent()
if parentDNANode:
# Remove DNANode from its parent
parentDNANode.remove(dnaNode)
# Delete DNA and associated Node Relations from DNA Store
DNASTORE.removeDNAGroup(dnaNode)
else:
pointOrCell, type = self.findPointOrCell(nodePath)
if pointOrCell and type:
if (type == 'suitPointMarker'):
print 'Suit Point:', pointOrCell
if DNASTORE.removeSuitPoint(pointOrCell):
print "Removed from DNASTORE"
else:
print "Not found in DNASTORE"
# Remove point from pointDict
del(self.pointDict[pointOrCell])
# Remove point from visitedPoints list
if pointOrCell in self.visitedPoints:
self.visitedPoints.remove(pointOrCell)
# Update edge related dictionaries
for edge in self.point2edgeDict[pointOrCell]:
# Is it still in edge dict?
oldEdgeLine = self.edgeDict.get(edge, None)
if oldEdgeLine:
del self.edgeDict[edge]
oldEdgeLine.reset()
del oldEdgeLine
# Find other endpoints of edge and clear out
# corresponding point2edgeDict entry
startPoint = edge.getStartPoint()
endPoint = edge.getEndPoint()
if pointOrCell == startPoint:
self.point2edgeDict[endPoint].remove(edge)
elif pointOrCell == endPoint:
Yay, i got it
:’( Thats not all of it. but u get the idea.
ok i think i got it.
In this part of the above there is a part that says;
i think if you where to put in
ppython LevelEditor.py DD TT BR
then yoy could edit it??? i dont know for shure but here it is.
don’t use LevelEditor.py its disnay specific thing.
Why is it even in the srouce tree?
there is a generic , community-based level editor in development. there should be posts on the forum about it,too.
btw. next time you post code. please use code-tags. if you post a lot of code.think about uploading it somewhere and link to it.
kk