Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 115 additions & 21 deletions core/sockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import inspect
import sys
from typing import Set
import math

from mathutils import Matrix, Quaternion
import bpy
Expand All @@ -34,7 +35,7 @@
enum_item_4,
get_other_socket, replace_socket,
SIMPLE_DATA_TYPES,
flatten_data, graft_data, map_at_level, wrap_data, unwrap_data)
flatten_data, graft_data, map_at_level, map_recursive, wrap_data, unwrap_data)

from sverchok.settings import get_param

Expand Down Expand Up @@ -120,6 +121,73 @@ def draw(self, context):
if hasattr(context.socket, 'draw_menu_items'):
context.socket.draw_menu_items(context, layout)

class SvAnglesSocket():
DEGREES = 'DEGREES'
RADIANS = 'RADIANS'

angle_modes = [
(DEGREES, "Degrees", "Degrees", 0),
(RADIANS, "Radians", "Radians", 1)
]

def update_degrees(self, context):
if self.skip_angles_mode_update:
return

try:
self.skip_angles_mode_update = True
if self.use_degrees:
self.use_radians = False
finally:
self.skip_angles_mode_update = False

def update_radians(self, context):
if self.skip_angles_mode_update:
return

try:
self.skip_angles_mode_update = True
if self.use_radians:
self.use_degrees = False
finally:
self.skip_angles_mode_update = False

skip_angles_mode_update : BoolProperty(default = False)
use_degrees : BoolProperty(name = "Degrees", default = False, update = update_degrees)
use_radians : BoolProperty(name = "Radians", default = True, update = update_radians)

angles_socket : BoolProperty(name = "Socket for angles", default = False)

internal_angles_unit : EnumProperty(
name = "Internal angles unit",
items = angle_modes,
default = RADIANS)

def process_angles(self, data):
if not self.angles_socket:
return data
if self.internal_angles_unit == SvAnglesSocket.DEGREES and self.use_degrees:
return data
if self.internal_angles_unit == SvAnglesSocket.RADIANS and self.use_radians:
return data
if self.internal_angles_unit == SvAnglesSocket.DEGREES and self.use_radians:
if not self.is_output:
return map_recursive(math.degrees, data)
else:
return map_recursive(math.radians, data)
if self.internal_angles_unit == SvAnglesSocket.RADIANS and self.use_degrees:
if not self.is_output:
return map_recursive(math.radians, data)
else:
return map_recursive(math.degrees, data)
return data

def draw_angle_options(self, context, layout):
if not self.angles_socket:
return
layout.prop(self, 'use_degrees')
layout.prop(self, 'use_radians')

class SvSocketProcessing():
"""
Mixin class for data processing logic of a socket.
Expand Down Expand Up @@ -290,6 +358,9 @@ def postprocess_output(self, data):
result = wrap_data(result)
return result

def is_show_menu(self):
return self.is_output

def has_simplify_modes(self, context):
return self.can_flatten() or self.can_simplify()

Expand All @@ -298,7 +369,7 @@ def has_menu(self, context):

def draw_menu_button(self, context, layout, node, text):
if hasattr(node.id_data, 'sv_show_socket_menus') and node.id_data.sv_show_socket_menus:
if (self.is_output or self.is_linked or not self.use_prop):
if (self.is_show_menu() or self.is_linked or not self.use_prop):
layout.menu('SV_MT_SocketOptionsMenu', text='', icon='TRIA_DOWN')

def draw_menu_items(self, context, layout):
Expand Down Expand Up @@ -429,25 +500,29 @@ def sv_get(self, default=..., deepcopy=True):
:param deepcopy: in most cases should be False for efficiency but not in cases if input data will be modified
:return: data bound to the socket
"""
if self.is_output:
return sv_get_socket(self, False)
def _get():
if self.is_output:
return sv_get_socket(self, False)

if self.is_linked:
return sv_get_socket(self, deepcopy)
if self.is_linked:
return sv_get_socket(self, deepcopy)

prop_name = self.get_prop_name()
if prop_name:
prop = getattr(self.node, prop_name)
return format_bpy_property(prop)
prop_name = self.get_prop_name()
if prop_name:
prop = getattr(self.node, prop_name)
return format_bpy_property(prop)

if self.use_prop and hasattr(self, 'default_property') and self.default_property is not None:
default_property = self.default_property
return format_bpy_property(default_property)
if self.use_prop and hasattr(self, 'default_property') and self.default_property is not None:
default_property = self.default_property
return format_bpy_property(default_property)

