bastd.actor.text
Defines Actor(s).
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defines Actor(s).""" 4 5from __future__ import annotations 6 7from enum import Enum 8from typing import TYPE_CHECKING 9 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any, Sequence 14 15 16class Text(ba.Actor): 17 """Text with some tricks.""" 18 19 class Transition(Enum): 20 """Transition types for text.""" 21 FADE_IN = 'fade_in' 22 IN_RIGHT = 'in_right' 23 IN_LEFT = 'in_left' 24 IN_BOTTOM = 'in_bottom' 25 IN_BOTTOM_SLOW = 'in_bottom_slow' 26 IN_TOP_SLOW = 'in_top_slow' 27 28 class HAlign(Enum): 29 """Horizontal alignment type.""" 30 LEFT = 'left' 31 CENTER = 'center' 32 RIGHT = 'right' 33 34 class VAlign(Enum): 35 """Vertical alignment type.""" 36 NONE = 'none' 37 CENTER = 'center' 38 39 class HAttach(Enum): 40 """Horizontal attach type.""" 41 LEFT = 'left' 42 CENTER = 'center' 43 RIGHT = 'right' 44 45 class VAttach(Enum): 46 """Vertical attach type.""" 47 BOTTOM = 'bottom' 48 CENTER = 'center' 49 TOP = 'top' 50 51 def __init__(self, 52 text: str | ba.Lstr, 53 position: tuple[float, float] = (0.0, 0.0), 54 h_align: HAlign = HAlign.LEFT, 55 v_align: VAlign = VAlign.NONE, 56 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 57 transition: Transition | None = None, 58 transition_delay: float = 0.0, 59 flash: bool = False, 60 v_attach: VAttach = VAttach.CENTER, 61 h_attach: HAttach = HAttach.CENTER, 62 scale: float = 1.0, 63 transition_out_delay: float | None = None, 64 maxwidth: float | None = None, 65 shadow: float = 0.5, 66 flatness: float = 0.0, 67 vr_depth: float = 0.0, 68 host_only: bool = False, 69 front: bool = False): 70 # pylint: disable=too-many-statements 71 # pylint: disable=too-many-branches 72 # pylint: disable=too-many-locals 73 super().__init__() 74 self.node = ba.newnode( 75 'text', 76 delegate=self, 77 attrs={ 78 'text': text, 79 'color': color, 80 'position': position, 81 'h_align': h_align.value, 82 'vr_depth': vr_depth, 83 'v_align': v_align.value, 84 'h_attach': h_attach.value, 85 'v_attach': v_attach.value, 86 'shadow': shadow, 87 'flatness': flatness, 88 'maxwidth': 0.0 if maxwidth is None else maxwidth, 89 'host_only': host_only, 90 'front': front, 91 'scale': scale 92 }) 93 94 if transition is self.Transition.FADE_IN: 95 if flash: 96 raise Exception('fixme: flash and fade-in' 97 ' currently cant both be on') 98 cmb = ba.newnode('combine', 99 owner=self.node, 100 attrs={ 101 'input0': color[0], 102 'input1': color[1], 103 'input2': color[2], 104 'size': 4 105 }) 106 keys = {transition_delay: 0.0, transition_delay + 0.5: color[3]} 107 if transition_out_delay is not None: 108 keys[transition_delay + transition_out_delay] = color[3] 109 keys[transition_delay + transition_out_delay + 0.5] = 0.0 110 ba.animate(cmb, 'input3', keys) 111 cmb.connectattr('output', self.node, 'color') 112 113 if flash: 114 mult = 2.0 115 tm1 = 0.15 116 tm2 = 0.3 117 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 4}) 118 ba.animate(cmb, 119 'input0', { 120 0.0: color[0] * mult, 121 tm1: color[0], 122 tm2: color[0] * mult 123 }, 124 loop=True) 125 ba.animate(cmb, 126 'input1', { 127 0.0: color[1] * mult, 128 tm1: color[1], 129 tm2: color[1] * mult 130 }, 131 loop=True) 132 ba.animate(cmb, 133 'input2', { 134 0.0: color[2] * mult, 135 tm1: color[2], 136 tm2: color[2] * mult 137 }, 138 loop=True) 139 cmb.input3 = color[3] 140 cmb.connectattr('output', self.node, 'color') 141 142 cmb = self.position_combine = ba.newnode('combine', 143 owner=self.node, 144 attrs={'size': 2}) 145 146 if transition is self.Transition.IN_RIGHT: 147 keys = { 148 transition_delay: position[0] + 1300, 149 transition_delay + 0.2: position[0] 150 } 151 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 152 ba.animate(cmb, 'input0', keys) 153 cmb.input1 = position[1] 154 ba.animate(self.node, 'opacity', o_keys) 155 elif transition is self.Transition.IN_LEFT: 156 keys = { 157 transition_delay: position[0] - 1300, 158 transition_delay + 0.2: position[0] 159 } 160 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 161 if transition_out_delay is not None: 162 keys[transition_delay + transition_out_delay] = position[0] 163 keys[transition_delay + transition_out_delay + 164 0.2] = position[0] - 1300.0 165 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 166 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 167 ba.animate(cmb, 'input0', keys) 168 cmb.input1 = position[1] 169 ba.animate(self.node, 'opacity', o_keys) 170 elif transition is self.Transition.IN_BOTTOM_SLOW: 171 keys = { 172 transition_delay: -100.0, 173 transition_delay + 1.0: position[1] 174 } 175 o_keys = {transition_delay: 0.0, transition_delay + 0.2: 1.0} 176 cmb.input0 = position[0] 177 ba.animate(cmb, 'input1', keys) 178 ba.animate(self.node, 'opacity', o_keys) 179 elif transition is self.Transition.IN_BOTTOM: 180 keys = { 181 transition_delay: -100.0, 182 transition_delay + 0.2: position[1] 183 } 184 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 185 if transition_out_delay is not None: 186 keys[transition_delay + transition_out_delay] = position[1] 187 keys[transition_delay + transition_out_delay + 0.2] = -100.0 188 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 189 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 190 cmb.input0 = position[0] 191 ba.animate(cmb, 'input1', keys) 192 ba.animate(self.node, 'opacity', o_keys) 193 elif transition is self.Transition.IN_TOP_SLOW: 194 keys = { 195 transition_delay: 400.0, 196 transition_delay + 3.5: position[1] 197 } 198 o_keys = {transition_delay: 0, transition_delay + 1.0: 1.0} 199 cmb.input0 = position[0] 200 ba.animate(cmb, 'input1', keys) 201 ba.animate(self.node, 'opacity', o_keys) 202 else: 203 assert transition is self.Transition.FADE_IN or transition is None 204 cmb.input0 = position[0] 205 cmb.input1 = position[1] 206 cmb.connectattr('output', self.node, 'position') 207 208 # If we're transitioning out, die at the end of it. 209 if transition_out_delay is not None: 210 ba.timer(transition_delay + transition_out_delay + 1.0, 211 ba.WeakCall(self.handlemessage, ba.DieMessage())) 212 213 def handlemessage(self, msg: Any) -> Any: 214 assert not self.expired 215 if isinstance(msg, ba.DieMessage): 216 if self.node: 217 self.node.delete() 218 return None 219 return super().handlemessage(msg)
class
Text(ba._actor.Actor):
17class Text(ba.Actor): 18 """Text with some tricks.""" 19 20 class Transition(Enum): 21 """Transition types for text.""" 22 FADE_IN = 'fade_in' 23 IN_RIGHT = 'in_right' 24 IN_LEFT = 'in_left' 25 IN_BOTTOM = 'in_bottom' 26 IN_BOTTOM_SLOW = 'in_bottom_slow' 27 IN_TOP_SLOW = 'in_top_slow' 28 29 class HAlign(Enum): 30 """Horizontal alignment type.""" 31 LEFT = 'left' 32 CENTER = 'center' 33 RIGHT = 'right' 34 35 class VAlign(Enum): 36 """Vertical alignment type.""" 37 NONE = 'none' 38 CENTER = 'center' 39 40 class HAttach(Enum): 41 """Horizontal attach type.""" 42 LEFT = 'left' 43 CENTER = 'center' 44 RIGHT = 'right' 45 46 class VAttach(Enum): 47 """Vertical attach type.""" 48 BOTTOM = 'bottom' 49 CENTER = 'center' 50 TOP = 'top' 51 52 def __init__(self, 53 text: str | ba.Lstr, 54 position: tuple[float, float] = (0.0, 0.0), 55 h_align: HAlign = HAlign.LEFT, 56 v_align: VAlign = VAlign.NONE, 57 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 58 transition: Transition | None = None, 59 transition_delay: float = 0.0, 60 flash: bool = False, 61 v_attach: VAttach = VAttach.CENTER, 62 h_attach: HAttach = HAttach.CENTER, 63 scale: float = 1.0, 64 transition_out_delay: float | None = None, 65 maxwidth: float | None = None, 66 shadow: float = 0.5, 67 flatness: float = 0.0, 68 vr_depth: float = 0.0, 69 host_only: bool = False, 70 front: bool = False): 71 # pylint: disable=too-many-statements 72 # pylint: disable=too-many-branches 73 # pylint: disable=too-many-locals 74 super().__init__() 75 self.node = ba.newnode( 76 'text', 77 delegate=self, 78 attrs={ 79 'text': text, 80 'color': color, 81 'position': position, 82 'h_align': h_align.value, 83 'vr_depth': vr_depth, 84 'v_align': v_align.value, 85 'h_attach': h_attach.value, 86 'v_attach': v_attach.value, 87 'shadow': shadow, 88 'flatness': flatness, 89 'maxwidth': 0.0 if maxwidth is None else maxwidth, 90 'host_only': host_only, 91 'front': front, 92 'scale': scale 93 }) 94 95 if transition is self.Transition.FADE_IN: 96 if flash: 97 raise Exception('fixme: flash and fade-in' 98 ' currently cant both be on') 99 cmb = ba.newnode('combine', 100 owner=self.node, 101 attrs={ 102 'input0': color[0], 103 'input1': color[1], 104 'input2': color[2], 105 'size': 4 106 }) 107 keys = {transition_delay: 0.0, transition_delay + 0.5: color[3]} 108 if transition_out_delay is not None: 109 keys[transition_delay + transition_out_delay] = color[3] 110 keys[transition_delay + transition_out_delay + 0.5] = 0.0 111 ba.animate(cmb, 'input3', keys) 112 cmb.connectattr('output', self.node, 'color') 113 114 if flash: 115 mult = 2.0 116 tm1 = 0.15 117 tm2 = 0.3 118 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 4}) 119 ba.animate(cmb, 120 'input0', { 121 0.0: color[0] * mult, 122 tm1: color[0], 123 tm2: color[0] * mult 124 }, 125 loop=True) 126 ba.animate(cmb, 127 'input1', { 128 0.0: color[1] * mult, 129 tm1: color[1], 130 tm2: color[1] * mult 131 }, 132 loop=True) 133 ba.animate(cmb, 134 'input2', { 135 0.0: color[2] * mult, 136 tm1: color[2], 137 tm2: color[2] * mult 138 }, 139 loop=True) 140 cmb.input3 = color[3] 141 cmb.connectattr('output', self.node, 'color') 142 143 cmb = self.position_combine = ba.newnode('combine', 144 owner=self.node, 145 attrs={'size': 2}) 146 147 if transition is self.Transition.IN_RIGHT: 148 keys = { 149 transition_delay: position[0] + 1300, 150 transition_delay + 0.2: position[0] 151 } 152 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 153 ba.animate(cmb, 'input0', keys) 154 cmb.input1 = position[1] 155 ba.animate(self.node, 'opacity', o_keys) 156 elif transition is self.Transition.IN_LEFT: 157 keys = { 158 transition_delay: position[0] - 1300, 159 transition_delay + 0.2: position[0] 160 } 161 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 162 if transition_out_delay is not None: 163 keys[transition_delay + transition_out_delay] = position[0] 164 keys[transition_delay + transition_out_delay + 165 0.2] = position[0] - 1300.0 166 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 167 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 168 ba.animate(cmb, 'input0', keys) 169 cmb.input1 = position[1] 170 ba.animate(self.node, 'opacity', o_keys) 171 elif transition is self.Transition.IN_BOTTOM_SLOW: 172 keys = { 173 transition_delay: -100.0, 174 transition_delay + 1.0: position[1] 175 } 176 o_keys = {transition_delay: 0.0, transition_delay + 0.2: 1.0} 177 cmb.input0 = position[0] 178 ba.animate(cmb, 'input1', keys) 179 ba.animate(self.node, 'opacity', o_keys) 180 elif transition is self.Transition.IN_BOTTOM: 181 keys = { 182 transition_delay: -100.0, 183 transition_delay + 0.2: position[1] 184 } 185 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 186 if transition_out_delay is not None: 187 keys[transition_delay + transition_out_delay] = position[1] 188 keys[transition_delay + transition_out_delay + 0.2] = -100.0 189 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 190 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 191 cmb.input0 = position[0] 192 ba.animate(cmb, 'input1', keys) 193 ba.animate(self.node, 'opacity', o_keys) 194 elif transition is self.Transition.IN_TOP_SLOW: 195 keys = { 196 transition_delay: 400.0, 197 transition_delay + 3.5: position[1] 198 } 199 o_keys = {transition_delay: 0, transition_delay + 1.0: 1.0} 200 cmb.input0 = position[0] 201 ba.animate(cmb, 'input1', keys) 202 ba.animate(self.node, 'opacity', o_keys) 203 else: 204 assert transition is self.Transition.FADE_IN or transition is None 205 cmb.input0 = position[0] 206 cmb.input1 = position[1] 207 cmb.connectattr('output', self.node, 'position') 208 209 # If we're transitioning out, die at the end of it. 210 if transition_out_delay is not None: 211 ba.timer(transition_delay + transition_out_delay + 1.0, 212 ba.WeakCall(self.handlemessage, ba.DieMessage())) 213 214 def handlemessage(self, msg: Any) -> Any: 215 assert not self.expired 216 if isinstance(msg, ba.DieMessage): 217 if self.node: 218 self.node.delete() 219 return None 220 return super().handlemessage(msg)
Text with some tricks.
Text( text: str | ba._language.Lstr, position: tuple[float, float] = (0.0, 0.0), h_align: 'HAlign' = <HAlign.LEFT: 'left'>, v_align: 'VAlign' = <VAlign.NONE: 'none'>, color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), transition: 'Transition | None' = None, transition_delay: float = 0.0, flash: bool = False, v_attach: 'VAttach' = <VAttach.CENTER: 'center'>, h_attach: 'HAttach' = <HAttach.CENTER: 'center'>, scale: float = 1.0, transition_out_delay: float | None = None, maxwidth: float | None = None, shadow: float = 0.5, flatness: float = 0.0, vr_depth: float = 0.0, host_only: bool = False, front: bool = False)
52 def __init__(self, 53 text: str | ba.Lstr, 54 position: tuple[float, float] = (0.0, 0.0), 55 h_align: HAlign = HAlign.LEFT, 56 v_align: VAlign = VAlign.NONE, 57 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 58 transition: Transition | None = None, 59 transition_delay: float = 0.0, 60 flash: bool = False, 61 v_attach: VAttach = VAttach.CENTER, 62 h_attach: HAttach = HAttach.CENTER, 63 scale: float = 1.0, 64 transition_out_delay: float | None = None, 65 maxwidth: float | None = None, 66 shadow: float = 0.5, 67 flatness: float = 0.0, 68 vr_depth: float = 0.0, 69 host_only: bool = False, 70 front: bool = False): 71 # pylint: disable=too-many-statements 72 # pylint: disable=too-many-branches 73 # pylint: disable=too-many-locals 74 super().__init__() 75 self.node = ba.newnode( 76 'text', 77 delegate=self, 78 attrs={ 79 'text': text, 80 'color': color, 81 'position': position, 82 'h_align': h_align.value, 83 'vr_depth': vr_depth, 84 'v_align': v_align.value, 85 'h_attach': h_attach.value, 86 'v_attach': v_attach.value, 87 'shadow': shadow, 88 'flatness': flatness, 89 'maxwidth': 0.0 if maxwidth is None else maxwidth, 90 'host_only': host_only, 91 'front': front, 92 'scale': scale 93 }) 94 95 if transition is self.Transition.FADE_IN: 96 if flash: 97 raise Exception('fixme: flash and fade-in' 98 ' currently cant both be on') 99 cmb = ba.newnode('combine', 100 owner=self.node, 101 attrs={ 102 'input0': color[0], 103 'input1': color[1], 104 'input2': color[2], 105 'size': 4 106 }) 107 keys = {transition_delay: 0.0, transition_delay + 0.5: color[3]} 108 if transition_out_delay is not None: 109 keys[transition_delay + transition_out_delay] = color[3] 110 keys[transition_delay + transition_out_delay + 0.5] = 0.0 111 ba.animate(cmb, 'input3', keys) 112 cmb.connectattr('output', self.node, 'color') 113 114 if flash: 115 mult = 2.0 116 tm1 = 0.15 117 tm2 = 0.3 118 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 4}) 119 ba.animate(cmb, 120 'input0', { 121 0.0: color[0] * mult, 122 tm1: color[0], 123 tm2: color[0] * mult 124 }, 125 loop=True) 126 ba.animate(cmb, 127 'input1', { 128 0.0: color[1] * mult, 129 tm1: color[1], 130 tm2: color[1] * mult 131 }, 132 loop=True) 133 ba.animate(cmb, 134 'input2', { 135 0.0: color[2] * mult, 136 tm1: color[2], 137 tm2: color[2] * mult 138 }, 139 loop=True) 140 cmb.input3 = color[3] 141 cmb.connectattr('output', self.node, 'color') 142 143 cmb = self.position_combine = ba.newnode('combine', 144 owner=self.node, 145 attrs={'size': 2}) 146 147 if transition is self.Transition.IN_RIGHT: 148 keys = { 149 transition_delay: position[0] + 1300, 150 transition_delay + 0.2: position[0] 151 } 152 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 153 ba.animate(cmb, 'input0', keys) 154 cmb.input1 = position[1] 155 ba.animate(self.node, 'opacity', o_keys) 156 elif transition is self.Transition.IN_LEFT: 157 keys = { 158 transition_delay: position[0] - 1300, 159 transition_delay + 0.2: position[0] 160 } 161 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 162 if transition_out_delay is not None: 163 keys[transition_delay + transition_out_delay] = position[0] 164 keys[transition_delay + transition_out_delay + 165 0.2] = position[0] - 1300.0 166 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 167 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 168 ba.animate(cmb, 'input0', keys) 169 cmb.input1 = position[1] 170 ba.animate(self.node, 'opacity', o_keys) 171 elif transition is self.Transition.IN_BOTTOM_SLOW: 172 keys = { 173 transition_delay: -100.0, 174 transition_delay + 1.0: position[1] 175 } 176 o_keys = {transition_delay: 0.0, transition_delay + 0.2: 1.0} 177 cmb.input0 = position[0] 178 ba.animate(cmb, 'input1', keys) 179 ba.animate(self.node, 'opacity', o_keys) 180 elif transition is self.Transition.IN_BOTTOM: 181 keys = { 182 transition_delay: -100.0, 183 transition_delay + 0.2: position[1] 184 } 185 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 186 if transition_out_delay is not None: 187 keys[transition_delay + transition_out_delay] = position[1] 188 keys[transition_delay + transition_out_delay + 0.2] = -100.0 189 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 190 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 191 cmb.input0 = position[0] 192 ba.animate(cmb, 'input1', keys) 193 ba.animate(self.node, 'opacity', o_keys) 194 elif transition is self.Transition.IN_TOP_SLOW: 195 keys = { 196 transition_delay: 400.0, 197 transition_delay + 3.5: position[1] 198 } 199 o_keys = {transition_delay: 0, transition_delay + 1.0: 1.0} 200 cmb.input0 = position[0] 201 ba.animate(cmb, 'input1', keys) 202 ba.animate(self.node, 'opacity', o_keys) 203 else: 204 assert transition is self.Transition.FADE_IN or transition is None 205 cmb.input0 = position[0] 206 cmb.input1 = position[1] 207 cmb.connectattr('output', self.node, 'position') 208 209 # If we're transitioning out, die at the end of it. 210 if transition_out_delay is not None: 211 ba.timer(transition_delay + transition_out_delay + 1.0, 212 ba.WeakCall(self.handlemessage, ba.DieMessage()))
Instantiates an Actor in the current ba.Activity.
def
handlemessage(self, msg: Any) -> Any:
214 def handlemessage(self, msg: Any) -> Any: 215 assert not self.expired 216 if isinstance(msg, ba.DieMessage): 217 if self.node: 218 self.node.delete() 219 return None 220 return super().handlemessage(msg)
General message handling; can be passed any message object.
Inherited Members
- ba._actor.Actor
- autoretain
- on_expire
- expired
- exists
- is_alive
- activity
- getactivity
class
Text.Transition(enum.Enum):
20 class Transition(Enum): 21 """Transition types for text.""" 22 FADE_IN = 'fade_in' 23 IN_RIGHT = 'in_right' 24 IN_LEFT = 'in_left' 25 IN_BOTTOM = 'in_bottom' 26 IN_BOTTOM_SLOW = 'in_bottom_slow' 27 IN_TOP_SLOW = 'in_top_slow'
Transition types for text.
Inherited Members
- enum.Enum
- name
- value
class
Text.HAlign(enum.Enum):
29 class HAlign(Enum): 30 """Horizontal alignment type.""" 31 LEFT = 'left' 32 CENTER = 'center' 33 RIGHT = 'right'
Horizontal alignment type.
Inherited Members
- enum.Enum
- name
- value
class
Text.VAlign(enum.Enum):
Vertical alignment type.
Inherited Members
- enum.Enum
- name
- value
class
Text.HAttach(enum.Enum):
40 class HAttach(Enum): 41 """Horizontal attach type.""" 42 LEFT = 'left' 43 CENTER = 'center' 44 RIGHT = 'right'
Horizontal attach type.
Inherited Members
- enum.Enum
- name
- value
class
Text.VAttach(enum.Enum):
46 class VAttach(Enum): 47 """Vertical attach type.""" 48 BOTTOM = 'bottom' 49 CENTER = 'center' 50 TOP = 'top'
Vertical attach type.
Inherited Members
- enum.Enum
- name
- value