2019-11-02 17:27:54 -05:00
|
|
|
from direct.gui.DirectGui import *
|
2022-12-16 18:40:57 -06:00
|
|
|
from panda3d.core import *
|
2022-12-19 02:08:37 -06:00
|
|
|
from panda3d.physics import *
|
2019-11-02 17:27:54 -05:00
|
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
|
|
from direct.interval.IntervalGlobal import *
|
|
|
|
from direct.distributed import DistributedObject
|
|
|
|
from direct.showutil import Rope
|
|
|
|
import math
|
|
|
|
from toontown.toonbase import ToontownGlobals
|
2019-12-30 00:07:56 -06:00
|
|
|
from . import VineGameGlobals
|
|
|
|
from . import VineSpider
|
2019-11-02 17:27:54 -05:00
|
|
|
|
2019-11-02 20:22:48 -05:00
|
|
|
class SwingVine(NodePath):
|
2019-11-02 17:27:54 -05:00
|
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('SwingVine')
|
|
|
|
defaultNormal = Vec3(1, 0, 0)
|
|
|
|
SwingAnimPeriod = 6.0
|
|
|
|
SmallAnimAngle = 10
|
|
|
|
NonMovingAnimAngle = 2
|
|
|
|
SwingAnimFull = 0
|
|
|
|
SwingAnimSmall = 1
|
|
|
|
SwingAnimMinimal = 2
|
|
|
|
MaxNumberOfFramesInSwingAnim = 144
|
|
|
|
|
|
|
|
def __init__(self, vineIndex, x, y, z, length = 20, baseAngle = 40, period = 4, spiderPeriod = 0):
|
|
|
|
NodePath.__init__(self, 'SwingVine')
|
|
|
|
self.cableLength = length
|
|
|
|
self.numLinks = 3
|
|
|
|
self.links = []
|
|
|
|
self.vineIndex = vineIndex
|
|
|
|
self.spider = None
|
|
|
|
self.spiderPeriod = spiderPeriod
|
|
|
|
self.hasSpider = not spiderPeriod == 0
|
|
|
|
self.numTubes = self.numLinks * 3
|
|
|
|
self.tubeLength = float(self.cableLength) / self.numTubes
|
|
|
|
self.tubeLength *= 1.25
|
|
|
|
self.tIncrement = 1.0 / self.numTubes
|
|
|
|
self.tHalfIncrement = self.tIncrement / 2.0
|
|
|
|
self.baseAngle = baseAngle
|
|
|
|
self.maxSwingAngle = deg2Rad(-90 + baseAngle)
|
|
|
|
self.minSwingAngle = deg2Rad(-90 - baseAngle)
|
|
|
|
self.period = period
|
|
|
|
self.swingingForward = True
|
|
|
|
self.swingT = 0
|
|
|
|
self.swingAngle = 0
|
|
|
|
self.setPos(x, y, z)
|
|
|
|
self.load()
|
|
|
|
self.attachedToons = {}
|
|
|
|
self.ival = None
|
|
|
|
self.spiderIval = None
|
|
|
|
self.unloading = False
|
|
|
|
self.spiderMovingDown = True
|
|
|
|
return
|
|
|
|
|
|
|
|
def load(self):
|
|
|
|
self.root = self.attachNewNode('root')
|
|
|
|
self.topLink = self.root.attachNewNode('topLink')
|
|
|
|
self.setupCable()
|
|
|
|
self.reparentTo(render)
|
|
|
|
self.debugTangent = None
|
|
|
|
nearBubble = CollisionSphere(0, 0, -self.cableLength / 2.0, self.cableLength / 2.0)
|
|
|
|
nearBubble.setTangible(0)
|
|
|
|
nearBubbleNode = CollisionNode('SwingVine')
|
|
|
|
nearBubbleNode.setCollideMask(GeomNode.getDefaultCollideMask())
|
|
|
|
nearBubbleNode.addSolid(nearBubble)
|
|
|
|
self.rope.setName('SwingVine-%d' % self.vineIndex)
|
|
|
|
self.setupTubes()
|
|
|
|
if self.hasSpider:
|
|
|
|
self.spider = VineSpider.VineSpider()
|
|
|
|
self.spiderT = 0.25
|
|
|
|
return
|
|
|
|
|
|
|
|
def unload(self):
|
|
|
|
self.unloading = True
|
|
|
|
if self.ival:
|
|
|
|
self.ival.finish()
|
|
|
|
self.ival = None
|
|
|
|
if self.spiderIval:
|
|
|
|
self.spiderIval.finish()
|
|
|
|
self.spiderIval = None
|
|
|
|
if self.debugTangent:
|
|
|
|
self.debugTangent.removeNode()
|
|
|
|
for tube in self.tubes:
|
|
|
|
tube.removeNode()
|
|
|
|
|
|
|
|
self.tubes = []
|
|
|
|
for tube in self.tubes2:
|
|
|
|
tube.removeNode()
|
|
|
|
|
|
|
|
self.tubes2 = []
|
|
|
|
if self.hasSpider:
|
|
|
|
self.spider.destroy()
|
|
|
|
del self.spider
|
2019-12-30 00:07:56 -06:00
|
|
|
for toonInfo in list(self.attachedToons.values()):
|
2019-11-02 17:27:54 -05:00
|
|
|
attachNode = toonInfo[4]
|
|
|
|
if attachNode:
|
|
|
|
attachNode.removeNode()
|
|
|
|
swingIval = toonInfo[6]
|
|
|
|
if swingIval:
|
|
|
|
swingIval.finish()
|
|
|
|
|
|
|
|
self.removeNode()
|
|
|
|
return
|
|
|
|
|
|
|
|
def setupCable(self):
|
|
|
|
self.links = []
|
|
|
|
self.links.append((self.topLink, Point3(0, 0, 0)))
|
|
|
|
anchor = self.topLink
|
2019-12-30 00:07:56 -06:00
|
|
|
for linkNum in range(self.numLinks):
|
2019-11-02 17:27:54 -05:00
|
|
|
anchor = self.__makeLink(anchor, linkNum)
|
|
|
|
|
|
|
|
self.bottomLink = self.links[-1][0]
|
|
|
|
self.link1 = self.links[-2][0]
|
|
|
|
self.rope = self.makeSpline()
|
|
|
|
self.rope.reparentTo(self.root)
|
|
|
|
myTexture = loader.loadTexture('phase_4/maps/swinging_vine.jpg')
|
|
|
|
gameAssets = loader.loadModel('phase_4/models/minigames/vine_game')
|
|
|
|
vine = gameAssets.find('**/vine1')
|
|
|
|
self.cableTex = vine.findTexture('*')
|
|
|
|
if self.cableTex:
|
|
|
|
self.cableTex.setWrapV(Texture.WMRepeat)
|
|
|
|
self.rope.setTexture(self.cableTex)
|
|
|
|
ts = TextureStage.getDefault()
|
|
|
|
self.rope.setTexScale(ts, 1.0, 0.15)
|
|
|
|
self.rope.setTransparency(1)
|
|
|
|
if self.vineIndex == VineGameGlobals.NumVines - 1:
|
|
|
|
pass
|
|
|
|
if self.cableTex:
|
|
|
|
self.setupStaticPart(self.cableTex)
|
|
|
|
|
|
|
|
def setupStaticPart(self, vineTexture):
|
|
|
|
cm = CardMaker('card')
|
|
|
|
cm.setFrame(-0.5, 0.5, -0.1, 8)
|
|
|
|
self.staticVine = self.attachNewNode(cm.generate())
|
|
|
|
self.staticVine.setTexture(vineTexture)
|
|
|
|
self.setTransparency(1)
|
|
|
|
radius = 0.5
|
|
|
|
tubeIndex = 0
|
|
|
|
colNode = CollisionNode('StaticVine-%d-%d' % (self.vineIndex, tubeIndex))
|
|
|
|
bz = 0
|
|
|
|
az = 58
|
|
|
|
quad = CollisionPolygon(Point3(0.25, radius + 1, bz), Point3(0.25, radius + 1, az), Point3(0.25, -radius - 1, az), Point3(0.25, -radius - 1, bz))
|
|
|
|
colNode.addSolid(quad)
|
|
|
|
colNode.setCollideMask(ToontownGlobals.PieBitmask)
|
|
|
|
colNode.setBounds(BoundingSphere(Point3(0, 0, 0), 10))
|
|
|
|
self.staticVine.attachNewNode(colNode)
|
|
|
|
colNode2 = CollisionNode('StaticVine-%d-%d' % (self.vineIndex, tubeIndex))
|
|
|
|
quad2 = CollisionPolygon(Point3(-0.25, -radius - 1, bz), Point3(-0.25, -radius - 1, az), Point3(-0.25, +radius + 1, az), Point3(-0.25, +radius + 1, bz))
|
|
|
|
colNode2.addSolid(quad2)
|
|
|
|
colNode2.setCollideMask(ToontownGlobals.PieBitmask)
|
|
|
|
colNode2.setBounds(BoundingSphere(Point3(0, 0, 0), 10))
|
|
|
|
self.staticVine.attachNewNode(colNode2)
|
|
|
|
|
|
|
|
def setupTubes(self):
|
|
|
|
self.tubes = []
|
|
|
|
self.tubes2 = []
|
|
|
|
radius = 0.5
|
2019-12-30 00:07:56 -06:00
|
|
|
for tubeIndex in range(self.numTubes):
|
2019-11-02 17:27:54 -05:00
|
|
|
az = self.tubeLength / 2.0
|
|
|
|
bz = -self.tubeLength / 2.0
|
|
|
|
ct = CollisionTube(0, 0, az, 0, 0, bz, radius)
|
|
|
|
ct.setTangible(0)
|
|
|
|
colNode = CollisionNode('SwingVine-%d-%d' % (self.vineIndex, tubeIndex))
|
|
|
|
quad = CollisionPolygon(Point3(0.25, radius + 1, bz), Point3(0.25, radius + 1, az), Point3(0.25, -radius - 1, az), Point3(0.25, -radius - 1, bz))
|
|
|
|
colNode.addSolid(quad)
|
|
|
|
colNode.setCollideMask(ToontownGlobals.PieBitmask)
|
|
|
|
colNode.setBounds(BoundingSphere(Point3(0, 0, 0), 10))
|
|
|
|
colNode2 = CollisionNode('SwingVine-%d-%d' % (self.vineIndex, tubeIndex))
|
|
|
|
quad2 = CollisionPolygon(Point3(-0.25, -radius - 1, bz), Point3(-0.25, -radius - 1, az), Point3(-0.25, +radius + 1, az), Point3(-0.25, +radius + 1, bz))
|
|
|
|
colNode2.addSolid(quad2)
|
|
|
|
colNode2.setCollideMask(ToontownGlobals.PieBitmask)
|
|
|
|
colNode2.setBounds(BoundingSphere(Point3(0, 0, 0), 10))
|
|
|
|
newTube = render.attachNewNode(colNode)
|
|
|
|
self.tubes.append(newTube)
|
|
|
|
newTube2 = render.attachNewNode(colNode2)
|
|
|
|
self.tubes2.append(newTube2)
|
|
|
|
|
|
|
|
self.updateTubes()
|
|
|
|
|
|
|
|
def __makeLink(self, anchor, linkNum):
|
|
|
|
an = ActorNode('link%s' % linkNum)
|
|
|
|
anp = NodePath(an)
|
|
|
|
anp.reparentTo(self.root)
|
|
|
|
z = float(linkNum + 1) / float(self.numLinks) * self.cableLength
|
|
|
|
anp.setPos(self.topLink.getPos())
|
|
|
|
anp.setZ(anp.getZ() - z)
|
|
|
|
self.links.append((anp, Point3(0, 0, 0)))
|
|
|
|
return anp
|
|
|
|
|
|
|
|
def makeSpline(self):
|
|
|
|
rope = Rope.Rope()
|
2019-12-30 00:07:56 -06:00
|
|
|
for i in range(len(self.links)):
|
2019-11-02 17:27:54 -05:00
|
|
|
pass
|
|
|
|
|
|
|
|
rope.setup(min(len(self.links), 4), self.links)
|
2019-12-30 00:07:56 -06:00
|
|
|
for i in range(len(self.links)):
|
2019-11-02 17:27:54 -05:00
|
|
|
pass
|
|
|
|
|
|
|
|
rope.curve.normalizeKnots()
|
|
|
|
self.notify.debug('after normalize Knots')
|
2019-12-30 00:07:56 -06:00
|
|
|
for i in range(len(self.links)):
|
2019-11-02 17:27:54 -05:00
|
|
|
pass
|
|
|
|
|
|
|
|
rn = rope.ropeNode
|
|
|
|
rn.setRenderMode(RopeNode.RMBillboard)
|
|
|
|
rn.setNumSlices(3)
|
|
|
|
rn.setTubeUp(Vec3(0, -1, 0))
|
|
|
|
rn.setUvMode(RopeNode.UVDistance)
|
|
|
|
rn.setUvDirection(False)
|
|
|
|
rn.setThickness(1.0)
|
|
|
|
return rope
|
|
|
|
|
|
|
|
def positionLink1(self, t, angleInRadians):
|
|
|
|
degAngle = rad2Deg(angleInRadians)
|
|
|
|
diffFrom90 = degAngle - -90.0
|
|
|
|
link1AngleDiff = diffFrom90 * 2 / 3.0
|
|
|
|
link1AngleToUse = deg2Rad(-90 + link1AngleDiff)
|
|
|
|
lengthToUse = self.cableLength * 2.0 / 3.0
|
|
|
|
link1X = math.cos(link1AngleToUse) * lengthToUse
|
|
|
|
link1Z = math.sin(link1AngleToUse) * lengthToUse
|
|
|
|
self.link1.setPos(link1X, 0, link1Z)
|
|
|
|
|
|
|
|
def swingForward(self, t):
|
|
|
|
diffAngle = self.maxSwingAngle - self.minSwingAngle
|
|
|
|
multiplier = t
|
|
|
|
angleToUse = self.minSwingAngle + multiplier * diffAngle
|
|
|
|
newX = math.cos(angleToUse) * self.cableLength
|
|
|
|
newZ = math.sin(angleToUse) * self.cableLength
|
|
|
|
self.bottomLink.setPos(newX, 0, newZ)
|
|
|
|
self.positionLink1(t, angleToUse)
|
|
|
|
oldSwingingForward = self.swingingForward
|
|
|
|
self.swingingForward = True
|
|
|
|
self.swingT = t
|
|
|
|
self.swingAngle = angleToUse
|
|
|
|
self.updateAttachedStuff()
|
|
|
|
if not oldSwingingForward == self.swingingForward:
|
|
|
|
self.updateSwingAnims()
|
|
|
|
|
|
|
|
def swingBack(self, t):
|
|
|
|
diffAngle = self.maxSwingAngle - self.minSwingAngle
|
|
|
|
multiplier = t
|
|
|
|
angleToUse = self.maxSwingAngle - multiplier * diffAngle
|
|
|
|
newX = math.cos(angleToUse) * self.cableLength
|
|
|
|
newZ = math.sin(angleToUse) * self.cableLength
|
|
|
|
self.bottomLink.setPos(newX, 0, newZ)
|
|
|
|
self.positionLink1(t, angleToUse)
|
|
|
|
oldSwingingForward = self.swingingForward
|
|
|
|
self.swingingForward = False
|
|
|
|
self.swingT = t
|
|
|
|
self.swingAngle = angleToUse
|
|
|
|
self.updateAttachedStuff()
|
|
|
|
if not oldSwingingForward == self.swingingForward:
|
|
|
|
self.updateSwingAnims()
|
|
|
|
|
|
|
|
def moveSpiderDown(self, t):
|
|
|
|
self.spiderMovingDown = True
|
|
|
|
self.spiderT = t
|
|
|
|
|
|
|
|
def moveSpiderUp(self, t):
|
|
|
|
self.spiderMovingDown = False
|
|
|
|
self.spiderT = 1 - t
|
|
|
|
|
|
|
|
def startSwing(self):
|
|
|
|
forwardX = math.cos(self.maxSwingAngle) * self.cableLength
|
|
|
|
forwardZ = math.sin(self.maxSwingAngle) * self.cableLength
|
|
|
|
backX = math.cos(self.minSwingAngle) * self.cableLength
|
|
|
|
backZ = math.sin(self.minSwingAngle) * self.cableLength
|
|
|
|
self.bottomLink.setPos(backX, 0, backZ)
|
|
|
|
self.ival = Sequence(LerpFunctionInterval(self.swingForward, duration=self.period / 2.0, blendType='easeInOut'))
|
|
|
|
self.ival.append(LerpFunctionInterval(self.swingBack, duration=self.period / 2.0, blendType='easeInOut'))
|
|
|
|
self.ival.loop()
|
|
|
|
if self.hasSpider:
|
|
|
|
self.spiderIval = Sequence(LerpFunctionInterval(self.moveSpiderDown, duration=self.spiderPeriod / 2.0, blendType='easeInOut'))
|
|
|
|
self.spiderIval.append(LerpFunctionInterval(self.moveSpiderUp, duration=self.spiderPeriod / 2.0, blendType='easeInOut'))
|
|
|
|
self.spiderIval.loop()
|
|
|
|
|
|
|
|
def stopSwing(self):
|
|
|
|
if self.ival:
|
|
|
|
self.ival.pause()
|
|
|
|
if self.hasSpider and self.spiderIval:
|
|
|
|
self.spiderIval.pause()
|
|
|
|
if self.hasSpider:
|
|
|
|
self.spider.hide()
|
|
|
|
|
|
|
|
def getAttachNode(self, toonId):
|
|
|
|
retval = None
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
existingAttachNode = self.attachedToons[toonId][4]
|
|
|
|
if existingAttachNode:
|
|
|
|
retval = existingAttachNode
|
|
|
|
else:
|
|
|
|
retval = render.attachNewNode('vineAttachNode-%s-%s' % (self.vineIndex, toonId))
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def calcOffset(self, toonId):
|
|
|
|
offset = Point3(0, 0, 0)
|
|
|
|
toon = base.cr.doId2do.get(toonId)
|
|
|
|
if toon:
|
|
|
|
toon.pose('swing', 86)
|
|
|
|
leftHand = toon.find('**/leftHand')
|
|
|
|
if not leftHand.isEmpty():
|
|
|
|
offset = leftHand.getPos(toon)
|
|
|
|
self.notify.debug('offset = %s' % offset)
|
|
|
|
else:
|
|
|
|
self.notify.warning('left hand not found for toon %d' % toonId)
|
|
|
|
else:
|
|
|
|
self.notify.warning('toon %d not found' % toonId)
|
|
|
|
return offset
|
|
|
|
|
|
|
|
def doubleCheckOffset(self, toonId):
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
curOffset = self.attachedToons[toonId][3]
|
|
|
|
if curOffset == Point3.zero():
|
|
|
|
newOffset = self.calcOffset(toonId)
|
|
|
|
self.attachedToons[toonId][3] = newOffset
|
|
|
|
av = base.cr.doId2do.get(toonId)
|
|
|
|
self.notify.info('correcting wrong offset %s and changing to %s' % (curOffset, newOffset))
|
|
|
|
if av:
|
|
|
|
av.setPos(-newOffset)
|
|
|
|
|
|
|
|
def attachToon(self, toonId, t, facingRight, setupAnim = True):
|
|
|
|
self.notify.debug('attachToon toonId=%d vineIndex=%d' % (toonId, self.vineIndex))
|
|
|
|
temp = Vec3(self.defaultNormal)
|
|
|
|
offset = self.calcOffset(toonId)
|
|
|
|
attachNode = self.getAttachNode(toonId)
|
|
|
|
if facingRight:
|
|
|
|
attachNode.setH(-90)
|
|
|
|
else:
|
|
|
|
attachNode.setH(90)
|
|
|
|
self.attachedToons[toonId] = [t,
|
|
|
|
temp,
|
|
|
|
Vec3(0, 0, 0),
|
|
|
|
offset,
|
|
|
|
attachNode,
|
|
|
|
facingRight,
|
|
|
|
None]
|
|
|
|
av = base.cr.doId2do.get(toonId)
|
|
|
|
if av:
|
|
|
|
av.reparentTo(attachNode)
|
|
|
|
if offset == Point3.zero():
|
|
|
|
self.notify.warning('calculated offset for %d is zero' % toonId)
|
|
|
|
av.setPos(-offset)
|
|
|
|
if setupAnim:
|
|
|
|
self.setupSwingAnim(toonId)
|
|
|
|
else:
|
|
|
|
zDownTheVine = self.getPos().getZ() - t * self.cableLength
|
|
|
|
attachNode.setPos(self.getPos())
|
|
|
|
attachNode.setZ(zDownTheVine)
|
|
|
|
else:
|
|
|
|
self.notify.warning('av %d not found' % toonId)
|
|
|
|
return
|
|
|
|
|
|
|
|
def changeAttachedToonT(self, toonId, t):
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
oldT = self.attachedToons[toonId][0]
|
|
|
|
self.attachedToons[toonId][0] = t
|
|
|
|
oldSwingType = self.calcSwingAnimType(oldT)
|
|
|
|
newSwingType = self.calcSwingAnimType(t)
|
|
|
|
if oldSwingType != newSwingType:
|
|
|
|
self.setupSwingAnim(toonId)
|
|
|
|
else:
|
|
|
|
self.notify.warning('changeAttachedToonT avId %d was not in the dict' % toonId)
|
|
|
|
self.attachToon(toonId, t, 1)
|
|
|
|
|
|
|
|
def changeAttachedToonFacing(self, toonId, facing):
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
curT = self.attachedToons[toonId][0]
|
|
|
|
self.detachToon(toonId)
|
|
|
|
self.attachToon(toonId, curT, facing)
|
|
|
|
else:
|
|
|
|
self.notify.warning('changeAttachedToonFacing avId %d was not in the dict' % toonId)
|
|
|
|
self.attachToon(toonId, VineGameGlobals.VineFellDownT, 1)
|
|
|
|
|
|
|
|
def detachToon(self, toonId):
|
|
|
|
self.notify.debug('detachToon toonId=%d vineIndex=%d' % (toonId, self.vineIndex))
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
self.attachedToons[toonId][4].removeNode()
|
|
|
|
swingIval = self.attachedToons[toonId][6]
|
|
|
|
if swingIval:
|
|
|
|
self.notify.debug('deleting swing ival %s' % swingIval)
|
|
|
|
swingIval.finish()
|
|
|
|
self.attachedToons[toonId][6] = None
|
|
|
|
del swingIval
|
|
|
|
del self.attachedToons[toonId]
|
|
|
|
return
|
|
|
|
|
|
|
|
def getAttachedToonInfo(self, toonId):
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
return self.attachedToons[toonId]
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
|
|
def getCenterTForTube(self, tubeIndex):
|
|
|
|
retval = self.tIncrement * tubeIndex + self.tHalfIncrement
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def updateTubes(self):
|
|
|
|
newPoint = Vec3(0, 0, 0)
|
|
|
|
curve = self.rope.ropeNode.getCurve().evaluate()
|
2019-12-30 00:07:56 -06:00
|
|
|
for tubeIndex in range(self.numTubes):
|
2019-11-02 17:27:54 -05:00
|
|
|
tube = self.tubes[tubeIndex]
|
|
|
|
t = self.getCenterTForTube(tubeIndex)
|
|
|
|
curve.evalPoint(t, newPoint)
|
|
|
|
tube.setPos(newPoint)
|
|
|
|
tangent = Vec3(0, 0, 0)
|
|
|
|
curve.evalTangent(t, tangent)
|
|
|
|
tangent.normalize()
|
|
|
|
theta = math.atan2(tangent.getZ(), tangent.getX())
|
|
|
|
degrees = rad2Deg(theta)
|
|
|
|
rAngle = -90 - degrees
|
|
|
|
tube.setR(rAngle)
|
|
|
|
|
2019-12-30 00:07:56 -06:00
|
|
|
for tubeIndex in range(self.numTubes):
|
2019-11-02 17:27:54 -05:00
|
|
|
tube = self.tubes2[tubeIndex]
|
|
|
|
t = self.getCenterTForTube(tubeIndex)
|
|
|
|
curve.evalPoint(t, newPoint)
|
|
|
|
tube.setPos(newPoint)
|
|
|
|
tangent = Vec3(0, 0, 0)
|
|
|
|
curve.evalTangent(t, tangent)
|
|
|
|
tangent.normalize()
|
|
|
|
theta = math.atan2(tangent.getZ(), tangent.getX())
|
|
|
|
degrees = rad2Deg(theta)
|
|
|
|
rAngle = -90 - degrees
|
|
|
|
tube.setR(rAngle)
|
|
|
|
|
|
|
|
def updateSpiders(self):
|
|
|
|
curve = self.rope.ropeNode.getCurve().evaluate()
|
|
|
|
if self.hasSpider:
|
|
|
|
t = self.spiderT
|
|
|
|
newPoint = Vec3(0, 0, 0)
|
|
|
|
curve.evalPoint(t, newPoint)
|
|
|
|
newPoint.setY(-0.5)
|
|
|
|
self.spider.setPos(newPoint)
|
|
|
|
tangent = Vec3(0, 0, 0)
|
|
|
|
curve.evalTangent(t, tangent)
|
|
|
|
theta = math.atan2(tangent.getZ(), tangent.getX())
|
|
|
|
degrees = rad2Deg(theta)
|
|
|
|
pAngle = degrees + 90
|
|
|
|
pAngle = -pAngle
|
|
|
|
if self.spiderMovingDown:
|
|
|
|
self.spider.setR(pAngle)
|
|
|
|
else:
|
|
|
|
self.spider.setR(pAngle - 180)
|
|
|
|
|
|
|
|
def updateAttachedStuff(self):
|
|
|
|
self.updateTubes()
|
|
|
|
self.updateSpiders()
|
|
|
|
self.updateAttachedToons()
|
|
|
|
|
|
|
|
def updateAttachedToons(self):
|
|
|
|
curve = self.rope.ropeNode.getCurve().evaluate()
|
2019-12-30 00:07:56 -06:00
|
|
|
for avId in list(self.attachedToons.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
self.doubleCheckOffset(avId)
|
|
|
|
t = self.attachedToons[avId][0]
|
|
|
|
newPoint = Vec3(0, 0, 0)
|
|
|
|
curve.evalPoint(t, newPoint)
|
|
|
|
attachNode = self.attachedToons[avId][4]
|
|
|
|
attachNode.setPos(newPoint)
|
|
|
|
tangent = Vec3(0, 0, 0)
|
|
|
|
curve.evalTangent(t, tangent)
|
|
|
|
tangent.normalize()
|
|
|
|
unitY = Vec3(0, 1, 0)
|
|
|
|
normal = tangent.cross(unitY)
|
|
|
|
theta = math.atan2(tangent.getZ(), tangent.getX())
|
|
|
|
degrees = rad2Deg(theta)
|
|
|
|
pAngle = degrees + 90
|
|
|
|
pAngle *= 0.5
|
|
|
|
facingRight = self.attachedToons[avId][5]
|
|
|
|
if facingRight:
|
|
|
|
pass
|
|
|
|
if self.debugTangent:
|
|
|
|
self.debugTangent.setPos(newPoint + normal)
|
|
|
|
self.attachedToons[avId][1] = newPoint
|
|
|
|
self.attachedToons[avId][2] = normal
|
|
|
|
|
|
|
|
def getAngularVelocity(self):
|
|
|
|
return deg2Rad(self.baseAngle) / self.period / 4.0
|
|
|
|
|
|
|
|
def getLinearSpeed(self, t):
|
|
|
|
retval = self.getAngularVelocity() * self.cableLength * t
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def calcTFromTubeHit(self, colEntry):
|
|
|
|
name = colEntry.getIntoNodePath().getName()
|
|
|
|
parts = name.split('-')
|
|
|
|
if len(parts) < 3:
|
|
|
|
return
|
|
|
|
tubeIndex = int(parts[2])
|
|
|
|
if tubeIndex < 0 or tubeIndex >= len(self.tubes):
|
|
|
|
return
|
|
|
|
if parts[0] == 'StaticVine':
|
|
|
|
retval = 0
|
|
|
|
else:
|
|
|
|
curve = self.rope.ropeNode.getCurve().evaluate()
|
|
|
|
tangent = Vec3(0, 0, 0)
|
|
|
|
centerT = self.getCenterTForTube(tubeIndex)
|
|
|
|
curve.evalTangent(centerT, tangent)
|
|
|
|
tangent.normalize()
|
|
|
|
endPos = colEntry.getSurfacePoint(render)
|
|
|
|
tubePos = self.tubes[tubeIndex].getPos()
|
|
|
|
vector = endPos - tubePos
|
|
|
|
projection = vector.dot(tangent)
|
|
|
|
self.notify.debug('projection = %s' % projection)
|
|
|
|
diffT = projection / self.tubeLength / 2.0
|
|
|
|
retval = centerT + diffT
|
|
|
|
P1 = tubePos
|
|
|
|
P2 = tubePos + tangent
|
|
|
|
P3 = endPos
|
|
|
|
u = (P3.getX() - P1.getX()) * (P2.getX() - P1.getX()) + (P3.getZ() - P1.getZ()) * (P2.getZ() - P1.getZ())
|
|
|
|
self.notify.debug('u=%s' % u)
|
|
|
|
x = P1.getX() + u * (P2.getX() - P1.getX())
|
|
|
|
z = P1.getZ() + u * (P2.getZ() - P1.getZ())
|
|
|
|
perpPoint = Vec3(x, 0, z)
|
|
|
|
distanceVector = perpPoint - tubePos
|
|
|
|
distance = distanceVector.length()
|
|
|
|
diffT = distance / self.cableLength
|
|
|
|
retval = centerT + diffT
|
|
|
|
if retval > 1:
|
|
|
|
retval = 1
|
|
|
|
if retval < 0:
|
|
|
|
retval = 0
|
|
|
|
self.notify.debug('retval = %s' % retval)
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def setupSwingAnimFull(self, av, avId):
|
|
|
|
toonT = self.attachedToons[avId][0]
|
|
|
|
playRate = self.SwingAnimPeriod / self.period
|
|
|
|
swingInterval = Sequence()
|
|
|
|
duration = (1 - self.swingT) * self.period / 2.0
|
|
|
|
if duration < 0.001:
|
|
|
|
duration = 0.001
|
|
|
|
facingRight = self.attachedToons[avId][5]
|
|
|
|
if self.swingingForward and facingRight or not self.swingingForward and not facingRight:
|
|
|
|
maxLeftFrame = 108
|
|
|
|
downFrame1 = 143
|
|
|
|
downFrame2 = 0
|
|
|
|
maxRightFrame = 35
|
|
|
|
numLeftFramesChoppedOff = (downFrame1 - maxLeftFrame) * (1 - toonT)
|
|
|
|
numRightFramesChoppedOff = maxRightFrame * (1 - toonT)
|
|
|
|
numLeftFramesChoppedOff = 0
|
|
|
|
numRightFramesChoppedOff = 0
|
|
|
|
maxLeftFrame += numLeftFramesChoppedOff
|
|
|
|
maxRightFrame -= numRightFramesChoppedOff
|
|
|
|
numFirstHalfFrames = downFrame1 - maxLeftFrame + 1
|
|
|
|
numSecondHalfFrames = maxRightFrame - downFrame2 + 1
|
|
|
|
numFrames = numFirstHalfFrames + numSecondHalfFrames
|
|
|
|
framesToChopOff = numFrames * self.swingT
|
|
|
|
if framesToChopOff < numFirstHalfFrames:
|
|
|
|
startingFrame = maxLeftFrame + framesToChopOff
|
|
|
|
halfDur = duration / 2.0
|
|
|
|
swing1Dur = (1 - framesToChopOff / numFirstHalfFrames) * halfDur
|
|
|
|
toonSwing1 = ActorInterval(av, 'swing', startFrame=startingFrame, endFrame=downFrame1, playRate=playRate, name='swingForward1')
|
|
|
|
toonSwing2 = ActorInterval(av, 'swing', startFrame=downFrame2, endFrame=maxRightFrame, playRate=playRate, name='swingForward2')
|
|
|
|
swingInterval.append(toonSwing1)
|
|
|
|
swingInterval.append(toonSwing2)
|
|
|
|
else:
|
|
|
|
secondHalfFramesToChopOff = framesToChopOff - numFirstHalfFrames
|
|
|
|
startingFrame = downFrame2 + secondHalfFramesToChopOff
|
|
|
|
toonSwing2 = ActorInterval(av, 'swing', startFrame=startingFrame, endFrame=maxRightFrame, playRate=playRate, name='swingForward2')
|
|
|
|
swingInterval.append(toonSwing2)
|
|
|
|
else:
|
|
|
|
maxRightFrame = 35
|
|
|
|
maxLeftFrame = 107
|
|
|
|
midFrame = (maxLeftFrame + maxRightFrame) / 2.0
|
|
|
|
numLeftFramesChoppedOff = 0
|
|
|
|
numRightFramesChoppedOff = 0
|
|
|
|
maxLeftFrame -= numLeftFramesChoppedOff
|
|
|
|
maxRightFrame += numRightFramesChoppedOff
|
|
|
|
numFrames = maxLeftFrame - maxRightFrame + 1
|
|
|
|
framesToChopOff = numFrames * self.swingT
|
|
|
|
startingFrame = maxRightFrame + framesToChopOff
|
|
|
|
toonSwing = ActorInterval(av, 'swing', startFrame=startingFrame, endFrame=maxLeftFrame, playRate=playRate)
|
|
|
|
swingInterval.append(toonSwing)
|
|
|
|
self.attachedToons[avId][6] = swingInterval
|
|
|
|
swingInterval.start()
|
|
|
|
|
|
|
|
def setupSwingAnimSmall(self, av, avId):
|
|
|
|
swingInterval = Sequence()
|
|
|
|
maxLeftFrame = 0
|
|
|
|
maxRightFrame = 20
|
|
|
|
startingLeftFrame = 5
|
|
|
|
numFrames = maxRightFrame - maxLeftFrame + 1
|
|
|
|
playRate = self.SwingAnimPeriod / self.period
|
|
|
|
duration = (1 - self.swingT) * self.period / 2.0
|
|
|
|
if duration == 0:
|
|
|
|
return
|
|
|
|
toonT = self.attachedToons[avId][0]
|
|
|
|
framesPerSecondBase = self.MaxNumberOfFramesInSwingAnim / self.SwingAnimPeriod
|
|
|
|
desiredFramesPerSecond = numFrames / duration
|
|
|
|
slowedPlayRate = desiredFramesPerSecond / framesPerSecondBase
|
|
|
|
facingRight = self.attachedToons[avId][5]
|
|
|
|
if self.swingingForward and facingRight or not self.swingingForward and not facingRight:
|
|
|
|
toonSwing1 = ActorInterval(av, 'swing', startFrame=startingLeftFrame, endFrame=maxLeftFrame, playRate=slowedPlayRate)
|
|
|
|
toonSwing2 = ActorInterval(av, 'swing', startFrame=maxLeftFrame + 1, endFrame=maxRightFrame - startingLeftFrame, playRate=slowedPlayRate)
|
|
|
|
swingInterval.append(toonSwing1)
|
|
|
|
swingInterval.append(toonSwing2)
|
|
|
|
else:
|
|
|
|
toonSwing1 = ActorInterval(av, 'swing', startFrame=maxRightFrame - startingLeftFrame, endFrame=maxRightFrame, playRate=slowedPlayRate)
|
|
|
|
toonSwing2 = ActorInterval(av, 'swing', startFrame=maxRightFrame, endFrame=startingLeftFrame, playRate=slowedPlayRate)
|
|
|
|
swingInterval.append(toonSwing1)
|
|
|
|
swingInterval.append(toonSwing2)
|
|
|
|
self.attachedToons[avId][6] = swingInterval
|
|
|
|
swingInterval.start()
|
|
|
|
|
|
|
|
def setupSwingAnimMinimal(self, av, avId):
|
|
|
|
swingInterval = Sequence()
|
|
|
|
maxLeftFrame = 88
|
|
|
|
maxRightFrame = 84
|
|
|
|
duration = (1 - self.swingT) * self.period / 2.0
|
|
|
|
if duration < 0.001:
|
|
|
|
duration = 0.001
|
|
|
|
numFrames = maxLeftFrame - maxRightFrame + 1
|
|
|
|
numFrames *= 2
|
|
|
|
framesPerSecondBase = self.MaxNumberOfFramesInSwingAnim / self.SwingAnimPeriod
|
|
|
|
desiredFramesPerSecond = numFrames / duration
|
|
|
|
slowedPlayRate = desiredFramesPerSecond / framesPerSecondBase
|
|
|
|
toonSwing1 = ActorInterval(av, 'swing', startFrame=maxLeftFrame, endFrame=maxRightFrame, playRate=slowedPlayRate)
|
|
|
|
toonSwing2 = ActorInterval(av, 'swing', startFrame=maxRightFrame, endFrame=maxLeftFrame, playRate=slowedPlayRate)
|
|
|
|
swingInterval.append(toonSwing1)
|
|
|
|
swingInterval.append(toonSwing2)
|
|
|
|
self.attachedToons[avId][6] = swingInterval
|
|
|
|
swingInterval.start()
|
|
|
|
|
|
|
|
def setupSwingAnim(self, avId):
|
2019-12-30 00:07:56 -06:00
|
|
|
if avId not in self.attachedToons:
|
2019-11-02 17:27:54 -05:00
|
|
|
return
|
|
|
|
av = base.cr.doId2do.get(avId)
|
|
|
|
if not av:
|
|
|
|
return
|
|
|
|
prevIval = self.attachedToons[avId][6]
|
|
|
|
if prevIval:
|
|
|
|
prevIval.pause()
|
|
|
|
del prevIval
|
|
|
|
toonT = self.attachedToons[avId][0]
|
|
|
|
swingAnimType = self.calcSwingAnimType(toonT)
|
|
|
|
if swingAnimType == self.SwingAnimFull:
|
|
|
|
self.setupSwingAnimFull(av, avId)
|
|
|
|
elif swingAnimType == self.SwingAnimSmall:
|
|
|
|
self.setupSwingAnimSmall(av, avId)
|
|
|
|
else:
|
|
|
|
self.setupSwingAnimMinimal(av, avId)
|
|
|
|
|
|
|
|
def calcSwingAnimType(self, toonT):
|
|
|
|
angleInDegrees = toonT * self.baseAngle
|
|
|
|
retval = self.SwingAnimFull
|
|
|
|
if angleInDegrees > 10:
|
|
|
|
retval = self.SwingAnimFull
|
|
|
|
elif angleInDegrees > 2:
|
|
|
|
retval = self.SwingAnimSmall
|
|
|
|
else:
|
|
|
|
retval = self.SwingAnimMinimal
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def updateSwingAnims(self):
|
|
|
|
if self.unloading:
|
|
|
|
return
|
2019-12-30 00:07:56 -06:00
|
|
|
for avId in list(self.attachedToons.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
self.setupSwingAnim(avId)
|