ursina_ui.py 12.1 KB
Newer Older
三月三net's avatar
三月三net 已提交
1 2 3 4 5 6 7 8 9
# -*- coding:utf-8 -*-
# title           :ursina天体运行模拟器UI控制
# description     :ursina天体运行模拟器UI控制
# author          :Python超人
# date            :2023-02-11
# link            :https://gitcode.net/pythoncr/
# python_version  :3.8
# ==============================================================================
from ursina import Ursina, window, Entity, Grid, Mesh, camera, Text, application, color, mouse, Vec2, Vec3, \
三月三net's avatar
三月三net 已提交
10
    load_texture, held_keys, Button, ButtonList, destroy, scene, distance
三月三net's avatar
三月三net 已提交
11
from ursina.prefabs.first_person_controller import FirstPersonController
三月三net's avatar
三月三net 已提交
12

三月三net's avatar
三月三net 已提交
13
from common.consts import AU
三月三net's avatar
三月三net 已提交
14
from simulators.ursina.ui_component import UiSlider, SwithButton, UiButton
三月三net's avatar
三月三net 已提交
15 16
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
三月三net's avatar
三月三net 已提交
17
from ursina import WindowPanel, InputField, Button, Slider, ButtonGroup, Panel
三月三net's avatar
三月三net 已提交
18 19 20 21


class UrsinaUI:

三月三net's avatar
三月三net 已提交
22
    def ui_component_init(self):
三月三net's avatar
三月三net 已提交
23

三月三net's avatar
三月三net 已提交
24 25 26 27
        self.start_button_text = "●"  # 》●▲○◎
        self.pause_button_text = "〓"  # 〓 || ‖
        self.no_trail_button_text = "○ "
        self.trail_button_text = "○--"
三月三net's avatar
三月三net 已提交
28

三月三net's avatar
三月三net 已提交
29
        application.time_scale = 0.5
三月三net's avatar
三月三net 已提交
30
        self.slider_body_spin_factor = UiSlider(text='自转速度', min=0.01, max=30, default=1)
三月三net's avatar
三月三net 已提交
31
        self.slider_body_size_factor = UiSlider(text='天体缩放', min=0.01, max=10, default=1)
三月三net's avatar
三月三net 已提交
32 33 34
        self.slider_run_speed_factor = UiSlider(text="运行速度", min=0.01, max=800, default=1)
        self.slider_control_speed_factor = UiSlider(text="控制速度", min=0.01, max=30, default=application.time_scale)
        self.slider_trail_length = UiSlider(text="拖尾长度", min=30, max=500, default=UrsinaConfig.trail_length)
三月三net's avatar
三月三net 已提交
35

三月三net's avatar
三月三net 已提交
36
        self.slider_body_size_factor.on_value_changed = self.on_slider_body_size_changed
三月三net's avatar
三月三net 已提交
37 38 39
        self.slider_body_spin_factor.on_value_changed = self.on_slider_body_spin_changed
        self.slider_run_speed_factor.on_value_changed = self.on_slider_run_speed_changed
        self.slider_control_speed_factor.on_value_changed = self.on_slider_control_speed_changed
三月三net's avatar
三月三net 已提交
40 41
        self.slider_trail_length.on_value_changed = self.on_slider_trail_length_changed

三月三net's avatar
三月三net 已提交
42
        self.on_off_switch = SwithButton((self.pause_button_text,
三月三net's avatar
三月三net 已提交
43 44 45
                                          self.start_button_text),
                                         default=self.start_button_text,
                                         tooltips=('暂停', '运行'))
三月三net's avatar
三月三net 已提交
46
        self.on_off_switch.selected_color = color.red
三月三net's avatar
三月三net 已提交
47

三月三net's avatar
三月三net 已提交
48 49 50 51 52 53
        self.sec_per_time_switch = SwithButton(("默认", "天", "周", "月", "年", "十年", "百年"),
                                               default="默认",
                                               tooltips=("系统默认", "每秒相当于1天", "每秒相当于1周",
                                                         "每秒相当于1个月",
                                                         "每秒相当于1年", "每秒相当于十年", "每秒相当于1百年"))

