Compare commits

...

10 Commits

Author SHA1 Message Date
39379c1621
Merge pull request #52 from shenjackyuanjie/dr_game/rust_render
Dr game/rust render
2023-08-12 01:55:12 +08:00
3595f98dc1
Merge pull request #51 from shenjackyuanjie/feature/group_camera
Feature/group camera
2023-08-12 01:54:22 +08:00
aa8af9ebef
DR sdk 0.8.7.0 2023-08-12 01:49:01 +08:00
692483320b
fetch up with DR 2023-08-12 01:20:24 +08:00
09e386e0fe
CenterGroupCamera! 2023-08-12 00:49:46 +08:00
55e83b708f
go for group cam 2023-08-12 00:28:31 +08:00
7278368b4c
sync pyglet 2023-08-09 12:29:18 +08:00
a2f12c2e77
fix little issue DR game 0.3.2.1 2023-08-09 11:55:26 +08:00
47d2629610
DR rs 0.2.21.0 2023-08-08 21:34:20 +08:00
e658fa3188
remove useless 2023-08-08 01:33:12 +08:00
18 changed files with 290 additions and 99 deletions

View File

@ -2,9 +2,5 @@
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml", "mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml",
"libs/pyglet_rs/src/Cargo.toml", "libs/pyglet_rs/src/Cargo.toml",
], ]
"python.analysis.extraPaths": [
"./libs"
],
"python.analysis.typeCheckingMode": "basic"
} }

View File

@ -10,7 +10,7 @@ from pathlib import Path
from Difficult_Rocket.api.types import Options, Version from Difficult_Rocket.api.types import Options, Version
sdk_version = Version("0.8.6.0") # SDK 版本 sdk_version = Version("0.8.7.0") # SDK 版本
build_version = Version("2.1.3.0") # 编译文件版本(与游戏本体无关) build_version = Version("2.1.3.0") # 编译文件版本(与游戏本体无关)
Api_version = Version("0.1.1.0") # API 版本 Api_version = Version("0.1.1.0") # API 版本
__version__ = sdk_version __version__ = sdk_version

View File

@ -4,9 +4,14 @@
# All rights reserved # All rights reserved
# ------------------------------- # -------------------------------
from Difficult_Rocket.utils.camera import (Camera, CenterCamera) from Difficult_Rocket.utils.camera import (Camera,
CenterCamera,
GroupCamera,
CenterGroupCamera)
__all__ = [ __all__ = [
'Camera', 'Camera',
'CenterCamera' 'CenterCamera',
'GroupCamera',
'CenterGroupCamera'
] ]

View File

@ -112,6 +112,7 @@ class BaseScreen(EventDispatcher):
:event: :event:
""" """
# def on_draw(self, dt: float, window: ClientWindow): # TODO: wait for pyglet 2.1
def on_draw(self, window: ClientWindow): def on_draw(self, window: ClientWindow):
"""The window contents must be redrawn. """The window contents must be redrawn.

View File

@ -275,7 +275,10 @@ class ClientWindow(Window):
def start_game(self) -> None: def start_game(self) -> None:
self.set_icon(pyglet.image.load('assets/textures/icon.png')) self.set_icon(pyglet.image.load('assets/textures/icon.png'))
try: 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: except KeyboardInterrupt:
self.logger.warning("==========client stop. KeyboardInterrupt info==========") self.logger.warning("==========client stop. KeyboardInterrupt info==========")
traceback.print_exc() traceback.print_exc()
@ -314,11 +317,13 @@ class ClientWindow(Window):
self.fps_log.update_tick(now_FPS, decimal_tick) self.fps_log.update_tick(now_FPS, decimal_tick)
@_call_screen_after @_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: while (command := self.game.console.get_command()) is not None:
self.on_command(line.CommandText(command)) self.on_command(line.CommandText(command))
pyglet.gl.glClearColor(0.1, 0, 0, 0.0) pyglet.gl.glClearColor(0.1, 0, 0, 0.0)
self.clear() self.clear()
# self.draw_update(dt) # TODO: wait for pyglet 2.1
self.draw_update(float(self.SPF)) self.draw_update(float(self.SPF))
self.draw_batch() self.draw_batch()

