Add tests and implement boundary smoothing and cutout functionality
- Introduced tests for boundary smoothing in `test_boundary_smoothing.py`, verifying that smoothing reduces stair-step artifacts while preserving boundary integrity. - Added tests for cutout boundary behavior in `test_cutout_boundary.py`, ensuring proper handling of boundary triangles and normal blending. - Created `test_temporary_attributes.py` to check the cleanup of temporary attributes across depth modifier branches, ensuring no warnings are raised. - Implemented point culling functionality in `test_validity.py`, confirming that invalid points are removed without affecting adjacent geometry. - Developed boundary smoothing logic in `boundary_smoothing.py`, allowing for depth smoothing while maintaining edge integrity. - Added cutout boundary management in `cutout_boundary.py`, including functions for removing boundary triangles and tapering thickness profiles. - Implemented validity checks in `validity.py` to ensure proper deletion of invalid vertices and associated wire edges.
This commit is contained in:
@@ -6,7 +6,7 @@ import bpy
|
||||
|
||||
from ...common.material import create_image_material
|
||||
from ...common.color_image import material_color_image
|
||||
from ...common.image import image_pixels
|
||||
from ...common.image import cleanup_image_input, image_pixels, save_packed_image
|
||||
|
||||
CLIPBOARD_HASH_PROPERTY = "anyimage_clipboard_sha256"
|
||||
CLIPBOARD_CONTENT_PROPERTY = "anyimage_clipboard_content_sha256"
|
||||
@@ -49,6 +49,10 @@ class PasteTargetError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class BrushPreviewError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def target_for_context(context):
|
||||
area = getattr(context, "area", None)
|
||||
area_type = getattr(area, "type", None)
|
||||
@@ -367,10 +371,31 @@ def set_tool_texture(context, image):
|
||||
raise PasteTargetError(
|
||||
f"The active brush could not use the image texture: {error}"
|
||||
) from error
|
||||
_redraw_area(context)
|
||||
try:
|
||||
if getattr(context, "mode", "") == "PAINT_TEXTURE":
|
||||
_set_brush_preview(context, brush, image)
|
||||
finally:
|
||||
_redraw_area(context)
|
||||
return texture
|
||||
|
||||
|
||||
def _set_brush_preview(context, brush, image):
|
||||
preview_path = None
|
||||
try:
|
||||
preview_path = save_packed_image(image, context.scene)
|
||||
with context.temp_override(id=brush):
|
||||
result = bpy.ops.ed.lib_id_load_custom_preview(filepath=str(preview_path))
|
||||
if result != {"FINISHED"}:
|
||||
raise RuntimeError("Blender did not load the custom preview")
|
||||
except (OSError, RuntimeError, ValueError) as error:
|
||||
raise BrushPreviewError(
|
||||
f"Texture pasted, but the brush preview could not be updated: {error}"
|
||||
) from error
|
||||
finally:
|
||||
if preview_path is not None:
|
||||
cleanup_image_input(preview_path, True)
|
||||
|
||||
|
||||
def _set_unbiased_paint_color(context, brush):
|
||||
if getattr(context, "mode", "") not in WHITE_BRUSH_COLOR_MODES:
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ import sys
|
||||
import bpy
|
||||
|
||||
from .actions import (
|
||||
BrushPreviewError,
|
||||
PasteTargetError,
|
||||
acquire_packed_image,
|
||||
paste_image,
|
||||
@@ -134,6 +135,9 @@ class PasteClipboardImage(bpy.types.Operator):
|
||||
import_as=self.import_as,
|
||||
shadeless=self.shadeless,
|
||||
)
|
||||
except BrushPreviewError as error:
|
||||
self.report({"WARNING"}, str(error))
|
||||
return {"FINISHED"}
|
||||
except (OSError, RuntimeError, PasteTargetError) as error:
|
||||
if image is not None and not image_reused and image.users == 0:
|
||||
bpy.data.images.remove(image)
|
||||
|
||||
@@ -35,7 +35,7 @@ def create_panorama_from_result(context, result, operator):
|
||||
try:
|
||||
with material_color_image(input_path=operator.color_path) as color:
|
||||
metadata = load_panorama_metadata(result.file("depth_metadata"))
|
||||
group = load_node_group("O Image Depth Panorama")
|
||||
group = load_node_group("O Image Depth Panorama", asset_revision=14)
|
||||
depth = load_depth_result_image(result.file("depth"), source, metadata)
|
||||
material = create_image_material(source.data, color, shadeless=True, scene=context.scene,
|
||||
texture_extension="REPEAT")
|
||||
|
||||
@@ -62,7 +62,7 @@ def create_depth_plane_object(
|
||||
node_group = load_node_group({
|
||||
"DEPTH": "O Image Depth Plane",
|
||||
"RELIEF": "O Image Relief Plane",
|
||||
}[plane_type])
|
||||
}[plane_type], asset_revision=14 if plane_type == "DEPTH" else None)
|
||||
source_name = source_object.name
|
||||
bounds = image_empty_bounds(source_object)
|
||||
mesh = create_image_plane_mesh(source_name, bounds)
|
||||
|
||||
@@ -99,7 +99,7 @@ def _assign_float_point_attribute(mesh, name, values):
|
||||
|
||||
|
||||
def load_cutout_node_group(shape):
|
||||
return load_node_group(CUTOUT_NODE_GROUP_NAMES[shape], asset_revision=11)
|
||||
return load_node_group(CUTOUT_NODE_GROUP_NAMES[shape], asset_revision=18 if shape == "DEPTH_SOLID" else 11)
|
||||
|
||||
|
||||
def _connect_cutout_normal_scale(material):
|
||||
|
||||
Reference in New Issue
Block a user