oldschool-toontown/toontown/coghq/DistributedInGameEditor.py

776 lines
29 KiB
Python
Raw Normal View History

2019-11-02 17:27:54 -05:00
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.showbase.PythonUtil import lineInfo, Functor
from direct.directnotify import DirectNotifyGlobal
from direct.distributed import DistributedObject
from otp.level import Level
from otp.level import LevelConstants
from otp.level import Entity
from otp.level import EditMgr
from .SpecImports import *
from .InGameEditorElements import *
2019-11-02 17:27:54 -05:00
from toontown.cogdominium import CogdoEntityCreator
import string
class InGameEditorEntityBase(InGameEditorElement):
def __init__(self):
InGameEditorElement.__init__(self)
def attribChanged(self, attrib, value):
Entity.Entity.attribChanged(self, attrib, value)
print('attribChange: %s %s, %s = %s' % (self.level.getEntityType(self.entId),
2019-11-02 17:27:54 -05:00
self.entId,
attrib,
repr(value)))
2019-11-02 17:27:54 -05:00
def getTypeName(self):
return self.level.getEntityType(self.entId)
def privGetNamePrefix(self):
return '[%s-%s] ' % (self.getTypeName(), self.entId)
def privGetEntityName(self):
return self.level.levelSpec.getEntitySpec(self.entId)['name']
def getName(self):
return '%s%s' % (self.privGetNamePrefix(), self.privGetEntityName())
def setNewName(self, newName):
prefix = self.privGetNamePrefix()
if newName[:len(prefix)] == prefix:
newName = newName[len(prefix):]
oldName = self.privGetEntityName()
if oldName != newName:
self.level.setAttribEdit(self.entId, 'name', newName)
def setParentEntId(self, parentEntId):
self.parentEntId = parentEntId
self.level.buildEntityTree()
def setName(self, name):
self.name = name
self.level.buildEntityTree()
class InGameEditorEntity(Entity.Entity, InGameEditorEntityBase):
def __init__(self, level, entId):
Entity.Entity.__init__(self, level, entId)
InGameEditorEntityBase.__init__(self)
def id(self):
return self.entId
def destroy(self):
Entity.Entity.destroy(self)
class InGameEditorEditMgr(EditMgr.EditMgr, InGameEditorEntityBase):
def __init__(self, level, entId):
EditMgr.EditMgr.__init__(self, level, entId)
InGameEditorEntityBase.__init__(self)
def destroy(self):
EditMgr.EditMgr.destroy(self)
class AttribModifier(Entity.Entity, InGameEditorEntityBase):
notify = DirectNotifyGlobal.directNotify.newCategory('AttribModifier')
def __init__(self, level, entId):
Entity.Entity.__init__(self, level, entId)
InGameEditorEntityBase.__init__(self)
def destroy(self):
Entity.Entity.destroy(self)
def setValue(self, value):
if len(self.typeName) == 0:
AttribModifier.notify.warning('no typeName set')
return
entTypeReg = self.level.entTypeReg
if self.typeName not in entTypeReg.getAllTypeNames():
AttribModifier.notify.warning('invalid typeName: %s' % self.typeName)
return
typeDesc = entTypeReg.getTypeDesc(self.typeName)
if len(self.attribName) == 0:
AttribModifier.notify.warning('no attribName set')
return
if self.attribName not in typeDesc.getAttribNames():
AttribModifier.notify.warning('invalid attribName: %s' % self.attribName)
return
if len(value) == 0:
AttribModifier.notify.warning('no value set')
def setAttrib(entId, typeName = self.typeName, attribName = self.attribName, value = eval(value), recursive = self.recursive):
if typeName == self.level.getEntityType(entId):
self.level.setAttribEdit(entId, attribName, value)
if recursive:
entity = self.level.getEntity(entId)
for child in entity.getChildren():
setAttrib(child.entId)
setAttrib(self.parentEntId)
def getInGameEditorEntityCreatorClass(level):
entCreator = level.createEntityCreator()
EntCreatorClass = entCreator.__class__
class InGameEditorEntityCreator(EntCreatorClass):
def __init__(self, editor):
EntCreatorClass.__init__(self, editor)
entTypes = list(self.entType2Ctor.keys())
2019-11-02 17:27:54 -05:00
for type in entTypes:
self.entType2Ctor[type] = InGameEditorEntity
self.entType2Ctor['editMgr'] = InGameEditorEditMgr
self.entType2Ctor['attribModifier'] = AttribModifier
return InGameEditorEntityCreator
class DistributedInGameEditor(DistributedObject.DistributedObject, Level.Level, InGameEditorElement):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedInGameEditor')
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
Level.Level.__init__(self)
InGameEditorElement.__init__(self)
self.editorInitialized = 0
self.specModified = 0
self.undoStack = []
self.redoStack = []
self.entCreateHandlerQ = []
self.entitiesWeCreated = []
self.nodePathId2EntId = {}
def generate(self):
self.notify.debug('generate')
DistributedObject.DistributedObject.generate(self)
base.inGameEditor = self
def setEditorAvId(self, editorAvId):
self.editorAvId = editorAvId
def setEditUsername(self, editUsername):
self.editUsername = editUsername
def getEditUsername(self):
return self.editUsername
def setLevelDoId(self, levelDoId):
self.levelDoId = levelDoId
self.level = base.cr.doId2do[self.levelDoId]
def getLevelDoId(self):
return self.levelDoId
def announceGenerate(self):
self.notify.debug('announceGenerate')
DistributedObject.DistributedObject.announceGenerate(self)
if self.editorIsLocalToon():
from otp.level import EditorGlobals
EditorGlobals.assertReadyToEdit()
self.notify.debug('requesting an up-to-date copy of the level spec')
self.sendUpdate('requestCurrentLevelSpec')
def setSpecSenderDoId(self, doId):
DistributedInGameEditor.notify.debug('setSpecSenderDoId: %s' % doId)
blobSender = base.cr.doId2do[doId]
def setSpecBlob(specBlob, blobSender = blobSender, self = self):
blobSender.sendAck()
from otp.level.LevelSpec import LevelSpec
curSpec = eval(specBlob)
self.gotCurrentSpec(curSpec)
if blobSender.isComplete():
setSpecBlob(blobSender.getBlob())
else:
evtName = self.uniqueName('specDone')
blobSender.setDoneEvent(evtName)
self.acceptOnce(evtName, setSpecBlob)
def gotCurrentSpec(self, curSpec):
self.entTypeReg = self.level.getEntityTypeReg()
curSpec.setEntityTypeReg(self.entTypeReg)
self.axis = loader.loadModel('models/misc/xyzAxis.bam')
self.axis.setColorOff()
self.axis.setColorScale(1, 1, 1, 1, 1)
self.initializeLevel(self.doId, curSpec, curSpec.getScenario())
entCreator = self.level.createEntityCreator()
self.entTypes = entCreator.getEntityTypes()
self.selectedEntity = None
base.startTk()
from . import InGameEditor
2019-11-02 17:27:54 -05:00
doneEvent = self.uniqueName('editorDone')
saveAsEvent = self.uniqueName('saveSpec')
requestSaveEvent = self.uniqueName('requestSpecSave')
undoEvent = self.uniqueName('undoEvent')
redoEvent = self.uniqueName('redoEvent')
wireframeEvent = self.uniqueName('wireframeEvent')
oobeEvent = self.uniqueName('oobeEvent')
csEvent = self.uniqueName('csEvent')
runEvent = self.uniqueName('runEvent')
texEvent = self.uniqueName('texEvent')
self.editor = InGameEditor.InGameEditor(level=self, doneEvent=doneEvent, requestSaveEvent=requestSaveEvent, saveAsEvent=saveAsEvent, undoEvent=undoEvent, redoEvent=redoEvent, wireframeEvent=wireframeEvent, oobeEvent=oobeEvent, csEvent=csEvent, runEvent=runEvent, texEvent=texEvent)
self.acceptOnce(doneEvent, self.doneEditing)
self.accept(saveAsEvent, self.saveSpec)
self.accept(requestSaveEvent, self.requestSpecSave)
self.accept(undoEvent, self.doUndo)
self.accept(redoEvent, self.doRedo)
self.accept(wireframeEvent, self.doWireframe)
self.accept(oobeEvent, self.doOobe)
self.accept(csEvent, self.doCs)
self.accept(runEvent, self.doRun)
self.accept(texEvent, self.doTex)
self.accept(self.editor.getEventMsgName('Select'), self.handleEntitySelect)
self.accept(self.editor.getEventMsgName('Flash'), self.handleEntitySelect)
self.editorInitialized = 1
self.buildEntityTree()
return
def editorIsLocalToon(self):
return self.editorAvId == base.localAvatar.doId
def createEntityCreator(self):
return getInGameEditorEntityCreatorClass(self.level)(self)
def doneEditing(self):
self.notify.debug('doneEditing')
if self.specModified:
if self.editor.askYesNo('Save the spec on the AI?'):
self.requestSpecSave()
self.sendUpdate('setFinished')
def disable(self):
self.notify.debug('disable')
if self.editorInitialized and self.editorIsLocalToon():
self.axis.removeNode()
del self.axis
if hasattr(self, 'entTypeReg'):
del self.entTypeReg
self.editorInitialized = 0
Level.Level.destroyLevel(self)
if hasattr(self, 'editor'):
self.editor.quit()
del self.editor
DistributedObject.DistributedObject.disable(self)
self.ignoreAll()
def getEntInstance(self, entId):
return self.level.getEntity(entId)
def getEntInstanceNP(self, entId):
entity = self.getEntInstance(entId)
if entity is None:
return
if isinstance(entity, NodePath):
return entity
if hasattr(entity, 'getNodePath'):
return entity.getNodePath()
return
def getEntInstanceNPCopy(self, entId):
np = self.getEntInstanceNP(entId)
if np is None:
return np
stashNodeGroups = []
searches = ('**/+ActorNode', '**/+Character')
for search in searches:
stashNodeGroups.append(np.findAllMatches(search))
for group in stashNodeGroups:
if not group.isEmpty():
group.stash()
par = np.getParent()
copy = np.copyTo(par)
for group in stashNodeGroups:
if not group.isEmpty():
group.unstash()
return copy
def saveSpec(self, filename):
return self.levelSpec.saveToDisk(filename)
def setEntityParent(self, entity, parent):
parent.addChild(entity)
entity._parentEntity = parent
def insertEntityIntoTree(self, entId):
ent = self.getEntity(entId)
if entId == LevelConstants.UberZoneEntId:
self.setEntityParent(ent, self)
return
parentEnt = self.getEntity(ent.parentEntId)
if parentEnt is not None:
self.setEntityParent(ent, parentEnt)
return
self.setEntityParent(ent, self.uberZoneEntity)
return
def buildEntityTree(self):
self.setChildren([])
entIds = list(self.entities.keys())
2019-11-02 17:27:54 -05:00
entIds.sort()
for entId in entIds:
ent = self.getEntity(entId)
ent.setChildren([])
for entId in entIds:
self.insertEntityIntoTree(entId)
self.editor.refreshExplorer()
def onEntityCreate(self, entId):
DistributedInGameEditor.notify.debug('onEntityCreate %s' % entId)
Level.Level.onEntityCreate(self, entId)
entityNP = self.getEntInstanceNP(entId)
if entityNP:
self.nodePathId2EntId[entityNP.id()] = entId
if not self.editorInitialized:
return
self.insertEntityIntoTree(entId)
self.editor.refreshExplorer()
if entId == self.entitiesWeCreated[0]:
self.entitiesWeCreated = self.entitiesWeCreated[1:]
self.editor.selectEntity(entId)
def onEntityDestroy(self, entId):
DistributedInGameEditor.notify.debug('onEntityDestroy %s' % entId)
ent = self.getEntity(entId)
if self.editorInitialized:
entityNP = self.getEntInstanceNP(entId)
if entityNP in self.nodePathId2EntId:
del self.nodePathId2EntId[entityNP.id()]
if ent is self.selectedEntity:
self.editor.clearAttribEditPane()
self.selectedEntity = None
ent._parentEntity.removeChild(ent)
del ent._parentEntity
self.editor.refreshExplorer()
Level.Level.onEntityDestroy(self, entId)
return
def handleEntitySelect(self, entity):
self.selectedEntity = entity
if hasattr(self, 'identifyIval'):
self.identifyIval.finish()
if entity is self:
self.editor.clearAttribEditPane()
else:
entityNP = self.getEntInstanceNP(entity.entId)
if entityNP is not None:
dur = float(0.5)
oColor = entityNP.getColorScale()
flashIval = Sequence(Func(Functor(entityNP.setColorScale, 1, 0, 0, 1)), WaitInterval(dur / 3), Func(Functor(entityNP.setColorScale, 0, 1, 0, 1)), WaitInterval(dur / 3), Func(Functor(entityNP.setColorScale, 0, 0, 1, 1)), WaitInterval(dur / 3), Func(Functor(entityNP.setColorScale, oColor[0], oColor[1], oColor[2], oColor[3])))
boundIval = Sequence(Func(entityNP.showBounds), WaitInterval(dur * 0.5), Func(entityNP.hideBounds))
entCp = self.getEntInstanceNPCopy(entity.entId)
entCp.setRenderModeWireframe()
entCp.setTextureOff(1)
wireIval = Sequence(Func(Functor(entCp.setColor, 1, 0, 0, 1, 1)), WaitInterval(dur / 3), Func(Functor(entCp.setColor, 0, 1, 0, 1, 1)), WaitInterval(dur / 3), Func(Functor(entCp.setColor, 0, 0, 1, 1, 1)), WaitInterval(dur / 3), Func(entCp.removeNode))
self.identifyIval = Parallel(flashIval, boundIval, wireIval)
def putAxis(self = self, entityNP = entityNP):
self.axis.reparentTo(entityNP)
self.axis.setPos(0, 0, 0)
self.axis.setHpr(0, 0, 0)
def takeAxis(self = self):
self.axis.reparentTo(hidden)
self.identifyIval = Sequence(Func(putAxis), Parallel(self.identifyIval, WaitInterval(1000.5)), Func(takeAxis))
self.identifyIval.start()
self.editor.updateAttribEditPane(entity.entId, self.levelSpec, self.entTypeReg)
entType = self.getEntityType(entity.entId)
menu = self.editor.menuBar.component('Entity-menu')
index = menu.index('Remove Selected Entity')
if entType in self.entTypeReg.getPermanentTypeNames():
menu.entryconfigure(index, state='disabled')
else:
menu.entryconfigure(index, state='normal')
return
def privSendAttribEdit(self, entId, attrib, value):
self.specModified = 1
valueStr = repr(value)
self.notify.debug("sending edit: %s: '%s' = %s" % (entId, attrib, valueStr))
self.sendUpdate('setEdit', [entId,
attrib,
valueStr,
self.editUsername])
def privExecActionList(self, actions):
for action in actions:
if callable(action):
action()
else:
entId, attrib, value = action
self.privSendAttribEdit(entId, attrib, value)
def setUndoableAttribEdit(self, old2new, new2old):
self.redoStack = []
self.undoStack.append((new2old, old2new))
self.privExecActionList(old2new)
def setAttribEdit(self, entId, attrib, value, canUndo = 1):
oldValue = eval(repr(self.levelSpec.getEntitySpec(entId)[attrib]))
new2old = [(entId, attrib, oldValue)]
old2new = [(entId, attrib, value)]
self.setUndoableAttribEdit(old2new, new2old)
if not canUndo:
self.undoStack = []
def doUndo(self):
if len(self.undoStack) == 0:
self.editor.showWarning('Nothing left to undo')
return
undo = self.undoStack.pop()
self.redoStack.append(undo)
new2old, old2new = undo
self.privExecActionList(new2old)
def doRedo(self):
if len(self.redoStack) == 0:
self.editor.showWarning('Nothing to redo')
return
redo = self.redoStack.pop()
self.undoStack.append(redo)
new2old, old2new = redo
self.privExecActionList(old2new)
def doWireframe(self):
messenger.send('magicWord', ['~wire'])
def doOobe(self):
messenger.send('magicWord', ['~oobe'])
def doCs(self):
messenger.send('magicWord', ['~cs'])
def doRun(self):
messenger.send('magicWord', ['~run'])
def doTex(self):
messenger.send('magicWord', ['~tex'])
def insertEntity(self, entType, parentEntId = None, callback = None):
if parentEntId is None:
try:
parentEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid parent entity first.', 'error')
return
removeAction = (self.editMgrEntity.entId, 'removeEntity', {'entId': 'REPLACEME'})
new2old = [removeAction]
def setNewEntityId(entId, self = self, action = removeAction, callback = callback):
action[2]['entId'] = entId
if callback:
callback(entId)
def setEntCreateHandler(self = self, handler = setNewEntityId):
self.entCreateHandlerQ.append(handler)
old2new = [setEntCreateHandler, (self.editMgrEntity.entId, 'requestNewEntity', {'entType': entType,
'parentEntId': parentEntId,
'username': self.editUsername})]
self.setUndoableAttribEdit(old2new, new2old)
return
def setEntityCreatorUsername(self, entId, editUsername):
Level.Level.setEntityCreatorUsername(self, entId, editUsername)
if editUsername == self.getEditUsername():
print('entity %s about to be created; we requested it' % entId)
2019-11-02 17:27:54 -05:00
callback = self.entCreateHandlerQ[0]
del self.entCreateHandlerQ[:1]
callback(entId)
self.entitiesWeCreated.append(entId)
def removeSelectedEntity(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity to be removed first.', 'error')
return -1
if self.getEntity(selectedEntId).getNumChildren() > 0:
self.editor.showWarning('Remove children first.')
return -1
self.doRemoveEntity(selectedEntId)
def removeSelectedEntityTree(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity to be removed first.', 'error')
return -1
def removeEntity(entId):
entity = self.getEntity(entId)
for child in entity.getChildren():
removeEntity(child.entId)
self.doRemoveEntity(entId)
removeEntity(selectedEntId)
def doRemoveEntity(self, entId):
parentEntId = self.getEntity(entId)._parentEntity.entId
entType = self.getEntityType(entId)
if entType in self.entTypeReg.getPermanentTypeNames():
self.editor.showWarning("Cannot remove entities of type '%s'" % entType)
return
removeAction = (self.editMgrEntity.entId, 'removeEntity', {'entId': entId})
old2new = [removeAction]
oldAttribs = []
spec = self.levelSpec.getEntitySpecCopy(entId)
del spec['type']
for attrib, value in list(spec.items()):
2019-11-02 17:27:54 -05:00
oldAttribs.append((attrib, value))
def setNewEntityId(entId, self = self, removeAction = removeAction, oldAttribs = oldAttribs):
removeAction[2]['entId'] = entId
for attrib, value in list(spec.items()):
2019-11-02 17:27:54 -05:00
self.privSendAttribEdit(entId, attrib, value)
def setEntCreateHandler(self = self, handler = setNewEntityId):
self.entCreateHandlerQ.append(handler)
new2old = [setEntCreateHandler, (self.editMgrEntity.entId, 'requestNewEntity', {'entType': self.getEntityType(entId),
'parentEntId': parentEntId,
'username': self.editUsername})]
self.setUndoableAttribEdit(old2new, new2old)
def makeCopyOfEntName(self, name):
prefix = 'copy of '
suffix = ' (%s)'
oldName = name
if len(oldName) <= len(prefix):
newName = prefix + oldName
elif oldName[:len(prefix)] != prefix:
newName = prefix + oldName
else:
hasSuffix = True
copyNum = 2
if oldName[-1] != ')':
hasSuffix = False
if hasSuffix and oldName[-2] in string.digits:
i = len(oldName) - 2
numString = ''
while oldName[i] in string.digits:
numString = oldName[i] + numString
i -= 1
if oldName[i] != '(':
hasSuffix = False
else:
i -= 1
if oldName[i] != ' ':
hasSuffix = False
else:
print('numString: %s' % numString)
2019-11-02 17:27:54 -05:00
copyNum = int(numString) + 1
if hasSuffix:
newName = oldName[:i] + suffix % copyNum
else:
newName = oldName + suffix % copyNum
return newName
def duplicateSelectedEntity(self):
try:
selectedEntId = self.selectedEntity.entId
parentEntId = self.selectedEntity._parentEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity to be removed first.', 'error')
return
if self.selectedEntity.getNumChildren() > 0:
self.editor.showTodo('Cannot duplicate entity with children.')
return
removeAction = (self.editMgrEntity.entId, 'removeEntity', {'entId': selectedEntId})
new2old = [removeAction]
copyAttribs = self.levelSpec.getEntitySpecCopy(selectedEntId)
copyAttribs['comment'] = ''
copyAttribs['name'] = self.makeCopyOfEntName(copyAttribs['name'])
typeDesc = self.entTypeReg.getTypeDesc(copyAttribs['type'])
attribDescs = typeDesc.getAttribDescDict()
for attribName, attribDesc in list(attribDescs.items()):
2019-11-02 17:27:54 -05:00
if attribDesc.getDatatype() == 'const':
del copyAttribs[attribName]
def setNewEntityId(entId, self = self, removeAction = removeAction, copyAttribs = copyAttribs):
removeAction[2]['entId'] = entId
for attribName, value in list(copyAttribs.items()):
2019-11-02 17:27:54 -05:00
self.privSendAttribEdit(entId, attribName, value)
def setEntCreateHandler(self = self, handler = setNewEntityId):
self.entCreateHandlerQ.append(handler)
old2new = [setEntCreateHandler, (self.editMgrEntity.entId, 'requestNewEntity', {'entType': self.getEntityType(selectedEntId),
'parentEntId': parentEntId,
'username': self.editUsername})]
self.setUndoableAttribEdit(old2new, new2old)
def specPrePickle(self, spec):
for attribName, value in list(spec.items()):
2019-11-02 17:27:54 -05:00
spec[attribName] = repr(value)
return spec
def specPostUnpickle(self, spec):
for attribName, value in list(spec.items()):
2019-11-02 17:27:54 -05:00
spec[attribName] = eval(value)
return spec
def handleImportEntities(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity first.', 'error')
return
import tkinter.filedialog
filename = tkinter.filedialog.askopenfilename(parent=self.editor.parent, defaultextension='.egroup', filetypes=[('Entity Group', '.egroup'), ('All Files', '*')])
2019-11-02 17:27:54 -05:00
if len(filename) == 0:
return
try:
import pickle
f = open(filename, 'r')
eTree = pickle.load(f)
eGroup = pickle.load(f)
for entId, spec in list(eGroup.items()):
2019-11-02 17:27:54 -05:00
eGroup[entId] = self.specPostUnpickle(spec)
except:
self.editor.showWarning("Error importing entity group from '%s'." % filename, 'error')
return
oldEntId2new = {}
def addEntities(treeEntry, parentEntId, eGroup = eGroup):
for entId, children in list(treeEntry.items()):
2019-11-02 17:27:54 -05:00
spec = eGroup[entId]
entType = spec['type']
del spec['type']
del spec['parentEntId']
typeDesc = self.entTypeReg.getTypeDesc(entType)
for attribName, attribDesc in list(typeDesc.getAttribDescDict().items()):
2019-11-02 17:27:54 -05:00
if attribDesc.getDatatype() == 'const':
if attribName in spec:
del spec[attribName]
def handleEntityInsertComplete(newEntId, oldEntId = entId, oldEntId2new = oldEntId2new, spec = spec, treeEntry = treeEntry, addEntities = addEntities):
oldEntId2new[oldEntId] = newEntId
def assignAttribs(entId = newEntId, oldEntId = oldEntId, spec = spec, treeEntry = treeEntry):
for attribName in spec:
self.setAttribEdit(entId, attribName, spec[attribName])
addEntities(treeEntry[oldEntId], newEntId)
self.acceptOnce(self.getEntityCreateEvent(newEntId), assignAttribs)
self.insertEntity(entType, parentEntId=parentEntId, callback=handleEntityInsertComplete)
addEntities(eTree, selectedEntId)
def handleExportEntity(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity first.', 'error')
return
import tkinter.filedialog
filename = tkinter.filedialog.asksaveasfilename(parent=self.editor.parent, defaultextension='.egroup', filetypes=[('Entity Group', '.egroup'), ('All Files', '*')])
2019-11-02 17:27:54 -05:00
if len(filename) == 0:
return
eTree = {selectedEntId: {}}
eGroup = {}
eGroup[selectedEntId] = self.levelSpec.getEntitySpecCopy(selectedEntId)
for entId, spec in list(eGroup.items()):
2019-11-02 17:27:54 -05:00
eGroup[entId] = self.specPrePickle(spec)
try:
import pickle
f = open(filename, 'w')
pickle.dump(eTree, f)
pickle.dump(eGroup, f)
except:
self.editor.showWarning("Error exporting entity group to '%s'." % filename, 'error')
return
def handleExportEntityTree(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity first.', 'error')
return
import tkinter.filedialog
filename = tkinter.filedialog.asksaveasfilename(parent=self.editor.parent, defaultextension='.egroup', filetypes=[('Entity Group', '.egroup'), ('All Files', '*')])
2019-11-02 17:27:54 -05:00
if len(filename) == 0:
return
eTree = {}
eGroup = {}
def addEntity(entId, treeEntry):
treeEntry[entId] = {}
eGroup[entId] = self.levelSpec.getEntitySpecCopy(entId)
entity = self.getEntity(entId)
for child in entity.getChildren():
addEntity(child.entId, treeEntry[entId])
addEntity(selectedEntId, eTree)
for entId, spec in list(eGroup.items()):
2019-11-02 17:27:54 -05:00
eGroup[entId] = self.specPrePickle(spec)
try:
import pickle
f = open(filename, 'w')
pickle.dump(eTree, f)
pickle.dump(eGroup, f)
except:
self.editor.showWarning("Error exporting entity group to '%s'." % filename, 'error')
return
def moveAvToSelected(self):
try:
selectedEntId = self.selectedEntity.entId
except AttributeError:
self.editor.showWarning('Please select a valid entity first.', 'error')
return
entNp = self.getEntInstanceNP(selectedEntId)
if entNp is None:
zoneEntId = self.levelSpec.getEntityZoneEntId(selectedEntId)
entNp = self.getEntInstanceNP(zoneEntId)
base.localAvatar.setPos(entNp, 0, 0, 0)
base.localAvatar.setHpr(entNp, 0, 0, 0)
zoneNum = self.getEntityZoneEntId(selectedEntId)
self.level.enterZone(zoneNum)
return
def requestSpecSave(self):
self.privSendAttribEdit(LevelConstants.EditMgrEntId, 'requestSave', None)
self.specModified = 0
return
def setAttribChange(self, entId, attrib, valueStr, username):
if username == self.editUsername:
print('we got our own edit back!')
2019-11-02 17:27:54 -05:00
value = eval(valueStr)
self.levelSpec.setAttribChange(entId, attrib, value, username)
def getTypeName(self):
return 'Level'