Poodletooth-iLand/toontown/nametag/Nametag3d.py
2015-05-10 05:51:55 -05:00

192 lines
6.8 KiB
Python

from direct.task.Task import Task
import math
from panda3d.core import BillboardEffect, Vec3, Point3, PGButton, VBase4
from panda3d.core import DepthWriteAttrib
from direct.interval.IntervalGlobal import *
from toontown.chat.ChatBalloon import ChatBalloon
from toontown.nametag import NametagGlobals
from toontown.nametag.Nametag import Nametag
from toontown.toontowngui.Clickable3d import Clickable3d
class Nametag3d(Nametag, Clickable3d):
SCALING_MIN_DISTANCE = 1
SCALING_MAX_DISTANCE = 50
SCALING_FACTOR = 0.065
def __init__(self):
Nametag.__init__(self)
Clickable3d.__init__(self, 'Nametag3d')
self.distance = 0
self.billboardOffset = 3
self.doBillboardEffect()
def destroy(self):
self.ignoreAll()
Nametag.destroy(self)
Clickable3d.destroy(self)
def getUniqueName(self):
return 'Nametag3d-' + str(id(self))
def getChatBalloonModel(self):
return NametagGlobals.chatBalloon3dModel
def getChatBalloonWidth(self):
return NametagGlobals.chatBalloon3dWidth
def getChatBalloonHeight(self):
return NametagGlobals.chatBalloon3dHeight
def setBillboardOffset(self, billboardOffset):
self.billboardOffset = billboardOffset
self.doBillboardEffect()
def getBillboardOffset(self):
return self.billboardOffset
def doBillboardEffect(self):
billboardEffect = BillboardEffect.make(
Vec3(0, 0, 1), True, False, self.billboardOffset, base.cam,
Point3(0, 0, 0))
self.contents.setEffect(billboardEffect)
def updateClickRegion(self):
if self.chatBalloon is not None:
left = self.chatBalloon.center[0] - (self.chatBalloon.width/2)
right = left + self.chatBalloon.width
# Calculate the bottom of the region based on constants.
# 2.4 is the padded height of a single-line message:
bottom = NametagGlobals.chatBalloon3dHeight - 2.4
top = bottom + self.chatBalloon.height
self.setClickRegionFrame(left, right, bottom, top)
elif self.panel is not None:
centerX = (self.textNode.getLeft()+self.textNode.getRight()) / 2.0
centerY = (self.textNode.getBottom()+self.textNode.getTop()) / 2.0
left = centerX - (self.panelWidth/2.0)
right = centerX + (self.panelWidth/2.0)
bottom = centerY - (self.panelHeight/2.0)
top = centerY + (self.panelHeight/2.0)
self.setClickRegionFrame(left, right, bottom, top)
def isClickable(self):
if self.getChatText() and self.hasChatButton():
return True
return NametagGlobals.wantActiveNametags and Clickable3d.isClickable(self)
def setClickState(self, clickState):
if self.isClickable():
self.applyClickState(clickState)
else:
self.applyClickState(PGButton.SInactive)
Clickable3d.setClickState(self, clickState)
def enterDepressed(self):
if self.isClickable():
base.playSfx(NametagGlobals.clickSound)
def enterRollover(self):
if self.isClickable() and (self.lastClickState != PGButton.SDepressed):
base.playSfx(NametagGlobals.rolloverSound)
def removeContents(self):
if self.contents:
self.contents.node().removeAllChildren()
def update(self):
if not self.chatBalloon:
self.removeContents()
Nametag.update(self)
else:
scaleLerp = Sequence(LerpScaleInterval(self.chatBalloon, 0.25, VBase3(0, 0, 0), blendType='easeInOut'),
Wait(0.25),
Func(self.removeContents),
Func(Nametag.update, self))
scaleLerp.start()
def tick(self, task):
distance = self.contents.getPos(base.cam).length()
if distance < self.SCALING_MIN_DISTANCE:
distance = self.SCALING_MIN_DISTANCE
elif distance > self.SCALING_MAX_DISTANCE:
distance = self.SCALING_MAX_DISTANCE
if distance != self.distance:
self.contents.setScale(math.sqrt(distance) * self.SCALING_FACTOR)
self.distance = distance
self.updateClickRegion()
return Task.cont
def drawChatBalloon(self, model, modelWidth, modelHeight):
if self.chatFont is None:
# We can't draw this without a font.
return
if self.isClickable():
foreground, background = self.chatColor[self.clickState]
else:
foreground, background = self.chatColor[PGButton.SInactive]
if self.chatType == NametagGlobals.SPEEDCHAT:
background = self.speedChatColor
if background[3] > self.CHAT_BALLOON_ALPHA:
background = VBase4(
background[0], background[1], background[2],
self.CHAT_BALLOON_ALPHA)
self.chatBalloon = ChatBalloon(
model, modelWidth, modelHeight, self.chatTextNode,
foreground=foreground, background=background,
reversed=self.chatReversed,
button=self.chatButton[self.clickState])
self.chatBalloon.setScale(0)
self.chatBalloon.reparentTo(self.contents)
scaleLerp = Sequence(Wait(0.15), LerpScaleInterval(self.chatBalloon, 0.25, VBase3(1, 1, 1), blendType='easeInOut'))
scaleLerp.start()
def drawNametag(self):
if self.font is None:
# We can't draw this without a font.
return
# Attach the icon:
if self.icon is not None:
self.contents.attachNewNode(self.icon)
if self.isClickable():
foreground, background = self.nametagColor[self.clickState]
else:
foreground, background = self.nametagColor[PGButton.SInactive]
# Set the color of the TextNode:
self.textNode.setTextColor(foreground)
# Attach the TextNode:
textNodePath = self.contents.attachNewNode(self.textNode, 1)
textNodePath.setTransparency(foreground[3] < 1)
textNodePath.setAttrib(DepthWriteAttrib.make(0))
textNodePath.setY(self.TEXT_Y_OFFSET)
# Attach a panel behind the TextNode:
self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0)
self.panel.setColor(background)
self.panel.setTransparency(background[3] < 1)
# Reposition the panel:
x = (self.textNode.getLeft()+self.textNode.getRight()) / 2.0
z = (self.textNode.getBottom()+self.textNode.getTop()) / 2.0
self.panel.setPos(x, 0, z)
# Resize the panel:
self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING
self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING
self.panel.setScale(self.panelWidth, 1, self.panelHeight)