if default is not ...:
return default
if default is not ...:
return default
raise SvNoDataError(self)

raise SvNoDataError(self)
result = _get()
result = self.preprocess_input(result)
return result

def sv_set(self, data):
"""Set data, provide context in case the node can be evaluated several times in different context"""
Expand Down Expand Up @@ -523,6 +598,10 @@ def draw_label(text):

menu_option = get_param('show_input_menus', 'QUICKLINK')

if not self.is_output:
if self.has_menu(context):
self.draw_menu_button(context, layout, node, text)

# just handle custom draw..be it input or output.
if self.custom_draw:
# does the node have the draw function referred to by
Expand Down Expand Up @@ -565,8 +644,9 @@ def draw_label(text):
self.draw_link_input_menu(context, layout, node)
draw_label(self.label or text)

if self.has_menu(context):
self.draw_menu_button(context, layout, node, text)
if self.is_output:
if self.has_menu(context):
self.draw_menu_button(context, layout, node, text)

# https://wiki.blender.org/wiki/Reference/Release_Notes/4.0/Python_API#Node_Groups
if bpy.app.version >= (4, 0):
Expand Down Expand Up @@ -879,7 +959,7 @@ def draw(self, context, layout, node, text):
layout.label(text="——————")


class SvStringsSocket(SocketDomain, NodeSocket, SvSocketCommon):
class SvStringsSocket(SocketDomain, NodeSocket, SvSocketCommon, SvAnglesSocket):
'''Generic, mostly numbers, socket type'''
bl_idname = "SvStringsSocket"
bl_label = "Strings Socket"
Expand All @@ -895,6 +975,10 @@ def get_mode_flags(self):
flags = super().get_mode_flags()
if self.use_graft_2:
flags.append('G2')
if self.use_radians:
flags.append('RAD')
if self.use_degrees:
flags.append('DEG')
return flags

def get_prop_data(self):
Expand All @@ -907,6 +991,13 @@ def get_prop_data(self):
else:
return {}

def is_show_menu(self):
return super().is_show_menu() or self.angles_socket

def has_menu(self,context):
r = super().has_menu(context) or self.angles_socket
return r

quick_link_to_node: StringProperty() # this can be overridden by socket instances

default_property_type: bpy.props.EnumProperty( # for internal usage
Expand Down Expand Up @@ -974,6 +1065,7 @@ def draw_property(self, layout, prop_origin=None, prop_name=None):
row.operator(SvSwitchDefaultOp.bl_idname, icon=icon, text='')

def draw_menu_items(self, context, layout):
self.draw_angle_options(context, layout)
self.draw_simplify_modes(layout)
if self.can_flatten_topology():
layout.prop(self, 'use_flatten_topology')
Expand Down Expand Up @@ -1009,10 +1101,11 @@ def to_zero_base(lst):

def preprocess_input(self, data):
result = data
result = self.process_angles(result)
if self.use_flatten:
result = self.do_flatten(data)
result = self.do_flatten(result)
elif self.use_simplify:
result = self.do_simplify(data)
result = self.do_simplify(result)
if self.use_graft:
result = self.do_graft(result)
elif not self.use_flatten and self.use_graft_2:
Expand All @@ -1025,6 +1118,7 @@ def preprocess_input(self, data):

def postprocess_output(self, data):
result = data
result = self.process_angles(result)

if self.use_flatten_topology:
result = self.do_flat_topology(data)
Expand Down
8 changes: 6 additions & 2 deletions nodes/surface/revolution_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ def sv_init(self, context):
p = self.inputs.new('SvVerticesSocket', "Direction")
p.use_prop = True
p.default_property = (0.0, 0.0, 1.0)
self.inputs.new('SvStringsSocket', 'AngleFrom').prop_name = 'v_min'
self.inputs.new('SvStringsSocket', 'AngleTo').prop_name = 'v_max'
p = self.inputs.new('SvStringsSocket', 'AngleFrom')
p.prop_name = 'v_min'
p.angles_socket = True
p = self.inputs.new('SvStringsSocket', 'AngleTo')
p.prop_name = 'v_max'
p.angles_socket = True
self.outputs.new('SvSurfaceSocket', "Surface")
# default for newly created nodes
self.origin = 'POINT'
Expand Down