Feature/py camera #35

Merged
shenjackyuanjie merged 9 commits from feature/py_camera into main 2023-06-25 15:45:54 +08:00
10 changed files with 148 additions and 44 deletions
Showing only changes of commit 85c2e4b21c - Show all commits

View File

@ -6,7 +6,7 @@
from .lib import * from .lib import *
from typing import TYPE_CHECKING, Dict, Tuple, Optional from typing import TYPE_CHECKING, Dict, Tuple, Optional, List, Tuple
if TYPE_CHECKING: if TYPE_CHECKING:
@ -107,6 +107,20 @@ if TYPE_CHECKING:
def get_part_type(self, name: str) -> SR1PartType_rs: ... 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: class SR1Ship_rs:
""" 用于高效且省内存的读取 SR1Ship """ """ 用于高效且省内存的读取 SR1Ship """
def __init__(self, file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip'): ... def __init__(self, file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip'): ...
@ -122,6 +136,8 @@ if TYPE_CHECKING:
def img_pos(self) -> Tuple[int, int, int, int]: ... def img_pos(self) -> Tuple[int, int, int, int]: ...
""" -x -y +x +y 左下右上 """ """ -x -y +x +y 左下右上 """
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: ... 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: class Console_rs:
def __init__(self) -> None: ... def __init__(self) -> None: ...

View File

@ -12,7 +12,6 @@ mod python;
mod render; mod render;
mod simulator; mod simulator;
mod sr1_data; mod sr1_data;
mod translate;
mod types; mod types;
use pyo3::prelude::*; use pyo3::prelude::*;
@ -27,7 +26,7 @@ enum LoadState {
} }
#[pyfunction] #[pyfunction]
fn get_version_str() -> String { "0.2.11.0".to_string() } fn get_version_str() -> String { "0.2.12.0".to_string() }
#[pyfunction] #[pyfunction]
fn test_call(py_obj: &PyAny) -> PyResult<bool> { fn test_call(py_obj: &PyAny) -> PyResult<bool> {

View File

@ -74,7 +74,7 @@ pub mod data {
} }
fn get_part_type(&self, name: String) -> Option<PySR1PartType> { fn get_part_type(&self, name: String) -> Option<PySR1PartType> {
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 { if let Some(part_type) = part_type {
Some(PySR1PartType::new(part_type.clone())) Some(PySR1PartType::new(part_type.clone()))
} else { } else {
@ -89,6 +89,28 @@ pub mod data {
pub data: SR1PartData, 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] #[pyclass]
#[pyo3(name = "SR1Ship_rs")] #[pyo3(name = "SR1Ship_rs")]
#[pyo3(text_signature = "(file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip')")] #[pyo3(text_signature = "(file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip')")]
@ -101,8 +123,9 @@ pub mod data {
impl PySR1Ship { impl PySR1Ship {
#[new] #[new]
fn new(file_path: String, part_list: String, ship_name: String) -> Self { 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(); let part_list = SR1PartList::from_file(part_list).unwrap();
ship.parse_part_list_to_part(&part_list); //
Self { ship, part_list } Self { ship, part_list }
} }
@ -132,14 +155,28 @@ pub mod data {
#[getter] #[getter]
fn get_touch_ground(&self) -> bool { self.ship.touch_ground.to_owned() } fn get_touch_ground(&self) -> bool { self.ship.touch_ground.to_owned() }
fn iter_parts(&self) -> HashMap<i64, (PySR1PartType, PySR1PartData)> { #[getter]
let mut parts = HashMap::new(); fn get_mass(&self) -> f64 {
let mut mass = 0_f64;
for part_data in self.ship.parts.iter() { for part_data in self.ship.parts.iter() {
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();
parts.insert( mass += part_type.mass
part_data.id, }
(PySR1PartType::new(part_type), PySR1PartData { data: part_data.clone() }), mass
); }
fn as_dict(&self) -> HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> {
let mut parts: HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> = 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 parts
} }
@ -147,7 +184,7 @@ pub mod data {
fn get_part_box(&self, part_id: i64) -> Option<((f64, f64), (f64, f64))> { 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); let part_data = self.ship.parts.iter().find(|&x| x.id == part_id);
if let Some(part_data) = part_data { 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 // rotate
let radius = part_data.angle; let radius = part_data.angle;
let ((x1, y1), (x2, y2)) = part_type.get_box(); let ((x1, y1), (x2, y2)) = part_type.get_box();
@ -162,11 +199,12 @@ pub mod data {
} }
None None
} }
}
}
pub mod translate { fn save(&self, file_path: String) -> PyResult<()> {
use crate::translate; self.ship.save(file_path).unwrap();
Ok(())
}
}
} }
pub mod console { pub mod console {

View File

@ -64,8 +64,38 @@ pub fn simulation() -> () {
} }
} }
#[allow(unused)] pub struct Simulator {
pub rigid_body_set: RigidBodySet,
pub collider_set: ColliderSet,
pub gravity: Vector<f64>,
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 { pub mod python {
use pyo3::prelude::*; use pyo3::prelude::*;
use rapier2d_f64::prelude::*; use rapier2d_f64::prelude::*;
#[pyclass]
pub struct PyIntegrationParameters {
pub data: IntegrationParameters,
}
#[pymethods]
impl PyIntegrationParameters {
#[new]
fn new() -> Self {
PyIntegrationParameters {
data: IntegrationParameters::default(),
}
}
}
} }

View File

@ -607,6 +607,17 @@ pub mod ship {
} }
} }
} }
#[inline]
pub fn save(&self, file_name: String) -> Option<()> {
let part_list_file = serde_xml_rs::to_string(self);
if let Ok(part_list_file) = part_list_file {
fs::write(file_name, part_list_file).unwrap();
Some(())
} else {
None
}
}
} }
#[pyfunction] #[pyfunction]

