"""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