三月三net's avatar
三月三net 已提交
54 55 56
        self.on_off_trail = SwithButton((self.no_trail_button_text, self.trail_button_text),
                                        default=self.no_trail_button_text,
                                        tooltips=('天体运行无轨迹', '天体运行有拖尾轨迹'))
三月三net's avatar
三月三net 已提交
57 58
        self.on_off_trail.on_value_changed = self.on_off_trail_changed

三月三net's avatar
三月三net 已提交
59
        self.point_button = UiButton(text='寻找', on_click=self.on_searching_bodies_click)
三月三net's avatar
三月三net 已提交
60
        self.reset_button = UiButton(text='重置', on_click=self.on_reset_button_click)
三月三net's avatar
三月三net 已提交
61

三月三net's avatar
三月三net 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
        # button1 = Button(text='Button 1', scale=(0.1, 0.1), position=(-0.1, 0))
        # button2 = Button(text='Button 2', scale=(0.1, 0.1), position=(0.1, 0))

        # btn_settings = UiButton(text='操作设置', on_click=self.on_point_button_click)
        # btn_settings.position = window.top_left
        # btn_settings.y = 0.5
        # # btn_settings.scale = (0.1,0.1)
        # # btn_settings.y = 0
        # btn_settings.scale = (.25, .025),
        # btn_settings.origin = (-.5, .5),
        # btn_settings.pressed_scale = 1,
        # if btn_settings.text_entity:
        #     btn_settings.text_entity.x = .05
        #     btn_settings.text_entity.origin = (-.5, 0)
        #     btn_settings.text_entity.scale *= .8
三月三net's avatar
三月三net 已提交
77 78

        self.on_off_switch.on_value_changed = self.on_off_switch_changed
三月三net's avatar
三月三net 已提交
79 80 81
        wp = WindowPanel(
            title='',
            content=(
三月三net's avatar
三月三net 已提交
82
                Text('方位控制: Q W E A S D + 鼠标右键', font='msyhl.ttc'),
三月三net's avatar
三月三net 已提交
83 84 85 86
                # InputField(name='name_field'),
                # Button(text='Submit', color=color.azure),
                self.point_button,
                self.reset_button,
三月三net's avatar
三月三net 已提交
87
                self.sec_per_time_switch,
三月三net's avatar
三月三net 已提交
88
                self.on_off_switch,
三月三net's avatar
三月三net 已提交
89 90
                self.on_off_trail,
                self.slider_trail_length,
三月三net's avatar
三月三net 已提交
91
                self.slider_body_size_factor,
三月三net's avatar
三月三net 已提交
92 93 94 95
                self.slider_body_spin_factor,
                self.slider_run_speed_factor,
                self.slider_control_speed_factor

三月三net's avatar
三月三net 已提交
96
            ), ignore_paused=True, color=color.rgba(0.0, 0.0, 0.0, 0.5)  # , popup=True
三月三net's avatar
三月三net 已提交
97
        )
三月三net's avatar
三月三net 已提交
98 99 100
        self.sec_per_time_switch.x = -0.5
        self.on_off_switch.x = -0.2
        self.on_off_trail.x = -0.2
三月三net's avatar
三月三net 已提交
101
        wp.y = 0.5  # wp.panel.scale_y / 2 * wp.scale_y  # center the window panel
三月三net's avatar
三月三net 已提交
102
        wp.x = 0.6  # wp.scale_x + 0.1
三月三net's avatar
三月三net 已提交
103
        # wp.x = 0#wp.panel.scale_x / 2 * wp.scale_x
三月三net's avatar
三月三net 已提交
104
        self.wp = wp
三月三net's avatar
三月三net 已提交
105
        self.wp.enabled = False
三月三net's avatar
三月三net 已提交
106

三月三net's avatar
三月三net 已提交
107 108 109
    def __init__(self):
        self.ui_component_init()

三月三net's avatar
三月三net 已提交
110
        self.settings_handler = Entity(ignore_paused=True)
三月三net's avatar
三月三net 已提交
111 112 113 114
        # 加载中文字体文件

        # text_time_scale = "1"
        # self.text_time_scale_info = None
三月三net's avatar
三月三net 已提交
115
        self.settings_handler.input = self.settings_handler_input