View File

@ -26,29 +26,25 @@ from pyglet.text.caret import Caret
from pyglet.text.document import UnformattedDocument from pyglet.text.document import UnformattedDocument
from pyglet.text.layout import IncrementalTextLayout from pyglet.text.layout import IncrementalTextLayout
# from libs import pyperclip from Difficult_Rocket.api.types import Fonts
# from libs.pyperclip import paste
from Difficult_Rocket.api.types import FontData, Fonts
# from Difficult_Rocket.client.guis.format import html
from Difficult_Rocket import DR_status from Difficult_Rocket import DR_status
__all__ = ['InputBox']
class TextButton(widgets.WidgetBase): class TextButton(widgets.WidgetBase):
""" """
自带字符的按钮就不用单独做材质了 自带 字符 + 材质 的按钮就不用单独做材质了
""" """
def __init__(self, def __init__(self,
x: int, y: int, width: int, height: int, x: int,
y: int,
width: int,
height: int,
text: str, text: str,
font: str = Fonts.鸿蒙简体, font_size: int = 13): font: str = Fonts.鸿蒙简体, font_size: int = 13):
super().__init__(x, y, width, height) super().__init__(x, y, width, height)
self.text = text self.text = text
self.text_label = Label( self.text_label = Label(font_name=font, font_size=font_size)
font_name=font, font_size=font_size)
@property @property
def value(self): def value(self):

View File

