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