diff --git a/ursina/prefabs/vec_field.py b/ursina/prefabs/vec_field.py index 4facfa6b..f4a82ba0 100644 --- a/ursina/prefabs/vec_field.py +++ b/ursina/prefabs/vec_field.py @@ -1,135 +1,136 @@ -from ursina.prefabs.button import Button -from ursina.entity import Entity -from ursina.vec2 import Vec2 -from ursina.prefabs.input_field import InputField, ContentTypes -from ursina import color, camera, mouse, round_to_closest - - -class VecField(Button): - def __init__(self, default_value=Vec2(0.0,0.0), character_limit=8, content_type=ContentTypes.math, **kwargs): - kwargs = dict(parent=camera.ui, scale=(.5,.05), character_limit=character_limit, text='', text_origin=(-.5,0), color=color.black90) | kwargs - super().__init__(**kwargs) - if isinstance(default_value, (int, float)): - default_value = [default_value, ] - - self.default_value = default_value - self.fields = [] - self.on_value_changed = None - w = 1 / len(default_value) *.5 - - self.highlight_color = self.color - self.pressed_color = self.color - self._dragging_on = None - self._value_on_drag_start = [] - self._temp_value = [] - - self.data_type = float - if isinstance(default_value[0], int): - self.data_type = int - content_type = ContentTypes.int_math - - for i in range(len(default_value)): - field = InputField(str(self.default_value[i])[:self.character_limit], character_limit=self.character_limit, model='quad', parent=self, limit_content_to=content_type, - x=(i*w)+w/2, scale=(w,1), z=-1, color=color._8, font='VeraMono.ttf', submit_on=['enter','tab']) - field.grid = Entity(parent=field, model='wireframe_quad', color=color.dark_gray, z=-1) - field.text_field.scale *= .75 - field.on_submit = self.convert_text_to_vector - field.on_value_changed = self.convert_text_to_vector - field.text_field.shortcuts['select_all'] = ('double click', ) - field.text_field.shortcuts['select_word'] = [] - self.fields.append(field) - - self.value = default_value - - - def convert_text_to_vector(self): - vector = [] - for i, field in enumerate(self.fields): - try: - # value = type(self.default_value[i])(eval(field.text[:self.character_limit])) - value = self.data_type(eval(field.text[:self.character_limit])) - if isinstance(value, self.data_type): - vector.append(value) - field.text_field.text_entity.text = str(value)[:8] - except: # invalid/incomplete math - print('invalid') - return - # print('vector:', vector, 'fotype', type(self.default_value)) - if not isinstance(self.default_value, (tuple, list)): - vector = type(self.default_value)(*vector) - - self.value = vector - - - @property - def value(self): - if len(self._value) == 1: - return self._value[0] - return self._value - - @value.setter - def value(self, value): - self._value = value - if len(value) == 1: - value = value[0] - - if self.on_value_changed is not None: - self.on_value_changed() - - for i, field in enumerate(self.fields): - field.text = value[i][:self.character_limit] - - - def input(self, key): - super().input(key) - if key == 'left mouse down': - self._dragging_on = None - self._temp_value = [e for e in self._value] - - for i, field in enumerate(self.fields): - if field.hovered: - self._dragging_on = field - self._value_on_drag_start = self.value - return - - elif key == 'left mouse up' and self._dragging_on: - self._dragging_on = None - self.value = self._value - self._temp_value = self._value - - - def update(self): - if mouse.left and self._dragging_on and not self._dragging_on.active: - # print('drag on:', self._dragging_on, mouse.velocity.x) - idx = self.fields.index(self._dragging_on) - if self.data_type == float: - self._temp_value[idx] += mouse.velocity.x - self._value = [round_to_closest(e, .01) for e in self._temp_value] - elif self.data_type == int: - self._temp_value[idx] += mouse.velocity.x * 10 - self._value = [int(e) for e in self._temp_value] - - for i, field in enumerate(self.fields): # set text temporarily while dragging - field.text_field.text_entity.text = str(self._value[i])[:self.character_limit] - - - -if __name__ == '__main__': - from ursina import * - app = Ursina() - # Entity(parent=camera.ui, model='quad', scale=.05, z=-10) - # field = VecField(text=' field', default_value=Vec3(0,0,0)) - def on_value_changed(): - print('set value to:', field.value) - - field = VecField(text=' int list', default_value=[10,1]) - field = VecField(text=' float list', default_value=[1.0,-2.0], y=-.1) - field = VecField(text=' Vec4', default_value=Vec4(1,-2,0,0), y=-.2) - field = VecField(text=' float', default_value=1.0, y=-.3) - field = VecField(text=' int', default_value=0, y=-.4) - # field.on_value_changed = on_value_changed - - # Entity(color=color.azure, scale=(.5,.05), model='quad', parent=camera.ui) - # InputField(y=-.1) - Sprite('shore', color=color.dark_gray) - app.run() +from ursina.prefabs.button import Button +from ursina.entity import Entity +from ursina.vec2 import Vec2 +from ursina.prefabs.input_field import InputField, ContentTypes +from ursina import color, camera, mouse, round_to_closest + + +class VecField(Button): + def __init__(self, default_value=Vec2(0.0,0.0), character_limit=8, content_type=ContentTypes.math, **kwargs): + kwargs = dict(parent=camera.ui, scale=(.5,.05), character_limit=character_limit, text='', text_origin=(-.5,0), color=color.black90) | kwargs + super().__init__(**kwargs) + if isinstance(default_value, (int, float)): + default_value = [default_value, ] + + self.default_value = default_value + self.fields = [] + self.on_value_changed = None + w = 1 / len(default_value) *.5 + + self.highlight_color = self.color + self.pressed_color = self.color + self._dragging_on = None + self._value_on_drag_start = [] + self._temp_value = [] + + self.data_type = float + if isinstance(default_value[0], int): + self.data_type = int + content_type = ContentTypes.int_math + + for i in range(len(default_value)): + field = InputField(str(self.default_value[i])[:self.character_limit], character_limit=self.character_limit, model='quad', parent=self, limit_content_to=content_type, + x=(i*w)+w/2, scale=(w,1), z=-1, color=color._8, font='VeraMono.ttf', submit_on=['enter','tab']) + field.grid = Entity(parent=field, model='wireframe_quad', color=color.dark_gray, z=-1) + field.text_field.scale *= .75 + field.on_submit = self.convert_text_to_vector + # field.on_value_changed = self.convert_text_to_vector + field.text_field.shortcuts['select_all'] = ('double click', ) + field.text_field.shortcuts['select_word'] = [] + self.fields.append(field) + + self.value = default_value + + + def convert_text_to_vector(self): + vector = [] + for i, field in enumerate(self.fields): + try: + # value = type(self.default_value[i])(eval(field.text[:self.character_limit])) + value = self.data_type(eval(field.text[:self.character_limit])) + if isinstance(value, self.data_type): + vector.append(value) + field.text_field.text_entity.text = str(value)[:8] + except: # invalid/incomplete math + print('invalid') + return + # print('vector:', vector, 'fotype', type(self.default_value)) + if not isinstance(self.default_value, (tuple, list)): + vector = type(self.default_value)(*vector) + + self.value = vector + + + @property + def value(self): + if len(self._value) == 1: + return self._value[0] + return self._value + + @value.setter + def value(self, value): + self._value = value + if len(value) == 1: + value = str(value[0]) + + if self.on_value_changed is not None: + self.on_value_changed() + + for i, field in enumerate(self.fields): + # print('---------', field.text, str(value[i])) + field.text = str(value[i])[:self.character_limit] + + + def input(self, key): + super().input(key) + if key == 'left mouse down': + self._dragging_on = None + self._temp_value = [e for e in self._value] + + for i, field in enumerate(self.fields): + if field.hovered: + self._dragging_on = field + self._value_on_drag_start = self.value + return + + elif key == 'left mouse up' and self._dragging_on: + self._dragging_on = None + self.value = self._value + self._temp_value = self._value + + + def update(self): + if mouse.left and self._dragging_on and not self._dragging_on.active: + # print('drag on:', self._dragging_on, mouse.velocity.x) + idx = self.fields.index(self._dragging_on) + if self.data_type == float: + self._temp_value[idx] += mouse.velocity.x + self._value = [round_to_closest(e, .01) for e in self._temp_value] + elif self.data_type == int: + self._temp_value[idx] += mouse.velocity.x * 10 + self._value = [int(e) for e in self._temp_value] + + for i, field in enumerate(self.fields): # set text temporarily while dragging + field.text_field.text_entity.text = str(self._value[i])[:self.character_limit] + + + +if __name__ == '__main__': + from ursina import * + app = Ursina() + # Entity(parent=camera.ui, model='quad', scale=.05, z=-10) + # field = VecField(text=' field', default_value=Vec3(0,0,0)) + def on_value_changed(): + print('set value to:', field.value) + + field = VecField(text=' int list', default_value=[10,1]) + field = VecField(text=' float list', default_value=[1.0,-2.0], y=-.1) + field = VecField(text=' Vec4', default_value=Vec4(1,-2,0,0), y=-.2) + field = VecField(text=' float', default_value=1.0, y=-.3) + field = VecField(text=' int', default_value=0, y=-.4) + # field.on_value_changed = on_value_changed + + # Entity(color=color.azure, scale=(.5,.05), model='quad', parent=camera.ui) + # InputField(y=-.1) + Sprite('shore', color=color.dark_gray) + app.run()