ursina_ui.py 13.0 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, Sequence, Wait, Func
三月三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, invoke
三月三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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    def show_message(self, message, close_time=3):
        """
        创建消息框
        :param message: 消息内容
        :param close_time: 定义关闭时间
        :return:
        """
        # 创建消息框
        message_box = Text(text=message, font=UrsinaConfig.CN_FONT, background=True, origin=(0, 0), y=.25)

        # 定义关闭函数
        def close_message():
            destroy(message_box)

        s = Sequence(
            Wait(3),
            Func(close_message)
        )
        s.start()
        # # 使用 time 模块来实现定时关闭
        # invoke(close_message, delay=close_time)

三月三net's avatar
三月三net 已提交
146
    def on_off_trail_changed(self):
三月三net's avatar
三月三net 已提交
147
        if self.on_off_trail.value == self.trail_button_text:
三月三net's avatar
三月三net 已提交
148 149 150 151
            UrsinaConfig.show_trail = True
        else:
            UrsinaConfig.show_trail = False

三月三net's avatar
三月三net 已提交
152
    def bodies_button_list_click(self, item):
三月三net's avatar
三月三net 已提交
153
        if item is not None:
三月三net's avatar
三月三net 已提交
154 155 156 157 158 159 160 161
            # 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 已提交
162 163 164

        destroy(self.bodies_button_list)

三月三net's avatar
三月三net 已提交
165 166 167 168 169 170 171 172 173 174
    # 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 已提交
175 176 177 178
    def on_searching_bodies_click(self):
        results = UrsinaEvent.on_searching_bodies()
        if len(results) > 0:
            sub_name, bodies = results[0]
三月三net's avatar
三月三net 已提交
179 180 181 182
            if len(bodies) == 0:
                self.show_message("天体都飞不见了,请重新运行。")
                # button_dict = {"天体都飞不见了,请重新运行。": lambda: self.bodies_button_list_click(None)}
                return
三月三net's avatar
三月三net 已提交
183
            # print(results[0])
三月三net's avatar
三月三net 已提交
184
            button_dict = {"[关闭]": lambda: self.bodies_button_list_click(None)}
三月三net's avatar
三月三net 已提交
185
            camera = scene.camera
三月三net's avatar
三月三net 已提交
186 187 188 189
            for body in bodies:
                def callback_action(b=body):
                    self.bodies_button_list_click(b)

三月三net's avatar
三月三net 已提交
190 191 192 193 194 195 196 197
                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 已提交
198

三月三net's avatar
三月三net 已提交
199 200
            if hasattr(self, "bodies_button_list"):
                destroy(self.bodies_button_list)
三月三net's avatar
三月三net 已提交
201 202
            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 已提交
203 204 205 206 207

    def on_reset_button_click(self):
        UrsinaEvent.on_reset()

    def on_off_switch_changed(self):
三月三net's avatar
三月三net 已提交
208
        if self.on_off_switch.value == self.pause_button_text:
三月三net's avatar
三月三net 已提交
209 210
            self.on_off_switch.selected_color = color.green
            application.paused = True
三月三net's avatar
三月三net 已提交
211 212 213 214
            for c in self.wp.children:
                if not c.ignore_paused:
                    # c.enabled = True
                    c.disabled = False
三月三net's avatar
三月三net 已提交
215 216 217
        else:
            self.on_off_switch.selected_color = color.red
            application.paused = False
三月三net's avatar
三月三net 已提交
218 219 220 221
            for c in self.wp.children:
                if not c.ignore_paused:
                    # c.enabled = True
                    c.disabled = False
三月三net's avatar
三月三net 已提交
222

三月三net's avatar
三月三net 已提交
223 224 225
    def on_slider_trail_length_changed(self):
        UrsinaConfig.trail_length = int(self.slider_trail_length.value)

三月三net's avatar
三月三net 已提交
226 227 228 229 230 231
    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 已提交
232 233 234
    def on_slider_body_size_changed(self):
        UrsinaConfig.body_size_factor = self.slider_body_size_factor.value

三月三net's avatar
三月三net 已提交
235 236 237 238 239 240 241 242 243
    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 已提交
244 245
    # def show_button(self):
    #     b = Button(scale=(0, .25), text='zzz')
三月三net's avatar
三月三net 已提交
246 247 248 249 250 251 252 253

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

    # 按空格键则暂停
三月三net's avatar
三月三net 已提交
254
    def settings_handler_input(self, key):
三月三net's avatar
三月三net 已提交
255 256 257 258 259
        import sys
        if key == "escape":
            sys.exit()
        # print(key)
        elif key == 'space':
三月三net's avatar
三月三net 已提交
260
            self.wp.enabled = not self.wp.enabled
三月三net's avatar
三月三net 已提交
261 262
        elif key == 'left mouse down':
            print(key)
三月三net's avatar
三月三net 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
        #     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()