blenderwright 2.2.0__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blenderwright-2.2.0 → blenderwright-2.2.1}/PKG-INFO +1 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/__init__.py +1 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/blender_manifest.toml +1 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/materials.py +12 -2
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/objects.py +21 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/pyproject.toml +1 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_materials_handler.py +64 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_objects_handler.py +62 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/uv.lock +1 -1
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.github/FUNDING.yml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.github/workflows/ci.yml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.github/workflows/pylint.yml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.github/workflows/release.yml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.github/workflows/test-bpy51.yml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/.gitignore +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/LICENSE.md +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/README.md +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/dispatcher.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/animation.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/armature.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/booltool.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/camera.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/code_exec.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/collections.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/curves.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/file_ops.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/geometry_nodes.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/gpencil.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/lighting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/mesh_editing.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/mesh_quality.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/modeling.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/physics.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/print3d.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/procedural.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/raster.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/rendering.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/scene.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/sculpting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/selection.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/sequencer.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/sweep.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/transforms.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/uv.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/handlers/viewport.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/render_guard.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/server.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/thread_safety.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/addon/ui_panel.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/blend-ai-v1.0.0.zip +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/build.ps1 +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/build.sh +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/.nojekyll +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/CNAME +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/googled2f6c71abc2d6a7b.html +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/index.html +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/robots.txt +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/shuttle-launch.mp4 +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/docs/sitemap.xml +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/glama.json +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/install-addon.sh +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/install_addon.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/launch_ollama.sh +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/saloon.png +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/screenshot.png +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/scripts/generate_tool_docs.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/shader-preview.png +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/shuttle-launch.gif +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/shuttle-launch.png +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/__main__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/aliases.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/connection.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/enum_hints.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/ollama_chat.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/prompts/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/prompts/workflows.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/resources/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/resources/scene_info.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/server.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/strict.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tool_registry.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/animation.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/armature.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/booltool.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/camera.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/code_exec.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/collections.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/curves.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/file_ops.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/geometry_nodes.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/gpencil.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/lighting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/materials.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/mesh_editing.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/mesh_quality.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/modeling.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/objects.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/physics.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/print3d.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/rendering.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/scene.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/screenshot.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/sculpting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/selection.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/sequencer.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/sweep.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/transforms.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/uv.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/tools/viewport.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/toolsets.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/src/blenderwright/validators.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/conftest.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/conftest.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_dispatcher.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handler_registration.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_camera_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_code_exec_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_geometry_nodes_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_gpencil_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_mesh_quality_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_modeling_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_print3d_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_procedural_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_raster_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_rendering_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_scene_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sculpting_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_selection_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sequencer_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sweep_handler.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_layer_consistency.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_module_cache_purge.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_render_guard.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_server.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_thread_safety.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_ui_panel.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_command_registry.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_connection.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_enum_hints.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_installer.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_long_names.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_object_param_naming.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_ollama_budget.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_ollama_chat.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_ollama_toolsets.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_ollama_vision.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_project_metadata.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_round_wasters.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_strict_parameters.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tool_disambiguation.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/__init__.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/conftest.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_animation.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_armature.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_auto_critique_prompt.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_booltool.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_camera.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_code_exec.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_collections.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_curves.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_eevee_light_path.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_extensions.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_file_ops.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_geometry_nodes.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_gpencil.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_issue_31_validation.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_lighting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_materials.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_mesh_editing.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_mesh_quality.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_mesh_repair.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_modeling.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_negative_scale_primitives.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_new_nodes.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_numeric_text_values.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_objects.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_physics.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_point_camera_at.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_print3d.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_procedural.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_prompts.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_raster.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_rendering.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_scene.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_screenshot.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_sculpting.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_selection.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_selection_respected.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_sequencer.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_shader_nodes.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_sweep.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_transforms.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_uv.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_uv_slim.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_viewport.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_toolsets.py +0 -0
- {blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_validators.py +0 -0
|
@@ -8,7 +8,7 @@ Blender's Python API.
|
|
|
8
8
|
bl_info = {
|
|
9
9
|
"name": "blenderwright",
|
|
10
10
|
"author": "blenderwright",
|
|
11
|
-
"version": (2, 2,
|
|
11
|
+
"version": (2, 2, 1),
|
|
12
12
|
"blender": (4, 2, 0),
|
|
13
13
|
"location": "View3D > Sidebar > blenderwright",
|
|
14
14
|
"description": "MCP Server integration for AI-assisted 3D workflows",
|
|
@@ -55,9 +55,19 @@ def handle_assign_material(params: dict) -> dict:
|
|
|
55
55
|
obj.active_material_index = i
|
|
56
56
|
return {"object": obj.name, "material": mat.name, "action": "already_assigned", "slot": i}
|
|
57
57
|
|
|
58
|
+
# Fill the first empty slot before adding one. A boolean modifier
|
|
59
|
+
# leaves an empty slot 0 that every face points at; appending puts
|
|
60
|
+
# the material in slot 1 and the object still renders grey.
|
|
61
|
+
for i, slot_mat in enumerate(obj.data.materials):
|
|
62
|
+
if slot_mat is None:
|
|
63
|
+
obj.data.materials[i] = mat
|
|
64
|
+
obj.active_material_index = i
|
|
65
|
+
return {"object": obj.name, "material": mat.name, "action": "assigned", "slot": i}
|
|
66
|
+
|
|
58
67
|
obj.data.materials.append(mat)
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
slot = len(obj.data.materials) - 1
|
|
69
|
+
obj.active_material_index = slot
|
|
70
|
+
return {"object": obj.name, "material": mat.name, "action": "assigned", "slot": slot}
|
|
61
71
|
except Exception as e:
|
|
62
72
|
raise RuntimeError(f"Failed to assign material: {e}")
|
|
63
73
|
|
|
@@ -39,6 +39,21 @@ def _get_primitive_op(ptype: str):
|
|
|
39
39
|
return ops_map.get(ptype)
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
def _bake_scale(obj, scale) -> None:
|
|
43
|
+
"""Apply a creation scale the way primitive_cube_add does: into the mesh.
|
|
44
|
+
|
|
45
|
+
Mesh data is transformed so the object keeps unit scale and modifiers
|
|
46
|
+
see the real size. An empty has no mesh, so it gets object scale.
|
|
47
|
+
"""
|
|
48
|
+
sx, sy, sz = (float(v) for v in scale)
|
|
49
|
+
if (sx, sy, sz) == (1.0, 1.0, 1.0):
|
|
50
|
+
return
|
|
51
|
+
if obj.data is not None and hasattr(obj.data, "transform"):
|
|
52
|
+
obj.data.transform(mathutils.Matrix.Diagonal((sx, sy, sz, 1)))
|
|
53
|
+
else:
|
|
54
|
+
obj.scale = (sx, sy, sz)
|
|
55
|
+
|
|
56
|
+
|
|
42
57
|
def _extent(obj) -> dict:
|
|
43
58
|
"""The object's size and where it ends, in world space.
|
|
44
59
|
|
|
@@ -77,9 +92,14 @@ def handle_create_object(params: dict) -> dict:
|
|
|
77
92
|
op_func = _get_primitive_op(obj_type)
|
|
78
93
|
if op_func is None:
|
|
79
94
|
raise ValueError(f"Unknown object type: {obj_type}")
|
|
80
|
-
|
|
95
|
+
# Created at unit scale on purpose: the scale is baked below.
|
|
96
|
+
# Blender 5.1's primitive_plane_add and primitive_circle_add
|
|
97
|
+
# silently ignore their scale argument while primitive_cube_add
|
|
98
|
+
# bakes it into the mesh, so the op cannot be trusted with it.
|
|
99
|
+
op_func(location=location, rotation=rotation)
|
|
81
100
|
|
|
82
101
|
obj = bpy.context.active_object
|
|
102
|
+
_bake_scale(obj, scale)
|
|
83
103
|
if name:
|
|
84
104
|
obj.name = name
|
|
85
105
|
if obj.data:
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_materials_handler.py
RENAMED
|
@@ -481,3 +481,67 @@ class TestRegistration:
|
|
|
481
481
|
"set_color_ramp_interpolation",
|
|
482
482
|
"get_color_ramp",
|
|
483
483
|
} <= registered
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
# ---------------------------------------------------------------------------
|
|
487
|
+
# assign_material fills an empty slot before adding one
|
|
488
|
+
# ---------------------------------------------------------------------------
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class TestAssignMaterialSlots:
|
|
492
|
+
"""An object that has been through a boolean modifier carries an empty
|
|
493
|
+
material slot 0. Appending put the material in slot 1, every face still
|
|
494
|
+
pointed at slot 0, and the wall rendered grey. The first empty slot is
|
|
495
|
+
filled instead; a new slot is only added when none is empty."""
|
|
496
|
+
|
|
497
|
+
def _obj(self, slots):
|
|
498
|
+
obj = MagicMock()
|
|
499
|
+
obj.name = "Wall"
|
|
500
|
+
obj.data.materials = list(slots)
|
|
501
|
+
return obj
|
|
502
|
+
|
|
503
|
+
def _mat(self, name):
|
|
504
|
+
mat = MagicMock()
|
|
505
|
+
mat.name = name
|
|
506
|
+
return mat
|
|
507
|
+
|
|
508
|
+
def _patch(self, monkeypatch, obj, mat):
|
|
509
|
+
import bpy
|
|
510
|
+
monkeypatch.setattr(bpy.data.objects, "get", lambda n: obj)
|
|
511
|
+
monkeypatch.setattr(bpy.data.materials, "get", lambda n: mat)
|
|
512
|
+
|
|
513
|
+
def test_fills_the_empty_slot(self, mh, monkeypatch):
|
|
514
|
+
sage = self._mat("Wall_Sage")
|
|
515
|
+
obj = self._obj([None])
|
|
516
|
+
self._patch(monkeypatch, obj, sage)
|
|
517
|
+
result = mh.handle_assign_material({"object_name": "Wall", "material_name": "Wall_Sage"})
|
|
518
|
+
assert obj.data.materials == [sage]
|
|
519
|
+
assert result["slot"] == 0
|
|
520
|
+
assert result["action"] == "assigned"
|
|
521
|
+
|
|
522
|
+
def test_fills_the_first_empty_slot_only(self, mh, monkeypatch):
|
|
523
|
+
sage = self._mat("Wall_Sage")
|
|
524
|
+
other = self._mat("Other")
|
|
525
|
+
obj = self._obj([other, None, None])
|
|
526
|
+
self._patch(monkeypatch, obj, sage)
|
|
527
|
+
result = mh.handle_assign_material({"object_name": "Wall", "material_name": "Wall_Sage"})
|
|
528
|
+
assert obj.data.materials == [other, sage, None]
|
|
529
|
+
assert result["slot"] == 1
|
|
530
|
+
|
|
531
|
+
def test_appends_when_no_slot_is_empty(self, mh, monkeypatch):
|
|
532
|
+
sage = self._mat("Wall_Sage")
|
|
533
|
+
other = self._mat("Other")
|
|
534
|
+
obj = self._obj([other])
|
|
535
|
+
self._patch(monkeypatch, obj, sage)
|
|
536
|
+
result = mh.handle_assign_material({"object_name": "Wall", "material_name": "Wall_Sage"})
|
|
537
|
+
assert obj.data.materials == [other, sage]
|
|
538
|
+
assert result["slot"] == 1
|
|
539
|
+
|
|
540
|
+
def test_already_assigned_is_reported(self, mh, monkeypatch):
|
|
541
|
+
sage = self._mat("Wall_Sage")
|
|
542
|
+
obj = self._obj([None, sage])
|
|
543
|
+
self._patch(monkeypatch, obj, sage)
|
|
544
|
+
result = mh.handle_assign_material({"object_name": "Wall", "material_name": "Wall_Sage"})
|
|
545
|
+
assert result["action"] == "already_assigned"
|
|
546
|
+
assert result["slot"] == 1
|
|
547
|
+
assert obj.data.materials == [None, sage]
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_objects_handler.py
RENAMED
|
@@ -544,3 +544,65 @@ class TestCreateReturnsExtent:
|
|
|
544
544
|
result = objects_handler.handle_create_object({"type": "CUBE"})
|
|
545
545
|
assert result["name"] == "Fuselage"
|
|
546
546
|
assert "bounds" not in result
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
# ---------------------------------------------------------------------------
|
|
550
|
+
# create_object bakes the scale itself
|
|
551
|
+
# ---------------------------------------------------------------------------
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
class TestCreateBakesScale:
|
|
555
|
+
"""Blender 5.1's primitive_plane_add and primitive_circle_add silently
|
|
556
|
+
ignore their scale argument, while primitive_cube_add bakes it into the
|
|
557
|
+
mesh. A hallway floor asked for at scale (3, 4.5, 1) came back 2m square.
|
|
558
|
+
The handler now creates every primitive at unit scale and bakes the scale
|
|
559
|
+
into the mesh itself, so every type behaves the way the cube always did."""
|
|
560
|
+
|
|
561
|
+
def _obj(self, bpy):
|
|
562
|
+
obj = MagicMock()
|
|
563
|
+
obj.name = "Floor"
|
|
564
|
+
obj.type = "MESH"
|
|
565
|
+
obj.location = [0, 0, 0]
|
|
566
|
+
obj.dimensions = [6.0, 9.0, 0.0]
|
|
567
|
+
obj.bound_box = None
|
|
568
|
+
for op in ("primitive_plane_add", "primitive_cube_add", "primitive_circle_add"):
|
|
569
|
+
getattr(bpy.ops.mesh, op).side_effect = None
|
|
570
|
+
bpy.context.active_object = obj
|
|
571
|
+
return obj
|
|
572
|
+
|
|
573
|
+
def test_plane_scale_is_baked_into_the_mesh(self, objects_handler):
|
|
574
|
+
import bpy
|
|
575
|
+
import mathutils
|
|
576
|
+
bpy.reset_mock()
|
|
577
|
+
mathutils.Matrix.reset_mock()
|
|
578
|
+
obj = self._obj(bpy)
|
|
579
|
+
objects_handler.handle_create_object({
|
|
580
|
+
"type": "PLANE", "location": (0, 4.5, 0), "scale": (3, 4.5, 1),
|
|
581
|
+
})
|
|
582
|
+
mathutils.Matrix.Diagonal.assert_called_once_with((3, 4.5, 1, 1))
|
|
583
|
+
obj.data.transform.assert_called_once_with(mathutils.Matrix.Diagonal.return_value)
|
|
584
|
+
|
|
585
|
+
def test_the_op_is_not_asked_to_scale(self, objects_handler):
|
|
586
|
+
"""Passing scale to the op as well would double it on the cube."""
|
|
587
|
+
import bpy
|
|
588
|
+
bpy.reset_mock()
|
|
589
|
+
self._obj(bpy)
|
|
590
|
+
objects_handler.handle_create_object({"type": "CUBE", "scale": (2, 2, 2)})
|
|
591
|
+
assert "scale" not in bpy.ops.mesh.primitive_cube_add.call_args.kwargs
|
|
592
|
+
|
|
593
|
+
def test_unit_scale_does_not_touch_the_mesh(self, objects_handler):
|
|
594
|
+
import bpy
|
|
595
|
+
bpy.reset_mock()
|
|
596
|
+
obj = self._obj(bpy)
|
|
597
|
+
objects_handler.handle_create_object({"type": "CIRCLE", "scale": (1, 1, 1)})
|
|
598
|
+
obj.data.transform.assert_not_called()
|
|
599
|
+
|
|
600
|
+
def test_empty_gets_object_scale(self, objects_handler):
|
|
601
|
+
"""An empty has no mesh to bake into, so its object scale is set."""
|
|
602
|
+
import bpy
|
|
603
|
+
bpy.reset_mock()
|
|
604
|
+
obj = self._obj(bpy)
|
|
605
|
+
obj.type = "EMPTY"
|
|
606
|
+
obj.data = None
|
|
607
|
+
objects_handler.handle_create_object({"type": "EMPTY", "scale": (2, 3, 4)})
|
|
608
|
+
assert tuple(obj.scale) == (2, 3, 4)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_camera_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_code_exec_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_gpencil_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_modeling_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_print3d_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_raster_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_rendering_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_scene_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sculpting_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_selection_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sequencer_handler.py
RENAMED
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_addon/test_handlers/test_sweep_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{blenderwright-2.2.0 → blenderwright-2.2.1}/tests/test_tools/test_negative_scale_primitives.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|