LevelEditor What I Found

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 :stuck_out_tongue:

:’( 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. :slight_smile:

kk