Merge branch 'origin/Rackaging' into hu_migrate_geng_new
This commit is contained in:
commit
9f1ce6812f
BIN
Assets/Models/box1.glb
Normal file
BIN
Assets/Models/box1.glb
Normal file
Binary file not shown.
8
Assets/Models/box1.glb.meta
Normal file
8
Assets/Models/box1.glb.meta
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"guid": "2c994aea36c94385a8f9a5274c406a67",
|
||||
"asset_type": "model",
|
||||
"source_hash": "fc694905c47a9b0005d77b701cc41852b56ef08c7406829a306e98f3ce158a64",
|
||||
"importer": "model_importer",
|
||||
"import_settings": {},
|
||||
"dependency_guids": []
|
||||
}
|
||||
@ -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}")
|
||||
|
||||
|
||||
75
packaging/debian/README.md
Normal file
75
packaging/debian/README.md
Normal 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
78
packaging/debian/build_deb.sh
Executable 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"
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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 "相机"
|
||||
|
||||
# 检查是否为模型
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user