Merge branch 'origin/Rackaging' into hu_migrate_geng_new

This commit is contained in:
Hector 2026-04-07 10:09:28 +08:00
commit 9f1ce6812f
9 changed files with 249 additions and 9 deletions

BIN
Assets/Models/box1.glb Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
{
"guid": "2c994aea36c94385a8f9a5274c406a67",
"asset_type": "model",
"source_hash": "fc694905c47a9b0005d77b701cc41852b56ef08c7406829a306e98f3ce158a64",
"importer": "model_importer",
"import_settings": {},
"dependency_guids": []
}

View File

@ -367,6 +367,20 @@ class SelectionSystem:
if not self.enable_unity_outline:
self.outline_manager.clear()
return
if nodePath and not nodePath.isEmpty():
has_geom = False
try:
has_geom = nodePath.find_all_matches("**/+GeomNode").get_num_paths() > 0
except Exception:
try:
has_geom = nodePath.findAllMatches("**/+GeomNode").getNumPaths() > 0
except Exception:
has_geom = False
if not has_geom:
self.outline_manager.clear()
return
if nodePath and not nodePath.isEmpty():
self.outline_manager.set_targets([nodePath])
else:
@ -2742,4 +2756,3 @@ class SelectionSystem:
print("已清除选择")
except Exception as e:
print(f"清除选择失败: {e}")

View File

@ -0,0 +1,75 @@
# EG `.deb` 打包
这套脚本的目标不是重新编译项目,而是把已经生成好的 PyInstaller 发行目录再封装成 Debian 安装包。
默认输入目录是:
```text
dist/EGEditor
```
默认输出目录是:
```text
dist-deb
```
## 最常用流程
1. 先生成 PyInstaller 发行目录:
```bash
python -m PyInstaller --clean packaging/eg_editor.spec
```
2. 再生成 `.deb`
```bash
bash packaging/debian/build_deb.sh 0.1.0
```
生成结果类似:
```text
dist-deb/eg-editor_0.1.0_amd64.deb
```
## 安装与卸载
安装:
```bash
sudo apt install ./dist-deb/eg-editor_0.1.0_amd64.deb
```
卸载:
```bash
sudo apt remove eg-editor
```
## 安装后路径
- 程序主体:`/opt/eg-editor`
- 命令行启动:`/usr/bin/eg-editor`
- 桌面启动器:`/usr/share/applications/eg-editor.desktop`
- 图标:`/usr/share/pixmaps/eg-editor.png`
## 可选环境变量
- `APP_DIR`:指定要封装的 PyInstaller 目录
- `PACKAGE_NAME`Debian 包名,默认 `eg-editor`
- `DISPLAY_NAME`:桌面显示名称
- `ARCH`:包架构,默认自动读取 `dpkg-architecture`
- `MAINTAINER`:维护者字段
- `OUTPUT_DIR``.deb` 输出目录
- `ICON_SOURCE`:图标文件路径
示例:
```bash
APP_DIR=/path/to/dist/EGEditor \
DISPLAY_NAME="EG Editor" \
MAINTAINER="hello <hello@example.com>" \
bash packaging/debian/build_deb.sh 0.1.0
```

78
packaging/debian/build_deb.sh Executable file
View File

@ -0,0 +1,78 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
APP_DIR="${APP_DIR:-$ROOT_DIR/dist/EGEditor}"
PACKAGE_NAME="${PACKAGE_NAME:-eg-editor}"
DISPLAY_NAME="${DISPLAY_NAME:-EG Editor}"
VERSION="${1:-${VERSION:-0.1.0}}"
ARCH="${ARCH:-$(dpkg-architecture -qDEB_HOST_ARCH 2>/dev/null || echo amd64)}"
MAINTAINER="${MAINTAINER:-EG Team <noreply@example.com>}"
DESCRIPTION="${DESCRIPTION:-EG 3D editor and engine packaged from the PyInstaller distribution directory.}"
INSTALL_DIR="/opt/${PACKAGE_NAME}"
STAGE_BASE="$ROOT_DIR/build/deb/${PACKAGE_NAME}_${VERSION}_${ARCH}"
PKG_ROOT="$STAGE_BASE/${PACKAGE_NAME}"
OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/dist-deb}"
OUTPUT_FILE="$OUTPUT_DIR/${PACKAGE_NAME}_${VERSION}_${ARCH}.deb"
ICON_SOURCE="${ICON_SOURCE:-$ROOT_DIR/icons/logo.png}"
if [[ ! -x "$APP_DIR/EGEditor" ]]; then
echo "error: executable not found: $APP_DIR/EGEditor" >&2
echo "hint: build the PyInstaller bundle first, or set APP_DIR=/path/to/EGEditor" >&2
exit 1
fi
if [[ ! -f "$ICON_SOURCE" ]]; then
echo "error: icon not found: $ICON_SOURCE" >&2
exit 1
fi
rm -rf "$STAGE_BASE"
mkdir -p \
"$PKG_ROOT/DEBIAN" \
"$PKG_ROOT$INSTALL_DIR" \
"$PKG_ROOT/usr/bin" \
"$PKG_ROOT/usr/share/applications" \
"$PKG_ROOT/usr/share/pixmaps" \
"$OUTPUT_DIR"
cp -a "$APP_DIR/." "$PKG_ROOT$INSTALL_DIR/"
cp "$ICON_SOURCE" "$PKG_ROOT/usr/share/pixmaps/${PACKAGE_NAME}.png"
cat > "$PKG_ROOT/usr/bin/${PACKAGE_NAME}" <<EOF
#!/usr/bin/env bash
exec "${INSTALL_DIR}/EGEditor" "\$@"
EOF
chmod 0755 "$PKG_ROOT/usr/bin/${PACKAGE_NAME}"
cat > "$PKG_ROOT/usr/share/applications/${PACKAGE_NAME}.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=${DISPLAY_NAME}
Comment=Launch ${DISPLAY_NAME}
Exec=${PACKAGE_NAME}
Icon=${PACKAGE_NAME}
Terminal=false
Categories=Graphics;Development;
StartupNotify=true
EOF
chmod 0644 "$PKG_ROOT/usr/share/applications/${PACKAGE_NAME}.desktop"
cat > "$PKG_ROOT/DEBIAN/control" <<EOF
Package: ${PACKAGE_NAME}
Version: ${VERSION}
Section: graphics
Priority: optional
Architecture: ${ARCH}
Maintainer: ${MAINTAINER}
Depends: libc6 (>= 2.35), libgl1
Description: ${DISPLAY_NAME}
${DESCRIPTION}
EOF
chmod 0644 "$PKG_ROOT/DEBIAN/control"
dpkg-deb --build --root-owner-group "$PKG_ROOT" "$OUTPUT_FILE"
echo "built: $OUTPUT_FILE"

