# -*- coding: utf-8 -*-
from __future__ import annotations
import math
from dataclasses import dataclass
from operator import getitem
from typing import Any, Dict, FrozenSet, List, Tuple
import bpy
from PyR3.shortcut.context import Objects
class _Modifier:
def apply(self, **extra_params):
MODIFIER = self.master_object.modifiers.new(
self.__class__.__qualname__, self.__class__.__qualname__.upper()
)
self._set_modifier_params(
MODIFIER, self.__class__.__dataclass_fields__.keys()
)
if extra_params:
self._set_modifier_extra_params(MODIFIER, extra_params)
self._apply_modifier(MODIFIER.name, self.master_object)
def _set_modifier_params(
self, modifier: bpy.types.Modifier, param_keys: List[str]
):
for param_name in param_keys:
if hasattr(modifier, param_name):
param_value = getattr(self, param_name)
setattr(modifier, param_name, param_value)
def _set_modifier_extra_params(
self, modifier: bpy.types.Modifier, extra: Dict[str, Any]
):
for param_name in extra.keys():
if hasattr(modifier, param_name):
param_value = getitem(extra, param_name)
setattr(modifier, param_name, param_value)
def _apply_modifier(
self, modifier_name: bpy.types.Modifier, ob: bpy.types.Object
) -> None:
Objects.select_only(ob)
Objects.active = ob
bpy.ops.object.modifier_apply(modifier=modifier_name)
[docs]@dataclass
class Boolean(_Modifier):
"""Boolean Modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.BooleanModifier.html
"""
master_object: bpy.types.Object
object: bpy.types.Object
operation: str = "DIFFERENCE"
solver: str = "EXACT"
use_self: bool = False
[docs]@dataclass
class Array(_Modifier):
"""Array modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.ArrayModifier.html
"""
master_object: bpy.types.Object
constant_offset_displace: Tuple[float, float, float] = (0, 0, 0)
count: int = 1
use_relative_offset: bool = False
use_constant_offset: bool = True
[docs]@dataclass
class Solidify(_Modifier):
"""Solidify modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.SolidifyModifier.html
"""
master_object: bpy.types.Object
thickness: float = 0.01
offset: float = -1
use_even_offset: bool = False
use_quality_normals: bool = True
[docs]@dataclass
class Bevel(_Modifier):
"""Solidify modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.BevelModifier.html
"""
master_object: bpy.types.Object
affect: str = "EDGES"
offset_type: str = "OFFSET"
width: float = 0.1
segments: int = 1
limit_method: str = "NONE"
angle_limit: float = math.pi / 6
use_clamp_overlap: bool = True
[docs]@dataclass
class Decimate(_Modifier):
"""Decimate modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.DecimateModifier.html
"""
master_object: bpy.types.Object
angle_limit: float = 0.0872665
decimate_type: str = "COLLAPSE"
delimit: FrozenSet[str] = frozenset(("NORMAL",))
invert_vertex_group: bool = False
iterations: int = 0
ratio: float = 1.0
symmetry_axis: str = "X"
use_collapse_triangulate: bool = False
use_dissolve_boundaries: bool = False
vertex_group: str = ""
vertex_group_factor: float = 1.0
[docs]@dataclass
class Remesh(_Modifier):
"""Remesh modifier wrapper.
For documentation over modifier parameters
visit https://docs.blender.org/api/current/bpy.types.RemeshModifier.html
"""
master_object: bpy.types.Object
adaptivity: float = 0.0
mode: str = "BLOCKS" # "SMOOTH", "SHARP", "VOXEL"
octree_depth: int = 4
scale: float = 0.9
sharpness: float = 1.0
threshold: float = 1.0
use_remove_disconnected: bool = True
use_smooth_shade: bool = False
voxel_size: float = 0.1