Compare commits

...

31 Commits

Author SHA1 Message Date
5cb642ea3c
az 2023-08-21 01:24:25 +08:00
2e9e3afc39
改进 options 修复了无限循环的问题 2023-08-21 00:43:00 +08:00
2e509575cd
Options! 2023-08-20 21:42:46 +08:00
33d5788826
better widget 2023-08-20 21:42:38 +08:00
6dbffb322d
improve widget 2023-08-20 21:42:25 +08:00
bff9649ca9
继续干活 2023-08-20 02:01:15 +08:00
5f335fa9b5
button gogogo 2023-08-20 01:52:22 +08:00
4b639c37e0
do not use nightly 2023-08-19 20:22:04 +08:00
cc5dec9122
update builder 2023-08-19 20:15:35 +08:00
05ac9871da
sync pyglet 2023-08-19 20:15:25 +08:00
dd5dca1099
nope, use lto=false 2023-08-17 20:47:55 +08:00
804dbfc992
use lto=yes on github? 2023-08-17 20:31:49 +08:00
8e494faa63
improve camera 2023-08-16 16:25:47 +08:00
42eef6743d
weirdddd 2023-08-15 23:30:34 +08:00
6fefb4460b
weird 2023-08-15 23:30:25 +08:00
8dfa5b230a
sync pyglet 2023-08-15 23:29:49 +08:00
726ba4ac17
add some magic from OpenGL 2023-08-13 01:01:15 +08:00
ede6f9ff6e
add back Mat4 2023-08-13 00:21:22 +08:00
d6f0caf2ae
remove zoomx and zoomy 2023-08-12 23:34:17 +08:00
d398ed1af9
opengl based render! 2023-08-12 23:32:43 +08:00
e888ddfdad
add readme info 2023-08-12 20:20:18 +08:00
82111be30b
add feature for dr rs 2023-08-12 02:15:53 +08:00
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
35 changed files with 609 additions and 251 deletions

View File

@ -10,7 +10,7 @@ from pathlib import Path
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") # 编译文件版本(与游戏本体无关)
Api_version = Version("0.1.1.0") # API 版本
__version__ = sdk_version

View File

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

View File

@ -0,0 +1,9 @@
# -------------------------------
# Difficult Rocket
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved
# -------------------------------
__all__ = [
'widget'
]

View 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'
]

View File

@ -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.

View File

@ -247,7 +247,7 @@ class ClientWindow(Window):
batch=self.main_batch, text='', group=Group(1000, parent=self.main_group)) # 实例化
self.input_box.push_handlers(self)
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
# 设置刷新率
# pyglet.clock.schedule_interval(self.draw_update, float(self.SPF))
@ -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()
@ -419,7 +424,7 @@ class ClientWindow(Window):
...
@_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

View File

@ -1,59 +0,0 @@
# -------------------------------
# Difficult Rocket
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved
# -------------------------------
"""
writen by shenjackyuanjie
mail: 3695888@qq.com
github: @shenjackyuanjie
gitee: @shenjackyuanjie
"""
from typing import Optional, Union, Tuple
# from libs import pyglet
# from pyglet import font
from pyglet.text import Label, HTMLLabel
# from pyglet.window import key
from pyglet.gui import widgets
# from pyglet.sprite import Sprite
from pyglet.shapes import Rectangle
# from pyglet.image import AbstractImage
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 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 import DR_status
__all__ = ['InputBox']
class TextButton(widgets.WidgetBase):
"""
自带字符的按钮就不用单独做材质了
"""
def __init__(self,
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)
@property
def value(self):
return self.text
def _update_position(self):
self.text_label.position = self._x, self._y
...

View File