View File

@ -1,16 +0,0 @@
/*
* -------------------------------
* Difficult Rocket
* Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
* All rights reserved
* -------------------------------
*/
use std::collections::HashMap;
type TranslateMapper = HashMap<String, HashMap<String, HashMap<String, String>>>;
pub struct Translater {
pub data: TranslateMapper,
pub language: String,
}

View File

@ -246,9 +246,9 @@ pub mod sr1 {
} }
#[inline] #[inline]
pub fn get_part_type(&self, type_name: String) -> Option<SR1PartType> { pub fn get_part_type(&self, type_name: &String) -> Option<SR1PartType> {
let cache = self.get_cache(); let cache = self.get_cache();
match cache.get(&type_name) { match cache.get(type_name) {
Some(part) => Some(part.clone()), Some(part) => Some(part.clone()),
None => None, None => None,
} }
@ -699,11 +699,10 @@ pub mod sr1 {
Some(ship.to_sr_ship(ship_name)) 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 // parse parts
for part in self.parts.iter_mut() { 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.part_type_id) {
if let Some(part_type) = part_list.get_part_type(part_type_id) {
part.part_type = part_type.p_type; part.part_type = part_type.p_type;
} else { } else {
part.part_type = SR1PartTypeEnum::strut; part.part_type = SR1PartTypeEnum::strut;
@ -712,8 +711,7 @@ pub mod sr1 {
for disconnects in self.disconnected.iter_mut() { for disconnects in self.disconnected.iter_mut() {
for (parts, _) in disconnects.iter_mut() { for (parts, _) in disconnects.iter_mut() {
for part in parts.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.part_type_id) {
if let Some(part_type) = part_list.get_part_type(part_type_id) {
part.part_type = part_type.p_type; part.part_type = part_type.p_type;
} else { } else {
part.part_type = SR1PartTypeEnum::strut; part.part_type = SR1PartTypeEnum::strut;
@ -722,6 +720,27 @@ pub mod sr1 {
} }
} }
} }
pub fn part_as_hashmap(&self) -> HashMap<i64, Vec<SR1PartData>> {
// 返回一个 HashMap 用于快速查找
// 同时为了 防止出现多个相同的 PartID 造成的数据丢失
// 采用 Vec 存储
let mut result: HashMap<i64, Vec<SR1PartData>> = 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 { impl SR1ShipTrait for SR1Ship {
@ -780,7 +799,7 @@ pub mod sr1 {
pub fn get_max_box(parts: &Vec<SR1PartData>, part_list: &SR1PartList) -> (f64, f64, f64, f64) { pub fn get_max_box(parts: &Vec<SR1PartData>, part_list: &SR1PartList) -> (f64, f64, f64, f64) {
let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64); let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64);
for part in parts.iter() { 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(); let ((x1, y1), (x2, y2)) = part_type.get_box();
// rotate // rotate
let mut p1 = Point2D::new(x1, y1); let mut p1 = Point2D::new(x1, y1);

View File

@ -17,7 +17,7 @@ from Difficult_Rocket.api.mod import ModInfo
from Difficult_Rocket.client import ClientWindow from Difficult_Rocket.client import ClientWindow
from Difficult_Rocket.api.types import Options, Version from Difficult_Rocket.api.types import Options, Version
DR_rust_version = Version("0.2.11.0") # DR_mod 的 Rust 编写部分的兼容版本 DR_rust_version = Version("0.2.12.0") # DR_mod 的 Rust 编写部分的兼容版本
logger = logging.getLogger('client.dr_game') logger = logging.getLogger('client.dr_game')

View File

@ -8,6 +8,5 @@ xml.load_done = "XML 文件加载完成"
xml.load_time = "XML 文件加载消耗时间: {} 秒" xml.load_time = "XML 文件加载消耗时间: {} 秒"
ship.load = "正在加载飞船: {}" ship.load = "正在加载飞船: {}"
ship.load_time = "飞船加载消耗时间: {} 秒" ship.load_time = "飞船加载消耗时间: {} 秒"
#ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}\n- 文件大小: {}"
ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}" ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}"
ship.render.done = "飞船渲染完成" ship.render.done = "飞船渲染完成"

View File

@ -430,6 +430,14 @@ 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.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') 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
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 not self.focus: if not self.focus:
return return