mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-25 04:32:33 -06:00
94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
|
from pandac.PandaModules import *
|
||
|
|
||
|
class ChatBalloon:
|
||
|
TEXT_SHIFT = (0.1, -0.05, 1.1)
|
||
|
TEXT_SHIFT_REVERSED = -0.05
|
||
|
TEXT_SHIFT_PROP = 0.08
|
||
|
NATIVE_WIDTH = 10.0
|
||
|
MIN_WIDTH = 2.5
|
||
|
MIN_HEIGHT = 1
|
||
|
BUBBLE_PADDING = 0.3
|
||
|
BUBBLE_PADDING_PROP = 0.05
|
||
|
BUTTON_SCALE = 6
|
||
|
BUTTON_SHIFT = (-0.2, 0, 0.6)
|
||
|
FRAME_SHIFT = (0.2, 1.4)
|
||
|
|
||
|
def __init__(self, model):
|
||
|
self.model = model
|
||
|
|
||
|
def generate(self, text, font, textColor=(0,0,0,1), balloonColor=(1,1,1,1),
|
||
|
wordWrap = 10.0, button=None, reversed=False):
|
||
|
root = NodePath('balloon')
|
||
|
|
||
|
# Add balloon geometry:
|
||
|
balloon = self.model.copyTo(root)
|
||
|
top = balloon.find('**/top')
|
||
|
middle = balloon.find('**/middle')
|
||
|
bottom = balloon.find('**/bottom')
|
||
|
|
||
|
balloon.setColor(balloonColor)
|
||
|
if balloonColor[3] < 1.0:
|
||
|
balloon.setTransparency(1)
|
||
|
|
||
|
# Render the text into a TextNode, using the font:
|
||
|
t = root.attachNewNode(TextNode('text'))
|
||
|
t.node().setFont(font)
|
||
|
t.node().setWordwrap(wordWrap)
|
||
|
t.node().setText(text)
|
||
|
t.node().setTextColor(textColor)
|
||
|
|
||
|
width, height = t.node().getWidth(), t.node().getHeight()
|
||
|
|
||
|
# Turn off depth write for the text: The place in the depth buffer is
|
||
|
# held by the chat bubble anyway, and the text renders after the bubble
|
||
|
# so there's no risk of the bubble overwriting the text's pixels.
|
||
|
t.setAttrib(DepthWriteAttrib.make(0))
|
||
|
t.setPos(self.TEXT_SHIFT)
|
||
|
t.setX(t, self.TEXT_SHIFT_PROP*width)
|
||
|
t.setZ(t, height)
|
||
|
|
||
|
if reversed:
|
||
|
# The nametag code wants the text on the left side of the axis,
|
||
|
# rather than on the right side. Therefore, we move the text to the
|
||
|
# opposite side:
|
||
|
t.setX(self.TEXT_SHIFT_REVERSED - self.TEXT_SHIFT_PROP*width - width)
|
||
|
|
||
|
# Give the chat bubble a button, if one is requested:
|
||
|
if button:
|
||
|
np = button.copyTo(root)
|
||
|
np.setPos(t, width, 0, -height)
|
||
|
np.setPos(np, self.BUTTON_SHIFT)
|
||
|
np.setScale(self.BUTTON_SCALE)
|
||
|
|
||
|
# Set a minimum width and height for short or empty messages
|
||
|
if width < self.MIN_WIDTH:
|
||
|
width = self.MIN_WIDTH
|
||
|
if reversed:
|
||
|
t.setX(t, -width/2.0)
|
||
|
else:
|
||
|
t.setX(t, width/2.0)
|
||
|
t.node().setAlign(TextNode.ACenter)
|
||
|
|
||
|
if height < self.MIN_HEIGHT:
|
||
|
height = self.MIN_HEIGHT
|
||
|
t.setX(t, height/2.0)
|
||
|
t.node().setAlign(TextNode.ACenter)
|
||
|
|
||
|
# Set the balloon's size:
|
||
|
width *= 1+self.BUBBLE_PADDING_PROP
|
||
|
width += self.BUBBLE_PADDING
|
||
|
balloon.setSx(width/self.NATIVE_WIDTH)
|
||
|
if reversed:
|
||
|
balloon.setSx(-balloon.getSx())
|
||
|
balloon.setTwoSided(True) # Render the backface of the balloon
|
||
|
middle.setSz(height)
|
||
|
top.setZ(top, height-1)
|
||
|
|
||
|
# Calculate the frame occupied by the balloon:
|
||
|
left, bottom = self.FRAME_SHIFT
|
||
|
if reversed:
|
||
|
left = -left - width
|
||
|
frame = (left, left+width, bottom, bottom+height+1)
|
||
|
|
||
|
return root, frame
|