first part for phy simluation #34
@ -15,7 +15,7 @@ import traceback
|
||||
|
||||
from pathlib import Path
|
||||
from decimal import Decimal
|
||||
from typing import Callable, Dict, List, TYPE_CHECKING
|
||||
from typing import Callable, Dict, List, TYPE_CHECKING, Optional
|
||||
|
||||
# third function
|
||||
import rtoml
|
||||
@ -23,6 +23,7 @@ import pyglet
|
||||
# from pyglet import gl
|
||||
# from pyglet.gl import glClearColor
|
||||
# from pyglet.libs.win32 import _user32
|
||||
from pyglet.graphics import Group, Batch
|
||||
from pyglet.window import Window
|
||||
from pyglet.window import key, mouse
|
||||
|
||||
@ -37,10 +38,10 @@ from Difficult_Rocket.utils.translate import tr
|
||||
from Difficult_Rocket.runtime import DR_runtime
|
||||
from Difficult_Rocket.api.screen import BaseScreen
|
||||
from Difficult_Rocket.utils.thread import new_thread
|
||||
from Difficult_Rocket.client.screen import DRDEBUGScreen
|
||||
from Difficult_Rocket.client.fps.fps_log import FpsLogger
|
||||
from Difficult_Rocket.client.guis.widgets import InputBox
|
||||
from Difficult_Rocket.exception.language import LanguageNotFound
|
||||
from Difficult_Rocket.client.screen import DRScreen, DRDEBUGScreen
|
||||
|
||||
|
||||
logger = logging.getLogger('client')
|
||||
@ -122,7 +123,36 @@ def pyglet_load_fonts_folder(folder) -> None:
|
||||
pyglet_load_fonts_folder(os.path.join(folder, obj))
|
||||
|
||||
|
||||
def _call_back(call_back: Callable) -> Callable:
|
||||
"""
|
||||
>>> def call_back():
|
||||
>>> pass
|
||||
>>> @_call_back(call_back)
|
||||
>>> def on_draw(self):
|
||||
>>> pass
|
||||
用于在调用窗口函数后调用指定函数 的装饰器
|
||||
:param call_back: 需要调用的函数
|
||||
:return: 包装后的函数
|
||||
"""
|
||||
def wrapper(func):
|
||||
@functools.wraps(func)
|
||||
def warp(self: "ClientWindow", *args, **kwargs):
|
||||
result = func(self, *args, **kwargs)
|
||||
call_back(self)
|
||||
return result
|
||||
return warp
|
||||
return wrapper
|
||||
|
||||
|
||||
def _call_screen_after(func: Callable) -> Callable:
|
||||
"""
|
||||
>>> @_call_screen_after
|
||||
>>> def on_draw(self):
|
||||
>>> pass
|
||||
用于在调用窗口函数后调用子窗口函数 的装饰器
|
||||
:param func: 需要包装的函数
|
||||
:return: 包装后的函数
|
||||
"""
|
||||
@functools.wraps(func)
|
||||
def warped(self: "ClientWindow", *args, **kwargs):
|
||||
result = func(self, *args, **kwargs)
|
||||
@ -141,6 +171,14 @@ def _call_screen_after(func: Callable) -> Callable:
|
||||
|
||||
|
||||
def _call_screen_before(func: Callable) -> Callable:
|
||||
"""
|
||||
>>> @_call_screen_before
|
||||
>>> def on_draw(self):
|
||||
>>> pass
|
||||
用于在调用窗口函数前调用子窗口函数 的装饰器
|
||||
:param func: 需要包装的函数
|
||||
:return: 包装后的函数
|
||||
"""
|
||||
@functools.wraps(func)
|
||||
def warped(self: "ClientWindow", *args, **kwargs):
|
||||
for title, a_screen in self.screen_list.items():
|
||||
@ -185,8 +223,9 @@ class ClientWindow(Window):
|
||||
self.SPF = Decimal('1') / self.FPS
|
||||
self.fps_log = FpsLogger(stable_fps=int(self.FPS))
|
||||
# batch
|
||||
self.part_batch = pyglet.graphics.Batch()
|
||||
self.label_batch = pyglet.graphics.Batch()
|
||||
self.part_batch = Batch()
|
||||
self.label_batch = Batch()
|
||||
self.main_group = Group(0)
|
||||
# frame
|
||||
self.frame = pyglet.gui.Frame(self, order=20)
|
||||
self.M_frame = pyglet.gui.MovableFrame(self, modifier=key.LCTRL)
|
||||
@ -194,9 +233,10 @@ class ClientWindow(Window):
|
||||
# setup
|
||||
self.setup()
|
||||
# 命令显示
|
||||
self.command_group = pyglet.graphics.Group(0)
|
||||
self.command_batch = Batch()
|
||||
self.command_group = Group(1, parent=self.main_group)
|
||||
self.input_box = InputBox(x=50, y=30, width=300,
|
||||
batch=self.label_batch, text='') # 实例化
|
||||
batch=self.command_batch, text='') # 实例化
|
||||
self.input_box.push_handlers(self)
|
||||
self.input_box.set_handler('on_commit', self.on_input)
|
||||
self.set_handlers(self.input_box)
|
||||
@ -215,9 +255,7 @@ class ClientWindow(Window):
|
||||
def setup(self):
|
||||
self.set_icon(pyglet.image.load('./textures/icon.png'))
|
||||
self.load_fonts()
|
||||
# TODO 读取配置文件,加载不同的屏幕,解耦
|
||||
self.screen_list['DR_debug'] = DRDEBUGScreen(self)
|
||||
self.screen_list['DR_main'] = DRScreen(self)
|
||||
self.game.dispatch_event('on_client_start', game=self.game, client=self)
|
||||
|
||||
def load_fonts(self) -> None:
|
||||
@ -264,6 +302,10 @@ class ClientWindow(Window):
|
||||
now_FPS = pyglet.clock.get_frequency()
|
||||
self.fps_log.update_tick(now_FPS, decimal_tick)
|
||||
|
||||
def on_command_draw(self):
|
||||
self.command_batch.draw()
|
||||
|
||||
@_call_back(on_command_draw)
|
||||
@_call_screen_after
|
||||
def on_draw(self, *dt):
|
||||
while command := self.game.console.get_command():
|
||||
@ -306,10 +348,15 @@ class ClientWindow(Window):
|
||||
self.on_command(command_text)
|
||||
self.input_box.value = ''
|
||||
|
||||
def new_command(self):
|
||||
self.game.console.new_command()
|
||||
|
||||
@_call_back(new_command)
|
||||
@_call_screen_after
|
||||
def on_command(self, command: line.CommandText):
|
||||
print(command.find('/'))
|
||||
command.text = command.text.rstrip('\n')
|
||||
self.logger.info(tr().window.command.text().format(command))
|
||||
command.find('/')
|
||||
if command.find('stop'):
|
||||
# self.dispatch_event('on_exit')
|
||||
print("command stop!")
|
||||
@ -335,8 +382,9 @@ class ClientWindow(Window):
|
||||
except LanguageNotFound:
|
||||
self.logger.info(tr().language_available().format(os.listdir('./configs/lang')))
|
||||
self.save_info()
|
||||
|
||||
# self.command_tree.parse(command.plain_command)
|
||||
elif command.find('mods'):
|
||||
for mod in self.game.mod_module:
|
||||
self.logger.info(f"mod: {mod.name} id: {mod.mod_id} version: {mod.version}")
|
||||
|
||||
@_call_screen_after
|
||||
def on_message(self, message: line.CommandText):
|
||||
|
@ -7,24 +7,17 @@
|
||||
import typing
|
||||
|
||||
from pyglet.text import Label
|
||||
from pyglet.graphics import Batch, Group
|
||||
from pyglet.clock import get_frequency
|
||||
from pyglet.graphics import Batch, Group
|
||||
|
||||
# Difficult Rocket function
|
||||
from Difficult_Rocket.api.types import Fonts
|
||||
# from Difficult_Rocket.utils import translate
|
||||
from Difficult_Rocket.api.screen import BaseScreen
|
||||
# from Difficult_Rocket.command.tree import CommandTree
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from Difficult_Rocket.client import ClientWindow
|
||||
|
||||
|
||||
class DRScreen(BaseScreen):
|
||||
def __init__(self, main_window: "ClientWindow"):
|
||||
super().__init__(main_window)
|
||||
|
||||
|
||||
class DRDEBUGScreen(BaseScreen):
|
||||
def __init__(self, main_window: "ClientWindow"):
|
||||
super().__init__(main_window)
|
||||
@ -55,4 +48,3 @@ class DRDEBUGScreen(BaseScreen):
|
||||
|
||||
def on_draw(self, *dt, window: "ClientWindow"):
|
||||
self.main_batch.draw()
|
||||
# print(self.window_pointer.try_if_runs)
|
||||
|
@ -44,9 +44,12 @@ class CommandText:
|
||||
i += 1
|
||||
|
||||
def find(self, text: str) -> bool:
|
||||
startswith = self.text.startswith(text)
|
||||
if startswith:
|
||||
find = self.text.find(text)
|
||||
if find != -1:
|
||||
self.text = self.text[find + len(text):]
|
||||
if not len(text) == len(self.text):
|
||||
self.text = self.text[find + len(text):] if not self.text[find+len(text)] == ' ' else self.text[find + len(text) + 1:]
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -65,6 +65,9 @@ class Console(Options):
|
||||
def get_command(self) -> Optional[str]:
|
||||
return self.caches.pop(0) if self.caches else None
|
||||
|
||||
def new_command(self) -> None:
|
||||
return None
|
||||
|
||||
|
||||
class Game(Options):
|
||||
name = 'MainGame'
|
||||
|
@ -16,20 +16,19 @@ import sys
|
||||
import time
|
||||
import math
|
||||
import json
|
||||
import rtoml
|
||||
import logging
|
||||
import configparser
|
||||
|
||||
from typing import Union
|
||||
from pathlib import Path
|
||||
from typing import Union, Optional
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import rtoml
|
||||
|
||||
from defusedxml.ElementTree import parse
|
||||
|
||||
from Difficult_Rocket.exception.unsupport import NoMoreJson5
|
||||
|
||||
# logger
|
||||
tools_logger = logging.getLogger('part-tools')
|
||||
tools_logger = logging.getLogger('tools')
|
||||
"""
|
||||
file configs
|
||||
"""
|
||||
@ -39,10 +38,12 @@ file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name:
|
||||
Exception: 'get some {error_type} when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'}
|
||||
|
||||
|
||||
def load_file(file_name: str,
|
||||
stack: Union[str, list, dict, None] = None,
|
||||
raise_error: bool = True,
|
||||
encoding: str = 'utf-8') -> Union[dict, ElementTree.ElementTree]:
|
||||
def load_file(file_name: Union[str, Path],
|
||||
stack: Optional[Union[str, list, dict]] = None,
|
||||
raise_error: Optional[bool] = True,
|
||||
encoding: Optional[str] = 'utf-8') -> Union[dict, ElementTree.ElementTree]:
|
||||
if isinstance(file_name, Path):
|
||||
file_name = str(file_name)
|
||||
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
|
||||
get_file = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!')
|
||||
try:
|
||||
|
@ -14,6 +14,7 @@ gitee: @shenjackyuanjie
|
||||
import os
|
||||
import inspect
|
||||
|
||||
from pathlib import Path
|
||||
from dataclasses import dataclass
|
||||
from typing import Union, Tuple, Any, List, Dict, Hashable, Optional
|
||||
|
||||
@ -153,15 +154,16 @@ class Tr:
|
||||
GOOD
|
||||
"""
|
||||
|
||||
def __init__(self, language: str = None, config: Optional[TranslateConfig] = None):
|
||||
def __init__(self, language: str = None, config: Optional[TranslateConfig] = None, lang_path: Optional[Path] = None):
|
||||
"""
|
||||
诶嘿,我抄的MCDR
|
||||
:param language: Tr 所使用的的语言
|
||||
:param config: 配置
|
||||
"""
|
||||
self.language_name = language if language is not None else DR_runtime.language
|
||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'configs/lang/{self.language_name}.toml')
|
||||
self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_status.default_language}.toml')
|
||||
self.language_path = lang_path if lang_path is not None else Path('configs/lang')
|
||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(self.language_path / f'{self.language_name}.toml')
|
||||
self.default_translate: Dict = tools.load_file(f'{self.language_path}/{DR_status.default_language}.toml')
|
||||
self.default_config = config.set('source', self) if config is not None else TranslateConfig(source=self)
|
||||
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
||||
|
||||
@ -185,11 +187,11 @@ class Tr:
|
||||
if lang == ' ' or lang == '':
|
||||
raise LanguageNotFound('Can not be empty')
|
||||
lang = lang or self.language_name
|
||||
if not os.path.exists(f'./configs/lang/{lang}.toml'):
|
||||
print(f"lang: {os.path.exists(f'./configs/lang/{lang}.toml')} language = {lang} {self.language_name=}")
|
||||
if not os.path.exists(f'{self.language_path}/{lang}.toml'):
|
||||
print(f"lang: {os.path.exists(f'{self.language_path}/{lang}.toml')} language = {lang} {self.language_name=}")
|
||||
raise LanguageNotFound(lang)
|
||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'configs/lang/{lang}.toml')
|
||||
self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_runtime.default_language}.toml')
|
||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'{self.language_path}/{lang}.toml')
|
||||
self.default_translate: Dict = tools.load_file(f'{self.language_path}/{DR_runtime.default_language}.toml')
|
||||
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
||||
self.language_name = lang
|
||||
DR_runtime.language = self.language_name
|
||||
|
@ -75,14 +75,3 @@ input = "console"
|
||||
window = "window"
|
||||
command = "in game commands"
|
||||
require_DR_rs = "require DR_rs module"
|
||||
|
||||
[client.sr1_render]
|
||||
setup.start = "SR1 Renderer start loading"
|
||||
setup.use_time = "SR1 Renderer loading has used: {} second"
|
||||
xml.loading = "Loading XML file: {}"
|
||||
xml.load_done = "XML file loaded"
|
||||
xml.load_time = "XML file loading has used: {} second"
|
||||
ship.load = "Loading ship: {}"
|
||||
ship.load_time = "Ship loading has used: {} second"
|
||||
ship.info = "Ship info:\n- Parts: {}\n- Weight: {}"
|
||||
ship.render.done = "Ship render done"
|
||||
|
@ -75,15 +75,3 @@ input = "控制台"
|
||||
window = "窗口"
|
||||
command = "游戏内命令行"
|
||||
require_DR_rs = "需要 DR_rs 模块"
|
||||
|
||||
[client.sr1_render]
|
||||
setup.start = "SR1 渲染器开始载入"
|
||||
setup.use_time = "SR1 渲染器载入消耗时间: {} 秒"
|
||||
xml.loading = "正在加载XML文件: {}"
|
||||
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 = "飞船渲染完成"
|
||||
|
@ -7,8 +7,8 @@ fonts_folder = "libs/fonts"
|
||||
|
||||
[window]
|
||||
style = "None"
|
||||
width = 1021
|
||||
height = 1078
|
||||
width = 1041
|
||||
height = 1050
|
||||
visible = true
|
||||
gui_scale = 1
|
||||
caption = "Difficult Rocket v{DR_version}"
|
||||
|
@ -3,7 +3,24 @@
|
||||
|
||||
- 最新版本号
|
||||
- DR game: 0.2.0.0
|
||||
- DR rs: 0.2.10.1
|
||||
- DR rs: 0.2.11.0
|
||||
|
||||
## DR game 0.1.2.0
|
||||
|
||||
### 修改
|
||||
|
||||
- 现在渲染飞船的时候不会再显示那个白色框了
|
||||
- 改为一个彩色的框
|
||||
- Now, the ship will not be displayed in the white box
|
||||
- Change to a colored box
|
||||
|
||||
## DR rs 0.2.11.0
|
||||
|
||||
### 添加
|
||||
|
||||
- `Python::data::PySR1Ship`
|
||||
- `get_part_box(&self, part_id: i64) -> Option<(f64, f64), (f64, f64)>`
|
||||
- 用于获取对应 id 的实际碰撞箱
|
||||
|
||||
## DR game 0.2.0.0
|
||||
|
||||
|
@ -11,6 +11,21 @@
|
||||
- issue #33 (https://github.com/shenjackyuanjie/Difficult-Rocket/issues/33)
|
||||
- 修复了实际上并不会加载 `.otf` 格式的字体文件的问题
|
||||
|
||||
### 修改
|
||||
|
||||
- 现在输入命令之后不会输出一个 `True`/`False` 了
|
||||
- (实际上是用来检测命令是不是用 `/` 开头的)
|
||||
- Now, the command will not output a `True`/`False`
|
||||
- (Actually used to detect whether the command starts with `/`)
|
||||
- `CommandText`
|
||||
- `find`
|
||||
- 现在会先用 `str.startswith` 检测是否以要求的字符串开头
|
||||
- 实际上就是丐版 `re.match`
|
||||
- 并且会在匹配上之后 如果匹配内容后面第一个字符是空格 则会截取掉空格
|
||||
- Now, it will first use `str.startswith` to detect whether it starts with the required string
|
||||
- Actually a poor version of `re.match`
|
||||
- And after matching, if the first character after the matching content is a space, the space will be intercepted
|
||||
|
||||
## DR sdk 0.8.3.0
|
||||
|
||||
### 删除
|
||||
|
@ -121,9 +121,11 @@ if TYPE_CHECKING:
|
||||
@property
|
||||
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]]]: ...
|
||||
|
||||
class Console_rs:
|
||||
def __init__(self) -> None: ...
|
||||
def start(self) -> None: ...
|
||||
def stop(self) -> bool: ...
|
||||
def get_command(self) -> Optional[str]: ...
|
||||
def new_command(self) -> bool: ...
|
||||
|
29
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
29
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
@ -84,14 +84,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.14"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"memoffset 0.9.0",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
@ -107,9 +107,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.15"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -167,9 +167,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.18"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
@ -190,6 +190,15 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.32.2"
|
||||
@ -348,7 +357,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"indoc",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"memoffset 0.8.0",
|
||||
"parking_lot",
|
||||
"pyo3-build-config",
|
||||
"pyo3-ffi",
|
||||
|
@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs'
|
||||
|
||||
setup(
|
||||
name='Difficult_Rocket_rs',
|
||||
version="0.2.10.1",
|
||||
version="0.2.11.0",
|
||||
author='shenjackyuanjie',
|
||||
author_email='3695888@qq.com',
|
||||
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
||||
|
@ -12,6 +12,7 @@ mod python;
|
||||
mod render;
|
||||
mod simulator;
|
||||
mod sr1_data;
|
||||
mod translate;
|
||||
mod types;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
@ -26,7 +27,7 @@ enum LoadState {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_version_str() -> String { "0.2.10.1".to_string() }
|
||||
fn get_version_str() -> String { "0.2.11.0".to_string() }
|
||||
|
||||
#[pyfunction]
|
||||
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
||||
@ -42,7 +43,6 @@ fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
||||
fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(get_version_str, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(test_call, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(simulator::simulation, 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::<render::camera::CameraRs>()?;
|
||||
|
@ -12,6 +12,7 @@
|
||||
/// 插件加载
|
||||
///
|
||||
|
||||
#[allow(unused)]
|
||||
pub mod plugin_trait {
|
||||
pub struct ModInfo {
|
||||
pub name: String,
|
||||
|
@ -12,6 +12,7 @@ pub mod data {
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::sr1_data::part_list::RawPartList;
|
||||
use crate::types::math::{Point2D, Rotatable};
|
||||
use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
|
||||
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
||||
|
||||
@ -142,96 +143,35 @@ pub mod data {
|
||||
}
|
||||
parts
|
||||
}
|
||||
|
||||
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();
|
||||
// rotate
|
||||
let radius = part_data.angle;
|
||||
let ((x1, y1), (x2, y2)) = part_type.get_box();
|
||||
let mut p1 = Point2D::new(x1, y1);
|
||||
let mut p2 = Point2D::new(x2, y2);
|
||||
p1.rotate_radius_mut(radius);
|
||||
p2.rotate_radius_mut(radius);
|
||||
// transform
|
||||
p1.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
p2.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
return Some(((p1.x, p1.y), (p2.x, p2.y)));
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod translate {
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::PyDict;
|
||||
|
||||
#[pyclass]
|
||||
#[pyo3(name = "TranslateConfig_rs")]
|
||||
#[pyo3(text_signature = "(language, raise_error = False, replace_normal = False, add_error = False, is_result = False, keep_get = False)")]
|
||||
pub struct PyTranslateConfig {
|
||||
pub raise_error: bool,
|
||||
pub replace_normal: bool,
|
||||
pub add_error: bool,
|
||||
pub is_result: bool,
|
||||
pub keep_get: bool,
|
||||
pub language: String,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyTranslateConfig {
|
||||
#[new]
|
||||
fn new(py_: Python, raise_error: bool, replace_normal: bool, language: Option<String>) -> Self {
|
||||
let dr_runtime = PyModule::import(py_, "Difficult_Rocket").unwrap().get_item("DR_runtime").unwrap();
|
||||
let default_language = dr_runtime.get_item("language").unwrap().extract::<String>().unwrap();
|
||||
Self {
|
||||
raise_error,
|
||||
replace_normal,
|
||||
add_error: false,
|
||||
is_result: false,
|
||||
keep_get: false,
|
||||
language: language.unwrap_or(default_language),
|
||||
}
|
||||
}
|
||||
|
||||
// fn set(&self, py_: Python, item: String, value: BoolString) -> &Self {
|
||||
// match item.as_str() {
|
||||
// "raise_error" => self,
|
||||
// _ => self,
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
pub struct PyTranslate {
|
||||
pub data: Py<PyAny>,
|
||||
pub get_list: Vec<(String, bool)>,
|
||||
pub config: PyTranslateConfig,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyTranslate {
|
||||
#[new]
|
||||
fn py_new(py_: Python, data: &PyAny) -> Self {
|
||||
let _ = data.is_instance_of::<PyDict>();
|
||||
Self {
|
||||
data: data.into_py(py_),
|
||||
get_list: Vec::new(),
|
||||
config: PyTranslateConfig::new(py_, false, false, None),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod physics {
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::simulator::interface::PhysicsSpace;
|
||||
|
||||
#[pyclass]
|
||||
#[pyo3(name = "PhysicsSpace_rs")]
|
||||
pub struct PyPhysicsSpace {
|
||||
pub space: PhysicsSpace,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyPhysicsSpace {
|
||||
#[new]
|
||||
fn new(gravity: (f64, f64)) -> Self {
|
||||
Self {
|
||||
space: PhysicsSpace::new(gravity),
|
||||
}
|
||||
}
|
||||
|
||||
fn tick_space(&mut self) { self.space.tick_space() }
|
||||
}
|
||||
use crate::translate;
|
||||
}
|
||||
|
||||
pub mod console {
|
||||
use pyo3::prelude::*;
|
||||
use std::io::{self, Write};
|
||||
|
||||
#[pyclass]
|
||||
#[pyo3(name = "Console_rs")]
|
||||
@ -255,7 +195,7 @@ pub mod console {
|
||||
let (stop_sender, stop_receiver) = std::sync::mpsc::channel();
|
||||
let (keyboard_input_sender, keyboard_input_receiver) = std::sync::mpsc::channel();
|
||||
std::thread::spawn(move || {
|
||||
let std_in = std::io::stdin();
|
||||
let std_in = io::stdin();
|
||||
loop {
|
||||
if let Ok(()) = stop_receiver.try_recv() {
|
||||
break;
|
||||
@ -265,9 +205,10 @@ pub mod console {
|
||||
if !input.is_empty() {
|
||||
keyboard_input_sender.send(input).unwrap();
|
||||
}
|
||||
print!(">>");
|
||||
}
|
||||
});
|
||||
print!("rs>");
|
||||
io::stdout().flush().unwrap();
|
||||
self.stop_sender = Some(stop_sender);
|
||||
self.keyboard_input_receiver = Some(keyboard_input_receiver);
|
||||
}
|
||||
@ -280,6 +221,12 @@ pub mod console {
|
||||
false
|
||||
}
|
||||
|
||||
fn new_command(&self) -> bool {
|
||||
print!("rs>");
|
||||
io::stdout().flush().unwrap();
|
||||
true
|
||||
}
|
||||
|
||||
fn get_command(&self) -> Option<String> {
|
||||
// 获取输入
|
||||
if let Some(receiver) = &self.keyboard_input_receiver {
|
||||
|
@ -9,6 +9,7 @@
|
||||
use pyo3::prelude::*;
|
||||
use rapier2d_f64::prelude::*;
|
||||
|
||||
#[allow(unused)]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "simulation")]
|
||||
pub fn simulation() -> () {
|
||||
@ -63,73 +64,8 @@ pub fn simulation() -> () {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod interface {
|
||||
#[allow(unused)]
|
||||
pub mod python {
|
||||
use pyo3::prelude::*;
|
||||
use rapier2d_f64::prelude::*;
|
||||
|
||||
pub struct PhysicsSpace {
|
||||
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: (),
|
||||
}
|
||||
|
||||
impl PhysicsSpace {
|
||||
pub fn new(gravity: (f64, f64)) -> Self {
|
||||
let rigid_body_set = RigidBodySet::new();
|
||||
let collider_set = ColliderSet::new();
|
||||
let gravity = vector![gravity.0, gravity.1];
|
||||
let integration_parameters = IntegrationParameters::default();
|
||||
let physics_pipeline = PhysicsPipeline::new();
|
||||
let island_manager = IslandManager::new();
|
||||
let broad_phase = BroadPhase::new();
|
||||
let narrow_phase = NarrowPhase::new();
|
||||
let impulse_joint_set = ImpulseJointSet::new();
|
||||
let multibody_joint_set = MultibodyJointSet::new();
|
||||
let ccd_solver = CCDSolver::new();
|
||||
let physics_hooks = ();
|
||||
let event_handler = ();
|
||||
Self {
|
||||
rigid_body_set,
|
||||
collider_set,
|
||||
gravity,
|
||||
integration_parameters,
|
||||
physics_pipeline,
|
||||
island_manager,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
impulse_joint_set,
|
||||
multibody_joint_set,
|
||||
ccd_solver,
|
||||
physics_hooks,
|
||||
event_handler,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick_space(&mut self) {
|
||||
self.physics_pipeline.step(
|
||||
&self.gravity,
|
||||
&self.integration_parameters,
|
||||
&mut self.island_manager,
|
||||
&mut self.broad_phase,
|
||||
&mut self.narrow_phase,
|
||||
&mut self.rigid_body_set,
|
||||
&mut self.collider_set,
|
||||
&mut self.impulse_joint_set,
|
||||
&mut self.multibody_joint_set,
|
||||
&mut self.ccd_solver,
|
||||
None,
|
||||
&self.physics_hooks,
|
||||
&self.event_handler,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
Normal file
16
mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* -------------------------------
|
||||
* 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,
|
||||
}
|
@ -197,9 +197,13 @@ pub mod sr1 {
|
||||
}
|
||||
|
||||
impl SR1PartType {
|
||||
pub fn get_box(&self) -> (f64, f64, f64, f64) {
|
||||
let x = self.width as f64 / 2.0;
|
||||
(-x, 0.0, x, self.height as f64)
|
||||
pub fn get_box(&self) -> ((f64, f64), (f64, f64)) {
|
||||
// -x, -y, x, y
|
||||
// 居中
|
||||
(
|
||||
(-(self.width as f64 / 2.0), -(self.height as f64 / 2.0)),
|
||||
(self.width as f64 / 2.0, self.height as f64 / 2.0),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -777,14 +781,14 @@ pub mod sr1 {
|
||||
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 (x1, y1, x2, y2) = part_type.get_box();
|
||||
let ((x1, y1), (x2, y2)) = part_type.get_box();
|
||||
// rotate
|
||||
let mut p1 = Point2D::new(x1, y1);
|
||||
let mut p2 = Point2D::new(x2, y2);
|
||||
p1.rotate_radius_mut(part.angle);
|
||||
p2.rotate_radius_mut(part.angle);
|
||||
let p1 = p1.add(part.x, part.y);
|
||||
let p2 = p2.add(part.x, part.y);
|
||||
let p1 = p1.add(part.x * 2.0, part.y * 2.0);
|
||||
let p2 = p2.add(part.x * 2.0, part.y * 2.0);
|
||||
let (x1, y1, x2, y2) = (p1.x, p1.y, p2.x, p2.y);
|
||||
// get max box
|
||||
max_box.0 = max_box.0.min(x1).min(part.x);
|
||||
@ -835,6 +839,12 @@ pub mod math {
|
||||
|
||||
#[inline]
|
||||
pub fn add(&self, x: f64, y: f64) -> Self { Point2D::new(self.x + x, self.y + y) }
|
||||
|
||||
#[inline]
|
||||
pub fn add_mut(&mut self, x: f64, y: f64) -> () {
|
||||
self.x += x;
|
||||
self.y += y;
|
||||
}
|
||||
}
|
||||
|
||||
impl Rotatable for Point2D {
|
||||
|
@ -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.10.1") # DR_mod 的 Rust 编写部分的兼容版本
|
||||
DR_rust_version = Version("0.2.11.0") # DR_mod 的 Rust 编写部分的兼容版本
|
||||
|
||||
logger = logging.getLogger('client.dr_game')
|
||||
|
||||
|
@ -22,3 +22,6 @@ class RustConsole(Console):
|
||||
|
||||
def get_command(self) -> str:
|
||||
return self.console.get_command()
|
||||
|
||||
def new_command(self) -> None:
|
||||
self.console.new_command()
|
||||
|
12
mods/dr_game/lang/en-us.toml
Normal file
12
mods/dr_game/lang/en-us.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[mod.info]
|
||||
setup.start = "SR1 Renderer start loading"
|
||||
setup.use_time = "SR1 Renderer loading has used: {} second"
|
||||
|
||||
[sr1.ship]
|
||||
xml.loading = "Loading XML file: {}"
|
||||
xml.load_done = "XML file loaded"
|
||||
xml.load_time = "XML file loading has used: {} second"
|
||||
ship.load = "Loading ship: {}"
|
||||
ship.load_time = "Ship loading has used: {} second"
|
||||
ship.info = "Ship info:\n- Parts: {}\n- Weight: {}"
|
||||
ship.render.done = "Ship render done"
|
13
mods/dr_game/lang/zh-CN.toml
Normal file
13
mods/dr_game/lang/zh-CN.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[mod.info]
|
||||
setup.start = "SR1 渲染器开始载入"
|
||||
setup.use_time = "SR1 渲染器载入消耗时间: {} 秒"
|
||||
|
||||
[sr1.ship]
|
||||
xml.loading = "正在加载XML文件: {}"
|
||||
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 = "飞船渲染完成"
|
@ -9,26 +9,24 @@ import time
|
||||
import random
|
||||
import logging
|
||||
import traceback
|
||||
# from xml.etree import ElementTree
|
||||
|
||||
from pathlib import Path
|
||||
from xml.etree.ElementTree import Element
|
||||
from typing import List, TYPE_CHECKING, Union, Dict, Optional, Generator
|
||||
|
||||
# third party package
|
||||
from defusedxml.ElementTree import parse
|
||||
|
||||
# pyglet
|
||||
from pyglet.math import Vec4
|
||||
from pyglet.text import Label
|
||||
from pyglet.shapes import Line, Rectangle
|
||||
from pyglet.sprite import Sprite
|
||||
# from pyglet.image import Texture
|
||||
from pyglet.graphics import Batch, Group
|
||||
from pyglet.shapes import Line, Rectangle
|
||||
|
||||
from . import DR_mod_runtime
|
||||
|
||||
# Difficult Rocket
|
||||
from Difficult_Rocket import DR_status
|
||||
from Difficult_Rocket.utils.translate import tr
|
||||
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
|
||||
@ -41,6 +39,7 @@ if DR_mod_runtime.use_DR_rust:
|
||||
from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, SR1Ship_rs
|
||||
|
||||
logger = logging.getLogger('client.dr_game_sr1_ship')
|
||||
sr_tr = Tr(lang_path=Path('./mods/dr_game/lang'))
|
||||
|
||||
|
||||
def get_sr1_part(part_xml: Element) -> Optional[SR1PartData]:
|
||||
@ -88,7 +87,7 @@ class SR1ShipRender(BaseScreen):
|
||||
def __init__(self,
|
||||
main_window: "ClientWindow"):
|
||||
super().__init__(main_window)
|
||||
logger.info(tr().client.sr1_render.setup.start())
|
||||
logger.info(sr_tr().mod.info.setup.start())
|
||||
load_start_time = time.time_ns()
|
||||
self.rendered = False
|
||||
self.focus = True
|
||||
@ -124,15 +123,16 @@ class SR1ShipRender(BaseScreen):
|
||||
self.part_box_batch = Batch()
|
||||
self.part_batch = Batch()
|
||||
self.part_group = Group()
|
||||
self.debug_label = Label(x=20, y=main_window.height - 20, font_size=DR_status.std_font_size,
|
||||
self.debug_label = Label(x=20, y=main_window.height - 100, font_size=DR_status.std_font_size,
|
||||
text='SR1 render!', font_name=Fonts.微软等宽无线,
|
||||
width=main_window.width - 20, height=20,
|
||||
anchor_x='left', anchor_y='top')
|
||||
self.part_data: Dict[int, SR1PartData] = {}
|
||||
self.parts_sprite: Dict[int, Sprite] = {}
|
||||
self.part_box_dict: Dict[int, Rectangle] = {}
|
||||
self.part_line_box: Dict[int, List[Line]] = {}
|
||||
load_end_time = time.time_ns()
|
||||
logger.info(tr().client.sr1_render.setup.use_time().format(
|
||||
logger.info(sr_tr().mod.info.setup.use_time().format(
|
||||
(load_end_time - load_start_time) / 1000000000))
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
self.camera_rs = CenterCamera_rs(main_window,
|
||||
@ -143,7 +143,7 @@ class SR1ShipRender(BaseScreen):
|
||||
def load_xml(self, file_path: str) -> bool:
|
||||
try:
|
||||
start_time = time.time_ns()
|
||||
logger.info(tr().client.sr1_render.xml.loading().format(file_path))
|
||||
logger.info(sr_tr().sr1.ship.xml.loading().format(file_path))
|
||||
cache_doc = parse(file_path)
|
||||
self.xml_doc = cache_doc
|
||||
self.xml_root = self.xml_doc.getroot()
|
||||
@ -155,8 +155,8 @@ class SR1ShipRender(BaseScreen):
|
||||
print(self.rust_ship.img_pos)
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
logger.info(tr().client.sr1_render.xml.load_done())
|
||||
logger.info(tr().client.sr1_render.xml.load_time().format(
|
||||
logger.info(sr_tr().sr1.ship.xml.load_done())
|
||||
logger.info(sr_tr().sr1.ship.xml.load_time().format(
|
||||
(time.time_ns() - start_time) / 1000000000))
|
||||
return True
|
||||
except Exception as e:
|
||||
@ -191,19 +191,26 @@ class SR1ShipRender(BaseScreen):
|
||||
cache_sprite.y = cache_sprite.y - cache_sprite.scale_y / 2
|
||||
self.parts_sprite[part.id] = cache_sprite
|
||||
|
||||
part_width = 100
|
||||
part_height = 100
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
part_type = self.part_list_rs.get_part_type(part.p_type)
|
||||
if part_type is not None:
|
||||
part_width = part_type.width * 15
|
||||
part_height = part_type.height * 15
|
||||
part_box = Rectangle(x=render_x, y=render_y,
|
||||
width=part_width, height=part_height,
|
||||
batch=self.part_box_batch, group=self.part_group)
|
||||
part_box.rotation = SR1Rotation.get_rotation(part.angle)
|
||||
part_box.opacity = 50
|
||||
self.part_box_dict[part.id] = part_box
|
||||
part_debug_box = self.rust_ship.get_part_box(part.id)
|
||||
if part_debug_box:
|
||||
# 线框
|
||||
part_line_box = []
|
||||
width = 4
|
||||
color = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255), random.randrange(100, 200))
|
||||
part_line_box.append(Line(x=part_debug_box[0][0] * 30, y=part_debug_box[0][1] * 30,
|
||||
x2=part_debug_box[0][0] * 30, y2=part_debug_box[1][1] * 30,
|
||||
batch=self.part_box_batch, width=width, color=color))
|
||||
part_line_box.append(Line(x=part_debug_box[0][0] * 30, y=part_debug_box[1][1] * 30,
|
||||
x2=part_debug_box[1][0] * 30, y2=part_debug_box[1][1] * 30,
|
||||
batch=self.part_box_batch, width=width, color=color))
|
||||
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[1][1] * 30,
|
||||
x2=part_debug_box[1][0] * 30, y2=part_debug_box[0][1] * 30,
|
||||
batch=self.part_box_batch, width=width, color=color))
|
||||
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[0][1] * 30,
|
||||
x2=part_debug_box[0][0] * 30, y2=part_debug_box[0][1] * 30,
|
||||
batch=self.part_box_batch, width=width, color=color))
|
||||
self.part_line_box[part.id] = part_line_box
|
||||
# if not part_render: # 如果不渲染(渲染有毛病)
|
||||
# self.parts_sprite[part.id].visible = False
|
||||
count += 1
|
||||
@ -216,10 +223,11 @@ class SR1ShipRender(BaseScreen):
|
||||
def render_ship(self):
|
||||
if self.textures is None:
|
||||
self.load_textures()
|
||||
logger.info(tr().client.sr1_render.ship.load().format(self.xml_name))
|
||||
logger.info(sr_tr().sr1.ship.ship.load().format(self.xml_name))
|
||||
start_time = time.perf_counter_ns()
|
||||
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
|
||||
@ -243,10 +251,10 @@ class SR1ShipRender(BaseScreen):
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
for part in self.part_data:
|
||||
full_mass += self.part_list_rs.get_part_type(self.part_data[part].p_type).mass * 500
|
||||
logger.info(tr().client.sr1_render.ship.load_time().format(
|
||||
logger.info(sr_tr().sr1.ship.ship.load_time().format(
|
||||
(time.perf_counter_ns() - start_time) / 1000000000))
|
||||
logger.info(tr().client.sr1_render.ship.info().format(
|
||||
len(self.part_data), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else tr().game.require_DR_rs()))
|
||||
logger.info(sr_tr().sr1.ship.ship.info().format(
|
||||
len(self.part_data), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
||||
self.rendered = True
|
||||
|
||||
def update_parts(self) -> bool:
|
||||
@ -269,7 +277,7 @@ class SR1ShipRender(BaseScreen):
|
||||
next(self.gen_draw)
|
||||
except GeneratorExit:
|
||||
self.drawing = False
|
||||
logger.info(tr().client.sr1_render.ship.render.done())
|
||||
logger.info(sr_tr().sr1.ship.ship.render.done())
|
||||
|
||||
if self.need_update_parts:
|
||||
self.update_parts()
|
||||
@ -292,6 +300,7 @@ class SR1ShipRender(BaseScreen):
|
||||
self.debug_mouse_delta_line.draw()
|
||||
|
||||
def on_resize(self, width: int, height: int, window: "ClientWindow"):
|
||||
self.debug_label.y = height - 100
|
||||
if not self.rendered:
|
||||
return
|
||||
self.debug_line.x = width / 2
|
||||
@ -348,22 +357,26 @@ class SR1ShipRender(BaseScreen):
|
||||
self.need_draw = True
|
||||
print('应该渲染飞船的')
|
||||
elif command.find('debug'):
|
||||
print('sr ?')
|
||||
if command.find('delta'):
|
||||
SR1ShipRender_Option.debug_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
||||
self.debug_line.visible = SR1ShipRender_Option.debug_d_pos
|
||||
self.debug_d_pos_label.visible = SR1ShipRender_Option.debug_d_pos
|
||||
# print('sr1 delta')
|
||||
# SR1ShipRender_Option.debug_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
||||
self.debug_line.visible = not self.debug_line.visible
|
||||
self.debug_d_pos_label.visible = not self.debug_d_pos_label.visible
|
||||
SR1ShipRender_Option.debug_d_pos = self.debug_line.visible
|
||||
logger.debug('sr1 delta')
|
||||
elif command.find('mouse'):
|
||||
if command.find('delta'):
|
||||
SR1ShipRender_Option.debug_mouse_pos = not SR1ShipRender_Option.debug_mouse_pos
|
||||
self.debug_mouse_line.visible = SR1ShipRender_Option.debug_mouse_pos
|
||||
self.debug_mouse_label.visible = SR1ShipRender_Option.debug_mouse_pos
|
||||
# print('sr1 mouse delta')
|
||||
logger.debug(f'sr1 mouse delta {SR1ShipRender_Option.debug_mouse_pos}')
|
||||
else:
|
||||
SR1ShipRender_Option.debug_mouse_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
||||
self.debug_mouse_delta_line.visible = SR1ShipRender_Option.debug_mouse_d_pos
|
||||
# print('sr1 mouse')
|
||||
self.debug_mouse_delta_line.visible = not self.debug_mouse_delta_line.visible
|
||||
SR1ShipRender_Option.debug_mouse_d_pos = self.debug_mouse_delta_line.visible
|
||||
logger.debug(f'sr1 mouse {SR1ShipRender_Option.debug_mouse_d_pos}')
|
||||
elif command.find('ship'):
|
||||
if self.rendered:
|
||||
for index, sprite in self.parts_sprite.items():
|
||||
sprite.visible = not sprite.visible
|
||||
|
||||
elif command.find('get_buf'):
|
||||
|
||||
@ -390,7 +403,6 @@ class SR1ShipRender(BaseScreen):
|
||||
return
|
||||
img_box = self.rust_ship.img_pos
|
||||
img_size = (img_box[2] - img_box[0] + 1000, img_box[3] - img_box[1] + 1000)
|
||||
# img_center = (abs(img_box[0]), abs(img_box[1]))
|
||||
# 中心点是左上角坐标
|
||||
img_center = (abs(img_box[0]), abs(img_box[3]))
|
||||
print(f"img_box: {img_box} img_size: {img_size} img_center: {img_center}")
|
||||
@ -400,23 +412,6 @@ class SR1ShipRender(BaseScreen):
|
||||
traceback.print_exc()
|
||||
print('PIL not found')
|
||||
return
|
||||
min_x = 0
|
||||
min_y = 0
|
||||
max_x = 0
|
||||
max_y = 0
|
||||
for part, sprite in self.parts_sprite.items():
|
||||
sprite_img = sprite.image
|
||||
print(f"sprite_img: {sprite_img} {sprite_img.width} {sprite_img.height}")
|
||||
# 碰撞箱是居中的
|
||||
# -x, -y, +x, +y
|
||||
part_data = self.part_data[part]
|
||||
bound_box = [-sprite_img.width / 2 + part_data.x, -sprite_img.height / 2 + part_data.y,
|
||||
sprite_img.width / 2 + part_data.x, sprite_img.height / 2 + part_data.y]
|
||||
min_x = min(min_x, bound_box[0])
|
||||
min_y = min(min_y, bound_box[1])
|
||||
max_x = max(max_x, bound_box[2])
|
||||
max_y = max(max_y, bound_box[3])
|
||||
print(f"min_x: {min_x} min_y: {min_y} max_x: {max_x} max_y: {max_y}")
|
||||
img = Image.new('RGBA', img_size)
|
||||
for part, sprite in self.parts_sprite.items():
|
||||
sprite_img = sprite.image
|
||||
|
Loading…
Reference in New Issue
Block a user