Feature/py camera #35
@ -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: ...
|
||||
|
@ -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> {
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
}
|
@ -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);
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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 = "飞船渲染完成"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user