This commit is contained in:
shenjack 2023-02-19 11:47:15 +08:00
parent 54efb392ee
commit 6bf4930463
9 changed files with 178 additions and 57 deletions

View File

@ -22,9 +22,9 @@ from Difficult_Rocket.api.types import Options
from libs.MCDR.version import Version from libs.MCDR.version import Version
game_version = Version("0.7.0.2") # 游戏版本 game_version = Version("0.7.0.3") # 游戏版本
build_version = Version("1.1.0.0") # 编译文件版本(与游戏本体无关) build_version = Version("1.1.0.0") # 编译文件版本(与游戏本体无关)
DR_rust_version = Version("0.2.0.0") # DR 的 Rust 编写部分的版本 DR_rust_version = Version("0.2.2.0") # DR 的 Rust 编写部分的版本
__version__ = game_version __version__ = game_version
long_version: int = 12 long_version: int = 12
@ -78,7 +78,7 @@ class _DR_option(Options):
if sys.platform != 'darwin': # MacOS 的测试只能在 Macos 上跑 if sys.platform != 'darwin': # MacOS 的测试只能在 Macos 上跑
self.pyglet_macosx_dev_test = False self.pyglet_macosx_dev_test = False
try: try:
from libs.Difficult_Rocket_rs import test_call, get_version_str from libs.Difficult_Rocket_rs import test_call, get_version_str, xml_read_test
test_call(self) test_call(self)
print(f'DR_rust available: {get_version_str()}') print(f'DR_rust available: {get_version_str()}')
except ImportError: except ImportError:

View File

@ -185,9 +185,11 @@ class SR1ShipRender(BaseScreen):
print(f'hey! warning! id{part.id}') print(f'hey! warning! id{part.id}')
self.part_data[part.id] = part self.part_data[part.id] = part
# 调用生成器 减少卡顿 # 调用生成器 减少卡顿
with contextlib.suppress(GeneratorExit): try:
self.gen_draw = self.gen_sprite(self.part_data) self.gen_draw = self.gen_sprite(self.part_data)
next(self.gen_draw) next(self.gen_draw)
except GeneratorExit:
self.drawing = False
self.need_draw = False self.need_draw = False
if DR_option.use_DR_rust: if DR_option.use_DR_rust:

View File

@ -20,6 +20,10 @@ if TYPE_CHECKING:
def get_version_str() -> str: ... def get_version_str() -> str: ...
def simluation() -> None: ... def simluation() -> None: ...
""" 用来测试 rust 的物理模拟能不能用 """
def xml_read_test() -> None: ...
""" 用来测试 rust 的 xml 读取"""
class PartDatas: class PartDatas:
""" 用于在 PyObj 里塞一个浓眉大眼的 HashMap<uszie, SR1PartData>""" """ 用于在 PyObj 里塞一个浓眉大眼的 HashMap<uszie, SR1PartData>"""

View File

