diff --git a/Difficult_Rocket/api/camera.py b/Difficult_Rocket/api/camera.py index c7360c3..e572e9a 100644 --- a/Difficult_Rocket/api/camera.py +++ b/Difficult_Rocket/api/camera.py @@ -4,9 +4,12 @@ # All rights reserved # ------------------------------- -from Difficult_Rocket.utils.camera import (Camera, CenterCamera) +from Difficult_Rocket.utils.camera import (Camera, + CenterCamera, + GroupCamera) __all__ = [ 'Camera', - 'CenterCamera' + 'CenterCamera', + 'GroupCamera' ] diff --git a/Difficult_Rocket/api/screen.py b/Difficult_Rocket/api/screen.py index 4260821..616ef62 100644 --- a/Difficult_Rocket/api/screen.py +++ b/Difficult_Rocket/api/screen.py @@ -112,6 +112,7 @@ class BaseScreen(EventDispatcher): :event: """ + # def on_draw(self, dt: float, window: ClientWindow): # TODO: wait for pyglet 2.1 def on_draw(self, window: ClientWindow): """The window contents must be redrawn. diff --git a/Difficult_Rocket/client/__init__.py b/Difficult_Rocket/client/__init__.py index 46b0244..25ba1d6 100644 --- a/Difficult_Rocket/client/__init__.py +++ b/Difficult_Rocket/client/__init__.py @@ -275,7 +275,10 @@ class ClientWindow(Window): def start_game(self) -> None: self.set_icon(pyglet.image.load('assets/textures/icon.png')) try: - pyglet.app.run(1 / self.main_config['runtime']['fps']) + # pyglet.clock.schedule_interval(self.on_draw, float(self.SPF)) + # pyglet.app.run() + # TODO: wait for pyglet 2.1 + pyglet.app.run(float(self.SPF)) except KeyboardInterrupt: self.logger.warning("==========client stop. KeyboardInterrupt info==========") traceback.print_exc() @@ -314,11 +317,13 @@ class ClientWindow(Window): self.fps_log.update_tick(now_FPS, decimal_tick) @_call_screen_after - def on_draw(self, *dt): + # def on_draw(self, dt: float): # TODO: wait for pyglet 2.1 + def on_draw(self): while (command := self.game.console.get_command()) is not None: self.on_command(line.CommandText(command)) pyglet.gl.glClearColor(0.1, 0, 0, 0.0) self.clear() + # self.draw_update(dt) # TODO: wait for pyglet 2.1 self.draw_update(float(self.SPF)) self.draw_batch() diff --git a/Difficult_Rocket/client/guis/widgets.py b/Difficult_Rocket/gui/widgets.py similarity index 75% rename from Difficult_Rocket/client/guis/widgets.py rename to Difficult_Rocket/gui/widgets.py index b20d2ea..000877d 100644 --- a/Difficult_Rocket/client/guis/widgets.py +++ b/Difficult_Rocket/gui/widgets.py @@ -26,29 +26,25 @@ from pyglet.text.caret import Caret from pyglet.text.document import UnformattedDocument from pyglet.text.layout import IncrementalTextLayout -# from libs import pyperclip -# from libs.pyperclip import paste - -from Difficult_Rocket.api.types import FontData, Fonts -# from Difficult_Rocket.client.guis.format import html +from Difficult_Rocket.api.types import Fonts from Difficult_Rocket import DR_status -__all__ = ['InputBox'] - class TextButton(widgets.WidgetBase): """ - 自带字符的按钮,就不用单独做材质了 + 自带 字符 + 材质 的按钮,就不用单独做材质了 """ def __init__(self, - x: int, y: int, width: int, height: int, + x: int, + y: int, + width: int, + height: int, text: str, font: str = Fonts.鸿蒙简体, font_size: int = 13): super().__init__(x, y, width, height) 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) @property def value(self): diff --git a/Difficult_Rocket/utils/camera.py b/Difficult_Rocket/utils/camera.py index 0348437..bb9b10f 100644 --- a/Difficult_Rocket/utils/camera.py +++ b/Difficult_Rocket/utils/camera.py @@ -3,11 +3,14 @@ # Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com # All rights reserved # ------------------------------- - # Huge thanks to pyglet developers from typing import Tuple, Optional +from pyglet.gl import gl +from pyglet.math import Mat4, Vec3 +from pyglet.graphics import Group + class Camera: """ @@ -24,8 +27,9 @@ class Camera: >>> camera.end() """ - def __init__(self, - window, + + def __init__(self, + window, zoom: Optional[float] = 1.0, dx: Optional[float] = 1.0, dy: Optional[float] = 1.0, @@ -68,11 +72,11 @@ class Camera: def end(self) -> None: self.window.view = self._stored_view - + def __enter__(self): self.begin() return self - + def __exit__(self, exc_type, exc_val, exc_tb): self.end() @@ -91,8 +95,8 @@ class CenterCamera(Camera): >>> camera.begin() >>> window.clear() >>> camera.end() - """ + def begin(self) -> None: view = self.window.view self._stored_view = view @@ -100,10 +104,77 @@ class CenterCamera(Camera): y = self.window.height / 2.0 / self.zoom + (self.dy / self.zoom) view_matrix = view.translate((x * self.zoom, y * self.zoom, 0)) + # print(f"camera translation {view_matrix}") view_matrix = view_matrix.scale((self.zoom, self.zoom, 1)) self.window.view = view_matrix def end(self) -> None: self.window.view = self._stored_view - \ No newline at end of file + + +class GroupCamera(Group): + """ + A camera by group + can be used by just added to your widget + """ + + def __init__(self, + window, + order: int = 0, + parent: Optional[Group] = None, + view_x: Optional[int] = 0, + view_y: Optional[int] = 0, + zoom: Optional[float] = 1.0, ): + super().__init__(order=order, parent=parent) + self._window = window + self._previous_view = None + + self._view_x = view_x + self._view_y = view_y + self._zoom = zoom + self._zoom_x = self._zoom + self._zoom_y = self._zoom + + @property + def view_x(self) -> int: + return self._view_x + + @view_x.setter + def view_x(self, value: int): + self._view_x = value + + @property + def view_y(self) -> int: + return self._view_y + + @view_y.setter + def view_y(self, value: int): + self._view_y = value + + @property + def zoom(self) -> float: + return self._zoom + + @zoom.setter + def zoom(self, value: float): + self._zoom = value + + def set_state(self): + self._previous_view = self._window.view + # print(self._previous_view) + + x = self._window.width / 2.0 / self._zoom_x + (self._view_x / self._zoom_x) + y = self._window.height / 2.0 / self._zoom_y + (self._view_y / self._zoom_y) + + # view = Mat4.from_translation(Vec3(self._view_x * x, self._view_y * y, 0)) + view = Mat4.from_translation(Vec3(self._view_x, self._view_y, 0)) + # print(f"group translation {view}") + if self._zoom == 1.0: + self._window.view = view + else: + view = view.scale(Vec3(self._zoom, self._zoom, 1)) + self._window.view = view + + def unset_state(self): + self._window.view = self._previous_view diff --git a/mods/dr_game/sr1_ship.py b/mods/dr_game/sr1_ship.py index 052404f..0293b5c 100644 --- a/mods/dr_game/sr1_ship.py +++ b/mods/dr_game/sr1_ship.py @@ -25,7 +25,7 @@ from . import DR_mod_runtime # Difficult Rocket from Difficult_Rocket import DR_status from Difficult_Rocket.utils.translate import Tr -from Difficult_Rocket.api.camera import CenterCamera +from Difficult_Rocket.api.camera import CenterCamera, GroupCamera from Difficult_Rocket.api.types import Fonts, Options from Difficult_Rocket.command.line import CommandText from Difficult_Rocket.client.screen import BaseScreen @@ -38,8 +38,7 @@ if DR_mod_runtime.use_DR_rust: from .Difficult_Rocket_rs import (SR1PartList_rs, SR1Ship_rs, SR1PartData_rs, - SR1PartType_rs, - map_ptype_textures) + SR1PartType_rs) logger = logging.getLogger('client.dr_game_sr1_ship') logger.level = logging.DEBUG @@ -82,6 +81,8 @@ class SR1ShipRender(BaseScreen): self.buffer.attach_texture(self.render_texture) self.main_batch = Batch() + # self.group_camera = GroupCamera(window=main_window, order=10, parent=main_window.main_group) + # self.part_group = Group(0, parent=self.group_camera) self.part_group = Group(10, parent=main_window.main_group) self.debug_label = Label(x=20, y=main_window.height - 100, font_size=DR_status.std_font_size, @@ -163,10 +164,11 @@ class SR1ShipRender(BaseScreen): # rust 渲染 if DR_mod_runtime.use_DR_rust: cache = self.rust_ship.as_dict() + part_group = Group(2, parent=self.part_group) + line_box_group = Group(6, parent=self.part_group) for p_id, parts in cache.items(): p_id: int parts: List[Tuple[SR1PartType_rs, SR1PartData_rs]] - part_group = Group(2, parent=self.part_group) batch = [] for p_type, p_data in parts: sprite_name = self.part_list_rs.get_part_type(p_data.part_type_id).sprite @@ -178,7 +180,6 @@ class SR1ShipRender(BaseScreen): part_sprite.scale_y = -1 if p_data.flip_y else 1 batch.append(part_sprite) - line_box_group = Group(6, parent=self.part_group) part_box = self.rust_ship.get_part_box(p_id) if part_box: # 线框 @@ -285,9 +286,11 @@ class SR1ShipRender(BaseScreen): window.clear() with self.camera: self.main_batch.draw() + # self.main_batch.draw() # use group camera, no need to with self.buffer.unbind() self.render_texture.blit(x=self.dx, y=self.dy, z=0, width=self.width, height=self.height) + # def on_draw(self, dt: float, window): # TODO: wait for pyglet 2.1 def on_draw(self, window: "ClientWindow"): if self.status.draw_call: self.render_ship() @@ -443,6 +446,8 @@ class SR1ShipRender(BaseScreen): if self.status.focus: self.camera.dx += dx self.camera.dy += dy + self.group_camera.view_x += dx + self.group_camera.view_y += dy self.status.update_call = True elif self.status.moving: # 如果是在移动整体渲染位置