三月三net's avatar
三月三net 已提交
116
        # self.show_text_time_scale_info()
三月三net's avatar
三月三net 已提交
117 118 119
        key_info_str = "按[空格]设置"
        key_info = Text(text=key_info_str, font=UrsinaConfig.CN_FONT, position=(-0.5, 0.5), origin=(-1, 1),
                        background=True)
三月三net's avatar
三月三net 已提交
120 121 122 123
        # # self.show_button()
        # slider_text = Text(text='自转速度', scale=1, position=(-0.6, 0.3))
        # slider = Slider(scale=0.5, position=(-0.6, 0), min=0, max=10, step=1, text=slider_text)

三月三net's avatar
三月三net 已提交
124
    def on_off_trail_changed(self):
三月三net's avatar
三月三net 已提交
125
        if self.on_off_trail.value == self.trail_button_text:
三月三net's avatar
三月三net 已提交
126 127 128 129
            UrsinaConfig.show_trail = True
        else:
            UrsinaConfig.show_trail = False

三月三net's avatar
三月三net 已提交
130
    def bodies_button_list_click(self, item):
三月三net's avatar
三月三net 已提交
131
        if item is not None:
三月三net's avatar
三月三net 已提交
132 133 134 135 136 137 138 139
            # TODO: 先找到位置,确定摄像机的位置
            # print("select->", item)
            # UrsinaConfig.SCALE_FACTOR
            x = item.planet.scale_x * 10
            camera.position = item.planet.position + Vec3(-x, 0, 0)
            camera.look_at(item.planet)
            camera.rotation = (0, 90, 0)
            # camera.forward = (1, 0, 0)  # 设置相机的方向向量为x轴方向
三月三net's avatar
三月三net 已提交
140 141 142

        destroy(self.bodies_button_list)

三月三net's avatar
三月三net 已提交
143 144 145 146 147 148 149 150 151 152
    # my_entity = Entity(model='cube', color=color.red, position=(0, 1, 5))
    #
    # # 获取当前摄像机
    # camera = scene.camera
    #
    # # 计算 Entity 和摄像机之间的距离
    # distance_to_entity = distance(my_entity, camera)
    #
    # print('距离:', distance_to_entity)

三月三net's avatar
三月三net 已提交
153 154 155 156 157
    def on_searching_bodies_click(self):
        results = UrsinaEvent.on_searching_bodies()
        if len(results) > 0:
            sub_name, bodies = results[0]
            # print(results[0])
三月三net's avatar
三月三net 已提交
158
            button_dict = {"[关闭]": lambda: self.bodies_button_list_click(None)}
三月三net's avatar
三月三net 已提交
159
            camera = scene.camera
三月三net's avatar
三月三net 已提交
160 161 162 163
            for body in bodies:
                def callback_action(b=body):
                    self.bodies_button_list_click(b)

三月三net's avatar
三月三net 已提交
164 165 166 167 168 169 170 171
                if body.appeared:
                    distance_to_entity = distance(body.planet, camera)
                    d = distance_to_entity / UrsinaConfig.SCALE_FACTOR / AU
                    name = f"{body.name}\t距离:{d:.4f}天文单位"
                    button_dict[name] = callback_action
                else:
                    name = f"{body.name}\t距离太远,找不到了"
                    button_dict[name] = lambda: self.bodies_button_list_click(None)
三月三net's avatar
三月三net 已提交
172

三月三net's avatar
三月三net 已提交
173 174
            if hasattr(self, "bodies_button_list"):
                destroy(self.bodies_button_list)
三月三net's avatar
三月三net 已提交
175 176
            self.bodies_button_list = ButtonList(button_dict, font=UrsinaConfig.CN_FONT, button_height=1.5)
            # self.bodies_button_list.input = self.bodies_button_list_input
三月三net's avatar
三月三net 已提交
177 178 179 180 181

    def on_reset_button_click(self):
        UrsinaEvent.on_reset()

    def on_off_switch_changed(self):
三月三net's avatar
三月三net 已提交
182
        if self.on_off_switch.value == self.pause_button_text:
三月三net's avatar
三月三net 已提交
183 184
            self.on_off_switch.selected_color = color.green
            application.paused = True