@ -3,11 +3,14 @@
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com # Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved # All rights reserved
# ------------------------------- # -------------------------------
# Huge thanks to pyglet developers # Huge thanks to pyglet developers
from typing import Tuple, Optional from typing import Tuple, Optional
from pyglet.gl import gl
from pyglet.math import Mat4, Vec3
from pyglet.graphics import Group
class Camera: class Camera:
""" """
@ -24,8 +27,9 @@ class Camera:
>>> camera.end() >>> camera.end()
""" """
def __init__(self,
window, def __init__(self,
window,
zoom: Optional[float] = 1.0, zoom: Optional[float] = 1.0,
dx: Optional[float] = 1.0, dx: Optional[float] = 1.0,
dy: Optional[float] = 1.0, dy: Optional[float] = 1.0,
@ -68,11 +72,16 @@ class Camera:
def end(self) -> None: def end(self) -> None:
self.window.view = self._stored_view self.window.view = self._stored_view
def reset(self):
self.zoom = 1
self.dx = 0
self.dy = 0
def __enter__(self): def __enter__(self):
self.begin() self.begin()
return self return self
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
self.end() self.end()
@ -91,8 +100,8 @@ class CenterCamera(Camera):
>>> camera.begin() >>> camera.begin()
>>> window.clear() >>> window.clear()
>>> camera.end() >>> camera.end()
""" """
def begin(self) -> None: def begin(self) -> None:
view = self.window.view view = self.window.view
self._stored_view = view self._stored_view = view
@ -106,4 +115,99 @@ class CenterCamera(Camera):
def end(self) -> None: def end(self) -> None:
self.window.view = self._stored_view self.window.view = self._stored_view
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,
min_zoom: Optional[float] = 1.0,
max_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
self.min_zoom = min_zoom
self.max_zoom = max_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
self._zoom_x = self._zoom
self._zoom_y = self._zoom
def reset(self):
self._view_x = 0
self._view_y = 0
self.zoom = 1
def set_state(self):
self._previous_view = self._window.view
view = Mat4.from_translation(Vec3(self._view_x, self._view_y, 0))
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
class CenterGroupCamera(GroupCamera):
"""
A camera by group
can be used by just added to your widget
"""
def set_state(self):
self._previous_view = self._window.view
x = (self._window.width / 2) / self._zoom_x + (self._view_x / self._zoom_x)
y = (self._window.height / 2) / self._zoom_y + (self._view_y / self._zoom_y)
view = Mat4.from_translation(Vec3(x * self._zoom_x, y * self._zoom_y, 0))
# 不懂就问 为啥这里 * zoom 下面还 * zoom
if self._zoom == 1.0 and self._zoom_x == 1.0 and self._zoom_y == 1.0:
self._window.view = view
else:
view = view.scale(Vec3(self._zoom_x, self._zoom_y, 1))
self._window.view = view
def unset_state(self):
self._window.view = self._previous_view

View File

@ -2,8 +2,36 @@
# DR game/DR rs 更新日志 # DR game/DR rs 更新日志
- 最新版本号 - 最新版本号
- DR game: 0.3.2.0 - DR game: 0.3.3.0
- DR rs: 0.2.20.2 - DR rs: 0.2.21.0
## 20230812 DR game 0.3.3.0
### Changes
- 将 `sr1_ship` 渲染器使用的 Camera 改成 `CenterGroupCamera`
- 删除了之前的 Camera 相关代码
## 20230809 DR game 0.3.2.1
### Fix
- 因为把部件加载图片的数据源改成从 `SR1PartType_rs` 里取
- 所以修改了 `SR1Textures` 的加载逻辑
- 可以自动忽略文件名最后的 `.png`
## 20230808 DR rs 0.2.21.0
### Add
- 在 `__init__.py` 里添加了
- `sprite`
- `type`
- 的导出 (实际上就是 typing)
- `SR1PartType_rs`
- 添加了 `type` getter
摸鱼真开心
## 20230724 DR rs 0.2.20.2 ## 20230724 DR rs 0.2.20.2

View File

@ -2,7 +2,30 @@
# DR SDK 更新日志 # DR SDK 更新日志
- 最新版本号 - 最新版本号
- DR sdk: 0.8.6.0 - DR sdk: 0.8.7.0
- DR api: 0.1.1.0
## DR sdk 0.8.7.0
### Add
- 添加了 `Difficult_Rocket.utils.camera.GroupCamera`
- 和 `Difficult_Rocket.utils.camera.CenterGroupCamera`
- 实际上就是使用 `pyglet.graphics.Group` 来实现的 `Camera`
- 具有相同的功能
- 顺便同样在 `api.camera` 里添加了导出
- 这次我一定不会再忘记导出了
- Added `Difficult_Rocket.utils.camera.GroupCamera`
- And `Difficult_Rocket.utils.camera.CenterGroupCamera`
- Actually, it is implemented `Camera` using `pyglet.graphics.Group`
- Has the same function
- By the way, the export was also added in `api.camera`
- This time I will never forget to export it again
- 为所有 `xxCamera` 添加了
- `reset` 方法
- 用于一键重置缩放+平移
- Added `reset` method for all `xxCamera`
- Used to reset zoom + translation with one click
## DR sdk 0.8.6.1 ## DR sdk 0.8.6.1

View File

@ -68,12 +68,12 @@ class Win32Config(Config):
if pf: if pf:
return [Win32CanvasConfig(canvas, pf, self)] return [Win32CanvasConfig(canvas, pf, self)]
else: else:
return [] return []
def _get_arb_pixel_format_matching_configs(self, canvas): def _get_arb_pixel_format_matching_configs(self, canvas):
"""Get configs using the WGL_ARB_pixel_format extension. """Get configs using the WGL_ARB_pixel_format extension.
This method assumes a (dummy) GL context is already created.""" This method assumes a (dummy) GL context is already created."""
# Check for required extensions # Check for required extensions
if self.sample_buffers or self.samples: if self.sample_buffers or self.samples:
if not gl_info.have_extension('GL_ARB_multisample'): if not gl_info.have_extension('GL_ARB_multisample'):
@ -85,7 +85,7 @@ class Win32Config(Config):
attr = Win32CanvasConfigARB.attribute_ids.get(name, None) attr = Win32CanvasConfigARB.attribute_ids.get(name, None)
if attr and value is not None: if attr and value is not None:
attrs.extend([attr, int(value)]) attrs.extend([attr, int(value)])
attrs.append(0) attrs.append(0)
attrs = (c_int * len(attrs))(*attrs) attrs = (c_int * len(attrs))(*attrs)
pformats = (c_int * 16)() pformats = (c_int * 16)()
@ -98,7 +98,7 @@ class Win32Config(Config):
class Win32CanvasConfig(CanvasConfig): class Win32CanvasConfig(CanvasConfig):
def __init__(self, canvas, pf, config): def __init__(self, canvas, pf, config):
super(Win32CanvasConfig, self).__init__(canvas, config) super().__init__(canvas, config)
self._pf = pf self._pf = pf
self._pfd = PIXELFORMATDESCRIPTOR() self._pfd = PIXELFORMATDESCRIPTOR()
@ -153,14 +153,14 @@ class Win32CanvasConfigARB(CanvasConfig):
} }
def __init__(self, canvas, pf, config): def __init__(self, canvas, pf, config):
super(Win32CanvasConfigARB, self).__init__(canvas, config) super().__init__(canvas, config)
self._pf = pf self._pf = pf
names = list(self.attribute_ids.keys()) names = list(self.attribute_ids.keys())
attrs = list(self.attribute_ids.values()) attrs = list(self.attribute_ids.values())
attrs = (c_int * len(attrs))(*attrs) attrs = (c_int * len(attrs))(*attrs)
values = (c_int * len(attrs))() values = (c_int * len(attrs))()
wglext_arb.wglGetPixelFormatAttribivARB(canvas.hdc, pf, 0, len(attrs), attrs, values) wglext_arb.wglGetPixelFormatAttribivARB(canvas.hdc, pf, 0, len(attrs), attrs, values)
for name, value in zip(names, values): for name, value in zip(names, values):
@ -182,35 +182,21 @@ class Win32CanvasConfigARB(CanvasConfig):
_gdi32.SetPixelFormat(canvas.hdc, self._pf, None) _gdi32.SetPixelFormat(canvas.hdc, self._pf, None)
class Win32Context(Context): class _BaseWin32Context(Context):
def __init__(self, config, share): def __init__(self, config, share):
super(Win32Context, self).__init__(config, share) super().__init__(config, share)
self._context = None self._context = None
def attach(self, canvas):
super(Win32Context, self).attach(canvas)
if not self._context:
self.config._set_pixel_format(canvas)
self._context = wgl.wglCreateContext(canvas.hdc)
share = self.context_share
if share:
if not share.canvas:
raise RuntimeError('Share context has no canvas.')
if not wgl.wglShareLists(share._context, self._context):
raise gl.ContextException('Unable to share contexts.')
def set_current(self): def set_current(self):
if self._context is not None and self != gl.current_context: if self._context is not None and self != gl.current_context:
wgl.wglMakeCurrent(self.canvas.hdc, self._context) wgl.wglMakeCurrent(self.canvas.hdc, self._context)
super(Win32Context, self).set_current() super().set_current()
def detach(self): def detach(self):
if self.canvas: if self.canvas:
wgl.wglDeleteContext(self._context) wgl.wglDeleteContext(self._context)
self._context = None self._context = None
super(Win32Context, self).detach() super().detach()
def flip(self): def flip(self):
_gdi32.SwapBuffers(self.canvas.hdc) _gdi32.SwapBuffers(self.canvas.hdc)
@ -224,9 +210,23 @@ class Win32Context(Context):
wglext_arb.wglSwapIntervalEXT(int(vsync)) wglext_arb.wglSwapIntervalEXT(int(vsync))
class Win32ARBContext(Win32Context): class Win32Context(_BaseWin32Context):
def __init__(self, config, share): def attach(self, canvas):
super(Win32ARBContext, self).__init__(config, share) super().attach(canvas)
if not self._context:
self.config._set_pixel_format(canvas)
self._context = wgl.wglCreateContext(canvas.hdc)
share = self.context_share
if share:
if not share.canvas:
raise RuntimeError('Share context has no canvas.')
if not wgl.wglShareLists(share._context, self._context):
raise gl.ContextException('Unable to share contexts.')
class Win32ARBContext(_BaseWin32Context):
def attach(self, canvas): def attach(self, canvas):
share = self.context_share share = self.context_share
@ -252,4 +252,4 @@ class Win32ARBContext(Win32Context):
self.config._set_pixel_format(canvas) self.config._set_pixel_format(canvas)
self._context = wglext_arb.wglCreateContextAttribsARB(canvas.hdc, share, attribs) self._context = wglext_arb.wglCreateContextAttribsARB(canvas.hdc, share, attribs)
super(Win32ARBContext, self).attach(canvas) super().attach(canvas)

