Poodletooth-iLand/toontown/estate/DistributedCloset.py

493 lines
21 KiB
Python

from direct.gui.DirectGui import *
from panda3d.core import *
from toontown.toonbase.ToontownGlobals import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.interval.IntervalGlobal import *
from direct.distributed.ClockDelta import *
from toontown.toonbase import ToontownGlobals
from direct.showbase import DirectObject
from toontown.toon import ToonDNA
from direct.fsm import ClassicFSM, State, StateData
import ClosetGUI
from direct.task.Task import Task
import ClosetGlobals
import DistributedFurnitureItem
from toontown.toonbase import TTLocalizer
from toontown.catalog import CatalogFurnitureItem
class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem):
notify = directNotify.newCategory('DistributedCloset')
def __init__(self, cr):
DistributedFurnitureItem.DistributedFurnitureItem.__init__(self, cr)
self.notify.debug('__init__')
self.lastAvId = 0
self.hasLocalAvatar = 0
self.lastTime = 0
self.av = None
self.closetGUI = None
self.closetModel = None
self.closetSphere = None
self.closetSphereNode = None
self.closetSphereNodePath = None
self.topList = []
self.botList = []
self.oldTopList = []
self.oldBotList = []
self.oldStyle = None
self.button = None
self.topTrashButton = None
self.bottomTrashButton = None
self.isLocalToon = None
self.popupInfo = None
self.isOwner = 0
self.ownerId = 0
self.customerId = 0
self.purchaseDoneEvent = ''
self.swapEvent = ''
self.locked = 0
self.gender = None
self.topDeleted = 0
self.bottomDeleted = 0
self.closetTrack = None
self.avMoveTrack = None
self.scale = 1.0
self.fsm = ClassicFSM.ClassicFSM('Closet', [State.State('off', self.enterOff, self.exitOff, ['ready', 'open', 'closed']),
State.State('ready', self.enterReady, self.exitReady, ['open', 'closed']),
State.State('closed', self.enterClosed, self.exitClosed, ['open', 'off']),
State.State('open', self.enterOpen, self.exitOpen, ['closed', 'off'])], 'off', 'off')
self.fsm.enterInitialState()
return
def generate(self):
DistributedFurnitureItem.DistributedFurnitureItem.generate(self)
def announceGenerate(self):
self.notify.debug('announceGenerate')
DistributedFurnitureItem.DistributedFurnitureItem.announceGenerate(self)
self.load()
self.setupCollisionSphere()
self.fsm.request('ready')
def load(self):
self.setTwoSided(1)
lNode = self.find('**/door_rotate_L')
lDoor = self.find('**/closetdoor_L')
if lNode.isEmpty() or lDoor.isEmpty():
self.leftDoor = None
else:
lDoor.wrtReparentTo(lNode)
self.leftDoor = lNode
rNode = self.find('**/door_rotate_R')
rDoor = self.find('**/closetdoor_R')
if rNode.isEmpty() or rDoor.isEmpty():
self.rightDoor = None
else:
rDoor.wrtReparentTo(rNode)
self.rightDoor = rNode
if not lNode.isEmpty():
self.scale = lNode.getScale()[0]
return
def setupCollisionSphere(self):
if self.ownerId:
self.closetSphereEvent = self.uniqueName('closetSphere')
self.closetSphereEnterEvent = 'enter' + self.closetSphereEvent
self.closetSphere = CollisionSphere(0, 0, 0, self.scale * 2.125)
self.closetSphere.setTangible(0)
self.closetSphereNode = CollisionNode(self.closetSphereEvent)
self.closetSphereNode.setIntoCollideMask(WallBitmask)
self.closetSphereNode.addSolid(self.closetSphere)
self.closetSphereNodePath = self.attachNewNode(self.closetSphereNode)
def disable(self):
self.notify.debug('disable')
self.ignore(self.closetSphereEnterEvent)
self.ignoreAll()
taskMgr.remove(self.uniqueName('popupChangeClothesGUI'))
taskMgr.remove(self.uniqueName('lerpCamera'))
taskMgr.remove(self.uniqueName('lerpToon'))
if self.closetTrack:
self.closetTrack.finish()
self.closetTrack = None
if self.closetGUI:
self.closetGUI.resetClothes(self.oldStyle)
self.resetCloset()
if self.hasLocalAvatar:
self.freeAvatar()
self.ignoreAll()
DistributedFurnitureItem.DistributedFurnitureItem.disable(self)
return
def delete(self):
self.notify.debug('delete')
DistributedFurnitureItem.DistributedFurnitureItem.delete(self)
if self.popupInfo:
self.popupInfo.destroy()
self.popupInfo = None
if self.av:
del self.av
del self.gender
del self.closetSphere
del self.closetSphereNode
del self.closetSphereNodePath
del self.closetGUI
del self.fsm
return
def enterOff(self):
pass
def exitOff(self):
pass
def enterReady(self):
if self.ownerId:
self.accept(self.closetSphereEnterEvent, self.handleEnterSphere)
def exitReady(self):
pass
def enterOpen(self):
if self.ownerId:
self.ignore(self.closetSphereEnterEvent)
self._openDoors()
if self.customerId == base.localAvatar.doId:
camera.wrtReparentTo(self)
camera.posQuatInterval(1, (-7.58, -6.02, 6.9), (286.3, 336.8, 0), other=self, blendType='easeOut').start()
camera.setPosHpr(self, -7.58, -6.02, 6.9, 286.3, 336.8, 0)
if self.av:
if self.avMoveTrack:
self.avMoveTrack.finish()
self.av.stopSmooth()
self.avMoveTrack = Sequence(Parallel(Func(self.av.play, 'walk'), LerpPosHprInterval(nodePath=self.av, other=self, duration=1.0, pos=Vec3(1.67, -3.29, 0.025), hpr=Vec3(112, 0, 0), blendType='easeOut')), Func(self.av.loop, 'neutral'), Func(self.av.startSmooth))
self.avMoveTrack.start()
def exitOpen(self):
if self.ownerId:
self._closeDoors()
def enterClosed(self):
if self.ownerId:
self.accept(self.closetSphereEnterEvent, self.handleEnterSphere)
def exitClosed(self):
pass
def handleEnterSphere(self, collEntry):
if self.smoothStarted:
return
if base.localAvatar.doId == self.lastAvId and globalClock.getFrameTime() <= self.lastTime + 0.5:
self.notify.info('Ignoring duplicate entry for avatar.')
return
if self.hasLocalAvatar:
self.freeAvatar()
self.notify.debug('Entering Closet Sphere....%s' % self.closetSphereEnterEvent)
if self.cr.playGame.getPlace() == None:
self.notify.info('Not opening closet before place is defined.')
return
self.ignore(self.closetSphereEnterEvent)
if not self.locked:
self.cr.playGame.getPlace().fsm.request('closet')
self.accept('closetAsleep', self._handleCancel)
self.sendUpdate('enterAvatar', [])
self.hasLocalAvatar = 1
return
def setState(self, mode, avId, ownerId, gender, topList, botList):
self.notify.debug('setState, mode=%s, avId=%s, ownerId=%d' % (mode, avId, ownerId))
self.isOwner = avId == ownerId
self.ownerGender = gender
if mode == ClosetGlobals.CLOSED:
self.fsm.request('closed')
return
elif mode == ClosetGlobals.OPEN:
self.customerId = avId
self.av = self.cr.doId2do.get(self.customerId, None)
if self.av:
if base.localAvatar.getDoId() == self.customerId:
self.gender = self.av.style.gender
self.topList = topList
self.botList = botList
self.oldTopList = self.topList[0:]
self.oldBotList = self.botList[0:]
self.printInfo()
if not self.isOwner:
self.__popupNotOwnerPanel()
else:
taskMgr.doMethodLater(0.5, self.popupChangeClothesGUI, self.uniqueName('popupChangeClothesGUI'))
self.fsm.request('open')
return
def _revertGender(self):
if self.gender:
self.av.style.gender = self.gender
self.av.loop('neutral')
def popupChangeClothesGUI(self, task):
self.notify.debug('popupChangeClothesGUI')
self.purchaseDoneEvent = self.uniqueName('purchaseDone')
self.swapEvent = self.uniqueName('swap')
self.cancelEvent = self.uniqueName('cancel')
self.accept(self.purchaseDoneEvent, self.__proceedToCheckout)
self.accept(self.swapEvent, self.__handleSwap)
self.accept(self.cancelEvent, self._handleCancel)
self.deleteEvent = self.uniqueName('delete')
if self.isOwner:
self.accept(self.deleteEvent, self.__handleDelete)
if not self.closetGUI:
maxClothes = CatalogFurnitureItem.ClosetToClothes.get(self.item.furnitureType)
self.closetGUI = ClosetGUI.ClosetGUI(self.isOwner, self.purchaseDoneEvent, self.cancelEvent, self.swapEvent, self.deleteEvent, self.topList, self.botList, maxClothes)
self.closetGUI.load()
if self.gender != self.ownerGender:
self.closetGUI.setGender(self.ownerGender)
self.closetGUI.enter(base.localAvatar)
self.closetGUI.showButtons()
style = self.av.getStyle()
self.oldStyle = ToonDNA.ToonDNA()
self.oldStyle.makeFromNetString(style.makeNetString())
return Task.done
def resetCloset(self):
self.ignoreAll()
taskMgr.remove(self.uniqueName('popupChangeClothesGUI'))
taskMgr.remove(self.uniqueName('lerpCamera'))
taskMgr.remove(self.uniqueName('lerpToon'))
if self.closetGUI:
self.closetGUI.hideButtons()
self.closetGUI.exit()
self.closetGUI.unload()
self.closetGUI = None
del self.av
self.av = base.localAvatar
style = self.av.getStyle()
self.oldStyle = ToonDNA.ToonDNA()
self.oldStyle.makeFromNetString(style.makeNetString())
self.topDeleted = 0
self.bottomDeleted = 0
return Task.done
def __handleButton(self):
messenger.send('next')
def _handleCancel(self):
if self.oldStyle:
self.d_setDNA(self.oldStyle.makeNetString(), 1)
else:
self.notify.info('avoided crash in handleCancel')
self._handlePurchaseDone()
if self.closetGUI:
self.closetGUI.resetClothes(self.oldStyle)
if self.popupInfo != None:
self.popupInfo.destroy()
self.popupInfo = None
return
def __handleSwap(self):
self.d_setDNA(self.av.getStyle().makeNetString(), 0)
def __handleDelete(self, t_or_b):
if t_or_b == ClosetGlobals.SHIRT:
itemList = self.closetGUI.tops
trashIndex = self.closetGUI.topChoice
swapFunc = self.closetGUI.swapTop
removeFunc = self.closetGUI.removeTop
self.topDeleted = self.topDeleted | 1
def setItemChoice(i):
self.closetGUI.topChoice = i
else:
itemList = self.closetGUI.bottoms
trashIndex = self.closetGUI.bottomChoice
swapFunc = self.closetGUI.swapBottom
removeFunc = self.closetGUI.removeBottom
self.bottomDeleted = self.bottomDeleted | 1
def setItemChoice(i):
self.closetGUI.bottomChoice = i
if len(itemList) > 1:
trashDNA = ToonDNA.ToonDNA()
trashItem = self.av.getStyle().makeNetString()
trashDNA.makeFromNetString(trashItem)
if trashIndex == 0:
swapFunc(1)
else:
swapFunc(-1)
removeFunc(trashIndex)
self.sendUpdate('removeItem', [trashItem, t_or_b])
swapFunc(0)
self.closetGUI.updateTrashButtons()
else:
self.notify.warning("cant delete this item(type = %s), since we don't have a replacement" % t_or_b)
def __proceedToCheckout(self):
if self.topDeleted or self.bottomDeleted:
self.__popupAreYouSurePanel()
else:
self._handlePurchaseDone()
def _handlePurchaseDone(self, timeout = 0):
if timeout == 1:
self.d_setDNA(self.oldStyle.makeNetString(), 1)
else:
which = 0
if hasattr(self.closetGUI, 'topChoice') and hasattr(self.closetGUI, 'bottomChoice'):
if self.closetGUI.topChoice != 0 or self.topDeleted:
which = which | 1
if self.closetGUI.bottomChoice != 0 or self.bottomDeleted:
which = which | 2
self.d_setDNA(self.av.getStyle().makeNetString(), 2, which)
def d_setDNA(self, dnaString, finished, whichItems = 3):
self.sendUpdate('setDNA', [dnaString, finished, whichItems])
def setCustomerDNA(self, avId, dnaString):
if avId and avId != base.localAvatar.doId:
av = base.cr.doId2do.get(avId, None)
if av:
if self.av == base.cr.doId2do[avId]:
oldTorso = self.av.style.torso
self.av.style.makeFromNetString(dnaString)
if len(oldTorso) == 2 and len(self.av.style.torso) == 2 and self.av.style.torso[1] != oldTorso[1]:
self.av.swapToonTorso(self.av.style.torso, genClothes=0)
self.av.loop('neutral', 0)
self.av.generateToonClothes()
def printInfo(self):
print 'avid: %s, gender: %s' % (self.av.doId, self.av.style.gender)
print 'current top = %s,%s,%s,%s and bot = %s,%s,' % (self.av.style.topTex,
self.av.style.topTexColor,
self.av.style.sleeveTex,
self.av.style.sleeveTexColor,
self.av.style.botTex,
self.av.style.botTexColor)
print 'topsList = %s' % self.av.getClothesTopsList()
print 'bottomsList = %s' % self.av.getClothesBottomsList()
def setMovie(self, mode, avId, timestamp):
self.isLocalToon = avId == base.localAvatar.doId
if avId != 0:
self.lastAvId = avId
self.lastTime = globalClock.getFrameTime()
if mode == ClosetGlobals.CLOSET_MOVIE_CLEAR:
return
elif mode == ClosetGlobals.CLOSET_MOVIE_COMPLETE:
if self.isLocalToon:
self._revertGender()
self.printInfo()
self.resetCloset()
self.freeAvatar()
return
elif mode == ClosetGlobals.CLOSET_MOVIE_TIMEOUT:
taskMgr.remove(self.uniqueName('lerpCamera'))
taskMgr.remove(self.uniqueName('lerpToon'))
if self.isLocalToon:
self.ignore(self.purchaseDoneEvent)
self.ignore(self.swapEvent)
if self.closetGUI:
self.closetGUI.resetClothes(self.oldStyle)
self._handlePurchaseDone(timeout=1)
self.resetCloset()
self._popupTimeoutPanel()
self.freeAvatar()
def freeAvatar(self):
self.notify.debug('freeAvatar()')
if self.hasLocalAvatar:
base.localAvatar.posCamera(0, 0)
place = base.cr.playGame.getPlace()
if place:
place.setState('walk')
self.ignore('closetAsleep')
base.localAvatar.startLookAround()
self.hasLocalAvatar = 0
self.lastTime = globalClock.getFrameTime()
def setOwnerId(self, avId):
self.ownerId = avId
def _popupTimeoutPanel(self):
if self.popupInfo != None:
self.popupInfo.destroy()
self.popupInfo = None
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetTimeoutMessage, frameSize=(-1, 1, -1, 1), geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.45), geom_pos=(0, 0, -.08), text_scale=0.08)
DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.0, 0.0, -0.16), command=self.__handleTimeoutMessageOK)
buttons.removeNode()
self.popupInfo.reparentTo(aspect2d)
def __handleTimeoutMessageOK(self):
self.popupInfo.reparentTo(hidden)
def __popupNotOwnerPanel(self):
if self.popupInfo != None:
self.popupInfo.destroy()
self.popupInfo = None
self.purchaseDoneEvent = self.uniqueName('purchaseDone')
self.swapEvent = self.uniqueName('swap')
self.cancelEvent = self.uniqueName('cancel')
self.accept(self.purchaseDoneEvent, self.__proceedToCheckout)
self.accept(self.swapEvent, self.__handleSwap)
self.accept(self.cancelEvent, self._handleCancel)
self.deleteEvent = self.uniqueName('delete')
if self.isOwner:
self.accept(self.deleteEvent, self.__handleDelete)
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetNotOwnerMessage, frameSize=(-1, 1, -1, 1), text_wordwrap=10, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.55), geom_pos=(0, 0, -.08), text_scale=0.08, text_pos=(0, 0.06))
DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.0, 0.0, -0.21), command=self._handleNotOwnerMessageOK)
buttons.removeNode()
self.popupInfo.reparentTo(aspect2d)
return
def _handleNotOwnerMessageOK(self):
self.popupInfo.reparentTo(hidden)
taskMgr.doMethodLater(0.1, self.popupChangeClothesGUI, self.uniqueName('popupChangeClothesGUI'))
def __popupAreYouSurePanel(self):
if self.popupInfo != None:
self.popupInfo.destroy()
self.popupInfo = None
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
cancelButtonImage = (buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr'))
self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetAreYouSureMessage, frameSize=(-1, 1, -1, 1), text_wordwrap=10, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.55), geom_pos=(0, 0, -.08), text_scale=0.08, text_pos=(0, 0.08))
DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(-0.1, 0.0, -0.21), command=self._handleYesImSure)
DirectButton(self.popupInfo, image=cancelButtonImage, relief=None, text=TTLocalizer.ClosetPopupCancel, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.1, 0.0, -0.21), command=self._handleNotSure)
buttons.removeNode()
self.popupInfo.reparentTo(aspect2d)
return
def _handleYesImSure(self):
self.popupInfo.reparentTo(hidden)
self._handlePurchaseDone()
def _handleNotSure(self):
self.popupInfo.reparentTo(hidden)
def _openDoors(self):
if self.closetTrack:
self.closetTrack.finish()
leftHpr = Vec3(-110, 0, 0)
rightHpr = Vec3(110, 0, 0)
self.closetTrack = Parallel()
if self.rightDoor:
self.closetTrack.append(self.rightDoor.hprInterval(0.5, rightHpr))
if self.leftDoor:
self.closetTrack.append(self.leftDoor.hprInterval(0.5, leftHpr))
self.closetTrack.start()
def _closeDoors(self):
if self.closetTrack:
self.closetTrack.finish()
leftHpr = Vec3(0, 0, 0)
rightHpr = Vec3(0, 0, 0)
self.closetTrack = Parallel()
if self.rightDoor:
self.closetTrack.append(self.rightDoor.hprInterval(0.5, rightHpr))
if self.leftDoor:
self.closetTrack.append(self.leftDoor.hprInterval(0.5, leftHpr))
self.closetTrack.start()