368 lines
14 KiB
Python
368 lines
14 KiB
Python
"""Geometry Script recreation of a scalar helper from Shriinivas/fieldvalue.blend."""
|
|
|
|
try:
|
|
from tools.geometry_script_loader import load_repo_geometry_script
|
|
except ModuleNotFoundError:
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
|
from tools.geometry_script_loader import load_repo_geometry_script
|
|
|
|
load_repo_geometry_script()
|
|
|
|
from geometry_script import * # noqa: F403 - Geometry Script exposes node functions as DSL globals.
|
|
|
|
|
|
def _int_equal(value, target: int):
|
|
return compare(
|
|
operation=Compare.Operation.EQUAL,
|
|
data_type=Compare.DataType.INT,
|
|
mode=Compare.Mode.ELEMENT,
|
|
a=value,
|
|
b=target,
|
|
)
|
|
|
|
|
|
def _float_equal(value, target: float):
|
|
return compare(
|
|
operation=Compare.Operation.EQUAL,
|
|
data_type=Compare.DataType.FLOAT,
|
|
mode=Compare.Mode.ELEMENT,
|
|
a=value,
|
|
b=target,
|
|
)
|
|
|
|
|
|
@tree("VG Create Decimal")
|
|
def vg_create_decimal(vertical_segment_size: Float = 2.0, radius: Float = 0.0):
|
|
dot = mesh_circle(fill_type=MeshCircle.FillType.NGON, vertices=32, radius=radius)
|
|
offset = combine_xyz(
|
|
x=0.0,
|
|
y=math(operation=Math.Operation.MULTIPLY, value=(-1.0, vertical_segment_size)),
|
|
z=0.0,
|
|
)
|
|
return {"Dot": dot.set_position(offset=offset)}
|
|
|
|
|
|
@tree("VG Digit At")
|
|
def vg_digit_at(number: Float = 0.0, position: Int = 0):
|
|
shifted_position = math(operation=Math.Operation.ADD, value=(position, 1.0))
|
|
upper_scale = math(operation=Math.Operation.POWER, value=(10.0, shifted_position))
|
|
shifted_number = math(operation=Math.Operation.DIVIDE, value=(number, upper_scale))
|
|
fractional_window = math(operation=Math.Operation.FRACT, value=shifted_number)
|
|
digit_window = math(operation=Math.Operation.MULTIPLY, value=(10.0, fractional_window))
|
|
|
|
position_scale = math(operation=Math.Operation.POWER, value=(10.0, position))
|
|
rounded_scaled_window = math(
|
|
operation=Math.Operation.ROUND,
|
|
value=math(operation=Math.Operation.MULTIPLY, value=(digit_window, position_scale)),
|
|
)
|
|
digit_value = math(operation=Math.Operation.DIVIDE, value=(rounded_scaled_window, position_scale))
|
|
|
|
is_ones_position = compare(
|
|
operation=Compare.Operation.EQUAL,
|
|
data_type=Compare.DataType.INT,
|
|
mode=Compare.Mode.ELEMENT,
|
|
a=position,
|
|
b=0,
|
|
)
|
|
return switch(
|
|
input_type=Switch.InputType.INT,
|
|
switch=is_ones_position,
|
|
false=math(operation=Math.Operation.FLOOR, value=digit_value),
|
|
true=math(operation=Math.Operation.ROUND, value=digit_value),
|
|
)
|
|
|
|
|
|
@tree("VG Next Digit")
|
|
def vg_next_digit(
|
|
whole_part: Float = 0.0,
|
|
fraction_part: Float = 0.0,
|
|
max_precision: Int = 0,
|
|
position: Int = 0,
|
|
):
|
|
whole_position = math(operation=Math.Operation.SUBTRACT, value=(position, max_precision))
|
|
use_fraction = math(operation=Math.Operation.LESS_THAN, value=(position, max_precision))
|
|
whole_digit = vg_digit_at(number=whole_part, position=whole_position)
|
|
fraction_digit = vg_digit_at(number=fraction_part, position=position)
|
|
return switch(
|
|
input_type=Switch.InputType.INT,
|
|
switch=use_fraction,
|
|
false=whole_digit,
|
|
true=fraction_digit,
|
|
)
|
|
|
|
|
|
@tree("VG Create Segment")
|
|
def vg_create_segment(
|
|
x_major: Bool = False,
|
|
segment_length_along_x: Float = 0.0,
|
|
segment_length_along_y: Float = 0.0,
|
|
secondary_axis_segment_thickness: Float = 0.0,
|
|
sharpness: Float = 0.0,
|
|
offset: Vector = (0.0, 0.0, 0.0),
|
|
):
|
|
position_parts = separate_xyz(vector=position())
|
|
major_axis = switch(input_type=Switch.InputType.FLOAT, switch=x_major, false=position_parts.y, true=position_parts.x)
|
|
secondary_axis = switch(
|
|
input_type=Switch.InputType.FLOAT,
|
|
switch=x_major,
|
|
false=position_parts.x,
|
|
true=position_parts.y,
|
|
)
|
|
|
|
not_x_major = math(operation=Math.Operation.SUBTRACT, value=(1.0, x_major))
|
|
vertices_x = math(operation=Math.Operation.ADD, value=(2.0, not_x_major))
|
|
vertices_y = math(operation=Math.Operation.ADD, value=(2.0, x_major))
|
|
|
|
tip_amount = math(
|
|
operation=Math.Operation.MULTIPLY,
|
|
value=(
|
|
math(operation=Math.Operation.MULTIPLY, value=(0.5, sharpness)),
|
|
secondary_axis_segment_thickness,
|
|
),
|
|
)
|
|
tip_vector = combine_xyz(
|
|
x=math(operation=Math.Operation.MULTIPLY, value=(x_major, tip_amount)),
|
|
y=math(operation=Math.Operation.MULTIPLY, value=(not_x_major, tip_amount)),
|
|
z=0.0,
|
|
)
|
|
|
|
has_secondary_axis = compare(
|
|
operation=Compare.Operation.NOT_EQUAL,
|
|
data_type=Compare.DataType.FLOAT,
|
|
mode=Compare.Mode.ELEMENT,
|
|
a=secondary_axis,
|
|
b=0.0,
|
|
)
|
|
negative_tip_gate = math(
|
|
operation=Math.Operation.MULTIPLY,
|
|
value=(math(operation=Math.Operation.LESS_THAN, value=(major_axis, 0.0)), has_secondary_axis),
|
|
)
|
|
positive_tip_gate = math(
|
|
operation=Math.Operation.MULTIPLY,
|
|
value=(math(operation=Math.Operation.GREATER_THAN, value=(major_axis, 0.0)), has_secondary_axis),
|
|
)
|
|
negative_tip = vector_math(operation=VectorMath.Operation.MULTIPLY, vector=(-1.0, tip_vector))
|
|
positive_gate_vector = combine_xyz(x=positive_tip_gate, y=positive_tip_gate, z=positive_tip_gate)
|
|
negative_gate_vector = combine_xyz(x=negative_tip_gate, y=negative_tip_gate, z=negative_tip_gate)
|
|
positive_end_offset = vector_math(operation=VectorMath.Operation.MULTIPLY, vector=(negative_tip, positive_gate_vector))
|
|
negative_end_offset = vector_math(operation=VectorMath.Operation.MULTIPLY, vector=(tip_vector, negative_gate_vector))
|
|
total_offset = vector_math(
|
|
operation=VectorMath.Operation.ADD,
|
|
vector=(
|
|
vector_math(operation=VectorMath.Operation.ADD, vector=(offset, positive_end_offset)),
|
|
negative_end_offset,
|
|
),
|
|
)
|
|
|
|
segment = grid(
|
|
size_x=segment_length_along_x,
|
|
size_y=segment_length_along_y,
|
|
vertices_x=vertices_x,
|
|
vertices_y=vertices_y,
|
|
).mesh
|
|
return {"Segment": segment.set_position(offset=total_offset)}
|
|
|
|
|
|
@tree("VG Seven Segments")
|
|
def vg_seven_segments(
|
|
horizontal_segment_size: Float = 2.0,
|
|
horizontal_segment_thickness: Float = 0.5,
|
|
vertical_segment_size: Float = 2.0,
|
|
vertical_segment_thickness: Float = 0.5,
|
|
x_separation: Float = 0.1,
|
|
y_seperation: Float = 0.1,
|
|
tip_sharpness: Float = 1.0,
|
|
):
|
|
half_horizontal = math(operation=Math.Operation.DIVIDE, value=(horizontal_segment_size, 2.0))
|
|
half_vertical = math(operation=Math.Operation.DIVIDE, value=(vertical_segment_size, 2.0))
|
|
negative_half_horizontal = math(operation=Math.Operation.MULTIPLY, value=(-1.0, half_horizontal))
|
|
negative_half_vertical = math(operation=Math.Operation.MULTIPLY, value=(-1.0, half_vertical))
|
|
|
|
vertical_bar_length = math(operation=Math.Operation.SUBTRACT, value=(vertical_segment_size, y_seperation))
|
|
horizontal_bar_length = math(operation=Math.Operation.SUBTRACT, value=(horizontal_segment_size, x_separation))
|
|
|
|
lower_left = vg_create_segment(
|
|
x_major=False,
|
|
segment_length_along_x=vertical_segment_thickness,
|
|
segment_length_along_y=vertical_bar_length,
|
|
secondary_axis_segment_thickness=horizontal_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=negative_half_horizontal, y=negative_half_vertical, z=0.0),
|
|
)
|
|
upper_left = vg_create_segment(
|
|
x_major=False,
|
|
segment_length_along_x=vertical_segment_thickness,
|
|
segment_length_along_y=vertical_bar_length,
|
|
secondary_axis_segment_thickness=horizontal_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=negative_half_horizontal, y=half_vertical, z=0.0),
|
|
)
|
|
lower_right = vg_create_segment(
|
|
x_major=False,
|
|
segment_length_along_x=vertical_segment_thickness,
|
|
segment_length_along_y=vertical_bar_length,
|
|
secondary_axis_segment_thickness=horizontal_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=half_horizontal, y=negative_half_vertical, z=0.0),
|
|
)
|
|
upper_right = vg_create_segment(
|
|
x_major=False,
|
|
segment_length_along_x=vertical_segment_thickness,
|
|
segment_length_along_y=vertical_bar_length,
|
|
secondary_axis_segment_thickness=horizontal_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=half_horizontal, y=half_vertical, z=0.0),
|
|
)
|
|
|
|
bottom = vg_create_segment(
|
|
x_major=True,
|
|
segment_length_along_x=horizontal_bar_length,
|
|
segment_length_along_y=horizontal_segment_thickness,
|
|
secondary_axis_segment_thickness=vertical_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=0.0, y=math(operation=Math.Operation.MULTIPLY, value=(-1.0, vertical_segment_size)), z=0.0),
|
|
)
|
|
middle = vg_create_segment(
|
|
x_major=True,
|
|
segment_length_along_x=horizontal_bar_length,
|
|
segment_length_along_y=horizontal_segment_thickness,
|
|
secondary_axis_segment_thickness=vertical_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=(0.0, 0.0, 0.0),
|
|
)
|
|
top = vg_create_segment(
|
|
x_major=True,
|
|
segment_length_along_x=horizontal_bar_length,
|
|
segment_length_along_y=horizontal_segment_thickness,
|
|
secondary_axis_segment_thickness=vertical_segment_thickness,
|
|
sharpness=tip_sharpness,
|
|
offset=combine_xyz(x=0.0, y=vertical_segment_size, z=0.0),
|
|
)
|
|
dot = vg_create_decimal(
|
|
vertical_segment_size=vertical_segment_size,
|
|
radius=math(operation=Math.Operation.DIVIDE, value=(horizontal_segment_thickness, 2.0)),
|
|
)
|
|
|
|
return {
|
|
"bars": join_geometry(
|
|
geometry=[
|
|
dot,
|
|
top,
|
|
middle,
|
|
bottom,
|
|
upper_right,
|
|
lower_right,
|
|
upper_left,
|
|
lower_left,
|
|
]
|
|
)
|
|
}
|
|
|
|
|
|
@tree("VG Delete Segments")
|
|
def vg_delete_segments(digit: Int = 0, segment_position: Int = 0):
|
|
digit_minus_one = math(operation=Math.Operation.SUBTRACT, value=(digit, 1.0))
|
|
|
|
p01 = _int_equal(segment_position, 0) | _int_equal(segment_position, 1)
|
|
p23 = _int_equal(segment_position, 2) | _int_equal(segment_position, 3)
|
|
p45 = _int_equal(segment_position, 4) | _int_equal(segment_position, 5)
|
|
p67 = _int_equal(segment_position, 6) | _int_equal(segment_position, 7)
|
|
p89 = _int_equal(segment_position, 8) | _int_equal(segment_position, 9)
|
|
p1011 = _int_equal(segment_position, 10) | _int_equal(segment_position, 11)
|
|
p1213 = _int_equal(segment_position, 12) | _int_equal(segment_position, 13)
|
|
p14 = _int_equal(segment_position, 14)
|
|
|
|
d_minus_one = _float_equal(digit_minus_one, -1.0)
|
|
d0 = _float_equal(digit_minus_one, 0.0)
|
|
d1 = _float_equal(digit_minus_one, 1.0)
|
|
d2 = _float_equal(digit_minus_one, 2.0)
|
|
d3 = _float_equal(digit_minus_one, 3.0)
|
|
d4 = _float_equal(digit_minus_one, 4.0)
|
|
d5 = _float_equal(digit_minus_one, 5.0)
|
|
d6 = _float_equal(digit_minus_one, 6.0)
|
|
d7 = _float_equal(digit_minus_one, 7.0)
|
|
d9 = _float_equal(digit_minus_one, 9.0)
|
|
d10 = _float_equal(digit_minus_one, 10.0)
|
|
d11 = _float_equal(digit_minus_one, 11.0)
|
|
|
|
delete_for_minus_one = d_minus_one
|
|
delete_for_zero = d0 & p1011
|
|
delete_for_one = d1 & ~(p45 | p67)
|
|
delete_for_two = d2 & (p23 | p45 | p14)
|
|
delete_for_three = d3 & (p01 | p23 | p14)
|
|
delete_for_four = d4 & (p89 | p1213 | p01 | p14)
|
|
delete_for_five = d5 & (p01 | p67 | p14)
|
|
delete_for_six = d6 & (p67 | p14)
|
|
delete_for_seven = d7 & ~(p1213 | p45 | p67)
|
|
delete_for_nine = d9 & (p01 | p14)
|
|
delete_for_ten = d10 & ~p1011
|
|
delete_for_eleven = d11 & ~p14
|
|
delete_for_decimal = p14 & ~d11
|
|
|
|
return (
|
|
delete_for_eleven
|
|
| delete_for_ten
|
|
| delete_for_minus_one
|
|
| delete_for_zero
|
|
| delete_for_one
|
|
| delete_for_two
|
|
| delete_for_three
|
|
| delete_for_four
|
|
| delete_for_five
|
|
| delete_for_six
|
|
| delete_for_seven
|
|
| delete_for_decimal
|
|
| delete_for_nine
|
|
)
|
|
|
|
|
|
def _finalize_groups():
|
|
import bpy
|
|
|
|
groups = []
|
|
for name in (
|
|
"VG Create Decimal",
|
|
"VG Digit At",
|
|
"VG Next Digit",
|
|
"VG Create Segment",
|
|
"VG Seven Segments",
|
|
"VG Delete Segments",
|
|
):
|
|
group = bpy.data.node_groups.get(name)
|
|
if not group:
|
|
continue
|
|
group.use_fake_user = True
|
|
if hasattr(group, "interface"):
|
|
for item in group.interface.items_tree:
|
|
if item.item_type == "SOCKET" and item.in_out == "INPUT" and item.name == "X Major":
|
|
item.name = "X Major"
|
|
if item.item_type == "SOCKET" and item.in_out == "INPUT" and item.name in {"Radius", "Offset"}:
|
|
item.name = item.name.lower()
|
|
if item.item_type == "SOCKET" and item.in_out == "OUTPUT" and item.name == "Bars":
|
|
item.name = "bars"
|
|
if (
|
|
name == "VG Delete Segments"
|
|
and item.item_type == "SOCKET"
|
|
and item.in_out == "OUTPUT"
|
|
and item.name == "Result"
|
|
):
|
|
item.name = "result"
|
|
groups.append(group)
|
|
return groups
|
|
|
|
|
|
_finalize_groups()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
for group in _finalize_groups():
|
|
print(
|
|
"VG_FIELDVALUE_GROUP",
|
|
group.name,
|
|
len(group.nodes),
|
|
len(group.links),
|
|
sorted(set(node.bl_idname for node in group.nodes)),
|
|
)
|