Files
blender-portable-repo/extensions/blender_org/bool_tool/functions/poll.py
T
2026-07-14 14:44:58 -06:00

131 lines
4.4 KiB
Python

import bpy
from ..constants import (
CONVERTABLE_TYPES,
)
from .mesh import (
is_instanced_mesh,
)
from .object import (
has_evaluated_mesh,
)
#### ------------------------------ FUNCTIONS ------------------------------ ####
def basic_poll(cls, context, check_active=True):
"""Basic poll for Boolean operators."""
if context.mode != 'OBJECT':
cls.poll_message_set("Boolean operators can only be performed in Object Mode")
return False
if check_active:
if context.active_object is None:
cls.poll_message_set("No active object")
return False
return True
def destructive_op_confirmation(cls, context, event, canvases: list, title="Boolean Operation"):
"""
Creates & returns the confirmation pop-up window for destructive Boolean operators.\n
Confirmation window is triggered by canvases that have instanced data or shape keys.\n
If none of the canvases have them the operator is executed without any confirmation.
"""
if len(canvases) == 0:
return cls.execute(context)
has_instanced_data = any(obj for obj in canvases if is_instanced_mesh(obj.data))
has_shape_keys = any(obj for obj in canvases if obj.data.shape_keys)
if has_instanced_data or has_shape_keys:
# Instanced data message.
if has_instanced_data and not has_shape_keys:
message = ("Object(s) you're trying to cut have instanced object data.\n"
"In order to apply modifiers, they need to be made single-user.\n"
"Do you proceed?")
# Shape keys message.
if has_shape_keys and not has_instanced_data:
message = ("Object(s) you're trying to cut have shape keys.\n"
"In order to apply modifiers shape keys need to be applied as well.\n"
"Do you proceed?")
# Combined message.
if has_instanced_data and has_shape_keys:
message = ("Object(s) you're trying to cut have shape keys and instanced object data.\n"
"In order to apply modifiers shape keys need to be applied & object data made single user.\n"
"Do you proceed?")
popup = context.window_manager.invoke_confirm(cls, event, title=title,
confirm_text="Yes", icon='WARNING',
message=message)
cls._unflippable = True
return popup
# Execute without confirmation window.
else:
return cls.execute(context)
def convert_to_mesh_confirmation(cls, context, event, cutters: list, title="Boolean Operation"):
"""
Creates & returns the confirmation pop-up window when the object is
about to be converted to mesh to be used as a cutter.
NOTE (1): Only triggers during brush Boolean operators,
because object gets destroyed in the destructive one anyway.
NOTE (2): This is only required because of the limitation of legacy Boolean modifier.
Geometry nodes implementation works with any object type. When the add-on is
updated to work with custom modifiers this will not be necesary anymore.
"""
if len(cutters) == 0:
return cls.execute(context)
is_convertable = any(
obj.type in CONVERTABLE_TYPES and has_evaluated_mesh(context, obj)
for obj in cutters
)
if is_convertable:
message = ("Some of the selected objects are not of the Mesh type, but output mesh.\n"
"In order to use them as cutters, they need to be converted to mesh.\n"
"This is a destructive operator. Do you proceed?")
popup = context.window_manager.invoke_confirm(cls, event, title=title,
confirm_text="Yes", icon='WARNING',
message=message)
cls._unflippable = True
return popup
# Execute without confirmation window.
else:
return cls.execute(context)
#### ------------------------------ /operator_helpers/ ------------------------------ ####
def _guess_toggle_state(modifiers):
"""Guess whether cutters should be hidden or revealed."""
enabled = 0
disabled = 0
for mod in modifiers:
if mod.show_viewport:
enabled += 1
else:
disabled += 1
if enabled > disabled:
return "On"
else:
return "Off"