diff --git a/Difficult_Rocket/utils/camera.py b/Difficult_Rocket/utils/camera.py
new file mode 100644
index 0000000..7a48b50
--- /dev/null
+++ b/Difficult_Rocket/utils/camera.py
@@ -0,0 +1,123 @@
+# -------------------------------
+# Difficult Rocket
+# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
+# All rights reserved
+# -------------------------------
+
+# Huge thanks to pyglet developers
+
+from typing import Tuple, Optional
+
+
+class Camera:
+ """
+
+ >>> from pyglet.window import Window
+ >>> window = Window()
+
+ >>> camera = Camera(window)
+ >>> @window.event
+
+ >>> def on_draw():
+ >>> camera.begin()
+ >>> window.clear()
+ >>> camera.end()
+
+ """
+ def __init__(self,
+ window,
+ zoom: Optional[float] = 1.0,
+ dx: Optional[float] = 1.0,
+ dy: Optional[float] = 1.0,
+ min_zoom: Optional[float] = 1.0,
+ max_zoom: Optional[float] = 1.0) -> None:
+ self.window = window
+ self.dx = dx
+ self.dy = dy
+ self.zoom = zoom
+ self.min_zoom = min_zoom
+ self.max_zoom = max_zoom
+
+ def get_view(self):
+ return self.window.view
+
+ @property
+ def position(self) -> Tuple[float, float]:
+ return self.dx, self.dy
+
+ @position.setter
+ def position(self, value: Tuple[float, float]):
+ self.dx, self.dy = value
+
+ @property
+ def zoom_level(self) -> float:
+ return self.zoom
+
+ @zoom_level.setter
+ def zoom_level(self, value: float) -> None:
+ self.zoom = min(max(value, self.min_zoom), self.max_zoom)
+
+ def begin(self) -> None:
+ view = self.window.view
+ x = self.window.width / self.zoom + (self.dx / self.zoom)
+ y = self.window.height / self.zoom + (self.dy / self.zoom)
+
+ view_matrix = view.translate((x * self.zoom, y * self.zoom, 0))
+ view_matrix = view_matrix.scale((self.zoom, self.zoom, 1))
+
+ self.window.view = view_matrix
+
+ def end(self) -> None:
+ view = self.window.view
+ x = self.window.width / self.zoom + (self.dx / self.zoom)
+ y = self.window.height / self.zoom + (self.dy / self.zoom)
+
+ view_matrix = view.scale((1.0 / self.zoom, 1.0 / self.zoom, 1))
+ view_matrix = view_matrix.translate((-x * self.zoom, -y * self.zoom, 0))
+
+ self.window.view = view_matrix
+
+ def __enter__(self):
+ self.begin()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.end()
+
+
+class CenterCamera(Camera):
+ """
+ A camera that centers the view on the center of the window
+
+ >>> from pyglet.window import Window
+ >>> window = Window()
+
+ >>> camera = CenterCamera(window)
+ >>> @window.event
+
+ >>> def on_draw():
+ >>> camera.begin()
+ >>> window.clear()
+ >>> camera.end()
+
+ """
+ def begin(self) -> None:
+ view = self.window.view
+ x = self.window.width / 2.0 / self.zoom + (self.dx / self.zoom)
+ y = self.window.height / 2.0 / self.zoom + (self.dy / self.zoom)
+
+ view_matrix = view.translate((x * self.zoom, y * self.zoom, 0))
+ view_matrix = view_matrix.scale((self.zoom, self.zoom, 1))
+
+ self.window.view = view_matrix
+
+ def end(self) -> None:
+ view = self.window.view
+ x = self.window.width / 2.0 / self.zoom + (self.dx / self.zoom)
+ y = self.window.height / 2.0 / self.zoom + (self.dy / self.zoom)
+
+ view_matrix = view.scale((1.0 / self.zoom, 1.0 / self.zoom, 1))
+ view_matrix = view_matrix.translate((-x * self.zoom, -y * self.zoom, 0))
+
+ self.window.view = view_matrix
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c13bef1..8acf609 100644
--- a/README.md
+++ b/README.md
@@ -12,16 +12,16 @@
[![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)
-[![Generic badge](https://img.shields.io/badge/编写于_Pyglet_版本-2.0.7-blue.svg)](https://pyglet.org)
+[![Generic badge](https://img.shields.io/badge/编写于_Pyglet_版本-2.0.8-blue.svg)](https://pyglet.org)
[![Generic badge](https://img.shields.io/badge/Python-_3.8_|_3.9_|_3.10_|_3.11_-blue.svg)](https://Python.org)
## 版本
[关于版本号的说明](./docs/src/version.md)
-[![Generic badge](https://img.shields.io/badge/Release-0.8.3.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
+[![Generic badge](https://img.shields.io/badge/Release-0.8.4.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
[![Generic badge](https://img.shields.io/badge/Pre_Release-0.8.4.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
-[![Generic badge](https://img.shields.io/badge/Devloping-0.8.4-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
+[![Generic badge](https://img.shields.io/badge/Devloping-0.8.5-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
[![language badge](https://stats.deeptrain.net/repo/shenjackyuanjie/Difficult-Rocket?theme=dark)](https://stats.deeptrain.net/repo/shenjackyuanjie/Difficult-Rocket?theme=dark)
diff --git a/configs/main.toml b/configs/main.toml
index 3e89e77..3490821 100644
--- a/configs/main.toml
+++ b/configs/main.toml
@@ -7,8 +7,8 @@ fonts_folder = "libs/fonts"
[window]
style = "None"
-width = 1041
-height = 1050
+width = 1918
+height = 2088
visible = true
gui_scale = 1
caption = "Difficult Rocket v{DR_version}"
diff --git a/docs/README-en.md b/docs/README-en.md
index deed982..e6bf020 100644
--- a/docs/README-en.md
+++ b/docs/README-en.md
@@ -12,16 +12,16 @@
[![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)
-[![Generic badge](https://img.shields.io/badge/Write_with_Pyglet-2.0.5-blue.svg)](https://pyglet.org)
+[![Generic badge](https://img.shields.io/badge/Write_with_Pyglet-2.0.8-blue.svg)](https://pyglet.org)
[![Generic badge](https://img.shields.io/badge/Python-_3.8_|_3.9_|_3.10_|_3.11_-blue.svg)](https://Python.org)
## Version
[About Versions](src/version.md)
-[![Generic badge](https://img.shields.io/badge/Release-0.8.3.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
+[![Generic badge](https://img.shields.io/badge/Release-0.8.4.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
[![Generic badge](https://img.shields.io/badge/Pre_Release-0.8.4.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
-[![Generic badge](https://img.shields.io/badge/Devloping-0.8.4-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
+[![Generic badge](https://img.shields.io/badge/Devloping-0.8.5-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases)
[![language badge](https://stats.deeptrain.net/repo/shenjackyuanjie/Difficult-Rocket?theme=dark)](https://stats.deeptrain.net/repo/shenjackyuanjie/Difficult-Rocket?theme=dark)
diff --git a/docs/src/change_log/dr_game.md b/docs/src/change_log/dr_game.md
index 14630c6..3315aee 100644
--- a/docs/src/change_log/dr_game.md
+++ b/docs/src/change_log/dr_game.md
@@ -3,7 +3,27 @@
- 最新版本号
- DR game: 0.2.0.0
- - DR rs: 0.2.11.0
+ - DR rs: 0.2.13.0
+
+## DR game 0.2.1.0
+
+### 修改
+
+- 将 `sr1_ship` 中的 `Camera_rs` 改为 `Difficult_Rocket.utils.camera.Camera`
+
+## DR rs 0.2.13.0
+
+### 删除
+
+- 删除了 `render.rs`
+ - 没必要拿 rust 写这玩意(
+ - 用 `DR game` 的 `camera` 代替
+
+## DR rs 0.2.12.0
+
+### 添加
+
+- 添加了 xml 的读取测试
## DR game 0.1.2.0
diff --git a/docs/src/change_log/dr_sdk.md b/docs/src/change_log/dr_sdk.md
index 5620ab7..bca9a98 100644
--- a/docs/src/change_log/dr_sdk.md
+++ b/docs/src/change_log/dr_sdk.md
@@ -2,13 +2,23 @@
# DR SDK 更新日志
- 最新版本号
- - DR sdk: 0.8.3.0
+ - DR sdk: 0.8.4.0
+
+## DR sdk 0.8.4.1
+
+### Add
+
+- `utils.camera`
+ - `Camera`
+ - 一个 2D 摄影机,可以用于高效变换渲染坐标
+ - `CenterCamera`
+ - 一个中心对器的 2D 摄影机,可以用于高效变换渲染坐标
## DR sdk 0.8.4.0
### Fix
-- issue #33 (https://github.com/shenjackyuanjie/Difficult-Rocket/issues/33)
+- issue #33 ()
- 修复了实际上并不会加载 `.otf` 格式的字体文件的问题
### language
diff --git a/libs/pyglet/__init__.py b/libs/pyglet/__init__.py
index 6a71f88..7f743b1 100644
--- a/libs/pyglet/__init__.py
+++ b/libs/pyglet/__init__.py
@@ -9,7 +9,7 @@ import sys
from typing import TYPE_CHECKING
#: The release version
-version = '2.0.7'
+version = '2.0.8'
__version__ = version
MIN_PYTHON_VERSION = 3, 8
diff --git a/libs/pyglet/input/linux/evdev.py b/libs/pyglet/input/linux/evdev.py
index 9b53b1f..5c00fee 100644
--- a/libs/pyglet/input/linux/evdev.py
+++ b/libs/pyglet/input/linux/evdev.py
@@ -4,6 +4,7 @@ import fcntl
import ctypes
import warnings
+from os import readv
from ctypes import c_uint16 as _u16
from ctypes import c_int16 as _s16
from ctypes import c_uint32 as _u32
@@ -306,7 +307,6 @@ class EvdevDevice(XlibSelectDevice, Device):
self._filename = filename
fileno = os.open(filename, os.O_RDONLY)
- # event_version = EVIOCGVERSION(fileno).value
self._id = EVIOCGID(fileno)
self.id_bustype = self._id.bustype
@@ -357,6 +357,9 @@ class EvdevDevice(XlibSelectDevice, Device):
self.controls.sort(key=lambda c: c._event_code)
os.close(fileno)
+ self._event_size = ctypes.sizeof(InputEvent)
+ self._event_buffer = (InputEvent * 64)()
+
super().__init__(display, name)
def get_guid(self):
@@ -405,17 +408,16 @@ class EvdevDevice(XlibSelectDevice, Device):
return
try:
- events = (InputEvent * 64)()
- bytes_read = os.readv(self._fileno, events)
+ bytes_read = readv(self._fileno, self._event_buffer)
except OSError:
self.close()
return
- n_events = bytes_read // ctypes.sizeof(InputEvent)
- for event in events[:n_events]:
+ n_events = bytes_read // self._event_size
+
+ for event in self._event_buffer[:n_events]:
try:
- control = self.control_map[(event.type, event.code)]
- control.value = event.value
+ self.control_map[(event.type, event.code)].value = event.value
except KeyError:
pass
@@ -651,5 +653,4 @@ def _create_controller(device):
def get_controllers(display=None):
return [controller for controller in
- [_create_controller(device) for device in get_devices(display)]
- if controller is not None]
+ [_create_controller(device) for device in get_devices(display)] if controller]
diff --git a/libs/pyglet/media/codecs/base.py b/libs/pyglet/media/codecs/base.py
index d65b23a..652a8a8 100644
--- a/libs/pyglet/media/codecs/base.py
+++ b/libs/pyglet/media/codecs/base.py
@@ -135,17 +135,6 @@ class AudioData:
self.duration -= num_bytes / audio_format.bytes_per_second
self.timestamp += num_bytes / audio_format.bytes_per_second
- def get_string_data(self):
- """Return data as a bytestring.
-
- Returns:
- bytes: Data as a (byte)string.
- """
- if self.data is None:
- return b''
-
- return memoryview(self.data).tobytes()[:self.length]
-
class SourceInfo:
"""Source metadata information.
@@ -409,7 +398,7 @@ class StaticSource(Source):
audio_data = source.get_audio_data(buffer_size)
if not audio_data:
break
- data.write(audio_data.get_string_data())
+ data.write(audio_data.data)
self._data = data.getvalue()
self._duration = len(self._data) / self.audio_format.bytes_per_second
diff --git a/mods/dr_game/Difficult_Rocket_rs/__init__.py b/mods/dr_game/Difficult_Rocket_rs/__init__.py
index ab367f7..d3ac426 100644
--- a/mods/dr_game/Difficult_Rocket_rs/__init__.py
+++ b/mods/dr_game/Difficult_Rocket_rs/__init__.py
@@ -6,7 +6,7 @@
from .lib import *
-from typing import TYPE_CHECKING, Dict, Tuple, Optional
+from typing import TYPE_CHECKING, Dict, Tuple, Optional, List, Tuple
if TYPE_CHECKING:
@@ -18,56 +18,11 @@ if TYPE_CHECKING:
def get_version_str() -> str: ...
-
- def simluation() -> None: ...
-
-
- """ 用来测试 rust 的物理模拟能不能用 """
-
-
def part_list_read_test(file_name: Optional[str] = "./configs/PartList.xml") -> None: ...
def read_ship_test(path: Optional[str] = "./configs/dock1.xml") -> None: ...
-
- class Camera_rs:
- """ 用于闲的没事 用 rust 写一个 camera """
-
- def __new__(cls, window: Window,
- zoom: float = 1.0,
- dx: float = 1.0, dy: float = 1.0,
- min_zoom: float = 1.0,
- max_zoom: float = 1.0): ...
-
- @property
- def dx(self) -> float: ...
- @property
- def dy(self) -> float: ...
- @property
- def zoom(self) -> float: ...
- @property
- def position(self) -> Tuple[float, float]: ...
- @dx.setter
- def dx(self, value: float) -> None: ...
- @dy.setter
- def dy(self, value: float) -> None: ...
- @zoom.setter
- def zoom(self, value: float) -> None: ...
-
- def begin(self) -> None: ...
-
- def end(self) -> None: ...
-
- def __enter__(self, window) -> None: ...
-
- def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...
-
-
- class CenterCamera_rs(Camera_rs):
- """ 用于依旧闲的没事 用 rust 写一个中央对齐的 camera """
-
-
- class PartFrame_rs:
- ...
+
+ def load_and_save_test(file_name: str): ...
class SR1PartType_rs:
@@ -107,6 +62,20 @@ if TYPE_CHECKING:
def get_part_type(self, name: str) -> SR1PartType_rs: ...
+ class SR1PartData_rs:
+ """ 用于从 rust 中读取 SR1PartData (其实好像也没啥用哈)
+ """
+ @property
+ def part_type_id(self) -> str: ...
+ @property
+ def pos(self) -> Tuple[float, float]: ...
+ @property
+ def angle(self) -> float: ...
+ @property
+ def flip_x(self) -> bool: ...
+ @property
+ def flip_y(self) -> bool: ...
+
class SR1Ship_rs:
""" 用于高效且省内存的读取 SR1Ship """
def __init__(self, file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip'): ...
@@ -122,6 +91,8 @@ if TYPE_CHECKING:
def img_pos(self) -> Tuple[int, int, int, int]: ...
""" -x -y +x +y 左下右上 """
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: ...
+ def as_dict(self) -> Dict[int, List[Tuple[SR1PartType_rs, SR1PartData]]]:
+ """用于返回一个包含所有已连接零件的字典"""
class Console_rs:
def __init__(self) -> None: ...
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock b/mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
index d40428d..59acc84 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
+++ b/mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
@@ -91,7 +91,7 @@ dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
- "memoffset 0.9.0",
+ "memoffset",
"scopeguard",
]
@@ -119,6 +119,7 @@ name = "difficult_rocket_rs"
version = "0.2.5"
dependencies = [
"pyo3",
+ "quick-xml",
"rapier2d-f64",
"serde",
"serde-xml-rs",
@@ -182,13 +183,10 @@ dependencies = [
]
[[package]]
-name = "memoffset"
-version = "0.8.0"
+name = "memchr"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
-dependencies = [
- "autocfg",
-]
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
@@ -350,14 +348,14 @@ dependencies = [
[[package]]
name = "pyo3"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b1ac5b3731ba34fdaa9785f8d74d17448cd18f30cf19e0c7e7b1fdb5272109"
+checksum = "cffef52f74ec3b1a1baf295d9b8fcc3070327aefc39a6d00656b13c1d0b8885c"
dependencies = [
"cfg-if",
"indoc",
"libc",
- "memoffset 0.8.0",
+ "memoffset",
"parking_lot",
"pyo3-build-config",
"pyo3-ffi",
@@ -367,9 +365,9 @@ dependencies = [
[[package]]
name = "pyo3-build-config"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cb946f5ac61bb61a5014924910d936ebd2b23b705f7a4a3c40b05c720b079a3"
+checksum = "713eccf888fb05f1a96eb78c0dbc51907fee42b3377272dc902eb38985f418d5"
dependencies = [
"once_cell",
"target-lexicon",
@@ -377,9 +375,9 @@ dependencies = [
[[package]]
name = "pyo3-ffi"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd4d7c5337821916ea2a1d21d1092e8443cf34879e53a0ac653fbb98f44ff65c"
+checksum = "5b2ecbdcfb01cbbf56e179ce969a048fd7305a66d4cdf3303e0da09d69afe4c3"
dependencies = [
"libc",
"pyo3-build-config",
@@ -387,9 +385,9 @@ dependencies = [
[[package]]
name = "pyo3-macros"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9d39c55dab3fc5a4b25bbd1ac10a2da452c4aca13bb450f22818a002e29648d"
+checksum = "b78fdc0899f2ea781c463679b20cb08af9247febc8d052de941951024cd8aea0"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
@@ -399,15 +397,25 @@ dependencies = [
[[package]]
name = "pyo3-macros-backend"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97daff08a4c48320587b5224cc98d609e3c27b6d437315bd40b605c98eeb5918"
+checksum = "60da7b84f1227c3e2fe7593505de274dcf4c8928b4e0a1c23d551a14e4e80a0f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
+[[package]]
+name = "quick-xml"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
[[package]]
name = "quote"
version = "1.0.28"
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml b/mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml
index c787117..de5b5f3 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml
+++ b/mods/dr_game/Difficult_Rocket_rs/src/Cargo.toml
@@ -16,11 +16,11 @@ opt-level = 3
[profile.release]
strip = true
opt-level = "s"
-codegen-units = 1
+# codegen-units = 1
-#[dependencies.quick-xml]
-#version = "0.27.1"
-#features = ["serialize"]
+[dependencies.quick-xml]
+version = "0.29.0"
+features = ["serialize"]
[dependencies.serde]
version = "1.0.164"
@@ -37,5 +37,5 @@ version = "0.17.2"
features = ["simd-stable"]
[dependencies.pyo3]
-version = "0.18.3"
+version = "0.19.0"
features = ["extension-module"]
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs
index 25031ab..767b240 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs
+++ b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs
@@ -9,10 +9,8 @@
mod logger;
mod plugin;
mod python;
-mod render;
mod simulator;
mod sr1_data;
-mod translate;
mod types;
use pyo3::prelude::*;
@@ -27,7 +25,7 @@ enum LoadState {
}
#[pyfunction]
-fn get_version_str() -> String { "0.2.11.0".to_string() }
+fn get_version_str() -> String { "0.2.13.0".to_string() }
#[pyfunction]
fn test_call(py_obj: &PyAny) -> PyResult {
@@ -45,9 +43,8 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(test_call, m)?)?;
m.add_function(wrap_pyfunction!(sr1_data::part_list::read_part_list_py, m)?)?;
m.add_function(wrap_pyfunction!(sr1_data::ship::py_raw_ship_from_file, m)?)?;
- m.add_class::()?;
- m.add_class::()?;
- m.add_class::()?;
+ m.add_function(wrap_pyfunction!(python::data::load_and_save_test, m)?)?;
+ m.add_function(wrap_pyfunction!(python::serde_test::test_ship_read_and_write, m)?)?;
m.add_class::()?;
m.add_class::()?;
m.add_class::()?;
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs
index 8e88f87..f36ada7 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs
+++ b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs
@@ -55,7 +55,6 @@ pub mod data {
#[pyclass]
#[pyo3(name = "SR1PartList_rs")]
- #[pyo3(text_signature = "(file_path = './configs/PartList.xml', list_name = 'NewPartList')")]
pub struct PySR1PartList {
pub data: SR1PartList,
}
@@ -63,6 +62,7 @@ pub mod data {
#[pymethods]
impl PySR1PartList {
#[new]
+ #[pyo3(text_signature = "(file_path = './configs/PartList.xml', list_name = 'NewPartList')")]
fn new(file_path: String, list_name: String) -> Self {
let raw_part_list: RawPartList = RawPartList::from_file(file_path).unwrap();
let data = raw_part_list.to_sr_part_list(Some(list_name));
@@ -74,7 +74,7 @@ pub mod data {
}
fn get_part_type(&self, name: String) -> Option {
- let part_type = self.data.get_part_type(name.clone());
+ let part_type = self.data.get_part_type(&name);
if let Some(part_type) = part_type {
Some(PySR1PartType::new(part_type.clone()))
} else {
@@ -89,9 +89,30 @@ pub mod data {
pub data: SR1PartData,
}
+ impl PySR1PartData {
+ pub fn new(data: SR1PartData) -> Self { Self { data } }
+ }
+
+ #[pymethods]
+ impl PySR1PartData {
+ #[getter]
+ fn get_part_type_id(&self) -> String { self.data.part_type_id.clone() }
+
+ #[getter]
+ fn get_pos(&self) -> (f64, f64) { (self.data.x, self.data.y) }
+
+ #[getter]
+ fn get_angle(&self) -> f64 { self.data.angle }
+
+ #[getter]
+ fn get_flip_x(&self) -> bool { self.data.flip_x }
+
+ #[getter]
+ fn get_flip_y(&self) -> bool { self.data.flip_y }
+ }
+
#[pyclass]
#[pyo3(name = "SR1Ship_rs")]
- #[pyo3(text_signature = "(file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip')")]
pub struct PySR1Ship {
pub ship: SR1Ship,
pub part_list: SR1PartList,
@@ -100,9 +121,11 @@ pub mod data {
#[pymethods]
impl PySR1Ship {
#[new]
+ #[pyo3(text_signature = "(file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip')")]
fn new(file_path: String, part_list: String, ship_name: String) -> Self {
- let ship = SR1Ship::from_file(file_path, Some(ship_name)).unwrap();
+ let mut ship = SR1Ship::from_file(file_path, Some(ship_name)).unwrap();
let part_list = SR1PartList::from_file(part_list).unwrap();
+ ship.parse_part_list_to_part(&part_list); //
Self { ship, part_list }
}
@@ -132,14 +155,28 @@ pub mod data {
#[getter]
fn get_touch_ground(&self) -> bool { self.ship.touch_ground.to_owned() }
- fn iter_parts(&self) -> HashMap {
- let mut parts = HashMap::new();
+ #[getter]
+ fn get_mass(&self) -> f64 {
+ let mut mass = 0_f64;
for part_data in self.ship.parts.iter() {
- let part_type = self.part_list.get_part_type(part_data.part_type_id.clone()).unwrap();
- parts.insert(
- part_data.id,
- (PySR1PartType::new(part_type), PySR1PartData { data: part_data.clone() }),
- );
+ let part_type = self.part_list.get_part_type(&part_data.part_type_id).unwrap();
+ mass += part_type.mass
+ }
+ mass
+ }
+
+ fn as_dict(&self) -> HashMap> {
+ let mut parts: HashMap> = HashMap::new();
+ for part_data in self.ship.parts.iter() {
+ if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
+ let part_type = PySR1PartType::new(part_type.clone());
+ let py_part_data = PySR1PartData::new(part_data.clone());
+ if let Some(part_list) = parts.get_mut(&part_data.id) {
+ part_list.push((part_type, py_part_data));
+ } else {
+ parts.insert(part_data.id, vec![(part_type, py_part_data)]);
+ }
+ }
}
parts
}
@@ -147,7 +184,7 @@ pub mod data {
fn get_part_box(&self, part_id: i64) -> Option<((f64, f64), (f64, f64))> {
let part_data = self.ship.parts.iter().find(|&x| x.id == part_id);
if let Some(part_data) = part_data {
- let part_type = self.part_list.get_part_type(part_data.part_type_id.clone()).unwrap();
+ let part_type = self.part_list.get_part_type(&part_data.part_type_id).unwrap();
// rotate
let radius = part_data.angle;
let ((x1, y1), (x2, y2)) = part_type.get_box();
@@ -162,11 +199,21 @@ pub mod data {
}
None
}
- }
-}
-pub mod translate {
- use crate::translate;
+ fn save(&self, file_path: String) -> PyResult<()> {
+ self.ship.save(file_path).unwrap();
+ Ok(())
+ }
+ }
+
+ #[pyfunction]
+ pub fn load_and_save_test(file_name: String) -> PyResult<()> {
+ use crate::sr1_data::ship::RawShip;
+ use serde_xml_rs::to_string;
+ let ship = RawShip::from_file(file_name).unwrap();
+ let _save_string = to_string(&ship);
+ Ok(())
+ }
}
pub mod console {
@@ -238,3 +285,127 @@ pub mod console {
}
}
}
+
+pub mod serde_test {
+ use pyo3::prelude::*;
+ use quick_xml::de::from_str;
+ use quick_xml::se::to_string;
+ use quick_xml::Writer;
+ use serde::{Deserialize, Serialize};
+ use std::fs;
+
+ type IdType = i64;
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ #[serde(rename = "Ship")]
+ pub struct TestShip {
+ #[serde(rename = "@version")]
+ pub version: i32,
+ #[serde(rename = "@liftedOff")]
+ pub lift_off: i8,
+ #[serde(rename = "@touchingGround")]
+ pub touching_ground: i8,
+ #[serde(rename = "Connections")]
+ pub connections: Connections,
+ #[serde(rename = "DisconnectedParts")]
+ pub disconnected_parts: Option,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct DisconnectedParts {
+ #[serde(rename = "DisconnectedPart")]
+ pub disconnected_part: Option>,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct DisconnectedPart {
+ #[serde(rename = "Parts")]
+ pub parts: Parts,
+ #[serde(rename = "Connections")]
+ pub connections: Connections,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct Connections {
+ #[serde(rename = "Connection")]
+ pub connection: Option>,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct Connection {
+ #[serde(rename = "@parentAttachPoint")]
+ pub parent_attach_point: i32,
+ #[serde(rename = "@childAttachPoint")]
+ pub child_attach_point: i32,
+ #[serde(rename = "@parentPart")]
+ pub parent_part: IdType,
+ #[serde(rename = "@childPart")]
+ pub child_part: IdType,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct Parts {
+ #[serde(rename = "Part")]
+ pub part: Vec,
+ }
+
+ #[derive(Serialize, Deserialize, Debug, Clone)]
+ pub struct Part {
+ // #[serde(rename = "@Tank")]
+ // pub tank: Option,
+ // #[serde(rename = "@Engine")]
+ // pub engine: Option,
+ // #[serde(rename = "@Pod")]
+ // pub pod: Option,
+ #[serde(rename = "@partType")]
+ pub part_type_id: String,
+ #[serde(rename = "@id")]
+ pub id: i64,
+ #[serde(rename = "@x")]
+ pub x: f64,
+ #[serde(rename = "@y")]
+ pub y: f64,
+ #[serde(rename = "@editorAngle")]
+ pub editor_angle: i32,
+ #[serde(rename = "@angle")]
+ pub angle: f64,
+ #[serde(rename = "@angleV")]
+ pub angle_v: f64,
+ #[serde(rename = "@flippedX")]
+ pub flip_x: Option,
+ #[serde(rename = "@flippedY")]
+ pub flip_y: Option,
+ #[serde(rename = "@chuteX")]
+ pub chute_x: Option,
+ #[serde(rename = "@chuteY")]
+ pub chute_y: Option,
+ #[serde(rename = "@chuteAngle")]
+ pub chute_angle: Option,
+ #[serde(rename = "@chuteHeight")]
+ pub chute_height: Option,
+ #[serde(rename = "@extension")]
+ pub extension: Option,
+ #[serde(rename = "@inflate")]
+ pub inflate: Option,
+ #[serde(rename = "@inflation")]
+ pub inflation: Option,
+ #[serde(rename = "@exploded")]
+ pub exploded: Option,
+ #[serde(rename = "@rope")]
+ pub rope: Option,
+ #[serde(rename = "@activated")]
+ pub activated: Option,
+ #[serde(rename = "@deployed")]
+ pub deployed: Option,
+ }
+
+ #[pyfunction]
+ #[pyo3(name = "test_ship_read_and_write")]
+ pub fn test_ship_read_and_write(file_name: String) -> PyResult<()> {
+ let file = fs::read_to_string(file_name).unwrap();
+ let ship: TestShip = from_str(&file).unwrap();
+ let save_string = to_string(&ship).unwrap();
+ fs::write("./test-xml-rs.xml", save_string).unwrap();
+ Ok(())
+ }
+}
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/render.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/render.rs
deleted file mode 100644
index 7d560f6..0000000
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/render.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * -------------------------------
- * Difficult Rocket
- * Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
- * All rights reserved
- * -------------------------------
- */
-
-pub mod camera {
-
- use pyo3::intern;
- use pyo3::prelude::*;
-
- #[pyclass(name = "Camera_rs", subclass)]
- pub struct CameraRs {
- pub window: Py,
- #[pyo3(get, set)]
- pub dx: f64,
- #[pyo3(get, set)]
- pub dy: f64,
- pub zoom: f64,
- #[pyo3(get, set)]
- pub max_zoom: f64,
- #[pyo3(get, set)]
- pub min_zoom: f64,
- }
-
- #[pyclass(extends = CameraRs, name = "CenterCamera_rs")]
- pub struct CenterCameraRs;
-
- #[pymethods]
- impl CenterCameraRs {
- #[new]
- #[pyo3(signature = (window, zoom=1.0, dx=1.0, dy=1.0, min_zoom=1.0, max_zoom=1.0))]
- pub fn py_new(window: &PyAny, zoom: f64, dx: f64, dy: f64, min_zoom: f64, max_zoom: f64) -> PyResult<(Self, CameraRs)> {
- return Ok((
- CenterCameraRs {},
- CameraRs {
- dx,
- dy,
- zoom,
- min_zoom,
- max_zoom,
- window: window.into(),
- },
- ));
- }
-
- // pub fn __enter__(py_self: PyRef) -> PyResult> {
- // // println!("enter!");
- // CenterCameraRs::begin()?;
- // Ok(py_self)
- // }
-
- pub fn begin(self_: PyRef<'_, Self>) -> PyResult<()> {
- println!("begin!");
- let super_: &CameraRs = self_.as_ref();
- // 获取父类
- Python::with_gil(|py| -> PyResult<()> {
- let view = super_.window.getattr(py, intern!(py, "view"))?;
- // 获取存储的 view
- let x: f64 = super_.window.getattr(py, intern!(py, "width"))?.extract(py)?;
- let y: f64 = super_.window.getattr(py, intern!(py, "height"))?.extract(py)?;
- let x: f64 = x / 2.0 / super_.zoom + (super_.dx / super_.zoom);
- let y: f64 = y / 2.0 / super_.zoom + (super_.dy / super_.zoom);
- // 计算中心点
-
- // view.call_method1(py, "translate", (x, y))?;
- // view.call_method1(py, "scale", (super_.zoom, super_.zoom))?;
-
- let args = ((x * super_.zoom, y * super_.zoom, 0),);
- let view_matrix = view.call_method1(py, intern!(py, "translate"), args)?;
- // view_matrix = self.view.translate((x * zoom, y * zoom, 0))
-
- let args = ((super_.zoom, super_.zoom, 1),);
- let view_matrix = view_matrix.call_method1(py, intern!(py, "scale"), args)?;
- // view_matrix = view_matrix.scale((zoom, zoom, 1))
-
- super_.window.setattr(py, intern!(py, "view"), view_matrix)?;
- // self.view = view_matrix
- Ok(())
- })?;
- Ok(())
- }
- }
-
- #[pymethods]
- impl CameraRs {
- #[new]
- #[pyo3(signature = (window, zoom=1.0, dx=1.0, dy=1.0, min_zoom=1.0, max_zoom=1.0))]
- pub fn py_new(window: &PyAny, zoom: f64, dx: f64, dy: f64, min_zoom: f64, max_zoom: f64) -> PyResult {
- return Ok(CameraRs {
- dx,
- dy,
- zoom,
- min_zoom,
- max_zoom,
- window: window.into(),
- });
- }
-
- pub fn get_view(&self) -> PyResult {
- Ok(Python::with_gil(|py| -> PyResult {
- Ok(self.window.getattr(py, intern!(py, "view"))?)
- })?)
- }
-
- #[getter]
- pub fn get_position(&self) -> (f64, f64) { return (self.dx, self.dy); }
-
- #[setter]
- pub fn set_position(&mut self, value: (f64, f64)) -> () {
- self.dx = value.0;
- self.dy = value.1;
- }
-
- #[getter]
- pub fn get_zoom(&self) -> PyResult { Ok(self.zoom) }
-
- #[setter]
- pub fn set_zoom(&mut self, value: f64) -> PyResult<()> {
- self.zoom = value.min(self.max_zoom).max(self.min_zoom);
- Ok(())
- }
-
- pub fn begin(&self) -> PyResult<()> {
- Python::with_gil(|py| -> PyResult<()> {
- let view = self.window.getattr(py, intern!(py, "view"))?;
-
- let x: f64 = self.window.getattr(py, intern!(py, "width"))?.extract(py)?;
- let y: f64 = self.window.getattr(py, intern!(py, "height"))?.extract(py)?;
- let x: f64 = x / 2.0 / self.zoom + (self.dx / self.zoom);
- let y: f64 = y / 2.0 / self.zoom + (self.dy / self.zoom);
- // use to get center of the screen
-
- let args = ((x * self.zoom, y * self.zoom, 0),);
- let view_matrix = view.call_method1(py, intern!(py, "translate"), args)?;
- // view_matrix = self.view.translate((x * zoom, y * zoom, 0))
-
- let args = ((self.zoom, self.zoom, 1),);
- let view_matrix = view_matrix.call_method1(py, intern!(py, "scale"), args)?;
- // view_matrix = view_matrix.scale((zoom, zoom, 1))
-
- self.window.setattr(py, intern!(py, "view"), view_matrix)?;
- // self.view = view_matrix
- Ok(())
- })?;
- return Ok(());
- }
-
- pub fn end(&self) -> PyResult<()> {
- Python::with_gil(|py| -> PyResult<()> {
- let view = self.window.getattr(py, intern!(py, "view"))?;
-
- let x: f64 = self.window.getattr(py, intern!(py, "width"))?.extract(py)?;
- let y: f64 = self.window.getattr(py, intern!(py, "height"))?.extract(py)?;
- let x: f64 = x / 2.0 / self.zoom + (self.dx / self.zoom);
- let y: f64 = y / 2.0 / self.zoom + (self.dy / self.zoom);
-
- let args = ((1.0 / self.zoom, 1.0 / self.zoom, 1),);
- let view_matrix = view.call_method1(py, intern!(py, "scale"), args)?;
-
- let args = ((-x * self.zoom, -y * self.zoom, 0),);
- let view_matrix = view_matrix.call_method1(py, intern!(py, "translate"), args)?;
-
- self.window.setattr(py, intern!(py, "view"), view_matrix)?;
- Ok(())
- })?;
- return Ok(());
- }
-
- /// https://github.com/PyO3/pyo3/discussions/2931#discussioncomment-4820729 for finding this
- /// https://github.com/PyO3/pyo3/issues/1205#issuecomment-1164096251 for advice on `__enter__`
- pub fn __enter__(py_self: PyRef) -> PyResult> {
- // println!("enter!");
- py_self.begin()?;
- Ok(py_self)
- }
-
- pub fn __exit__(&self, _exc_type: PyObject, _exc_value: PyObject, _traceback: PyObject) -> PyResult<()> {
- // println!("exit!");
- self.end()?;
- return Ok(());
- }
- }
-}
-
-pub mod screen {
- use pyo3::prelude::*;
- // use crate::types::sr1::SR1PartData;
-
- #[pyclass]
- #[pyo3(name = "PartFrame_rs")]
- pub struct PartFrame {
- pub box_size: i32,
- pub width: i64,
- pub height: i64,
- // pub frame_box: Vec>
- }
-
- #[pymethods]
- impl PartFrame {
- #[new]
- pub fn py_new() -> PyResult {
- Ok(PartFrame {
- box_size: 111,
- width: 111,
- height: 111,
- })
- }
- }
-}
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/simulator.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/simulator.rs
index 67f4737..1dad45f 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/simulator.rs
+++ b/mods/dr_game/Difficult_Rocket_rs/src/src/simulator.rs
@@ -64,8 +64,38 @@ pub fn simulation() -> () {
}
}
-#[allow(unused)]
+pub struct Simulator {
+ pub rigid_body_set: RigidBodySet,
+ pub collider_set: ColliderSet,
+ pub gravity: Vector,
+ pub integration_parameters: IntegrationParameters,
+ pub physics_pipeline: PhysicsPipeline,
+ pub island_manager: IslandManager,
+ pub broad_phase: BroadPhase,
+ pub narrow_phase: NarrowPhase,
+ pub impulse_joint_set: ImpulseJointSet,
+ pub multibody_joint_set: MultibodyJointSet,
+ pub ccd_solver: CCDSolver,
+ pub physics_hooks: (),
+ pub event_handler: (),
+}
+
pub mod python {
use pyo3::prelude::*;
use rapier2d_f64::prelude::*;
+
+ #[pyclass]
+ pub struct PyIntegrationParameters {
+ pub data: IntegrationParameters,
+ }
+
+ #[pymethods]
+ impl PyIntegrationParameters {
+ #[new]
+ fn new() -> Self {
+ PyIntegrationParameters {
+ data: IntegrationParameters::default(),
+ }
+ }
+ }
}
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/sr1_data.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/sr1_data.rs
index b4c6794..e80160a 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/sr1_data.rs
+++ b/mods/dr_game/Difficult_Rocket_rs/src/src/sr1_data.rs
@@ -607,6 +607,18 @@ pub mod ship {
}
}
}
+
+ #[inline]
+ pub fn save(&self, file_name: String) -> Option<()> {
+ let part_list_file = serde_xml_rs::to_string(self);
+ print!("{:?}", part_list_file);
+ if let Ok(part_list_file) = part_list_file {
+ fs::write(file_name, part_list_file).unwrap();
+ Some(())
+ } else {
+ None
+ }
+ }
}
#[pyfunction]
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
deleted file mode 100644
index 586097b..0000000
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * -------------------------------
- * Difficult Rocket
- * Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
- * All rights reserved
- * -------------------------------
- */
-
-use std::collections::HashMap;
-
-type TranslateMapper = HashMap>>;
-
-pub struct Translater {
- pub data: TranslateMapper,
- pub language: String,
-}
diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs
index 63b739a..4c45ff1 100644
--- a/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs
+++ b/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs
@@ -246,9 +246,9 @@ pub mod sr1 {
}
#[inline]
- pub fn get_part_type(&self, type_name: String) -> Option {
+ pub fn get_part_type(&self, type_name: &String) -> Option {
let cache = self.get_cache();
- match cache.get(&type_name) {
+ match cache.get(type_name) {
Some(part) => Some(part.clone()),
None => None,
}
@@ -699,11 +699,10 @@ pub mod sr1 {
Some(ship.to_sr_ship(ship_name))
}
- pub fn parse_part_list_to_part(&mut self, part_list: SR1PartList) {
+ pub fn parse_part_list_to_part(&mut self, part_list: &SR1PartList) {
// parse parts
for part in self.parts.iter_mut() {
- let part_type_id = part.part_type_id.clone();
- if let Some(part_type) = part_list.get_part_type(part_type_id) {
+ if let Some(part_type) = part_list.get_part_type(&part.part_type_id) {
part.part_type = part_type.p_type;
} else {
part.part_type = SR1PartTypeEnum::strut;
@@ -712,8 +711,7 @@ pub mod sr1 {
for disconnects in self.disconnected.iter_mut() {
for (parts, _) in disconnects.iter_mut() {
for part in parts.iter_mut() {
- let part_type_id = part.part_type_id.clone();
- if let Some(part_type) = part_list.get_part_type(part_type_id) {
+ if let Some(part_type) = part_list.get_part_type(&part.part_type_id) {
part.part_type = part_type.p_type;
} else {
part.part_type = SR1PartTypeEnum::strut;
@@ -722,6 +720,27 @@ pub mod sr1 {
}
}
}
+
+ pub fn part_as_hashmap(&self) -> HashMap> {
+ // 返回一个 HashMap 用于快速查找
+ // 同时为了 防止出现多个相同的 PartID 造成的数据丢失
+ // 采用 Vec 存储
+ let mut result: HashMap> = HashMap::new();
+ for part_data in self.parts.iter() {
+ if let Some(part_vec) = result.get_mut(&part_data.id) {
+ part_vec.push(part_data.clone());
+ } else {
+ result.insert(part_data.id, vec![part_data.clone()]);
+ }
+ }
+ result
+ }
+
+ pub fn save(&self, file_name: String) -> Option<()> {
+ let raw_ship = self.to_raw_ship();
+ raw_ship.save(file_name);
+ Some(())
+ }
}
impl SR1ShipTrait for SR1Ship {
@@ -780,7 +799,7 @@ pub mod sr1 {
pub fn get_max_box(parts: &Vec, part_list: &SR1PartList) -> (f64, f64, f64, f64) {
let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64);
for part in parts.iter() {
- let part_type = part_list.get_part_type(part.part_type_id.clone()).unwrap();
+ let part_type = part_list.get_part_type(&part.part_type_id).unwrap();
let ((x1, y1), (x2, y2)) = part_type.get_box();
// rotate
let mut p1 = Point2D::new(x1, y1);
diff --git a/mods/dr_game/__init__.py b/mods/dr_game/__init__.py
index a930e96..55238fe 100644
--- a/mods/dr_game/__init__.py
+++ b/mods/dr_game/__init__.py
@@ -17,7 +17,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.11.0") # DR_mod 的 Rust 编写部分的兼容版本
+DR_rust_version = Version("0.2.12.0") # DR_mod 的 Rust 编写部分的兼容版本
logger = logging.getLogger('client.dr_game')
diff --git a/mods/dr_game/lang/zh-CN.toml b/mods/dr_game/lang/zh-CN.toml
index a1baf37..b124803 100644
--- a/mods/dr_game/lang/zh-CN.toml
+++ b/mods/dr_game/lang/zh-CN.toml
@@ -8,6 +8,6 @@ xml.load_done = "XML 文件加载完成"
xml.load_time = "XML 文件加载消耗时间: {} 秒"
ship.load = "正在加载飞船: {}"
ship.load_time = "飞船加载消耗时间: {} 秒"
-#ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}\n- 文件大小: {}"
ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}"
ship.render.done = "飞船渲染完成"
+save.start = "正在保存飞船: {}"
diff --git a/mods/dr_game/sr1_ship.py b/mods/dr_game/sr1_ship.py
index 3c56220..cf4d87e 100644
--- a/mods/dr_game/sr1_ship.py
+++ b/mods/dr_game/sr1_ship.py
@@ -30,13 +30,17 @@ from Difficult_Rocket.utils.translate import Tr
from Difficult_Rocket.api.types import Fonts, Options
from Difficult_Rocket.command.line import CommandText
from Difficult_Rocket.client.screen import BaseScreen
+from Difficult_Rocket.utils.camera import CenterCamera
from .types import SR1Textures, SR1PartTexture, SR1PartData, SR1Rotation, xml_bool
if TYPE_CHECKING:
from Difficult_Rocket.client import ClientWindow
if DR_mod_runtime.use_DR_rust:
- from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, SR1Ship_rs
+ from .Difficult_Rocket_rs import (SR1PartList_rs,
+ SR1Ship_rs,
+ load_and_save_test,
+ test_ship_read_and_write)
logger = logging.getLogger('client.dr_game_sr1_ship')
sr_tr = Tr(lang_path=Path('./mods/dr_game/lang'))
@@ -134,9 +138,9 @@ class SR1ShipRender(BaseScreen):
load_end_time = time.time_ns()
logger.info(sr_tr().mod.info.setup.use_time().format(
(load_end_time - load_start_time) / 1000000000))
+ self.camera = CenterCamera(main_window,
+ min_zoom=(1 / 2) ** 10, max_zoom=10)
if DR_mod_runtime.use_DR_rust:
- self.camera_rs = CenterCamera_rs(main_window,
- min_zoom=(1 / 2) ** 10, max_zoom=10)
self.rust_parts = None
self.part_list_rs = SR1PartList_rs('configs/PartList.xml', 'default_part_list')
@@ -150,6 +154,8 @@ class SR1ShipRender(BaseScreen):
self.xml_name = file_path
if DR_mod_runtime.use_DR_rust:
try:
+ load_and_save_test(self.xml_name)
+ test_ship_read_and_write(self.xml_name)
self.rust_ship = SR1Ship_rs(file_path, 'configs/PartList.xml', 'a_new_ship')
print(self.rust_ship.name)
print(self.rust_ship.img_pos)
@@ -228,10 +234,9 @@ class SR1ShipRender(BaseScreen):
self.part_data: Dict[int, SR1PartData] = {}
self.parts_sprite: Dict[int, Sprite] = {}
self.part_line_box = {}
- self.camera_rs.zoom = 1.0
- if DR_mod_runtime.use_DR_rust:
- self.camera_rs.dx = 0
- self.camera_rs.dy = 0
+ self.camera.zoom = 1.0
+ self.camera.dx = 0
+ self.camera.dy = 0
parts = self.xml_root.find('Parts')
for part_xml in parts:
if part_xml.tag != 'Part':
@@ -260,11 +265,11 @@ class SR1ShipRender(BaseScreen):
def update_parts(self) -> bool:
if not self.rendered:
return False
- self.debug_line.x2, self.debug_line.y2 = self.camera_rs.dx + (
- self.window_pointer.width / 2), self.camera_rs.dy + (
+ self.debug_line.x2, self.debug_line.y2 = self.camera.dx + (
+ self.window_pointer.width / 2), self.camera.dy + (
self.window_pointer.height / 2)
- self.debug_d_pos_label.text = f'x: {self.camera_rs.dx} y: {self.camera_rs.dy}'
- self.debug_d_pos_label.position = self.camera_rs.dx + (self.window_pointer.width / 2), self.camera_rs.dy + (
+ self.debug_d_pos_label.text = f'x: {self.camera.dx} y: {self.camera.dy}'
+ self.debug_d_pos_label.position = self.camera.dx + (self.window_pointer.width / 2), self.camera.dy + (
self.window_pointer.height / 2) + 10, 0
self.need_update_parts = False
@@ -283,7 +288,7 @@ class SR1ShipRender(BaseScreen):
self.update_parts()
self.need_update_parts = False
- with self.camera_rs:
+ with self.camera:
self.part_box_batch.draw()
self.part_batch.draw()
self.part_box_batch.draw()
@@ -317,29 +322,29 @@ class SR1ShipRender(BaseScreen):
mouse_dx = x - (window.width / 2)
mouse_dy = y - (window.height / 2)
# 鼠标缩放位置相对于屏幕中心的位置
- mouse_dx_d = mouse_dx - self.camera_rs.dx
- mouse_dy_d = mouse_dy - self.camera_rs.dy
+ mouse_dx_d = mouse_dx - self.camera.dx
+ mouse_dy_d = mouse_dy - self.camera.dy
# 鼠标相对偏移量的偏移量
if scroll_y == 0:
zoom_d = 1
else:
zoom_d = ((2 ** scroll_y) - 1) * 0.5 + 1
# 缩放的变换量
- if not (self.camera_rs.zoom == 10 and scroll_y > 0):
- if self.camera_rs.zoom * zoom_d >= 10:
- zoom_d = 10 / self.camera_rs.zoom
- self.camera_rs.zoom = 10
+ 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
else:
- self.camera_rs.zoom *= zoom_d
+ self.camera.zoom *= zoom_d
mouse_dx_d *= (1 - zoom_d)
mouse_dy_d *= (1 - zoom_d)
- self.camera_rs.dx += mouse_dx_d
- self.camera_rs.dy += mouse_dy_d
+ self.camera.dx += mouse_dx_d
+ self.camera.dy += mouse_dy_d
self.debug_mouse_line.x2, self.debug_mouse_line.y2 = x, y
- self.debug_mouse_delta_line.x2 = (mouse_dx - self.camera_rs.dx) * (1 - (0.5 ** scroll_y)) + (
+ self.debug_mouse_delta_line.x2 = (mouse_dx - self.camera.dx) * (1 - (0.5 ** scroll_y)) + (
window.width / 2)
- self.debug_mouse_delta_line.y2 = (mouse_dy - self.camera_rs.dy) * (1 - (0.5 ** scroll_y)) + (
+ self.debug_mouse_delta_line.y2 = (mouse_dy - self.camera.dy) * (1 - (0.5 ** scroll_y)) + (
window.height / 2)
self.debug_mouse_label.text = f'x: {mouse_dx} y: {mouse_dy}'
self.debug_mouse_label.position = x, y + 10, 0
@@ -349,9 +354,9 @@ class SR1ShipRender(BaseScreen):
def on_command(self, command: CommandText, window: "ClientWindow"):
if command.find('render'):
if command.find('reset'):
- self.camera_rs.zoom = 1
- self.camera_rs.dx = 0
- self.camera_rs.dy = 0
+ self.camera.zoom = 1
+ self.camera.dx = 0
+ self.camera.dy = 0
self.window_pointer.view = Vec4()
else:
self.need_draw = True
@@ -430,11 +435,20 @@ class SR1ShipRender(BaseScreen):
img.paste(pil_image, (int(self.part_data[part].x * 60 + img_center[0]), int(-self.part_data[part].y * 60 + img_center[1])), pil_image)
img.save(f'test{time.time()}.png', 'PNG')
+ elif command.find('test'):
+ if command.find('save'):
+ if not self.rendered:
+ return
+ if not DR_mod_runtime.use_DR_rust:
+ return
+ 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"):
if not self.focus:
return
- self.camera_rs.dx += dx
- self.camera_rs.dy += dy
+ self.camera.dx += dx
+ self.camera.dy += dy
self.need_update_parts = True
# self.update_parts()