View File

@ -1880,7 +1880,15 @@ class ProjectManager:
except Exception:
imported_np = None
if imported_np and not imported_np.isEmpty():
self._apply_scene_description_state_to_node(imported_np, node, project_path)
# Animated/Actor imports still need the saved child-node
# overrides (transform/material/visibility), not just
# the model root state.
self._apply_scene_description_state_to_subtree(
imported_np,
node,
project_path,
node_lookup,
)
loaded_any = True
continue

View File

@ -571,7 +571,14 @@ class EditorPanelsRightMixin(
"""绘制光源属性"""
imgui.text("光源属性")
color = self.app._get_light_color(node)
color = self.app._get_light_color(node) or (1.0, 1.0, 1.0, 1.0)
if len(color) < 4:
color = (
float(color[0]) if len(color) > 0 else 1.0,
float(color[1]) if len(color) > 1 else 1.0,
float(color[2]) if len(color) > 2 else 1.0,
1.0,
)
changed, new_color = imgui.color_edit3(
"颜色##light_color",
(color[0], color[1], color[2]),
@ -917,4 +924,3 @@ class EditorPanelsRightMixin(
if self.app.style_manager.draw_toolbar_button("删除", size=(64, 28), tooltip="删除当前对象"):
if hasattr(self, 'selection') and self.selection:
self.selection.deleteSelectedNode()

View File

@ -153,14 +153,40 @@ class PanelDelegates:
# 检查是否为GUI元素
if hasattr(node, 'getPythonTag') and node.getPythonTag('gui_element'):
return "GUI元素"
# 检查是否为光源
try:
if node.hasTag("tree_item_type"):
tree_item_type = str(node.getTag("tree_item_type") or "").strip().upper()
if tree_item_type == "CAMERA_NODE":
return "相机"
if tree_item_type in {"LIGHT_NODE", "SPOT_LIGHT_NODE", "POINT_LIGHT_NODE"}:
return "光源"
if node.hasTag("light_type"):
return "光源"
except Exception:
pass
try:
panda_node = node.node() if hasattr(node, "node") else None
if panda_node is not None and hasattr(panda_node, "getClassType"):
class_name = panda_node.getClassType().getName() or ""
class_name_lower = class_name.lower()
if "camera" in class_name_lower:
return "相机"
if "light" in class_name_lower:
return "光源"
except Exception:
pass
node_name = node.getName() or ""
if "light" in node_name.lower() or "Light" in node_name:
node_name_lower = node_name.lower()
# 检查是否为光源
if "light" in node_name_lower:
return "光源"
# 检查是否为相机
if "camera" in node_name.lower() or "Camera" in node_name:
if "camera" in node_name_lower:
return "相机"
# 检查是否为模型

View File

@ -769,6 +769,22 @@ class PropertyHelpers:
float(color[3]) if len(color) > 3 else 1.0,
)
panda_node = node.node() if hasattr(node, "node") else None
if panda_node is not None:
try:
get_color = getattr(panda_node, "getColor", None) or getattr(panda_node, "get_color", None)
if callable(get_color):
light_color = get_color()
if light_color is not None and len(light_color) >= 3:
return (
float(light_color[0]),
float(light_color[1]),
float(light_color[2]),
float(light_color[3]) if len(light_color) > 3 else 1.0,
)
except Exception:
pass
rp_light = node.getPythonTag("rp_light_object")
if rp_light is not None:
try:
@ -784,6 +800,7 @@ class PropertyHelpers:
pass
except Exception:
return (1.0, 1.0, 1.0, 1.0)
return (1.0, 1.0, 1.0, 1.0)
def _apply_light_color(self, node, color):
"""Apply light color to both editor node and RP light object."""
@ -799,6 +816,15 @@ class PropertyHelpers:
except Exception:
pass
try:
panda_node = node.node() if hasattr(node, "node") else None
if panda_node is not None:
set_color = getattr(panda_node, "setColor", None) or getattr(panda_node, "set_color", None)
if callable(set_color):
set_color(*rgba)
except Exception:
pass
try:
rp_light = node.getPythonTag("rp_light_object")
if rp_light is not None: