|
@@ -1,5532 +1,27 @@
|
|
|
-
|
|
|
|
|
-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 direct.directnotify import DirectNotifyGlobal
|
|
|
|
|
-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
|
|
|
|
|
-
|
|
|
|
|
-from LevelStyleManager import *
|
|
|
|
|
-
|
|
|
|
|
-# 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 PA')
|
|
|
|
|
- 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',
|
|
|
|
|
- 'PA': 'party_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)
|
|
|
|
|
- if 'PA' in hoods:
|
|
|
|
|
- loadDNAFile(DNASTORE, 'phase_13/dna/storage_party_sz.dna', CSDefault, 1)
|
|
|
|
|
- __builtin__.dnaLoaded = 1
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class LevelEditor(NodePath, DirectObject):
|
|
|
|
|
- """Class used to create a Toontown LevelEditor object"""
|
|
|
|
|
- notify = DirectNotifyGlobal.directNotify.newCategory('LevelEditor')
|
|
|
|
|
-
|
|
|
|
|
- # 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(NEIGHBORHOODS, NEIGHBORHOOD_CODES)
|
|
|
|
|
- # 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 = True
|
|
|
|
|
-
|
|
|
|
|
- # [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
|
|
|
|
|
- if not nodePath:
|
|
|
|
|
- return None
|
|
|
|
|
- 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
|
|
|
|
|
- try:
|
|
|
|
|
- newNodePath = dnaNode.traverse(parent, DNASTORE, 1)
|
|
|
|
|
- except Exception:
|
|
|
|
|
- self.notify.debug("Couldn't traverse existing DNA! Do not trust replace")
|
|
|
|
|
- return None
|
|
|
|
|
- # 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:
|
|
|
|
|
- self.point2edgeDict[startPoint].remove(edge)
|
|
|
|
|
- # Is it in the visited edges list?
|
|
|
|
|
- if edge in self.visitedEdges:
|
|
|
|
|
- self.visitedEdges.remove(edge)
|
|
|
|
|
- # Now delete point2edgeDict entry for this point
|
|
|
|
|
- del(self.point2edgeDict[pointOrCell])
|
|
|
|
|
- elif (type == 'battleCellMarker'):
|
|
|
|
|
- # Get parent vis group
|
|
|
|
|
- visGroupNP, visGroupDNA = self.findParentVisGroup(
|
|
|
|
|
- nodePath)
|
|
|
|
|
- print 'Battle Cell:', pointOrCell
|
|
|
|
|
- # Remove cell from vis group
|
|
|
|
|
- if visGroupNP and visGroupDNA:
|
|
|
|
|
- if visGroupDNA.removeBattleCell(pointOrCell):
|
|
|
|
|
- print "Removed from Vis Group"
|
|
|
|
|
- else:
|
|
|
|
|
- print "Not found in Vis Group"
|
|
|
|
|
- else:
|
|
|
|
|
- print "Parent Vis Group not found"
|
|
|
|
|
- # Remove cell from DNASTORE
|
|
|
|
|
- if DNASTORE.removeBattleCell(pointOrCell):
|
|
|
|
|
- print "Removed from DNASTORE"
|
|
|
|
|
- else:
|
|
|
|
|
- print "Not found in DNASTORE"
|
|
|
|
|
- # Remove cell from cellDict
|
|
|
|
|
- del(self.cellDict[pointOrCell])
|
|
|
|
|
-
|
|
|
|
|
- def reparent(self, nodePath, oldParent, newParent):
|
|
|
|
|
- """ Move node path (and its DNA) to active parent """
|
|
|
|
|
- # Does the node path correspond to a DNA Object
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- # Find old parent DNA
|
|
|
|
|
- oldParentDNANode = self.findDNANode(oldParent)
|
|
|
|
|
- # Remove DNA from old parent
|
|
|
|
|
- if oldParentDNANode:
|
|
|
|
|
- oldParentDNANode.remove(dnaNode)
|
|
|
|
|
- if newParent:
|
|
|
|
|
- # Update active parent just to be safe
|
|
|
|
|
- self.setActiveParent(newParent)
|
|
|
|
|
- # Move DNA to new parent (if active parent set)
|
|
|
|
|
- if self.DNAParent != None:
|
|
|
|
|
- self.DNAParent.add(dnaNode)
|
|
|
|
|
- # It is, is it a DNA_NODE (i.e. it has pos/hpr/scale)?
|
|
|
|
|
- # Update pose to reflect new relationship
|
|
|
|
|
- if DNAIsDerivedFrom(dnaNode, DNA_NODE):
|
|
|
|
|
- # Update DNA
|
|
|
|
|
- self.updatePose(dnaNode, nodePath)
|
|
|
|
|
- elif newParent:
|
|
|
|
|
- # See if this node path is a suit edge
|
|
|
|
|
- suitEdge, oldVisGroup = self.np2EdgeDict.get(nodePath.id(), (None, None))
|
|
|
|
|
- # And see if the new parent is a vis group
|
|
|
|
|
- newVisGroupNP, newVisGroupDNA = self.findParentVisGroup(newParent)
|
|
|
|
|
- if suitEdge and DNAClassEqual(newVisGroupDNA, DNA_VIS_GROUP):
|
|
|
|
|
- # If so, remove suit edge from old vis group and add it to the new group
|
|
|
|
|
- oldVisGroup.removeSuitEdge(suitEdge)
|
|
|
|
|
- # Update suit edge to reflect new zone ID
|
|
|
|
|
- suitEdge.setZoneId(newVisGroupDNA.getName())
|
|
|
|
|
- newVisGroupDNA.addSuitEdge(suitEdge)
|
|
|
|
|
- # Update np2EdgeDict to reflect changes
|
|
|
|
|
- self.np2EdgeDict[nodePath.id()] = [suitEdge, newVisGroupDNA]
|
|
|
|
|
-
|
|
|
|
|
- def setActiveParent(self, nodePath = None):
|
|
|
|
|
- """ Set NPParent and DNAParent to node path and its DNA """
|
|
|
|
|
- # If we've got a valid node path
|
|
|
|
|
- if nodePath:
|
|
|
|
|
- # See if this is in the DNA database
|
|
|
|
|
- newDNAParent = self.findDNANode(nodePath)
|
|
|
|
|
- if newDNAParent:
|
|
|
|
|
- self.DNAParent = newDNAParent
|
|
|
|
|
- self.NPParent = nodePath
|
|
|
|
|
- else:
|
|
|
|
|
- print 'LevelEditor.setActiveParent: nodePath not found'
|
|
|
|
|
- else:
|
|
|
|
|
- print 'LevelEditor.setActiveParent: nodePath == None'
|
|
|
|
|
-
|
|
|
|
|
- def setName(self, nodePath, newName):
|
|
|
|
|
- """ Set name of nodePath's DNA (if it exists) """
|
|
|
|
|
- # Find the DNA that corresponds to this node path
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- # If it exists, set the name of the DNA Node
|
|
|
|
|
- dnaNode.setName(newName)
|
|
|
|
|
-
|
|
|
|
|
- def updateSelectedPose(self, nodePathList):
|
|
|
|
|
- """
|
|
|
|
|
- Update the DNA database to reflect selected objects current positions
|
|
|
|
|
- """
|
|
|
|
|
- for selectedNode in nodePathList:
|
|
|
|
|
- # Is this a DNA Object in the DNASTORE database?
|
|
|
|
|
- dnaObject = self.findDNANode(selectedNode)
|
|
|
|
|
- if dnaObject:
|
|
|
|
|
- # It is, is it a DNA_NODE (i.e. does it have pos/hpr/scale)?
|
|
|
|
|
- if DNAIsDerivedFrom(dnaObject, DNA_NODE):
|
|
|
|
|
- # First snap selected node path to grid
|
|
|
|
|
- pos = selectedNode.getPos(base.direct.grid)
|
|
|
|
|
- snapPos = base.direct.grid.computeSnapPoint(pos)
|
|
|
|
|
- if self.panel.fPlaneSnap.get():
|
|
|
|
|
- zheight = 0
|
|
|
|
|
- else:
|
|
|
|
|
- zheight = snapPos[2]
|
|
|
|
|
- selectedNode.setPos(base.direct.grid,
|
|
|
|
|
- snapPos[0], snapPos[1], zheight)
|
|
|
|
|
- # Angle snap
|
|
|
|
|
- h = base.direct.grid.computeSnapAngle(selectedNode.getH())
|
|
|
|
|
- if base.direct.grid.getHprSnap():
|
|
|
|
|
- selectedNode.setH(h)
|
|
|
|
|
- if selectedNode == base.direct.selected.last:
|
|
|
|
|
- self.setLastAngle(h)
|
|
|
|
|
- # Update DNA
|
|
|
|
|
- self.updatePose(dnaObject, selectedNode)
|
|
|
|
|
- else:
|
|
|
|
|
- pointOrCell, type = self.findPointOrCell(selectedNode)
|
|
|
|
|
- if pointOrCell and type:
|
|
|
|
|
- # First snap selected node path to grid
|
|
|
|
|
- pos = selectedNode.getPos(base.direct.grid)
|
|
|
|
|
- snapPos = base.direct.grid.computeSnapPoint(pos)
|
|
|
|
|
- if self.panel.fPlaneSnap.get():
|
|
|
|
|
- zheight = 0
|
|
|
|
|
- else:
|
|
|
|
|
- zheight = snapPos[2]
|
|
|
|
|
- selectedNode.setPos(
|
|
|
|
|
- base.direct.grid,
|
|
|
|
|
- snapPos[0], snapPos[1], zheight)
|
|
|
|
|
- newPos = selectedNode.getPos(self.NPToplevel)
|
|
|
|
|
- # Update DNA
|
|
|
|
|
- pointOrCell.setPos(newPos)
|
|
|
|
|
- if (type == 'suitPointMarker'):
|
|
|
|
|
- print "Found suit point!", pointOrCell
|
|
|
|
|
- # Ok, now update all the lines into that node
|
|
|
|
|
- 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()
|
|
|
|
|
- oldEdgeLine.removeNode()
|
|
|
|
|
- del oldEdgeLine
|
|
|
|
|
- newEdgeLine = self.drawSuitEdge(
|
|
|
|
|
- edge, self.NPParent)
|
|
|
|
|
- self.edgeDict[edge] = newEdgeLine
|
|
|
|
|
- elif (type == 'battleCellMarker'):
|
|
|
|
|
- print "Found battle cell!", pointOrCell
|
|
|
|
|
-
|
|
|
|
|
- def updatePose(self, dnaObject, nodePath):
|
|
|
|
|
- """
|
|
|
|
|
- Update a DNA Object's pos, hpr, and scale based upon
|
|
|
|
|
- node path's current pose
|
|
|
|
|
- """
|
|
|
|
|
- # Set DNA's pos, hpr, and scale
|
|
|
|
|
- dnaObject.setPos(nodePath.getPos())
|
|
|
|
|
- dnaObject.setHpr(nodePath.getHpr())
|
|
|
|
|
- dnaObject.setScale(nodePath.getScale())
|
|
|
|
|
-
|
|
|
|
|
- # LEVEL OBJECT CREATION FUNCTIONS
|
|
|
|
|
- def initDNANode(self, dnaNode):
|
|
|
|
|
- """
|
|
|
|
|
- This method adds a new DNA object to the scene and adds hooks that
|
|
|
|
|
- allow duplicate copies of this DNA node to be added using the
|
|
|
|
|
- space bar. For DNAFlatBuildings, a new copy with random style is
|
|
|
|
|
- generated by hitting the insert key.
|
|
|
|
|
- """
|
|
|
|
|
- # First create the visible geometry for this DNA Node
|
|
|
|
|
- self.initNodePath(dnaNode)
|
|
|
|
|
- # And add hooks to insert copies of dnaNode
|
|
|
|
|
- self.addReplicationHooks(dnaNode)
|
|
|
|
|
-
|
|
|
|
|
- def addReplicationHooks(self, dnaNode):
|
|
|
|
|
- # Now add hook to allow placement of a new dna Node of this type
|
|
|
|
|
- # by simply hitting the space bar or insert key. Note, extra paramter
|
|
|
|
|
- # indicates new dnaNode should be a copy
|
|
|
|
|
- self.accept('space', self.initNodePath, [dnaNode, 'space'])
|
|
|
|
|
- self.accept('insert', self.initNodePath, [dnaNode, 'insert'])
|
|
|
|
|
-
|
|
|
|
|
- def setRandomBuildingStyle(self, dnaNode, name = 'building'):
|
|
|
|
|
- """ Initialize a new DNA Flat building to a random building style """
|
|
|
|
|
- # What is the current building type?
|
|
|
|
|
- buildingType = self.getCurrent('building_type')
|
|
|
|
|
- # If random
|
|
|
|
|
- if buildingType == 'random':
|
|
|
|
|
- # Generate height list based on current building height
|
|
|
|
|
- buildingHeight = self.getCurrent('building_height')
|
|
|
|
|
- heightList = self.getRandomHeightList(buildingHeight)
|
|
|
|
|
- # Convert height list to building type
|
|
|
|
|
- buildingType = createHeightCode(heightList)
|
|
|
|
|
- else:
|
|
|
|
|
- # Use specified height list
|
|
|
|
|
- heightList = map(string.atof, string.split(buildingType, '_'))
|
|
|
|
|
- height = calcHeight(heightList)
|
|
|
|
|
- # Is this a never before seen height list? If so, record it.
|
|
|
|
|
- try:
|
|
|
|
|
- attr = self.getAttribute(`height` + '_ft_wall_heights')
|
|
|
|
|
- if heightList not in attr.getList():
|
|
|
|
|
- print 'Adding new height list entry'
|
|
|
|
|
- attr.add(heightList)
|
|
|
|
|
- except KeyError:
|
|
|
|
|
- print 'Non standard height building'
|
|
|
|
|
-
|
|
|
|
|
- # See if this building type corresponds to existing style dict
|
|
|
|
|
- try:
|
|
|
|
|
- dict = self.getDict(buildingType + '_styles')
|
|
|
|
|
- except KeyError:
|
|
|
|
|
- # Nope
|
|
|
|
|
- dict = {}
|
|
|
|
|
-
|
|
|
|
|
- # No specific dict or empty dict, try to pick a dict
|
|
|
|
|
- # based on number of walls
|
|
|
|
|
- if not dict:
|
|
|
|
|
- # How many walls?
|
|
|
|
|
- numWalls = len(heightList)
|
|
|
|
|
- # Get the building_style attribute dictionary for
|
|
|
|
|
- # this number of walls
|
|
|
|
|
- dict = self.getDict(`numWalls` + '_wall_styles')
|
|
|
|
|
-
|
|
|
|
|
- if not dict:
|
|
|
|
|
- # Still no dict, create new random style using height list
|
|
|
|
|
- styleList = []
|
|
|
|
|
- # Build up wall styles
|
|
|
|
|
- for height in heightList:
|
|
|
|
|
- wallStyle = self.getRandomDictionaryEntry(
|
|
|
|
|
- self.getDict('wall_style'))
|
|
|
|
|
- styleList.append((wallStyle, height))
|
|
|
|
|
- # Create new random flat building style
|
|
|
|
|
- style = DNAFlatBuildingStyle(styleList = styleList)
|
|
|
|
|
- else:
|
|
|
|
|
- # Pick a style
|
|
|
|
|
- style = self.getRandomDictionaryEntry(dict)
|
|
|
|
|
-
|
|
|
|
|
- # Set style....finally
|
|
|
|
|
- self.styleManager.setDNAFlatBuildingStyle(
|
|
|
|
|
- dnaNode, style, width = self.getRandomWallWidth(),
|
|
|
|
|
- heightList = heightList, name = name)
|
|
|
|
|
-
|
|
|
|
|
- def getRandomHeightList(self, buildingHeight):
|
|
|
|
|
- # Select a list of wall heights
|
|
|
|
|
- heightLists = self.getList(`buildingHeight` + '_ft_wall_heights')
|
|
|
|
|
- l = len(heightLists)
|
|
|
|
|
- if l > 0:
|
|
|
|
|
- # If a list exists for this building height, pick randomly
|
|
|
|
|
- return heightLists[randint(0, l - 1)]
|
|
|
|
|
- else:
|
|
|
|
|
- # No height lists exists for this building height, generate
|
|
|
|
|
- chance = randint(0, 100)
|
|
|
|
|
- if buildingHeight <= 10:
|
|
|
|
|
- return [buildingHeight]
|
|
|
|
|
- elif buildingHeight <= 14:
|
|
|
|
|
- return [4, 10]
|
|
|
|
|
- elif buildingHeight <= 20:
|
|
|
|
|
- if chance <= 30:
|
|
|
|
|
- return [20]
|
|
|
|
|
- elif chance <= 80:
|
|
|
|
|
- return [10, 10]
|
|
|
|
|
- else:
|
|
|
|
|
- return [12, 8]
|
|
|
|
|
- elif buildingHeight <= 24:
|
|
|
|
|
- if chance <= 50:
|
|
|
|
|
- return [4, 10, 10]
|
|
|
|
|
- else:
|
|
|
|
|
- return [4, 20]
|
|
|
|
|
- elif buildingHeight <= 25:
|
|
|
|
|
- if chance <= 25:
|
|
|
|
|
- return [3, 22]
|
|
|
|
|
- elif chance <= 50:
|
|
|
|
|
- return [4, 21]
|
|
|
|
|
- elif chance <= 75:
|
|
|
|
|
- return [3, 13, 9]
|
|
|
|
|
- else:
|
|
|
|
|
- return [4, 13, 8]
|
|
|
|
|
- else:
|
|
|
|
|
- if chance <= 20:
|
|
|
|
|
- return [10, 20]
|
|
|
|
|
- elif chance <= 35:
|
|
|
|
|
- return [20, 10]
|
|
|
|
|
- elif chance <= 75:
|
|
|
|
|
- return [10, 10, 10]
|
|
|
|
|
- else:
|
|
|
|
|
- return [13, 9, 8]
|
|
|
|
|
-
|
|
|
|
|
- def getRandomWallWidth(self):
|
|
|
|
|
- chance = randint(0, 100)
|
|
|
|
|
- if chance <= 15:
|
|
|
|
|
- return 5.0
|
|
|
|
|
- elif chance <= 30:
|
|
|
|
|
- return 10.0
|
|
|
|
|
- elif chance <= 65:
|
|
|
|
|
- return 15.0
|
|
|
|
|
- elif chance <= 85:
|
|
|
|
|
- return 20.0
|
|
|
|
|
- else:
|
|
|
|
|
- return 25.0
|
|
|
|
|
-
|
|
|
|
|
- def initNodePath(self, dnaNode, hotKey = None):
|
|
|
|
|
- """
|
|
|
|
|
- Update DNA to reflect latest style choices and then generate
|
|
|
|
|
- new node path and add it to the scene graph
|
|
|
|
|
- """
|
|
|
|
|
- # Determine dnaNode Class Type
|
|
|
|
|
- nodeClass = DNAGetClassType(dnaNode)
|
|
|
|
|
- # Did the user hit insert or space?
|
|
|
|
|
- if hotKey:
|
|
|
|
|
- # Yes, make a new copy of the dnaNode
|
|
|
|
|
- dnaNode = dnaNode.__class__(dnaNode)
|
|
|
|
|
- # And determine dnaNode type and perform any type specific updates
|
|
|
|
|
- if nodeClass.eq(DNA_PROP):
|
|
|
|
|
- dnaNode.setCode(self.getCurrent('prop_texture'))
|
|
|
|
|
- elif nodeClass.eq(DNA_STREET):
|
|
|
|
|
- dnaNode.setCode(self.getCurrent('street_texture'))
|
|
|
|
|
- elif nodeClass.eq(DNA_FLAT_BUILDING):
|
|
|
|
|
- # If insert, pick a new random style
|
|
|
|
|
- if hotKey == 'insert':
|
|
|
|
|
- self.setRandomBuildingStyle(dnaNode, dnaNode.getName())
|
|
|
|
|
- # Get a new building width
|
|
|
|
|
- self.setCurrent('building_width',
|
|
|
|
|
- self.getRandomWallWidth())
|
|
|
|
|
- dnaNode.setWidth(self.getCurrent('building_width'))
|
|
|
|
|
-
|
|
|
|
|
- # Position it
|
|
|
|
|
- # First kill autoposition task so grid can jump to its final
|
|
|
|
|
- # destination (part of cleanup
|
|
|
|
|
- taskMgr.remove('autoPositionGrid')
|
|
|
|
|
- # Now find where to put node path
|
|
|
|
|
- if (hotKey is not None) and nodeClass.eq(DNA_PROP):
|
|
|
|
|
- # If its a prop and a copy, place it based upon current
|
|
|
|
|
- # mouse position
|
|
|
|
|
- hitPt = self.getGridIntersectionPoint()
|
|
|
|
|
- # Attach a node, so we can set pos with respect to:
|
|
|
|
|
- tempNode = hidden.attachNewNode('tempNode')
|
|
|
|
|
- # Place it:
|
|
|
|
|
- tempNode.setPos(base.direct.grid, hitPt)
|
|
|
|
|
- # Copy the pos to where we really want it:
|
|
|
|
|
- dnaNode.setPos(tempNode.getPos())
|
|
|
|
|
- # Clean up:
|
|
|
|
|
- tempNode.removeNode()
|
|
|
|
|
- else:
|
|
|
|
|
- # Place the new node path at the current grid origin
|
|
|
|
|
- dnaNode.setPos(base.direct.grid.getPos())
|
|
|
|
|
- # Initialize angle to match last object
|
|
|
|
|
- dnaNode.setHpr(Vec3(self.getLastAngle(), 0, 0))
|
|
|
|
|
-
|
|
|
|
|
- # Add the DNA to the active parent
|
|
|
|
|
- self.DNAParent.add(dnaNode)
|
|
|
|
|
- # And create the geometry
|
|
|
|
|
- newNodePath = dnaNode.traverse(self.NPParent, DNASTORE, 1)
|
|
|
|
|
- # Update scene graph explorer
|
|
|
|
|
- # self.panel.sceneGraphExplorer.update()
|
|
|
|
|
-
|
|
|
|
|
- # Reset last Code (for autoPositionGrid)
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_STREET):
|
|
|
|
|
- self.snapList = self.getSnapPoint(dnaNode.getCode())
|
|
|
|
|
- # Select the instance
|
|
|
|
|
- base.direct.select(newNodePath)
|
|
|
|
|
- self.lastNodePath = newNodePath
|
|
|
|
|
- # Update grid to get ready for the next object
|
|
|
|
|
- self.autoPositionGrid()
|
|
|
|
|
-
|
|
|
|
|
- def getSnapPoint(self, code):
|
|
|
|
|
- return OBJECT_SNAP_POINTS.get(code, [(Vec3(0.0, 0, 0), Vec3(0)), (Vec3(0), Vec3(0))])
|
|
|
|
|
-
|
|
|
|
|
- def addGroup(self, nodePath):
|
|
|
|
|
- """ Add a new DNA Node Group to the specified Node Path """
|
|
|
|
|
- # Set the node path as the current parent
|
|
|
|
|
- base.direct.setActiveParent(nodePath)
|
|
|
|
|
- # Add a new group to the selected parent
|
|
|
|
|
- self.createNewGroup()
|
|
|
|
|
-
|
|
|
|
|
- def addVisGroup(self, nodePath):
|
|
|
|
|
- """ Add a new DNA Group to the specified Node Path """
|
|
|
|
|
- # Set the node path as the current parent
|
|
|
|
|
- base.direct.setActiveParent(nodePath)
|
|
|
|
|
- # Add a new group to the selected parent
|
|
|
|
|
- self.createNewGroup(type = 'vis')
|
|
|
|
|
-
|
|
|
|
|
- def createNewGroup(self, type = 'dna'):
|
|
|
|
|
- print "createNewGroup"
|
|
|
|
|
- """ Create a new DNA Node group under the active parent """
|
|
|
|
|
- # Create a new DNA Node group
|
|
|
|
|
- if type == 'dna':
|
|
|
|
|
- newDNANode = DNANode('group_' + `self.getGroupNum()`)
|
|
|
|
|
- else:
|
|
|
|
|
- newDNANode = DNAVisGroup('VisGroup_' + `self.getGroupNum()`)
|
|
|
|
|
- # Increment group counter
|
|
|
|
|
- self.setGroupNum(self.getGroupNum() + 1)
|
|
|
|
|
- # Add new DNA Node group to the current parent DNA Object
|
|
|
|
|
- self.DNAParent.add(newDNANode)
|
|
|
|
|
- # The new Node group becomes the active parent
|
|
|
|
|
- self.DNAParent = newDNANode
|
|
|
|
|
- # Traverse it to generate the new node path as a child of NPParent
|
|
|
|
|
- newNodePath = self.DNAParent.traverse(self.NPParent, DNASTORE, 1)
|
|
|
|
|
- # Update NPParent to point to the new node path
|
|
|
|
|
- self.NPParent = newNodePath
|
|
|
|
|
- # Update scene graph explorer
|
|
|
|
|
- # self.panel.sceneGraphExplorer.update()
|
|
|
|
|
-
|
|
|
|
|
- def addFlatBuilding(self, buildingType):
|
|
|
|
|
- # Create new building
|
|
|
|
|
- newDNAFlatBuilding = DNAFlatBuilding()
|
|
|
|
|
- self.setRandomBuildingStyle(newDNAFlatBuilding,
|
|
|
|
|
- name = 'tb0:'+ buildingType + '_DNARoot')
|
|
|
|
|
- # Now place new building in the world
|
|
|
|
|
- self.initDNANode(newDNAFlatBuilding)
|
|
|
|
|
-
|
|
|
|
|
- def getNextLandmarkBlock(self):
|
|
|
|
|
- self.landmarkBlock=self.landmarkBlock+1
|
|
|
|
|
- return str(self.landmarkBlock)
|
|
|
|
|
-
|
|
|
|
|
- def addLandmark(self, landmarkType, specialType):
|
|
|
|
|
- # Record new landmark type
|
|
|
|
|
- self.setCurrent('toon_landmark_texture', landmarkType)
|
|
|
|
|
- # And create new landmark building
|
|
|
|
|
- block=self.getNextLandmarkBlock()
|
|
|
|
|
- newDNALandmarkBuilding = DNALandmarkBuilding(
|
|
|
|
|
- 'tb'+block+':'+landmarkType + '_DNARoot')
|
|
|
|
|
- newDNALandmarkBuilding.setCode(landmarkType)
|
|
|
|
|
- newDNALandmarkBuilding.setBuildingType(specialType)
|
|
|
|
|
- newDNALandmarkBuilding.setPos(VBase3(0))
|
|
|
|
|
- newDNALandmarkBuilding.setHpr(VBase3(0))
|
|
|
|
|
- # Headquarters do not have doors
|
|
|
|
|
- if specialType not in ['hq', 'kartshop']:
|
|
|
|
|
- newDNADoor = self.createDoor('landmark_door')
|
|
|
|
|
- newDNALandmarkBuilding.add(newDNADoor)
|
|
|
|
|
- # Now place new landmark building in the world
|
|
|
|
|
- self.initDNANode(newDNALandmarkBuilding)
|
|
|
|
|
-
|
|
|
|
|
- def addProp(self, propType):
|
|
|
|
|
- print "addProp %s " % propType
|
|
|
|
|
- # Record new prop type
|
|
|
|
|
- self.setCurrent('prop_texture', propType)
|
|
|
|
|
- # And create new prop
|
|
|
|
|
- newDNAProp = DNAProp(propType + '_DNARoot')
|
|
|
|
|
- newDNAProp.setCode(propType)
|
|
|
|
|
- newDNAProp.setPos(VBase3(0))
|
|
|
|
|
- newDNAProp.setHpr(VBase3(0))
|
|
|
|
|
- # Now place new prop in the world
|
|
|
|
|
- self.initDNANode(newDNAProp)
|
|
|
|
|
-
|
|
|
|
|
- def addStreet(self, streetType):
|
|
|
|
|
- # Record new street type
|
|
|
|
|
- self.setCurrent('street_texture', streetType)
|
|
|
|
|
- # And create new street
|
|
|
|
|
- newDNAStreet = DNAStreet(streetType + '_DNARoot')
|
|
|
|
|
- newDNAStreet.setCode(streetType)
|
|
|
|
|
- newDNAStreet.setPos(VBase3(0))
|
|
|
|
|
- newDNAStreet.setHpr(VBase3(0))
|
|
|
|
|
- # Set street texture to neighborhood dependant texture
|
|
|
|
|
- newDNAStreet.setStreetTexture(
|
|
|
|
|
- 'street_street_' + self.neighborhoodCode + '_tex')
|
|
|
|
|
- newDNAStreet.setSidewalkTexture(
|
|
|
|
|
- 'street_sidewalk_' + self.neighborhoodCode + '_tex')
|
|
|
|
|
- newDNAStreet.setCurbTexture(
|
|
|
|
|
- 'street_curb_' + self.neighborhoodCode + '_tex')
|
|
|
|
|
- # Now place new street in the world
|
|
|
|
|
- self.initDNANode(newDNAStreet)
|
|
|
|
|
-
|
|
|
|
|
- def createCornice(self):
|
|
|
|
|
- newDNACornice = DNACornice('cornice')
|
|
|
|
|
- newDNACornice.setCode(self.getCurrent('cornice_texture'))
|
|
|
|
|
- newDNACornice.setColor(self.getCurrent('cornice_color'))
|
|
|
|
|
- return newDNACornice
|
|
|
|
|
-
|
|
|
|
|
- def createDoor(self, type):
|
|
|
|
|
- if (type == 'landmark_door'):
|
|
|
|
|
- newDNADoor = DNADoor('door')
|
|
|
|
|
- print "createDoor %s" % type
|
|
|
|
|
- if not (self.getCurrent('door_double_texture')):
|
|
|
|
|
- doorStyles = self.styleManager.attributeDictionary['door_double_texture'].getList()[1:]
|
|
|
|
|
- defaultDoorStyle = random.choice(doorStyles)
|
|
|
|
|
- self.setCurrent('door_double_texture', defaultDoorStyle)
|
|
|
|
|
- newDNADoor.setCode(self.getCurrent('door_double_texture'))
|
|
|
|
|
- print "doorcolor = %s" % self.getCurrent('door_color')
|
|
|
|
|
- newDNADoor.setColor(self.getCurrent('door_color'))
|
|
|
|
|
- elif (type == 'door'):
|
|
|
|
|
- newDNADoor = DNAFlatDoor('door')
|
|
|
|
|
- if not (self.getCurrent('door_single_texture')):
|
|
|
|
|
- doorStyles = self.styleManager.attributeDictionary['door_single_texture'].getList()[1:]
|
|
|
|
|
- defaultDoorStyle = random.choice(doorStyles)
|
|
|
|
|
- self.setCurrent('door_single_texture', defaultDoorStyle)
|
|
|
|
|
- newDNADoor.setCode(self.getCurrent('door_single_texture'))
|
|
|
|
|
- newDNADoor.setColor(self.getCurrent('door_color'))
|
|
|
|
|
- return newDNADoor
|
|
|
|
|
-
|
|
|
|
|
- def createSign(self):
|
|
|
|
|
- if not (self.getCurrent('sign_texture')):
|
|
|
|
|
- defaultSignStyle = self.styleManager.attributeDictionary['sign_texture'].getList()[0]
|
|
|
|
|
- self.setCurrent('sign_texture', defaultSignStyle)
|
|
|
|
|
- newDNASign = DNASign('sign')
|
|
|
|
|
- newDNASign.setCode(self.getCurrent('sign_texture'))
|
|
|
|
|
- newDNASign.setColor(self.getCurrent('sign_color'))
|
|
|
|
|
- #newDNASign.setColor(VBase4(0.0, 1.0, 0.0, 1.0))
|
|
|
|
|
- #newDNASign.setScale(VBase3(2.0, 1.0, 2.0))
|
|
|
|
|
-
|
|
|
|
|
- baseline = DNASignBaseline('baseline')
|
|
|
|
|
- baseline.setCode("humanist")
|
|
|
|
|
- baseline.setColor(VBase4(0.0, 0.0, 0.0, 1.0))
|
|
|
|
|
- #baseline.setKern(1.0)
|
|
|
|
|
- #baseline.setWiggle(30.0)
|
|
|
|
|
- #baseline.setStumble(1.0)
|
|
|
|
|
- #baseline.setStomp(10.0)
|
|
|
|
|
- #baseline.setWidth(16.0)
|
|
|
|
|
- #baseline.setHeight(16.0)
|
|
|
|
|
- baseline.setScale(VBase3(0.7, 1.0, 0.7))
|
|
|
|
|
- newDNASign.add(baseline)
|
|
|
|
|
-
|
|
|
|
|
- #graphic = DNASignGraphic('graphic')
|
|
|
|
|
- #graphic.setCode("sign_general1")
|
|
|
|
|
- #graphic.setColor(VBase4(1.0, 1.0, 0.0, 0.5))
|
|
|
|
|
- #graphic.setScale(VBase3(.2, 1.0, .2))
|
|
|
|
|
- #graphic.setHpr(VBase3(0.0, 0.0, 90.0))
|
|
|
|
|
- #baseline.add(graphic)
|
|
|
|
|
-
|
|
|
|
|
- DNASetBaselineString(baseline, "Toon Shop")
|
|
|
|
|
-
|
|
|
|
|
- return newDNASign
|
|
|
|
|
-
|
|
|
|
|
- def createWindows(self):
|
|
|
|
|
- newDNAWindows = DNAWindows()
|
|
|
|
|
- newDNAWindows.setCode(self.getCurrent('window_texture'))
|
|
|
|
|
- newDNAWindows.setWindowCount(self.getCurrent('window_count'))
|
|
|
|
|
- newDNAWindows.setColor(self.getCurrent('window_color'))
|
|
|
|
|
- return newDNAWindows
|
|
|
|
|
-
|
|
|
|
|
- def removeCornice(self, cornice, parent):
|
|
|
|
|
- self.setCurrent('cornice_color', cornice.getColor())
|
|
|
|
|
- DNARemoveChildOfClass(parent, DNA_CORNICE)
|
|
|
|
|
-
|
|
|
|
|
- def removeLandmarkDoor(self, door, parent):
|
|
|
|
|
- self.setCurrent('door_color', door.getColor())
|
|
|
|
|
- DNARemoveChildOfClass(parent, DNA_DOOR)
|
|
|
|
|
-
|
|
|
|
|
- def removeSign(self, sign, parent):
|
|
|
|
|
- self.setCurrent('sign_color', sign.getColor())
|
|
|
|
|
- DNARemoveChildOfClass(parent, DNA_SIGN)
|
|
|
|
|
-
|
|
|
|
|
- def removeDoor(self, door, parent):
|
|
|
|
|
- self.setCurrent('door_color', door.getColor())
|
|
|
|
|
- DNARemoveChildOfClass(parent, DNA_FLAT_DOOR)
|
|
|
|
|
-
|
|
|
|
|
- def removeWindows(self, windows, parent):
|
|
|
|
|
- # And record number of windows
|
|
|
|
|
- self.setCurrent('window_color', windows.getColor())
|
|
|
|
|
- self.setCurrent('window_count', windows.getWindowCount())
|
|
|
|
|
- DNARemoveChildOfClass(parent, DNA_WINDOWS)
|
|
|
|
|
-
|
|
|
|
|
- # LEVEL-OBJECT MODIFICATION FUNCTIONS
|
|
|
|
|
- def levelHandleMouse3(self, modifiers):
|
|
|
|
|
- # import pdb; pdb.set_trace()
|
|
|
|
|
- if base.direct.cameraControl.useMayaCamControls and modifiers == 4: # alt is down, use maya controls
|
|
|
|
|
- self.mouseMayaCamera = True
|
|
|
|
|
- return
|
|
|
|
|
- else:
|
|
|
|
|
- self.mouseMayaCamera = False
|
|
|
|
|
-
|
|
|
|
|
- # Initialize dna target
|
|
|
|
|
- self.DNATarget = None
|
|
|
|
|
-
|
|
|
|
|
- # If nothing selected, just return
|
|
|
|
|
- if not self.selectedNPRoot:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- # Next check to see if the selected object is a DNA object
|
|
|
|
|
- dnaObject = self.findDNANode(self.selectedNPRoot)
|
|
|
|
|
- # Nope, not a DNA object, just return
|
|
|
|
|
- if not dnaObject:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- # Pick a menu based upon object type
|
|
|
|
|
- if DNAClassEqual(dnaObject, DNA_FLAT_BUILDING):
|
|
|
|
|
- # FLAT BUILDING OPERATIONS
|
|
|
|
|
- menuMode, wallNum = self.getFlatBuildingMode(dnaObject, modifiers)
|
|
|
|
|
- # Check menuMode
|
|
|
|
|
- if menuMode == None:
|
|
|
|
|
- return
|
|
|
|
|
- # Find appropriate target
|
|
|
|
|
- wall = self.getWall(dnaObject, wallNum)
|
|
|
|
|
- # Record bldg/wall
|
|
|
|
|
- self.lastBuilding = dnaObject
|
|
|
|
|
- self.lastWall = wall
|
|
|
|
|
- if string.find(menuMode,'wall') >= 0:
|
|
|
|
|
- self.DNATarget = wall
|
|
|
|
|
- self.DNATargetParent = dnaObject
|
|
|
|
|
- elif string.find(menuMode,'door') >= 0:
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(wall, DNA_FLAT_DOOR)
|
|
|
|
|
- self.DNATargetParent = wall
|
|
|
|
|
- elif string.find(menuMode, 'window') >= 0:
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(wall, DNA_WINDOWS)
|
|
|
|
|
- self.DNATargetParent = wall
|
|
|
|
|
- elif string.find(menuMode,'cornice') >= 0:
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(wall, DNA_CORNICE)
|
|
|
|
|
- self.DNATargetParent = wall
|
|
|
|
|
- else:
|
|
|
|
|
- self.DNATarget = dnaObject
|
|
|
|
|
- elif DNAClassEqual(dnaObject, DNA_PROP):
|
|
|
|
|
- # PROP OPERATIONS
|
|
|
|
|
- self.DNATarget = dnaObject
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'prop_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers) and self.panel.currentBaselineDNA:
|
|
|
|
|
- menuMode = 'baseline_style'
|
|
|
|
|
- elif base.direct.gotShift(modifiers):
|
|
|
|
|
- menuMode = 'sign_texture'
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_SIGN)
|
|
|
|
|
- self.DNATargetParent = dnaObject
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'prop_texture'
|
|
|
|
|
- elif DNAClassEqual(dnaObject, DNA_LANDMARK_BUILDING):
|
|
|
|
|
- # INSERT HERE
|
|
|
|
|
- # LANDMARK BUILDING OPERATIONS
|
|
|
|
|
- menuMode = self.getLandmarkBuildingMode(dnaObject, modifiers)
|
|
|
|
|
- if string.find(menuMode, 'door') >= 0:
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_DOOR)
|
|
|
|
|
- self.DNATargetParent = dnaObject
|
|
|
|
|
- elif string.find(menuMode, 'sign') >= 0:
|
|
|
|
|
- self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_SIGN)
|
|
|
|
|
- self.DNATargetParent = dnaObject
|
|
|
|
|
- else:
|
|
|
|
|
- self.DNATarget = dnaObject
|
|
|
|
|
- elif DNAClassEqual(dnaObject, DNA_STREET):
|
|
|
|
|
- # STREET OPERATIONS
|
|
|
|
|
- self.DNATarget = dnaObject
|
|
|
|
|
- menuMode = 'street_texture'
|
|
|
|
|
-
|
|
|
|
|
- # No valid menu mode, get the hell out of here!
|
|
|
|
|
- if menuMode == None:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- # Now spawn apropriate menu task if menu selected
|
|
|
|
|
- self.activeMenu = self.getMenu(menuMode)
|
|
|
|
|
- # Set initial state
|
|
|
|
|
- state = None
|
|
|
|
|
- if self.DNATarget:
|
|
|
|
|
- if string.find(menuMode,'texture') >= 0:
|
|
|
|
|
- state = self.DNATarget.getCode()
|
|
|
|
|
- elif string.find(menuMode, 'color') >= 0:
|
|
|
|
|
- state = self.DNATarget.getColor()
|
|
|
|
|
- self.panel.setCurrentColor(state)
|
|
|
|
|
- self.panel.setResetColor(state)
|
|
|
|
|
- elif string.find(menuMode, 'orientation') >= 0:
|
|
|
|
|
- state = self.DNATarget.getCode()[-2:]
|
|
|
|
|
- elif menuMode == 'building_width':
|
|
|
|
|
- state = self.DNATarget.getWidth()
|
|
|
|
|
- elif menuMode == 'window_count':
|
|
|
|
|
- state = self.DNATarget.getWindowCount()
|
|
|
|
|
- elif menuMode == 'building_style_all':
|
|
|
|
|
- # Extract the building style from the current building
|
|
|
|
|
- state = DNAFlatBuildingStyle(building = self.DNATarget)
|
|
|
|
|
- elif menuMode == 'baseline_style':
|
|
|
|
|
- # Extract the baseline style
|
|
|
|
|
- state = DNABaselineStyle(
|
|
|
|
|
- baseline = self.panel.currentBaselineDNA)
|
|
|
|
|
- elif menuMode == 'wall_style':
|
|
|
|
|
- # Extract the wall style from the current wall
|
|
|
|
|
- state = DNAWallStyle(wall = self.DNATarget)
|
|
|
|
|
- self.activeMenu.setInitialState(state)
|
|
|
|
|
-
|
|
|
|
|
- # Spawn active menu's task
|
|
|
|
|
- self.activeMenu.spawnPieMenuTask()
|
|
|
|
|
-
|
|
|
|
|
- def getLandmarkBuildingMode(self, dnaObject, modifiers):
|
|
|
|
|
- # Where are we hitting the building?
|
|
|
|
|
- hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
|
|
|
|
|
- if hitPt[2] < 10.0:
|
|
|
|
|
- # Do door operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'door_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'door_orientation'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'door_double_texture'
|
|
|
|
|
- else:
|
|
|
|
|
- # Do sign operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'sign_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers) and self.panel.currentBaselineDNA:
|
|
|
|
|
- menuMode = 'baseline_style'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'sign_orientation'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'sign_texture'
|
|
|
|
|
- return menuMode
|
|
|
|
|
-
|
|
|
|
|
- def getFlatBuildingMode(self, dnaObject, modifiers):
|
|
|
|
|
- # Where are we hitting the building?
|
|
|
|
|
- hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
|
|
|
|
|
- wallNum = self.computeWallNum(dnaObject, hitPt)
|
|
|
|
|
- if wallNum < 0:
|
|
|
|
|
- # Do building related operations
|
|
|
|
|
- if base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'building_width'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'building_style_all'
|
|
|
|
|
- else:
|
|
|
|
|
- # Otherwise, do wall specific operations
|
|
|
|
|
- # Figure out where you are hitting on the wall
|
|
|
|
|
- wallHeights, offsetList = DNAGetWallHeights(dnaObject)
|
|
|
|
|
- # Find a normalized X and Z coordinate
|
|
|
|
|
- xPt = hitPt[0]/dnaObject.getWidth()
|
|
|
|
|
- # Adjust zPt depending on what wall you are pointing at
|
|
|
|
|
- wallHeight = wallHeights[wallNum]
|
|
|
|
|
- zPt = (hitPt[2] - offsetList[wallNum])/wallHeight
|
|
|
|
|
- # Record current wall height
|
|
|
|
|
- self.setCurrent('wall_height', wallHeight)
|
|
|
|
|
- # Determine which zone you are pointing at
|
|
|
|
|
- if (zPt > 0.8):
|
|
|
|
|
- # Do cornice operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'cornice_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'cornice_orientation'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'cornice_texture'
|
|
|
|
|
- elif ((xPt < 0.3) or (xPt > 0.7)):
|
|
|
|
|
- # Do wall operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'wall_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'wall_orientation'
|
|
|
|
|
- elif base.direct.gotShift(modifiers):
|
|
|
|
|
- menuMode = 'wall_texture'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'wall_style'
|
|
|
|
|
- elif (zPt < 0.4):
|
|
|
|
|
- # Do door operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'door_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'door_orientation'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'door_single_texture'
|
|
|
|
|
- else:
|
|
|
|
|
- # Do window operations
|
|
|
|
|
- if base.direct.gotControl(modifiers):
|
|
|
|
|
- menuMode = 'window_color'
|
|
|
|
|
- elif base.direct.gotAlt(modifiers):
|
|
|
|
|
- menuMode = 'window_orientation'
|
|
|
|
|
- elif base.direct.gotShift(modifiers):
|
|
|
|
|
- menuMode = 'window_count'
|
|
|
|
|
- else:
|
|
|
|
|
- menuMode = 'window_texture'
|
|
|
|
|
- return menuMode, wallNum
|
|
|
|
|
-
|
|
|
|
|
- def levelHandleMouse3Up(self):
|
|
|
|
|
- if self.mouseMayaCamera:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- if self.activeMenu:
|
|
|
|
|
- self.activeMenu.removePieMenuTask()
|
|
|
|
|
- # Update panel color if appropriate
|
|
|
|
|
- if self.DNATarget:
|
|
|
|
|
- objClass = DNAGetClassType(self.DNATarget)
|
|
|
|
|
- if ((objClass.eq(DNA_WALL)) or
|
|
|
|
|
- (objClass.eq(DNA_WINDOWS)) or
|
|
|
|
|
- (objClass.eq(DNA_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_FLAT_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_CORNICE)) or
|
|
|
|
|
- (objClass.eq(DNA_PROP))
|
|
|
|
|
- ):
|
|
|
|
|
- self.panel.setCurrentColor(self.DNATarget.getColor())
|
|
|
|
|
-
|
|
|
|
|
-## b1 = DirectButton(text = ("Button1", "click!", "roll", "disabled"),
|
|
|
|
|
-## text_scale=0.1, borderWidth = (0.01, 0.01),
|
|
|
|
|
-## relief=2)
|
|
|
|
|
-##
|
|
|
|
|
-## b2 = DirectButton(text = ("Button2", "click!", "roll", "disabled"),
|
|
|
|
|
-## text_scale=0.1, borderWidth = (0.01, 0.01),
|
|
|
|
|
-## relief=2)
|
|
|
|
|
-##
|
|
|
|
|
-## l1 = DirectLabel(text = "Test1", text_scale=0.1)
|
|
|
|
|
-## l2 = DirectLabel(text = "Test2", text_scale=0.1)
|
|
|
|
|
-## l3 = DirectLabel(text = "Test3", text_scale=0.1)
|
|
|
|
|
-##
|
|
|
|
|
-## numItemsVisible = 4
|
|
|
|
|
-## itemHeight = 0.11
|
|
|
|
|
-##
|
|
|
|
|
-## myScrolledList = DirectScrolledList(
|
|
|
|
|
-## decButton_pos= (0.35, 0, 0.53),
|
|
|
|
|
-## decButton_text = "Dec",
|
|
|
|
|
-## decButton_text_scale = 0.04,
|
|
|
|
|
-## decButton_borderWidth = (0.005, 0.005),
|
|
|
|
|
-##
|
|
|
|
|
-## incButton_pos= (0.35, 0, -0.02),
|
|
|
|
|
-## incButton_text = "Inc",
|
|
|
|
|
-## incButton_text_scale = 0.04,
|
|
|
|
|
-## incButton_borderWidth = (0.005, 0.005),
|
|
|
|
|
-##
|
|
|
|
|
-## frameSize = (0.0, 0.7, -0.05, 0.59),
|
|
|
|
|
-## frameColor = (1,0,0,0.5),
|
|
|
|
|
-## pos = (-1, 0, 0),
|
|
|
|
|
-## items = [b1, b2],
|
|
|
|
|
-## numItemsVisible = numItemsVisible,
|
|
|
|
|
-## forceHeight = itemHeight,
|
|
|
|
|
-## itemFrame_frameSize = (-0.2, 0.2, -0.37, 0.11),
|
|
|
|
|
-## itemFrame_pos = (0.35, 0, 0.4),
|
|
|
|
|
-## )
|
|
|
|
|
-##
|
|
|
|
|
-## myScrolledList.addItem(l1)
|
|
|
|
|
-## myScrolledList.addItem(l2)
|
|
|
|
|
-## myScrolledList.addItem(l3)
|
|
|
|
|
-##
|
|
|
|
|
-## for fruit in ['apple', 'pear', 'banana', 'orange']:
|
|
|
|
|
-## l = DirectLabel(text = fruit, text_scale=0.1)
|
|
|
|
|
-## myScrolledList.addItem(l)
|
|
|
|
|
-##
|
|
|
|
|
-## myScrolledList.reparentTo(aspect2d)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetColor(self, color):
|
|
|
|
|
- if self.DNATarget:
|
|
|
|
|
- self.DNATarget.setColor(color)
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetCode(self, type, code):
|
|
|
|
|
- if (self.DNATarget != None) and (code != None):
|
|
|
|
|
- # Update code
|
|
|
|
|
- self.DNATarget.setCode(code)
|
|
|
|
|
- elif (self.DNATarget != None) and (code == None):
|
|
|
|
|
- # Delete object, record pertinant properties before
|
|
|
|
|
- # you delete the object so you can restore them later
|
|
|
|
|
- # Remove object
|
|
|
|
|
- if (type == 'cornice'):
|
|
|
|
|
- self.removeCornice(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- elif (type == 'sign'):
|
|
|
|
|
- self.removeSign(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- elif (type == 'landmark_door'):
|
|
|
|
|
- self.removeLandmarkDoor(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- elif (type == 'door'):
|
|
|
|
|
- self.removeDoor(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- elif (type == 'windows'):
|
|
|
|
|
- self.removeWindows(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- # Clear out DNATarget
|
|
|
|
|
- self.DNATarget = None
|
|
|
|
|
- elif (self.DNATarget == None) and (code != None):
|
|
|
|
|
- # Add new object
|
|
|
|
|
- if (type == 'cornice'):
|
|
|
|
|
- self.DNATarget = self.createCornice()
|
|
|
|
|
- elif (type == 'sign'):
|
|
|
|
|
- self.DNATarget = self.createSign()
|
|
|
|
|
- elif (type == 'landmark_door'):
|
|
|
|
|
- self.DNATarget = self.createDoor('landmark_door')
|
|
|
|
|
- elif (type == 'door'):
|
|
|
|
|
- self.DNATarget = self.createDoor('door')
|
|
|
|
|
- elif (type == 'windows'):
|
|
|
|
|
- # Make sure window_count n.e. 0
|
|
|
|
|
- if self.getCurrent('window_count') == 0:
|
|
|
|
|
- self.setCurrent(
|
|
|
|
|
- 'window_count',
|
|
|
|
|
- self.getRandomWindowCount())
|
|
|
|
|
- # Now create the windows
|
|
|
|
|
- self.DNATarget = self.createWindows()
|
|
|
|
|
- if self.DNATarget:
|
|
|
|
|
- self.DNATargetParent.add(self.DNATarget)
|
|
|
|
|
- # Update visible representation
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetOrientation(self, orientation):
|
|
|
|
|
- if (self.DNATarget != None) and (orientation != None):
|
|
|
|
|
- oldCode = self.DNATarget.getCode()[:-2]
|
|
|
|
|
- # Suit walls only have two orientations!
|
|
|
|
|
- if oldCode.find('wall_suit') >= 0:
|
|
|
|
|
- orientation = 'u' + orientation[1]
|
|
|
|
|
- self.DNATarget.setCode(oldCode+orientation)
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setBuildingStyle(self, style):
|
|
|
|
|
- if (self.DNATarget != None) and (style != None):
|
|
|
|
|
- self.styleManager.setDNAFlatBuildingStyle(
|
|
|
|
|
- self.DNATarget, style,
|
|
|
|
|
- width = self.DNATarget.getWidth(),
|
|
|
|
|
- name = self.DNATarget.getName())
|
|
|
|
|
- # MRM: Need to disable dna store warning
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
- # Re-add replication hooks so we get right kind of copy
|
|
|
|
|
- self.addReplicationHooks(self.DNATarget)
|
|
|
|
|
-
|
|
|
|
|
- def setBuildingType(self, type):
|
|
|
|
|
- print 'setBuildingType: ', `type`
|
|
|
|
|
-
|
|
|
|
|
- def setBuildingWidth(self, width):
|
|
|
|
|
- if self.DNATarget:
|
|
|
|
|
- self.DNATarget.setWidth(width)
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setWindowCount(self, count):
|
|
|
|
|
- if (self.DNATarget != None) and (count != 0):
|
|
|
|
|
- self.DNATarget.setWindowCount(count)
|
|
|
|
|
- elif (self.DNATarget != None) and (count == 0):
|
|
|
|
|
- # Remove windows and clear out DNATarget
|
|
|
|
|
- self.removeWindows(self.DNATarget, self.DNATargetParent)
|
|
|
|
|
- self.DNATarget = None
|
|
|
|
|
- elif (self.DNATarget == None) and (count != 0):
|
|
|
|
|
- self.DNATarget = self.createWindows()
|
|
|
|
|
- self.DNATargetParent.add(self.DNATarget)
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setWallStyle(self, style):
|
|
|
|
|
- if (self.DNATarget != None) and (style != None):
|
|
|
|
|
- self.styleManager.setDNAWallStyle(
|
|
|
|
|
- self.DNATarget, style,
|
|
|
|
|
- self.DNATarget.getHeight())
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setColor(self, nodePath, r, g, b, a):
|
|
|
|
|
- """ This is used to set color of dnaNode subparts """
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- objClass = DNAGetClassType(dnaNode)
|
|
|
|
|
- if ((objClass.eq(DNA_WALL)) or
|
|
|
|
|
- (objClass.eq(DNA_WINDOWS)) or
|
|
|
|
|
- (objClass.eq(DNA_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_FLAT_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_CORNICE)) or
|
|
|
|
|
- (objClass.eq(DNA_PROP)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_BASELINE)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_TEXT)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_GRAPHIC))
|
|
|
|
|
- ):
|
|
|
|
|
- # Update dna information
|
|
|
|
|
- dnaNode.setColor(VBase4(r/255.0, g/255.0, b/255.0, a/255.0))
|
|
|
|
|
-
|
|
|
|
|
- # SELECTION FUNCTIONS
|
|
|
|
|
- def selectedNodePathHook(self, nodePath):
|
|
|
|
|
- """
|
|
|
|
|
- Hook called upon selection of a node path used to restrict
|
|
|
|
|
- selection to DNA Objects. Press control to select any type of
|
|
|
|
|
- DNA Object, with no control key pressed, hook selects only
|
|
|
|
|
- DNA Root objects
|
|
|
|
|
- """
|
|
|
|
|
- # Clear out old root variables
|
|
|
|
|
- self.selectedDNARoot = None
|
|
|
|
|
- self.selectedNPRoot = None
|
|
|
|
|
- self.selectedSuitPoint = None
|
|
|
|
|
- # Now process newly selected node path
|
|
|
|
|
- dnaParent = None
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if base.direct.fControl:
|
|
|
|
|
- # Is the current node a DNA Object?
|
|
|
|
|
- if not dnaNode:
|
|
|
|
|
- # No it isn't, look for a parent DNA object
|
|
|
|
|
- dnaParent = self.findDNAParent(nodePath.getParent())
|
|
|
|
|
- else:
|
|
|
|
|
- # Is the current node a DNA Root object?
|
|
|
|
|
- if nodePath.getName()[-8:] != '_DNARoot':
|
|
|
|
|
- # No it isn't, look for a parent DNA Root object
|
|
|
|
|
- dnaParent = self.findDNARoot(nodePath.getParent())
|
|
|
|
|
- # Do we need to switch selection to a parent object?
|
|
|
|
|
- if dnaParent:
|
|
|
|
|
- # Yes, deselect currently selected node path
|
|
|
|
|
- base.direct.deselect(nodePath)
|
|
|
|
|
- # And select parent
|
|
|
|
|
- base.direct.select(dnaParent, base.direct.fShift)
|
|
|
|
|
- elif dnaNode:
|
|
|
|
|
- # We got a valid node path/DNA object, continue
|
|
|
|
|
- self.selectedNPRoot = nodePath
|
|
|
|
|
- self.selectedDNARoot = dnaNode
|
|
|
|
|
- # Reset last landmark
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_LANDMARK_BUILDING):
|
|
|
|
|
- self.lastLandmarkBuildingDNA=dnaNode
|
|
|
|
|
- if self.showLandmarkBlockToggleGroup:
|
|
|
|
|
- # Toggle old highlighting off:
|
|
|
|
|
- self.toggleShowLandmarkBlock()
|
|
|
|
|
- # Toggle on the the new highlighting:
|
|
|
|
|
- self.toggleShowLandmarkBlock()
|
|
|
|
|
- # Reset last Code (for autoPositionGrid)
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_STREET):
|
|
|
|
|
- self.snapList = self.getSnapPoint(dnaNode.getCode())
|
|
|
|
|
- else:
|
|
|
|
|
- pointOrCell, type = self.findPointOrCell(nodePath)
|
|
|
|
|
- if pointOrCell and (type == 'suitPointMarker'):
|
|
|
|
|
- print "Found suit point!", pointOrCell
|
|
|
|
|
- self.selectedSuitPoint = pointOrCell
|
|
|
|
|
- elif pointOrCell and (type == 'battleCellMarker'):
|
|
|
|
|
- print "Found battle cell!", pointOrCell
|
|
|
|
|
- else:
|
|
|
|
|
- if nodePath.getName() != 'suitEdge':
|
|
|
|
|
- suitEdge = self.findSuitEdge(nodePath.getParent())
|
|
|
|
|
- if suitEdge:
|
|
|
|
|
- # Yes, deselect currently selected node path
|
|
|
|
|
- base.direct.deselect(nodePath)
|
|
|
|
|
- # And select parent
|
|
|
|
|
- base.direct.select(suitEdge, base.direct.fShift)
|
|
|
|
|
-
|
|
|
|
|
- # Let others know that something new may be selected:
|
|
|
|
|
- for i in self.selectedNodePathHookHooks:
|
|
|
|
|
- i()
|
|
|
|
|
-
|
|
|
|
|
- if self.fDrive:
|
|
|
|
|
- base.direct.deselect(nodePath)
|
|
|
|
|
-
|
|
|
|
|
- def deselectedNodePathHook(self, nodePath):
|
|
|
|
|
- # Clear out old root variables
|
|
|
|
|
- self.selectedDNARoot = None
|
|
|
|
|
- self.selectedNPRoot = None
|
|
|
|
|
- self.selectedSuitPoint = None
|
|
|
|
|
- # Let others know:
|
|
|
|
|
- for i in self.deselectedNodePathHookHooks:
|
|
|
|
|
- i()
|
|
|
|
|
-
|
|
|
|
|
- def findDNAParent(self, nodePath):
|
|
|
|
|
- """ Walk up a node path's ancestry looking for its DNA Root """
|
|
|
|
|
- # Check to see if current node is a dna object
|
|
|
|
|
- if self.findDNANode(nodePath):
|
|
|
|
|
- # Its a root!
|
|
|
|
|
- return nodePath
|
|
|
|
|
- else:
|
|
|
|
|
- # If reached the top: fail
|
|
|
|
|
- if not nodePath.hasParent():
|
|
|
|
|
- return 0
|
|
|
|
|
- else:
|
|
|
|
|
- # Try parent
|
|
|
|
|
- return self.findDNAParent(nodePath.getParent())
|
|
|
|
|
-
|
|
|
|
|
- def findDNARoot(self, nodePath):
|
|
|
|
|
- """ Walk up a node path's ancestry looking for its DNA Root """
|
|
|
|
|
- # Check current node's name for root marker
|
|
|
|
|
- if (nodePath.getName()[-8:] == '_DNARoot'):
|
|
|
|
|
- # Its a root!
|
|
|
|
|
- return nodePath
|
|
|
|
|
- else:
|
|
|
|
|
- # If reached the top: fail
|
|
|
|
|
- if not nodePath.hasParent():
|
|
|
|
|
- return None
|
|
|
|
|
- else:
|
|
|
|
|
- # Try parent
|
|
|
|
|
- return self.findDNARoot(nodePath.getParent())
|
|
|
|
|
-
|
|
|
|
|
- def findSuitEdge(self, nodePath):
|
|
|
|
|
- """ Walk up a node path's ancestry looking for a suit edge """
|
|
|
|
|
- # Check current node's name for suitEdge marker
|
|
|
|
|
- if (nodePath.getName() == 'suitEdge'):
|
|
|
|
|
- # Its a suitEdge
|
|
|
|
|
- return nodePath
|
|
|
|
|
- else:
|
|
|
|
|
- # If reached the top: fail
|
|
|
|
|
- if not nodePath.hasParent():
|
|
|
|
|
- return None
|
|
|
|
|
- else:
|
|
|
|
|
- # Try parent
|
|
|
|
|
- return self.findSuitEdge(nodePath.getParent())
|
|
|
|
|
-
|
|
|
|
|
- def findPointOrCell(self, nodePath):
|
|
|
|
|
- """
|
|
|
|
|
- Walk up a node path's ancestry to see if its a suit point marker
|
|
|
|
|
- or a battle cell marker
|
|
|
|
|
- """
|
|
|
|
|
- # Check current node's name for root marker
|
|
|
|
|
- if (nodePath.getName() == 'suitPointMarker'):
|
|
|
|
|
- # Its a suit point marker!
|
|
|
|
|
- # See if point is in pointDict
|
|
|
|
|
- point = self.getSuitPointFromNodePath(nodePath)
|
|
|
|
|
- return point, 'suitPointMarker'
|
|
|
|
|
- elif (nodePath.getName() == 'battleCellMarker'):
|
|
|
|
|
- # Its a battle cell marker
|
|
|
|
|
- # See if cell is in cell Dict
|
|
|
|
|
- cell = self.getBattleCellFromNodePath(nodePath)
|
|
|
|
|
- return cell, 'battleCellMarker'
|
|
|
|
|
- else:
|
|
|
|
|
- # If reached the top: fail
|
|
|
|
|
- if not nodePath.hasParent():
|
|
|
|
|
- return None, None
|
|
|
|
|
- else:
|
|
|
|
|
- # Try parent
|
|
|
|
|
- return self.findPointOrCell(nodePath.getParent())
|
|
|
|
|
-
|
|
|
|
|
- # MANIPULATION FUNCTIONS
|
|
|
|
|
- def keyboardRotateSelected(self, arrowDirection):
|
|
|
|
|
- """ Rotate selected objects using arrow keys """
|
|
|
|
|
- # Get snap angle
|
|
|
|
|
- if base.direct.fShift:
|
|
|
|
|
- oldSnapAngle = base.direct.grid.snapAngle
|
|
|
|
|
- base.direct.grid.setSnapAngle(1.0)
|
|
|
|
|
- snapAngle = base.direct.grid.snapAngle
|
|
|
|
|
- # Compute new angle
|
|
|
|
|
- if ((arrowDirection == 'left') or (arrowDirection == 'up')):
|
|
|
|
|
- self.setLastAngle(self.getLastAngle() + snapAngle)
|
|
|
|
|
- else:
|
|
|
|
|
- self.setLastAngle(self.getLastAngle() - snapAngle)
|
|
|
|
|
-
|
|
|
|
|
- if (self.getLastAngle() < -180.0):
|
|
|
|
|
- self.setLastAngle(self.getLastAngle() + 360.0)
|
|
|
|
|
- elif (self.getLastAngle() > 180.0):
|
|
|
|
|
- self.setLastAngle(self.getLastAngle() - 360.0)
|
|
|
|
|
- # Move selected objects
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- selectedNode.setHpr(self.getLastAngle(), 0, 0)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
- if base.direct.fShift:
|
|
|
|
|
- base.direct.grid.setSnapAngle(oldSnapAngle)
|
|
|
|
|
-
|
|
|
|
|
- def keyboardTranslateSelected(self, arrowDirection):
|
|
|
|
|
- gridToCamera = base.direct.grid.getMat(base.direct.camera)
|
|
|
|
|
- camXAxis = gridToCamera.xformVec(X_AXIS)
|
|
|
|
|
- xxDot = camXAxis.dot(X_AXIS)
|
|
|
|
|
- xzDot = camXAxis.dot(Z_AXIS)
|
|
|
|
|
-
|
|
|
|
|
- # what is the current grid spacing?
|
|
|
|
|
- if base.direct.fShift:
|
|
|
|
|
- # If shift, divide grid spacing by 10.0
|
|
|
|
|
- oldGridSpacing = base.direct.grid.gridSpacing
|
|
|
|
|
- # Use back door to set grid spacing to avoid grid update
|
|
|
|
|
- base.direct.grid.gridSpacing = base.direct.grid.gridSpacing/10.0
|
|
|
|
|
- deltaMove = base.direct.grid.gridSpacing
|
|
|
|
|
-
|
|
|
|
|
- # Compute the specified delta
|
|
|
|
|
- deltaPos = Vec3(0)
|
|
|
|
|
- if (abs(xxDot) > abs(xzDot)):
|
|
|
|
|
- if (xxDot < 0.0):
|
|
|
|
|
- deltaMove = -deltaMove
|
|
|
|
|
- # Compute delta
|
|
|
|
|
- if (arrowDirection == 'right'):
|
|
|
|
|
- deltaPos.setX(deltaPos[0] + deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'left'):
|
|
|
|
|
- deltaPos.setX(deltaPos[0] - deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'up'):
|
|
|
|
|
- deltaPos.setY(deltaPos[1] + deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'down'):
|
|
|
|
|
- deltaPos.setY(deltaPos[1] - deltaMove)
|
|
|
|
|
- else:
|
|
|
|
|
- if (xzDot < 0.0):
|
|
|
|
|
- deltaMove = -deltaMove
|
|
|
|
|
- # Compute delta
|
|
|
|
|
- if (arrowDirection == 'right'):
|
|
|
|
|
- deltaPos.setY(deltaPos[1] - deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'left'):
|
|
|
|
|
- deltaPos.setY(deltaPos[1] + deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'up'):
|
|
|
|
|
- deltaPos.setX(deltaPos[0] + deltaMove)
|
|
|
|
|
- elif (arrowDirection == 'down'):
|
|
|
|
|
- deltaPos.setX(deltaPos[0] - deltaMove)
|
|
|
|
|
-
|
|
|
|
|
- # Move selected objects
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- # Move it
|
|
|
|
|
- selectedNode.setPos(base.direct.grid,
|
|
|
|
|
- selectedNode.getPos(base.direct.grid) + deltaPos)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
- # Restore grid spacing
|
|
|
|
|
- if base.direct.fShift:
|
|
|
|
|
- # Use back door to set grid spacing to avoid grid update
|
|
|
|
|
- base.direct.grid.gridSpacing = oldGridSpacing
|
|
|
|
|
-
|
|
|
|
|
- def keyboardXformSelected(self, arrowDirection, mode):
|
|
|
|
|
- if mode == 'rotate':
|
|
|
|
|
- self.keyboardRotateSelected(arrowDirection)
|
|
|
|
|
- else:
|
|
|
|
|
- self.keyboardTranslateSelected(arrowDirection)
|
|
|
|
|
-
|
|
|
|
|
- # VISIBILITY FUNCTIONS
|
|
|
|
|
- def editDNAVisGroups(self):
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- if visGroups:
|
|
|
|
|
- self.vgpanel = VisGroupsEditor(self, visGroups)
|
|
|
|
|
- else:
|
|
|
|
|
- showinfo('Vis Groups Editor','No DNA Vis Groups Found!')
|
|
|
|
|
-
|
|
|
|
|
- def getDNAVisGroups(self, nodePath):
|
|
|
|
|
- """ Find the highest level vis groups in the scene graph """
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_VIS_GROUP):
|
|
|
|
|
- return [[nodePath, dnaNode]]
|
|
|
|
|
- childVisGroups = []
|
|
|
|
|
- children = nodePath.getChildren()
|
|
|
|
|
- for child in children:
|
|
|
|
|
- childVisGroups = (childVisGroups + self.getDNAVisGroups(child))
|
|
|
|
|
- return childVisGroups
|
|
|
|
|
-
|
|
|
|
|
- def findParentVisGroup(self, nodePath):
|
|
|
|
|
- """ Find the containing vis group """
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_VIS_GROUP):
|
|
|
|
|
- return nodePath, dnaNode
|
|
|
|
|
- elif nodePath.hasParent():
|
|
|
|
|
- return self.findParentVisGroup(nodePath.getParent())
|
|
|
|
|
- # Fall through
|
|
|
|
|
- return None, None
|
|
|
|
|
-
|
|
|
|
|
- def showGrid(self, flag):
|
|
|
|
|
- """ toggle direct grid """
|
|
|
|
|
- if flag:
|
|
|
|
|
- base.direct.grid.enable()
|
|
|
|
|
- else:
|
|
|
|
|
- base.direct.grid.disable()
|
|
|
|
|
-
|
|
|
|
|
- # LEVEL MAP/MARKER FUNCTIONS
|
|
|
|
|
- def createLevelMaps(self):
|
|
|
|
|
- """
|
|
|
|
|
- Load up the various neighborhood maps
|
|
|
|
|
- """
|
|
|
|
|
- # For neighborhood maps
|
|
|
|
|
- self.levelMap = hidden.attachNewNode('level-map')
|
|
|
|
|
- self.activeMap = None
|
|
|
|
|
- self.mapDictionary = {}
|
|
|
|
|
- """
|
|
|
|
|
- for neighborhood in NEIGHBORHOODS:
|
|
|
|
|
- self.createMap(neighborhood)
|
|
|
|
|
- """
|
|
|
|
|
-
|
|
|
|
|
- def createMap(self, neighborhood):
|
|
|
|
|
- map = loader.loadModel('models/level_editor/' + neighborhood +
|
|
|
|
|
- '_layout')
|
|
|
|
|
- if map:
|
|
|
|
|
- map.setTransparency(1)
|
|
|
|
|
- map.setColor(Vec4(1, 1, 1, .4))
|
|
|
|
|
- self.mapDictionary[neighborhood] = map
|
|
|
|
|
- # Make sure this item isn't pickable
|
|
|
|
|
- base.direct.addUnpickable(neighborhood + '_layout')
|
|
|
|
|
-
|
|
|
|
|
- def selectMap(self, neighborhood):
|
|
|
|
|
- if self.activeMap:
|
|
|
|
|
- self.activeMap.reparentTo(hidden)
|
|
|
|
|
- if self.mapDictionary.has_key(neighborhood):
|
|
|
|
|
- self.activeMap = self.mapDictionary[neighborhood]
|
|
|
|
|
- self.activeMap.reparentTo(self.levelMap)
|
|
|
|
|
-
|
|
|
|
|
- def toggleMapVis(self, flag):
|
|
|
|
|
- if flag:
|
|
|
|
|
- self.levelMap.reparentTo(base.direct.group)
|
|
|
|
|
- else:
|
|
|
|
|
- self.levelMap.reparentTo(hidden)
|
|
|
|
|
-
|
|
|
|
|
- def createInsertionMarker(self):
|
|
|
|
|
- self.insertionMarker = LineNodePath(self)
|
|
|
|
|
- self.insertionMarker.lineNode.setName('insertionMarker')
|
|
|
|
|
- self.insertionMarker.setColor(VBase4(0.785, 0.785, 0.5, 1))
|
|
|
|
|
- self.insertionMarker.setThickness(1)
|
|
|
|
|
- self.insertionMarker.reset()
|
|
|
|
|
- self.insertionMarker.moveTo(-75, 0, 0)
|
|
|
|
|
- self.insertionMarker.drawTo(75, 0, 0)
|
|
|
|
|
- self.insertionMarker.moveTo(0, -75, 0)
|
|
|
|
|
- self.insertionMarker.drawTo(0, 75, 0)
|
|
|
|
|
- self.insertionMarker.moveTo(0, 0, -75)
|
|
|
|
|
- self.insertionMarker.drawTo(0, 0, 75)
|
|
|
|
|
- self.insertionMarker.create()
|
|
|
|
|
-
|
|
|
|
|
- def spawnInsertionMarkerTask(self):
|
|
|
|
|
- taskMgr.add(self.insertionMarkerTask, 'insertionMarkerTask')
|
|
|
|
|
-
|
|
|
|
|
- def insertionMarkerTask(self, state):
|
|
|
|
|
- self.insertionMarker.setPosHpr(base.direct.grid, 0, 0, 0, 0, 0, 0)
|
|
|
|
|
- # MRM: Why is this necessary?
|
|
|
|
|
- self.insertionMarker.setScale(1, 1, 1)
|
|
|
|
|
- return Task.cont
|
|
|
|
|
-
|
|
|
|
|
- # UTILITY FUNCTIONS
|
|
|
|
|
- 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 getRandomWindowCount(self):
|
|
|
|
|
- if ((self.lastWall != None) and (self.lastBuilding != None)):
|
|
|
|
|
- h = ROUND_INT(self.lastWall.getHeight())
|
|
|
|
|
- w = ROUND_INT(self.lastBuilding.getWidth())
|
|
|
|
|
- # Otherwise....
|
|
|
|
|
- if w == 5:
|
|
|
|
|
- # 5 ft walls can have 1 window
|
|
|
|
|
- return 1
|
|
|
|
|
- elif h == 10:
|
|
|
|
|
- # All other 10 ft high bldgs can have 1 or 2
|
|
|
|
|
- return randint(1, 2)
|
|
|
|
|
- else:
|
|
|
|
|
- # All others can have 1 - 4
|
|
|
|
|
- return randint(1, 4)
|
|
|
|
|
- else:
|
|
|
|
|
- return 1
|
|
|
|
|
-
|
|
|
|
|
- def autoPositionGrid(self, fLerp = 1):
|
|
|
|
|
- taskMgr.remove('autoPositionGrid')
|
|
|
|
|
- # Move grid to prepare for placement of next object
|
|
|
|
|
- selectedNode = base.direct.selected.last
|
|
|
|
|
- if selectedNode:
|
|
|
|
|
- dnaNode = self.findDNANode(selectedNode)
|
|
|
|
|
- if dnaNode == None:
|
|
|
|
|
- return
|
|
|
|
|
- nodeClass = DNAGetClassType(dnaNode)
|
|
|
|
|
- deltaPos = Point3(20, 0, 0)
|
|
|
|
|
- deltaHpr = VBase3(0)
|
|
|
|
|
- if nodeClass.eq(DNA_FLAT_BUILDING):
|
|
|
|
|
- deltaPos.setX(dnaNode.getWidth())
|
|
|
|
|
- elif nodeClass.eq(DNA_STREET):
|
|
|
|
|
- objectCode = dnaNode.getCode()
|
|
|
|
|
- deltas = self.getNextSnapPoint()
|
|
|
|
|
- deltaPos.assign(deltas[0])
|
|
|
|
|
- deltaHpr.assign(deltas[1])
|
|
|
|
|
- elif nodeClass.eq(DNA_LANDMARK_BUILDING):
|
|
|
|
|
- objectCode = dnaNode.getCode()
|
|
|
|
|
- if objectCode[-2:-1] == 'A':
|
|
|
|
|
- deltaPos.setX(25.0)
|
|
|
|
|
- elif objectCode[-2:-1] == 'B':
|
|
|
|
|
- deltaPos.setX(15.0)
|
|
|
|
|
- elif objectCode[-2:-1] == 'C':
|
|
|
|
|
- deltaPos.setX(20.0)
|
|
|
|
|
-
|
|
|
|
|
- if fLerp:
|
|
|
|
|
- # Position grid for placing next object
|
|
|
|
|
- # Eventually we need to setHpr too
|
|
|
|
|
- t = base.direct.grid.lerpPosHpr(
|
|
|
|
|
- deltaPos, deltaHpr, 0.25,
|
|
|
|
|
- other = selectedNode,
|
|
|
|
|
- blendType = 'easeInOut',
|
|
|
|
|
- task = 'autoPositionGrid')
|
|
|
|
|
- t.deltaPos = deltaPos
|
|
|
|
|
- t.deltaHpr = deltaHpr
|
|
|
|
|
- t.selectedNode = selectedNode
|
|
|
|
|
- t.setUponDeath(self.autoPositionCleanup)
|
|
|
|
|
- else:
|
|
|
|
|
- base.direct.grid.setPosHpr(selectedNode, deltaPos, deltaHpr)
|
|
|
|
|
-
|
|
|
|
|
- if self.mouseMayaCamera:
|
|
|
|
|
- return
|
|
|
|
|
- # Also move the camera
|
|
|
|
|
- taskMgr.remove('autoMoveDelay')
|
|
|
|
|
- handlesToCam = base.direct.widget.getPos(base.direct.camera)
|
|
|
|
|
- handlesToCam = handlesToCam * (base.direct.dr.near/handlesToCam[1])
|
|
|
|
|
- if ((abs(handlesToCam[0]) > (base.direct.dr.nearWidth * 0.4)) or
|
|
|
|
|
- (abs(handlesToCam[2]) > (base.direct.dr.nearHeight * 0.4))):
|
|
|
|
|
- taskMgr.remove('manipulateCamera')
|
|
|
|
|
- base.direct.cameraControl.centerCamIn(0.5)
|
|
|
|
|
-
|
|
|
|
|
- def autoPositionCleanup(self, state):
|
|
|
|
|
- base.direct.grid.setPosHpr(state.selectedNode, state.deltaPos,
|
|
|
|
|
- state.deltaHpr)
|
|
|
|
|
- if base.direct.grid.getHprSnap():
|
|
|
|
|
- # Clean up grid angle
|
|
|
|
|
- base.direct.grid.setH(ROUND_TO(base.direct.grid.getH(),
|
|
|
|
|
- base.direct.grid.snapAngle))
|
|
|
|
|
-
|
|
|
|
|
- def getNextSnapPoint(self):
|
|
|
|
|
- """ Pull next pos hpr deltas off of snap list then rotate list """
|
|
|
|
|
- if self.snapList:
|
|
|
|
|
- deltas = self.snapList[0]
|
|
|
|
|
- # Rotate list by one
|
|
|
|
|
- self.snapList = self.snapList[1:] + self.snapList[:1]
|
|
|
|
|
- return deltas
|
|
|
|
|
- else:
|
|
|
|
|
- return (ZERO_VEC, ZERO_VEC)
|
|
|
|
|
-
|
|
|
|
|
- def getWallIntersectionPoint(self, selectedNode):
|
|
|
|
|
- """
|
|
|
|
|
- Return point of intersection between building's wall and line from cam
|
|
|
|
|
- through mouse.
|
|
|
|
|
- """
|
|
|
|
|
- # Find mouse point on near plane
|
|
|
|
|
- mouseX = base.direct.dr.mouseX
|
|
|
|
|
- mouseY = base.direct.dr.mouseY
|
|
|
|
|
- nearX = (math.tan(deg2Rad(base.direct.dr.fovH)/2.0) *
|
|
|
|
|
- mouseX * base.direct.dr.near)
|
|
|
|
|
- nearZ = (math.tan(deg2Rad(base.direct.dr.fovV)/2.0) *
|
|
|
|
|
- mouseY * base.direct.dr.near)
|
|
|
|
|
- # Initialize points
|
|
|
|
|
- mCam2Wall = base.direct.camera.getMat(selectedNode)
|
|
|
|
|
- mouseOrigin = Point3(0)
|
|
|
|
|
- mouseOrigin.assign(mCam2Wall.getRow3(3))
|
|
|
|
|
- mouseDir = Vec3(0)
|
|
|
|
|
- mouseDir.set(nearX, base.direct.dr.near, nearZ)
|
|
|
|
|
- mouseDir.assign(mCam2Wall.xformVec(mouseDir))
|
|
|
|
|
- # Calc intersection point
|
|
|
|
|
- return planeIntersect(mouseOrigin, mouseDir, ZERO_POINT, NEG_Y_AXIS)
|
|
|
|
|
-
|
|
|
|
|
- def getGridSnapIntersectionPoint(self):
|
|
|
|
|
- """
|
|
|
|
|
- Return point of intersection between ground plane and line from cam
|
|
|
|
|
- through mouse. Return false, if nothing selected. Snap to grid.
|
|
|
|
|
- """
|
|
|
|
|
- return base.direct.grid.computeSnapPoint(self.getGridIntersectionPoint())
|
|
|
|
|
-
|
|
|
|
|
- def getGridIntersectionPoint(self):
|
|
|
|
|
- """
|
|
|
|
|
- Return point of intersection between ground plane and line from cam
|
|
|
|
|
- through mouse. Return false, if nothing selected
|
|
|
|
|
- """
|
|
|
|
|
- # Find mouse point on near plane
|
|
|
|
|
- mouseX = base.direct.dr.mouseX
|
|
|
|
|
- mouseY = base.direct.dr.mouseY
|
|
|
|
|
- nearX = (math.tan(deg2Rad(base.direct.dr.fovH)/2.0) *
|
|
|
|
|
- mouseX * base.direct.dr.near)
|
|
|
|
|
- nearZ = (math.tan(deg2Rad(base.direct.dr.fovV)/2.0) *
|
|
|
|
|
- mouseY * base.direct.dr.near)
|
|
|
|
|
- # Initialize points
|
|
|
|
|
- mCam2Grid = base.direct.camera.getMat(base.direct.grid)
|
|
|
|
|
- mouseOrigin = Point3(0)
|
|
|
|
|
- mouseOrigin.assign(mCam2Grid.getRow3(3))
|
|
|
|
|
- mouseDir = Vec3(0)
|
|
|
|
|
- mouseDir.set(nearX, base.direct.dr.near, nearZ)
|
|
|
|
|
- mouseDir.assign(mCam2Grid.xformVec(mouseDir))
|
|
|
|
|
- # Calc intersection point
|
|
|
|
|
- return planeIntersect(mouseOrigin, mouseDir, ZERO_POINT, Z_AXIS)
|
|
|
|
|
-
|
|
|
|
|
- def jumpToInsertionPoint(self):
|
|
|
|
|
- """ Move selected object to insertion point """
|
|
|
|
|
- selectedNode = base.direct.selected.last
|
|
|
|
|
- if selectedNode:
|
|
|
|
|
- # Check if its a dna node
|
|
|
|
|
- dnaNode = self.findDNANode(selectedNode)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- # Place the new node path at the current grid origin
|
|
|
|
|
- selectedNode.setPos(base.direct.grid, 0, 0, 0)
|
|
|
|
|
- # Initialize angle to match last object
|
|
|
|
|
- selectedNode.setHpr(self.getLastAngle(), 0, 0)
|
|
|
|
|
- # Now update DNA pos and hpr to reflect final pose
|
|
|
|
|
- dnaNode.setPos(selectedNode.getPos())
|
|
|
|
|
- dnaNode.setHpr(selectedNode.getHpr())
|
|
|
|
|
- # Update grid to get ready for the next object
|
|
|
|
|
- self.autoPositionGrid()
|
|
|
|
|
-
|
|
|
|
|
- # CVS OPERATIONS
|
|
|
|
|
- def cvsUpdate(self, filename):
|
|
|
|
|
- dirname = os.path.dirname(filename)
|
|
|
|
|
- if not os.path.isdir(dirname):
|
|
|
|
|
- print 'Cannot CVS update %s: invalid directory' % (filename)
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- basename = os.path.basename(filename)
|
|
|
|
|
- cwd = os.getcwd()
|
|
|
|
|
- os.chdir(dirname)
|
|
|
|
|
- cvsCommand = 'cvs update ' + basename
|
|
|
|
|
- print cvsCommand
|
|
|
|
|
- os.system(cvsCommand)
|
|
|
|
|
- os.chdir(cwd)
|
|
|
|
|
-
|
|
|
|
|
- def cvsAdd(self, filename):
|
|
|
|
|
- dirname = os.path.dirname(filename)
|
|
|
|
|
- if not os.path.isdir(dirname):
|
|
|
|
|
- print 'Cannot CVS add %s: invalid directory' % (filename)
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- basename = os.path.basename(filename)
|
|
|
|
|
- cwd = os.getcwd()
|
|
|
|
|
- os.chdir(dirname)
|
|
|
|
|
- cvsCommand = 'cvs add ' + basename
|
|
|
|
|
- print cvsCommand
|
|
|
|
|
- os.system(cvsCommand)
|
|
|
|
|
- os.chdir(cwd)
|
|
|
|
|
-
|
|
|
|
|
- def cvsUpdateAll(self):
|
|
|
|
|
- # Update the entire dna source directory.
|
|
|
|
|
- dirname = dnaDirectory.toOsSpecific()
|
|
|
|
|
- if not os.path.isdir(dirname):
|
|
|
|
|
- print 'Cannot CVS commit: invalid directory'
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- cwd = os.getcwd()
|
|
|
|
|
- os.chdir(dirname)
|
|
|
|
|
- cvsCommand = 'cvs update -dP'
|
|
|
|
|
- print cvsCommand
|
|
|
|
|
- os.system(cvsCommand)
|
|
|
|
|
- os.chdir(cwd)
|
|
|
|
|
-
|
|
|
|
|
- def cvsCommitAll(self):
|
|
|
|
|
- # cvs commit always commits the entire dna source directory.
|
|
|
|
|
- dirname = dnaDirectory.toOsSpecific()
|
|
|
|
|
- if not os.path.isdir(dirname):
|
|
|
|
|
- print 'Cannot CVS commit: invalid directory'
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- cwd = os.getcwd()
|
|
|
|
|
- os.chdir(dirname)
|
|
|
|
|
- cvsCommand = 'cvs commit -m "level editor"'
|
|
|
|
|
- print cvsCommand
|
|
|
|
|
- os.system(cvsCommand)
|
|
|
|
|
- os.chdir(cwd)
|
|
|
|
|
-
|
|
|
|
|
- # STYLE/DNA FILE FUNCTIONS
|
|
|
|
|
- def loadSpecifiedDNAFile(self):
|
|
|
|
|
- path = dnaDirectory.toOsSpecific()
|
|
|
|
|
- if not os.path.isdir(path):
|
|
|
|
|
- print 'LevelEditor Warning: Invalid default DNA directory!'
|
|
|
|
|
- print 'Using current directory'
|
|
|
|
|
- path = '.'
|
|
|
|
|
- dnaFilename = askopenfilename(
|
|
|
|
|
- defaultextension = '.dna',
|
|
|
|
|
- filetypes = (('DNA Files', '*.dna'), ('All files', '*')),
|
|
|
|
|
- initialdir = path,
|
|
|
|
|
- title = 'Load DNA File',
|
|
|
|
|
- parent = self.panel.component('hull'))
|
|
|
|
|
- if dnaFilename:
|
|
|
|
|
- self.loadDNAFromFile(dnaFilename)
|
|
|
|
|
- self.outputFile = dnaFilename
|
|
|
|
|
- print "Finished Load: ", dnaFilename
|
|
|
|
|
-
|
|
|
|
|
- def saveToSpecifiedDNAFile(self):
|
|
|
|
|
- path = dnaDirectory.toOsSpecific()
|
|
|
|
|
- if not os.path.isdir(path):
|
|
|
|
|
- print 'LevelEditor Warning: Invalid DNA save directory!'
|
|
|
|
|
- print 'Using current directory'
|
|
|
|
|
- path = '.'
|
|
|
|
|
- dnaFilename = asksaveasfilename(
|
|
|
|
|
- defaultextension = '.dna',
|
|
|
|
|
- filetypes = (('DNA Files', '*.dna'), ('All files', '*')),
|
|
|
|
|
- initialdir = path,
|
|
|
|
|
- title = 'Save DNA File as',
|
|
|
|
|
- parent = self.panel.component('hull'))
|
|
|
|
|
- if dnaFilename:
|
|
|
|
|
- self.outputDNA(dnaFilename)
|
|
|
|
|
- self.outputFile = dnaFilename
|
|
|
|
|
-
|
|
|
|
|
- def loadDNAFromFile(self, filename):
|
|
|
|
|
- print filename
|
|
|
|
|
- # Reset level, destroying existing scene/DNA hierarcy
|
|
|
|
|
- self.reset(fDeleteToplevel = 1, fCreateToplevel = 0,
|
|
|
|
|
- fUpdateExplorer = 0)
|
|
|
|
|
- # Now load in new file
|
|
|
|
|
- if fUseCVS:
|
|
|
|
|
- self.cvsUpdate(filename)
|
|
|
|
|
- try:
|
|
|
|
|
- node = loadDNAFile(DNASTORE, Filename.fromOsSpecific(filename).cStr(), CSDefault, 1)
|
|
|
|
|
- except Exception:
|
|
|
|
|
- self.notify.debug("Couldn't load specified DNA file. Please make sure storage code has been specified in Config.prc file")
|
|
|
|
|
- if node.getNumParents() == 1:
|
|
|
|
|
- # If the node already has a parent arc when it's loaded, we must
|
|
|
|
|
- # be using the level editor and we want to preserve that arc.
|
|
|
|
|
- newNPToplevel = NodePath(node)
|
|
|
|
|
- newNPToplevel.reparentTo(hidden)
|
|
|
|
|
- else:
|
|
|
|
|
- # Otherwise, we should create a new arc for the node.
|
|
|
|
|
- newNPToplevel = hidden.attachNewNode(node)
|
|
|
|
|
-
|
|
|
|
|
- # Make sure the topmost file DNA object gets put under DNARoot
|
|
|
|
|
- newDNAToplevel = self.findDNANode(newNPToplevel)
|
|
|
|
|
-
|
|
|
|
|
- # reset the landmark block number:
|
|
|
|
|
- (self.landmarkBlock, needTraverse)=self.findHighestLandmarkBlock(
|
|
|
|
|
- newDNAToplevel, newNPToplevel)
|
|
|
|
|
-
|
|
|
|
|
- # Update toplevel variables
|
|
|
|
|
- if needTraverse:
|
|
|
|
|
- self.createToplevel(newDNAToplevel)
|
|
|
|
|
- else:
|
|
|
|
|
- self.createToplevel(newDNAToplevel, newNPToplevel)
|
|
|
|
|
-
|
|
|
|
|
- # Create visible representations of all the paths and battle cells
|
|
|
|
|
- self.createSuitPaths()
|
|
|
|
|
- self.hideSuitPaths()
|
|
|
|
|
- self.createBattleCells()
|
|
|
|
|
- self.hideBattleCells()
|
|
|
|
|
- # Set the title bar to have the filename to make it easier
|
|
|
|
|
- # to remember what file you are working on
|
|
|
|
|
- self.panel["title"] = 'Level Editor: ' + os.path.basename(filename)
|
|
|
|
|
- self.panel.sceneGraphExplorer.update()
|
|
|
|
|
-
|
|
|
|
|
- def outputDNADefaultFile(self):
|
|
|
|
|
- outputFile = self.outputFile
|
|
|
|
|
- if outputFile == None:
|
|
|
|
|
- outputFile = self.neighborhood + '_working.dna'
|
|
|
|
|
- file = os.path.join(dnaDirectory.toOsSpecific(), outputFile)
|
|
|
|
|
- self.outputDNA(file)
|
|
|
|
|
-
|
|
|
|
|
- def outputDNA(self, filename):
|
|
|
|
|
- print 'Saving DNA to: ', filename
|
|
|
|
|
- binaryFilename = Filename(filename)
|
|
|
|
|
- binaryFilename.setBinary()
|
|
|
|
|
- self.DNAData.writeDna(binaryFilename, Notify.out(), DNASTORE)
|
|
|
|
|
-
|
|
|
|
|
- def saveColor(self):
|
|
|
|
|
- self.appendColorToColorPaletteFile(self.panel.colorEntry.get())
|
|
|
|
|
-
|
|
|
|
|
- def appendColorToColorPaletteFile(self, color):
|
|
|
|
|
- obj = self.DNATarget
|
|
|
|
|
- if obj:
|
|
|
|
|
- classType = DNAGetClassType(obj)
|
|
|
|
|
- if classType.eq(DNA_WALL):
|
|
|
|
|
- tag = 'wall_color:'
|
|
|
|
|
- elif classType.eq(DNA_WINDOWS):
|
|
|
|
|
- tag = 'window_color:'
|
|
|
|
|
- elif classType.eq(DNA_DOOR):
|
|
|
|
|
- tag = 'door_color:'
|
|
|
|
|
- elif classType.eq(DNA_FLAT_DOOR):
|
|
|
|
|
- tag = 'door_color:'
|
|
|
|
|
- elif classType.eq(DNA_CORNICE):
|
|
|
|
|
- tag = 'cornice_color:'
|
|
|
|
|
- elif classType.eq(DNA_PROP):
|
|
|
|
|
- tag = 'prop_color:'
|
|
|
|
|
- else:
|
|
|
|
|
- return
|
|
|
|
|
- # Valid type, add color to file
|
|
|
|
|
- filename = self.neighborhood + '_colors.txt'
|
|
|
|
|
- fname = Filename(dnaDirectory.getFullpath() +
|
|
|
|
|
- '/stylefiles/' + filename)
|
|
|
|
|
- f = open(fname.toOsSpecific(), 'ab')
|
|
|
|
|
- f.write('%s Vec4(%.2f, %.2f, %.2f, 1.0)\n' %
|
|
|
|
|
- (tag,
|
|
|
|
|
- color[0]/255.0,
|
|
|
|
|
- color[1]/255.0,
|
|
|
|
|
- color[2]/255.0))
|
|
|
|
|
- f.close()
|
|
|
|
|
-
|
|
|
|
|
- def saveStyle(self, filename, style):
|
|
|
|
|
- # A generic routine to append a new style definition to one of
|
|
|
|
|
- # the style files.
|
|
|
|
|
-
|
|
|
|
|
- fname = Filename(dnaDirectory.getFullpath() +
|
|
|
|
|
- '/stylefiles/' + filename)
|
|
|
|
|
- # We use binary mode to avoid Windows' end-of-line convention
|
|
|
|
|
- f = open(fname.toOsSpecific(), 'ab')
|
|
|
|
|
- # Add a blank line
|
|
|
|
|
- f.write('\n')
|
|
|
|
|
- # Now output style details to file
|
|
|
|
|
- style.output(f)
|
|
|
|
|
- # Close the file
|
|
|
|
|
- f.close()
|
|
|
|
|
-
|
|
|
|
|
- def saveBaselineStyle(self):
|
|
|
|
|
- if self.panel.currentBaselineDNA:
|
|
|
|
|
- # Valid baseline, add style to file
|
|
|
|
|
- filename = self.neighborhood + '_baseline_styles.txt'
|
|
|
|
|
- style = DNABaselineStyle(self.panel.currentBaselineDNA)
|
|
|
|
|
- self.saveStyle(filename, style)
|
|
|
|
|
-
|
|
|
|
|
- def saveWallStyle(self):
|
|
|
|
|
- if self.lastWall:
|
|
|
|
|
- # Valid wall, add style to file
|
|
|
|
|
- filename = self.neighborhood + '_wall_styles.txt'
|
|
|
|
|
- style = DNAWallStyle(self.lastWall)
|
|
|
|
|
- self.saveStyle(filename, style)
|
|
|
|
|
-
|
|
|
|
|
- def saveBuildingStyle(self):
|
|
|
|
|
- dnaObject = self.selectedDNARoot
|
|
|
|
|
- if dnaObject:
|
|
|
|
|
- if DNAClassEqual(dnaObject, DNA_FLAT_BUILDING):
|
|
|
|
|
- # Valid wall, add style to file
|
|
|
|
|
- filename = self.neighborhood + '_building_styles.txt'
|
|
|
|
|
- style = DNAFlatBuildingStyle(dnaObject)
|
|
|
|
|
- self.saveStyle(filename, style)
|
|
|
|
|
- return
|
|
|
|
|
- print 'Must select building before saving building style'
|
|
|
|
|
-
|
|
|
|
|
- # GET/SET
|
|
|
|
|
- # DNA Object elements
|
|
|
|
|
- def getWall(self, dnaFlatBuilding, wallNum):
|
|
|
|
|
- wallCount = 0
|
|
|
|
|
- for i in range(dnaFlatBuilding.getNumChildren()):
|
|
|
|
|
- child = dnaFlatBuilding.at(i)
|
|
|
|
|
- if DNAClassEqual(child, DNA_WALL):
|
|
|
|
|
- if wallCount == wallNum:
|
|
|
|
|
- return child
|
|
|
|
|
- wallCount = wallCount + 1
|
|
|
|
|
- # Not found
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
- def computeWallNum(self, aDNAFlatBuilding, hitPt):
|
|
|
|
|
- """
|
|
|
|
|
- Given a hitPt, return wall number if cursor is over building
|
|
|
|
|
- Return -1 if cursor is outside of building
|
|
|
|
|
- """
|
|
|
|
|
- xPt = hitPt[0]
|
|
|
|
|
- zPt = hitPt[2]
|
|
|
|
|
- # Left or right of building
|
|
|
|
|
- if ((xPt < 0) or (xPt > aDNAFlatBuilding.getWidth())):
|
|
|
|
|
- return -1
|
|
|
|
|
- # Below the building
|
|
|
|
|
- if zPt < 0:
|
|
|
|
|
- return -1
|
|
|
|
|
- # Above z = 0 and within wall width, check height of walls
|
|
|
|
|
- heightList, offsetList = DNAGetWallHeights(aDNAFlatBuilding)
|
|
|
|
|
- wallNum = 0
|
|
|
|
|
- for i in range(len(heightList)):
|
|
|
|
|
- # Compute top of wall segment
|
|
|
|
|
- top = offsetList[i] + heightList[i]
|
|
|
|
|
- if zPt < top:
|
|
|
|
|
- return wallNum
|
|
|
|
|
- wallNum = wallNum + 1
|
|
|
|
|
- return -1
|
|
|
|
|
-
|
|
|
|
|
- def getWindowCount(self, dnaWall):
|
|
|
|
|
- windowCount = 0
|
|
|
|
|
- for i in range(dnaWall.getNumChildren()):
|
|
|
|
|
- child = dnaWall.at(i)
|
|
|
|
|
- if DNAClassEqual(child, DNA_WINDOWS):
|
|
|
|
|
- windowCount = windowCount + 1
|
|
|
|
|
- # Not found
|
|
|
|
|
- return windowCount
|
|
|
|
|
-
|
|
|
|
|
- # Style manager edit mode
|
|
|
|
|
- def setEditMode(self, neighborhood):
|
|
|
|
|
- self.neighborhood = neighborhood
|
|
|
|
|
- self.neighborhoodCode = NEIGHBORHOOD_CODES[self.neighborhood]
|
|
|
|
|
- if neighborhood == 'toontown_central':
|
|
|
|
|
- self.outputDir = 'ToontownCentral'
|
|
|
|
|
- elif neighborhood == 'donalds_dock':
|
|
|
|
|
- self.outputDir = 'DonaldsDock'
|
|
|
|
|
- elif neighborhood == 'minnies_melody_land':
|
|
|
|
|
- self.outputDir = 'MinniesMelodyLand'
|
|
|
|
|
- elif neighborhood == 'the_burrrgh':
|
|
|
|
|
- self.outputDir = 'TheBurrrgh'
|
|
|
|
|
- elif neighborhood == 'daisys_garden':
|
|
|
|
|
- self.outputDir = 'DaisysGarden'
|
|
|
|
|
- elif neighborhood == 'donalds_dreamland':
|
|
|
|
|
- self.outputDir = 'DonaldsDreamland'
|
|
|
|
|
- self.panel.editMenu.selectitem(neighborhood)
|
|
|
|
|
- self.styleManager.setEditMode(neighborhood)
|
|
|
|
|
- self.panel.updateHeightList(self.getCurrent('building_height'))
|
|
|
|
|
- self.selectMap(neighborhood)
|
|
|
|
|
-
|
|
|
|
|
- def getEditMode(self):
|
|
|
|
|
- return self.styleManager.getEditMode()
|
|
|
|
|
-
|
|
|
|
|
- # Level Style Attributes
|
|
|
|
|
- def __getitem__(self, attribute):
|
|
|
|
|
- """ Return top level entry in attribute dictionary """
|
|
|
|
|
- return self.styleManager.attributeDictionary[attribute]
|
|
|
|
|
-
|
|
|
|
|
- def getAttribute(self, attribute):
|
|
|
|
|
- """ Return specified attribute for current neighborhood """
|
|
|
|
|
- return self.styleManager.getAttribute(attribute)
|
|
|
|
|
-
|
|
|
|
|
- def hasAttribute(self, attribute):
|
|
|
|
|
- """ Return specified attribute for current neighborhood """
|
|
|
|
|
- return self.styleManager.hasAttribute(attribute)
|
|
|
|
|
-
|
|
|
|
|
- def getCurrent(self, attribute):
|
|
|
|
|
- """ Return neighborhood's current selection for specified attribute """
|
|
|
|
|
- return self.getAttribute(attribute).getCurrent()
|
|
|
|
|
-
|
|
|
|
|
- def setCurrent(self, attribute, newCurrent):
|
|
|
|
|
- """ Set neighborhood's current selection for specified attribute """
|
|
|
|
|
- self.getAttribute(attribute).setCurrent(newCurrent, fEvent = 0)
|
|
|
|
|
-
|
|
|
|
|
- def getMenu(self, attribute):
|
|
|
|
|
- """ Return neighborhood's Pie Menu object for specified attribute """
|
|
|
|
|
- return self.getAttribute(attribute).getMenu()
|
|
|
|
|
-
|
|
|
|
|
- def getDict(self, attribute):
|
|
|
|
|
- """ Return neighborhood's Dictionary for specified attribute """
|
|
|
|
|
- return self.getAttribute(attribute).getDict()
|
|
|
|
|
-
|
|
|
|
|
- def getList(self, attribute):
|
|
|
|
|
- """ Return neighborhood's List for specified attribute """
|
|
|
|
|
- return self.getAttribute(attribute).getList()
|
|
|
|
|
-
|
|
|
|
|
- # DNA variables
|
|
|
|
|
- def getDNAData(self):
|
|
|
|
|
- return self.DNAData
|
|
|
|
|
-
|
|
|
|
|
- def getDNAToplevel(self):
|
|
|
|
|
- return self.DNAToplevel
|
|
|
|
|
-
|
|
|
|
|
- def getDNAParent(self):
|
|
|
|
|
- return self.DNAParent
|
|
|
|
|
-
|
|
|
|
|
- def getDNATarget(self):
|
|
|
|
|
- return self.DNATarget
|
|
|
|
|
-
|
|
|
|
|
- # Node Path variables
|
|
|
|
|
- def getNPToplevel(self):
|
|
|
|
|
- return self.NPToplevel
|
|
|
|
|
-
|
|
|
|
|
- def getNPParent(self):
|
|
|
|
|
- return self.NPParent
|
|
|
|
|
-
|
|
|
|
|
- # Count of groups added to level
|
|
|
|
|
- def setGroupNum(self, num):
|
|
|
|
|
- self.groupNum = num
|
|
|
|
|
-
|
|
|
|
|
- def getGroupNum(self):
|
|
|
|
|
- return self.groupNum
|
|
|
|
|
-
|
|
|
|
|
- # Angle of last object added to level
|
|
|
|
|
- def setLastAngle(self, angle):
|
|
|
|
|
- self.lastAngle = angle
|
|
|
|
|
-
|
|
|
|
|
- def getLastAngle(self):
|
|
|
|
|
- return self.lastAngle
|
|
|
|
|
-
|
|
|
|
|
- def drawSuitEdge(self, edge, parent):
|
|
|
|
|
- # Draw a line from start to end
|
|
|
|
|
- edgeLine = LineNodePath(parent)
|
|
|
|
|
- edgeLine.lineNode.setName('suitEdge')
|
|
|
|
|
- edgeLine.setColor(VBase4(0.0, 0.0, 0.5, 1))
|
|
|
|
|
- edgeLine.setThickness(1)
|
|
|
|
|
- edgeLine.reset()
|
|
|
|
|
- # We need to draw the arrow relative to the parent, but the
|
|
|
|
|
- # point positions are relative to the NPToplevel. So get the
|
|
|
|
|
- # start and end positions relative to the parent, then draw
|
|
|
|
|
- # the arrow using those points
|
|
|
|
|
- tempNode = self.NPToplevel.attachNewNode('tempNode')
|
|
|
|
|
- mat = self.NPToplevel.getMat(parent)
|
|
|
|
|
- relStartPos = Point3(mat.xformPoint(edge.getStartPoint().getPos()))
|
|
|
|
|
- relEndPos = Point3(mat.xformPoint(edge.getEndPoint().getPos()))
|
|
|
|
|
- # Compute offset: a vector rotated 90 degrees clockwise
|
|
|
|
|
- offset = Vec3(relEndPos - relStartPos)
|
|
|
|
|
- offset.normalize()
|
|
|
|
|
- offset *= 0.1
|
|
|
|
|
- a = offset[0]
|
|
|
|
|
- offset.setX(offset[1])
|
|
|
|
|
- offset.setY(-1 * a)
|
|
|
|
|
- # Just to get it above the street
|
|
|
|
|
- offset.setZ(0.05)
|
|
|
|
|
- # Add offset to start and end to help differentiate lines
|
|
|
|
|
- relStartPos += offset
|
|
|
|
|
- relEndPos += offset
|
|
|
|
|
- # Draw arrow
|
|
|
|
|
- edgeLine.drawArrow(relStartPos,
|
|
|
|
|
- relEndPos,
|
|
|
|
|
- 15, # arrow angle
|
|
|
|
|
- 1) # arrow length
|
|
|
|
|
- edgeLine.create()
|
|
|
|
|
- # Add a clickable sphere
|
|
|
|
|
- marker = self.suitPointMarker.copyTo(edgeLine)
|
|
|
|
|
- marker.setName('suitEdgeMarker')
|
|
|
|
|
- midPos = (relStartPos + relEndPos)/2.0
|
|
|
|
|
- marker.setPos(midPos)
|
|
|
|
|
- # Adjust color of highlighted lines
|
|
|
|
|
- if edge in self.visitedEdges:
|
|
|
|
|
- NodePath.setColor(edgeLine, 1, 0, 0, 1)
|
|
|
|
|
- # Clean up:
|
|
|
|
|
- tempNode.removeNode()
|
|
|
|
|
- return edgeLine
|
|
|
|
|
-
|
|
|
|
|
- def drawSuitPoint(self, suitPoint, pos, type, parent):
|
|
|
|
|
- marker = self.suitPointMarker.copyTo(parent)
|
|
|
|
|
- marker.setName("suitPointMarker")
|
|
|
|
|
- marker.setPos(pos)
|
|
|
|
|
- if (type == DNASuitPoint.STREETPOINT):
|
|
|
|
|
- marker.setColor(0, 0, 0.6)
|
|
|
|
|
- marker.setScale(0.4)
|
|
|
|
|
- elif (type == DNASuitPoint.FRONTDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0, 1)
|
|
|
|
|
- marker.setScale(0.5)
|
|
|
|
|
- elif (type == DNASuitPoint.SIDEDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0.6, 0.2)
|
|
|
|
|
- marker.setScale(0.5)
|
|
|
|
|
- # Highlight if necessary
|
|
|
|
|
- if suitPoint in self.visitedPoints:
|
|
|
|
|
- marker.setColor(1, 0, 0, 1)
|
|
|
|
|
- return marker
|
|
|
|
|
-
|
|
|
|
|
- def placeSuitPoint(self):
|
|
|
|
|
- v = self.getGridSnapIntersectionPoint()
|
|
|
|
|
- # get the absolute pos relative to the top level.
|
|
|
|
|
- # That is what gets stored in the point
|
|
|
|
|
- mat = base.direct.grid.getMat(self.NPToplevel)
|
|
|
|
|
- absPos = Point3(mat.xformPoint(v))
|
|
|
|
|
- print 'Suit point: ' + `absPos`
|
|
|
|
|
- # Store the point in the DNA. If this point is already in there,
|
|
|
|
|
- # it returns the existing point
|
|
|
|
|
- suitPoint = DNASTORE.storeSuitPoint(self.currentSuitPointType, absPos)
|
|
|
|
|
- print "placeSuitPoint: ", suitPoint
|
|
|
|
|
- # In case the point returned is a different type, update our type
|
|
|
|
|
- self.currentSuitPointType = suitPoint.getPointType()
|
|
|
|
|
- if not self.pointDict.has_key(suitPoint):
|
|
|
|
|
- marker = self.drawSuitPoint(suitPoint,
|
|
|
|
|
- absPos, self.currentSuitPointType,
|
|
|
|
|
- self.suitPointToplevel)
|
|
|
|
|
- self.pointDict[suitPoint] = marker
|
|
|
|
|
- self.currentSuitPointIndex = suitPoint.getIndex()
|
|
|
|
|
-
|
|
|
|
|
- if self.startSuitPoint:
|
|
|
|
|
- self.endSuitPoint = suitPoint
|
|
|
|
|
- # Make a new dna edge
|
|
|
|
|
- if DNAClassEqual(self.DNAParent, DNA_VIS_GROUP):
|
|
|
|
|
- zoneId = self.DNAParent.getName()
|
|
|
|
|
-
|
|
|
|
|
- suitEdge = DNASuitEdge(
|
|
|
|
|
- self.startSuitPoint, self.endSuitPoint, zoneId)
|
|
|
|
|
- DNASTORE.storeSuitEdge(suitEdge)
|
|
|
|
|
- # Add edge to the current vis group so it can be written out
|
|
|
|
|
- self.DNAParent.addSuitEdge(suitEdge)
|
|
|
|
|
- # Draw a line to represent the edge
|
|
|
|
|
- edgeLine = self.drawSuitEdge(suitEdge, self.NPParent)
|
|
|
|
|
- # Store the line in a dict so we can hide/show them
|
|
|
|
|
- self.edgeDict[suitEdge] = edgeLine
|
|
|
|
|
- self.np2EdgeDict[edgeLine.id()] = [suitEdge, self.DNAParent]
|
|
|
|
|
- # Store the edge on each point in case we move the point
|
|
|
|
|
- # we can update the edge
|
|
|
|
|
- for point in [self.startSuitPoint, self.endSuitPoint]:
|
|
|
|
|
- if self.point2edgeDict.has_key(point):
|
|
|
|
|
- self.point2edgeDict[point].append(suitEdge)
|
|
|
|
|
- else:
|
|
|
|
|
- self.point2edgeDict[point] = [suitEdge]
|
|
|
|
|
-
|
|
|
|
|
- # If this is a building point, you need edges in both directions
|
|
|
|
|
- # so just make the other edge automatically
|
|
|
|
|
- if ((self.startSuitPoint.getPointType() == DNASuitPoint.FRONTDOORPOINT)
|
|
|
|
|
- or (self.startSuitPoint.getPointType() == DNASuitPoint.SIDEDOORPOINT)):
|
|
|
|
|
-
|
|
|
|
|
- suitEdge = DNASuitEdge(
|
|
|
|
|
- self.endSuitPoint, self.startSuitPoint, zoneId)
|
|
|
|
|
- DNASTORE.storeSuitEdge(suitEdge)
|
|
|
|
|
- # Add edge to the current vis group so it can be written out
|
|
|
|
|
- self.DNAParent.addSuitEdge(suitEdge)
|
|
|
|
|
- # Draw a line to represent the edge
|
|
|
|
|
- edgeLine = self.drawSuitEdge(suitEdge, self.NPParent)
|
|
|
|
|
- # Store the line in a dict so we can hide/show them
|
|
|
|
|
- self.edgeDict[suitEdge] = edgeLine
|
|
|
|
|
- self.np2EdgeDict[edgeLine.id()] = [suitEdge, self.DNAParent]
|
|
|
|
|
- for point in [self.startSuitPoint, self.endSuitPoint]:
|
|
|
|
|
- if self.point2edgeDict.has_key(point):
|
|
|
|
|
- self.point2edgeDict[point].append(suitEdge)
|
|
|
|
|
- else:
|
|
|
|
|
- self.point2edgeDict[point] = [suitEdge]
|
|
|
|
|
-
|
|
|
|
|
- print 'Added dnaSuitEdge to zone: ' + zoneId
|
|
|
|
|
- else:
|
|
|
|
|
- print 'Error: DNAParent is not a dnaVisGroup. Did not add edge'
|
|
|
|
|
- # Reset
|
|
|
|
|
- self.startSuitPoint = None
|
|
|
|
|
- self.endSuitPoint = None
|
|
|
|
|
-
|
|
|
|
|
- else:
|
|
|
|
|
- # First point, store it
|
|
|
|
|
- self.startSuitPoint = suitPoint
|
|
|
|
|
-
|
|
|
|
|
- def highlightConnected(self, nodePath = None, fReversePath = 0):
|
|
|
|
|
- if nodePath == None:
|
|
|
|
|
- nodePath = base.direct.selected.last
|
|
|
|
|
- if nodePath:
|
|
|
|
|
- suitPoint = self.findPointOrCell(nodePath)[0]
|
|
|
|
|
- if suitPoint:
|
|
|
|
|
- self.clearPathHighlights()
|
|
|
|
|
- self.highlightConnectedRec(suitPoint, fReversePath)
|
|
|
|
|
-
|
|
|
|
|
- def highlightConnectedRec(self, suitPoint, fReversePath):
|
|
|
|
|
- nodePath = self.pointDict.get(suitPoint, None)
|
|
|
|
|
- if nodePath:
|
|
|
|
|
- # highlight marker
|
|
|
|
|
- nodePath.setColor(1, 0, 0, 1)
|
|
|
|
|
- # Add point to visited points
|
|
|
|
|
- self.visitedPoints.append(suitPoint)
|
|
|
|
|
- # highlight connected edges
|
|
|
|
|
- for edge in self.point2edgeDict[suitPoint]:
|
|
|
|
|
- if ((fReversePath or (suitPoint == edge.getStartPoint())) and
|
|
|
|
|
- (edge not in self.visitedEdges)):
|
|
|
|
|
- edgeLine = self.edgeDict[edge]
|
|
|
|
|
- # Call node path not LineNodePath setColor
|
|
|
|
|
- NodePath.setColor(edgeLine, 1, 0, 0, 1)
|
|
|
|
|
- # Add edge to visited edges
|
|
|
|
|
- self.visitedEdges.append(edge)
|
|
|
|
|
- # Color components connected to the edge
|
|
|
|
|
- if fReversePath:
|
|
|
|
|
- startPoint = edge.getStartPoint()
|
|
|
|
|
- if startPoint not in self.visitedPoints:
|
|
|
|
|
- self.highlightConnectedRec(startPoint,
|
|
|
|
|
- fReversePath)
|
|
|
|
|
- endPoint = edge.getEndPoint()
|
|
|
|
|
- type = endPoint.getPointType()
|
|
|
|
|
- if ((endPoint not in self.visitedPoints) and
|
|
|
|
|
- (fReversePath or (type == DNASuitPoint.STREETPOINT))):
|
|
|
|
|
- self.highlightConnectedRec(endPoint,
|
|
|
|
|
- fReversePath)
|
|
|
|
|
-
|
|
|
|
|
- def clearPathHighlights(self):
|
|
|
|
|
- for point in self.pointDict.keys():
|
|
|
|
|
- type = point.getPointType()
|
|
|
|
|
- marker = self.pointDict[point]
|
|
|
|
|
- if (type == DNASuitPoint.STREETPOINT):
|
|
|
|
|
- marker.setColor(0, 0, 0.6)
|
|
|
|
|
- elif (type == DNASuitPoint.FRONTDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0, 1)
|
|
|
|
|
- elif (type == DNASuitPoint.SIDEDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0.6, 0.2)
|
|
|
|
|
- for edge in self.edgeDict.values():
|
|
|
|
|
- edge.clearColor()
|
|
|
|
|
- self.visitedPoints = []
|
|
|
|
|
- self.visitedEdges = []
|
|
|
|
|
-
|
|
|
|
|
- def drawBattleCell(self, cell, parent):
|
|
|
|
|
- marker = self.battleCellMarker.copyTo(parent)
|
|
|
|
|
- # Greenish
|
|
|
|
|
- marker.setColor(0.25, 0.75, 0.25, 0.5)
|
|
|
|
|
- marker.setTransparency(1)
|
|
|
|
|
- marker.setPos(cell.getPos())
|
|
|
|
|
- # scale to radius which is width/2
|
|
|
|
|
- marker.setScale(cell.getWidth()/2.0,
|
|
|
|
|
- cell.getHeight()/2.0,
|
|
|
|
|
- 1)
|
|
|
|
|
- return marker
|
|
|
|
|
-
|
|
|
|
|
- def placeBattleCell(self):
|
|
|
|
|
- # Store the battle cell in the current vis group
|
|
|
|
|
- if not DNAClassEqual(self.DNAParent, DNA_VIS_GROUP):
|
|
|
|
|
- print 'Error: DNAParent is not a dnaVisGroup. Did not add battle cell'
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- v = self.getGridSnapIntersectionPoint()
|
|
|
|
|
- mat = base.direct.grid.getMat(self.NPParent)
|
|
|
|
|
- absPos = Point3(mat.xformPoint(v))
|
|
|
|
|
- if (self.currentBattleCellType == '20w 20l'):
|
|
|
|
|
- cell = DNABattleCell(20, 20, absPos)
|
|
|
|
|
- elif (self.currentBattleCellType == '20w 30l'):
|
|
|
|
|
- cell = DNABattleCell(20, 30, absPos)
|
|
|
|
|
- elif (self.currentBattleCellType == '30w 20l'):
|
|
|
|
|
- cell = DNABattleCell(30, 20, absPos)
|
|
|
|
|
- elif (self.currentBattleCellType == '30w 30l'):
|
|
|
|
|
- cell = DNABattleCell(30, 30, absPos)
|
|
|
|
|
- # Store the battle cell in the storage
|
|
|
|
|
- DNASTORE.storeBattleCell(cell)
|
|
|
|
|
- # Draw the battle cell
|
|
|
|
|
- marker = self.drawBattleCell(cell, self.NPParent)
|
|
|
|
|
- # Keep a handy dict of the visible markers
|
|
|
|
|
- self.cellDict[cell] = marker
|
|
|
|
|
- # Store the battle cell in the current vis group
|
|
|
|
|
- self.DNAParent.addBattleCell(cell)
|
|
|
|
|
-
|
|
|
|
|
- def createSuitPaths(self):
|
|
|
|
|
- # Points
|
|
|
|
|
- numPoints = DNASTORE.getNumSuitPoints()
|
|
|
|
|
- for i in range(numPoints):
|
|
|
|
|
- point = DNASTORE.getSuitPointAtIndex(i)
|
|
|
|
|
- marker = self.drawSuitPoint(point,
|
|
|
|
|
- point.getPos(), point.getPointType(),
|
|
|
|
|
- self.suitPointToplevel)
|
|
|
|
|
- self.pointDict[point] = marker
|
|
|
|
|
-
|
|
|
|
|
- # Edges
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- for visGroup in visGroups:
|
|
|
|
|
- np = visGroup[0]
|
|
|
|
|
- dnaVisGroup = visGroup[1]
|
|
|
|
|
- numSuitEdges = dnaVisGroup.getNumSuitEdges()
|
|
|
|
|
- for i in range(numSuitEdges):
|
|
|
|
|
- edge = dnaVisGroup.getSuitEdge(i)
|
|
|
|
|
- edgeLine = self.drawSuitEdge(edge, np)
|
|
|
|
|
- self.edgeDict[edge] = edgeLine
|
|
|
|
|
- self.np2EdgeDict[edgeLine.id()] = [edge, dnaVisGroup]
|
|
|
|
|
- # Store the edge on each point in case we move the point
|
|
|
|
|
- # we can update the edge
|
|
|
|
|
- for point in [edge.getStartPoint(), edge.getEndPoint()]:
|
|
|
|
|
- if self.point2edgeDict.has_key(point):
|
|
|
|
|
- self.point2edgeDict[point].append(edge)
|
|
|
|
|
- else:
|
|
|
|
|
- self.point2edgeDict[point] = [edge]
|
|
|
|
|
-
|
|
|
|
|
- def getSuitPointFromNodePath(self, nodePath):
|
|
|
|
|
- """
|
|
|
|
|
- Given a node path, attempt to find the point, nodePath pair
|
|
|
|
|
- in the pointDict. If it is there, return the point. If we
|
|
|
|
|
- cannot find it, return None.
|
|
|
|
|
- TODO: a reverse lookup pointDict would speed this up quite a bit
|
|
|
|
|
- """
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- if marker.eq(nodePath):
|
|
|
|
|
- return point
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
- def resetPathMarkers(self):
|
|
|
|
|
- for edge, edgeLine in self.edgeDict.items():
|
|
|
|
|
- if not edgeLine.isEmpty():
|
|
|
|
|
- edgeLine.reset()
|
|
|
|
|
- edgeLine.removeNode()
|
|
|
|
|
- self.edgeDict = {}
|
|
|
|
|
- self.np2EdgeDict = {}
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- if not marker.isEmpty():
|
|
|
|
|
- marker.removeNode()
|
|
|
|
|
- self.pointDict = {}
|
|
|
|
|
-
|
|
|
|
|
- def hideSuitPaths(self):
|
|
|
|
|
- for edge, edgeLine in self.edgeDict.items():
|
|
|
|
|
- edgeLine.hide()
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- marker.hide()
|
|
|
|
|
-
|
|
|
|
|
- def showSuitPaths(self):
|
|
|
|
|
- for edge, edgeLine in self.edgeDict.items():
|
|
|
|
|
- edgeLine.show()
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- marker.show()
|
|
|
|
|
-
|
|
|
|
|
- def createBattleCells(self):
|
|
|
|
|
- # Edges
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- for visGroup in visGroups:
|
|
|
|
|
- np = visGroup[0]
|
|
|
|
|
- dnaVisGroup = visGroup[1]
|
|
|
|
|
- numCells = dnaVisGroup.getNumBattleCells()
|
|
|
|
|
- for i in range(numCells):
|
|
|
|
|
- cell = dnaVisGroup.getBattleCell(i)
|
|
|
|
|
- marker = self.drawBattleCell(cell, np)
|
|
|
|
|
- self.cellDict[cell] = marker
|
|
|
|
|
-
|
|
|
|
|
- def resetBattleCellMarkers(self):
|
|
|
|
|
- for cell, marker in self.cellDict.items():
|
|
|
|
|
- if not marker.isEmpty():
|
|
|
|
|
- marker.remove()
|
|
|
|
|
- self.cellDict = {}
|
|
|
|
|
-
|
|
|
|
|
- def hideBattleCells(self):
|
|
|
|
|
- for cell, marker in self.cellDict.items():
|
|
|
|
|
- marker.hide()
|
|
|
|
|
-
|
|
|
|
|
- def showBattleCells(self):
|
|
|
|
|
- for cell, marker in self.cellDict.items():
|
|
|
|
|
- marker.show()
|
|
|
|
|
-
|
|
|
|
|
- def getBattleCellFromNodePath(self, nodePath):
|
|
|
|
|
- """
|
|
|
|
|
- Given a node path, attempt to find the battle cell, nodePath pair
|
|
|
|
|
- in the cellDict. If it is there, return the cell. If we
|
|
|
|
|
- cannot find it, return None.
|
|
|
|
|
- TODO: a reverse lookup cellDict would speed this up quite a bit
|
|
|
|
|
- """
|
|
|
|
|
- for cell, marker in self.cellDict.items():
|
|
|
|
|
- if marker.eq(nodePath):
|
|
|
|
|
- return cell
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
- def toggleZoneColors(self):
|
|
|
|
|
- if self.panel.zoneColor.get():
|
|
|
|
|
- self.colorZones()
|
|
|
|
|
- else:
|
|
|
|
|
- self.clearZoneColors()
|
|
|
|
|
-
|
|
|
|
|
- def colorZones(self):
|
|
|
|
|
- # Give each zone a random color to see them better
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- for visGroup in visGroups:
|
|
|
|
|
- np = visGroup[0]
|
|
|
|
|
- np.setColor(0.5 + random()/2.0,
|
|
|
|
|
- 0.5 + random()/2.0,
|
|
|
|
|
- 0.5 + random()/2.0)
|
|
|
|
|
-
|
|
|
|
|
- def clearZoneColors(self):
|
|
|
|
|
- # Clear random colors
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- for visGroup in visGroups:
|
|
|
|
|
- np = visGroup[0]
|
|
|
|
|
- np.clearColor()
|
|
|
|
|
-
|
|
|
|
|
- def labelZones(self):
|
|
|
|
|
- # Label each zone
|
|
|
|
|
- # First clear out old labels if any
|
|
|
|
|
- self.clearZoneLabels()
|
|
|
|
|
- visGroups = self.getDNAVisGroups(self.NPToplevel)
|
|
|
|
|
- from direct.gui import DirectGui
|
|
|
|
|
- for np, dna in visGroups:
|
|
|
|
|
- name = dna.getName()
|
|
|
|
|
- label = DirectGui.DirectLabel(text = name,
|
|
|
|
|
- parent = np.getParent(),
|
|
|
|
|
- relief = None, scale = 3)
|
|
|
|
|
- label.setBillboardPointEye(0)
|
|
|
|
|
- center = np.getBounds().getCenter()
|
|
|
|
|
- label.setPos(center[0], center[1], .1)
|
|
|
|
|
- self.zoneLabels.append(label)
|
|
|
|
|
-
|
|
|
|
|
- def clearZoneLabels(self):
|
|
|
|
|
- for label in self.zoneLabels:
|
|
|
|
|
- label.removeNode()
|
|
|
|
|
- self.zoneLabels = []
|
|
|
|
|
-
|
|
|
|
|
- def getBlockFromName(self, name):
|
|
|
|
|
- block=name[2:name.find(':')]
|
|
|
|
|
- return block
|
|
|
|
|
-
|
|
|
|
|
- def addToLandmarkBlock(self):
|
|
|
|
|
- dnaRoot=self.selectedDNARoot
|
|
|
|
|
- if dnaRoot and self.lastLandmarkBuildingDNA:
|
|
|
|
|
- if DNAClassEqual(dnaRoot, DNA_FLAT_BUILDING):
|
|
|
|
|
- n=dnaRoot.getName()
|
|
|
|
|
- n=n[n.find(':'):]
|
|
|
|
|
- block=self.lastLandmarkBuildingDNA.getName()
|
|
|
|
|
- block=block[2:block.find(':')]
|
|
|
|
|
- dnaRoot.setName('tb'+block+n)
|
|
|
|
|
- self.replaceSelected()
|
|
|
|
|
- # If we're highlighting the landmark blocks:
|
|
|
|
|
- if self.showLandmarkBlockToggleGroup:
|
|
|
|
|
- # then highlight this one:
|
|
|
|
|
- np=self.selectedNPRoot
|
|
|
|
|
- self.showLandmarkBlockToggleGroup.append(np)
|
|
|
|
|
- np.setColor(1, 0, 0, 1)
|
|
|
|
|
- elif self.selectedSuitPoint and self.lastLandmarkBuildingDNA:
|
|
|
|
|
- block=self.lastLandmarkBuildingDNA.getName()
|
|
|
|
|
- block=block[2:block.find(':')]
|
|
|
|
|
- print ("associate point with building: " + str(block))
|
|
|
|
|
- self.selectedSuitPoint.setLandmarkBuildingIndex(int(block))
|
|
|
|
|
- marker = self.pointDict[self.selectedSuitPoint]
|
|
|
|
|
- marker.setColor(1, 0, 0, 1)
|
|
|
|
|
- marker.setScale(1.0)
|
|
|
|
|
-
|
|
|
|
|
- def findHighestLandmarkBlock(self, dnaRoot, npRoot):
|
|
|
|
|
- npc=npRoot.findAllMatches("**/*:toon_landmark_*")
|
|
|
|
|
- highest=0
|
|
|
|
|
- for i in range(npc.getNumPaths()):
|
|
|
|
|
- path=npc.getPath(i)
|
|
|
|
|
- block=path.getName()
|
|
|
|
|
- block=int(block[2:block.find(':')])
|
|
|
|
|
- if (block > highest):
|
|
|
|
|
- highest=block
|
|
|
|
|
- # Make a list of flat building names, outside of the
|
|
|
|
|
- # recursive function:
|
|
|
|
|
- self.flatNames=['random'] + BUILDING_TYPES
|
|
|
|
|
- self.flatNames=map(lambda n: n+'_DNARoot', self.flatNames)
|
|
|
|
|
- # Search/recurse the dna:
|
|
|
|
|
- newHighest=self.convertToLandmarkBlocks(highest, dnaRoot)
|
|
|
|
|
- # Get rid of the list of flat building names:
|
|
|
|
|
- del self.flatNames
|
|
|
|
|
-
|
|
|
|
|
- needToTraverse = (highest!=newHighest)
|
|
|
|
|
- return (newHighest, needToTraverse)
|
|
|
|
|
-
|
|
|
|
|
- def convertToLandmarkBlocks(self, block, dnaRoot):
|
|
|
|
|
- """
|
|
|
|
|
- Find all the buildings without landmark blocks and
|
|
|
|
|
- assign them one.
|
|
|
|
|
- """
|
|
|
|
|
- for i in range(dnaRoot.getNumChildren()):
|
|
|
|
|
- child = dnaRoot.at(i)
|
|
|
|
|
- if DNAClassEqual(child, DNA_LANDMARK_BUILDING):
|
|
|
|
|
- # Landmark buildings:
|
|
|
|
|
- name=child.getName()
|
|
|
|
|
- if name.find('toon_landmark_')==0:
|
|
|
|
|
- block=block+1
|
|
|
|
|
- child.setName('tb'+str(block)+':'+name)
|
|
|
|
|
- elif DNAClassEqual(child, DNA_FLAT_BUILDING):
|
|
|
|
|
- # Flat buildings:
|
|
|
|
|
- name=child.getName()
|
|
|
|
|
- if (name in self.flatNames):
|
|
|
|
|
- child.setName('tb0:'+name)
|
|
|
|
|
- else:
|
|
|
|
|
- block = self.convertToLandmarkBlocks(block, child)
|
|
|
|
|
- return block
|
|
|
|
|
-
|
|
|
|
|
- def revertLandmarkBlock(self, block):
|
|
|
|
|
- """
|
|
|
|
|
- un-block flat buildings (set them to block zero).
|
|
|
|
|
- """
|
|
|
|
|
- npc=self.NPToplevel.findAllMatches("**/tb"+block+":*_DNARoot")
|
|
|
|
|
- for i in range(npc.getNumPaths()):
|
|
|
|
|
- nodePath=npc.getPath(i)
|
|
|
|
|
- name=nodePath.getName()
|
|
|
|
|
- if name[name.find(':'):][:15] != ':toon_landmark_':
|
|
|
|
|
- name='tb0'+name[name.find(':'):]
|
|
|
|
|
- dna=self.findDNANode(nodePath)
|
|
|
|
|
- dna.setName(name)
|
|
|
|
|
- nodePath=self.replace(nodePath, dna)
|
|
|
|
|
- # If we're highlighting the landmark blocks:
|
|
|
|
|
- if self.showLandmarkBlockToggleGroup:
|
|
|
|
|
- # then highlight this one:
|
|
|
|
|
- self.showLandmarkBlockToggleGroup.append(nodePath)
|
|
|
|
|
- nodePath.setColor(0, 1, 0, 1)
|
|
|
|
|
-
|
|
|
|
|
- def landmarkBlockRemove(self, dna, nodePath):
|
|
|
|
|
- if dna:
|
|
|
|
|
- name=dna.getName()
|
|
|
|
|
- # Get the underscore index within the name:
|
|
|
|
|
- usIndex=name.find(':')
|
|
|
|
|
- if name[usIndex:][:15] == ':toon_landmark_':
|
|
|
|
|
- block=name[2:usIndex]
|
|
|
|
|
- self.lastLandmarkBuildingDNA=None
|
|
|
|
|
- self.revertLandmarkBlock(block)
|
|
|
|
|
-
|
|
|
|
|
- def toggleShowLandmarkBlock(self):
|
|
|
|
|
- dna=self.lastLandmarkBuildingDNA
|
|
|
|
|
- if dna:
|
|
|
|
|
- if not self.showLandmarkBlockToggleGroup:
|
|
|
|
|
- group=[]
|
|
|
|
|
- block=dna.getName()
|
|
|
|
|
- block=block[2:block.find(':')]
|
|
|
|
|
-
|
|
|
|
|
- # Get current landmark buildings:
|
|
|
|
|
- npc=self.NPToplevel.findAllMatches("**/tb"+block+":*_DNARoot")
|
|
|
|
|
- for i in range(npc.getNumPaths()):
|
|
|
|
|
- nodePath=npc.getPath(i)
|
|
|
|
|
- group.append(nodePath)
|
|
|
|
|
- nodePath.setColor(1, 0, 0, 1)
|
|
|
|
|
-
|
|
|
|
|
- # Get block zero buildings (i.e. non-blocked):
|
|
|
|
|
- npc=self.NPToplevel.findAllMatches("**/tb0:*_DNARoot")
|
|
|
|
|
- for i in range(npc.getNumPaths()):
|
|
|
|
|
- nodePath=npc.getPath(i)
|
|
|
|
|
- group.append(nodePath)
|
|
|
|
|
- nodePath.setColor(0, 1, 0, 1)
|
|
|
|
|
-
|
|
|
|
|
- # Get the suit point for this lb
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- if ((point.getPointType() == DNASuitPoint.FRONTDOORPOINT)
|
|
|
|
|
- or (point.getPointType() == DNASuitPoint.SIDEDOORPOINT)):
|
|
|
|
|
- lbIndex = point.getLandmarkBuildingIndex()
|
|
|
|
|
- if (lbIndex == int(block)):
|
|
|
|
|
- marker.setColor(1, 0, 0, 1)
|
|
|
|
|
- marker.setScale(1.0)
|
|
|
|
|
- # There should only be one, so break now
|
|
|
|
|
- elif (lbIndex == -1):
|
|
|
|
|
- # This point belongs to no block
|
|
|
|
|
- marker.setColor(0, 1, 0, 1)
|
|
|
|
|
-
|
|
|
|
|
- self.showLandmarkBlockToggleGroup=group
|
|
|
|
|
- else:
|
|
|
|
|
- for i in self.showLandmarkBlockToggleGroup:
|
|
|
|
|
- i.clearColor()
|
|
|
|
|
- for point, marker in self.pointDict.items():
|
|
|
|
|
- if (point.getPointType() == DNASuitPoint.FRONTDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0, 1, 1)
|
|
|
|
|
- marker.setScale(0.5)
|
|
|
|
|
- elif (point.getPointType() == DNASuitPoint.SIDEDOORPOINT):
|
|
|
|
|
- marker.setColor(0, 0.6, 0.2, 1)
|
|
|
|
|
- marker.setScale(0.5)
|
|
|
|
|
- self.showLandmarkBlockToggleGroup=None
|
|
|
|
|
-
|
|
|
|
|
- def pdbBreak(self):
|
|
|
|
|
- pdb.set_trace()
|
|
|
|
|
-
|
|
|
|
|
- def reparentStreetBuildings(self, nodePath):
|
|
|
|
|
- dnaNode = self.findDNANode(nodePath)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- if (DNAClassEqual(dnaNode, DNA_FLAT_BUILDING) or
|
|
|
|
|
- DNAClassEqual(dnaNode, DNA_LANDMARK_BUILDING)):
|
|
|
|
|
- base.direct.reparent(nodePath, fWrt = 1)
|
|
|
|
|
- children = nodePath.getChildren()
|
|
|
|
|
- for child in children:
|
|
|
|
|
- self.reparentStreetBuildings(child)
|
|
|
|
|
-
|
|
|
|
|
- def consolidateStreetBuildings(self):
|
|
|
|
|
- # First put everything under the ATR group so the leftover
|
|
|
|
|
- # can be easily deleted
|
|
|
|
|
- originalChildren = self.NPToplevel.getChildren()
|
|
|
|
|
- self.addGroup(self.NPToplevel)
|
|
|
|
|
- atrGroup = self.NPParent
|
|
|
|
|
- atrGroup.setName('ATR')
|
|
|
|
|
- self.setName(atrGroup, 'ATR')
|
|
|
|
|
- base.direct.setActiveParent(atrGroup)
|
|
|
|
|
- for child in originalChildren:
|
|
|
|
|
- base.direct.reparent(child)
|
|
|
|
|
- # Now create a new group with just the buildings
|
|
|
|
|
- self.addGroup(self.NPToplevel)
|
|
|
|
|
- newGroup = self.NPParent
|
|
|
|
|
- newGroup.setName('LongStreet')
|
|
|
|
|
- self.setName(newGroup, 'LongStreet')
|
|
|
|
|
- base.direct.setActiveParent(newGroup)
|
|
|
|
|
- self.reparentStreetBuildings(self.NPToplevel)
|
|
|
|
|
- return newGroup
|
|
|
|
|
-
|
|
|
|
|
- def makeNewBuildingGroup(self, sequenceNum, side, curveName):
|
|
|
|
|
- print "-------------------------- new building group %s curveName=%s------------------------" % (sequenceNum, curveName)
|
|
|
|
|
- # Now create a new group with just the buildings
|
|
|
|
|
- self.addGroup(self.NPToplevel)
|
|
|
|
|
- newGroup = self.NPParent
|
|
|
|
|
- groupName = ''
|
|
|
|
|
- #if curveName == "urban_curveside_inner_1_1":
|
|
|
|
|
- # import pdb; pdb.set_trace()
|
|
|
|
|
-
|
|
|
|
|
- if 'curveside' in curveName:
|
|
|
|
|
- #we want to preserve which group the side street is closest to
|
|
|
|
|
- print "special casing %s" % curveName
|
|
|
|
|
- parts = curveName.split('_')
|
|
|
|
|
- groupName = 'Buildings_' + side + "-" + parts[3] + "_" + parts[4]
|
|
|
|
|
- print "groupname = %s" % groupName
|
|
|
|
|
- else:
|
|
|
|
|
- groupName = 'Buildings_' + side + "-" + str(sequenceNum)
|
|
|
|
|
- newGroup.setName(groupName)
|
|
|
|
|
- self.setName(newGroup, groupName)
|
|
|
|
|
- base.direct.setActiveParent(newGroup)
|
|
|
|
|
-
|
|
|
|
|
- if 'barricade_curve' in curveName:
|
|
|
|
|
- parts = curveName.split('_')
|
|
|
|
|
- origBarricadeNum = parts[3]
|
|
|
|
|
- self.updateBarricadeDict(side, int(origBarricadeNum), sequenceNum)
|
|
|
|
|
-
|
|
|
|
|
- def adjustPropChildren(self, nodePath, maxPropOffset = -4):
|
|
|
|
|
- for np in nodePath.getChildren():
|
|
|
|
|
- dnaNode = self.findDNANode(np)
|
|
|
|
|
- if dnaNode:
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_PROP):
|
|
|
|
|
- if np.getY() < maxPropOffset:
|
|
|
|
|
- np.setY(maxPropOffset)
|
|
|
|
|
- self.updateSelectedPose([np])
|
|
|
|
|
-
|
|
|
|
|
- def getBuildingWidth(self, bldg):
|
|
|
|
|
- dnaNode = self.findDNANode(bldg)
|
|
|
|
|
- bldgWidth = 0
|
|
|
|
|
- if DNAClassEqual(dnaNode, DNA_FLAT_BUILDING):
|
|
|
|
|
- bldgWidth = dnaNode.getWidth()
|
|
|
|
|
- elif DNAClassEqual(dnaNode, DNA_LANDMARK_BUILDING):
|
|
|
|
|
- objectCode = dnaNode.getCode()
|
|
|
|
|
- if objectCode[-2:-1] == 'A':
|
|
|
|
|
- bldgWidth = 25.0
|
|
|
|
|
- elif objectCode[-2:-1] == 'B':
|
|
|
|
|
- bldgWidth = 15.0
|
|
|
|
|
- elif objectCode[-2:-1] == 'C':
|
|
|
|
|
- bldgWidth = 20.0
|
|
|
|
|
- return bldgWidth
|
|
|
|
|
-
|
|
|
|
|
- def calcLongStreetLength(self, bldgs):
|
|
|
|
|
- streetLength = 0
|
|
|
|
|
- for bldg in bldgs:
|
|
|
|
|
- streetLength += self.getBuildingWidth(bldg)
|
|
|
|
|
- return streetLength
|
|
|
|
|
-
|
|
|
|
|
- def addStreetUnits(self, streetLength):
|
|
|
|
|
- base.direct.grid.setPosHpr(0, -40, 0, 0, 0, 0)
|
|
|
|
|
- currLength = 0
|
|
|
|
|
- while (currLength < streetLength):
|
|
|
|
|
- self.addStreet('street_80x40')
|
|
|
|
|
- currLength += 80
|
|
|
|
|
-
|
|
|
|
|
- def makeLongStreet(self):
|
|
|
|
|
- bldgGroup = self.consolidateStreetBuildings()
|
|
|
|
|
- bldgs = bldgGroup.getChildren()
|
|
|
|
|
- numBldgs = len(bldgs)
|
|
|
|
|
- streetLength = self.calcLongStreetLength(bldgs)/2.0
|
|
|
|
|
- ref = None
|
|
|
|
|
- base.direct.grid.fXyzSnap = 0
|
|
|
|
|
- currLength = 0
|
|
|
|
|
- for i in range(numBldgs):
|
|
|
|
|
- bldg = bldgs[i]
|
|
|
|
|
- if ref == None:
|
|
|
|
|
- base.direct.grid.iPosHpr(bldgGroup)
|
|
|
|
|
- else:
|
|
|
|
|
- ref.select()
|
|
|
|
|
- self.autoPositionGrid(fLerp = 0)
|
|
|
|
|
- if base.direct.grid.getX() >= streetLength:
|
|
|
|
|
- base.direct.grid.setPosHpr(base.direct.grid, 0, -40, 0, 180, 0, 0)
|
|
|
|
|
- bldg.iPosHpr(base.direct.grid)
|
|
|
|
|
- self.updateSelectedPose([bldg])
|
|
|
|
|
- self.adjustPropChildren(bldg)
|
|
|
|
|
- ref = bldg
|
|
|
|
|
- self.addStreetUnits(streetLength)
|
|
|
|
|
-
|
|
|
|
|
- def loadStreetCurve(self):
|
|
|
|
|
- path = '.'
|
|
|
|
|
- streetCurveFilename = askopenfilename(
|
|
|
|
|
- defaultextension = '.egg',
|
|
|
|
|
- filetypes = (('Egg files', '*.egg'),
|
|
|
|
|
- ('Bam files', '*.bam'),
|
|
|
|
|
- ('Maya files', '*.mb'),
|
|
|
|
|
- ('All files', '*')),
|
|
|
|
|
- initialdir = path,
|
|
|
|
|
- title = 'Load Curve File',
|
|
|
|
|
- parent = self.panel.component('hull'))
|
|
|
|
|
- if streetCurveFilename:
|
|
|
|
|
- modelFile = loader.loadModel(Filename.fromOsSpecific(streetCurveFilename))
|
|
|
|
|
- #curves = modelFile.findAllMatches('**/+ClassicNurbsCurve')
|
|
|
|
|
- curves = {'inner':[], 'outer':[],'innersidest':[], 'outersidest':[]}
|
|
|
|
|
- curvesInner = modelFile.findAllMatches('**/*curve_inner*')
|
|
|
|
|
- print("-------------- curvesInner-----------------")
|
|
|
|
|
- print curvesInner
|
|
|
|
|
- curvesOuter = modelFile.findAllMatches('**/*curve_outer*')
|
|
|
|
|
- print("---------------- curvesOuter---------------")
|
|
|
|
|
- print curvesOuter
|
|
|
|
|
- curveInnerSideSts = modelFile.findAllMatches('**/*curveside_inner*')
|
|
|
|
|
- print("--------- curveInnerSideSts----------")
|
|
|
|
|
- print curveInnerSideSts
|
|
|
|
|
-
|
|
|
|
|
- curveOuterSideSts = modelFile.findAllMatches('**/*curveside_outer*')
|
|
|
|
|
- print("----------- curveOuterSideSits ----------")
|
|
|
|
|
- print curveOuterSideSts
|
|
|
|
|
-
|
|
|
|
|
- # return an ordered list
|
|
|
|
|
- for i in range(len(curvesInner) +1): #RAU don't forget, these curves are 1 based
|
|
|
|
|
- curve = modelFile.find('**/*curve_inner_'+str(i))
|
|
|
|
|
- if not curve.isEmpty():
|
|
|
|
|
- # Mark whether it is a section of buildings or trees
|
|
|
|
|
- curveType = curve.getName().split("_")[0]
|
|
|
|
|
- curves['inner'].append([curve.node(), curveType])
|
|
|
|
|
-
|
|
|
|
|
- for i in range(len(curvesOuter) +1):
|
|
|
|
|
- curve = modelFile.find('**/*curve_outer_'+str(i))
|
|
|
|
|
- if not curve.isEmpty():
|
|
|
|
|
- # Mark whether it is a section of buildings or trees
|
|
|
|
|
- curveType = curve.getName().split("_")[0]
|
|
|
|
|
- curves['outer'].append([curve.node(), curveType])
|
|
|
|
|
-
|
|
|
|
|
- maxNum = len(curvesInner)
|
|
|
|
|
- if len(curvesOuter) > maxNum:
|
|
|
|
|
- maxNum = len(curvesOuter)
|
|
|
|
|
-
|
|
|
|
|
- maxNum += 2; #track ends in a barricade, and add 1 since 1 based
|
|
|
|
|
- #RAU also do special processing for the side streets
|
|
|
|
|
- # side streets are numbered differently and could be non consecutive
|
|
|
|
|
- # curveside_inner_28_1, curveside_outer_28_1, curveside_inner_28_2,
|
|
|
|
|
- # curveside_outer_28_2 (two side streets closest to main building track 28)
|
|
|
|
|
- for i in range(maxNum):
|
|
|
|
|
- for barricade in ['innerbarricade','outerbarricade']:
|
|
|
|
|
- curve = modelFile.find('**/*curveside_inner_'+ barricade + '_' + str(i))
|
|
|
|
|
- if not curve.isEmpty():
|
|
|
|
|
- # Mark whether it is a section of buildings or trees
|
|
|
|
|
- curveType = curve.getName().split("_")[0]
|
|
|
|
|
- curves['innersidest'].append([curve.node(), curveType])
|
|
|
|
|
- print "adding innersidest %s" % curve.getName()
|
|
|
|
|
-
|
|
|
|
|
- for i in range(maxNum):
|
|
|
|
|
- for barricade in ['innerbarricade','outerbarricade']:
|
|
|
|
|
- curve = modelFile.find('**/*curveside_outer_'+ barricade + '_' + str(i))
|
|
|
|
|
- if not curve.isEmpty():
|
|
|
|
|
- # Mark whether it is a section of buildings or trees
|
|
|
|
|
- curveType = curve.getName().split("_")[0]
|
|
|
|
|
- curves['outersidest'].append([curve.node(), curveType])
|
|
|
|
|
- print "adding outersidest %s" % curve.getName()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- print "loaded curves: %s" % curves
|
|
|
|
|
- return curves
|
|
|
|
|
- else:
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
- def duplicateFlatBuilding(self, oldDNANode):
|
|
|
|
|
- # Yes, make a new copy of the dnaNode
|
|
|
|
|
- print "a"
|
|
|
|
|
- dnaNode = oldDNANode.__class__(oldDNANode)
|
|
|
|
|
- print "b"
|
|
|
|
|
- dnaNode.setWidth(oldDNANode.getWidth())
|
|
|
|
|
- # Add the DNA to the active parent
|
|
|
|
|
- print "c"
|
|
|
|
|
- self.DNAParent.add(dnaNode)
|
|
|
|
|
- # And create the geometry
|
|
|
|
|
- print "d %s" % (oldDNANode)
|
|
|
|
|
- newNodePath = dnaNode.traverse(self.NPParent, DNASTORE, 1)
|
|
|
|
|
- print "e"
|
|
|
|
|
- return newNodePath
|
|
|
|
|
-
|
|
|
|
|
- def getBldg(self, bldgIndex, bldgs, forceDuplicate = False):
|
|
|
|
|
- numBldgs = len(bldgs)
|
|
|
|
|
- if bldgIndex < numBldgs and not forceDuplicate:
|
|
|
|
|
- # Use original
|
|
|
|
|
- print "using original bldg"
|
|
|
|
|
- bldg = bldgs[bldgIndex]
|
|
|
|
|
- bldgIndex += 1
|
|
|
|
|
- else:
|
|
|
|
|
- # Make a copy
|
|
|
|
|
- oldBldg = bldgs[bldgIndex % numBldgs]
|
|
|
|
|
- bldgIndex += 1
|
|
|
|
|
-
|
|
|
|
|
- oldBldg.select()
|
|
|
|
|
- oldDNANode = self.findDNANode(oldBldg)
|
|
|
|
|
- nodeClass = DNAGetClassType(oldDNANode)
|
|
|
|
|
- if nodeClass.eq(DNA_LANDMARK_BUILDING):
|
|
|
|
|
- print "making landmark copy"
|
|
|
|
|
- # Remove white and dark grey doors from color list
|
|
|
|
|
- colorList = self.getAttribute('door_color').getList()
|
|
|
|
|
- colorList = colorList[1:3] + colorList[4:len(colorList)]
|
|
|
|
|
- # Set a random door color
|
|
|
|
|
- doorColor = random.choice(colorList)
|
|
|
|
|
- self.setCurrent('door_color', doorColor)
|
|
|
|
|
- self.addLandmark(oldDNANode.getCode(), oldDNANode.getBuildingType())
|
|
|
|
|
- bldg = self.lastNodePath
|
|
|
|
|
- else:
|
|
|
|
|
- print "making flatbuilding copy"
|
|
|
|
|
- bldg = self.duplicateFlatBuilding(oldDNANode)
|
|
|
|
|
- return bldg, bldgIndex
|
|
|
|
|
-
|
|
|
|
|
- def updateBarricadeDict(self, side, barricadeOrigNum, curBldgGroupIndex):
|
|
|
|
|
- barricadeDict = None
|
|
|
|
|
- if (side == 'outer'):
|
|
|
|
|
- barricadeDict = self.outerBarricadeDict
|
|
|
|
|
- elif (side == 'inner'):
|
|
|
|
|
- barricadeDict = self.innerBarricadeDict
|
|
|
|
|
- else:
|
|
|
|
|
- print("unhandled side %s" % side)
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- if not barricadeDict.has_key(barricadeOrigNum):
|
|
|
|
|
- barricadeDict[barricadeOrigNum] = [curBldgGroupIndex, curBldgGroupIndex]
|
|
|
|
|
-
|
|
|
|
|
- if curBldgGroupIndex < barricadeDict[barricadeOrigNum][0]:
|
|
|
|
|
- barricadeDict[barricadeOrigNum][0] = curBldgGroupIndex
|
|
|
|
|
-
|
|
|
|
|
- if barricadeDict[barricadeOrigNum][1] < curBldgGroupIndex:
|
|
|
|
|
- barricadeDict[barricadeOrigNum][1] = curBldgGroupIndex
|
|
|
|
|
-
|
|
|
|
|
- print "---------- %s barricadeDict origNum=%d data=(%d, %d)" %(side, barricadeOrigNum, barricadeDict[barricadeOrigNum][0], barricadeDict[barricadeOrigNum][1])
|
|
|
|
|
-
|
|
|
|
|
- def makeStreetAlongCurve(self):
|
|
|
|
|
- curves = self.loadStreetCurve()
|
|
|
|
|
- if curves == None:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- self.outerBarricadeDict = {}
|
|
|
|
|
- self.innerBarricadeDict = {}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- base.direct.grid.fXyzSnap = 0
|
|
|
|
|
- base.direct.grid.fHprSnap = 0
|
|
|
|
|
- self.panel.fPlaneSnap.set(0)
|
|
|
|
|
- bldgGroup = self.consolidateStreetBuildings()
|
|
|
|
|
- bldgs = bldgGroup.getChildren()
|
|
|
|
|
-
|
|
|
|
|
- # streetWidth puts buildings on the edge of the street, not the middle
|
|
|
|
|
- currPoint = Point3(0)
|
|
|
|
|
- bldgIndex = 0
|
|
|
|
|
-
|
|
|
|
|
- #populate side streets
|
|
|
|
|
- self.makeSideStreets(curves)
|
|
|
|
|
-
|
|
|
|
|
- # Populate buildings on both sides of the street
|
|
|
|
|
- #sides = ['inner', 'outer','innersidest','outersidest']
|
|
|
|
|
- sides = ['inner', 'outer']
|
|
|
|
|
- maxGroupWidth = 500
|
|
|
|
|
- for side in sides:
|
|
|
|
|
- print "Building street for %s side" % side
|
|
|
|
|
- # Subdivide the curve into different groups.
|
|
|
|
|
- bldgGroupIndex = 0
|
|
|
|
|
- curGroupWidth = 0
|
|
|
|
|
- curveName = '';
|
|
|
|
|
- if len(curves[side]):
|
|
|
|
|
- initialCurve, initialCurveType = curves[side][0]
|
|
|
|
|
- if initialCurve:
|
|
|
|
|
- curveName = initialCurve.getName()
|
|
|
|
|
- self.makeNewBuildingGroup(bldgGroupIndex, side, curveName)
|
|
|
|
|
-
|
|
|
|
|
- for curve, curveType in curves[side]:
|
|
|
|
|
- print "----------------- curve(%s, %s): %s --------------- " % (side, curve.getName(), curve)
|
|
|
|
|
- #import pdb; pdb.set_trace()
|
|
|
|
|
- currT = 0
|
|
|
|
|
- endT = curve.getMaxT()
|
|
|
|
|
-
|
|
|
|
|
- while currT < endT:
|
|
|
|
|
- if curveType == 'urban':
|
|
|
|
|
- bldg, bldgIndex = self.getBldg(bldgIndex, bldgs)
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
-
|
|
|
|
|
- if side == "inner" or side == "innersidest":
|
|
|
|
|
- heading = 90
|
|
|
|
|
- else:
|
|
|
|
|
- heading = -90
|
|
|
|
|
- bldg.setPos(currPoint)
|
|
|
|
|
- bldgWidth = self.getBuildingWidth(bldg)
|
|
|
|
|
-
|
|
|
|
|
- curGroupWidth += bldgWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(bldgWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- bldg.lookAt(Point3(currPoint))
|
|
|
|
|
- bldg.setH(bldg, heading)
|
|
|
|
|
-
|
|
|
|
|
- # Shift building forward if it is on the out track, since we just turned it away from
|
|
|
|
|
- # the direction of the track
|
|
|
|
|
- if side == "outer" or side == "outersidest":
|
|
|
|
|
- bldg.setPos(currPoint)
|
|
|
|
|
-
|
|
|
|
|
- self.updateSelectedPose([bldg])
|
|
|
|
|
- self.adjustPropChildren(bldg)
|
|
|
|
|
- base.direct.reparent(bldg, fWrt = 1)
|
|
|
|
|
- print bldgIndex
|
|
|
|
|
- elif curveType == 'trees':
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
- # trees are spaced anywhere from 40-80 ft apart
|
|
|
|
|
- treeWidth = random.randint(40, 80)
|
|
|
|
|
- curGroupWidth += treeWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(treeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
-
|
|
|
|
|
- # Add some trees
|
|
|
|
|
- tree = random.choice(["prop_tree_small_ul",
|
|
|
|
|
- "prop_tree_small_ur",
|
|
|
|
|
- "prop_tree_large_ur",
|
|
|
|
|
- "prop_tree_large_ul"])
|
|
|
|
|
-
|
|
|
|
|
- #use snow if necessaryy
|
|
|
|
|
-
|
|
|
|
|
- if (useSnowTree):
|
|
|
|
|
- tree = random.choice(["prop_snow_tree_small_ul",
|
|
|
|
|
- "prop_snow_tree_small_ur",
|
|
|
|
|
- "prop_snow_tree_large_ur",
|
|
|
|
|
- "prop_snow_tree_large_ul"])
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- self.addProp(tree)
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- # Move it
|
|
|
|
|
- selectedNode.setPos(currPoint)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
- elif curveType == 'bridge':
|
|
|
|
|
- # Don't add any dna for the bridge sections, but add the length
|
|
|
|
|
- # of the bridge so we can increment our building groups correctly
|
|
|
|
|
- print "adding bridge (%s), curT = %s" % (side, currT)
|
|
|
|
|
- bridgeWidth = 1050
|
|
|
|
|
- curGroupWidth += bridgeWidth
|
|
|
|
|
- #currT, currPoint = self.findBldgEndPoint(bridgeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- print "currT after adding bridge = %s" % currT
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- elif curveType == 'tunnel':
|
|
|
|
|
- # Don't add any dna for the tunnel sections, but add the length
|
|
|
|
|
- # of the bridge so we can increment our building groups correctly
|
|
|
|
|
- print "adding tunnel (%s), curT = %s" % (side, currT)
|
|
|
|
|
- tunnelWidth = 775
|
|
|
|
|
- curGroupWidth += tunnelWidth
|
|
|
|
|
- #currT, currPoint = self.findBldgEndPoint(tunnelWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- print "currT after adding tunnel = %s" % currT
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- elif curveType == 'barricade':
|
|
|
|
|
- print "adding barricade (%s) %s, curT = %d" % (side, curve.getName(), currT)
|
|
|
|
|
- barricadeWidth = curve.calcLength()
|
|
|
|
|
- print "barricade width = %f" % barricadeWidth
|
|
|
|
|
-
|
|
|
|
|
- simple =1
|
|
|
|
|
- if (simple):
|
|
|
|
|
- curGroupWidth += barricadeWidth
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- else:
|
|
|
|
|
- #add a prop_tree to force it to be shown
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
- #trees are spaced anywhere from 40-80 ft apart
|
|
|
|
|
- #treeWidth = random.randint(40, 80)
|
|
|
|
|
- treeWidth = barricadeWidth
|
|
|
|
|
- curGroupWidth += treeWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(treeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
-
|
|
|
|
|
- # Add some trees
|
|
|
|
|
- tree = random.choice(["prop_snow_tree_small_ul",
|
|
|
|
|
- "prop_snow_tree_small_ur",
|
|
|
|
|
- "prop_snow_tree_large_ur",
|
|
|
|
|
- "prop_snow_tree_large_ul"])
|
|
|
|
|
- self.addProp(tree)
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- # Move it
|
|
|
|
|
- selectedNode.setPos(currPoint)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- # Check if we need a new group yet
|
|
|
|
|
- if curGroupWidth > maxGroupWidth:
|
|
|
|
|
- print "curGroupWidth %s > %s" % (curGroupWidth, maxGroupWidth)
|
|
|
|
|
- diffGroup = curGroupWidth - maxGroupWidth
|
|
|
|
|
- while diffGroup > 0:
|
|
|
|
|
- bldgGroupIndex += 1
|
|
|
|
|
- self.makeNewBuildingGroup(bldgGroupIndex, side, curve.getName())
|
|
|
|
|
- print "adding group %s (%s)" % (bldgGroupIndex, diffGroup)
|
|
|
|
|
- diffGroup -= maxGroupWidth
|
|
|
|
|
- curGroupWidth = 0
|
|
|
|
|
- print currT, curGroupWidth
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- def makeSideStreets(self, curves):
|
|
|
|
|
- """ Each side in a sidestreet MUST be in 1 building group, otherwise the 2nd half
|
|
|
|
|
- of a building group could be very far away. This would cause the stashing and
|
|
|
|
|
- unstashing code to go off kilter.
|
|
|
|
|
- """
|
|
|
|
|
-
|
|
|
|
|
- base.direct.grid.fXyzSnap = 0
|
|
|
|
|
- base.direct.grid.fHprSnap = 0
|
|
|
|
|
- self.panel.fPlaneSnap.set(0)
|
|
|
|
|
- bldgGroup = self.consolidateStreetBuildings()
|
|
|
|
|
- bldgs = bldgGroup.getChildren()
|
|
|
|
|
-
|
|
|
|
|
- # streetWidth puts buildings on the edge of the street, not the middle
|
|
|
|
|
- currPoint = Point3(0)
|
|
|
|
|
- bldgIndex = 0
|
|
|
|
|
-
|
|
|
|
|
- # Populate buildings on both sides of the street
|
|
|
|
|
- #sides = ['inner', 'outer','innersidest','outersidest']
|
|
|
|
|
- sides = ['innersidest', 'outersidest']
|
|
|
|
|
- maxGroupWidth = 50000
|
|
|
|
|
- for side in sides:
|
|
|
|
|
- print "Building street for %s side" % side
|
|
|
|
|
- # Subdivide the curve into different groups.
|
|
|
|
|
- bldgGroupIndex = 0
|
|
|
|
|
- curGroupWidth = 0
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- for curve, curveType in curves[side]:
|
|
|
|
|
- print "----------------- curve(%s, %s): %s --------------- " % (side, curve.getName(), curve)
|
|
|
|
|
- #import pdb; pdb.set_trace()
|
|
|
|
|
- currT = 0
|
|
|
|
|
- endT = curve.getMaxT()
|
|
|
|
|
-
|
|
|
|
|
- #RAU side streets still too long, lets try arbitrarily dividing it in half
|
|
|
|
|
- #endT = endT / 2
|
|
|
|
|
-
|
|
|
|
|
- print ("endT = %f" % endT)
|
|
|
|
|
- #if (maxGroupWidth < endT):
|
|
|
|
|
- # self.notify.debug("changing endT from %f to %f" % (endT, maxGroupWidth))
|
|
|
|
|
- # endT = maxGroupWidth
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- currGroupWidth = 0
|
|
|
|
|
- self.makeNewBuildingGroup(bldgGroupIndex, side, curve.getName())
|
|
|
|
|
-
|
|
|
|
|
- while currT < endT:
|
|
|
|
|
- if curveType == 'urban':
|
|
|
|
|
- bldg, bldgIndex = self.getBldg(bldgIndex, bldgs, forceDuplicate = True)
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
-
|
|
|
|
|
- if side == "inner" or side == "innersidest":
|
|
|
|
|
- heading = 90
|
|
|
|
|
- else:
|
|
|
|
|
- heading = -90
|
|
|
|
|
- bldg.setPos(currPoint)
|
|
|
|
|
- bldgWidth = self.getBuildingWidth(bldg)
|
|
|
|
|
-
|
|
|
|
|
- curGroupWidth += bldgWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(bldgWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- bldg.lookAt(Point3(currPoint))
|
|
|
|
|
- bldg.setH(bldg, heading)
|
|
|
|
|
-
|
|
|
|
|
- # Shift building forward if it is on the out track, since we just turned it away from
|
|
|
|
|
- # the direction of the track
|
|
|
|
|
- if side == "outer" or side == "outersidest":
|
|
|
|
|
- bldg.setPos(currPoint)
|
|
|
|
|
-
|
|
|
|
|
- self.updateSelectedPose([bldg])
|
|
|
|
|
- self.adjustPropChildren(bldg)
|
|
|
|
|
- base.direct.reparent(bldg, fWrt = 1)
|
|
|
|
|
- print bldgIndex
|
|
|
|
|
- elif curveType == 'trees':
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
- # trees are spaced anywhere from 40-80 ft apart
|
|
|
|
|
- treeWidth = random.randint(40, 80)
|
|
|
|
|
- curGroupWidth += treeWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(treeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
-
|
|
|
|
|
- # Add some trees
|
|
|
|
|
- tree = random.choice(["prop_tree_small_ul",
|
|
|
|
|
- "prop_tree_small_ur",
|
|
|
|
|
- "prop_tree_large_ur",
|
|
|
|
|
- "prop_tree_large_ul"])
|
|
|
|
|
-
|
|
|
|
|
- #use snow tree if necessary
|
|
|
|
|
- if (useSnowTree):
|
|
|
|
|
- tree = random.choice(["prop_snow_tree_small_ul",
|
|
|
|
|
- "prop_snow_tree_small_ur",
|
|
|
|
|
- "prop_snow_tree_large_ur",
|
|
|
|
|
- "prop_snow_tree_large_ul"])
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- self.addProp(tree)
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- # Move it
|
|
|
|
|
- selectedNode.setPos(currPoint)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
- elif curveType == 'bridge':
|
|
|
|
|
- # Don't add any dna for the bridge sections, but add the length
|
|
|
|
|
- # of the bridge so we can increment our building groups correctly
|
|
|
|
|
- print "adding bridge (%s), curT = %s" % (side, currT)
|
|
|
|
|
- bridgeWidth = 1050
|
|
|
|
|
- curGroupWidth += bridgeWidth
|
|
|
|
|
- #currT, currPoint = self.findBldgEndPoint(bridgeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- print "currT after adding bridge = %s" % currT
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- elif curveType == 'tunnel':
|
|
|
|
|
- # Don't add any dna for the tunnel sections, but add the length
|
|
|
|
|
- # of the bridge so we can increment our building groups correctly
|
|
|
|
|
- print "adding tunnel (%s), curT = %s" % (side, currT)
|
|
|
|
|
- tunnelWidth = 775
|
|
|
|
|
- curGroupWidth += tunnelWidth
|
|
|
|
|
- #currT, currPoint = self.findBldgEndPoint(tunnelWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
- print "currT after adding tunnel = %s" % currT
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- elif curveType == 'barricade':
|
|
|
|
|
- print "adding barricade (%s) %s, curT = %d" % (side, curve.getName(), currT)
|
|
|
|
|
- barricadeWidth = curve.calcLength()
|
|
|
|
|
- print "barricade width = %f" % barricadeWidth
|
|
|
|
|
-
|
|
|
|
|
- simple =1
|
|
|
|
|
- if (simple):
|
|
|
|
|
- curGroupWidth += barricadeWidth
|
|
|
|
|
- # force move to next curve
|
|
|
|
|
- currT = endT + 1
|
|
|
|
|
- else:
|
|
|
|
|
- #add a prop_tree to force it to be shown
|
|
|
|
|
- curve.getPoint(currT, currPoint)
|
|
|
|
|
- #trees are spaced anywhere from 40-80 ft apart
|
|
|
|
|
- #treeWidth = random.randint(40, 80)
|
|
|
|
|
- treeWidth = barricadeWidth
|
|
|
|
|
- curGroupWidth += treeWidth
|
|
|
|
|
- # Adjust grid orientation based upon next point along curve
|
|
|
|
|
- currT, currPoint = self.findBldgEndPoint(treeWidth, curve, currT, currPoint, rd = 0)
|
|
|
|
|
-
|
|
|
|
|
- # Add some trees
|
|
|
|
|
- tree = random.choice(["prop_snow_tree_small_ul",
|
|
|
|
|
- "prop_snow_tree_small_ur",
|
|
|
|
|
- "prop_snow_tree_large_ur",
|
|
|
|
|
- "prop_snow_tree_large_ul"])
|
|
|
|
|
- self.addProp(tree)
|
|
|
|
|
- for selectedNode in base.direct.selected:
|
|
|
|
|
- # Move it
|
|
|
|
|
- selectedNode.setPos(currPoint)
|
|
|
|
|
- # Snap objects to grid and update DNA if necessary
|
|
|
|
|
- self.updateSelectedPose(base.direct.selected.getSelectedAsList())
|
|
|
|
|
-
|
|
|
|
|
- #done with for loop, increment bldgGroupIndex
|
|
|
|
|
- bldgGroupIndex += 1
|
|
|
|
|
-
|
|
|
|
|
- def findBldgEndPoint(self, bldgWidth, curve, currT, currPoint,
|
|
|
|
|
- startT = None, endT = None, tolerance = 0.1, rd = 0):
|
|
|
|
|
- if startT == None:
|
|
|
|
|
- startT = currT
|
|
|
|
|
- if endT == None:
|
|
|
|
|
- endT = curve.getMaxT()
|
|
|
|
|
- if rd > 100:
|
|
|
|
|
- import pdb
|
|
|
|
|
- pdb.set_trace()
|
|
|
|
|
- midT = (startT + endT)/2.0
|
|
|
|
|
- midPoint = Point3(0)
|
|
|
|
|
- curve.getPoint(midT, midPoint)
|
|
|
|
|
- separation = Vec3(midPoint - currPoint).length()
|
|
|
|
|
- error = separation - bldgWidth
|
|
|
|
|
- #print error, startT, midT
|
|
|
|
|
- if abs(error) < tolerance:
|
|
|
|
|
- return midT, midPoint
|
|
|
|
|
- elif error > 0:
|
|
|
|
|
- # Mid point was beyond building end point, focus on first half
|
|
|
|
|
- return self.findBldgEndPoint(bldgWidth, curve, currT, currPoint, startT = startT, endT = midT,
|
|
|
|
|
- rd = rd + 1)
|
|
|
|
|
- else:
|
|
|
|
|
- # End point beyond Mid point, focus on second half
|
|
|
|
|
- # But make sure buildind end point is not beyond curve end point
|
|
|
|
|
- endPoint = Point3(0)
|
|
|
|
|
- curve.getPoint(endT, endPoint)
|
|
|
|
|
- separation = Vec3(endPoint - currPoint).length()
|
|
|
|
|
- if bldgWidth > separation:
|
|
|
|
|
- # Must have reached end of the curve
|
|
|
|
|
- return endT, endPoint
|
|
|
|
|
- else:
|
|
|
|
|
- return self.findBldgEndPoint(bldgWidth, curve, currT, currPoint, startT = midT, endT = endT,
|
|
|
|
|
- rd = rd + 1)
|
|
|
|
|
-
|
|
|
|
|
-class OldLevelEditor(NodePath, DirectObject):
|
|
|
|
|
- pass
|
|
|
|
|
-
|
|
|
|
|
-class LevelEditorPanel(Pmw.MegaToplevel):
|
|
|
|
|
- def __init__(self, levelEditor, parent = None, **kw):
|
|
|
|
|
-
|
|
|
|
|
- INITOPT = Pmw.INITOPT
|
|
|
|
|
- optiondefs = (
|
|
|
|
|
- ('title', 'Toontown Level Editor', None),
|
|
|
|
|
- )
|
|
|
|
|
- self.defineoptions(kw, optiondefs)
|
|
|
|
|
-
|
|
|
|
|
- Pmw.MegaToplevel.__init__(self, parent, title = self['title'])
|
|
|
|
|
-
|
|
|
|
|
- self.levelEditor = levelEditor
|
|
|
|
|
- self.styleManager = self.levelEditor.styleManager
|
|
|
|
|
- self.fUpdateSelected = 1
|
|
|
|
|
- # Handle to the toplevels hull
|
|
|
|
|
- hull = self.component('hull')
|
|
|
|
|
- hull.geometry('400x625')
|
|
|
|
|
-
|
|
|
|
|
- balloon = self.balloon = Pmw.Balloon(hull)
|
|
|
|
|
- # Start with balloon help disabled
|
|
|
|
|
- self.balloon.configure(state = 'none')
|
|
|
|
|
-
|
|
|
|
|
- menuFrame = Frame(hull, relief = GROOVE, bd = 2)
|
|
|
|
|
- menuFrame.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon)
|
|
|
|
|
- menuBar.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- menuBar.addmenu('Level Editor', 'Level Editor Operations')
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Load DNA from specified file',
|
|
|
|
|
- label = 'Load DNA...',
|
|
|
|
|
- command = self.levelEditor.loadSpecifiedDNAFile)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Save DNA data to specified file',
|
|
|
|
|
- label = 'Save DNA As...',
|
|
|
|
|
- command = self.levelEditor.saveToSpecifiedDNAFile)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Save DNA File',
|
|
|
|
|
- label = 'Save DNA',
|
|
|
|
|
- command = self.levelEditor.outputDNADefaultFile)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'CVS update directory',
|
|
|
|
|
- label = 'CVS update',
|
|
|
|
|
- command = self.levelEditor.cvsUpdateAll)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'CVS commit directory',
|
|
|
|
|
- label = 'CVS commit',
|
|
|
|
|
- command = self.levelEditor.cvsCommitAll)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Edit Visibility Groups',
|
|
|
|
|
- label = 'Edit Vis Groups',
|
|
|
|
|
- command = self.levelEditor.editDNAVisGroups)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Reset level',
|
|
|
|
|
- label = 'Reset level',
|
|
|
|
|
- command = self.levelEditor.reset)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Make Long Street',
|
|
|
|
|
- label = 'Make Long Street',
|
|
|
|
|
- command = self.levelEditor.makeLongStreet)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Make Street Along Curve',
|
|
|
|
|
- label = 'Make Street Along Curve',
|
|
|
|
|
- command = self.levelEditor.makeStreetAlongCurve)
|
|
|
|
|
- menuBar.addmenuitem('Level Editor', 'command',
|
|
|
|
|
- 'Exit Level Editor Panel',
|
|
|
|
|
- label = 'Exit',
|
|
|
|
|
- command = self.levelEditor.destroy)
|
|
|
|
|
-
|
|
|
|
|
- menuBar.addmenu('Style', 'Style Operations')
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- "Save Selected Object's Color",
|
|
|
|
|
- label = 'Save Color',
|
|
|
|
|
- command = self.levelEditor.saveColor)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- "Save Selected Baseline's Style",
|
|
|
|
|
- label = 'Save Baseline Style',
|
|
|
|
|
- command = self.levelEditor.saveBaselineStyle)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- "Save Selected Wall's Style",
|
|
|
|
|
- label = 'Save Wall Style',
|
|
|
|
|
- command = self.levelEditor.saveWallStyle)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- "Save Selected Buildings's Style",
|
|
|
|
|
- label = 'Save Bldg Style',
|
|
|
|
|
- command = self.levelEditor.saveBuildingStyle)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- 'Reload Color Palettes',
|
|
|
|
|
- label = 'Reload Colors',
|
|
|
|
|
- command = self.styleManager.createColorAttributes)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- 'Reload Baseline Style Palettes',
|
|
|
|
|
- label = 'Reload Baseline Styles',
|
|
|
|
|
- command = self.styleManager.createBaselineStyleAttributes)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- 'Reload Wall Style Palettes',
|
|
|
|
|
- label = 'Reload Wall Styles',
|
|
|
|
|
- command = self.styleManager.createWallStyleAttributes)
|
|
|
|
|
- menuBar.addmenuitem('Style', 'command',
|
|
|
|
|
- 'Reload Building Style Palettes',
|
|
|
|
|
- label = 'Reload Bldg Styles',
|
|
|
|
|
- command = self.styleManager.createBuildingStyleAttributes)
|
|
|
|
|
-
|
|
|
|
|
- menuBar.addmenu('Help', 'Level Editor Help Operations')
|
|
|
|
|
- self.toggleBalloonVar = IntVar()
|
|
|
|
|
- self.toggleBalloonVar.set(0)
|
|
|
|
|
- menuBar.addmenuitem('Help', 'checkbutton',
|
|
|
|
|
- 'Toggle balloon help',
|
|
|
|
|
- label = 'Balloon Help',
|
|
|
|
|
- variable = self.toggleBalloonVar,
|
|
|
|
|
- command = self.toggleBalloon)
|
|
|
|
|
-
|
|
|
|
|
- self.editMenu = Pmw.ComboBox(
|
|
|
|
|
- menuFrame, labelpos = W,
|
|
|
|
|
- label_text = 'Edit Mode:', entry_width = 18,
|
|
|
|
|
- selectioncommand = self.levelEditor.setEditMode, history = 0,
|
|
|
|
|
- scrolledlist_items = NEIGHBORHOODS)
|
|
|
|
|
- self.editMenu.selectitem(NEIGHBORHOODS[0])
|
|
|
|
|
- self.editMenu.pack(side = LEFT, expand = 0)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- # Create the notebook pages
|
|
|
|
|
- self.notebook = Pmw.NoteBook(hull)
|
|
|
|
|
- self.notebook.pack(fill = BOTH, expand = 1)
|
|
|
|
|
- streetsPage = self.notebook.add('Streets')
|
|
|
|
|
- toonBuildingsPage = self.notebook.add('Toon Bldgs')
|
|
|
|
|
- landmarkBuildingsPage = self.notebook.add('Landmark Bldgs')
|
|
|
|
|
- # suitBuildingsPage = self.notebook.add('Suit Buildings')
|
|
|
|
|
- propsPage = self.notebook.add('Props')
|
|
|
|
|
- signPage = self.notebook.add('Signs')
|
|
|
|
|
- suitPathPage = self.notebook.add('Paths')
|
|
|
|
|
- battleCellPage = self.notebook.add('Cells')
|
|
|
|
|
- sceneGraphPage = self.notebook.add('SceneGraph')
|
|
|
|
|
- self.notebook['raisecommand'] = self.updateInfo
|
|
|
|
|
-
|
|
|
|
|
- # STREETS
|
|
|
|
|
- Label(streetsPage, text = 'Streets',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- self.addStreetButton = Button(
|
|
|
|
|
- streetsPage,
|
|
|
|
|
- text = 'ADD STREET',
|
|
|
|
|
- command = self.addStreet)
|
|
|
|
|
- self.addStreetButton.pack(fill = X, padx = 20, pady = 10)
|
|
|
|
|
- streets = map(lambda s: s[7:],
|
|
|
|
|
- self.styleManager.getCatalogCodes(
|
|
|
|
|
- 'street'))
|
|
|
|
|
- streets.sort()
|
|
|
|
|
- self.streetSelector = Pmw.ComboBox(
|
|
|
|
|
- streetsPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_text = 'Street type:',
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setStreetModuleType,
|
|
|
|
|
- scrolledlist_items = streets
|
|
|
|
|
- )
|
|
|
|
|
- self.streetModuleType = self.styleManager.getCatalogCode('street', 0)
|
|
|
|
|
- self.streetSelector.selectitem(self.streetModuleType[7:])
|
|
|
|
|
- self.streetSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # TOON BUILDINGS
|
|
|
|
|
- Label(toonBuildingsPage, text = 'Toon Buildings',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- self.addToonBuildingButton = Button(
|
|
|
|
|
- toonBuildingsPage,
|
|
|
|
|
- text = 'ADD TOON BUILDING',
|
|
|
|
|
- command = self.addFlatBuilding)
|
|
|
|
|
- self.addToonBuildingButton.pack(fill = X, padx = 20, pady = 10)
|
|
|
|
|
- self.toonBuildingSelector = Pmw.ComboBox(
|
|
|
|
|
- toonBuildingsPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- label_text = 'Bldg type:',
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setFlatBuildingType,
|
|
|
|
|
- scrolledlist_items = (['random'] + BUILDING_TYPES)
|
|
|
|
|
- )
|
|
|
|
|
- bf = Frame(toonBuildingsPage)
|
|
|
|
|
- Label(bf, text = 'Building Height:').pack(side = LEFT, expand = 0)
|
|
|
|
|
- self.heightMode = IntVar()
|
|
|
|
|
- self.heightMode.set(20)
|
|
|
|
|
- self.tenFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '10 ft',
|
|
|
|
|
- value = 10,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.tenFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- self.fourteenFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '14 ft',
|
|
|
|
|
- value = 14,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.fourteenFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- self.twentyFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '20 ft',
|
|
|
|
|
- value = 20,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.twentyFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- self.twentyFourFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '24 ft',
|
|
|
|
|
- value = 24,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.twentyFourFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- self.twentyFiveFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '25 ft',
|
|
|
|
|
- value = 25,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.twentyFiveFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- self.thirtyFootButton = Radiobutton(
|
|
|
|
|
- bf,
|
|
|
|
|
- text = '30 ft',
|
|
|
|
|
- value = 30,
|
|
|
|
|
- variable = self.heightMode,
|
|
|
|
|
- command = self.setFlatBuildingHeight)
|
|
|
|
|
- self.thirtyFootButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- bf.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.toonBuildingType = 'random'
|
|
|
|
|
- self.toonBuildingSelector.selectitem(self.toonBuildingType)
|
|
|
|
|
- self.toonBuildingSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # LANDMARK BUILDINGS
|
|
|
|
|
- Label(landmarkBuildingsPage, text = 'Landmark Buildings',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
-
|
|
|
|
|
- """
|
|
|
|
|
- self.landmarkHQIntVar = IntVar()
|
|
|
|
|
- self.landmarkHQIntVar.set(0)
|
|
|
|
|
- self.landmarkHQButton = Checkbutton(
|
|
|
|
|
- landmarkBuildingsPage,
|
|
|
|
|
- text = 'HQ',
|
|
|
|
|
- variable=self.landmarkHQIntVar,
|
|
|
|
|
- command=self.setLandmarkHQ)
|
|
|
|
|
- self.landmarkHQButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- """
|
|
|
|
|
-
|
|
|
|
|
- self.addLandmarkBuildingButton = Button(
|
|
|
|
|
- landmarkBuildingsPage,
|
|
|
|
|
- text = 'ADD LANDMARK BUILDING',
|
|
|
|
|
- command = self.addLandmark)
|
|
|
|
|
- self.addLandmarkBuildingButton.pack(fill = X, padx = 20, pady = 10)
|
|
|
|
|
- bldgs = map(lambda s: s[14:],
|
|
|
|
|
- self.styleManager.getCatalogCodes(
|
|
|
|
|
- 'toon_landmark'))
|
|
|
|
|
- bldgs.sort()
|
|
|
|
|
- self.landmarkBuildingSelector = Pmw.ComboBox(
|
|
|
|
|
- landmarkBuildingsPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- label_text = 'Bldg type:',
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setLandmarkType,
|
|
|
|
|
- scrolledlist_items = bldgs
|
|
|
|
|
- )
|
|
|
|
|
- self.landmarkType = self.styleManager.getCatalogCode(
|
|
|
|
|
- 'toon_landmark', 0)
|
|
|
|
|
- self.landmarkBuildingSelector.selectitem(
|
|
|
|
|
- self.styleManager.getCatalogCode('toon_landmark', 0)[14:])
|
|
|
|
|
- self.landmarkBuildingSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- self.landmarkBuildingSpecialSelector = Pmw.ComboBox(
|
|
|
|
|
- landmarkBuildingsPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 100,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- label_text = 'Special type:',
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setLandmarkSpecialType,
|
|
|
|
|
- scrolledlist_items = LANDMARK_SPECIAL_TYPES
|
|
|
|
|
- )
|
|
|
|
|
- self.landmarkSpecialType = LANDMARK_SPECIAL_TYPES[0]
|
|
|
|
|
- self.landmarkBuildingSpecialSelector.selectitem(
|
|
|
|
|
- LANDMARK_SPECIAL_TYPES[0])
|
|
|
|
|
- self.landmarkBuildingSpecialSelector.pack(expand = 0)
|
|
|
|
|
-
|
|
|
|
|
- # SIGNS
|
|
|
|
|
- Label(signPage, text = 'Signs',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- self.currentSignDNA=None
|
|
|
|
|
- self.currentBaselineDNA=None
|
|
|
|
|
- self.levelEditor.selectedNodePathHookHooks.append(self.updateSignPage)
|
|
|
|
|
-
|
|
|
|
|
- gridFrame = Frame(signPage)
|
|
|
|
|
- signSelectedFrame = Frame(gridFrame)
|
|
|
|
|
-
|
|
|
|
|
- self.currentBaselineIndex=0
|
|
|
|
|
- self.baselineMenu = Pmw.ComboBox(
|
|
|
|
|
- signSelectedFrame,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_text = 'Selected:', entry_width = 24,
|
|
|
|
|
- selectioncommand = self.selectSignBaseline,
|
|
|
|
|
- history = 0, # unique = 0,
|
|
|
|
|
- scrolledlist_items = ['<the sign>'])
|
|
|
|
|
- self.baselineMenu.selectitem(self.currentBaselineIndex)
|
|
|
|
|
- self.baselineMenu.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.baselineAddButton = Button(
|
|
|
|
|
- signSelectedFrame,
|
|
|
|
|
- text="Add Baseline", command=self.addBaseline)
|
|
|
|
|
- self.baselineAddButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.baselineDeleteButton = Button(
|
|
|
|
|
- signSelectedFrame,
|
|
|
|
|
- text="Del", command=self.deleteSignItem)
|
|
|
|
|
- self.baselineDeleteButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- signSelectedFrame.grid(row=0, column=0, columnspan=6)
|
|
|
|
|
-
|
|
|
|
|
- self.baselineString=StringVar()
|
|
|
|
|
- self.baselineString.trace("wu", self.signBaselineTrace)
|
|
|
|
|
- self.baselineTextBox = Entry(
|
|
|
|
|
- gridFrame, width = 24,
|
|
|
|
|
- textvariable=self.baselineString)
|
|
|
|
|
- self.baselineTextBox.grid(row=1, column=0, columnspan=3)
|
|
|
|
|
-
|
|
|
|
|
- fontList = [""]+self.styleManager.getCatalogCodes('font')
|
|
|
|
|
- self.fontMenu = Pmw.ComboBox(
|
|
|
|
|
- gridFrame, labelpos = W,
|
|
|
|
|
- label_text = 'Font:', entry_width = 12,
|
|
|
|
|
- selectioncommand = self.setSignBaslineFont, history = 0,
|
|
|
|
|
- scrolledlist_items = fontList)
|
|
|
|
|
- self.fontMenu.selectitem(0)
|
|
|
|
|
- self.fontMenu.grid(row=1, column=3, columnspan=3)
|
|
|
|
|
-
|
|
|
|
|
- graphicList = self.styleManager.getCatalogCodes('graphic')
|
|
|
|
|
- self.graphicMenu = Pmw.ComboBox(
|
|
|
|
|
- gridFrame, labelpos = W,
|
|
|
|
|
- label_text = 'Add Graphic:', entry_width = 24,
|
|
|
|
|
- selectioncommand = self.addSignGraphic, history = 0,
|
|
|
|
|
- scrolledlist_items = graphicList)
|
|
|
|
|
- self.graphicMenu.selectitem(0)
|
|
|
|
|
- self.graphicMenu.grid(row=2, column=0, columnspan=4)
|
|
|
|
|
-
|
|
|
|
|
- signButtonFrame = Frame(gridFrame)
|
|
|
|
|
-
|
|
|
|
|
- self.bigFirstLetterIntVar = IntVar()
|
|
|
|
|
- self.bigFirstLetterCheckbutton = Checkbutton(
|
|
|
|
|
- signButtonFrame,
|
|
|
|
|
- text = 'Big First Letter',
|
|
|
|
|
- variable=self.bigFirstLetterIntVar, command=self.setBigFirstLetter)
|
|
|
|
|
- self.bigFirstLetterCheckbutton.pack(
|
|
|
|
|
- side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.allCapsIntVar = IntVar()
|
|
|
|
|
- self.allCapsCheckbutton = Checkbutton(
|
|
|
|
|
- signButtonFrame,
|
|
|
|
|
- text = 'All Caps',
|
|
|
|
|
- variable=self.allCapsIntVar, command=self.setAllCaps)
|
|
|
|
|
- self.allCapsCheckbutton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.dropShadowIntVar = IntVar()
|
|
|
|
|
- self.dropShadowCheckbutton = Checkbutton(
|
|
|
|
|
- signButtonFrame,
|
|
|
|
|
- text = 'Drop Shadow',
|
|
|
|
|
- variable=self.dropShadowIntVar, command=self.setDropShadow)
|
|
|
|
|
- self.dropShadowCheckbutton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- signButtonFrame.grid(row=3, column=0, columnspan=6)
|
|
|
|
|
-
|
|
|
|
|
- self.addKernFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Kern',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setSignBaselineKern)
|
|
|
|
|
- self.addKernFloater.grid(row=4, column=0, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addWiggleFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Wiggle',
|
|
|
|
|
- #maxVelocity=10.0,
|
|
|
|
|
- command=self.setSignBaselineWiggle)
|
|
|
|
|
- self.addWiggleFloater.grid(row=6, column=0, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addStumbleFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Stumble',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setSignBaselineStumble)
|
|
|
|
|
- self.addStumbleFloater.grid(row=8, column=0, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addStompFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Stomp',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setSignBaselineStomp)
|
|
|
|
|
- self.addStompFloater.grid(row=10, column=0, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addCurveFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Curve',
|
|
|
|
|
- #maxVelocity = 1.0,
|
|
|
|
|
- command=self.setSignBaselineCurve)
|
|
|
|
|
- self.addCurveFloater.grid(row=12, column=0, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addXFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='X',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setDNATargetX)
|
|
|
|
|
- self.addXFloater.grid(row=4, column=3, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addZFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Z',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setDNATargetZ)
|
|
|
|
|
- self.addZFloater.grid(row=6, column=3, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addScaleXFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Scale X',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setDNATargetScaleX)
|
|
|
|
|
- self.addScaleXFloater.grid(row=8, column=3, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addScaleZFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Scale Z',
|
|
|
|
|
- #maxVelocity=1.0,
|
|
|
|
|
- command=self.setDNATargetScaleZ)
|
|
|
|
|
- self.addScaleZFloater.grid(row=10, column=3, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
- self.addRollFloater = Floater.Floater(
|
|
|
|
|
- gridFrame,
|
|
|
|
|
- text='Roll',
|
|
|
|
|
- #maxVelocity=10.0,
|
|
|
|
|
- command=self.setDNATargetRoll)
|
|
|
|
|
- self.addRollFloater.grid(row=12, column=3, rowspan=2, columnspan=3,
|
|
|
|
|
- sticky = EW)
|
|
|
|
|
-
|
|
|
|
|
- gridFrame.pack(fill=BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # PROPS
|
|
|
|
|
- Label(propsPage, text = 'Props',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- self.addPropsButton = Button(
|
|
|
|
|
- propsPage,
|
|
|
|
|
- text = 'ADD PROP',
|
|
|
|
|
- command = self.addProp)
|
|
|
|
|
- self.addPropsButton.pack(fill = X, padx = 20, pady = 10)
|
|
|
|
|
- codes = (self.styleManager.getCatalogCodes('prop') +
|
|
|
|
|
- self.styleManager.getCatalogCodes('holiday_prop'))
|
|
|
|
|
- codes.sort()
|
|
|
|
|
- self.propSelector = Pmw.ComboBox(
|
|
|
|
|
- propsPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- label_text = 'Prop type:',
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setPropType,
|
|
|
|
|
- scrolledlist_items = codes
|
|
|
|
|
- )
|
|
|
|
|
- self.propType = self.styleManager.getCatalogCode('prop', 0)
|
|
|
|
|
- self.propSelector.selectitem(
|
|
|
|
|
- self.styleManager.getCatalogCode('prop', 0))
|
|
|
|
|
- self.propSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # SUIT PATHS
|
|
|
|
|
- Label(suitPathPage, text = 'Suit Paths',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
-
|
|
|
|
|
- spButtons = Frame(suitPathPage)
|
|
|
|
|
- self.fPaths = IntVar()
|
|
|
|
|
- self.fPaths.set(0)
|
|
|
|
|
- self.pathButton = Checkbutton(spButtons,
|
|
|
|
|
- text = 'Show Paths',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fPaths,
|
|
|
|
|
- command = self.toggleSuitPaths)
|
|
|
|
|
- self.pathButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.zoneColor = IntVar()
|
|
|
|
|
- self.zoneColor.set(0)
|
|
|
|
|
- self.colorZoneButton1 = Checkbutton(
|
|
|
|
|
- spButtons,
|
|
|
|
|
- text = 'Color Zones', width = 6,
|
|
|
|
|
- variable = self.zoneColor,
|
|
|
|
|
- command = self.levelEditor.toggleZoneColors)
|
|
|
|
|
- self.colorZoneButton1.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- spButtons.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- spButtons = Frame(suitPathPage)
|
|
|
|
|
- Label(spButtons, text = 'Highlight:').pack(side = LEFT, fill = X)
|
|
|
|
|
- self.highlightConnectedButton = Button(
|
|
|
|
|
- spButtons,
|
|
|
|
|
- text = 'Forward',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- command = self.levelEditor.highlightConnected)
|
|
|
|
|
- self.highlightConnectedButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.highlightConnectedButton2 = Button(
|
|
|
|
|
- spButtons,
|
|
|
|
|
- text = 'Connected',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- command = lambda s = self: s.levelEditor.highlightConnected(fReversePath = 1))
|
|
|
|
|
- self.highlightConnectedButton2.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.clearHighlightButton = Button(
|
|
|
|
|
- spButtons,
|
|
|
|
|
- text = 'Clear',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- command = self.levelEditor.clearPathHighlights)
|
|
|
|
|
- self.clearHighlightButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- spButtons.pack(fill = X, pady = 4)
|
|
|
|
|
-
|
|
|
|
|
- self.suitPointSelector = Pmw.ComboBox(
|
|
|
|
|
- suitPathPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_text = 'Point type:',
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setSuitPointType,
|
|
|
|
|
- scrolledlist_items = ['street', 'front door', 'side door']
|
|
|
|
|
- )
|
|
|
|
|
- self.suitPointSelector.selectitem('street')
|
|
|
|
|
- self.suitPointSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # BATTLE CELLS
|
|
|
|
|
- Label(battleCellPage, text = 'Battle Cells',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- bcButtons = Frame(battleCellPage)
|
|
|
|
|
- self.fCells = IntVar()
|
|
|
|
|
- self.fCells.set(0)
|
|
|
|
|
- self.cellButton = Checkbutton(bcButtons,
|
|
|
|
|
- text = 'Show Cells',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fCells,
|
|
|
|
|
- command = self.toggleBattleCells)
|
|
|
|
|
- self.cellButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.colorZoneButton2 = Checkbutton(
|
|
|
|
|
- bcButtons,
|
|
|
|
|
- text = 'Color Zones', width = 6,
|
|
|
|
|
- variable = self.zoneColor,
|
|
|
|
|
- command = self.levelEditor.toggleZoneColors)
|
|
|
|
|
- self.colorZoneButton2.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- bcButtons.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.battleCellSelector = Pmw.ComboBox(
|
|
|
|
|
- battleCellPage,
|
|
|
|
|
- dropdown = 0,
|
|
|
|
|
- listheight = 200,
|
|
|
|
|
- labelpos = W,
|
|
|
|
|
- label_text = 'Cell type:',
|
|
|
|
|
- label_width = 12,
|
|
|
|
|
- label_anchor = W,
|
|
|
|
|
- entry_width = 30,
|
|
|
|
|
- selectioncommand = self.setBattleCellType,
|
|
|
|
|
- scrolledlist_items = ['20w 20l', '20w 30l', '30w 20l', '30w 30l']
|
|
|
|
|
- )
|
|
|
|
|
- self.battleCellSelector.selectitem('20w 20l')
|
|
|
|
|
- self.battleCellSelector.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # SCENE GRAPH EXPLORER
|
|
|
|
|
- Label(sceneGraphPage, text = 'Level Scene Graph',
|
|
|
|
|
- font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
|
|
|
|
- self.sceneGraphExplorer = SceneGraphExplorer(
|
|
|
|
|
- parent = sceneGraphPage,
|
|
|
|
|
- nodePath = self.levelEditor,
|
|
|
|
|
- menuItems = ['Add Group', 'Add Vis Group'])
|
|
|
|
|
- self.sceneGraphExplorer.pack(expand = 1, fill = BOTH)
|
|
|
|
|
-
|
|
|
|
|
- # Compact down notebook
|
|
|
|
|
- self.notebook.setnaturalsize()
|
|
|
|
|
-
|
|
|
|
|
- self.colorEntry = VectorWidgets.ColorEntry(
|
|
|
|
|
- hull, text = 'Select Color',
|
|
|
|
|
- command = self.updateSelectedObjColor)
|
|
|
|
|
- self.colorEntry.menu.add_command(
|
|
|
|
|
- label = 'Save Color', command = self.levelEditor.saveColor)
|
|
|
|
|
- self.colorEntry.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame = Frame(hull)
|
|
|
|
|
- self.fMapVis = IntVar()
|
|
|
|
|
- self.fMapVis.set(0)
|
|
|
|
|
- self.mapSnapButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'Map Vis',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fMapVis,
|
|
|
|
|
- command = self.toggleMapVis)
|
|
|
|
|
- #self.mapSnapButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fXyzSnap = IntVar()
|
|
|
|
|
- self.fXyzSnap.set(1)
|
|
|
|
|
- self.xyzSnapButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'XyzSnap',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fXyzSnap,
|
|
|
|
|
- command = self.toggleXyzSnap)
|
|
|
|
|
- self.xyzSnapButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fHprSnap = IntVar()
|
|
|
|
|
- self.fHprSnap.set(1)
|
|
|
|
|
- self.hprSnapButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'HprSnap',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fHprSnap,
|
|
|
|
|
- command = self.toggleHprSnap)
|
|
|
|
|
- self.hprSnapButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- def toggleWidgetHandles(s = self):
|
|
|
|
|
- if s.fPlaneSnap.get():
|
|
|
|
|
- base.direct.widget.disableHandles(['x-ring', 'x-disc',
|
|
|
|
|
- 'y-ring', 'y-disc',
|
|
|
|
|
- 'z-post'])
|
|
|
|
|
- else:
|
|
|
|
|
- base.direct.widget.enableHandles('all')
|
|
|
|
|
- self.fPlaneSnap = IntVar()
|
|
|
|
|
- self.fPlaneSnap.set(1)
|
|
|
|
|
- self.planeSnapButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'PlaneSnap',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fPlaneSnap,
|
|
|
|
|
- command = toggleWidgetHandles)
|
|
|
|
|
- self.planeSnapButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fGrid = IntVar()
|
|
|
|
|
- self.fGrid.set(0)
|
|
|
|
|
- base.direct.gridButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'Show Grid',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fGrid,
|
|
|
|
|
- command = self.toggleGrid)
|
|
|
|
|
- base.direct.gridButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fMaya = IntVar()
|
|
|
|
|
- self.fMaya.set(1)
|
|
|
|
|
- self.mayaButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'Maya Cam',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fMaya,
|
|
|
|
|
- command = self.toggleMaya)
|
|
|
|
|
- self.mayaButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
|
|
+"""
|
|
|
|
|
+This is just a sample code.
|
|
|
|
|
+
|
|
|
|
|
+LevelEditor, ObjectHandler, ObjectPalette should be rewritten
|
|
|
|
|
+to be game specific.
|
|
|
|
|
+"""
|
|
|
|
|
+
|
|
|
|
|
+from LevelEditorBase import *
|
|
|
|
|
+from ObjectHandler import *
|
|
|
|
|
+from ObjectPalette import *
|
|
|
|
|
+from LevelEditorUI import *
|
|
|
|
|
+
|
|
|
|
|
+class LevelEditor(LevelEditorBase):
|
|
|
|
|
+ """ Class for Panda3D LevelEditor """
|
|
|
|
|
+ def __init__(self):
|
|
|
|
|
+ LevelEditorBase.__init__(self)
|
|
|
|
|
+ # If you have your own ObjectPalette and ObjectHandler
|
|
|
|
|
+ # connect them in your own LevelEditor class
|
|
|
|
|
+ self.objectPalette = ObjectPalette()
|
|
|
|
|
+ self.objectHandler = ObjectHandler(self)
|
|
|
|
|
+
|
|
|
|
|
+ # LevelEditorUI class must declared after ObjectPalette
|
|
|
|
|
+ self.ui = LevelEditorUI(self)
|
|
|
|
|
|
|
|
- #Make maya mode on by default
|
|
|
|
|
- self.toggleMaya()
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame4 = Frame(hull)
|
|
|
|
|
- self.driveMode = IntVar()
|
|
|
|
|
- self.driveMode.set(1)
|
|
|
|
|
- self.directModeButton = Radiobutton(
|
|
|
|
|
- buttonFrame4,
|
|
|
|
|
- text = 'DIRECT Fly',
|
|
|
|
|
- value = 1,
|
|
|
|
|
- variable = self.driveMode,
|
|
|
|
|
- command = self.levelEditor.useDirectFly)
|
|
|
|
|
- self.directModeButton.pack(side = LEFT, fill = X, expand = 1)
|
|
|
|
|
- self.driveModeButton = Radiobutton(
|
|
|
|
|
- buttonFrame4,
|
|
|
|
|
- text = 'Drive',
|
|
|
|
|
- value = 0,
|
|
|
|
|
- variable = self.driveMode,
|
|
|
|
|
- command = self.levelEditor.useDriveMode)
|
|
|
|
|
- self.driveModeButton.pack(side = LEFT, fill = X, expand = 1)
|
|
|
|
|
-
|
|
|
|
|
- self.fColl = IntVar()
|
|
|
|
|
- self.fColl.set(1)
|
|
|
|
|
- base.direct.collButton = Checkbutton(
|
|
|
|
|
- buttonFrame4,
|
|
|
|
|
- text = 'Collide',
|
|
|
|
|
- variable = self.fColl,
|
|
|
|
|
- command = self.levelEditor.toggleCollisions)
|
|
|
|
|
- base.direct.collButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fVis = IntVar()
|
|
|
|
|
- self.fVis.set(1)
|
|
|
|
|
- base.direct.visButton = Checkbutton(
|
|
|
|
|
- buttonFrame4,
|
|
|
|
|
- text = 'Visibility',
|
|
|
|
|
- variable = self.fVis,
|
|
|
|
|
- command = self.levelEditor.toggleVisibility)
|
|
|
|
|
- base.direct.visButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.fVisZones = IntVar()
|
|
|
|
|
- self.fVisZones.set(visualizeZones)
|
|
|
|
|
- base.direct.visZonesButton = Checkbutton(
|
|
|
|
|
- buttonFrame4,
|
|
|
|
|
- text = 'Show Zones',
|
|
|
|
|
- variable = self.fVisZones)
|
|
|
|
|
- base.direct.visZonesButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame4.pack(fill = X, padx = 5)
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame = Frame(hull)
|
|
|
|
|
- self.fLabel = IntVar()
|
|
|
|
|
- self.fLabel.set(0)
|
|
|
|
|
- self.labelButton = Checkbutton(buttonFrame,
|
|
|
|
|
- text = 'Show Zone Labels',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- variable = self.fLabel,
|
|
|
|
|
- command = self.toggleZoneLabels)
|
|
|
|
|
- self.labelButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- self.selectButton = Button(buttonFrame,
|
|
|
|
|
- text = 'Place Selected',
|
|
|
|
|
- width = 6,
|
|
|
|
|
- command = lambda: last.place()
|
|
|
|
|
- )
|
|
|
|
|
- self.selectButton.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- buttonFrame.pack(fill = X)
|
|
|
|
|
-
|
|
|
|
|
- # Make sure input variables processed
|
|
|
|
|
- self.initialiseoptions(LevelEditorPanel)
|
|
|
|
|
-
|
|
|
|
|
- def updateInfo(self, page):
|
|
|
|
|
- if page == 'Signs':
|
|
|
|
|
- self.updateSignPage()
|
|
|
|
|
-
|
|
|
|
|
- # [gjeon] to toggle maya cam mode
|
|
|
|
|
- def toggleMaya(self):
|
|
|
|
|
- base.direct.cameraControl.lockRoll = self.fMaya.get()
|
|
|
|
|
- direct.cameraControl.useMayaCamControls = self.fMaya.get()
|
|
|
|
|
-
|
|
|
|
|
- def toggleGrid(self):
|
|
|
|
|
- if self.fGrid.get():
|
|
|
|
|
- base.direct.grid.enable()
|
|
|
|
|
- else:
|
|
|
|
|
- base.direct.grid.disable()
|
|
|
|
|
-
|
|
|
|
|
- def toggleSuitPaths(self):
|
|
|
|
|
- if self.fPaths.get():
|
|
|
|
|
- self.levelEditor.showSuitPaths()
|
|
|
|
|
- else:
|
|
|
|
|
- self.levelEditor.hideSuitPaths()
|
|
|
|
|
-
|
|
|
|
|
- def toggleBattleCells(self):
|
|
|
|
|
- if self.fCells.get():
|
|
|
|
|
- self.levelEditor.showBattleCells()
|
|
|
|
|
- else:
|
|
|
|
|
- self.levelEditor.hideBattleCells()
|
|
|
|
|
-
|
|
|
|
|
- def toggleZoneLabels(self):
|
|
|
|
|
- if self.fLabel.get():
|
|
|
|
|
- self.levelEditor.labelZones()
|
|
|
|
|
- else:
|
|
|
|
|
- self.levelEditor.clearZoneLabels()
|
|
|
|
|
-
|
|
|
|
|
- def toggleXyzSnap(self):
|
|
|
|
|
- base.direct.grid.setXyzSnap(self.fXyzSnap.get())
|
|
|
|
|
-
|
|
|
|
|
- def toggleHprSnap(self):
|
|
|
|
|
- base.direct.grid.setHprSnap(self.fXyzSnap.get())
|
|
|
|
|
-
|
|
|
|
|
- def toggleMapVis(self):
|
|
|
|
|
- self.levelEditor.toggleMapVis(self.fMapVis.get())
|
|
|
|
|
-
|
|
|
|
|
- def setStreetModuleType(self, name):
|
|
|
|
|
- self.streetModuleType = 'street_' + name
|
|
|
|
|
- self.levelEditor.setCurrent('street_texture', self.streetModuleType)
|
|
|
|
|
-
|
|
|
|
|
- def addStreet(self):
|
|
|
|
|
- self.levelEditor.addStreet(self.streetModuleType)
|
|
|
|
|
-
|
|
|
|
|
- def setFlatBuildingType(self, name):
|
|
|
|
|
- self.toonBuildingType = name
|
|
|
|
|
- self.levelEditor.setCurrent('building_type', self.toonBuildingType)
|
|
|
|
|
-
|
|
|
|
|
- def setFlatBuildingHeight(self):
|
|
|
|
|
- height = self.heightMode.get()
|
|
|
|
|
- self.levelEditor.setCurrent('building_height', height)
|
|
|
|
|
- self.updateHeightList(height)
|
|
|
|
|
-
|
|
|
|
|
- def updateHeightList(self, height):
|
|
|
|
|
- # Update combo box
|
|
|
|
|
- heightList = self.levelEditor.getList(`height` + '_ft_wall_heights')
|
|
|
|
|
- self.toonBuildingSelector.setlist(
|
|
|
|
|
- ['random'] + map(createHeightCode, heightList))
|
|
|
|
|
- self.toonBuildingSelector.selectitem(0)
|
|
|
|
|
- self.toonBuildingSelector.invoke()
|
|
|
|
|
-
|
|
|
|
|
- def addFlatBuilding(self):
|
|
|
|
|
- self.levelEditor.addFlatBuilding(self.toonBuildingType)
|
|
|
|
|
-
|
|
|
|
|
- def setLandmarkType(self, name):
|
|
|
|
|
- self.landmarkType = 'toon_landmark_' + name
|
|
|
|
|
- self.levelEditor.setCurrent('toon_landmark_texture', self.landmarkType)
|
|
|
|
|
-
|
|
|
|
|
- def signPanelSync(self):
|
|
|
|
|
- self.baselineMenu.delete(1, END)
|
|
|
|
|
- sign=self.findSignFromDNARoot()
|
|
|
|
|
- if not sign:
|
|
|
|
|
- return
|
|
|
|
|
- baselineList = DNAGetChildren(sign, DNA_SIGN_BASELINE)
|
|
|
|
|
- for baseline in baselineList:
|
|
|
|
|
- s=DNAGetBaselineString(baseline)
|
|
|
|
|
- self.baselineMenu.insert(END, s)
|
|
|
|
|
- self.baselineMenu.selectitem(0)
|
|
|
|
|
- self.selectSignBaseline(0)
|
|
|
|
|
-
|
|
|
|
|
- def updateSignPage(self):
|
|
|
|
|
- if (self.notebook.getcurselection() == 'Signs'):
|
|
|
|
|
- sign=self.findSignFromDNARoot()
|
|
|
|
|
- # Only update if it's not the current sign:
|
|
|
|
|
- if (self.currentSignDNA != sign):
|
|
|
|
|
- self.currentSignDNA = sign
|
|
|
|
|
- self.signPanelSync()
|
|
|
|
|
-
|
|
|
|
|
- def findSignFromDNARoot(self):
|
|
|
|
|
- dnaRoot=self.levelEditor.selectedDNARoot
|
|
|
|
|
- if not dnaRoot:
|
|
|
|
|
- return
|
|
|
|
|
- objClass=DNAGetClassType(dnaRoot)
|
|
|
|
|
- if (objClass.eq(DNA_LANDMARK_BUILDING)
|
|
|
|
|
- or objClass.eq(DNA_PROP)):
|
|
|
|
|
- target=DNAGetChildRecursive(dnaRoot, DNA_SIGN)
|
|
|
|
|
- return target
|
|
|
|
|
-
|
|
|
|
|
- def selectSignBaseline(self, val):
|
|
|
|
|
- if not self.currentSignDNA:
|
|
|
|
|
- return
|
|
|
|
|
- # Temporarily undefine DNATarget (this will speed
|
|
|
|
|
- # up setting the values, because the callbacks won't
|
|
|
|
|
- # call self.levelEditor.replaceSelected() with each
|
|
|
|
|
- # setting):
|
|
|
|
|
- self.levelEditor.DNATarget=None
|
|
|
|
|
- self.currentBaselineDNA=None
|
|
|
|
|
- target=None
|
|
|
|
|
- index=self.currentBaselineIndex=int((self.baselineMenu.curselection())[0])
|
|
|
|
|
- if (index==0):
|
|
|
|
|
- target=self.currentSignDNA
|
|
|
|
|
- # Unset some ui elements:
|
|
|
|
|
- self.baselineString.set('')
|
|
|
|
|
- self.fontMenu.selectitem(0)
|
|
|
|
|
- self.addCurveFloater.set(0)
|
|
|
|
|
- self.addKernFloater.set(0)
|
|
|
|
|
- self.addWiggleFloater.set(0)
|
|
|
|
|
- self.addStumbleFloater.set(0)
|
|
|
|
|
- self.addStompFloater.set(0)
|
|
|
|
|
- self.bigFirstLetterIntVar.set(0)
|
|
|
|
|
- self.allCapsIntVar.set(0)
|
|
|
|
|
- self.dropShadowIntVar.set(0)
|
|
|
|
|
- else:
|
|
|
|
|
- target=DNAGetChild(self.currentSignDNA, DNA_SIGN_BASELINE, index-1)
|
|
|
|
|
- if target:
|
|
|
|
|
- # Update panel info:
|
|
|
|
|
- s = DNAGetBaselineString(target)
|
|
|
|
|
- self.baselineString.set(s)
|
|
|
|
|
- self.fontMenu.selectitem(target.getCode())
|
|
|
|
|
- try:
|
|
|
|
|
- val = 1.0/target.getWidth()
|
|
|
|
|
- except ZeroDivisionError:
|
|
|
|
|
- val = 0.0
|
|
|
|
|
- self.addCurveFloater.set(val)
|
|
|
|
|
- self.addKernFloater.set(target.getKern())
|
|
|
|
|
- self.addWiggleFloater.set(target.getWiggle())
|
|
|
|
|
- self.addStumbleFloater.set(target.getStumble())
|
|
|
|
|
- self.addStompFloater.set(target.getStomp())
|
|
|
|
|
- flags=target.getFlags()
|
|
|
|
|
- self.bigFirstLetterIntVar.set('b' in flags)
|
|
|
|
|
- self.allCapsIntVar.set('c' in flags)
|
|
|
|
|
- self.dropShadowIntVar.set('d' in flags)
|
|
|
|
|
-
|
|
|
|
|
- self.currentBaselineDNA=target
|
|
|
|
|
- if target:
|
|
|
|
|
- pos=target.getPos()
|
|
|
|
|
- self.addXFloater.set(pos[0])
|
|
|
|
|
- self.addZFloater.set(pos[2])
|
|
|
|
|
- scale=target.getScale()
|
|
|
|
|
- self.addScaleXFloater.set(scale[0])
|
|
|
|
|
- self.addScaleZFloater.set(scale[2])
|
|
|
|
|
- hpr=target.getHpr()
|
|
|
|
|
- self.addRollFloater.set(hpr[2])
|
|
|
|
|
-
|
|
|
|
|
- self.levelEditor.DNATarget=target
|
|
|
|
|
-
|
|
|
|
|
- def deleteSignItem(self):
|
|
|
|
|
- """Delete the selected sign or sign baseline"""
|
|
|
|
|
- if (self.currentBaselineDNA):
|
|
|
|
|
- # Remove the baseline:
|
|
|
|
|
- assert int((self.baselineMenu.curselection())[0]) == self.currentBaselineIndex
|
|
|
|
|
- DNARemoveChildOfClass(self.currentSignDNA, DNA_SIGN_BASELINE,
|
|
|
|
|
- self.currentBaselineIndex-1)
|
|
|
|
|
- self.baselineMenu.delete(self.currentBaselineIndex)
|
|
|
|
|
- self.baselineMenu.selectitem(0)
|
|
|
|
|
- self.currentBaselineIndex=0
|
|
|
|
|
- self.currentBaselineDNA=None
|
|
|
|
|
- self.selectSignBaseline(0)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
- elif (self.currentSignDNA):
|
|
|
|
|
- # Remove the sign:
|
|
|
|
|
- assert int((self.baselineMenu.curselection())[0]) == 0
|
|
|
|
|
- le = self.levelEditor
|
|
|
|
|
- le.removeSign(le.DNATarget, le.DNATargetParent)
|
|
|
|
|
- self.currentBaselineDNA=None
|
|
|
|
|
- self.currentSignDNA=None
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def signBaselineTrace(self, a, b, mode):
|
|
|
|
|
- #print self, a, b, mode, self.baselineString.get()
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- s = self.baselineString.get()
|
|
|
|
|
- self.setBaselineString(s)
|
|
|
|
|
-
|
|
|
|
|
- def addSignGraphic(self, code):
|
|
|
|
|
- """
|
|
|
|
|
- Create a new baseline with a graphic and
|
|
|
|
|
- add it to the current sign
|
|
|
|
|
- """
|
|
|
|
|
- sign=self.findSignFromDNARoot()
|
|
|
|
|
- if sign:
|
|
|
|
|
- graphic=DNASignGraphic()
|
|
|
|
|
- graphic.setCode(code)
|
|
|
|
|
- baseline=DNASignBaseline()
|
|
|
|
|
- baseline.add(graphic)
|
|
|
|
|
- sign.add(baseline)
|
|
|
|
|
- # Show the UI to the new baseline:
|
|
|
|
|
- self.levelEditor.DNATarget=baseline
|
|
|
|
|
- self.baselineMenu.insert(END, '['+code+']')
|
|
|
|
|
- current=self.baselineMenu.size()-1
|
|
|
|
|
- self.baselineMenu.selectitem(current)
|
|
|
|
|
- self.selectSignBaseline(current)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def addBaseline(self):
|
|
|
|
|
- sign=self.findSignFromDNARoot()
|
|
|
|
|
- if sign:
|
|
|
|
|
- baseline=DNASignBaseline()
|
|
|
|
|
- text="Zoo"
|
|
|
|
|
- DNASetBaselineString(baseline, text)
|
|
|
|
|
- sign.add(baseline)
|
|
|
|
|
- # Show the UI to the new baseline:
|
|
|
|
|
- self.levelEditor.DNATarget=baseline
|
|
|
|
|
- self.baselineMenu.insert(END, text)
|
|
|
|
|
- current=self.baselineMenu.size()-1
|
|
|
|
|
- self.baselineMenu.selectitem(current)
|
|
|
|
|
- self.selectSignBaseline(current)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def addBaselineItem(self):
|
|
|
|
|
- pass
|
|
|
|
|
-
|
|
|
|
|
- def selectSignBaselineItem(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- baseline.setCode(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineStyle(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline == None:
|
|
|
|
|
- print "\n\nbaseline == None"
|
|
|
|
|
- return #skyler: This isn't working yet.
|
|
|
|
|
- # As a workaround, select the baseline from the tk panel.
|
|
|
|
|
- # Try to find the first baseline in the sign:
|
|
|
|
|
- sign=self.findSignFromDNARoot()
|
|
|
|
|
- if sign:
|
|
|
|
|
- self.currentSignDNA = sign
|
|
|
|
|
- baseline=DNAGetChild(sign, DNA_SIGN_BASELINE)
|
|
|
|
|
- if baseline and val:
|
|
|
|
|
- self.levelEditor.DNATarget=baseline
|
|
|
|
|
- self.currentBaselineDNA=baseline
|
|
|
|
|
- settings=val
|
|
|
|
|
- self.levelEditor.replaceSelectedEnabled=0
|
|
|
|
|
-
|
|
|
|
|
- # Don't set string: self.baselineString.set('')
|
|
|
|
|
- if settings['curve'] != None:
|
|
|
|
|
- self.addCurveFloater.set(settings['curve'])
|
|
|
|
|
- if settings['kern'] != None:
|
|
|
|
|
- self.addKernFloater.set(settings['kern'])
|
|
|
|
|
- if settings['wiggle'] != None:
|
|
|
|
|
- self.addWiggleFloater.set(settings['wiggle'])
|
|
|
|
|
- if settings['stumble'] != None:
|
|
|
|
|
- self.addStumbleFloater.set(settings['stumble'])
|
|
|
|
|
- if settings['stomp'] != None:
|
|
|
|
|
- self.addStompFloater.set(settings['stomp'])
|
|
|
|
|
-
|
|
|
|
|
- flags=settings['flags']
|
|
|
|
|
- if flags != None:
|
|
|
|
|
- self.bigFirstLetterIntVar.set('b' in flags)
|
|
|
|
|
- self.setBigFirstLetter()
|
|
|
|
|
-
|
|
|
|
|
- self.allCapsIntVar.set('c' in flags)
|
|
|
|
|
- self.setAllCaps()
|
|
|
|
|
-
|
|
|
|
|
- self.dropShadowIntVar.set('d' in flags)
|
|
|
|
|
- self.setDropShadow()
|
|
|
|
|
-
|
|
|
|
|
- code = settings['code']
|
|
|
|
|
- if code != None:
|
|
|
|
|
- self.fontMenu.selectitem(code)
|
|
|
|
|
- self.setSignBaslineFont(code)
|
|
|
|
|
-
|
|
|
|
|
- if settings['x'] != None:
|
|
|
|
|
- self.addXFloater.set(settings['x'])
|
|
|
|
|
- if settings['z'] != None:
|
|
|
|
|
- self.addZFloater.set(settings['z'])
|
|
|
|
|
- if settings['scaleX'] != None:
|
|
|
|
|
- self.addScaleXFloater.set(settings['scaleX'])
|
|
|
|
|
- if settings['scaleZ'] != None:
|
|
|
|
|
- self.addScaleZFloater.set(settings['scaleZ'])
|
|
|
|
|
- if settings['roll'] != None:
|
|
|
|
|
- self.addRollFloater.set(settings['roll'])
|
|
|
|
|
-
|
|
|
|
|
- color = settings['color']
|
|
|
|
|
- if color != None:
|
|
|
|
|
- #self.updateSelectedObjColor(settings['color'])
|
|
|
|
|
- self.setCurrentColor(color)
|
|
|
|
|
- self.setResetColor(color)
|
|
|
|
|
- baseline.setColor(color)
|
|
|
|
|
-
|
|
|
|
|
- self.levelEditor.replaceSelectedEnabled=1
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- def setBaselineString(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- DNASetBaselineString(baseline, val)
|
|
|
|
|
- self.baselineMenu.delete(self.currentBaselineIndex)
|
|
|
|
|
- self.baselineMenu.insert(self.currentBaselineIndex, val)
|
|
|
|
|
- self.baselineMenu.selectitem(self.currentBaselineIndex)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def adjustBaselineFlag(self, newValue, flagChar):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- flags=baseline.getFlags()
|
|
|
|
|
- if newValue:
|
|
|
|
|
- if not flagChar in flags:
|
|
|
|
|
- # Add the flag:
|
|
|
|
|
- baseline.setFlags(flags+flagChar)
|
|
|
|
|
- elif flagChar in flags:
|
|
|
|
|
- # Remove the flag:
|
|
|
|
|
- flags=string.join(flags.split(flagChar), '')
|
|
|
|
|
- baseline.setFlags(flags)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setLandmarkSpecialType(self, type):
|
|
|
|
|
- self.landmarkSpecialType = type
|
|
|
|
|
- if self.levelEditor.lastLandmarkBuildingDNA:
|
|
|
|
|
- self.levelEditor.lastLandmarkBuildingDNA.setBuildingType(self.landmarkSpecialType)
|
|
|
|
|
-
|
|
|
|
|
- def setBigFirstLetter(self):
|
|
|
|
|
- self.adjustBaselineFlag(self.bigFirstLetterIntVar.get(), 'b')
|
|
|
|
|
-
|
|
|
|
|
- def setAllCaps(self):
|
|
|
|
|
- self.adjustBaselineFlag(self.allCapsIntVar.get(), 'c')
|
|
|
|
|
-
|
|
|
|
|
- def setDropShadow(self):
|
|
|
|
|
- self.adjustBaselineFlag(self.dropShadowIntVar.get(), 'd')
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaslineFont(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target and (DNAGetClassType(target).eq(DNA_SIGN_BASELINE)
|
|
|
|
|
- or DNAGetClassType(target).eq(DNA_SIGN_TEXT)):
|
|
|
|
|
- target.setCode(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineCurve(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- try:
|
|
|
|
|
- val=1.0/val
|
|
|
|
|
- except ZeroDivisionError:
|
|
|
|
|
- val=0.0
|
|
|
|
|
- baseline.setWidth(val)
|
|
|
|
|
- baseline.setHeight(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineKern(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- baseline.setKern(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineWiggle(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- baseline.setWiggle(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineStumble(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- baseline.setStumble(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setSignBaselineStomp(self, val):
|
|
|
|
|
- baseline=self.currentBaselineDNA
|
|
|
|
|
- if baseline:
|
|
|
|
|
- baseline.setStomp(val)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetX(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target:
|
|
|
|
|
- pos=target.getPos()
|
|
|
|
|
- pos=VBase3(val, pos[1], pos[2])
|
|
|
|
|
- target.setPos(pos)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetZ(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target:
|
|
|
|
|
- pos=target.getPos()
|
|
|
|
|
- pos=VBase3(pos[0], pos[1], val)
|
|
|
|
|
- target.setPos(pos)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetScaleX(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target:
|
|
|
|
|
- scale=target.getScale()
|
|
|
|
|
- scale=VBase3(val, scale[1], scale[2])
|
|
|
|
|
- target.setScale(scale)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetScaleZ(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target:
|
|
|
|
|
- scale=target.getScale()
|
|
|
|
|
- scale=VBase3(scale[0], scale[1], val)
|
|
|
|
|
- target.setScale(scale)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def setDNATargetRoll(self, val):
|
|
|
|
|
- target=self.levelEditor.DNATarget
|
|
|
|
|
- if target:
|
|
|
|
|
- hpr=target.getHpr()
|
|
|
|
|
- hpr=VBase3(hpr[0], hpr[1], val)
|
|
|
|
|
- target.setHpr(hpr)
|
|
|
|
|
- self.levelEditor.replaceSelected()
|
|
|
|
|
-
|
|
|
|
|
- def addLandmark(self):
|
|
|
|
|
- self.levelEditor.addLandmark(self.landmarkType, self.landmarkSpecialType)
|
|
|
|
|
-
|
|
|
|
|
- def setPropType(self, name):
|
|
|
|
|
- self.propType = name
|
|
|
|
|
- self.levelEditor.setCurrent('prop_texture', self.propType)
|
|
|
|
|
-
|
|
|
|
|
- def addProp(self):
|
|
|
|
|
- self.levelEditor.addProp(self.propType)
|
|
|
|
|
-
|
|
|
|
|
- def updateSelectedWallWidth(self, strVal):
|
|
|
|
|
- self.levelEditor.updateSelectedWallWidth(string.atof(strVal))
|
|
|
|
|
-
|
|
|
|
|
- def setCurrentColor(self, colorVec, fUpdate = 0):
|
|
|
|
|
- # Turn on/off update of selected before updating entry
|
|
|
|
|
- self.fUpdateSelected = fUpdate
|
|
|
|
|
- self.colorEntry.set([int(colorVec[0] * 255.0),
|
|
|
|
|
- int(colorVec[1] * 255.0),
|
|
|
|
|
- int(colorVec[2] * 255.0),
|
|
|
|
|
- 255])
|
|
|
|
|
-
|
|
|
|
|
- def setResetColor(self, colorVec):
|
|
|
|
|
- self.colorEntry['resetValue'] = (
|
|
|
|
|
- [int(colorVec[0] * 255.0),
|
|
|
|
|
- int(colorVec[1] * 255.0),
|
|
|
|
|
- int(colorVec[2] * 255.0),
|
|
|
|
|
- 255])
|
|
|
|
|
-
|
|
|
|
|
- def setSuitPointType(self, name):
|
|
|
|
|
- if (name == "street"):
|
|
|
|
|
- self.levelEditor.currentSuitPointType = DNASuitPoint.STREETPOINT
|
|
|
|
|
- elif (name == "front door"):
|
|
|
|
|
- self.levelEditor.currentSuitPointType = DNASuitPoint.FRONTDOORPOINT
|
|
|
|
|
- elif (name == "side door"):
|
|
|
|
|
- self.levelEditor.currentSuitPointType = DNASuitPoint.SIDEDOORPOINT
|
|
|
|
|
- print self.levelEditor.currentSuitPointType
|
|
|
|
|
-
|
|
|
|
|
- def setBattleCellType(self, name):
|
|
|
|
|
- self.levelEditor.currentBattleCellType = name
|
|
|
|
|
-
|
|
|
|
|
- def updateSelectedObjColor(self, color):
|
|
|
|
|
- try:
|
|
|
|
|
- obj = self.levelEditor.DNATarget
|
|
|
|
|
- if self.fUpdateSelected and (obj != None):
|
|
|
|
|
- objClass = DNAGetClassType(obj)
|
|
|
|
|
- if ((objClass.eq(DNA_WALL)) or
|
|
|
|
|
- (objClass.eq(DNA_WINDOWS)) or
|
|
|
|
|
- (objClass.eq(DNA_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_FLAT_DOOR)) or
|
|
|
|
|
- (objClass.eq(DNA_CORNICE)) or
|
|
|
|
|
- (objClass.eq(DNA_PROP)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_BASELINE)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_TEXT)) or
|
|
|
|
|
- (objClass.eq(DNA_SIGN_GRAPHIC))
|
|
|
|
|
- ):
|
|
|
|
|
- self.levelEditor.setDNATargetColor(
|
|
|
|
|
- VBase4((color[0]/255.0),
|
|
|
|
|
- (color[1]/255.0),
|
|
|
|
|
- (color[2]/255.0),
|
|
|
|
|
- 1.0))
|
|
|
|
|
- except AttributeError:
|
|
|
|
|
- pass
|
|
|
|
|
- # Default is to update selected
|
|
|
|
|
- self.fUpdateSelected = 1
|
|
|
|
|
-
|
|
|
|
|
- def toggleBalloon(self):
|
|
|
|
|
- if self.toggleBalloonVar.get():
|
|
|
|
|
- self.balloon.configure(state = 'balloon')
|
|
|
|
|
- else:
|
|
|
|
|
- self.balloon.configure(state = 'none')
|
|
|
|
|
-
|
|
|
|
|
-class VisGroupsEditor(Pmw.MegaToplevel):
|
|
|
|
|
- def __init__(self, levelEditor, visGroups = ['None'],
|
|
|
|
|
- parent = None, **kw):
|
|
|
|
|
-
|
|
|
|
|
- INITOPT = Pmw.INITOPT
|
|
|
|
|
- optiondefs = (
|
|
|
|
|
- ('title', 'Visability Groups Editor', None),
|
|
|
|
|
- )
|
|
|
|
|
- self.defineoptions(kw, optiondefs)
|
|
|
|
|
-
|
|
|
|
|
- Pmw.MegaToplevel.__init__(self, parent, title = self['title'])
|
|
|
|
|
-
|
|
|
|
|
- self.levelEditor = levelEditor
|
|
|
|
|
- self.visGroups = visGroups
|
|
|
|
|
- self.visGroupNames = map(lambda pair: pair[1].getName(),
|
|
|
|
|
- self.visGroups)
|
|
|
|
|
- # Initialize dictionary of visibility relationships
|
|
|
|
|
- self.visDict = {}
|
|
|
|
|
- # Group we are currently setting visGroups for
|
|
|
|
|
- self.target = None
|
|
|
|
|
- # Flag to enable/disable toggleVisGroup command
|
|
|
|
|
- self.fCommand = 1
|
|
|
|
|
-
|
|
|
|
|
- # Handle to the toplevels hull
|
|
|
|
|
- hull = self.component('hull')
|
|
|
|
|
-
|
|
|
|
|
- balloon = self.balloon = Pmw.Balloon(hull)
|
|
|
|
|
- # Start with balloon help disabled
|
|
|
|
|
- self.balloon.configure(state = 'none')
|
|
|
|
|
-
|
|
|
|
|
- menuFrame = Frame(hull, relief = GROOVE, bd = 2)
|
|
|
|
|
- menuFrame.pack(fill = X, expand = 1)
|
|
|
|
|
-
|
|
|
|
|
- menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon)
|
|
|
|
|
- menuBar.pack(side = LEFT, expand = 1, fill = X)
|
|
|
|
|
- menuBar.addmenu('Vis Groups Editor',
|
|
|
|
|
- 'Visability Groups Editor Operations')
|
|
|
|
|
- menuBar.addmenuitem('Vis Groups Editor', 'command',
|
|
|
|
|
- 'Exit Visability Groups Editor',
|
|
|
|
|
- label = 'Exit',
|
|
|
|
|
- command = self.preDestroy)
|
|
|
|
|
-
|
|
|
|
|
- menuBar.addmenu('Help', 'Visability Groups Editor Help Operations')
|
|
|
|
|
- self.toggleBalloonVar = IntVar()
|
|
|
|
|
- self.toggleBalloonVar.set(0)
|
|
|
|
|
- menuBar.addmenuitem('Help', 'checkbutton',
|
|
|
|
|
- 'Toggle balloon help',
|
|
|
|
|
- label = 'Balloon Help',
|
|
|
|
|
- variable = self.toggleBalloonVar,
|
|
|
|
|
- command = self.toggleBalloon)
|
|
|
|
|
-
|
|
|
|
|
- # Create a combo box to choose target vis group
|
|
|
|
|
- self.targetSelector = Pmw.ComboBox(
|
|
|
|
|
- hull, labelpos = W, label_text = 'Target Vis Group:',
|
|
|
|
|
- entry_width = 12, selectioncommand = self.selectVisGroup,
|
|
|
|
|
- scrolledlist_items = self.visGroupNames)
|
|
|
|
|
- self.targetSelector.selectitem(self.visGroupNames[0])
|
|
|
|
|
- self.targetSelector.pack(expand = 1, fill = X)
|
|
|
|
|
-
|
|
|
|
|
- # Scrolled frame to hold radio selector
|
|
|
|
|
- sf = Pmw.ScrolledFrame(hull, horizflex = 'elastic',
|
|
|
|
|
- usehullsize = 1, hull_width = 200,
|
|
|
|
|
- hull_height = 400)
|
|
|
|
|
- frame = sf.interior()
|
|
|
|
|
- sf.pack(padx=5, pady=3, fill = BOTH, expand = 1)
|
|
|
|
|
-
|
|
|
|
|
- # Add vis groups selector
|
|
|
|
|
- self.selected = Pmw.RadioSelect(frame, selectmode=MULTIPLE,
|
|
|
|
|
- orient = VERTICAL,
|
|
|
|
|
- pady = 0,
|
|
|
|
|
- command = self.toggleVisGroup)
|
|
|
|
|
- for groupInfo in self.visGroups:
|
|
|
|
|
- nodePath = groupInfo[0]
|
|
|
|
|
- group = groupInfo[1]
|
|
|
|
|
- name = group.getName()
|
|
|
|
|
- self.selected.add(name, width = 12)
|
|
|
|
|
- # Assemble list of groups visible from this group
|
|
|
|
|
- visible = []
|
|
|
|
|
- for i in range(group.getNumVisibles()):
|
|
|
|
|
- visible.append(group.getVisibleName(i))
|
|
|
|
|
- visible.sort()
|
|
|
|
|
- self.visDict[name] = [nodePath, group, visible]
|
|
|
|
|
- # Pack the widget
|
|
|
|
|
- self.selected.pack(expand = 1, fill = X)
|
|
|
|
|
- # And make sure scrolled frame is happy
|
|
|
|
|
- sf.reposition()
|
|
|
|
|
-
|
|
|
|
|
- buttonFrame = Frame(hull)
|
|
|
|
|
- buttonFrame.pack(fill=X, expand = 1)
|
|
|
|
|
-
|
|
|
|
|
- self.showMode = IntVar()
|
|
|
|
|
- self.showMode.set(0)
|
|
|
|
|
- self.showAllButton = Radiobutton(buttonFrame, text = 'Show All',
|
|
|
|
|
- value = 0, indicatoron = 1,
|
|
|
|
|
- variable = self.showMode,
|
|
|
|
|
- command = self.refreshVisibility)
|
|
|
|
|
- self.showAllButton.pack(side = LEFT, fill = X, expand = 1)
|
|
|
|
|
- self.showActiveButton = Radiobutton(buttonFrame, text = 'Show Target',
|
|
|
|
|
- value = 1, indicatoron = 1,
|
|
|
|
|
- variable = self.showMode,
|
|
|
|
|
- command = self.refreshVisibility)
|
|
|
|
|
- self.showActiveButton.pack(side = LEFT, fill = X, expand = 1)
|
|
|
|
|
-
|
|
|
|
|
- # Make sure input variables processed
|
|
|
|
|
- self.initialiseoptions(VisGroupsEditor)
|
|
|
|
|
-
|
|
|
|
|
- # Switch to current target's list
|
|
|
|
|
- self.selectVisGroup(self.visGroupNames[0])
|
|
|
|
|
-
|
|
|
|
|
- def selectVisGroup(self, target):
|
|
|
|
|
- print 'Setting vis options for group:', target
|
|
|
|
|
- # Record current target
|
|
|
|
|
- oldTarget = self.target
|
|
|
|
|
- # Record new target
|
|
|
|
|
- self.target = target
|
|
|
|
|
- # Deselect buttons from old target (first deactivating command)
|
|
|
|
|
- self.fCommand = 0
|
|
|
|
|
- if oldTarget:
|
|
|
|
|
- visList = self.visDict[oldTarget][2]
|
|
|
|
|
- for group in visList:
|
|
|
|
|
- self.selected.invoke(self.selected.index(group))
|
|
|
|
|
- # Now set buttons to reflect state of new target
|
|
|
|
|
- visList = self.visDict[target][2]
|
|
|
|
|
- for group in visList:
|
|
|
|
|
- self.selected.invoke(self.selected.index(group))
|
|
|
|
|
- # Reactivate command
|
|
|
|
|
- self.fCommand = 1
|
|
|
|
|
- # Update scene
|
|
|
|
|
- self.refreshVisibility()
|
|
|
|
|
-
|
|
|
|
|
- def toggleVisGroup(self, groupName, state):
|
|
|
|
|
- if self.fCommand:
|
|
|
|
|
- targetInfo = self.visDict[self.target]
|
|
|
|
|
- target = targetInfo[1]
|
|
|
|
|
- visList = targetInfo[2]
|
|
|
|
|
- groupNP = self.visDict[groupName][0]
|
|
|
|
|
- group = self.visDict[groupName][1]
|
|
|
|
|
- # MRM: Add change in visibility here
|
|
|
|
|
- # Show all vs. show active
|
|
|
|
|
- if state == 1:
|
|
|
|
|
- print 'Vis Group:', self.target, 'adding group:', groupName
|
|
|
|
|
- if groupName not in visList:
|
|
|
|
|
- visList.append(groupName)
|
|
|
|
|
- target.addVisible(groupName)
|
|
|
|
|
- # Update vis and color
|
|
|
|
|
- groupNP.show()
|
|
|
|
|
- groupNP.setColor(1, 0, 0, 1)
|
|
|
|
|
- else:
|
|
|
|
|
- print 'Vis Group:', self.target, 'removing group:', groupName
|
|
|
|
|
- if groupName in visList:
|
|
|
|
|
- visList.remove(groupName)
|
|
|
|
|
- target.removeVisible(groupName)
|
|
|
|
|
- # Update vis and color
|
|
|
|
|
- if self.showMode.get() == 1:
|
|
|
|
|
- groupNP.hide()
|
|
|
|
|
- groupNP.clearColor()
|
|
|
|
|
-
|
|
|
|
|
- def refreshVisibility(self):
|
|
|
|
|
- # Get current visibility list for target
|
|
|
|
|
- targetInfo = self.visDict[self.target]
|
|
|
|
|
- visList = targetInfo[2]
|
|
|
|
|
- for key in self.visDict.keys():
|
|
|
|
|
- groupNP = self.visDict[key][0]
|
|
|
|
|
- if key in visList:
|
|
|
|
|
- groupNP.show()
|
|
|
|
|
- if key == self.target:
|
|
|
|
|
- groupNP.setColor(0, 1, 0, 1)
|
|
|
|
|
- else:
|
|
|
|
|
- groupNP.setColor(1, 0, 0, 1)
|
|
|
|
|
- else:
|
|
|
|
|
- if self.showMode.get() == 0:
|
|
|
|
|
- groupNP.show()
|
|
|
|
|
- else:
|
|
|
|
|
- groupNP.hide()
|
|
|
|
|
- groupNP.clearColor()
|
|
|
|
|
-
|
|
|
|
|
- def preDestroy(self):
|
|
|
|
|
- # First clear level editor variable
|
|
|
|
|
- self.levelEditor.vgpanel = None
|
|
|
|
|
- self.destroy()
|
|
|
|
|
-
|
|
|
|
|
- def toggleBalloon(self):
|
|
|
|
|
- if self.toggleBalloonVar.get():
|
|
|
|
|
- self.balloon.configure(state = 'balloon')
|
|
|
|
|
- else:
|
|
|
|
|
- self.balloon.configure(state = 'none')
|
|
|
|
|
-
|
|
|
|
|
-# [gjeon] for LevelEditor specific Avatar
|
|
|
|
|
-class LEAvatar(LocalAvatar.LocalAvatar):
|
|
|
|
|
- def __init__(self, cr, chatMgr, chatAssistant, passMessagesThrough = False):
|
|
|
|
|
- LocalAvatar.LocalAvatar.__init__(self, cr, chatMgr, chatAssistant, passMessagesThrough)
|
|
|
|
|
-
|
|
|
|
|
- def getAutoRun(self):
|
|
|
|
|
- return 0
|
|
|
|
|
-
|
|
|
|
|
-base.l = LevelEditor()
|
|
|
|
|
-run()
|
|
|
|
|
-
|
|
|
|
|
|
|
+ # When you define your own LevelEditor class inheriting LevelEditorBase
|
|
|
|
|
+ # you should call self.initialize() at the end of __init__() function
|
|
|
|
|
+ self.initialize()
|