bastd.actor.image
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 Image(ba.Actor): 17 """Just a wrapped up image node with a few tricks up its sleeve.""" 18 19 class Transition(Enum): 20 """Transition types we support.""" 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 Attach(Enum): 29 """Attach types we support.""" 30 CENTER = 'center' 31 TOP_CENTER = 'topCenter' 32 TOP_LEFT = 'topLeft' 33 BOTTOM_CENTER = 'bottomCenter' 34 35 def __init__(self, 36 texture: ba.Texture | dict[str, Any], 37 position: tuple[float, float] = (0, 0), 38 transition: Transition | None = None, 39 transition_delay: float = 0.0, 40 attach: Attach = Attach.CENTER, 41 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 42 scale: tuple[float, float] = (100.0, 100.0), 43 transition_out_delay: float | None = None, 44 model_opaque: ba.Model | None = None, 45 model_transparent: ba.Model | None = None, 46 vr_depth: float = 0.0, 47 host_only: bool = False, 48 front: bool = False): 49 # pylint: disable=too-many-statements 50 # pylint: disable=too-many-branches 51 # pylint: disable=too-many-locals 52 super().__init__() 53 54 # If they provided a dict as texture, assume its an icon. 55 # otherwise its just a texture value itself. 56 mask_texture: ba.Texture | None 57 if isinstance(texture, dict): 58 tint_color = texture['tint_color'] 59 tint2_color = texture['tint2_color'] 60 tint_texture = texture['tint_texture'] 61 texture = texture['texture'] 62 mask_texture = ba.gettexture('characterIconMask') 63 else: 64 tint_color = (1, 1, 1) 65 tint2_color = None 66 tint_texture = None 67 mask_texture = None 68 69 self.node = ba.newnode('image', 70 attrs={ 71 'texture': texture, 72 'tint_color': tint_color, 73 'tint_texture': tint_texture, 74 'position': position, 75 'vr_depth': vr_depth, 76 'scale': scale, 77 'mask_texture': mask_texture, 78 'color': color, 79 'absolute_scale': True, 80 'host_only': host_only, 81 'front': front, 82 'attach': attach.value 83 }, 84 delegate=self) 85 86 if model_opaque is not None: 87 self.node.model_opaque = model_opaque 88 if model_transparent is not None: 89 self.node.model_transparent = model_transparent 90 if tint2_color is not None: 91 self.node.tint2_color = tint2_color 92 if transition is self.Transition.FADE_IN: 93 keys = {transition_delay: 0, transition_delay + 0.5: color[3]} 94 if transition_out_delay is not None: 95 keys[transition_delay + transition_out_delay] = color[3] 96 keys[transition_delay + transition_out_delay + 0.5] = 0 97 ba.animate(self.node, 'opacity', keys) 98 cmb = self.position_combine = ba.newnode('combine', 99 owner=self.node, 100 attrs={'size': 2}) 101 if transition is self.Transition.IN_RIGHT: 102 keys = { 103 transition_delay: position[0] + 1200, 104 transition_delay + 0.2: position[0] 105 } 106 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 107 ba.animate(cmb, 'input0', keys) 108 cmb.input1 = position[1] 109 ba.animate(self.node, 'opacity', o_keys) 110 elif transition is self.Transition.IN_LEFT: 111 keys = { 112 transition_delay: position[0] - 1200, 113 transition_delay + 0.2: position[0] 114 } 115 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 116 if transition_out_delay is not None: 117 keys[transition_delay + transition_out_delay] = position[0] 118 keys[transition_delay + transition_out_delay + 119 200] = -position[0] - 1200 120 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 121 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 122 ba.animate(cmb, 'input0', keys) 123 cmb.input1 = position[1] 124 ba.animate(self.node, 'opacity', o_keys) 125 elif transition is self.Transition.IN_BOTTOM_SLOW: 126 keys = { 127 transition_delay: -400, 128 transition_delay + 3.5: position[1] 129 } 130 o_keys = {transition_delay: 0.0, transition_delay + 2.0: 1.0} 131 cmb.input0 = position[0] 132 ba.animate(cmb, 'input1', keys) 133 ba.animate(self.node, 'opacity', o_keys) 134 elif transition is self.Transition.IN_BOTTOM: 135 keys = { 136 transition_delay: -400, 137 transition_delay + 0.2: position[1] 138 } 139 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 140 if transition_out_delay is not None: 141 keys[transition_delay + transition_out_delay] = position[1] 142 keys[transition_delay + transition_out_delay + 0.2] = -400 143 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 144 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 145 cmb.input0 = position[0] 146 ba.animate(cmb, 'input1', keys) 147 ba.animate(self.node, 'opacity', o_keys) 148 elif transition is self.Transition.IN_TOP_SLOW: 149 keys = {transition_delay: 400, transition_delay + 3.5: position[1]} 150 o_keys = {transition_delay: 0.0, transition_delay + 1.0: 1.0} 151 cmb.input0 = position[0] 152 ba.animate(cmb, 'input1', keys) 153 ba.animate(self.node, 'opacity', o_keys) 154 else: 155 assert transition is self.Transition.FADE_IN or transition is None 156 cmb.input0 = position[0] 157 cmb.input1 = position[1] 158 cmb.connectattr('output', self.node, 'position') 159 160 # If we're transitioning out, die at the end of it. 161 if transition_out_delay is not None: 162 ba.timer(transition_delay + transition_out_delay + 1.0, 163 ba.WeakCall(self.handlemessage, ba.DieMessage())) 164 165 def handlemessage(self, msg: Any) -> Any: 166 assert not self.expired 167 if isinstance(msg, ba.DieMessage): 168 if self.node: 169 self.node.delete() 170 return None 171 return super().handlemessage(msg)
class
Image(ba._actor.Actor):
17class Image(ba.Actor): 18 """Just a wrapped up image node with a few tricks up its sleeve.""" 19 20 class Transition(Enum): 21 """Transition types we support.""" 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 Attach(Enum): 30 """Attach types we support.""" 31 CENTER = 'center' 32 TOP_CENTER = 'topCenter' 33 TOP_LEFT = 'topLeft' 34 BOTTOM_CENTER = 'bottomCenter' 35 36 def __init__(self, 37 texture: ba.Texture | dict[str, Any], 38 position: tuple[float, float] = (0, 0), 39 transition: Transition | None = None, 40 transition_delay: float = 0.0, 41 attach: Attach = Attach.CENTER, 42 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 43 scale: tuple[float, float] = (100.0, 100.0), 44 transition_out_delay: float | None = None, 45 model_opaque: ba.Model | None = None, 46 model_transparent: ba.Model | None = None, 47 vr_depth: float = 0.0, 48 host_only: bool = False, 49 front: bool = False): 50 # pylint: disable=too-many-statements 51 # pylint: disable=too-many-branches 52 # pylint: disable=too-many-locals 53 super().__init__() 54 55 # If they provided a dict as texture, assume its an icon. 56 # otherwise its just a texture value itself. 57 mask_texture: ba.Texture | None 58 if isinstance(texture, dict): 59 tint_color = texture['tint_color'] 60 tint2_color = texture['tint2_color'] 61 tint_texture = texture['tint_texture'] 62 texture = texture['texture'] 63 mask_texture = ba.gettexture('characterIconMask') 64 else: 65 tint_color = (1, 1, 1) 66 tint2_color = None 67 tint_texture = None 68 mask_texture = None 69 70 self.node = ba.newnode('image', 71 attrs={ 72 'texture': texture, 73 'tint_color': tint_color, 74 'tint_texture': tint_texture, 75 'position': position, 76 'vr_depth': vr_depth, 77 'scale': scale, 78 'mask_texture': mask_texture, 79 'color': color, 80 'absolute_scale': True, 81 'host_only': host_only, 82 'front': front, 83 'attach': attach.value 84 }, 85 delegate=self) 86 87 if model_opaque is not None: 88 self.node.model_opaque = model_opaque 89 if model_transparent is not None: 90 self.node.model_transparent = model_transparent 91 if tint2_color is not None: 92 self.node.tint2_color = tint2_color 93 if transition is self.Transition.FADE_IN: 94 keys = {transition_delay: 0, transition_delay + 0.5: color[3]} 95 if transition_out_delay is not None: 96 keys[transition_delay + transition_out_delay] = color[3] 97 keys[transition_delay + transition_out_delay + 0.5] = 0 98 ba.animate(self.node, 'opacity', keys) 99 cmb = self.position_combine = ba.newnode('combine', 100 owner=self.node, 101 attrs={'size': 2}) 102 if transition is self.Transition.IN_RIGHT: 103 keys = { 104 transition_delay: position[0] + 1200, 105 transition_delay + 0.2: position[0] 106 } 107 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 108 ba.animate(cmb, 'input0', keys) 109 cmb.input1 = position[1] 110 ba.animate(self.node, 'opacity', o_keys) 111 elif transition is self.Transition.IN_LEFT: 112 keys = { 113 transition_delay: position[0] - 1200, 114 transition_delay + 0.2: position[0] 115 } 116 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 117 if transition_out_delay is not None: 118 keys[transition_delay + transition_out_delay] = position[0] 119 keys[transition_delay + transition_out_delay + 120 200] = -position[0] - 1200 121 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 122 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 123 ba.animate(cmb, 'input0', keys) 124 cmb.input1 = position[1] 125 ba.animate(self.node, 'opacity', o_keys) 126 elif transition is self.Transition.IN_BOTTOM_SLOW: 127 keys = { 128 transition_delay: -400, 129 transition_delay + 3.5: position[1] 130 } 131 o_keys = {transition_delay: 0.0, transition_delay + 2.0: 1.0} 132 cmb.input0 = position[0] 133 ba.animate(cmb, 'input1', keys) 134 ba.animate(self.node, 'opacity', o_keys) 135 elif transition is self.Transition.IN_BOTTOM: 136 keys = { 137 transition_delay: -400, 138 transition_delay + 0.2: position[1] 139 } 140 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 141 if transition_out_delay is not None: 142 keys[transition_delay + transition_out_delay] = position[1] 143 keys[transition_delay + transition_out_delay + 0.2] = -400 144 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 145 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 146 cmb.input0 = position[0] 147 ba.animate(cmb, 'input1', keys) 148 ba.animate(self.node, 'opacity', o_keys) 149 elif transition is self.Transition.IN_TOP_SLOW: 150 keys = {transition_delay: 400, transition_delay + 3.5: position[1]} 151 o_keys = {transition_delay: 0.0, transition_delay + 1.0: 1.0} 152 cmb.input0 = position[0] 153 ba.animate(cmb, 'input1', keys) 154 ba.animate(self.node, 'opacity', o_keys) 155 else: 156 assert transition is self.Transition.FADE_IN or transition is None 157 cmb.input0 = position[0] 158 cmb.input1 = position[1] 159 cmb.connectattr('output', self.node, 'position') 160 161 # If we're transitioning out, die at the end of it. 162 if transition_out_delay is not None: 163 ba.timer(transition_delay + transition_out_delay + 1.0, 164 ba.WeakCall(self.handlemessage, ba.DieMessage())) 165 166 def handlemessage(self, msg: Any) -> Any: 167 assert not self.expired 168 if isinstance(msg, ba.DieMessage): 169 if self.node: 170 self.node.delete() 171 return None 172 return super().handlemessage(msg)
Just a wrapped up image node with a few tricks up its sleeve.
Image( texture: _ba.Texture | dict[str, typing.Any], position: tuple[float, float] = (0, 0), transition: 'Transition | None' = None, transition_delay: float = 0.0, attach: 'Attach' = <Attach.CENTER: 'center'>, color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), scale: tuple[float, float] = (100.0, 100.0), transition_out_delay: float | None = None, model_opaque: _ba.Model | None = None, model_transparent: _ba.Model | None = None, vr_depth: float = 0.0, host_only: bool = False, front: bool = False)
36 def __init__(self, 37 texture: ba.Texture | dict[str, Any], 38 position: tuple[float, float] = (0, 0), 39 transition: Transition | None = None, 40 transition_delay: float = 0.0, 41 attach: Attach = Attach.CENTER, 42 color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), 43 scale: tuple[float, float] = (100.0, 100.0), 44 transition_out_delay: float | None = None, 45 model_opaque: ba.Model | None = None, 46 model_transparent: ba.Model | None = None, 47 vr_depth: float = 0.0, 48 host_only: bool = False, 49 front: bool = False): 50 # pylint: disable=too-many-statements 51 # pylint: disable=too-many-branches 52 # pylint: disable=too-many-locals 53 super().__init__() 54 55 # If they provided a dict as texture, assume its an icon. 56 # otherwise its just a texture value itself. 57 mask_texture: ba.Texture | None 58 if isinstance(texture, dict): 59 tint_color = texture['tint_color'] 60 tint2_color = texture['tint2_color'] 61 tint_texture = texture['tint_texture'] 62 texture = texture['texture'] 63 mask_texture = ba.gettexture('characterIconMask') 64 else: 65 tint_color = (1, 1, 1) 66 tint2_color = None 67 tint_texture = None 68 mask_texture = None 69 70 self.node = ba.newnode('image', 71 attrs={ 72 'texture': texture, 73 'tint_color': tint_color, 74 'tint_texture': tint_texture, 75 'position': position, 76 'vr_depth': vr_depth, 77 'scale': scale, 78 'mask_texture': mask_texture, 79 'color': color, 80 'absolute_scale': True, 81 'host_only': host_only, 82 'front': front, 83 'attach': attach.value 84 }, 85 delegate=self) 86 87 if model_opaque is not None: 88 self.node.model_opaque = model_opaque 89 if model_transparent is not None: 90 self.node.model_transparent = model_transparent 91 if tint2_color is not None: 92 self.node.tint2_color = tint2_color 93 if transition is self.Transition.FADE_IN: 94 keys = {transition_delay: 0, transition_delay + 0.5: color[3]} 95 if transition_out_delay is not None: 96 keys[transition_delay + transition_out_delay] = color[3] 97 keys[transition_delay + transition_out_delay + 0.5] = 0 98 ba.animate(self.node, 'opacity', keys) 99 cmb = self.position_combine = ba.newnode('combine', 100 owner=self.node, 101 attrs={'size': 2}) 102 if transition is self.Transition.IN_RIGHT: 103 keys = { 104 transition_delay: position[0] + 1200, 105 transition_delay + 0.2: position[0] 106 } 107 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 108 ba.animate(cmb, 'input0', keys) 109 cmb.input1 = position[1] 110 ba.animate(self.node, 'opacity', o_keys) 111 elif transition is self.Transition.IN_LEFT: 112 keys = { 113 transition_delay: position[0] - 1200, 114 transition_delay + 0.2: position[0] 115 } 116 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 117 if transition_out_delay is not None: 118 keys[transition_delay + transition_out_delay] = position[0] 119 keys[transition_delay + transition_out_delay + 120 200] = -position[0] - 1200 121 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 122 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 123 ba.animate(cmb, 'input0', keys) 124 cmb.input1 = position[1] 125 ba.animate(self.node, 'opacity', o_keys) 126 elif transition is self.Transition.IN_BOTTOM_SLOW: 127 keys = { 128 transition_delay: -400, 129 transition_delay + 3.5: position[1] 130 } 131 o_keys = {transition_delay: 0.0, transition_delay + 2.0: 1.0} 132 cmb.input0 = position[0] 133 ba.animate(cmb, 'input1', keys) 134 ba.animate(self.node, 'opacity', o_keys) 135 elif transition is self.Transition.IN_BOTTOM: 136 keys = { 137 transition_delay: -400, 138 transition_delay + 0.2: position[1] 139 } 140 o_keys = {transition_delay: 0.0, transition_delay + 0.05: 1.0} 141 if transition_out_delay is not None: 142 keys[transition_delay + transition_out_delay] = position[1] 143 keys[transition_delay + transition_out_delay + 0.2] = -400 144 o_keys[transition_delay + transition_out_delay + 0.15] = 1.0 145 o_keys[transition_delay + transition_out_delay + 0.2] = 0.0 146 cmb.input0 = position[0] 147 ba.animate(cmb, 'input1', keys) 148 ba.animate(self.node, 'opacity', o_keys) 149 elif transition is self.Transition.IN_TOP_SLOW: 150 keys = {transition_delay: 400, transition_delay + 3.5: position[1]} 151 o_keys = {transition_delay: 0.0, transition_delay + 1.0: 1.0} 152 cmb.input0 = position[0] 153 ba.animate(cmb, 'input1', keys) 154 ba.animate(self.node, 'opacity', o_keys) 155 else: 156 assert transition is self.Transition.FADE_IN or transition is None 157 cmb.input0 = position[0] 158 cmb.input1 = position[1] 159 cmb.connectattr('output', self.node, 'position') 160 161 # If we're transitioning out, die at the end of it. 162 if transition_out_delay is not None: 163 ba.timer(transition_delay + transition_out_delay + 1.0, 164 ba.WeakCall(self.handlemessage, ba.DieMessage()))
Instantiates an Actor in the current ba.Activity.
def
handlemessage(self, msg: Any) -> Any:
166 def handlemessage(self, msg: Any) -> Any: 167 assert not self.expired 168 if isinstance(msg, ba.DieMessage): 169 if self.node: 170 self.node.delete() 171 return None 172 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
Image.Transition(enum.Enum):
20 class Transition(Enum): 21 """Transition types we support.""" 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 we support.
Inherited Members
- enum.Enum
- name
- value
class
Image.Attach(enum.Enum):
29 class Attach(Enum): 30 """Attach types we support.""" 31 CENTER = 'center' 32 TOP_CENTER = 'topCenter' 33 TOP_LEFT = 'topLeft' 34 BOTTOM_CENTER = 'bottomCenter'
Attach types we support.
Inherited Members
- enum.Enum
- name
- value