185 lines
5.9 KiB
Python
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
|