feat(node_assets): add image plane geometry nodes and validation scripts

- Implemented `image_plane.py` to build the Image Plane Geometry Nodes group with customizable parameters for geometry, subdivide, and thickness.
- Created `image_plane_validation.py` to validate the functionality of the image plane, ensuring correct geometry generation and material assignment.
- Developed `material_layers.py` to construct shader node groups for image materials, including depth and normal handling.
- Authored `plane_layouts.py` to define node arrangements for image geometry assets.
- Introduced `shadeless.py` to create a shadeless shader node group that displays color without scene lighting while preserving shadows and reflections.
This commit is contained in:
2026-09-08 23:24:27 +08:00
parent 196b964efc
commit 4c902ed7db
155 changed files with 9700 additions and 10393 deletions

View File

@@ -0,0 +1,88 @@
import importlib
import importlib.util
import sys
from pathlib import Path
from types import ModuleType, SimpleNamespace
from unittest.mock import patch
from blender_test_support import mock_bpy_imports
PROJECT_ROOT = Path(__file__).resolve().parents[1]
SOURCE_ROOT = PROJECT_ROOT / "src"
sys.path.insert(0, str(SOURCE_ROOT))
def load_common_modules():
fake_bpy = ModuleType("bpy")
fake_bpy.props = SimpleNamespace(
BoolProperty=lambda **options: options,
EnumProperty=lambda **options: options,
FloatProperty=lambda **options: options,
IntProperty=lambda **options: options,
StringProperty=lambda **options: options,
)
fake_bpy.types = SimpleNamespace(Menu=object, Operator=object)
fake_bpy.path = SimpleNamespace(abspath=lambda path: path)
fake_bpy.context = SimpleNamespace(scene=None)
module_paths = (
(
"anyimage.common.image",
PROJECT_ROOT
/ "src"
/ "anyimage"
/ "common"
/ "image.py",
),
(
"anyimage.common.node",
PROJECT_ROOT
/ "src"
/ "anyimage"
/ "common"
/ "node.py",
),
(
"anyimage.common.material",
PROJECT_ROOT
/ "src"
/ "anyimage"
/ "common"
/ "material.py",
),
(
"anyimage.common.object",
PROJECT_ROOT
/ "src"
/ "anyimage"
/ "common"
/ "object.py",
),
)
packages = {
name: ModuleType(name)
for name in (
"anyimage",
"anyimage.operators",
"anyimage.common",
"anyimage.operators.convert_to_plane",
)
}
for package in packages.values():
package.__path__ = []
loaded = []
preferences = ModuleType("anyimage.preferences")
preferences.configured_material_view_adaptation = lambda: True
with mock_bpy_imports(fake_bpy), patch.dict(sys.modules, {"anyimage.preferences": preferences, **packages}):
for module_name, module_path in module_paths:
specification = importlib.util.spec_from_file_location(
module_name,
module_path,
)
module = importlib.util.module_from_spec(specification)
sys.modules[module_name] = module
specification.loader.exec_module(module)
loaded.append(module)
return SimpleNamespace(image=loaded[0], node=loaded[1], material=loaded[2], object=loaded[3])