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 typing import TYPE_CHECKING, Dict, Tuple, Optional
from typing import TYPE_CHECKING, Dict, Tuple, Optional, List, Tuple
if TYPE_CHECKING:
@ -107,6 +107,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 +136,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: ...

View File

@ -12,7 +12,6 @@ mod python;
mod render;
mod simulator;
mod sr1_data;
mod translate;
mod types;
use pyo3::prelude::*;
@ -27,7 +26,7 @@ enum LoadState {
}
#[pyfunction]
fn get_version_str() -> String { "0.2.11.0".to_string() }
fn get_version_str() -> String { "0.2.12.0".to_string() }
#[pyfunction]
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> {
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,6 +89,28 @@ 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')")]
@ -101,8 +123,9 @@ pub mod data {
impl PySR1Ship {
#[new]
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<i64, (PySR1PartType, PySR1PartData)> {
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<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
}
@ -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,12 @@ pub mod data {
}
None
}
}
}
pub mod translate {
use crate::translate;
fn save(&self, file_path: String) -> PyResult<()> {
self.ship.save(file_path).unwrap();
Ok(())
}
}
}
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 {
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(),
}
}
}
}

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]

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]
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();
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<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 {
@ -780,7 +799,7 @@ pub mod sr1 {
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);
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);

View File

@ -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')

View File

@ -8,6 +8,5 @@ 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 = "飞船渲染完成"

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.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"):
if not self.focus:
return