View File

@ -60,6 +60,10 @@ if TYPE_CHECKING:
def description(self) -> str: def description(self) -> str:
""" 零件的描述 """ """ 零件的描述 """
@property
def sprite(self) -> str:
""" 零件的贴图 """
@property @property
def mass(self) -> float: def mass(self) -> float:
""" 零件的质量 """ """ 零件的质量 """
@ -80,6 +84,10 @@ if TYPE_CHECKING:
def hidden(self) -> bool: def hidden(self) -> bool:
""" 零件是否隐藏 """ """ 零件是否隐藏 """
@property
def type(self):
""" 零件的类型 """
class SR1PartList_rs: # NOQA class SR1PartList_rs: # NOQA
""" 用于从 rust 中读取 SR1PartList """ """ 用于从 rust 中读取 SR1PartList """

View File

@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs'
setup( setup(
name='Difficult_Rocket_rs', name='Difficult_Rocket_rs',
version="0.2.18.0", version="0.2.21.0",
author='shenjackyuanjie', author='shenjackyuanjie',
author_email='3695888@qq.com', author_email='3695888@qq.com',
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs", rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",

View File

@ -24,7 +24,7 @@ enum LoadState {
} }
#[pyfunction] #[pyfunction]
fn get_version_str() -> String { "0.2.20.2".to_string() } fn get_version_str() -> String { "0.2.21.0".to_string() }
#[pyfunction] #[pyfunction]
fn test_call(py_obj: &PyAny) -> PyResult<bool> { fn test_call(py_obj: &PyAny) -> PyResult<bool> {

View File

@ -76,6 +76,9 @@ pub mod data {
#[getter] #[getter]
fn get_hidden(&self) -> bool { self.data.hidden } fn get_hidden(&self) -> bool { self.data.hidden }
#[getter]
fn get_type(&self) -> String { self.data.p_type.into() }
} }
impl PySR1PartType { impl PySR1PartType {

View File

@ -41,6 +41,27 @@ pub mod part_list {
lander, lander,
} }
impl Into<String> for SR1PartTypeEnum {
fn into(self) -> String {
match self {
SR1PartTypeEnum::pod => "pod".to_string(),
SR1PartTypeEnum::detacher => "detacher".to_string(),
SR1PartTypeEnum::wheel => "wheel".to_string(),
SR1PartTypeEnum::fuselage => "fuselage".to_string(),
SR1PartTypeEnum::strut => "strut".to_string(),
SR1PartTypeEnum::tank => "tank".to_string(),
SR1PartTypeEnum::engine => "engine".to_string(),
SR1PartTypeEnum::parachute => "parachute".to_string(),
SR1PartTypeEnum::nosecone => "nosecone".to_string(),
SR1PartTypeEnum::rcs => "rcs".to_string(),
SR1PartTypeEnum::solar => "solar".to_string(),
SR1PartTypeEnum::dockconnector => "dockconnector".to_string(),
SR1PartTypeEnum::dockport => "dockport".to_string(),
SR1PartTypeEnum::lander => "lander".to_string(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Copy, Clone)] #[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub enum Location { pub enum Location {
Top, Top,

View File

@ -16,7 +16,7 @@ from Difficult_Rocket.api.mod import ModInfo
from Difficult_Rocket.client import ClientWindow from Difficult_Rocket.client import ClientWindow
from Difficult_Rocket.api.types import Options, Version from Difficult_Rocket.api.types import Options, Version
DR_rust_version = Version("0.2.20.2") # DR_mod 的 Rust 编写部分的兼容版本 DR_rust_version = Version("0.2.21.0") # DR_mod 的 Rust 编写部分的兼容版本
logger = logging.getLogger('client.dr_game') logger = logging.getLogger('client.dr_game')
@ -53,7 +53,7 @@ DR_mod_runtime = _DR_mod_runtime()
class DR_mod(ModInfo): # NOQA class DR_mod(ModInfo): # NOQA
mod_id = "difficult_rocket_mod" mod_id = "difficult_rocket_mod"
name = "Difficult Rocket mod" name = "Difficult Rocket mod"
version = Version("0.3.2.0") version = Version("0.3.3.0")
writer = "shenjackyuanjie" writer = "shenjackyuanjie"
link = "shenjack.top" link = "shenjack.top"

View File

@ -10,26 +10,25 @@ import logging
import traceback import traceback
from pathlib import Path from pathlib import Path
from typing import List, TYPE_CHECKING, Union, Dict, Optional, Generator, Tuple from typing import List, TYPE_CHECKING, Dict, Optional, Generator, Tuple
from pyglet.math import Vec4 from pyglet.math import Vec4
from pyglet.text import Label from pyglet.text import Label
from pyglet.sprite import Sprite from pyglet.sprite import Sprite
# from pyglet.image import Texture
from pyglet.graphics import Batch, Group from pyglet.graphics import Batch, Group
from pyglet.shapes import Line, Rectangle from pyglet.shapes import Line, Rectangle
from pyglet.image import Framebuffer, Texture from pyglet.image import Framebuffer, Texture
from . import DR_mod_runtime from . import DR_mod_runtime
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.api.camera import CenterCamera
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 .types import SR1Textures, SR1Rotation from Difficult_Rocket.api.camera import CenterGroupCamera
if TYPE_CHECKING: if TYPE_CHECKING:
from Difficult_Rocket.client import ClientWindow from Difficult_Rocket.client import ClientWindow
@ -38,8 +37,7 @@ if DR_mod_runtime.use_DR_rust:
from .Difficult_Rocket_rs import (SR1PartList_rs, from .Difficult_Rocket_rs import (SR1PartList_rs,
SR1Ship_rs, SR1Ship_rs,
SR1PartData_rs, SR1PartData_rs,
SR1PartType_rs, SR1PartType_rs)
map_ptype_textures)
logger = logging.getLogger('client.dr_game_sr1_ship') logger = logging.getLogger('client.dr_game_sr1_ship')
logger.level = logging.DEBUG logger.level = logging.DEBUG
@ -82,7 +80,12 @@ class SR1ShipRender(BaseScreen):
self.buffer.attach_texture(self.render_texture) self.buffer.attach_texture(self.render_texture)
self.main_batch = Batch() self.main_batch = Batch()
self.part_group = Group(10, parent=main_window.main_group) self.group_camera = CenterGroupCamera(window=main_window,
order=10,
parent=main_window.main_group,
min_zoom=(1 / 2) ** 10,
max_zoom=10)
self.part_group = Group(0, parent=self.group_camera)
self.debug_label = Label(x=20, y=main_window.height - 100, font_size=DR_status.std_font_size, self.debug_label = Label(x=20, y=main_window.height - 100, font_size=DR_status.std_font_size,
text='SR1 render!', font_name=Fonts.微软等宽无线, text='SR1 render!', font_name=Fonts.微软等宽无线,
@ -95,7 +98,6 @@ class SR1ShipRender(BaseScreen):
self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线, self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线,
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.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
# Optional data # Optional data
self.textures: SR1Textures = SR1Textures() self.textures: SR1Textures = SR1Textures()
@ -163,13 +165,15 @@ class SR1ShipRender(BaseScreen):
# rust 渲染 # rust 渲染
if DR_mod_runtime.use_DR_rust: if DR_mod_runtime.use_DR_rust:
cache = self.rust_ship.as_dict() 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(): for p_id, parts in cache.items():
p_id: int p_id: int
parts: List[Tuple[SR1PartType_rs, SR1PartData_rs]] parts: List[Tuple[SR1PartType_rs, SR1PartData_rs]]
part_group = Group(2, parent=self.part_group)
batch = [] batch = []
for p_type, p_data in parts: for p_type, p_data in parts:
part_sprite = Sprite(img=self.textures.get_texture(map_ptype_textures(p_data.part_type_id)), sprite_name = self.part_list_rs.get_part_type(p_data.part_type_id).sprite
part_sprite = Sprite(img=self.textures.get_texture(sprite_name),
x=p_data.x * 60, y=p_data.y * 60, z=random.random(), x=p_data.x * 60, y=p_data.y * 60, z=random.random(),
batch=self.main_batch, group=part_group) batch=self.main_batch, group=part_group)
part_sprite.rotation = p_data.angle_r part_sprite.rotation = p_data.angle_r
@ -177,7 +181,6 @@ class SR1ShipRender(BaseScreen):
part_sprite.scale_y = -1 if p_data.flip_y else 1 part_sprite.scale_y = -1 if p_data.flip_y else 1
batch.append(part_sprite) batch.append(part_sprite)
line_box_group = Group(6, parent=self.part_group)
part_box = self.rust_ship.get_part_box(p_id) part_box = self.rust_ship.get_part_box(p_id)
if part_box: if part_box:
# 线框 # 线框
@ -253,9 +256,7 @@ class SR1ShipRender(BaseScreen):
self.parts_sprite: Dict[int, Sprite] = {} self.parts_sprite: Dict[int, Sprite] = {}
self.part_line_box = {} self.part_line_box = {}
self.part_line_list = [] self.part_line_list = []
self.camera.zoom = 1.0 self.group_camera.reset()
self.camera.dx = 0
self.camera.dy = 0
# 调用生成器 减少卡顿 # 调用生成器 减少卡顿
try: try:
self.gen_draw = self.gen_sprite() self.gen_draw = self.gen_sprite()
@ -275,18 +276,18 @@ class SR1ShipRender(BaseScreen):
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.camera.dx} y: {self.camera.dy}' self.render_d_label.text = f'x: {self.group_camera.view_x} y: {self.group_camera.view_y}'
self.render_d_label.position = self.camera.dx + (self.window_pointer.width / 2), self.camera.dy + ( self.render_d_label.position = self.group_camera.view_x + (self.window_pointer.width / 2), self.group_camera.view_y + (
self.window_pointer.height / 2) + 10, 0 # 0 for z self.window_pointer.height / 2) + 10, 0 # 0 for z
self.render_d_line.x2 = self.camera.dx self.render_d_line.x2 = self.group_camera.view_x
self.render_d_line.y2 = self.camera.dy self.render_d_line.y2 = self.group_camera.view_y
self.buffer.bind() self.buffer.bind()
window.clear() window.clear()
with self.camera: self.main_batch.draw() # use group camera, no need to with
self.main_batch.draw()
self.buffer.unbind() self.buffer.unbind()
self.render_texture.blit(x=self.dx, y=self.dy, z=0, width=self.width, height=self.height) 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"): def on_draw(self, window: "ClientWindow"):
if self.status.draw_call: if self.status.draw_call:
self.render_ship() self.render_ship()
@ -316,24 +317,24 @@ class SR1ShipRender(BaseScreen):
mouse_dx = x - (window.width / 2) mouse_dx = x - (window.width / 2)
mouse_dy = y - (window.height / 2) mouse_dy = y - (window.height / 2)
# 鼠标缩放位置相对于屏幕中心的位置 # 鼠标缩放位置相对于屏幕中心的位置
mouse_dx_d = mouse_dx - self.camera.dx mouse_dx_d = mouse_dx - self.group_camera.view_x
mouse_dy_d = mouse_dy - self.camera.dy mouse_dy_d = mouse_dy - self.group_camera.view_y
# 鼠标相对偏移量的偏移量 # 鼠标相对偏移量的偏移量
if scroll_y == 0: if scroll_y == 0:
zoom_d = 1 zoom_d = 1
else: else:
zoom_d = ((2 ** scroll_y) - 1) * 0.5 + 1 zoom_d = ((2 ** scroll_y) - 1) * 0.5 + 1
# 缩放的变换量 # 缩放的变换量
if not (self.camera.zoom == 10 and scroll_y > 0): if not (self.group_camera.zoom == 10 and scroll_y > 0):
if self.camera.zoom * zoom_d >= 10: if self.group_camera.zoom * zoom_d >= 10:
zoom_d = 10 / self.camera.zoom zoom_d = 10 / self.group_camera.zoom
self.camera.zoom = 10 self.group_camera.zoom = 10
else: else:
self.camera.zoom *= zoom_d self.group_camera.zoom *= zoom_d
mouse_dx_d *= (1 - zoom_d) mouse_dx_d *= (1 - zoom_d)
mouse_dy_d *= (1 - zoom_d) mouse_dy_d *= (1 - zoom_d)
self.camera.dx += mouse_dx_d self.group_camera.view_x += mouse_dx_d
self.camera.dy += mouse_dy_d self.group_camera.view_y += mouse_dy_d
elif self.status.moving: elif self.status.moving:
# 如果是在移动整体渲染位置 # 如果是在移动整体渲染位置
size_x, size_y = self.size size_x, size_y = self.size
@ -350,9 +351,7 @@ class SR1ShipRender(BaseScreen):
self.logger.info(f'command: {command}') self.logger.info(f'command: {command}')
if command.find('render'): if command.find('render'):
if command.find('reset'): if command.find('reset'):
self.camera.zoom = 1 self.group_camera.reset()
self.camera.dx = 0
self.camera.dy = 0
self.window_pointer.view = Vec4() self.window_pointer.view = Vec4()
else: else:
self.status.draw_call = True self.status.draw_call = True
@ -440,8 +439,8 @@ class SR1ShipRender(BaseScreen):
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.camera.dx += dx self.group_camera.view_x += dx
self.camera.dy += dy self.group_camera.view_y += dy
self.status.update_call = True self.status.update_call = True
elif self.status.moving: elif self.status.moving:
# 如果是在移动整体渲染位置 # 如果是在移动整体渲染位置

View File

@ -33,8 +33,10 @@ class SR1Textures(Options):
""" """
if name in self.cached_options: if name in self.cached_options:
return self.cached_options.get(name) return self.cached_options.get(name)
elif name.split('.')[0] in self.cached_options:
return self.cached_options.get(name.split('.')[0])
else: else:
img = load(f'assets/textures/parts/{name}.png') img = load(f'assets/textures/parts/{name}')
img.anchor_x = img.width // 2 img.anchor_x = img.width // 2
img.anchor_y = img.height // 2 img.anchor_y = img.height // 2
setattr(self, name, img) setattr(self, name, img)