@ -0,0 +1,125 @@
# -------------------------------
# Difficult Rocket
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved
# -------------------------------
"""
writen by shenjackyuanjie
mail: 3695888@qq.com
github: @shenjackyuanjie
gitee: @shenjackyuanjie
"""
from typing import Optional, Union, Tuple
# from libs import pyglet
# from pyglet import font
from pyglet.text import Label
from pyglet.window import mouse
from pyglet.gui import widgets
# from pyglet.sprite import Sprite
from pyglet.shapes import Rectangle
# from pyglet.image import AbstractImage
from pyglet.graphics import Batch, Group
from Difficult_Rocket.api.types import Fonts
# 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):
"""
自带 字符 + 材质 的按钮就不用单独做材质了
"""
def __init__(self,
x: int,
y: int,
width: int,
height: int,
text: str,
font: str = Fonts.鸿蒙简体,
font_size: int = 13,
batch: Optional[Batch] = None,
group: Optional[Group] = None,
):
super().__init__(x, y, width, height)
self.back_ground_batch = batch or Batch()
self.front_batch = batch or Batch()
if group:
self.front_group = Group(order=10, parent=group)
self.back_ground_group = Group(order=5, parent=group)
else:
self.front_group = Group(order=5)
self.back_ground_group = Group(order=10)
self.pressed = False
self.untouched_color = (39, 73, 114, 255)
self.touched_color = (66, 150, 250, 255)
self.hit_color = (15, 135, 250, 255)
# from ImGui
self.text = text
self.text_label = Label(font_name=font, font_size=font_size,
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,
color=self.untouched_color, # ImGui color
batch=self.back_ground_batch, group=self.back_ground_group)
@property
def value(self):
return self.text
def __contains__(self, item):
return item in self.back_rec
def on_mouse_motion(self, x, y, dx, dy):
if (x, y) in self.back_rec:
self.back_rec.color = self.touched_color
else:
self.pressed = False
self.back_rec.color = self.untouched_color
def on_mouse_press(self, x, y, buttons, modifiers) -> bool:
if (x, y) in self and buttons == mouse.LEFT:
self.back_rec.color = self.hit_color
self.dispatch_event('on_press', x, y)
self.pressed = True
return True
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):
self.text_label.position = self._x, self._y
self.back_rec.position = self._x, self._y
self.back_rec.width = self._width
self.back_rec.height = self._height
...
PressTextButton.register_event_type('on_press')

View File