@ -116,9 +116,10 @@ dependencies = [
[[package]] [[package]]
name = "difficult_rocket_rs" name = "difficult_rocket_rs"
version = "0.2.0" version = "0.2.2"
dependencies = [ dependencies = [
"pyo3", "pyo3",
"quick-xml",
"rapier2d-f64", "rapier2d-f64",
] ]
@ -171,6 +172,12 @@ dependencies = [
"rawpointer", "rawpointer",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.7.1" version = "0.7.1"
@ -398,6 +405,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "quick-xml"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffc053f057dd768a56f62cd7e434c42c831d296968997e9ac1f76ea7c2d14c41"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.23"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "difficult_rocket_rs" name = "difficult_rocket_rs"
version = "0.2.0" version = "0.2.2"
edition = "2021" edition = "2021"
license-file = '../../LICENSE' license-file = '../../LICENSE'
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -17,6 +17,10 @@ opt-level = 3
[profile.release] [profile.release]
codegen-units = 1 codegen-units = 1
[dependencies.quick-xml]
version = "0.27.1"
[dependencies.rapier2d-f64] [dependencies.rapier2d-f64]
version = "0.17.1" version = "0.17.1"
features = ["simd-stable"] features = ["simd-stable"]

View File

@ -8,6 +8,7 @@
mod sr1_render; mod sr1_render;
mod simulator; mod simulator;
mod sr1_data;
mod render; mod render;
mod types; mod types;
@ -15,7 +16,7 @@ use pyo3::prelude::*;
#[pyfunction] #[pyfunction]
fn get_version_str() -> String { fn get_version_str() -> String {
return String::from("0.2.0.0"); return String::from("0.2.2.0");
} }
#[pyfunction] #[pyfunction]
@ -34,6 +35,7 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(test_call, m)?)?; m.add_function(wrap_pyfunction!(test_call, m)?)?;
m.add_function(wrap_pyfunction!(sr1_render::better_update_parts, m)?)?; m.add_function(wrap_pyfunction!(sr1_render::better_update_parts, m)?)?;
m.add_function(wrap_pyfunction!(simulator::simluation, m)?)?; m.add_function(wrap_pyfunction!(simulator::simluation, m)?)?;
m.add_function(wrap_pyfunction!(sr1_data::read_xml, m)?)?;
m.add_class::<sr1_render::types::PartDatas>()?; m.add_class::<sr1_render::types::PartDatas>()?;
m.add_class::<render::camera::CameraRs>()?; m.add_class::<render::camera::CameraRs>()?;
m.add_class::<render::screen::PartFrame>()?; m.add_class::<render::screen::PartFrame>()?;

View File

@ -0,0 +1,56 @@
/*
* -------------------------------
* Difficult Rocket
* Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
* All rights reserved
* -------------------------------
*/
use pyo3::prelude::*;
use quick_xml::events::Event;
use quick_xml::reader::Reader;
#[pyfunction]
#[pyo3(name = "xml_read_test")]
pub fn read_xml() {
let xml = r#"<tag1 att1 = "test">
<tag2><!--Test comment-->Test</tag2>
<tag2>Test 2</tag2>
</tag1>"#;
let mut reader = Reader::from_str(xml);
reader.trim_text(true);
let mut count = 0;
let mut txt = Vec::new();
let mut buf = Vec::new();
// The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
loop {
// NOTE: this is the generic case when we don't know about the input BufRead.
// when the input is a &str or a &[u8], we don't actually need to use another
// buffer, we could directly call `reader.read_event()`
match reader.read_event_into(&mut buf) {
Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
// exits the loop when reaching end of file
Ok(Event::Eof) => break,
Ok(Event::Start(e)) => {
match e.name().as_ref() {
b"tag1" => println!("attributes values: {:?}",
e.attributes().map(|a| a.unwrap().value)
.collect::<Vec<_>>()),
b"tag2" => count += 1,
_ => (),
}
}
Ok(Event::Text(e)) => txt.push(e.unescape().unwrap().into_owned()),
// There are several other `Event`s we do not consider here
_ => (),
}
// if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low
buf.clear();
}
}

View File

@ -52,6 +52,15 @@ pub mod types {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn part_data_to_SR1PartData(input: &PyAny) -> PyResult<SR1PartData> { pub fn part_data_to_SR1PartData(input: &PyAny) -> PyResult<SR1PartData> {
let connections = match input.getattr(intern!(input.py(), "connections")) {
Ok(ok) => {
ok.extract()?
}
_ => {
None
}
};
return Ok(SR1PartData{ return Ok(SR1PartData{
x: input.getattr(intern!(input.py(), "x"))?.extract()?, x: input.getattr(intern!(input.py(), "x"))?.extract()?,
y: input.getattr(intern!(input.py(), "y"))?.extract()?, y: input.getattr(intern!(input.py(), "y"))?.extract()?,
@ -65,7 +74,7 @@ pub mod types {
flip_y: input.getattr(intern!(input.py(), "flip_y"))?.extract()?, flip_y: input.getattr(intern!(input.py(), "flip_y"))?.extract()?,
explode: input.getattr(intern!(input.py(), "explode"))?.extract()?, explode: input.getattr(intern!(input.py(), "explode"))?.extract()?,
textures: input.getattr(intern!(input.py(), "textures"))?.extract()?, textures: input.getattr(intern!(input.py(), "textures"))?.extract()?,
connections: None connections
// connections: input.getattr(intern!(input.py(), "connections"))?.extract()?, // connections: input.getattr(intern!(input.py(), "connections"))?.extract()?,
}) })
} }

View File

@ -6,47 +6,39 @@
* ------------------------------- * -------------------------------
*/ */
#[allow(dead_code)]
pub mod sr1 {
use std::collections::HashMap;
pub mod sr1 {
pub fn map_ptype_textures(ptype: String) -> String { pub fn map_ptype_textures(ptype: String) -> String {
let mut value_map: HashMap<&str, &str> = HashMap::with_capacity(27 * 2); match ptype.as_str() {
value_map.insert("pod-1", "Pod"); "pod-1" => "Pod",
value_map.insert("detacher-1", "DetacherVertical"); "detacher-1" => "DetacherVertical",
value_map.insert("detacher-2", "DetacherRadial"); "detacher-2" => "DetacherRadial",
value_map.insert("wheel-1", "Wheel"); "wheel-1" => "Wheel",
value_map.insert("wheel-2", "Wheel"); "wheel-2" => "Wheel",
value_map.insert("fuselage-1", "Fuselage"); "fuselage-1" => "Fuselage",
value_map.insert("strut-1", "Beam"); "strut-1" => "Beam",
value_map.insert("fueltank-0", "TankTiny"); "fueltank-0" => "TankTiny",
value_map.insert("fueltank-1", "TankSmall"); "fueltank-1" => "TankSmall",
value_map.insert("fueltank-2", "TankMedium"); "fueltank-2" => "TankMedium",
value_map.insert("fueltank-3", "TankLarge"); "fueltank-3" => "TankLarge",
value_map.insert("fueltank-4", "Puffy750"); "fueltank-4" => "Puffy750",
value_map.insert("fueltank-5", "SideTank"); "fueltank-5" => "SideTank",
value_map.insert("engine-0", "EngineTiny"); "engine-0" => "EngineTiny",
value_map.insert("engine-1", "EngineSmall"); "engine-1" => "EngineSmall",
value_map.insert("engine-2", "EngineMedium"); "engine-2" => "EngineMedium",
value_map.insert("engine-3", "EngineLarge"); "engine-3" => "EngineLarge",
value_map.insert("engine-4", "SolidRocketBooster"); "engine-4" => "SolidRocketBooster",
value_map.insert("ion-0", "EngineIon"); "ion-0" => "EngineIon",
value_map.insert("parachute-1", "ParachuteCanister"); "parachute-1" => "ParachuteCanister",
value_map.insert("nosecone-1", "NoseCone"); "nosecone-1" => "NoseCone",
value_map.insert("rcs-1", "RcsBlock"); "rcs-1" => "RcsBlock",
value_map.insert("solar-1", "SolarPanelBase"); "solar-1" => "SolarPanelBase",
value_map.insert("battery-0", "Battery"); "battery-0" => "Battery",
value_map.insert("dock-1", "DockingConnector"); "dock-1" => "DockingConnector",
value_map.insert("port-1", "DockingPort"); "port-1" => "DockingPort",
value_map.insert("lander-1", "LanderLegPreview"); "lander-1" => "LanderLegPreview",
let result = value_map.get(ptype.as_str()); _ => "Pod",
match result { }.to_string()
None => "Pod".to_string(),
Some(i) => {
let i = *i;
i.to_string()
}
}
} }
pub struct SR1PartData { pub struct SR1PartData {
@ -62,7 +54,7 @@ pub mod sr1 {
pub flip_y: bool, pub flip_y: bool,
pub explode: bool, pub explode: bool,
pub textures: String, pub textures: String,
pub connections: Option<Vec<(usize, usize)>> pub connections: Option<Vec<((usize, usize), (isize, isize))>>
} }
} }
@ -80,6 +72,7 @@ pub mod math {
Point2D{x, y} Point2D{x, y}
} }
#[inline]
pub fn new_00() -> Self { Point2D { x: 0.0, y :0.0 } } pub fn new_00() -> Self { Point2D { x: 0.0, y :0.0 } }
#[inline] #[inline]
@ -90,9 +83,19 @@ pub mod math {
} }
#[inline] #[inline]
pub fn get_op(&self) -> f64 { pub fn distance_00(&self) -> f64 {
self.distance(&Point2D::new(0.0, 0.0)) self.distance(&Point2D::new(0.0, 0.0))
} }
#[inline]
pub fn rotate_angle(&self, angle: f64) -> Self {
let radius = angle.to_radians();
let sin = radius.sin();
let cos = radius.cos();
let x = self.x * cos - self.y * sin;
let y = self.x * sin + self.y * cos;
Point2D{ x, y }
}
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -125,6 +128,39 @@ pub mod math {
CircularArc{data: CircularArc}, CircularArc{data: CircularArc},
} }
#[derive(Clone)]
pub struct Shape {
pub pos: Point2D,
pub angle: f64,
// 旋转角度 角度值
pub bounds: Vec<Edge>
}
impl Shape {
pub fn new(x: Option<f64>, y: Option<f64>, angle: Option<f64>, bounds: Vec<Edge>) -> Self {
let x = x.unwrap_or(0.0);
let y = y.unwrap_or(0.0);
let angle = angle.unwrap_or(0.0);
Shape { pos: Point2D::new(x, y), angle, bounds }
}
pub fn new_width_height(width: f64, height: f64, angle: Option<f64>) -> Self {
let d_width = width / 2.0;
let d_height = height / 2.0;
let mut edges: Vec<Edge> = vec![
Edge::OneTimeLine{data: OneTimeLine::pos_new(-d_width, -d_height, d_width, -d_height)},
Edge::OneTimeLine{data: OneTimeLine::pos_new(d_width, -d_height, d_width, d_height)},
Edge::OneTimeLine{data: OneTimeLine::pos_new(d_width, d_height, -d_width, d_height)},
Edge::OneTimeLine{data: OneTimeLine::pos_new(-d_width, d_height, -d_width, -d_height)}
];
if let Some(angle) = angle {
}
Shape { pos: Point2D::new_00(), angle: 0.0, bounds: edges}
}
}
impl OneTimeLine { impl OneTimeLine {
#[inline] #[inline]
pub fn pos_new(x1: f64, y1: f64, x2: f64, y2: f64) -> Self { pub fn pos_new(x1: f64, y1: f64, x2: f64, y2: f64) -> Self {
@ -194,14 +230,6 @@ pub mod dr {
} }
#[derive(Clone)]
pub struct Shape {
pub x: f64,
pub y: f64,
pub angle: f64,
// 旋转角度 角度值
pub bounds: Vec<math::Edge>
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum PartType { pub enum PartType {