chore: make_resources.py 脚本加入对 PyCharm 的支持

This commit is contained in:
XcantloadX 2025-04-09 14:52:19 +08:00
parent 96769344ec
commit 9c6e980adf
2 changed files with 87 additions and 10 deletions

47
tools/image_server.py Normal file
View File

@ -0,0 +1,47 @@
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
import cv2
import numpy as np
from pathlib import Path
app = FastAPI()
def cv2_imread(path: str, flags=cv2.IMREAD_COLOR):
"""读取图片,支持中文路径"""
return cv2.imdecode(np.fromfile(path, dtype=np.uint8), flags)
@app.get("/image")
async def get_image(path: str):
"""返回指定路径的图片
Args:
path: 图片的文件路径
Returns:
图片数据
"""
try:
# 检查文件是否存在
if not Path(path).exists():
raise HTTPException(status_code=404, detail="Image not found")
# 读取图片
img = cv2_imread(path)
if img is None:
raise HTTPException(status_code=400, detail="Invalid image format")
# 编码为PNG并返回
_, img_encoded = cv2.imencode('.png', img)
return Response(content=img_encoded.tobytes(), media_type="image/png")
except Exception as e:
if isinstance(e, HTTPException):
raise e
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=6532)

View File

@ -148,7 +148,28 @@ def escape(s: str) -> str:
return s.replace('\\', '\\\\')
def unify_path(path: str) -> str:
return path.replace('/', '\\')
return path.replace('\\', '/')
def ide_type() -> Literal['vscode', 'pycharm'] | None:
"""通过递归枚举父进程判断当前IDE类型"""
import psutil
me = psutil.Process()
while True:
parent = me.parent()
if parent is None:
break
name = parent.name().lower()
if 'code.exe' in name:
return 'vscode'
elif 'cursor.exe' in name:
return 'vscode'
elif 'windsurf.exe' in name:
return 'vscode'
elif 'pycharm' in name:
return 'pycharm'
me = parent
return None
def scan_png_files(path: str) -> list[str]:
"""扫描所有 PNG 文件"""
@ -269,11 +290,19 @@ def load_sprites(root_path: str, png_files: list[str]) -> list[Resource]:
print(f'Loaded basic sprite: {file}')
return resources
def make_classes(resources: list[Resource], output_path: str) -> list[OutputClass]:
def make_img(ide: Literal['vscode', 'pycharm'], path: str, title: str, height: str = ''):
if ide == 'vscode':
return f'<img src="vscode-file://vscode-app/{escape(path)}" title="{title}" height="{height}" />\n'
elif ide == 'pycharm':
return f'.. image:: http://localhost:6532/image?path={unify_path(path)}\n'
else:
raise ValueError(f'Unknown IDE: {ide}')
def make_classes(resources: list[Resource], ide: Literal['vscode', 'pycharm']) -> list[OutputClass]:
"""根据 Sprite 数据生成 R.py 中的类信息。"""
# 按照 class_path 对 sprites 进行分组
class_map: dict[str, OutputClass] = {}
# 创建或获取指定路径的类
def get_or_create_class(path: list[str]) -> Union[OutputClass, None]:
if not path:
@ -326,14 +355,14 @@ def make_classes(resources: list[Resource], output_path: str) -> list[OutputClas
docstring = (
f"名称:{sprite.display_name}\\n\n"
f"描述:{resource.description}\\n\n"
f"路径:{escape(sprite.rel_path)}\\n\n"
f"路径:{unify_path(sprite.rel_path)}\\n\n"
f"模块:`{'.'.join(sprite.class_path)}`\\n\n"
f'<img src="vscode-file://vscode-app/{escape(sprite.abs_path)}" title="{sprite.display_name}" />\\n\n'
+ make_img(ide, sprite.abs_path, sprite.display_name)
)
if sprite.type == 'metadata':
docstring += (
f"原始文件:\\n\n"
f"<img src='vscode-file://vscode-app/{escape(sprite.origin_file)}' title='原始文件' height='{height}' />"
+ make_img(ide, sprite.origin_file, '原始文件', height)
)
img_attr = ImageAttribute(
type='image',
@ -361,9 +390,9 @@ def make_classes(resources: list[Resource], output_path: str) -> list[OutputClas
f"模块:`{'.'.join(hint_box.class_path)}`\\n\n"
f"x1={hint_box.x1}, y1={hint_box.y1}, x2={hint_box.x2}, y2={hint_box.y2}\\n\n"
f"裁剪区域:\\n\n"
f"<img src='vscode-file://vscode-app/{escape(clip_abs_path)}' title='裁剪区域' />\\n\n"
f"原始图片:\\n\n"
f"<img src='vscode-file://vscode-app/{escape(hint_box.origin_file)}' title='原始文件' width='80%' />"
+ make_img(ide, clip_abs_path, '裁剪区域')
+ f"原始图片:\\n\n"
+ make_img(ide, hint_box.origin_file, '原始文件', '80%')
)
img_attr = ImageAttribute(
type='image',
@ -425,6 +454,7 @@ if __name__ == '__main__':
# 添加命令行参数解析
parser = argparse.ArgumentParser(description='生成图片资源文件')
parser.add_argument('-p', '--production', action='store_true', help='生产模式:不输出注释')
parser.add_argument('-i', '--ide', help='IDE 类型', default=ide_type())
args = parser.parse_args()
if os.path.exists(r'kotonebot\tasks\sprites'):
@ -433,7 +463,7 @@ if __name__ == '__main__':
files = scan_png_files(path)
sprites = load_sprites(path, files)
sprites = copy_sprites(sprites, r'kotonebot\tasks\sprites')
classes = make_classes(sprites, r'kotonebot\tasks\sprites')
classes = make_classes(sprites, args.ide)
env = jinja2.Environment(loader=jinja2.FileSystemLoader('./tools'))
env.filters['indent'] = indent