@ -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_compat, gl
from pyglet.math import Mat4, Vec3
from pyglet.graphics import Group
class Camera:
"""
@ -24,6 +27,7 @@ class Camera:
>>> camera.end()
"""
def __init__(self,
window,
zoom: Optional[float] = 1.0,
@ -69,6 +73,11 @@ class Camera:
def end(self) -> None:
self.window.view = self._stored_view
def reset(self):
self.zoom = 1
self.dx = 0
self.dy = 0
def __enter__(self):
self.begin()
return self
@ -91,8 +100,8 @@ class CenterCamera(Camera):
>>> camera.begin()
>>> window.clear()
>>> camera.end()
"""
def begin(self) -> None:
view = self.window.view
self._stored_view = view
@ -107,3 +116,148 @@ class CenterCamera(Camera):
def end(self) -> None:
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.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 min(max(self._zoom, self.min_zoom), self.max_zoom)
@zoom.setter
def zoom(self, value: float):
self._zoom = value
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 + (self._view_x / self._zoom)
y = (self._window.height / 2) / self._zoom + (self._view_y / self._zoom)
view = Mat4.from_translation(Vec3(x * self._zoom, y * self._zoom, 0))
# 不懂就问 为啥这里 * zoom 下面还 * zoom
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 CenterGroupFrame(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,
dx: Optional[int] = 0,
dy: Optional[int] = 0,
width: Optional[int] = 0,
height: 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.dx = dx
self.dy = dy
self._width = width
self._height = height
self._zoom = zoom
self.min_zoom = min_zoom
self.max_zoom = max_zoom
@property
def zoom(self) -> float:
return self._zoom
@zoom.setter
def zoom(self, value: float):
self._zoom = min(max(value, self.min_zoom), self.max_zoom)
def set_state(self):
self._previous_view = self.window.view
gl.glScissor(int(self.dx), int(self.dy), int(self._width), int(self._height))
gl.glViewport(int(self.dx), int(self.dy), int(self.window.width), int(self.window.height))
gl.glEnable(gl.GL_SCISSOR_TEST)
x = (self.window.width / 2) / self._zoom + (self.dx / self._zoom)
y = (self.window.height / 2) / self._zoom + (self.dy / self._zoom)
view = Mat4.from_translation(Vec3(x * self._zoom, y * self._zoom, 0))
view.scale(Vec3(self._zoom, self._zoom, 1))
self.window.view = view
def unset_state(self):
self.window.view = self._previous_view
gl.glDisable(gl.GL_SCISSOR_TEST)
gl.glViewport(0, 0, int(self.window.width), int(self.window.height))

View File

@ -4,6 +4,7 @@
# All rights reserved
# -------------------------------
import shutil
import traceback
from io import StringIO
from dataclasses import dataclass
@ -175,15 +176,12 @@ class Options:
self.cached_options = self.option()
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 列表
:return:
"""
if longest is None:
options = self.flush_option()
else:
options = self.str_option(longest)
max_len_key = 1
max_len_value = 1
max_len_value_t = 1
@ -193,19 +191,61 @@ class Options:
max_len_key = max(max_len_key, len(key))
max_len_value = max(max_len_value, len(str(value)))
max_len_value_t = max(max_len_value_t, len(str(value_t)))
option_list.append((key, value, value_t))
return option_list, max_len_key, max_len_value, max_len_value_t
option_list.append([key, value, 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:
"""
返回一个 markdown 格式的 option 字符串
:param longest: 最长的输出长度
:return: markdown 格式的 option 字符串
"""
value = self.option_with_len(longest)
value = self.option_with_len()
cache = StringIO()
option_len = max(value[1], len('Option'))
value_len = max(value[2], len('Value'))
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)
# 为每一栏 预分配 1/3 或者 需要的宽度 (如果不需要 1/3)
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)
# 先指定每一个列的输出最窄宽度, 然后去尝试增加宽度
# 循环分配新空间之前 首先检查是否已经不需要多分配 (and 后面)
while option_len + value_len + value_type_len + 16 < console_width\
and (option_len < value[1]
or value_len < value[2]
or value_type_len < value[3]):
# 每一个部分的逻辑都是
# 如果现在的输出长度小于原始长度
# 并且长度 + 1 之后的总长度依然在允许范围内
# 那么就 + 1
if option_len < value[1] and option_len + value_len + value_type_len + 15 < console_width:
option_len += 1
if value_len < value[2] and option_len + value_len + value_type_len + 15 < console_width:
value_len += 1
if value_type_len < value[3] and option_len + value_len + value_type_len + 15 < console_width:
value_type_len += 1
# 实际上 对于列表(可变对象) for 出来的这个值是一个引用
# 所以可以直接修改 string
for v in value[0]:
if len(str(v[0])) > option_len:
v[0] = f'{str(v[0])[:value_len - 3]}...'
if len(str(v[1])) > value_len:
v[1] = f'{str(v[1])[:value_len - 3]}...'
if len(str(v[2])) > value_type_len:
v[2] = f'{str(v[2])[:value_len - 3]}..'
cache.write(
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')

View File

@ -11,6 +11,8 @@
## 请注意 这个仓库未来只会发布 `DR SDK` 的更新 `DR game` 的更新会在 [这里](https://github.com/shenjackyuanjie/DR-game) 发布
![demo](docs/src/demo.png)
<a href="https://996.icu"><img src="https://img.shields.io/badge/link-996.icu-red.svg" alt="996.icu" /></a>
[![Generic badge](https://img.shields.io/badge/SemVer-2.0.0-blue.svg)](https://Semver.org/)
[![Generic badge](https://img.shields.io/badge/编写于_Python_版本-3.8.10-blue.svg)](https://Python.org)

View File

@ -9,6 +9,8 @@
## Notice: This repo will only publish `DR SDK` updates, `DR game` updates will be published [here](https://github.com/shenjackyuanjie/DR-game)
![demo](/src/demo.png)
<a href="https://996.icu"><img src="https://img.shields.io/badge/link-996.icu-red.svg" alt="996.icu" /></a>
[![Generic badge](https://img.shields.io/badge/SemVer-2.0.0-blue.svg)](https://Semver.org/)
[![Generic badge](https://img.shields.io/badge/Write_with_Python-3.8.10-blue.svg)](https://Python.org)

View File

@ -2,8 +2,38 @@
# DR game/DR rs 更新日志
- 最新版本号
- DR game: 0.3.2.0
- DR rs: 0.2.20.2
- DR game: 0.3.3.0
- DR rs: 0.2.21.0
## 20230812 DR game 0.3.3.0
### Changes
- 将 `sr1_ship` 渲染器使用的 Camera 改成 `CenterGroupCamera`
- 删除了之前的 Camera 相关代码
- 将用于渲染到材质的代码部分改为使用 `glScissor``glViewport`
- 优化了一点性能 ( 毕竟是OpenGL )
## 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

View File

@ -2,7 +2,30 @@
# 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

BIN
docs/src/demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

View File

@ -208,7 +208,6 @@ class ObjectSpace:
# the next time this object space is active.
self.doomed_textures = []
self.doomed_buffers = []
self.doomed_vaos = []
self.doomed_shader_programs = []
@ -231,6 +230,8 @@ class Context:
self.context_share = context_share
self.canvas = None
self.doomed_vaos = []
if context_share:
self.object_space = context_share.object_space
else:
@ -276,15 +277,15 @@ class Context:
buffers = (gl.GLuint * len(buffers))(*buffers)
gl.glDeleteBuffers(len(buffers), buffers)
self.object_space.doomed_buffers.clear()
if self.object_space.doomed_vaos:
vaos = self.object_space.doomed_vaos[:]
vaos = (gl.GLuint * len(vaos))(*vaos)
gl.glDeleteVertexArrays(len(vaos), vaos)
self.object_space.doomed_vaos.clear()
if self.object_space.doomed_shader_programs:
for program_id in self.object_space.doomed_shader_programs:
gl.glDeleteProgram(program_id)
self.object_space.doomed_shader_programs.clear()
if self.doomed_vaos:
vaos = self.doomed_vaos[:]
vaos = (gl.GLuint * len(vaos))(*vaos)
gl.glDeleteVertexArrays(len(vaos), vaos)
self.doomed_vaos.clear()
def destroy(self):
"""Release the context.
@ -351,10 +352,10 @@ class Context:
.. versionadded:: 2.0
"""
if gl.current_context and self.object_space is gl.current_context.object_space and False:
if gl.current_context is self:
gl.glDeleteVertexArrays(1, gl.GLuint(vao_id))
else:
self.object_space.doomed_vaos.append(vao_id)
self.doomed_vaos.append(vao_id)
def delete_shader_program(self, program_id):
"""Safely delete a Shader Program belonging to this context.

View File

@ -98,7 +98,7 @@ class Win32Config(Config):
class Win32CanvasConfig(CanvasConfig):
def __init__(self, canvas, pf, config):
super(Win32CanvasConfig, self).__init__(canvas, config)
super().__init__(canvas, config)
self._pf = pf
self._pfd = PIXELFORMATDESCRIPTOR()
@ -153,7 +153,7 @@ class Win32CanvasConfigARB(CanvasConfig):
}
def __init__(self, canvas, pf, config):
super(Win32CanvasConfigARB, self).__init__(canvas, config)
super().__init__(canvas, config)
self._pf = pf
names = list(self.attribute_ids.keys())
@ -182,35 +182,21 @@ class Win32CanvasConfigARB(CanvasConfig):
_gdi32.SetPixelFormat(canvas.hdc, self._pf, None)
class Win32Context(Context):
class _BaseWin32Context(Context):
def __init__(self, config, share):
super(Win32Context, self).__init__(config, share)
super().__init__(config, share)
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):
if self._context is not None and self != gl.current_context:
wgl.wglMakeCurrent(self.canvas.hdc, self._context)
super(Win32Context, self).set_current()
super().set_current()
def detach(self):
if self.canvas:
wgl.wglDeleteContext(self._context)
self._context = None
super(Win32Context, self).detach()
super().detach()
def flip(self):
_gdi32.SwapBuffers(self.canvas.hdc)
@ -224,9 +210,23 @@ class Win32Context(Context):
wglext_arb.wglSwapIntervalEXT(int(vsync))
class Win32ARBContext(Win32Context):
def __init__(self, config, share):
super(Win32ARBContext, self).__init__(config, share)
class Win32Context(_BaseWin32Context):
def attach(self, canvas):
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):
share = self.context_share
@ -252,4 +252,4 @@ class Win32ARBContext(Win32Context):
self.config._set_pixel_format(canvas)
self._context = wglext_arb.wglCreateContextAttribsARB(canvas.hdc, share, attribs)
super(Win32ARBContext, self).attach(canvas)
super().attach(canvas)

View File

@ -148,11 +148,8 @@ class InterfacePtrMeta(type(ctypes.POINTER(COMInterface))):
return super(InterfacePtrMeta, cls).__new__(cls, name, bases, dct)
# pyglet.util.with_metaclass does not work here, as the base class is from _ctypes.lib
# See https://wiki.python.org/moin/PortingToPy3k/BilingualQuickRef
pInterface = InterfacePtrMeta(str('Interface'),
(ctypes.POINTER(COMInterface),),
{'__doc__': 'Base COM interface pointer.'})
class pInterface(ctypes.POINTER(COMInterface), metaclass=InterfacePtrMeta):
"""Base COM interface pointer."""
class COMInterfaceMeta(type):

View File

@ -3,7 +3,6 @@ from enum import Enum, auto
from typing import Dict, Optional
from pyglet import event
from pyglet.util import with_metaclass
class DeviceState(Enum):
@ -37,7 +36,7 @@ class AudioDevice:
self.__class__.__name__, self.name, self.platform_state[self.state].name, self.platform_flow[self.flow].name)
class AbstractAudioDeviceManager(with_metaclass(ABCMeta, event.EventDispatcher, object)):
class AbstractAudioDeviceManager(event.EventDispatcher, metaclass=ABCMeta):
def __del__(self):
"""Required to remove handlers before exit, as it can cause problems with the event system's weakrefs."""

View File

@ -4,10 +4,9 @@ import weakref
from abc import ABCMeta, abstractmethod
import pyglet
from pyglet.util import with_metaclass
class AbstractAudioPlayer(with_metaclass(ABCMeta)):
class AbstractAudioPlayer(metaclass=ABCMeta):
"""Base class for driver audio players.
"""
@ -176,7 +175,7 @@ class AbstractAudioPlayer(with_metaclass(ABCMeta)):
self._source = weakref.proxy(value)
class AbstractAudioDriver(with_metaclass(ABCMeta)):
class AbstractAudioDriver(metaclass=ABCMeta):
@abstractmethod
def create_audio_player(self, source, player):
pass

View File

@ -1,9 +1,7 @@
from abc import ABCMeta, abstractmethod
from pyglet.util import with_metaclass
class AbstractListener(with_metaclass(ABCMeta, object)):
class AbstractListener(metaclass=ABCMeta):
"""The listener properties for positional audio.
You can obtain the singleton instance of this class by calling

View File

@ -31,37 +31,6 @@ def asstr(s):
return s.decode("utf-8")
def with_metaclass(meta, *bases):
"""
Function from jinja2/_compat.py. License: BSD.
Use it like this::
class BaseForm:
pass
class FormType(type):
pass
class Form(with_metaclass(FormType, BaseForm)):
pass
This requires a bit of explanation: the basic idea is to make a
dummy metaclass for one level of class instantiation that replaces
itself with the actual metaclass. Because of internal type checks
we also need to make sure that we downgrade the custom metaclass
for one level to something closer to type (that's why __call__ and
__init__ comes back from type etc.).
This has the advantage over six.with_metaclass of not introducing
dummy classes into the final MRO.
"""
class MetaClass(meta):
__call__ = type.__call__
__init__ = type.__init__
def __new__(cls, name, this_bases, d):
if this_bases is None:
return type.__new__(cls, name, (), d)
return meta(name, bases, d)
return MetaClass('temporary_class', None, {})
def debug_print(enabled_or_option='debug'):
"""Get a debug printer that is enabled based on a boolean input or a pyglet option.
The debug print function returned should be used in an assert. This way it can be

View File

@ -99,7 +99,6 @@ from pyglet import gl
from pyglet.math import Mat4
from pyglet.event import EventDispatcher
from pyglet.window import key, event
from pyglet.util import with_metaclass
from pyglet.graphics import shader
@ -256,7 +255,7 @@ class _WindowMetaclass(type):
super(_WindowMetaclass, cls).__init__(name, bases, dict)
class BaseWindow(with_metaclass(_WindowMetaclass, EventDispatcher)):
class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
"""Platform-independent application window.
A window is a "heavyweight" object occupying operating system resources.

View File

@ -45,6 +45,7 @@ class CompilerHelper(Options):
show_progress: bool = True # --show-progress
show_memory: bool = False # --show-memory
remove_output: bool = True # --remove-output
save_xml: bool = False # --xml
xml_path: Path = Path('build/compile_data.xml')
@ -147,6 +148,7 @@ class CompilerHelper(Options):
_add_cmd(cmd_list, '--disable-ccache' if not self.use_ccache else None)
_add_cmd(cmd_list, '--show-progress' if self.show_progress else None)
_add_cmd(cmd_list, '--show-memory' if self.show_memory else None)
_add_cmd(cmd_list, '--remove-output' if self.remove_output else None)
_add_cmd(cmd_list, '--assume-yes-for-download' if self.download_confirm else None)
_add_cmd(cmd_list, '--run' if self.run_after_build else None)
_add_cmd(cmd_list, '--enable-console' if self.enable_console else '--disable-console')

View File

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

View File

@ -348,9 +348,9 @@ dependencies = [
[[package]]
name = "pyo3"
version = "0.19.1"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb88ae05f306b4bfcde40ac4a51dc0b05936a9207a4b75b798c7729c4258a59"
checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38"
dependencies = [
"cfg-if",
"indoc",
@ -365,9 +365,9 @@ dependencies = [
[[package]]
name = "pyo3-build-config"
version = "0.19.1"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "554db24f0b3c180a9c0b1268f91287ab3f17c162e15b54caaae5a6b3773396b0"
checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5"
dependencies = [
"once_cell",
"target-lexicon",
@ -375,9 +375,9 @@ dependencies = [
[[package]]
name = "pyo3-ffi"
version = "0.19.1"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "922ede8759e8600ad4da3195ae41259654b9c55da4f7eec84a0ccc7d067a70a4"
checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9"
dependencies = [
"libc",
"pyo3-build-config",
@ -385,9 +385,9 @@ dependencies = [
[[package]]
name = "pyo3-macros"
version = "0.19.1"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a5caec6a1dd355964a841fcbeeb1b89fe4146c87295573f94228911af3cc5a2"
checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
@ -397,9 +397,9 @@ dependencies = [
[[package]]
name = "pyo3-macros-backend"
version = "0.19.1"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0b78ccbb160db1556cdb6fd96c50334c5d4ec44dc5e0a968d0a1208fa0efa8b"
checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536"
dependencies = [
"proc-macro2",
"quote",

View File

@ -40,5 +40,5 @@ version = "0.17.2"
features = ["simd-stable"]
[dependencies.pyo3]
version = "0.19.1"
features = ["extension-module"]
version = "0.19.2"
features = ["extension-module" , "macros"]

View File

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

View File

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

View File

@ -51,6 +51,10 @@ pub mod data {
pub data: SR1PartType,
}
impl PySR1PartType {
pub fn new(data: SR1PartType) -> Self { Self { data } }
}
#[pymethods]
impl PySR1PartType {
#[getter]
@ -76,10 +80,9 @@ pub mod data {
#[getter]
fn get_hidden(&self) -> bool { self.data.hidden }
}
impl PySR1PartType {
pub fn new(data: SR1PartType) -> Self { Self { data } }
#[getter]
fn get_type(&self) -> String { self.data.p_type.into() }
}
#[pyclass]

View File

@ -41,6 +41,27 @@ pub mod part_list {
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)]
pub enum Location {
Top,

View File

@ -16,7 +16,7 @@ from Difficult_Rocket.api.mod import ModInfo
from Difficult_Rocket.client import ClientWindow
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')
@ -53,7 +53,7 @@ DR_mod_runtime = _DR_mod_runtime()
class DR_mod(ModInfo): # NOQA
mod_id = "difficult_rocket_mod"
name = "Difficult Rocket mod"
version = Version("0.3.2.0")
version = Version("0.3.3.0")
writer = "shenjackyuanjie"
link = "shenjack.top"

View File

@ -10,36 +10,33 @@ import logging
import traceback
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.gl import gl
from pyglet.math import Mat4
from pyglet.text import Label
from pyglet.sprite import Sprite
# from pyglet.image import Texture
from pyglet.graphics import Batch, Group
from pyglet.shapes import Line, Rectangle
from pyglet.image import Framebuffer, Texture
from . import DR_mod_runtime
from .types import SR1Textures, SR1Rotation
# 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.client import ClientWindow
from Difficult_Rocket.api.types import Fonts, Options
from Difficult_Rocket.command.line import CommandText
from Difficult_Rocket.client.screen import BaseScreen
from .types import SR1Textures, SR1Rotation
if TYPE_CHECKING:
from Difficult_Rocket.client import ClientWindow
from Difficult_Rocket.api.camera import CenterGroupCamera
from Difficult_Rocket.api.gui.widget import PressTextButton
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
@ -65,7 +62,7 @@ class SR1ShipRender(BaseScreen):
"""用于渲染 sr1 船的类"""
def __init__(self,
main_window: "ClientWindow"):
main_window: ClientWindow):
super().__init__(main_window)
self.logger = logger
logger.info(sr_tr().mod.info.setup.start())
@ -75,14 +72,16 @@ class SR1ShipRender(BaseScreen):
self.dx = 0
self.dy = 0
self.width = main_window.width - 100
self.height = main_window.height - 100
self.buffer = Framebuffer()
self.render_texture = Texture.create(self.width, self.height)
self.buffer.attach_texture(self.render_texture)
self.width = main_window.width
self.height = main_window.height
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,
text='SR1 render!', font_name=Fonts.微软等宽无线,
@ -95,7 +94,12 @@ class SR1ShipRender(BaseScreen):
self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线,
x=main_window.width / 2, y=main_window.height / 2)
self.render_d_label.visible = self.status.draw_d_pos
self.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
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
self.textures: SR1Textures = SR1Textures()
@ -127,8 +131,6 @@ class SR1ShipRender(BaseScreen):
def size(self, value: Tuple[int, int]):
if not self.width == value[0] or not self.height == value[1]:
self.width, self.height = value
self.render_texture = Texture.create(self.width, self.height)
self.buffer.attach_texture(self.render_texture)
def load_xml(self, file_path: str) -> bool:
"""
@ -163,13 +165,15 @@ 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:
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(),
batch=self.main_batch, group=part_group)
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
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:
# 线框
@ -253,9 +256,7 @@ class SR1ShipRender(BaseScreen):
self.parts_sprite: Dict[int, Sprite] = {}
self.part_line_box = {}
self.part_line_list = []
self.camera.zoom = 1.0
self.camera.dx = 0
self.camera.dy = 0
self.group_camera.reset()
# 调用生成器 减少卡顿
try:
self.gen_draw = self.gen_sprite()
@ -273,21 +274,24 @@ class SR1ShipRender(BaseScreen):
len(self.rust_ship.as_list()),
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:
self.render_d_label.text = f'x: {self.camera.dx} y: {self.camera.dy}'
self.render_d_label.position = self.camera.dx + (self.window_pointer.width / 2), 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.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.render_d_line.x2 = self.camera.dx
self.render_d_line.y2 = self.camera.dy
self.buffer.bind()
window.clear()
with self.camera:
self.main_batch.draw()
self.buffer.unbind()
self.render_texture.blit(x=self.dx, y=self.dy, z=0, width=self.width, height=self.height)
self.render_d_line.x2 = self.group_camera.view_x
self.render_d_line.y2 = self.group_camera.view_y
def on_draw(self, window: "ClientWindow"):
gl.glEnable(gl.GL_SCISSOR_TEST)
gl.glScissor(int(self.dx), int(self.dy), int(self.width), int(self.height))
gl.glViewport(int(self.dx), int(self.dy), self.window_pointer.width, self.window_pointer.height)
self.main_batch.draw() # use group camera, no need to with
gl.glViewport(0, 0, self.window_pointer.width, self.window_pointer.height)
gl.glScissor(0, 0, self.window_pointer.width, self.window_pointer.height)
gl.glDisable(gl.GL_SCISSOR_TEST)
# 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()
@ -302,38 +306,39 @@ class SR1ShipRender(BaseScreen):
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
if not self.status.draw_done:
return
self.render_d_line.x2 = width // 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:
return
if self.status.focus:
mouse_dx = x - (window.width / 2)
mouse_dy = y - (window.height / 2)
mouse_dx = x - (self.width / 2) + self.dx
mouse_dy = y - (self.height / 2) + self.dy
# 鼠标缩放位置相对于屏幕中心的位置
mouse_dx_d = mouse_dx - self.camera.dx
mouse_dy_d = mouse_dy - self.camera.dy
mouse_dx_d = mouse_dx - self.group_camera.view_x
mouse_dy_d = mouse_dy - self.group_camera.view_y
# 鼠标相对偏移量的偏移量
if scroll_y == 0:
zoom_d = 1
else:
zoom_d = ((2 ** scroll_y) - 1) * 0.5 + 1
# 缩放的变换量
if not (self.camera.zoom == 10 and scroll_y > 0):
if self.camera.zoom * zoom_d >= 10:
zoom_d = 10 / self.camera.zoom
self.camera.zoom = 10
if not (self.group_camera.zoom == 10 and scroll_y > 0):
if self.group_camera.zoom * zoom_d >= 10:
zoom_d = 10 / self.group_camera.zoom
self.group_camera.zoom = 10
else:
self.camera.zoom *= zoom_d
self.group_camera.zoom *= zoom_d
mouse_dx_d *= (1 - zoom_d)
mouse_dy_d *= (1 - zoom_d)
self.camera.dx += mouse_dx_d
self.camera.dy += mouse_dy_d
self.group_camera.view_x += mouse_dx_d
self.group_camera.view_y += mouse_dy_d
elif self.status.moving:
# 如果是在移动整体渲染位置
size_x, size_y = self.size
@ -345,15 +350,12 @@ class SR1ShipRender(BaseScreen):
size_y = 10
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}')
if command.find('render'):
if command.find('reset'):
self.camera.zoom = 1
self.camera.dx = 0
self.camera.dy = 0
self.window_pointer.view = Vec4()
self.group_camera.reset()
else:
self.status.draw_call = True
print('应该渲染飞船的')
@ -438,17 +440,17 @@ class SR1ShipRender(BaseScreen):
logger.info(sr_tr().sr1.ship.save.start().format(self.rust_ship))
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:
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:
# 如果是在移动整体渲染位置
self.dx += dx
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:
for path in paths:
try:
@ -469,6 +471,15 @@ class SR1ShipRender(BaseScreen):
# break
# self.render_ship()
@property
def view(self):
return self.window_pointer.view
@view.setter
def view(self, value: Mat4):
self.window_pointer.view = value
if __name__ == '__main__':
from objprint import op

View File

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

View File

@ -46,9 +46,10 @@ if __name__ == '__main__':
# 检测 --output xx 参数
if '--output' in sys.argv:
# 输入的是输出目录
compiler.output_path = sys.argv[sys.argv.index('--output') + 1]
out_path = sys.argv[sys.argv.index('--output') + 1]
compiler.output_path = Path(out_path)
sys.argv.remove('--output')
sys.argv.remove(compiler.output_path)
sys.argv.remove(out_path)
# 检测 --no-pyglet-opt 参数
pyglet_optimizations = True
@ -83,7 +84,7 @@ if __name__ == '__main__':
else:
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())