Skip to content

Commit

Permalink
remove curvemapper from snlite (#4162)
Browse files Browse the repository at this point in the history
* remove curvemapper from snlite

* using self.info

* remove a few prints

* use fstrings

* no need to hasattr

* less info

* use debug

* memo

* complete > comment

* function is no longer called

* remove unused imports

* these functions are no longer needed in snlite

* prepare for new directive

* typo

* info <- print

* postpone error reporting.. or execution

* reorder test for unregister

* Revert registration order

* try >

* fix logic >

* seems ok

* seems ok

* seems ok

* forgot to pass from self

* typo

* remix logic

* maybe

* printing only if execution_ends_early

* use default to get content from socket

* remove some debug prints

* confirm it works. but i might remove for now

* use default

* remove print
  • Loading branch information
zeffii committed Jun 12, 2021
1 parent 925540f commit da35f41
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 222 deletions.
2 changes: 1 addition & 1 deletion json_examples/Shapes/Concave_sverchok.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
"params": {
"n_id": "-9215397972143259885",
"script_name": "concave",
"script_str": "\"\"\"\nin vertices_in v\nin alpha_in s\nout vertices_out v\nout edges_out s\nout faces_out s\n\"\"\"\n\nfrom scipy.spatial import Delaunay\nimport numpy as np\nfrom collections import defaultdict\n\nfrom sverchok.data_structure import zip_long_repeat\n\ndef alpha_shape_3D(pos, alpha):\n \"\"\"\n Compute the alpha shape (concave hull) of a set of 3D points.\n Parameters:\n pos - np.array of shape (n,3) points.\n alpha - alpha value.\n return\n outer surface vertex indices, edge indices, and triangle indices\n \"\"\"\n\n tetra = Delaunay(pos)\n # Find radius of the circumsphere.\n # By definition, radius of the sphere fitting inside the tetrahedral needs \n # to be smaller than alpha value\n # http://mathworld.wolfram.com/Circumsphere.html\n tetrapos = np.take(pos,tetra.vertices,axis=0)\n normsq = np.sum(tetrapos**2,axis=2)[:,:,None]\n ones = np.ones((tetrapos.shape[0],tetrapos.shape[1],1))\n a = np.linalg.det(np.concatenate((tetrapos,ones),axis=2))\n Dx = np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[1,2]],ones),axis=2))\n Dy = -np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[0,2]],ones),axis=2))\n Dz = np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[0,1]],ones),axis=2))\n c = np.linalg.det(np.concatenate((normsq,tetrapos),axis=2))\n r = np.sqrt(Dx**2+Dy**2+Dz**2-4*a*c)/(2*np.abs(a))\n\n # Find tetrahedrals\n tetras = tetra.simplices[r<alpha,:]\n # triangles\n TriComb = np.array([(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)])\n Triangles = tetras[:,TriComb].reshape(-1,3)\n Triangles = np.sort(Triangles,axis=1)\n # Remove triangles that occurs twice, because they are within shapes\n TrianglesDict = defaultdict(int)\n for tri in Triangles:TrianglesDict[tuple(tri)] += 1\n Triangles=np.array([tri for tri in TrianglesDict if TrianglesDict[tri] ==1])\n #edges\n EdgeComb=np.array([(0, 1), (0, 2), (1, 2)])\n Edges=Triangles[:,EdgeComb].reshape(-1,2)\n Edges=np.sort(Edges,axis=1)\n Edges=np.unique(Edges,axis=0)\n\n Vertices = np.unique(Edges)\n return Vertices,Edges,Triangles\n\nvertices_out = []\nedges_out = []\nfaces_out = []\n\nfor vertices, alpha in zip_long_repeat(vertices_in, alpha_in):\n if isinstance(alpha, (list, tuple)):\n alpha = alpha[0]\n\n _, new_edges, new_faces = alpha_shape_3D(vertices, alpha)\n #print(new_vertices)\n new_vertices = vertices\n\n vertices_out.append(new_vertices)\n edges_out.append(new_edges.tolist())\n faces_out.append(new_faces.tolist())"
"script_str": "\"\"\"\n>in vertices_in v\n>in alpha_in s\nout vertices_out v\nout edges_out s\nout faces_out s\n\"\"\"\n\nfrom scipy.spatial import Delaunay\nimport numpy as np\nfrom collections import defaultdict\n\nfrom sverchok.data_structure import zip_long_repeat\n\ndef alpha_shape_3D(pos, alpha):\n \"\"\"\n Compute the alpha shape (concave hull) of a set of 3D points.\n Parameters:\n pos - np.array of shape (n,3) points.\n alpha - alpha value.\n return\n outer surface vertex indices, edge indices, and triangle indices\n \"\"\"\n\n tetra = Delaunay(pos)\n # Find radius of the circumsphere.\n # By definition, radius of the sphere fitting inside the tetrahedral needs \n # to be smaller than alpha value\n # http://mathworld.wolfram.com/Circumsphere.html\n tetrapos = np.take(pos,tetra.vertices,axis=0)\n normsq = np.sum(tetrapos**2,axis=2)[:,:,None]\n ones = np.ones((tetrapos.shape[0],tetrapos.shape[1],1))\n a = np.linalg.det(np.concatenate((tetrapos,ones),axis=2))\n Dx = np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[1,2]],ones),axis=2))\n Dy = -np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[0,2]],ones),axis=2))\n Dz = np.linalg.det(np.concatenate((normsq,tetrapos[:,:,[0,1]],ones),axis=2))\n c = np.linalg.det(np.concatenate((normsq,tetrapos),axis=2))\n r = np.sqrt(Dx**2+Dy**2+Dz**2-4*a*c)/(2*np.abs(a))\n\n # Find tetrahedrals\n tetras = tetra.simplices[r<alpha,:]\n # triangles\n TriComb = np.array([(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)])\n Triangles = tetras[:,TriComb].reshape(-1,3)\n Triangles = np.sort(Triangles,axis=1)\n # Remove triangles that occurs twice, because they are within shapes\n TrianglesDict = defaultdict(int)\n for tri in Triangles:TrianglesDict[tuple(tri)] += 1\n Triangles=np.array([tri for tri in TrianglesDict if TrianglesDict[tri] ==1])\n #edges\n EdgeComb=np.array([(0, 1), (0, 2), (1, 2)])\n Edges=Triangles[:,EdgeComb].reshape(-1,2)\n Edges=np.sort(Edges,axis=1)\n Edges=np.unique(Edges,axis=0)\n\n Vertices = np.unique(Edges)\n return Vertices,Edges,Triangles\n\nvertices_out = []\nedges_out = []\nfaces_out = []\n\nfor vertices, alpha in zip_long_repeat(vertices_in, alpha_in):\n if isinstance(alpha, (list, tuple)):\n alpha = alpha[0]\n\n _, new_edges, new_faces = alpha_shape_3D(vertices, alpha)\n #print(new_vertices)\n new_vertices = vertices\n\n vertices_out.append(new_vertices)\n edges_out.append(new_edges.tolist())\n faces_out.append(new_faces.tolist())"
},
"use_custom_color": true,
"width": 140.0
Expand Down
2 changes: 1 addition & 1 deletion json_examples/Shapes/Tie_revange_2020.json
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@
"properties": {
"n_id": "-8503949147017355656",
"script_name": "Tie_Instructions",
"script_str": "from sverchok.utils.geom import LinearSpline, CubicSpline\nfrom sverchok.utils.math import supported_metrics\nfrom sverchok.utils.curve import SvSplineCurve\n\n\"\"\"\nin numbr s d=[[]] n=0\nout splin C\nout verts v\n\"\"\"\n\n# '''use note node to define toe\n# l - left, r - right, t - top,\n# bake, convert to curve and\n# extrude 0.3\n# Start always from l finish with t\n# and finish inside out\n# use live_curve script \n# to materialize curve to tie\n# Nikitron, 2014'''\n\n\nout = [ \n (0, 0.2, -5),\n (0, 0.2, -3),\n (0, 0.2, 0),\n (1, 0.2, 1),\n (3, 5, 2),\n (0, 7, 2),\n (-3, 5, 2),\n (-1, 0.5, 1) ]\nfront = True\n\nvecs = [(0.8660254037844386, 0.0, -0.5),\n (0,0,1),\n (-0.8660254037844386, 0.0, -0.5)]\nif numbr:\n n_ = numbr[0][0].split(' ')\n print('default letters: ',n_)\n for k, i in enumerate(n_):\n if i[0] == 'l':\n i = 0\n elif i[0] == 't':\n i = 1\n elif i[0] == 'r':\n i = 2\n v = vecs[i]\n if front:\n front = False\n y1 = -0.015\n y2 = 0.015\n else:\n front = True\n y1 = 0.015\n y2 = -0.015\n out.append([v[0]*k*0.05+v[0],\n y1*(k+1),\n v[2]*k*0.05+v[2]])\n out.append([v[0]*k*0.05+v[0],\n y2*(k+1),\n v[2]*k*0.05+v[2]])\n out.extend([\n (0, -0.4,-1),\n (0, -0.2,-3),\n (0, 0,-10)])\n\nspline = CubicSpline(out, metric = 'CHEBYSHEV', is_cyclic = False)\ncurve = SvSplineCurve(spline)\nverts=[out]\n\nsplin = [curve]\n"
"script_str": "from sverchok.utils.geom import LinearSpline, CubicSpline\nfrom sverchok.utils.math import supported_metrics\nfrom sverchok.utils.curve import SvSplineCurve\n\n\"\"\"\nin numbr s d=[[]] n=0\nout splin C\nout verts v\n\"\"\"\n\n# '''use note node to define toe\n# l - left, r - right, t - top,\n# bake, convert to curve and\n# extrude 0.3\n# Start always from l finish with t\n# and finish inside out\n# use live_curve script \n# to materialize curve to tie\n# Nikitron, 2014'''\n\n\nout = [ \n (0, 0.2, -5),\n (0, 0.2, -3),\n (0, 0.2, 0),\n (1, 0.2, 1),\n (3, 5, 2),\n (0, 7, 2),\n (-3, 5, 2),\n (-1, 0.5, 1) ]\nfront = True\n\nvecs = [(0.8660254037844386, 0.0, -0.5),\n (0,0,1),\n (-0.8660254037844386, 0.0, -0.5)]\nif numbr and numbr[0]:\n n_ = numbr[0][0].split(' ')\n print('default letters: ',n_)\n for k, i in enumerate(n_):\n if i[0] == 'l':\n i = 0\n elif i[0] == 't':\n i = 1\n elif i[0] == 'r':\n i = 2\n v = vecs[i]\n if front:\n front = False\n y1 = -0.015\n y2 = 0.015\n else:\n front = True\n y1 = 0.015\n y2 = -0.015\n out.append([v[0]*k*0.05+v[0],\n y1*(k+1),\n v[2]*k*0.05+v[2]])\n out.append([v[0]*k*0.05+v[0],\n y2*(k+1),\n v[2]*k*0.05+v[2]])\n out.extend([\n (0, -0.4,-1),\n (0, -0.2,-3),\n (0, 0,-10)])\n\nspline = CubicSpline(out, metric = 'CHEBYSHEV', is_cyclic = False)\ncurve = SvSplineCurve(spline)\nverts=[out]\n\nsplin = [curve]\n"
},
"inputs": {
"numbr": {
Expand Down
25 changes: 0 additions & 25 deletions node_scripts/SNLite_templates/bpy_stuff/UI_curves_manual.py

This file was deleted.

25 changes: 0 additions & 25 deletions node_scripts/SNLite_templates/demo/draw_override_complex.py

This file was deleted.

4 changes: 2 additions & 2 deletions nodes/analyzer/area.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ def draw_buttons(self, context, layout):

def process(self):
inputs = self.inputs
Vertices = inputs["Vertices"].sv_get()
Polygons = inputs["Polygons"].sv_get()
Vertices = inputs["Vertices"].sv_get(default=None)
Polygons = inputs["Polygons"].sv_get(default=None)

outputs = self.outputs
if not outputs['Area'].is_linked or not all([Vertices, Polygons]):
Expand Down
92 changes: 50 additions & 42 deletions nodes/script/script1_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@

from sverchok.utils.sv_update_utils import sv_get_local_path
from sverchok.utils.snlite_importhelper import (
UNPARSABLE, set_autocolor, parse_sockets, are_matched,
get_rgb_curve, set_rgb_curve
)
UNPARSABLE, set_autocolor, parse_sockets, are_matched)

from sverchok.utils.snlite_utils import vectorize, ddir
from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata, pydata_from_bmesh
from sverchok.node_tree import SverchCustomTreeNode
Expand Down Expand Up @@ -252,7 +251,7 @@ def add_prop_to_socket(self, socket, default_value):
socket.use_prop = False

except:
print('some failure in the add_props_to_sockets function. ouch.')
self.info('some failure in the add_props_to_sockets function. ouch.')

self.halt_updates = False

Expand All @@ -274,7 +273,7 @@ def update_sockets(self):
continue

if not self.add_or_update_sockets(k, v):
print('failed to load sockets for ', k)
self.info(f'failed to load sockets for {k}')
return

self.flush_excess_sockets(k, v)
Expand All @@ -298,12 +297,10 @@ def load(self):
text = self.get_bpy_data_from_name(self.script_name, bpy.data.texts)
if text and hasattr(text, "as_string"):
self.script_str = text.as_string()
# if isinstance(text, str):
# self.script_str = text
else:
print(f'bpy.data.texts not read yet, self.script_name="{self.script_name}"')
self.info(f'bpy.data.texts not read yet, self.script_name="{self.script_name}"')
if self.script_str:
print('but script loaded locally anyway.')
self.info('but script loaded locally anyway.')

if self.update_sockets():
self.injected_state = False
Expand Down Expand Up @@ -339,7 +336,7 @@ def make_new_locals(self):
# make inputs local, do function with inputs, return outputs if present
ND = self.node_dict.get(hash(self))
if not ND:
print('hash invalidated')
self.info('hash invalidated')
self.injected_state = False
self.update_sockets()
ND = self.node_dict.get(hash(self))
Expand Down Expand Up @@ -369,6 +366,7 @@ def make_new_locals(self):
def get_node_from_function_name(self, func_name):
"""
this seems to get enough info for a snlite stateful setup function.
"node" here refers to a node/function in the self.script_str after being parsed
"""
tree = ast.parse(self.script_str)
Expand Down Expand Up @@ -441,6 +439,13 @@ def process_script(self):
if self.inject_params:
locals().update({'parameters': [__local__dict__.get(s.name) for s in self.inputs]})

if socket_info['inputs_required']:
# if not fully connected do not raise.
# should inform the user that the execution was halted because not
# enough input was provided for the script to do anything useful.
if not self.socket_requirements_met(socket_info):
return

exec(self.script_str, locals(), locals())

for idx, _socket in enumerate(self.outputs):
Expand All @@ -449,16 +454,42 @@ def process_script(self):

set_autocolor(self, True, READY_COLOR)


except Exception as err:

print("Unexpected error:", sys.exc_info()[0])

self.info(f"Unexpected error: {sys.exc_info()[0]}")
exc_type, exc_value, exc_traceback = sys.exc_info()
lineno = traceback.extract_tb(exc_traceback)[-1][1]
print('on line: ', lineno)
self.info(f'on line: {lineno}')

show = traceback.print_exception
show(exc_type, exc_value, exc_traceback, limit=6, file=sys.stdout)
if hasattr(self, "snlite_raise_exception") and self.snlite_raise_exception:
raise # SNLITE_EXCEPTION(sys.exc_info()[2]) from err

if self.snlite_raise_exception:
raise

def socket_requirements_met(self, socket_info):
required_count = 0
requirements = socket_info['inputs_required']
for socket_name in requirements:
if self.inputs.get(socket_name):
obtained_data = self.inputs[socket_name].sv_get(default=None)
# print(f"{obtained_data} from {socket_name}")
if obtained_data is None:
continue
try:
if obtained_data and obtained_data[0]:
required_count += 1
except:
...

requirements_met = required_count == len(requirements)
if requirements_met:
return True

self.info(f"end execution early because required sockets are not connected {requirements}")


def custom_draw(self, context, layout):
tk = self.node_dict.get(hash(self))
Expand Down Expand Up @@ -506,9 +537,8 @@ def draw_buttons_ext(self, _, layout):
box = layout.box()
r = box.row()
r.label(text="extra snlite features")
if hasattr(self, "snlite_raise_exception"):
r = box.row()
r.prop(self, "snlite_raise_exception", toggle=True, text="raise errors to tree level")
r = box.row()
r.prop(self, "snlite_raise_exception", toggle=True, text="raise errors to tree level")



Expand All @@ -517,14 +547,6 @@ def draw_buttons_ext(self, _, layout):
def save_to_json(self, node_data: dict):
texts = bpy.data.texts

data_list = node_data.get('snlite_ui')
if data_list:
# self.node_dict[hash(self)]['sockets']['snlite_ui'] = ui_elements
for data_json_str in data_list:
data_dict = json.loads(data_json_str)
if data_dict['bl_idname'] == 'ShaderNodeRGBCurve':
set_rgb_curve(data_dict)

includes = node_data.get('includes')
if includes:
for include_name, include_content in includes.items():
Expand Down Expand Up @@ -570,13 +592,13 @@ def load_from_json(self, node_data: dict, import_version: float):
elif script_name and (script_name in texts):
# This was added to fix existing texts with the same name but no / different content.
if texts[script_name].as_string() == script_content:
self.debug("SN skipping text named `%s' - their content are the same", script_name)
self.debug(f'SN skipping text named "{script_name}" - their content are the same')
else:
self.info("SN text named `%s' already found in current, but content differs", script_name)
self.info(f'SN text named "{script_name}" already found, but content differs')
new_text = texts.new(script_name)
new_text.from_string(script_content)
script_name = new_text.name
self.info('SN text named replaced with %s', script_name)
self.info(f'SN text named replaced with "{script_name}"')

self.script_name = script_name
self.script_str = script_content
Expand All @@ -589,20 +611,6 @@ def load_from_json(self, node_data: dict, import_version: float):
self.make_new_locals()

storage = self.node_dict[hash(self)]['sockets']

ui_info = storage['snlite_ui']
node_data['snlite_ui'] = []
print(ui_info)
for _, info in enumerate(ui_info):
mat_name = info['mat_name']
node_name = info['node_name']
bl_idname = info['bl_idname']
if bl_idname == 'ShaderNodeRGBCurve':
data = get_rgb_curve(mat_name, node_name)
print(data)
data_json_str = json.dumps(data)
node_data['snlite_ui'].append(data_json_str)

includes = storage['includes']
if includes:
node_data['includes'] = {}
Expand Down
Loading

0 comments on commit da35f41

Please sign in to comment.