三月三net's avatar
三月三net 已提交
185 186 187 188
            for c in self.wp.children:
                if not c.ignore_paused:
                    # c.enabled = True
                    c.disabled = False
三月三net's avatar
三月三net 已提交
189 190 191
        else:
            self.on_off_switch.selected_color = color.red
            application.paused = False
三月三net's avatar
三月三net 已提交
192 193 194 195
            for c in self.wp.children:
                if not c.ignore_paused:
                    # c.enabled = True
                    c.disabled = False
三月三net's avatar
三月三net 已提交
196

三月三net's avatar
三月三net 已提交
197 198 199
    def on_slider_trail_length_changed(self):
        UrsinaConfig.trail_length = int(self.slider_trail_length.value)

三月三net's avatar
三月三net 已提交
200 201 202 203 204 205
    def on_slider_control_speed_changed(self):
        application.time_scale = self.slider_control_speed_factor.value

    def on_slider_body_spin_changed(self):
        UrsinaConfig.body_spin_factor = self.slider_body_spin_factor.value

三月三net's avatar
三月三net 已提交
206 207 208
    def on_slider_body_size_changed(self):
        UrsinaConfig.body_size_factor = self.slider_body_size_factor.value

三月三net's avatar
三月三net 已提交
209 210 211 212 213 214 215 216 217
    def on_slider_run_speed_changed(self):
        UrsinaConfig.run_speed_factor = self.slider_run_speed_factor.value

    def show_text_time_scale_info(self):
        if self.text_time_scale_info is not None:
            self.text_time_scale_info.disable()
        text_time_scale = "控制倍率:" + str(application.time_scale).ljust(4, " ")
        text_time_scale_info = Text(text=text_time_scale, position=(-0.8, 0.5), origin=(-1, 1), background=True)

三月三net's avatar
三月三net 已提交
218 219
    # def show_button(self):
    #     b = Button(scale=(0, .25), text='zzz')
三月三net's avatar
三月三net 已提交
220 221 222 223 224 225 226 227

    #  if key == "escape":
    #             if mouse.locked:
    #                 self.on_disable()
    #             else:
    #                 sys.exit()

    # 按空格键则暂停
三月三net's avatar
三月三net 已提交
228
    def settings_handler_input(self, key):
三月三net's avatar
三月三net 已提交
229 230 231 232 233
        import sys
        if key == "escape":
            sys.exit()
        # print(key)
        elif key == 'space':
三月三net's avatar
三月三net 已提交
234
            self.wp.enabled = not self.wp.enabled
三月三net's avatar
三月三net 已提交
235 236
        elif key == 'left mouse down':
            print(key)
三月三net's avatar
三月三net 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
        #     application.paused = not application.paused  # Pause/unpause the game.
        # elif key == 'tab':
        #     # application.time_scale 属性控制游戏时间流逝的速度。
        #     # 具体来说,它是一个浮点数,用于调整游戏时间流逝速度的比例,其默认值为 1.0,表示正常速度。
        #     # 当你将它设置为小于 1.0 的值时,游戏时间会变慢,而设置为大于 1.0 的值时,游戏时间则会变快。
        #     for idx, time_scale in enumerate(time_scales):
        #         if float(application.time_scale) == time_scale:
        #             if idx < len(time_scales) - 1:
        #                 application.time_scale = time_scales[idx + 1]
        #                 break
        #             else:
        #                 application.time_scale = time_scales[0]
        # elif key == '+':
        #     UrsinaConfig.run_speed_factor *= 2
        # elif key == "= up":
        #     UrsinaConfig.body_spin_factor *= 2
        #     # if application.time_scale in time_scales:
        #     #     idx = time_scales.index(application.time_scale)
        #     #     if idx < len(time_scales) - 1:
        #     #         application.time_scale = time_scales[idx + 1]
        # elif key == '-':
        #     UrsinaConfig.run_speed_factor *= 0.5
        # elif key == "- up":
        #     UrsinaConfig.body_spin_factor *= 0.5
        #     # if application.time_scale in time_scales:
        #     #     idx = time_scales.index(application.time_scale)
        #     #     if idx > 0:
        #     #         application.time_scale = time_scales[idx - 1]
        #
        # self.show_text_time_scale_info()