Compare commits
3 Commits
bff9649ca9
...
2e509575cd
Author | SHA1 | Date | |
---|---|---|---|
2e509575cd | |||
33d5788826 | |||
6dbffb322d |
9
Difficult_Rocket/api/gui/__init__.py
Normal file
9
Difficult_Rocket/api/gui/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# -------------------------------
|
||||||
|
# Difficult Rocket
|
||||||
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
||||||
|
# All rights reserved
|
||||||
|
# -------------------------------
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'widget'
|
||||||
|
]
|
11
Difficult_Rocket/api/gui/widget/__init__.py
Normal file
11
Difficult_Rocket/api/gui/widget/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# -------------------------------
|
||||||
|
# Difficult Rocket
|
||||||
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
||||||
|
# All rights reserved
|
||||||
|
# -------------------------------
|
||||||
|
|
||||||
|
from Difficult_Rocket.gui.widget.button import PressTextButton
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'PressTextButton'
|
||||||
|
]
|
@ -247,7 +247,7 @@ class ClientWindow(Window):
|
|||||||
batch=self.main_batch, text='', group=Group(1000, parent=self.main_group)) # 实例化
|
batch=self.main_batch, text='', group=Group(1000, parent=self.main_group)) # 实例化
|
||||||
self.input_box.push_handlers(self)
|
self.input_box.push_handlers(self)
|
||||||
self.input_box.set_handler('on_commit', self.on_input)
|
self.input_box.set_handler('on_commit', self.on_input)
|
||||||
self.set_handlers(self.input_box)
|
self.push_handlers(self.input_box)
|
||||||
self.input_box.enabled = True
|
self.input_box.enabled = True
|
||||||
# 设置刷新率
|
# 设置刷新率
|
||||||
# pyglet.clock.schedule_interval(self.draw_update, float(self.SPF))
|
# pyglet.clock.schedule_interval(self.draw_update, float(self.SPF))
|
||||||
@ -424,7 +424,7 @@ class ClientWindow(Window):
|
|||||||
...
|
...
|
||||||
|
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
def on_mouse_motion(self, x, y, dx, dy) -> None:
|
def on_mouse_motion(self, x, y, dx, dy):
|
||||||
...
|
...
|
||||||
|
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
|
@ -15,19 +15,36 @@ from typing import Optional, Union, Tuple
|
|||||||
|
|
||||||
# from libs import pyglet
|
# from libs import pyglet
|
||||||
# from pyglet import font
|
# from pyglet import font
|
||||||
from pyglet.text import Label, HTMLLabel
|
from pyglet.text import Label
|
||||||
from pyglet.window import key
|
from pyglet.window import mouse
|
||||||
from pyglet.gui import widgets
|
from pyglet.gui import widgets
|
||||||
# from pyglet.sprite import Sprite
|
# from pyglet.sprite import Sprite
|
||||||
from pyglet.shapes import Rectangle
|
from pyglet.shapes import Rectangle
|
||||||
# from pyglet.image import AbstractImage
|
# from pyglet.image import AbstractImage
|
||||||
from pyglet.graphics import Batch, Group
|
from pyglet.graphics import Batch, Group
|
||||||
from pyglet.text.caret import Caret
|
|
||||||
from pyglet.text.document import UnformattedDocument
|
|
||||||
from pyglet.text.layout import IncrementalTextLayout
|
|
||||||
|
|
||||||
from Difficult_Rocket.api.types import Fonts
|
from Difficult_Rocket.api.types import Fonts
|
||||||
from Difficult_Rocket import DR_status
|
|
||||||
|
# from Difficult_Rocket import DR_status
|
||||||
|
|
||||||
|
|
||||||
|
RGBA = Tuple[int, int, int, int]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTheme:
|
||||||
|
"""
|
||||||
|
用于定义主题的类
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
main_color: RGBA = (39, 73, 114, 256),
|
||||||
|
secondary_color: RGBA = (66, 150, 250, 256),
|
||||||
|
main_font: str = Fonts.鸿蒙简体,
|
||||||
|
):
|
||||||
|
self.main_color = main_color
|
||||||
|
self.secondary_color = secondary_color
|
||||||
|
self.main_font = main_font
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PressTextButton(widgets.WidgetBase):
|
class PressTextButton(widgets.WidgetBase):
|
||||||
@ -47,15 +64,17 @@ class PressTextButton(widgets.WidgetBase):
|
|||||||
group: Optional[Group] = None,
|
group: Optional[Group] = None,
|
||||||
):
|
):
|
||||||
super().__init__(x, y, width, height)
|
super().__init__(x, y, width, height)
|
||||||
self.back_ground_batch = Batch()
|
self.back_ground_batch = batch or Batch()
|
||||||
self.front_batch = batch or Batch()
|
self.front_batch = batch or Batch()
|
||||||
if group:
|
if group:
|
||||||
self.front_group = Group(order=5, parent=group)
|
self.front_group = Group(order=10, parent=group)
|
||||||
self.back_ground_group = Group(order=10, parent=group)
|
self.back_ground_group = Group(order=5, parent=group)
|
||||||
else:
|
else:
|
||||||
self.front_group = Group(order=5)
|
self.front_group = Group(order=5)
|
||||||
self.back_ground_group = Group(order=10)
|
self.back_ground_group = Group(order=10)
|
||||||
|
|
||||||
|
self.pressed = False
|
||||||
|
|
||||||
self.untouched_color = (39, 73, 114, 255)
|
self.untouched_color = (39, 73, 114, 255)
|
||||||
self.touched_color = (66, 150, 250, 255)
|
self.touched_color = (66, 150, 250, 255)
|
||||||
self.hit_color = (15, 135, 250, 255)
|
self.hit_color = (15, 135, 250, 255)
|
||||||
@ -63,7 +82,8 @@ class PressTextButton(widgets.WidgetBase):
|
|||||||
|
|
||||||
self.text = text
|
self.text = text
|
||||||
self.text_label = Label(font_name=font, font_size=font_size,
|
self.text_label = Label(font_name=font, font_size=font_size,
|
||||||
batch=self.front_batch, group=self.front_group)
|
batch=self.front_batch, group=self.front_group,
|
||||||
|
x=self._x, y=self._y, text=self.text)
|
||||||
self.back_rec = Rectangle(x=self._x, y=self._y, width=self._width, height=self._height,
|
self.back_rec = Rectangle(x=self._x, y=self._y, width=self._width, height=self._height,
|
||||||
color=self.untouched_color, # ImGui color
|
color=self.untouched_color, # ImGui color
|
||||||
batch=self.back_ground_batch, group=self.back_ground_group)
|
batch=self.back_ground_batch, group=self.back_ground_group)
|
||||||
@ -76,18 +96,25 @@ class PressTextButton(widgets.WidgetBase):
|
|||||||
return item in self.back_rec
|
return item in self.back_rec
|
||||||
|
|
||||||
def on_mouse_motion(self, x, y, dx, dy):
|
def on_mouse_motion(self, x, y, dx, dy):
|
||||||
if (x, y) in self:
|
if (x, y) in self.back_rec:
|
||||||
self.back_rec.color = self.touched_color
|
self.back_rec.color = self.touched_color
|
||||||
else:
|
else:
|
||||||
|
self.pressed = False
|
||||||
self.back_rec.color = self.untouched_color
|
self.back_rec.color = self.untouched_color
|
||||||
|
|
||||||
def on_mouse_press(self, x, y, buttons, modifiers):
|
def on_mouse_press(self, x, y, buttons, modifiers) -> bool:
|
||||||
if (x, y) in self:
|
if (x, y) in self and buttons == mouse.LEFT:
|
||||||
self.back_rec.color = self.hit_color
|
self.back_rec.color = self.hit_color
|
||||||
self.dispatch_event('on_press', x, y)
|
self.dispatch_event('on_press', x, y)
|
||||||
|
self.pressed = True
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def on_mouse_release(self, x, y, buttons, modifiers):
|
||||||
|
if self.pressed and (x, y) in self:
|
||||||
|
self.back_rec.color = self.touched_color
|
||||||
|
self.pressed = False
|
||||||
|
|
||||||
def _update_position(self):
|
def _update_position(self):
|
||||||
self.text_label.position = self._x, self._y
|
self.text_label.position = self._x, self._y
|
||||||
self.back_rec.position = self._x, self._y
|
self.back_rec.position = self._x, self._y
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
|
|
||||||
|
import shutil
|
||||||
import traceback
|
import traceback
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
@ -175,15 +176,12 @@ class Options:
|
|||||||
self.cached_options = self.option()
|
self.cached_options = self.option()
|
||||||
return self.cached_options
|
return self.cached_options
|
||||||
|
|
||||||
def option_with_len(self, longest: Optional[int] = None) -> Tuple[List[Tuple[str, Union[Any, Type], Type]], int, int, int]:
|
def option_with_len(self) -> Tuple[List[Tuple[str, Any, Type]], int, int, int]:
|
||||||
"""
|
"""
|
||||||
返回一个可以用于打印的 option 列表
|
返回一个可以用于打印的 option 列表
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if longest is None:
|
options = self.flush_option()
|
||||||
options = self.flush_option()
|
|
||||||
else:
|
|
||||||
options = self.str_option(longest)
|
|
||||||
max_len_key = 1
|
max_len_key = 1
|
||||||
max_len_value = 1
|
max_len_value = 1
|
||||||
max_len_value_t = 1
|
max_len_value_t = 1
|
||||||
@ -193,19 +191,53 @@ class Options:
|
|||||||
max_len_key = max(max_len_key, len(key))
|
max_len_key = max(max_len_key, len(key))
|
||||||
max_len_value = max(max_len_value, len(str(value)))
|
max_len_value = max(max_len_value, len(str(value)))
|
||||||
max_len_value_t = max(max_len_value_t, len(str(value_t)))
|
max_len_value_t = max(max_len_value_t, len(str(value_t)))
|
||||||
option_list.append((key, value, value_t))
|
option_list.append([key, value, value_t])
|
||||||
return option_list, max_len_key, max_len_value, max_len_value_t
|
return [option_list, max_len_key, max_len_value, max_len_value_t] # noqa
|
||||||
|
|
||||||
def as_markdown(self, longest: Optional[int] = None) -> str:
|
def as_markdown(self, longest: Optional[int] = None) -> str:
|
||||||
"""
|
"""
|
||||||
返回一个 markdown 格式的 option 字符串
|
返回一个 markdown 格式的 option 字符串
|
||||||
:return: markdown 格式的 option 字符串
|
:return: markdown 格式的 option 字符串
|
||||||
"""
|
"""
|
||||||
value = self.option_with_len(longest)
|
value = self.option_with_len()
|
||||||
cache = StringIO()
|
cache = StringIO()
|
||||||
option_len = max(value[1], len('Option'))
|
option_len = max(value[1], len('Option'))
|
||||||
value_len = max(value[2], len('Value'))
|
value_len = max(value[2], len('Value'))
|
||||||
value_type_len = max(value[3], len('Value Type'))
|
value_type_len = max(value[3], len('Value Type'))
|
||||||
|
|
||||||
|
# | Option | Value | Value Type |
|
||||||
|
shortest = len('Option" "Value" "Value Type')
|
||||||
|
|
||||||
|
if longest is not None:
|
||||||
|
console_width = max(longest, shortest)
|
||||||
|
else:
|
||||||
|
console_width = shutil.get_terminal_size(fallback=(100, 80)).columns
|
||||||
|
console_width = max(console_width, shortest)
|
||||||
|
|
||||||
|
option_len = min(option_len, console_width // 3)
|
||||||
|
value_len = min(value_len, console_width // 3)
|
||||||
|
value_type_len = min(value_type_len, console_width // 3)
|
||||||
|
# 先指定每一个列的输出最窄宽度, 然后去尝试增加宽度
|
||||||
|
while option_len + value_len + value_type_len + 16 < console_width:
|
||||||
|
# 每一个部分的逻辑都是
|
||||||
|
# 如果现在的输出长度小于原始长度
|
||||||
|
# 并且长度 + 1 之后的总长度依然在允许范围内
|
||||||
|
# 那么就 + 1
|
||||||
|
if option_len < value[1] and option_len + value_len + value_type_len + 1 + 15 < console_width:
|
||||||
|
option_len += 1
|
||||||
|
if value_len < value[2] and option_len + value_len + value_type_len + 1 + 15 < console_width:
|
||||||
|
value_len += 1
|
||||||
|
if value_type_len < value[3] and option_len + value_len + value_type_len + 1 + 15 < console_width:
|
||||||
|
value_type_len += 1
|
||||||
|
|
||||||
|
for k in range(len(value[0])):
|
||||||
|
if len(str(value[0][k][0])) > option_len:
|
||||||
|
value[0][k][0] = str(value[0][k][0])[:value_len - 3] + '..'
|
||||||
|
if len(str(value[0][k][1])) > value_len:
|
||||||
|
value[0][k][1] = str(value[0][k][1])[:value_len - 3] + '..'
|
||||||
|
if len(str(value[0][k][2])) > value_type_len:
|
||||||
|
value[0][k][2] = str(value[0][k][2])[:value_len - 3] + '..'
|
||||||
|
|
||||||
cache.write(
|
cache.write(
|
||||||
f"| Option{' ' * (option_len - 3)}| Value{' ' * (value_len - 2)}| Value Type{' ' * (value_type_len - 7)}|\n")
|
f"| Option{' ' * (option_len - 3)}| Value{' ' * (value_len - 2)}| Value Type{' ' * (value_type_len - 7)}|\n")
|
||||||
cache.write(f'|:{"-" * (option_len + 3)}|:{"-" * (value_len + 3)}|:{"-" * (value_type_len + 3)}|\n')
|
cache.write(f'|:{"-" * (option_len + 3)}|:{"-" * (value_len + 3)}|:{"-" * (value_type_len + 3)}|\n')
|
||||||
|
@ -25,13 +25,12 @@ from .types import SR1Textures, SR1Rotation
|
|||||||
# Difficult Rocket
|
# Difficult Rocket
|
||||||
from Difficult_Rocket import DR_status
|
from Difficult_Rocket import DR_status
|
||||||
from Difficult_Rocket.utils.translate import Tr
|
from Difficult_Rocket.utils.translate import Tr
|
||||||
|
from Difficult_Rocket.client import ClientWindow
|
||||||
from Difficult_Rocket.api.types import Fonts, Options
|
from Difficult_Rocket.api.types import Fonts, Options
|
||||||
from Difficult_Rocket.command.line import CommandText
|
from Difficult_Rocket.command.line import CommandText
|
||||||
from Difficult_Rocket.client.screen import BaseScreen
|
from Difficult_Rocket.client.screen import BaseScreen
|
||||||
from Difficult_Rocket.api.camera import CenterGroupCamera
|
from Difficult_Rocket.api.camera import CenterGroupCamera
|
||||||
|
from Difficult_Rocket.api.gui.widget import PressTextButton
|
||||||
if TYPE_CHECKING:
|
|
||||||
from Difficult_Rocket.client import ClientWindow
|
|
||||||
|
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
from .Difficult_Rocket_rs import (SR1PartList_rs,
|
from .Difficult_Rocket_rs import (SR1PartList_rs,
|
||||||
@ -63,7 +62,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
"""用于渲染 sr1 船的类"""
|
"""用于渲染 sr1 船的类"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
main_window: "ClientWindow"):
|
main_window: ClientWindow):
|
||||||
super().__init__(main_window)
|
super().__init__(main_window)
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
logger.info(sr_tr().mod.info.setup.start())
|
logger.info(sr_tr().mod.info.setup.start())
|
||||||
@ -96,6 +95,12 @@ class SR1ShipRender(BaseScreen):
|
|||||||
x=main_window.width / 2, y=main_window.height / 2)
|
x=main_window.width / 2, y=main_window.height / 2)
|
||||||
self.render_d_label.visible = self.status.draw_d_pos
|
self.render_d_label.visible = self.status.draw_d_pos
|
||||||
|
|
||||||
|
self.test_button = PressTextButton(x=100, y=100,
|
||||||
|
width=100, height=20, text='test button',
|
||||||
|
batch=self.main_batch, group=Group(5, parent=main_window.main_group))
|
||||||
|
# self.test_button.push_handlers(main_window)
|
||||||
|
main_window.push_handlers(self.test_button)
|
||||||
|
|
||||||
# Optional data
|
# Optional data
|
||||||
self.textures: SR1Textures = SR1Textures()
|
self.textures: SR1Textures = SR1Textures()
|
||||||
self.gen_draw: Optional[Generator] = None
|
self.gen_draw: Optional[Generator] = None
|
||||||
@ -269,7 +274,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
len(self.rust_ship.as_list()),
|
len(self.rust_ship.as_list()),
|
||||||
f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
||||||
|
|
||||||
def draw_batch(self, window: "ClientWindow"):
|
def draw_batch(self, window: ClientWindow):
|
||||||
if self.status.draw_done:
|
if self.status.draw_done:
|
||||||
self.render_d_label.text = f'x: {self.group_camera.view_x} y: {self.group_camera.view_y}'
|
self.render_d_label.text = f'x: {self.group_camera.view_x} y: {self.group_camera.view_y}'
|
||||||
self.render_d_label.position = self.group_camera.view_x + (self.window_pointer.width / 2), self.group_camera.view_y + (
|
self.render_d_label.position = self.group_camera.view_x + (self.window_pointer.width / 2), self.group_camera.view_y + (
|
||||||
@ -286,7 +291,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
gl.glDisable(gl.GL_SCISSOR_TEST)
|
gl.glDisable(gl.GL_SCISSOR_TEST)
|
||||||
|
|
||||||
# def on_draw(self, dt: float, window): # TODO: wait for pyglet 2.1
|
# def on_draw(self, dt: float, window): # TODO: wait for pyglet 2.1
|
||||||
def on_draw(self, window: "ClientWindow"):
|
def on_draw(self, window: ClientWindow):
|
||||||
if self.status.draw_call:
|
if self.status.draw_call:
|
||||||
self.render_ship()
|
self.render_ship()
|
||||||
|
|
||||||
@ -301,14 +306,15 @@ class SR1ShipRender(BaseScreen):
|
|||||||
|
|
||||||
self.debug_label.draw()
|
self.debug_label.draw()
|
||||||
|
|
||||||
def on_resize(self, width: int, height: int, window: "ClientWindow"):
|
def on_resize(self, width: int, height: int, window: ClientWindow):
|
||||||
self.debug_label.y = height - 100
|
self.debug_label.y = height - 100
|
||||||
if not self.status.draw_done:
|
if not self.status.draw_done:
|
||||||
return
|
return
|
||||||
self.render_d_line.x2 = width // 2
|
self.render_d_line.x2 = width // 2
|
||||||
self.render_d_line.y2 = height // 2
|
self.render_d_line.y2 = height // 2
|
||||||
|
self.test_button._update_position()
|
||||||
|
|
||||||
def on_mouse_scroll(self, x: int, y: int, scroll_x: int, scroll_y: int, window: "ClientWindow"):
|
def on_mouse_scroll(self, x: int, y: int, scroll_x: int, scroll_y: int, window: ClientWindow):
|
||||||
if not self.status.draw_done:
|
if not self.status.draw_done:
|
||||||
return
|
return
|
||||||
if self.status.focus:
|
if self.status.focus:
|
||||||
@ -344,7 +350,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
size_y = 10
|
size_y = 10
|
||||||
self.size = size_x, size_y
|
self.size = size_x, size_y
|
||||||
|
|
||||||
def on_command(self, command: CommandText, window: "ClientWindow"):
|
def on_command(self, command: CommandText, window: ClientWindow):
|
||||||
""" 解析命令 """
|
""" 解析命令 """
|
||||||
self.logger.info(f'command: {command}')
|
self.logger.info(f'command: {command}')
|
||||||
if command.find('render'):
|
if command.find('render'):
|
||||||
@ -434,7 +440,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
logger.info(sr_tr().sr1.ship.save.start().format(self.rust_ship))
|
logger.info(sr_tr().sr1.ship.save.start().format(self.rust_ship))
|
||||||
self.rust_ship.save('./test-save.xml')
|
self.rust_ship.save('./test-save.xml')
|
||||||
|
|
||||||
def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int, window: "ClientWindow"):
|
def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int, window: ClientWindow):
|
||||||
if self.status.focus:
|
if self.status.focus:
|
||||||
self.group_camera.view_x += dx
|
self.group_camera.view_x += dx
|
||||||
self.group_camera.view_y += dy
|
self.group_camera.view_y += dy
|
||||||
@ -444,7 +450,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.dx += dx
|
self.dx += dx
|
||||||
self.dy += dy
|
self.dy += dy
|
||||||
|
|
||||||
def on_file_drop(self, x: int, y: int, paths: List[str], window: "ClientWindow"):
|
def on_file_drop(self, x: int, y: int, paths: List[str], window: ClientWindow):
|
||||||
if len(paths) > 1:
|
if len(paths) > 1:
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
@ -474,6 +480,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.window_pointer.view = value
|
self.window_pointer.view = value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from objprint import op
|
from objprint import op
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ if __name__ == '__main__':
|
|||||||
else:
|
else:
|
||||||
compiler.output_path = Path(f'./build/nuitka-{platform.system().lower()}')
|
compiler.output_path = Path(f'./build/nuitka-{platform.system().lower()}')
|
||||||
|
|
||||||
print(compiler.as_markdown(longest=70))
|
print(compiler.as_markdown())
|
||||||
|
|
||||||
print(compiler.gen_subprocess_cmd())
|
print(compiler.gen_subprocess_cmd())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user