EG/ui/LUI/lui_shared.py
2026-04-29 14:03:56 +08:00

185 lines
5.9 KiB
Python

"""Shared LUI bootstrap and imports."""
import importlib
import importlib.machinery
import importlib.util
import os
import sys
from pathlib import Path
import panda3d.core as p3d
from panda3d.core import NodePath, CardMaker
from imgui_bundle import imgui, imgui_ctx
UI_DIR = Path(__file__).resolve().parents[1]
if str(UI_DIR) not in sys.path:
sys.path.insert(0, str(UI_DIR))
BUILTIN_DIR = UI_DIR / "Builtin"
if str(BUILTIN_DIR) not in sys.path:
sys.path.insert(0, str(BUILTIN_DIR))
import panda3d
panda_dir = os.path.dirname(panda3d.__file__)
if hasattr(os, "add_dll_directory"):
try:
os.add_dll_directory(panda_dir)
os.add_dll_directory(str(UI_DIR))
except Exception as e:
print(f"Warning: Failed to add DLL directory: {e}")
LUI_IMPORT_DETAILS = ""
LUI_MODULE_SOURCE = ""
def _format_import_failure(prefix, error):
error_name = type(error).__name__
return f"{prefix}: {error_name}: {error}"
def _iter_local_lui_binaries():
seen = set()
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
candidate = UI_DIR / f"lui{suffix}"
if candidate.exists():
resolved = candidate.resolve()
if resolved not in seen:
seen.add(resolved)
yield resolved
if os.name == "nt":
patterns = ("lui*.pyd", "lui*.dll")
elif sys.platform == "darwin":
patterns = ("lui*.so", "lui*.dylib")
else:
patterns = ("lui*.so",)
for pattern in patterns:
for candidate in sorted(UI_DIR.glob(pattern)):
resolved = candidate.resolve()
if resolved not in seen:
seen.add(resolved)
yield resolved
def _load_lui_from_binary(binary_path):
spec = importlib.util.spec_from_file_location("lui", str(binary_path))
if spec is None or spec.loader is None:
raise ImportError(f"无法从二进制创建模块规范: {binary_path}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _bootstrap_lui_module():
failures = []
cached = sys.modules.get("lui") or sys.modules.get("panda3d.lui")
if cached is not None:
return cached, "sys.modules"
module_candidates = []
env_module = os.environ.get("EG_LUI_MODULE", "").strip()
if env_module:
for name in (part.strip() for part in env_module.split(",")):
if name:
module_candidates.append(name)
for default_name in ("lui", "panda3d.lui"):
if default_name not in module_candidates:
module_candidates.append(default_name)
for module_name in module_candidates:
try:
module = importlib.import_module(module_name)
return module, f"module:{module_name}"
except Exception as exc:
failures.append(_format_import_failure(f"import {module_name}", exc))
env_binary = os.environ.get("EG_LUI_BINARY", "").strip()
explicit_paths = []
if env_binary:
raw_path = Path(env_binary).expanduser()
explicit_paths.append(raw_path if raw_path.is_absolute() else (UI_DIR / raw_path))
explicit_paths.append(raw_path)
checked = set()
for path_candidate in explicit_paths:
resolved = path_candidate.resolve()
if resolved in checked:
continue
checked.add(resolved)
if not resolved.exists():
failures.append(f"binary path not found: {resolved}")
continue
try:
module = _load_lui_from_binary(resolved)
return module, f"binary:{resolved}"
except Exception as exc:
failures.append(_format_import_failure(f"load {resolved.name}", exc))
for binary_path in _iter_local_lui_binaries():
try:
module = _load_lui_from_binary(binary_path)
return module, f"binary:{binary_path}"
except Exception as exc:
failures.append(_format_import_failure(f"load {binary_path.name}", exc))
return None, " | ".join(failures)
lui = None
try:
lui, LUI_MODULE_SOURCE = _bootstrap_lui_module()
if lui is not None:
panda3d.lui = lui
sys.modules["panda3d.lui"] = lui
if "lui" not in sys.modules:
sys.modules["lui"] = lui
from Builtin.LUIRegion import LUIRegion
from Builtin.LUIInputHandler import LUIInputHandler
from Builtin.LUIButton import LUIButton
from Builtin.LUILabel import LUILabel
from Builtin.LUIInputField import LUIInputField
from Builtin.LUISlider import LUISlider
from Builtin.LUIFrame import LUIFrame
from Builtin.LUISkin import LUIDefaultSkin
from Builtin.LUISprite import LUISprite
from Builtin.LUIObject import LUIObject
from Builtin.LUICheckbox import LUICheckbox
from Builtin.LUIProgressbar import LUIProgressbar
from Builtin.LUISelectbox import LUISelectbox
from Builtin.LUIScrollableRegion import LUIScrollableRegion
from Builtin.LUITabbedFrame import LUITabbedFrame
from Builtin.LUIVerticalLayout import LUIVerticalLayout
from Builtin.LUIHorizontalLayout import LUIHorizontalLayout
else:
raise ImportError(LUI_MODULE_SOURCE or "No available LUI module.")
except Exception as e:
detail = str(LUI_MODULE_SOURCE or "").strip()
if detail:
LUI_IMPORT_DETAILS = detail
print(f"Error: Failed to import LUI: {detail}")
else:
LUI_IMPORT_DETAILS = str(e)
print(f"Error: Failed to import LUI: {e}")
lui = None
LUIRegion = None
LUIInputHandler = None
LUIButton = None
LUILabel = None
LUIInputField = None
LUISlider = None
LUIFrame = None
LUIDefaultSkin = None
LUISprite = None
LUIObject = None
LUICheckbox = None
LUIProgressbar = None
LUISelectbox = None
LUIScrollableRegion = None
LUITabbedFrame = None
LUIVerticalLayout = None
LUIHorizontalLayout = None