From cdf3a8f98e34a15acd846df4f3a6eb7766b69a74 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Sun, 3 May 2020 13:30:12 +0200 Subject: [PATCH 01/12] view 2d node - path mode --- index.md | 1 + nodes/viz/viewer2d.py | 292 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 nodes/viz/viewer2d.py diff --git a/index.md b/index.md index 347e7ff3a..75b8055f5 100644 --- a/index.md +++ b/index.md @@ -404,6 +404,7 @@ SvTextureViewerNodeLite SvWaveformViewer SvConsoleNode + SvViewer2D ## Text ViewerNodeTextMK3 diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py new file mode 100644 index 000000000..95ab925dd --- /dev/null +++ b/nodes/viz/viewer2d.py @@ -0,0 +1,292 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +from mathutils import Vector +import bpy +from bpy.props import FloatProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty + +import blf +import bgl +import gpu +from gpu_extras.batch import batch_for_shader + +from sverchok.utils.context_managers import sv_preferences +from sverchok.core.socket_data import SvGetSocketInfo +from sverchok.data_structure import updateNode, node_id, enum_item_4, fullList, match_long_repeat +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.ui import bgl_callback_nodeview as nvBGL + +# star imports easing_dict and all easing functions. +from sverchok.utils.sv_easing_functions import * + +easing_list = [] +for k in sorted(easing_dict.keys()): + fname = easing_dict[k].__name__ + easing_list.append(tuple([str(k), fname, "", k])) + + +palette_dict = { + "default": ( + (0.243299, 0.590403, 0.836084, 1.00), # back_color + (0.390805, 0.754022, 1.000000, 0.70), # grid_color + (1.000000, 0.330010, 0.107140, 1.00) # line_color + ), + "scope": ( + (0.274677, 0.366253, 0.386430, 1.00), # back_color + (0.423268, 0.558340, 0.584078, 1.00), # grid_color + (0.304762, 1.000000, 0.062827, 1.00) # line_color + ), + "sniper": ( + (0.2, 0.2, 0.2, 0.20), # back_color + (0.423268, 0.558340, 0.584078, 0.40), # grid_color + (0.304762, 1.000000, 0.062827, 1.00) # line_color + ) +} + + +def simple28_grid_xy(x, y, args): + """ x and y are passed by default so you could add font content """ + + geom, config = args + back_color, grid_color, line_color = config.palette + background_color = config.background_color + # draw background, this could be cached...... + shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') + batch = batch_for_shader(shader, 'TRIS', {"pos": geom.background_coords}, indices=geom.background_indices) + shader.bind() + shader.uniform_float("color", background_color) + batch.draw(shader) + + # draw grid and graph + config.batch.draw(config.shader) + + + +class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): + '''Curved interpolation''' + bl_idname = 'SvViewer2D' + bl_label = 'Viewer 2D' + sv_icon = 'SV_EASING' + + n_id: StringProperty(default='') + + activate: BoolProperty( + name='Show', description='Activate drawing', + default=True, update=updateNode + ) + cycle: BoolProperty( + name='Cycle', description='Activate drawing', + default=True, update=updateNode + ) + + selected_mode: EnumProperty( + items=easing_list, description="Set easing Function to:", + default="0", update=updateNode + ) + + in_float: FloatProperty( + min=0.0, max=1.0, default=0.0, name='Float Input', + description='input to the easy function', update=updateNode + ) + draw_scale: FloatProperty( + min=0.0, default=10.0, name='Scale', + description='Drawing Scale', update=updateNode + ) + unit_color: FloatVectorProperty( + update=updateNode, name='', default=(.9, .9, .8, 1.0), + size=4, min=0.0, max=1.0, subtype='COLOR' + ) + background_color: FloatVectorProperty( + update=updateNode, name='', default=(.1, .1, .1, 1.0), + size=4, min=0.0, max=1.0, subtype='COLOR' + ) + selected_theme_mode: EnumProperty( + items=enum_item_4(["default", "scope", "sniper"]), default="default", update=updateNode + ) + + def custom_draw_socket(self, socket, context, l): + info = socket.get_socket_info() + + r = l.row(align=True) + split = r.split(factor=0.85) + r1 = split.row(align=True) + r1.prop(self, "selected_mode", text="") + r1.prop(self, 'activate', icon='NORMALIZE_FCURVES', text="") + if info: + r2 = split.row() + r2.label(text=info) + def draw_buttons(self, context, layout): + r0 = layout.row() + r0.prop(self, "activate", text="", icon="HIDE_" + ("OFF" if self.activate else "ON")) + c0 = layout.column(align=True) + c0.prop(self, "background_color") + c0.prop(self, "draw_scale") + layout.prop(self, "cycle") + + def draw_buttons_ext(self, context, l): + l.prop(self, "selected_theme_mode") + + def sv_init(self, context): + self.inputs.new('SvVerticesSocket', "Vecs") + self.inputs.new('SvColorSocket', "Color").custom_draw = 'draw_color_socket' + self.get_and_set_gl_scale_info() + + def draw_color_socket(self, socket, context, layout): + if not socket.is_linked: + layout.prop(self, 'unit_color', text="") + + else: + layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) + + def get_drawing_attributes(self): + """ + adjust render location based on preference multiplier setting + """ + x, y = [int(j) for j in (Vector(self.absolute_location) + Vector((self.width + 20, 0)))[:]] + + try: + with sv_preferences() as prefs: + multiplier = prefs.render_location_xy_multiplier + scale = prefs.render_scale + except: + # print('did not find preferences - you need to save user preferences') + multiplier = 1.0 + scale = 1.0 + x, y = [x * multiplier, y * multiplier] + + return x, y, scale, multiplier + + def generate_shader(self, geom): + shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + batch = batch_for_shader(shader, 'LINES', {"pos": geom.vertices, "color": geom.vertex_colors}, indices=geom.indices) + return batch, shader + + def generate_graph_geom(self, config, paths): + + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + back_color, grid_color, line_color = config.palette + cycle = config.cycle + sys_scale = config.sys_scale + background_color = config.background_color + line_color = config.line_color + # if len(line_color) > 1: + # line_color= [c for color in line_color for c in color] + # easing_func = config.easing_func + all_vecs = [v for vecs in paths for v in vecs ] + maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) + # background geom + w = size + h = size + w = (maxmin[0][0]- maxmin[0][1]) * scale + h = (maxmin[1][0]- maxmin[1][1]) * scale + margin = 1 * scale + margin = 10 * sys_scale + geom.background_coords = [ + (x, y + margin), + (x + w+2*margin, y+ margin), + (w + x + 2*margin, y - h - margin), + (x, y - h-margin)] + geom.background_indices = [(0, 1, 2), (0, 2, 3)] + + # grid geom and associated vertex colors + num_divs = 8 + offset = size / num_divs + + vertices = [] + vertex_colors = [] + indices = [] + + idx_offset = 0 + for vecs, col in zip(paths, line_color): + graphline = [] + for v in vecs: + _px = x + (v[0] - maxmin[0][1]) * scale + margin + _py = y + (v[1] - maxmin[1][0]) * scale + graphline.append([_px, _py]) + vertex_colors.append(col) + vertices.extend(graphline) + + for i in range(len(vecs)-1): + indices.append([i + idx_offset, i + 1 + idx_offset]) + if cycle: + indices.append([len(graphline)-1 + idx_offset,0 + idx_offset]) + idx_offset += len(graphline) + + geom.vertices = vertices + geom.vertex_colors = vertex_colors + geom.indices = indices + return geom + + def process(self): + p = self.inputs['Vecs'].sv_get() + path_color = self.inputs['Color'].sv_get(default=[[self.unit_color]])[0] + fullList(path_color, len(p)) + n_id = node_id(self) + + # end early + nvBGL.callback_disable(n_id) + + if self.activate: + + config = lambda: None + x, y, scale, multiplier = self.get_drawing_attributes() + + config.loc = (x, y) + config.palette = palette_dict.get(self.selected_theme_mode)[:] + config.sys_scale = scale + config.scale = scale*self.draw_scale + config.cycle = self.cycle + config.background_color = self.background_color + config.line_color = path_color + # config.easing_func = easing_func + + geom = self.generate_graph_geom(config, p) + config.batch, config.shader = self.generate_shader(geom) + + draw_data = { + 'mode': 'custom_function', + 'tree_name': self.id_data.name[:], + 'loc': (x, y), + 'custom_function': simple28_grid_xy, + 'args': (geom, config) + } + nvBGL.callback_enable(n_id, draw_data) + + def sv_free(self): + nvBGL.callback_disable(node_id(self)) + + def sv_copy(self, node): + # reset n_id on copy + self.n_id = '' + + def sv_update(self): + # handle disconnecting sockets, also disconnect drawing to view? + if not ("Float" in self.inputs): + return + try: + if not self.inputs[0].other: + nvBGL.callback_disable(node_id(self)) + except: + print('Easing node update holdout (not a problem)') + + +classes = [SvViewer2D,] +register, unregister = bpy.utils.register_classes_factory(classes) -- GitLab From a2e0f456a5dcf5456b3e249580e85ccaa39f9ca6 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Mon, 4 May 2020 02:59:12 +0200 Subject: [PATCH 02/12] number mode --- nodes/viz/viewer2d.py | 134 +++++++++++++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 22 deletions(-) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 95ab925dd..15468e9f9 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -18,7 +18,7 @@ from mathutils import Vector import bpy -from bpy.props import FloatProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty +from bpy.props import FloatProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty import blf import bgl @@ -76,6 +76,64 @@ def simple28_grid_xy(x, y, args): config.batch.draw(config.shader) +def generate_number_geom(config, numbers): + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + # back_color, grid_color, line_color = config.palette + cycle = config.cycle + sys_scale = config.sys_scale + line_color = config.line_color + w, h = config.size + all_numbers = [n for l in numbers for n in l ] + maxmin = [max(all_numbers), min(all_numbers)] + # background geom + # w = size + # h = size + # w = (maxmin[0][0]- maxmin[0][1]) * scale + # h = (maxmin[1][0]- maxmin[1][1]) * scale + margin = 1 * scale + margin = 10 * sys_scale + geom.background_coords = [ + (x, y + margin), + (x + w + 2*margin, y + margin), + (w + x + 2*margin, y - h - margin), + (x, y - h - margin)] + geom.background_indices = [(0, 1, 2), (0, 2, 3)] + + vertices = [] + vertex_colors = [] + indices = [] + num_height = h/(max(all_numbers)- min(all_numbers)) + idx_offset = 0 + if config.continuous: + for nums, col in zip(numbers, line_color): + num_width = w/(len(nums)-1) + for i, n in enumerate(nums): + _px = x + (i * num_width) * sys_scale + margin + _py = y + ((n -maxmin[1])* num_height) * sys_scale - h + vertices.append([_px, _py]) + vertex_colors.append(col) + for i in range(len(nums)-1): + indices.append([i + idx_offset, i + 1 + idx_offset]) + idx_offset += len(nums) + else: + for nums, col in zip(numbers, line_color): + num_width = w/len(nums) + for i, n in enumerate(nums): + _px = x + (i * num_width) * sys_scale + margin + _py = y + ((n -maxmin[1])* num_height) * sys_scale - h + vertices.extend([[_px, _py], [_px + num_width, _py]]) + vertex_colors.extend([col, col]) + indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) + idx_offset += 2*len(nums) + + + geom.vertices = vertices + geom.vertex_colors = vertex_colors + geom.indices = indices + return geom class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): '''Curved interpolation''' @@ -83,8 +141,22 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): bl_label = 'Viewer 2D' sv_icon = 'SV_EASING' + modes = [ + ('Number', 'Number', 'Input UV coordinates to evaluate texture', '', 1), + ('Path', 'Path', 'Matrix to apply to verts before evaluating texture', '', 2), + ('Edges', 'Edges', 'Matrix of texture (External Object matrix)', '', 3), + ('Polygons', 'Polygons', 'Matrix of texture (External Object matrix)', '', 3), + + ] n_id: StringProperty(default='') + mode: EnumProperty( + name='Mode', + items=modes, + default='Path', + description="Display Mode", + update=updateNode) + activate: BoolProperty( name='Show', description='Activate drawing', default=True, update=updateNode @@ -107,12 +179,20 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): min=0.0, default=10.0, name='Scale', description='Drawing Scale', update=updateNode ) + drawing_size: IntVectorProperty( + update=updateNode, name='Size', default=(150, 150), + size=2 + ) + continuous: BoolProperty( + name='Continuous', description='Continuous Graph', + default=True, update=updateNode + ) unit_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) background_color: FloatVectorProperty( - update=updateNode, name='', default=(.1, .1, .1, 1.0), + update=updateNode, name='', default=(.05, .05, .05, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) selected_theme_mode: EnumProperty( @@ -133,15 +213,24 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): def draw_buttons(self, context, layout): r0 = layout.row() r0.prop(self, "activate", text="", icon="HIDE_" + ("OFF" if self.activate else "ON")) + r0.prop(self, "mode") c0 = layout.column(align=True) c0.prop(self, "background_color") - c0.prop(self, "draw_scale") - layout.prop(self, "cycle") + + if self.mode == 'Number': + row = c0.row(align=True) + for j in range(2): + row.prop(self, 'drawing_size', index=j, text='XY'[j]) + c0.prop(self, 'continuous') + elif self.mode == 'Path': + c0.prop(self, "draw_scale") + layout.prop(self, "cycle") def draw_buttons_ext(self, context, l): l.prop(self, "selected_theme_mode") def sv_init(self, context): + self.inputs.new('SvStringsSocket', "Number") self.inputs.new('SvVerticesSocket', "Vecs") self.inputs.new('SvColorSocket', "Color").custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() @@ -177,19 +266,15 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): return batch, shader def generate_graph_geom(self, config, paths): - geom = lambda: None x, y = config.loc size = 140 * config.scale scale = config.scale - back_color, grid_color, line_color = config.palette + # back_color, grid_color, line_color = config.palette cycle = config.cycle sys_scale = config.sys_scale - background_color = config.background_color line_color = config.line_color - # if len(line_color) > 1: - # line_color= [c for color in line_color for c in color] - # easing_func = config.easing_func + all_vecs = [v for vecs in paths for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) # background geom @@ -201,19 +286,15 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): margin = 10 * sys_scale geom.background_coords = [ (x, y + margin), - (x + w+2*margin, y+ margin), - (w + x + 2*margin, y - h - margin), - (x, y - h-margin)] + (x + w + 2*margin, y + margin), + (w + x + 2*margin, y - h - margin), + (x, y - h - margin)] geom.background_indices = [(0, 1, 2), (0, 2, 3)] - # grid geom and associated vertex colors - num_divs = 8 - offset = size / num_divs - vertices = [] vertex_colors = [] indices = [] - + idx_offset = 0 for vecs, col in zip(paths, line_color): graphline = [] @@ -227,7 +308,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): for i in range(len(vecs)-1): indices.append([i + idx_offset, i + 1 + idx_offset]) if cycle: - indices.append([len(graphline)-1 + idx_offset,0 + idx_offset]) + indices.append([len(graphline)-1 + idx_offset, 0 + idx_offset]) idx_offset += len(graphline) geom.vertices = vertices @@ -236,7 +317,10 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): return geom def process(self): - p = self.inputs['Vecs'].sv_get() + if self.mode == 'Number': + p = self.inputs['Number'].sv_get() + else: + p = self.inputs['Vecs'].sv_get() path_color = self.inputs['Color'].sv_get(default=[[self.unit_color]])[0] fullList(path_color, len(p)) n_id = node_id(self) @@ -258,9 +342,15 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config.line_color = path_color # config.easing_func = easing_func - geom = self.generate_graph_geom(config, p) + if self.mode == 'Number': + config.size = self.drawing_size + config.continuous = self.continuous + geom = generate_number_geom(config, p) + else: + geom = self.generate_graph_geom(config, p) + config.batch, config.shader = self.generate_shader(geom) - + draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], -- GitLab From 1e774a13f12068e70164eb0d5f27a2e96b6ccae0 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Mon, 4 May 2020 21:42:02 +0200 Subject: [PATCH 03/12] edges and polygon modes --- nodes/viz/vd_draw_experimental.py | 6 +- nodes/viz/viewer2d.py | 242 ++++++++++++++++++++++++++---- 2 files changed, 214 insertions(+), 34 deletions(-) diff --git a/nodes/viz/vd_draw_experimental.py b/nodes/viz/vd_draw_experimental.py index d2a0dbd6d..e1962d2f2 100644 --- a/nodes/viz/vd_draw_experimental.py +++ b/nodes/viz/vd_draw_experimental.py @@ -65,7 +65,7 @@ def edges_from_faces(indices): return list(out) -def ensure_triangles(node, coords, indices): +def ensure_triangles(coords, indices, handle_concave_quads): """ this fully tesselates the incoming topology into tris, not optimized for meshes that don't contain ngons @@ -77,7 +77,7 @@ def ensure_triangles(node, coords, indices): num_verts = len(idxset) if num_verts == 3: concat(tuple(idxset)) - elif num_verts == 4 and not node.handle_concave_quads: + elif num_verts == 4 and not handle_concave_quads: # a b c d -> [a, b, c], [a, c, d] concat2([(idxset[0], idxset[1], idxset[2]), (idxset[0], idxset[2], idxset[3])]) else: @@ -597,7 +597,7 @@ class SvVDExperimental(bpy.types.Node, SverchCustomTreeNode): # expecting mixed bag of tris/quads/ngons if self.display_faces: - geom.faces = ensure_triangles(self, coords, face_indices) + geom.faces = ensure_triangles(coords, face_indices, self.handle_concave_quads) if self.display_edges: if self.use_dashed: diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 15468e9f9..480fc7197 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -18,7 +18,7 @@ from mathutils import Vector import bpy -from bpy.props import FloatProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty +from bpy.props import FloatProperty, IntProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty import blf import bgl @@ -30,6 +30,7 @@ from sverchok.core.socket_data import SvGetSocketInfo from sverchok.data_structure import updateNode, node_id, enum_item_4, fullList, match_long_repeat from sverchok.node_tree import SverchCustomTreeNode from sverchok.ui import bgl_callback_nodeview as nvBGL +from sverchok.nodes.viz.vd_draw_experimental import ensure_triangles # star imports easing_dict and all easing functions. from sverchok.utils.sv_easing_functions import * @@ -58,7 +59,16 @@ palette_dict = { ) } +def background_rect(x, y, w, h, margin): + background_coords = [ + (x, y + margin), + (x + w + 2* margin, y + margin), + (w + x + 2* margin, y - h - margin), + (x, y - h - margin)] + background_indices = [(0, 1, 2), (0, 2, 3)] + return background_coords, background_indices + def simple28_grid_xy(x, y, args): """ x and y are passed by default so you could add font content """ @@ -73,8 +83,19 @@ def simple28_grid_xy(x, y, args): batch.draw(shader) # draw grid and graph + + config.batch.draw(config.shader) + if config.mode == 'Polygons': + config.batch2.draw(config.shader2) + if config.draw_verts: + bgl.glPointSize(config.point_size) + batch2 = batch_for_shader(shader, 'POINTS', {"pos": geom.vertices}) + shader.bind() + shader.uniform_float("color", geom.vertex_colors[0]) + batch2.draw(shader) + bgl.glPointSize(1) def generate_number_geom(config, numbers): geom = lambda: None @@ -88,20 +109,8 @@ def generate_number_geom(config, numbers): w, h = config.size all_numbers = [n for l in numbers for n in l ] maxmin = [max(all_numbers), min(all_numbers)] - # background geom - # w = size - # h = size - # w = (maxmin[0][0]- maxmin[0][1]) * scale - # h = (maxmin[1][0]- maxmin[1][1]) * scale - margin = 1 * scale margin = 10 * sys_scale - geom.background_coords = [ - (x, y + margin), - (x + w + 2*margin, y + margin), - (w + x + 2*margin, y - h - margin), - (x, y - h - margin)] - geom.background_indices = [(0, 1, 2), (0, 2, 3)] - + geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) vertices = [] vertex_colors = [] indices = [] @@ -135,6 +144,139 @@ def generate_number_geom(config, numbers): geom.indices = indices return geom +def generate_lines_geom(config, paths, edges): + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + # back_color, grid_color, line_color = config.palette + sys_scale = config.sys_scale + line_color = config.line_color + + all_vecs = [v for vecs in paths for v in vecs ] + maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) + # background geom + w = size + h = size + w = (maxmin[0][0]- maxmin[0][1]) * scale + h = (maxmin[1][0]- maxmin[1][1]) * scale + margin = 10 * sys_scale + geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) + + vertices = [] + vertex_colors = [] + indices = [] + + idx_offset = 0 + for vecs, edgs, col in zip(paths, edges, line_color): + + for i, e in enumerate(edgs): + print(e[0]) + v0= vecs[e[0]] + v1= vecs[e[1]] + _px = x + (v0[0] - maxmin[0][1]) * scale + margin + _py = y + (v0[1] - maxmin[1][0]) * scale + _px2 = x + (v1[0] - maxmin[0][1]) * scale + margin + _py2 = y + (v1[1] - maxmin[1][0]) * scale + vertices.extend([[_px, _py], [_px2, _py2]]) + vertex_colors.extend([col, col]) + indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) + + idx_offset += 2*len(edges) + + geom.vertices = vertices + geom.vertex_colors = vertex_colors + geom.indices = indices + return geom + +def generate_edges_geom(config, paths, edges): + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + # back_color, grid_color, line_color = config.palette + sys_scale = config.sys_scale + line_color = config.line_color + + all_vecs = [v for vecs in paths for v in vecs ] + maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) + # background geom + w = size + h = size + w = (maxmin[0][0]- maxmin[0][1]) * scale + h = (maxmin[1][0]- maxmin[1][1]) * scale + margin = 10 * sys_scale + geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) + + vertices = [] + vertex_colors = [] + indices = [] + + idx_offset = 0 + for vecs, edgs, col in zip(paths, edges, line_color): + + for i, v in enumerate(vecs): + _px = x + (v[0] - maxmin[0][1]) * scale + margin + _py = y + (v[1] - maxmin[1][0]) * scale + + vertices.append([_px, _py]) + vertex_colors.append(col) + + for e in edgs: + indices.append([e[0] + idx_offset, e[1] + idx_offset]) + + idx_offset += len(vecs) + + geom.vertices = vertices + geom.vertex_colors = vertex_colors + geom.indices = indices + return geom + + +def generate_polygons_geom(config, paths, polygons_s, poly_color): + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + # back_color, grid_color, line_color = config.palette + sys_scale = config.sys_scale + line_color = poly_color + + all_vecs = [v for vecs in paths for v in vecs ] + maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) + # background geom + w = size + h = size + w = (maxmin[0][0]- maxmin[0][1]) * scale + h = (maxmin[1][0]- maxmin[1][1]) * scale + margin = 10 * sys_scale + geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) + + vertices = [] + vertex_colors = [] + indices = [] + + idx_offset = 0 + for vecs, polygons, col in zip(paths, polygons_s, line_color): + polygon_indices = ensure_triangles(vecs, polygons, True) + for i, v in enumerate(vecs): + _px = x + (v[0] - maxmin[0][1]) * scale + margin + _py = y + (v[1] - maxmin[1][0]) * scale + + vertices.append([_px, _py]) + vertex_colors.append(col) + + for p in polygon_indices: + indices.append([c + idx_offset for c in p]) + + idx_offset += len(vecs) + + geom.vertices = vertices + geom.vertex_colors = vertex_colors + geom.indices = indices + return geom + + class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): '''Curved interpolation''' bl_idname = 'SvViewer2D' @@ -145,7 +287,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): ('Number', 'Number', 'Input UV coordinates to evaluate texture', '', 1), ('Path', 'Path', 'Matrix to apply to verts before evaluating texture', '', 2), ('Edges', 'Edges', 'Matrix of texture (External Object matrix)', '', 3), - ('Polygons', 'Polygons', 'Matrix of texture (External Object matrix)', '', 3), + ('Polygons', 'Polygons', 'Matrix of texture (External Object matrix)', '', 4), ] n_id: StringProperty(default='') @@ -166,11 +308,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): default=True, update=updateNode ) - selected_mode: EnumProperty( - items=easing_list, description="Set easing Function to:", - default="0", update=updateNode - ) - in_float: FloatProperty( min=0.0, max=1.0, default=0.0, name='Float Input', description='input to the easy function', update=updateNode @@ -183,6 +320,14 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): update=updateNode, name='Size', default=(150, 150), size=2 ) + draw_verts: BoolProperty( + default=False, name='See Verts', + description='Drawing Verts', update=updateNode + ) + point_size: IntProperty( + min=1, default=4, name='Verts Size', + description='Point Size', update=updateNode + ) continuous: BoolProperty( name='Continuous', description='Continuous Graph', default=True, update=updateNode @@ -191,6 +336,10 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) + unit_color2: FloatVectorProperty( + update=updateNode, name='', default=(.9, .9, .8, 1.0), + size=4, min=0.0, max=1.0, subtype='COLOR' + ) background_color: FloatVectorProperty( update=updateNode, name='', default=(.05, .05, .05, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' @@ -205,11 +354,11 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): r = l.row(align=True) split = r.split(factor=0.85) r1 = split.row(align=True) - r1.prop(self, "selected_mode", text="") r1.prop(self, 'activate', icon='NORMALIZE_FCURVES', text="") if info: r2 = split.row() r2.label(text=info) + def draw_buttons(self, context, layout): r0 = layout.row() r0.prop(self, "activate", text="", icon="HIDE_" + ("OFF" if self.activate else "ON")) @@ -222,9 +371,14 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): for j in range(2): row.prop(self, 'drawing_size', index=j, text='XY'[j]) c0.prop(self, 'continuous') - elif self.mode == 'Path': + # elif self.mode == 'Path': + else: c0.prop(self, "draw_scale") - layout.prop(self, "cycle") + row = c0.row(align=True) + row.prop(self, "draw_verts") + row.prop(self, "point_size") + if self.mode == "Path": + layout.prop(self, "cycle") def draw_buttons_ext(self, context, l): l.prop(self, "selected_theme_mode") @@ -232,12 +386,19 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): def sv_init(self, context): self.inputs.new('SvStringsSocket', "Number") self.inputs.new('SvVerticesSocket', "Vecs") - self.inputs.new('SvColorSocket', "Color").custom_draw = 'draw_color_socket' + self.inputs.new('SvStringsSocket', "Edges") + self.inputs.new('SvStringsSocket', "Polygons") + vc = self.inputs.new('SvColorSocket', "Color") + vc.prop_name = 'unit_color' + vc.custom_draw = 'draw_color_socket' + vc2 = self.inputs.new('SvColorSocket', "Polygon Color") + vc2.prop_name = 'unit_color2' + vc2.custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() def draw_color_socket(self, socket, context, layout): if not socket.is_linked: - layout.prop(self, 'unit_color', text="") + layout.prop(self, socket.prop_name, text="") else: layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) @@ -260,9 +421,9 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): return x, y, scale, multiplier - def generate_shader(self, geom): + def generate_shader(self, geom, gl_Type): shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') - batch = batch_for_shader(shader, 'LINES', {"pos": geom.vertices, "color": geom.vertex_colors}, indices=geom.indices) + batch = batch_for_shader(shader, gl_Type, {"pos": geom.vertices, "color": geom.vertex_colors}, indices=geom.indices) return batch, shader def generate_graph_geom(self, config, paths): @@ -321,6 +482,14 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): p = self.inputs['Number'].sv_get() else: p = self.inputs['Vecs'].sv_get() + if self.mode == 'Edges': + edges = self.inputs['Edges'].sv_get() + if self.mode == 'Polygons': + edges = self.inputs['Edges'].sv_get() + polygons_s = self.inputs['Polygons'].sv_get() + poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.unit_color]])[0] + fullList(poly_color, len(p)) + path_color = self.inputs['Color'].sv_get(default=[[self.unit_color]])[0] fullList(path_color, len(p)) n_id = node_id(self) @@ -332,7 +501,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config = lambda: None x, y, scale, multiplier = self.get_drawing_attributes() - + config.mode = self.mode config.loc = (x, y) config.palette = palette_dict.get(self.selected_theme_mode)[:] config.sys_scale = scale @@ -340,16 +509,27 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config.cycle = self.cycle config.background_color = self.background_color config.line_color = path_color + config.draw_verts = self.draw_verts + config.point_size = self.point_size # config.easing_func = easing_func if self.mode == 'Number': config.size = self.drawing_size config.continuous = self.continuous geom = generate_number_geom(config, p) - else: + elif self.mode == 'Path': geom = self.generate_graph_geom(config, p) - - config.batch, config.shader = self.generate_shader(geom) + elif self.mode == 'Edges': + geom = generate_edges_geom(config, p, edges) + else: + geom = generate_polygons_geom(config, p, polygons_s, poly_color) + geom2 = generate_edges_geom(config, p, edges) + # geom = generate_lines_geom(config, p, edges) + if self.mode == 'Polygons': + config.batch, config.shader = self.generate_shader(geom, 'TRIS') + config.batch2, config.shader2 = self.generate_shader(geom2, 'LINES') + else: + config.batch, config.shader = self.generate_shader(geom, 'LINES') draw_data = { 'mode': 'custom_function', -- GitLab From afacd964734dfd9c23f17a7661ed8fc2d513a487 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Tue, 5 May 2020 23:48:42 +0200 Subject: [PATCH 04/12] color_per_item started --- nodes/viz/viewer2d.py | 105 ++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 480fc7197..9f74eb815 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -17,6 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### from mathutils import Vector +from itertools import cycle import bpy from bpy.props import FloatProperty, IntProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty @@ -35,12 +36,11 @@ from sverchok.nodes.viz.vd_draw_experimental import ensure_triangles # star imports easing_dict and all easing functions. from sverchok.utils.sv_easing_functions import * -easing_list = [] -for k in sorted(easing_dict.keys()): - fname = easing_dict[k].__name__ - easing_list.append(tuple([str(k), fname, "", k])) - - +socket_dict = { + 'vector_color': ('vector_toggle', 'UV_VERTEXSEL', 'color_per_point'), + 'edge_color': ('edge_toggle', 'UV_EDGESEL', 'color_per_edge'), + 'polygon_color': ('polygon_toggle', 'UV_FACESEL', 'color_per_polygon'), + } palette_dict = { "default": ( (0.243299, 0.590403, 0.836084, 1.00), # back_color @@ -63,7 +63,7 @@ def background_rect(x, y, w, h, margin): background_coords = [ (x, y + margin), (x + w + 2* margin, y + margin), - (w + x + 2* margin, y - h - margin), + (w + x + 2 * margin, y - h - margin), (x, y - h - margin)] background_indices = [(0, 1, 2), (0, 2, 3)] @@ -82,18 +82,17 @@ def simple28_grid_xy(x, y, args): shader.uniform_float("color", background_color) batch.draw(shader) - # draw grid and graph - - config.batch.draw(config.shader) if config.mode == 'Polygons': config.batch2.draw(config.shader2) if config.draw_verts: bgl.glPointSize(config.point_size) - batch2 = batch_for_shader(shader, 'POINTS', {"pos": geom.vertices}) - shader.bind() - shader.uniform_float("color", geom.vertex_colors[0]) + print(geom.points_color) + shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + batch2 = batch_for_shader(shader, 'POINTS', {"pos": geom.vertices, "color": geom.points_color}) + # shader.bind() + # shader.uniform_float("color", config.vector_color[0]) batch2.draw(shader) bgl.glPointSize(1) @@ -103,7 +102,7 @@ def generate_number_geom(config, numbers): size = 140 * config.scale scale = config.scale # back_color, grid_color, line_color = config.palette - cycle = config.cycle + cyclic = config.cyclic sys_scale = config.sys_scale line_color = config.line_color w, h = config.size @@ -137,11 +136,21 @@ def generate_number_geom(config, numbers): vertex_colors.extend([col, col]) indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) idx_offset += 2*len(nums) - + points_color =[] + if config.color_per_point: + for cols, nums in zip(cycle(config.vector_color), numbers): + + for c, n in zip(cycle(cols), nums): + points_color.append(c) + else: + for nums, col in zip(numbers, cycle(config.vector_color[0])): + for n in nums: + points_color.append(col) geom.vertices = vertices geom.vertex_colors = vertex_colors geom.indices = indices + geom.points_color = points_color return geom def generate_lines_geom(config, paths, edges): @@ -281,6 +290,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): '''Curved interpolation''' bl_idname = 'SvViewer2D' bl_label = 'Viewer 2D' + bl_icon = 'HIDE_OFF' sv_icon = 'SV_EASING' modes = [ @@ -303,7 +313,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): name='Show', description='Activate drawing', default=True, update=updateNode ) - cycle: BoolProperty( + cyclic: BoolProperty( name='Cycle', description='Activate drawing', default=True, update=updateNode ) @@ -332,14 +342,36 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): name='Continuous', description='Continuous Graph', default=True, update=updateNode ) - unit_color: FloatVectorProperty( + vector_color: FloatVectorProperty( + update=updateNode, name='', default=(.9, .9, .95, 1.0), + size=4, min=0.0, max=1.0, subtype='COLOR' + ) + vector_toggle: BoolProperty( + update=updateNode, name='', default=True + ) + color_per_point: BoolProperty( + update=updateNode, name='Color per point', default=True + ) + color_per_edge: BoolProperty( + update=updateNode, name='Color per point', default=True + ) + color_per_polygon: BoolProperty( + update=updateNode, name='Color per point', default=True + ) + edge_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) - unit_color2: FloatVectorProperty( + edge_toggle: BoolProperty( + update=updateNode, name='', default=True + ) + polygon_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) + polygon_toggle: BoolProperty( + update=updateNode, name='', default=True + ) background_color: FloatVectorProperty( update=updateNode, name='', default=(.05, .05, .05, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' @@ -378,7 +410,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): row.prop(self, "draw_verts") row.prop(self, "point_size") if self.mode == "Path": - layout.prop(self, "cycle") + layout.prop(self, "cyclic") def draw_buttons_ext(self, context, l): l.prop(self, "selected_theme_mode") @@ -388,18 +420,23 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): self.inputs.new('SvVerticesSocket', "Vecs") self.inputs.new('SvStringsSocket', "Edges") self.inputs.new('SvStringsSocket', "Polygons") + vc0 = self.inputs.new('SvColorSocket', "Vector Color") + vc0.prop_name = 'vector_color' + vc0.custom_draw = 'draw_color_socket' vc = self.inputs.new('SvColorSocket', "Color") - vc.prop_name = 'unit_color' + vc.prop_name = 'edge_color' vc.custom_draw = 'draw_color_socket' vc2 = self.inputs.new('SvColorSocket', "Polygon Color") - vc2.prop_name = 'unit_color2' + vc2.prop_name = 'polygon_color' vc2.custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() def draw_color_socket(self, socket, context, layout): + socket_info = socket_dict[socket.prop_name] + layout.prop(self, socket_info[0], text="", icon=socket_info[1]) + layout.prop(self, socket_info[2], text="", icon='COLOR') if not socket.is_linked: layout.prop(self, socket.prop_name, text="") - else: layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) @@ -427,12 +464,13 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): return batch, shader def generate_graph_geom(self, config, paths): + geom = lambda: None x, y = config.loc size = 140 * config.scale scale = config.scale # back_color, grid_color, line_color = config.palette - cycle = config.cycle + cyclic = config.cyclic sys_scale = config.sys_scale line_color = config.line_color @@ -468,7 +506,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): for i in range(len(vecs)-1): indices.append([i + idx_offset, i + 1 + idx_offset]) - if cycle: + if cyclic: indices.append([len(graphline)-1 + idx_offset, 0 + idx_offset]) idx_offset += len(graphline) @@ -487,10 +525,12 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): if self.mode == 'Polygons': edges = self.inputs['Edges'].sv_get() polygons_s = self.inputs['Polygons'].sv_get() - poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.unit_color]])[0] + poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.polygon_color]])[0] fullList(poly_color, len(p)) - - path_color = self.inputs['Color'].sv_get(default=[[self.unit_color]])[0] + + vector_color = self.inputs['Vector Color'].sv_get(default=[[self.vector_color]]) + path_color = self.inputs['Color'].sv_get(default=[[self.edge_color]])[0] + fullList(vector_color, len(p)) fullList(path_color, len(p)) n_id = node_id(self) @@ -501,16 +541,21 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config = lambda: None x, y, scale, multiplier = self.get_drawing_attributes() + margin = 10* scale config.mode = self.mode - config.loc = (x, y) + config.loc = (x, y - margin) config.palette = palette_dict.get(self.selected_theme_mode)[:] config.sys_scale = scale config.scale = scale*self.draw_scale - config.cycle = self.cycle + config.cyclic = self.cyclic config.background_color = self.background_color + config.vector_color = vector_color config.line_color = path_color - config.draw_verts = self.draw_verts + config.draw_verts = self.vector_toggle config.point_size = self.point_size + config.color_per_point = self.color_per_point + config.color_per_edge = self.color_per_edge + config.color_per_polygon = self.color_per_polygon # config.easing_func = easing_func if self.mode == 'Number': -- GitLab From bc015576e77f0bf4904eaba38f7fe54f71aac6d5 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Wed, 6 May 2020 12:04:20 +0200 Subject: [PATCH 05/12] color per vertex --- nodes/viz/viewer2d.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 9f74eb815..1de48c420 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -69,6 +69,21 @@ def background_rect(x, y, w, h, margin): return background_coords, background_indices +def fill_points_colors(vectors_color, data, color_per_point): + points_color = [] + if color_per_point: + for cols, sub_data in zip(cycle(vectors_color), data): + + for c, n in zip(cycle(cols), sub_data): + points_color.append(c) + else: + for nums, col in zip(data, cycle(vectors_color[0])): + for n in nums: + points_color.append(col) + + return points_color + + def simple28_grid_xy(x, y, args): """ x and y are passed by default so you could add font content """ @@ -88,7 +103,6 @@ def simple28_grid_xy(x, y, args): if config.draw_verts: bgl.glPointSize(config.point_size) - print(geom.points_color) shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') batch2 = batch_for_shader(shader, 'POINTS', {"pos": geom.vertices, "color": geom.points_color}) # shader.bind() @@ -136,21 +150,13 @@ def generate_number_geom(config, numbers): vertex_colors.extend([col, col]) indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) idx_offset += 2*len(nums) - points_color =[] - if config.color_per_point: - for cols, nums in zip(cycle(config.vector_color), numbers): - - for c, n in zip(cycle(cols), nums): - points_color.append(c) - else: - for nums, col in zip(numbers, cycle(config.vector_color[0])): - for n in nums: - points_color.append(col) - + + points_color = fill_points_colors(config.vector_color, numbers, config.color_per_point) + geom.points_color = points_color geom.vertices = vertices geom.vertex_colors = vertex_colors geom.indices = indices - geom.points_color = points_color + return geom def generate_lines_geom(config, paths, edges): @@ -236,6 +242,8 @@ def generate_edges_geom(config, paths, edges): idx_offset += len(vecs) + points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) + geom.points_color = points_color geom.vertices = vertices geom.vertex_colors = vertex_colors geom.indices = indices @@ -279,7 +287,8 @@ def generate_polygons_geom(config, paths, polygons_s, poly_color): indices.append([c + idx_offset for c in p]) idx_offset += len(vecs) - + points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) + geom.points_color = points_color geom.vertices = vertices geom.vertex_colors = vertex_colors geom.indices = indices @@ -556,7 +565,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config.color_per_point = self.color_per_point config.color_per_edge = self.color_per_edge config.color_per_polygon = self.color_per_polygon - # config.easing_func = easing_func + if self.mode == 'Number': config.size = self.drawing_size -- GitLab From 6e8e2bf71ba67dfe756fc39b8ee8c56b4ff0cb26 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 7 May 2020 01:42:41 +0200 Subject: [PATCH 06/12] curve mode --- nodes/viz/viewer2d.py | 520 +++++++++++++++++++++++++++++------------- 1 file changed, 366 insertions(+), 154 deletions(-) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 1de48c420..3b21795f0 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -18,6 +18,7 @@ from mathutils import Vector from itertools import cycle +from numpy import float64 as np_float64, linspace as np_linspace import bpy from bpy.props import FloatProperty, IntProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty @@ -31,8 +32,7 @@ from sverchok.core.socket_data import SvGetSocketInfo from sverchok.data_structure import updateNode, node_id, enum_item_4, fullList, match_long_repeat from sverchok.node_tree import SverchCustomTreeNode from sverchok.ui import bgl_callback_nodeview as nvBGL -from sverchok.nodes.viz.vd_draw_experimental import ensure_triangles - +from mathutils.geometry import tessellate_polygon as tessellate # star imports easing_dict and all easing functions. from sverchok.utils.sv_easing_functions import * @@ -58,17 +58,41 @@ palette_dict = { (0.304762, 1.000000, 0.062827, 1.00) # line_color ) } +def ensure_triangles(coords, indices, handle_concave_quads): + """ + this fully tesselates the incoming topology into tris, + not optimized for meshes that don't contain ngons + """ + new_indices = [] + face_index =[] + concat = new_indices.append + concat2 = new_indices.extend + for idf, idxset in enumerate(indices): + num_verts = len(idxset) + if num_verts == 3: + concat(tuple(idxset)) + face_index.append(idf) + elif num_verts == 4 and not handle_concave_quads: + # a b c d -> [a, b, c], [a, c, d] + concat2([(idxset[0], idxset[1], idxset[2]), (idxset[0], idxset[2], idxset[3])]) + face_index.extend([idf, idf]) + else: + subcoords = [Vector(coords[idx]) for idx in idxset] + for pol in tessellate([subcoords]): + concat([idxset[i] for i in pol]) + face_index.append(idf) + return new_indices, face_index def background_rect(x, y, w, h, margin): background_coords = [ - (x, y + margin), + (x, y + margin), (x + w + 2* margin, y + margin), (w + x + 2 * margin, y - h - margin), (x, y - h - margin)] background_indices = [(0, 1, 2), (0, 2, 3)] return background_coords, background_indices - + def fill_points_colors(vectors_color, data, color_per_point): points_color = [] if color_per_point: @@ -97,68 +121,169 @@ def simple28_grid_xy(x, y, args): shader.uniform_float("color", background_color) batch.draw(shader) - config.batch.draw(config.shader) - if config.mode == 'Polygons': - config.batch2.draw(config.shader2) + if config.draw_polys and config.mode == 'Mesh': + config.p_batch.draw(config.p_shader) + + if config.draw_edges: + bgl.glLineWidth(config.edge_width) + config.e_batch.draw(config.e_shader) + bgl.glLineWidth(1) if config.draw_verts: bgl.glPointSize(config.point_size) - shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') - batch2 = batch_for_shader(shader, 'POINTS', {"pos": geom.vertices, "color": geom.points_color}) - # shader.bind() - # shader.uniform_float("color", config.vector_color[0]) - batch2.draw(shader) + config.v_batch.draw(config.v_shader) bgl.glPointSize(1) + +def path_from_nums(nums, x, y, num_width, num_height, maxmin, sys_scale): + v_path = [] + for i, n in enumerate(nums): + _px = x + (i * num_width) * sys_scale + _py = y + ((n - maxmin[1])* num_height) * sys_scale + v_path.append([_px, _py]) + return v_path def generate_number_geom(config, numbers): geom = lambda: None x, y = config.loc - size = 140 * config.scale - scale = config.scale - # back_color, grid_color, line_color = config.palette - cyclic = config.cyclic sys_scale = config.sys_scale - line_color = config.line_color + line_color = config.edge_color w, h = config.size all_numbers = [n for l in numbers for n in l ] maxmin = [max(all_numbers), min(all_numbers)] margin = 10 * sys_scale geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) - vertices = [] + v_vertices = [] + e_vertices = [] vertex_colors = [] indices = [] num_height = h/(max(all_numbers)- min(all_numbers)) idx_offset = 0 - if config.continuous: - for nums, col in zip(numbers, line_color): + + _x = x + margin + _y = y - h + if config.color_per_edge: + for nums, cols in zip(numbers, cycle(line_color)): num_width = w/(len(nums)-1) - for i, n in enumerate(nums): - _px = x + (i * num_width) * sys_scale + margin - _py = y + ((n -maxmin[1])* num_height) * sys_scale - h - vertices.append([_px, _py]) - vertex_colors.append(col) - for i in range(len(nums)-1): - indices.append([i + idx_offset, i + 1 + idx_offset]) - idx_offset += len(nums) - else: - for nums, col in zip(numbers, line_color): - num_width = w/len(nums) - for i, n in enumerate(nums): - _px = x + (i * num_width) * sys_scale + margin - _py = y + ((n -maxmin[1])* num_height) * sys_scale - h - vertices.extend([[_px, _py], [_px + num_width, _py]]) + v_path = path_from_nums(nums, _x, _y, num_width, num_height, maxmin, sys_scale) + v_vertices.extend(v_path) + + for v, v1, col in zip(v_path[:-1], v_path[1:], cycle(cols)): + e_vertices.extend([v, v1]) vertex_colors.extend([col, col]) + + for i in range(len(nums)-1): indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) idx_offset += 2*len(nums) - + else: + for nums, col in zip(numbers, line_color[0]): + num_width = w/(len(nums)-1) + v_path = path_from_nums(nums, _x, _y, num_width, num_height, maxmin, sys_scale) + e_vertices.extend(v_path) + vertex_colors.extend([col for v in v_path]) + + for i in range(len(nums)-1): + indices.append([i + idx_offset, i + 1 + idx_offset]) + idx_offset += len(nums) + + v_vertices = e_vertices + + points_color = fill_points_colors(config.vector_color, numbers, config.color_per_point) geom.points_color = points_color - geom.vertices = vertices + geom.points_vertices = v_vertices + geom.vertices = e_vertices geom.vertex_colors = vertex_colors geom.indices = indices + if config.draw_verts: + config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.v_batch = batch_for_shader(config.v_shader, 'POINTS', {"pos": v_vertices, "color": points_color}) + if config.draw_edges: + config.e_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.e_batch = batch_for_shader(config.e_shader, 'LINES', {"pos": e_vertices, "color": vertex_colors}, indices=indices) + + return geom + +def generate_graph_geom(config, paths): + + geom = lambda: None + x, y = config.loc + size = 140 * config.scale + scale = config.scale + # back_color, grid_color, line_color = config.palette + cyclic = config.cyclic + sys_scale = config.sys_scale + if config.color_per_edge: + edge_color = config.edge_color + else: + edge_color = config.edge_color[0] + # line_color = config.edge_color + + all_vecs = [v for vecs in paths for v in vecs ] + maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) + axis1, axis2 = get_axis_index(config.plane) + # background geom + w = size + h = size + w = (maxmin[axis1][0]- maxmin[axis1][1]) * scale + h = (maxmin[axis2][0]- maxmin[axis2][1]) * scale + margin = 1 * scale + margin = 10 * sys_scale + geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) + v_vertices = [] + e_vertices, e_vertex_colors, e_indices = [], [], [] + _x = x + margin + idx_offset = 0 + for vecs, col in zip(paths, edge_color): + v_path = transformed_verts(vecs, _x, y, maxmin, scale, axis1, axis2) + v_vertices.extend(v_path) + if not config.draw_edges: + continue + if config.color_per_edge and not config.edges_use_vertex_color: + + for v, v1, col in zip(v_path[:-1], v_path[1:], cycle(col)): + e_vertices.extend([v, v1]) + e_vertex_colors.extend([col, col]) + + for i in range(len(v_path)-1): + e_indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) + if cyclic: + + e_indices.append([len(e_vertices)-1 + idx_offset, 0 + idx_offset]) + idx_offset += 2 * len(v_path) + else: + e_vertex_colors.extend([col for v in v_path]) + e_vertices.extend(v_path) + + for i in range(len(vecs)-1): + e_indices.append([i + idx_offset, i + 1 + idx_offset]) + if cyclic: + e_indices.append([len(v_path)-1 + idx_offset, 0 + idx_offset]) + idx_offset += len(v_path) + + points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) + + if config.draw_verts: + config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.v_batch = batch_for_shader(config.v_shader, 'POINTS', {"pos": v_vertices, "color": points_color}) + + if config.draw_edges: + if config.edges_use_vertex_color: + e_vertex_colors = points_color + config.e_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.e_batch = batch_for_shader(config.e_shader, 'LINES', {"pos": e_vertices, "color": e_vertex_colors}, indices=e_indices) + return geom + +def transformed_verts(vecs, x, y, maxmin, scale, axis1, axis2): + v_path = [] + for v in vecs: + _px = x + (v[axis1] - maxmin[axis1][1]) * scale + _py = y + (v[axis2] - maxmin[axis2][0]) * scale + v_path.append([_px, _py]) + return v_path + def generate_lines_geom(config, paths, edges): geom = lambda: None x, y = config.loc @@ -166,7 +291,7 @@ def generate_lines_geom(config, paths, edges): scale = config.scale # back_color, grid_color, line_color = config.palette sys_scale = config.sys_scale - line_color = config.line_color + line_color = config.edge_color all_vecs = [v for vecs in paths for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) @@ -186,9 +311,8 @@ def generate_lines_geom(config, paths, edges): for vecs, edgs, col in zip(paths, edges, line_color): for i, e in enumerate(edgs): - print(e[0]) - v0= vecs[e[0]] - v1= vecs[e[1]] + v0 = vecs[e[0]] + v1 = vecs[e[1]] _px = x + (v0[0] - maxmin[0][1]) * scale + margin _py = y + (v0[1] - maxmin[1][0]) * scale _px2 = x + (v1[0] - maxmin[0][1]) * scale + margin @@ -196,7 +320,7 @@ def generate_lines_geom(config, paths, edges): vertices.extend([[_px, _py], [_px2, _py2]]) vertex_colors.extend([col, col]) indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) - + idx_offset += 2*len(edges) geom.vertices = vertices @@ -211,7 +335,7 @@ def generate_edges_geom(config, paths, edges): scale = config.scale # back_color, grid_color, line_color = config.palette sys_scale = config.sys_scale - line_color = config.line_color + line_color = config.edge_color all_vecs = [v for vecs in paths for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) @@ -228,18 +352,17 @@ def generate_edges_geom(config, paths, edges): indices = [] idx_offset = 0 - for vecs, edgs, col in zip(paths, edges, line_color): + for vecs, edgs, col in zip(paths, edges, cycle(line_color[0])): for i, v in enumerate(vecs): _px = x + (v[0] - maxmin[0][1]) * scale + margin _py = y + (v[1] - maxmin[1][0]) * scale - vertices.append([_px, _py]) vertex_colors.append(col) - + for e in edgs: indices.append([e[0] + idx_offset, e[1] + idx_offset]) - + idx_offset += len(vecs) points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) @@ -249,6 +372,28 @@ def generate_edges_geom(config, paths, edges): geom.indices = indices return geom +def splitted_polygons_geom(polygon_indices, original_idx, v_path, cols, idx_offset): + total_p_verts = 0 + p_vertices, vertex_colors, indices = [], [], [] + for p, idx in zip(polygon_indices, original_idx): + p_vertices.extend([v_path[c] for c in p]) + vertex_colors.extend([cols[idx % len(cols)] for c in p]) + indices.append([c + idx_offset + total_p_verts for c in range(len(p))]) + total_p_verts += len(p) + return p_vertices, vertex_colors, indices, total_p_verts + +def get_axis_index(plane): + if plane == 'XY': + axis1 = 0 + axis2 = 1 + elif plane == 'XZ': + axis1 = 0 + axis2 = 2 + elif plane == 'YZ': + axis1 = 1 + axis2 = 2 + return axis1, axis2 + def generate_polygons_geom(config, paths, polygons_s, poly_color): geom = lambda: None @@ -257,41 +402,86 @@ def generate_polygons_geom(config, paths, polygons_s, poly_color): scale = config.scale # back_color, grid_color, line_color = config.palette sys_scale = config.sys_scale - line_color = poly_color + if config.color_per_polygon: + pol_color = poly_color + else: + pol_color = poly_color[0] + + if config.color_per_edge: + edge_color = config.edge_color + else: + edge_color = config.edge_color[0] + edges_s = config.edges + axis1, axis2 = get_axis_index(config.plane) all_vecs = [v for vecs in paths for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) # background geom w = size h = size - w = (maxmin[0][0]- maxmin[0][1]) * scale - h = (maxmin[1][0]- maxmin[1][1]) * scale + w = (maxmin[axis1][0]- maxmin[axis1][1]) * scale + h = (maxmin[axis2][0]- maxmin[axis2][1]) * scale margin = 10 * sys_scale geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) - vertices = [] - vertex_colors = [] - indices = [] - - idx_offset = 0 - for vecs, polygons, col in zip(paths, polygons_s, line_color): - polygon_indices = ensure_triangles(vecs, polygons, True) - for i, v in enumerate(vecs): - _px = x + (v[0] - maxmin[0][1]) * scale + margin - _py = y + (v[1] - maxmin[1][0]) * scale + v_vertices = [] + e_vertices, e_vertex_colors, e_indices = [], [], [] + p_vertices = [] + p_vertex_colors = [] + p_indices = [] + _x = x + margin + idx_p_offset = 0 + idx_e_offset = 0 + + for vecs, polygons, edges, p_cols, e_col in zip(paths, polygons_s, edges_s, cycle(pol_color), cycle(edge_color)): + v_path = transformed_verts(vecs, _x, y, maxmin, scale, axis1, axis2) + v_vertices.extend(v_path) + if config.color_per_edge and not config.edges_use_vertex_color: + for (v, v1), col in zip(edges, cycle(e_col)): + e_vertices.extend([v_path[v], v_path[v1]]) + e_vertex_colors.extend([col, col]) + e_indices.append([len(e_vertices)-2, len(e_vertices)-1]) + + else: + e_vertices.extend(v_path) + e_vertex_colors.extend([e_col for v in v_path]) + e_indices.extend([[c + idx_e_offset for c in e] for e in edges ]) + idx_e_offset += len(v_path) + + + if config.color_per_polygon and not config.polygon_use_vertex_color: + polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) + p_v, v_c, idx, total_p_verts = splitted_polygons_geom(polygon_indices, original_idx, v_path, p_cols, idx_p_offset) + p_vertices.extend(p_v) + p_vertex_colors.extend(v_c) + p_indices.extend(idx) + else: + polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) + p_vertices.extend(v_path) + p_vertex_colors.extend([p_cols for v in v_path]) + p_indices.extend([[c + idx_p_offset for c in p] for p in polygon_indices]) + total_p_verts = len(vecs) + + idx_p_offset += total_p_verts - vertices.append([_px, _py]) - vertex_colors.append(col) - - for p in polygon_indices: - indices.append([c + idx_offset for c in p]) - - idx_offset += len(vecs) points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) + if config.polygon_use_vertex_color: + p_vertex_colors = points_color + if config.edges_use_vertex_color: + e_vertex_colors = points_color geom.points_color = points_color - geom.vertices = vertices - geom.vertex_colors = vertex_colors - geom.indices = indices + geom.points_vertices = v_vertices + + if config.draw_verts: + config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.v_batch = batch_for_shader(config.v_shader, 'POINTS', {"pos": v_vertices, "color": points_color}) + if config.draw_edges: + config.e_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.e_batch = batch_for_shader(config.e_shader, 'LINES', {"pos": e_vertices, "color": e_vertex_colors}, indices=e_indices) + + if config.draw_polys: + config.p_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') + config.p_batch = batch_for_shader(config.p_shader, 'TRIS', {"pos": p_vertices, "color": p_vertex_colors}, indices=p_indices) return geom @@ -305,18 +495,42 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): modes = [ ('Number', 'Number', 'Input UV coordinates to evaluate texture', '', 1), ('Path', 'Path', 'Matrix to apply to verts before evaluating texture', '', 2), - ('Edges', 'Edges', 'Matrix of texture (External Object matrix)', '', 3), - ('Polygons', 'Polygons', 'Matrix of texture (External Object matrix)', '', 4), + ('Curve', 'Curve', 'Matrix of texture (External Object matrix)', '', 3), + ('Mesh', 'Mesh', 'Matrix of texture (External Object matrix)', '', 4), + + ] + plane = [ + ('XY', 'XY', 'Input UV coordinates to evaluate texture', '', 1), + ('XZ', 'XZ', 'Matrix to apply to verts before evaluating texture', '', 2), + ('YZ', 'YZ', 'Matrix of texture (External Object matrix)', '', 3), + ] n_id: StringProperty(default='') + def update_mode(self, context): + self.inputs['Polygon Color'].hide_safe = self.mode != 'Mesh' + # self.inputs['Edge Color'].hide_safe = self.edges_use_vertex_color + self.inputs['Number'].hide_safe = not self.mode == 'Number' + self.inputs['Curve'].hide_safe = not self.mode == 'Curve' + self.inputs['Vecs'].hide_safe = self.mode in ['Number', 'Curve'] + self.inputs['Edges'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] + self.inputs['Polygons'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] + updateNode(self, context) + mode: EnumProperty( name='Mode', items=modes, default='Path', description="Display Mode", - update=updateNode) + update=update_mode) + + working_plane: EnumProperty( + name='Proyection Plane', + items=plane, + default='XY', + description="Display Mode", + update=update_mode) activate: BoolProperty( name='Show', description='Activate drawing', @@ -347,10 +561,18 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): min=1, default=4, name='Verts Size', description='Point Size', update=updateNode ) + edge_width: IntProperty( + min=1, default=4, name='Edge Width', + description='Edge Width', update=updateNode + ) continuous: BoolProperty( name='Continuous', description='Continuous Graph', default=True, update=updateNode ) + curve_samples: IntProperty( + min=2, default=25, name='Samples', + description='Curve Resolution', update=updateNode + ) vector_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .95, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' @@ -367,6 +589,13 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): color_per_polygon: BoolProperty( update=updateNode, name='Color per point', default=True ) + polygon_use_vertex_color: BoolProperty( + update=update_mode, name='Polys Vertex Color', default=True + ) + edges_use_vertex_color: BoolProperty( + update=update_mode, name='Edges Vertex Color', default=True + ) + edge_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' @@ -406,21 +635,32 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): r0.prop(self, "mode") c0 = layout.column(align=True) c0.prop(self, "background_color") - + if self.mode == 'Number': row = c0.row(align=True) for j in range(2): row.prop(self, 'drawing_size', index=j, text='XY'[j]) - c0.prop(self, 'continuous') + row = c0.row(align=True) + row.prop(self, "point_size") + row.prop(self, "edge_width") + c0.prop(self, "edges_use_vertex_color") # elif self.mode == 'Path': else: + row = c0.row(align=True) + row.prop(self, "working_plane", expand=True) c0.prop(self, "draw_scale") row = c0.row(align=True) - row.prop(self, "draw_verts") row.prop(self, "point_size") + row.prop(self, "edge_width") + + c0.prop(self, "edges_use_vertex_color") + if self.mode == 'Mesh': + c0.prop(self, "polygon_use_vertex_color") if self.mode == "Path": layout.prop(self, "cyclic") - + if self.mode == "Curve": + layout.prop(self, "curve_samples") + def draw_buttons_ext(self, context, l): l.prop(self, "selected_theme_mode") @@ -429,17 +669,18 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): self.inputs.new('SvVerticesSocket', "Vecs") self.inputs.new('SvStringsSocket', "Edges") self.inputs.new('SvStringsSocket', "Polygons") + self.inputs.new('SvCurveSocket', "Curve") vc0 = self.inputs.new('SvColorSocket', "Vector Color") vc0.prop_name = 'vector_color' vc0.custom_draw = 'draw_color_socket' - vc = self.inputs.new('SvColorSocket', "Color") + vc = self.inputs.new('SvColorSocket', "Edge Color") vc.prop_name = 'edge_color' vc.custom_draw = 'draw_color_socket' vc2 = self.inputs.new('SvColorSocket', "Polygon Color") vc2.prop_name = 'polygon_color' vc2.custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() - + def draw_color_socket(self, socket, context, layout): socket_info = socket_dict[socket.prop_name] layout.prop(self, socket_info[0], text="", icon=socket_info[1]) @@ -472,79 +713,39 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): batch = batch_for_shader(shader, gl_Type, {"pos": geom.vertices, "color": geom.vertex_colors}, indices=geom.indices) return batch, shader - def generate_graph_geom(self, config, paths): - - geom = lambda: None - x, y = config.loc - size = 140 * config.scale - scale = config.scale - # back_color, grid_color, line_color = config.palette - cyclic = config.cyclic - sys_scale = config.sys_scale - line_color = config.line_color - - all_vecs = [v for vecs in paths for v in vecs ] - maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) - # background geom - w = size - h = size - w = (maxmin[0][0]- maxmin[0][1]) * scale - h = (maxmin[1][0]- maxmin[1][1]) * scale - margin = 1 * scale - margin = 10 * sys_scale - geom.background_coords = [ - (x, y + margin), - (x + w + 2*margin, y + margin), - (w + x + 2*margin, y - h - margin), - (x, y - h - margin)] - geom.background_indices = [(0, 1, 2), (0, 2, 3)] - - vertices = [] - vertex_colors = [] - indices = [] - - idx_offset = 0 - for vecs, col in zip(paths, line_color): - graphline = [] - for v in vecs: - _px = x + (v[0] - maxmin[0][1]) * scale + margin - _py = y + (v[1] - maxmin[1][0]) * scale - graphline.append([_px, _py]) - vertex_colors.append(col) - vertices.extend(graphline) - - for i in range(len(vecs)-1): - indices.append([i + idx_offset, i + 1 + idx_offset]) - if cyclic: - indices.append([len(graphline)-1 + idx_offset, 0 + idx_offset]) - idx_offset += len(graphline) - - geom.vertices = vertices - geom.vertex_colors = vertex_colors - geom.indices = indices - return geom def process(self): + n_id = node_id(self) + nvBGL.callback_disable(n_id) + if self.mode == 'Number': - p = self.inputs['Number'].sv_get() + if not self.inputs['Number'].is_linked: + return + p = self.inputs['Number'].sv_get(default=[[]]) + elif self.mode == 'Curve': + if not self.inputs['Curve'].is_linked: + return + curves = self.inputs['Curve'].sv_get(default=[[]]) else: - p = self.inputs['Vecs'].sv_get() - if self.mode == 'Edges': - edges = self.inputs['Edges'].sv_get() - if self.mode == 'Polygons': - edges = self.inputs['Edges'].sv_get() - polygons_s = self.inputs['Polygons'].sv_get() - poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.polygon_color]])[0] - fullList(poly_color, len(p)) + if not self.inputs['Vecs'].is_linked: + return + p = self.inputs['Vecs'].sv_get(default=[[]]) + # if self.mode == 'Edges': + # edges = self.inputs['Edges'].sv_get(default=[[]]) + # if self.mode == 'Mesh': + edges = self.inputs['Edges'].sv_get(default=[[]]) + polygons_s = self.inputs['Polygons'].sv_get(default=[[]]) + poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.polygon_color]]) + # fullList(poly_color, len(p)) vector_color = self.inputs['Vector Color'].sv_get(default=[[self.vector_color]]) - path_color = self.inputs['Color'].sv_get(default=[[self.edge_color]])[0] - fullList(vector_color, len(p)) - fullList(path_color, len(p)) - n_id = node_id(self) + path_color = self.inputs['Edge Color'].sv_get(default=[[self.edge_color]]) + # fullList(vector_color, len(p)) + # fullList(path_color, len(p)) + # end early - nvBGL.callback_disable(n_id) + if self.activate: @@ -558,33 +759,44 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config.scale = scale*self.draw_scale config.cyclic = self.cyclic config.background_color = self.background_color + config.plane = self.working_plane config.vector_color = vector_color - config.line_color = path_color + config.edge_color = path_color config.draw_verts = self.vector_toggle + config.draw_edges = self.edge_toggle + config.draw_polys = self.polygon_toggle config.point_size = self.point_size + config.edge_width = self.edge_width config.color_per_point = self.color_per_point config.color_per_edge = self.color_per_edge config.color_per_polygon = self.color_per_polygon - + config.polygon_use_vertex_color = self.polygon_use_vertex_color + config.edges_use_vertex_color = self.edges_use_vertex_color + config.edges = edges + if self.mode == 'Number': config.size = self.drawing_size config.continuous = self.continuous geom = generate_number_geom(config, p) elif self.mode == 'Path': - geom = self.generate_graph_geom(config, p) + geom = generate_graph_geom(config, p) + elif self.mode == 'Curve': + + paths = [] + for curve in curves: + t_min, t_max = curve.get_u_bounds() + ts = np_linspace(t_min, t_max, num=self.curve_samples, dtype=np_float64) + paths.append(curve.evaluate_array(ts).tolist()) + geom = generate_graph_geom(config, paths) + elif self.mode == 'Edges': geom = generate_edges_geom(config, p, edges) else: geom = generate_polygons_geom(config, p, polygons_s, poly_color) geom2 = generate_edges_geom(config, p, edges) - # geom = generate_lines_geom(config, p, edges) - if self.mode == 'Polygons': - config.batch, config.shader = self.generate_shader(geom, 'TRIS') - config.batch2, config.shader2 = self.generate_shader(geom2, 'LINES') - else: - config.batch, config.shader = self.generate_shader(geom, 'LINES') - + + draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], -- GitLab From 69eced30f2cfd9cee5a55b3a3fc5a09058bd61ca Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 7 May 2020 02:11:20 +0200 Subject: [PATCH 07/12] start cleaning an pols_to edges if needed --- nodes/viz/viewer2d.py | 118 ++++++------------------------------------ 1 file changed, 17 insertions(+), 101 deletions(-) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index 3b21795f0..e7742af28 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -33,6 +33,7 @@ from sverchok.data_structure import updateNode, node_id, enum_item_4, fullList, from sverchok.node_tree import SverchCustomTreeNode from sverchok.ui import bgl_callback_nodeview as nvBGL from mathutils.geometry import tessellate_polygon as tessellate +from sverchok.utils.sv_mesh_utils import polygons_to_edges # star imports easing_dict and all easing functions. from sverchok.utils.sv_easing_functions import * @@ -112,7 +113,6 @@ def simple28_grid_xy(x, y, args): """ x and y are passed by default so you could add font content """ geom, config = args - back_color, grid_color, line_color = config.palette background_color = config.background_color # draw background, this could be cached...... shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') @@ -142,6 +142,7 @@ def path_from_nums(nums, x, y, num_width, num_height, maxmin, sys_scale): _py = y + ((n - maxmin[1])* num_height) * sys_scale v_path.append([_px, _py]) return v_path + def generate_number_geom(config, numbers): geom = lambda: None x, y = config.loc @@ -210,7 +211,7 @@ def generate_graph_geom(config, paths): x, y = config.loc size = 140 * config.scale scale = config.scale - # back_color, grid_color, line_color = config.palette + cyclic = config.cyclic sys_scale = config.sys_scale if config.color_per_edge: @@ -284,93 +285,6 @@ def transformed_verts(vecs, x, y, maxmin, scale, axis1, axis2): v_path.append([_px, _py]) return v_path -def generate_lines_geom(config, paths, edges): - geom = lambda: None - x, y = config.loc - size = 140 * config.scale - scale = config.scale - # back_color, grid_color, line_color = config.palette - sys_scale = config.sys_scale - line_color = config.edge_color - - all_vecs = [v for vecs in paths for v in vecs ] - maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) - # background geom - w = size - h = size - w = (maxmin[0][0]- maxmin[0][1]) * scale - h = (maxmin[1][0]- maxmin[1][1]) * scale - margin = 10 * sys_scale - geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) - - vertices = [] - vertex_colors = [] - indices = [] - - idx_offset = 0 - for vecs, edgs, col in zip(paths, edges, line_color): - - for i, e in enumerate(edgs): - v0 = vecs[e[0]] - v1 = vecs[e[1]] - _px = x + (v0[0] - maxmin[0][1]) * scale + margin - _py = y + (v0[1] - maxmin[1][0]) * scale - _px2 = x + (v1[0] - maxmin[0][1]) * scale + margin - _py2 = y + (v1[1] - maxmin[1][0]) * scale - vertices.extend([[_px, _py], [_px2, _py2]]) - vertex_colors.extend([col, col]) - indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) - - idx_offset += 2*len(edges) - - geom.vertices = vertices - geom.vertex_colors = vertex_colors - geom.indices = indices - return geom - -def generate_edges_geom(config, paths, edges): - geom = lambda: None - x, y = config.loc - size = 140 * config.scale - scale = config.scale - # back_color, grid_color, line_color = config.palette - sys_scale = config.sys_scale - line_color = config.edge_color - - all_vecs = [v for vecs in paths for v in vecs ] - maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) - # background geom - w = size - h = size - w = (maxmin[0][0]- maxmin[0][1]) * scale - h = (maxmin[1][0]- maxmin[1][1]) * scale - margin = 10 * sys_scale - geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) - - vertices = [] - vertex_colors = [] - indices = [] - - idx_offset = 0 - for vecs, edgs, col in zip(paths, edges, cycle(line_color[0])): - - for i, v in enumerate(vecs): - _px = x + (v[0] - maxmin[0][1]) * scale + margin - _py = y + (v[1] - maxmin[1][0]) * scale - vertices.append([_px, _py]) - vertex_colors.append(col) - - for e in edgs: - indices.append([e[0] + idx_offset, e[1] + idx_offset]) - - idx_offset += len(vecs) - - points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) - geom.points_color = points_color - geom.vertices = vertices - geom.vertex_colors = vertex_colors - geom.indices = indices - return geom def splitted_polygons_geom(polygon_indices, original_idx, v_path, cols, idx_offset): total_p_verts = 0 @@ -395,7 +309,7 @@ def get_axis_index(plane): return axis1, axis2 -def generate_polygons_geom(config, paths, polygons_s, poly_color): +def generate_mesh_geom(config, paths, polygons_s, poly_color): geom = lambda: None x, y = config.loc size = 140 * config.scale @@ -509,15 +423,16 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): n_id: StringProperty(default='') def update_mode(self, context): + self.update_sockets() + updateNode(self, context) + + def update_sockets(self): self.inputs['Polygon Color'].hide_safe = self.mode != 'Mesh' - # self.inputs['Edge Color'].hide_safe = self.edges_use_vertex_color self.inputs['Number'].hide_safe = not self.mode == 'Number' self.inputs['Curve'].hide_safe = not self.mode == 'Curve' self.inputs['Vecs'].hide_safe = self.mode in ['Number', 'Curve'] self.inputs['Edges'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] self.inputs['Polygons'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] - updateNode(self, context) - mode: EnumProperty( name='Mode', items=modes, @@ -562,7 +477,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): description='Point Size', update=updateNode ) edge_width: IntProperty( - min=1, default=4, name='Edge Width', + min=1, default=1, name='Edge Width', description='Edge Width', update=updateNode ) continuous: BoolProperty( @@ -656,7 +571,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): c0.prop(self, "edges_use_vertex_color") if self.mode == 'Mesh': c0.prop(self, "polygon_use_vertex_color") - if self.mode == "Path": + if self.mode in ["Path", "Curve"]: layout.prop(self, "cyclic") if self.mode == "Curve": layout.prop(self, "curve_samples") @@ -680,7 +595,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): vc2.prop_name = 'polygon_color' vc2.custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() - + self.update_sockets() def draw_color_socket(self, socket, context, layout): socket_info = socket_dict[socket.prop_name] layout.prop(self, socket_info[0], text="", icon=socket_info[1]) @@ -782,19 +697,20 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): elif self.mode == 'Path': geom = generate_graph_geom(config, p) elif self.mode == 'Curve': - paths = [] for curve in curves: t_min, t_max = curve.get_u_bounds() ts = np_linspace(t_min, t_max, num=self.curve_samples, dtype=np_float64) paths.append(curve.evaluate_array(ts).tolist()) + geom = generate_graph_geom(config, paths) - elif self.mode == 'Edges': - geom = generate_edges_geom(config, p, edges) else: - geom = generate_polygons_geom(config, p, polygons_s, poly_color) - geom2 = generate_edges_geom(config, p, edges) + if not self.inputs['Edges'].is_linked and self.edge_toggle: + config.edges = polygons_to_edges(polygons_s, unique_edges=True) + + geom = generate_mesh_geom(config, p, polygons_s, poly_color) + draw_data = { -- GitLab From 1740b1c40adca55b61612c1776f239101e5a902c Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 7 May 2020 22:37:52 +0200 Subject: [PATCH 08/12] cleaning refactoring and docs --- docs/nodes/viz/viewer_2d.rst | 50 +++++ docs/nodes/viz/viz_index.rst | 3 +- index.md | 2 +- nodes/viz/viewer2d.py | 417 ++++++++++++++++------------------- 4 files changed, 245 insertions(+), 227 deletions(-) create mode 100644 docs/nodes/viz/viewer_2d.rst diff --git a/docs/nodes/viz/viewer_2d.rst b/docs/nodes/viz/viewer_2d.rst new file mode 100644 index 000000000..21acc790b --- /dev/null +++ b/docs/nodes/viz/viewer_2d.rst @@ -0,0 +1,50 @@ +Viewer 2D +========= + +Functionality +------------- + +This node displays data it in the 2d view, using opengl and shaders. The node is intended to be a fast way to show you the result of your node tree. We've added various levels of refinements that you may find useful to better understand the virtual geometry you've created. + +Modes +----- + +Number: Displays graphically list of numbers + +Path: Displays paths using a vectors list + +Curve: Display Curves at desired resolution + +Mesh: Displays mesh data from vectors, edges and polygons list + +Features +-------- + +Background: Display background under the mesh with desired color + +Working Plane: Projection is over XY, XZ or YZ plane + +Scale: Drawing scale + +Point Size and Edge width. + +Edges Vertex Color: Uses vertex color to colorize edges + +Polygons Vertex Color: Uses vertex color to colorize polygons + +Cycle: Close Path (only in path mode) + +Vertex Color, Edge Color and Polygon Color: Color of displayed geometry. It can be color per element or color per object + + +Examples +-------- + +.. image:: https://user-images.githubusercontent.com/10011941/81240665-4d586c00-9008-11ea-8f2e-4d94a7a217fb.png +.. image:: https://user-images.githubusercontent.com/10011941/81240916-1c2c6b80-9009-11ea-82be-4866380631af.png +.. image:: https://user-images.githubusercontent.com/10011941/81241053-834a2000-9009-11ea-8bf5-b3e1fc8bbf71.png +.. image:: https://user-images.githubusercontent.com/10011941/81241195-e89e1100-9009-11ea-989c-d089d629b554.png +.. image:: https://user-images.githubusercontent.com/10011941/81241305-2dc24300-900a-11ea-8bba-26f9fb140767.png +.. image:: https://user-images.githubusercontent.com/10011941/81241480-a88b5e00-900a-11ea-9faa-c363a95c6084.png +.. image:: https://user-images.githubusercontent.com/10011941/81241852-c5746100-900b-11ea-97ba-43d0f9601409.png +.. image:: https://user-images.githubusercontent.com/10011941/81241930-05d3df00-900c-11ea-8b1f-20aaa88ff1f3.png diff --git a/docs/nodes/viz/viz_index.rst b/docs/nodes/viz/viz_index.rst index 5f6b6ec7d..f9cb6e708 100644 --- a/docs/nodes/viz/viz_index.rst +++ b/docs/nodes/viz/viz_index.rst @@ -9,6 +9,7 @@ Viz viewer_metaball viewer_waveform_output vd_draw_experimental + viewer_2d empty_out viewer_nurbs_curve viewer_nurbs_surface @@ -16,4 +17,4 @@ Viz viewer_texture viewer_texture_lite lamp_out - vd_matrix \ No newline at end of file + vd_matrix diff --git a/index.md b/index.md index e57540e33..913a4387b 100644 --- a/index.md +++ b/index.md @@ -390,6 +390,7 @@ SvVDExperimental SvMatrixViewer28 SvIDXViewer28 + SvViewer2D --- SvBmeshViewerNodeV28 SvCurveViewerNodeV28 @@ -407,7 +408,6 @@ SvTextureViewerNodeLite SvWaveformViewer SvConsoleNode - SvViewer2D ## Text ViewerNodeTextMK3 diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer2d.py index e7742af28..7edf01ffe 100644 --- a/nodes/viz/viewer2d.py +++ b/nodes/viz/viewer2d.py @@ -17,48 +17,31 @@ # ##### END GPL LICENSE BLOCK ##### from mathutils import Vector +from mathutils.geometry import tessellate_polygon as tessellate from itertools import cycle from numpy import float64 as np_float64, linspace as np_linspace import bpy -from bpy.props import FloatProperty, IntProperty, EnumProperty, StringProperty, BoolProperty, FloatVectorProperty, IntVectorProperty +from bpy.props import FloatProperty, IntProperty, EnumProperty, BoolProperty, FloatVectorProperty, IntVectorProperty -import blf import bgl import gpu from gpu_extras.batch import batch_for_shader from sverchok.utils.context_managers import sv_preferences from sverchok.core.socket_data import SvGetSocketInfo -from sverchok.data_structure import updateNode, node_id, enum_item_4, fullList, match_long_repeat +from sverchok.data_structure import updateNode, node_id from sverchok.node_tree import SverchCustomTreeNode from sverchok.ui import bgl_callback_nodeview as nvBGL -from mathutils.geometry import tessellate_polygon as tessellate from sverchok.utils.sv_mesh_utils import polygons_to_edges -# star imports easing_dict and all easing functions. -from sverchok.utils.sv_easing_functions import * + + socket_dict = { 'vector_color': ('vector_toggle', 'UV_VERTEXSEL', 'color_per_point'), 'edge_color': ('edge_toggle', 'UV_EDGESEL', 'color_per_edge'), 'polygon_color': ('polygon_toggle', 'UV_FACESEL', 'color_per_polygon'), } -palette_dict = { - "default": ( - (0.243299, 0.590403, 0.836084, 1.00), # back_color - (0.390805, 0.754022, 1.000000, 0.70), # grid_color - (1.000000, 0.330010, 0.107140, 1.00) # line_color - ), - "scope": ( - (0.274677, 0.366253, 0.386430, 1.00), # back_color - (0.423268, 0.558340, 0.584078, 1.00), # grid_color - (0.304762, 1.000000, 0.062827, 1.00) # line_color - ), - "sniper": ( - (0.2, 0.2, 0.2, 0.20), # back_color - (0.423268, 0.558340, 0.584078, 0.40), # grid_color - (0.304762, 1.000000, 0.062827, 1.00) # line_color - ) -} + def ensure_triangles(coords, indices, handle_concave_quads): """ this fully tesselates the incoming topology into tris, @@ -109,17 +92,18 @@ def fill_points_colors(vectors_color, data, color_per_point): return points_color -def simple28_grid_xy(x, y, args): +def view_2d_geom(x, y, args): """ x and y are passed by default so you could add font content """ geom, config = args - background_color = config.background_color - # draw background, this could be cached...... - shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') - batch = batch_for_shader(shader, 'TRIS', {"pos": geom.background_coords}, indices=geom.background_indices) - shader.bind() - shader.uniform_float("color", background_color) - batch.draw(shader) + if config.draw_background: + background_color = config.background_color + # draw background, this could be cached...... + shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') + batch = batch_for_shader(shader, 'TRIS', {"pos": geom.background_coords}, indices=geom.background_indices) + shader.bind() + shader.uniform_float("color", background_color) + batch.draw(shader) if config.draw_polys and config.mode == 'Mesh': config.p_batch.draw(config.p_shader) @@ -162,7 +146,7 @@ def generate_number_geom(config, numbers): _x = x + margin _y = y - h - if config.color_per_edge: + if config.color_per_edge and not config.edges_use_vertex_color: for nums, cols in zip(numbers, cycle(line_color)): num_width = w/(len(nums)-1) v_path = path_from_nums(nums, _x, _y, num_width, num_height, maxmin, sys_scale) @@ -200,67 +184,70 @@ def generate_number_geom(config, numbers): config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') config.v_batch = batch_for_shader(config.v_shader, 'POINTS', {"pos": v_vertices, "color": points_color}) if config.draw_edges: + if config.edges_use_vertex_color: + vertex_colors = points_color config.e_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') config.e_batch = batch_for_shader(config.e_shader, 'LINES', {"pos": e_vertices, "color": vertex_colors}, indices=indices) return geom + +def graph_edges(config, v_path, col, e_vertices, e_vertex_colors, e_indices, cyclic, idx_offset): + + offset = idx_offset[0] + if config.color_per_edge and not config.edges_use_vertex_color: + + for v, v1, c in zip(v_path[:-1], v_path[1:], cycle(col)): + e_vertices.extend([v, v1]) + e_vertex_colors.extend([c, c]) + + for i in range(len(v_path)-1): + e_indices.append([2*i + offset, 2*i + 1 + offset]) + if cyclic: + + e_indices.append([2 * len(v_path) - 2-1 + offset, 0 + offset]) + idx_offset[0] += 2 * len(v_path) - 2 + else: + e_vertex_colors.extend([col for v in v_path]) + e_vertices.extend(v_path) + + for i in range(len(v_path)-1): + e_indices.append([i + offset, i + 1 + offset]) + if cyclic: + e_indices.append([len(v_path)-1 + offset, 0 + offset]) + idx_offset[0] += len(v_path) + def generate_graph_geom(config, paths): geom = lambda: None x, y = config.loc - size = 140 * config.scale scale = config.scale - cyclic = config.cyclic sys_scale = config.sys_scale if config.color_per_edge: edge_color = config.edge_color else: edge_color = config.edge_color[0] - # line_color = config.edge_color all_vecs = [v for vecs in paths for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) axis1, axis2 = get_axis_index(config.plane) # background geom - w = size - h = size w = (maxmin[axis1][0]- maxmin[axis1][1]) * scale h = (maxmin[axis2][0]- maxmin[axis2][1]) * scale - margin = 1 * scale margin = 10 * sys_scale geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) v_vertices = [] e_vertices, e_vertex_colors, e_indices = [], [], [] _x = x + margin - idx_offset = 0 - for vecs, col in zip(paths, edge_color): + + idx_offset = [0] + for vecs, col in zip(paths, cycle(edge_color)): v_path = transformed_verts(vecs, _x, y, maxmin, scale, axis1, axis2) v_vertices.extend(v_path) - if not config.draw_edges: - continue - if config.color_per_edge and not config.edges_use_vertex_color: + if config.draw_edges: + graph_edges(config, v_path, col, e_vertices, e_vertex_colors, e_indices, cyclic, idx_offset) - for v, v1, col in zip(v_path[:-1], v_path[1:], cycle(col)): - e_vertices.extend([v, v1]) - e_vertex_colors.extend([col, col]) - - for i in range(len(v_path)-1): - e_indices.append([2*i + idx_offset, 2*i + 1 + idx_offset]) - if cyclic: - - e_indices.append([len(e_vertices)-1 + idx_offset, 0 + idx_offset]) - idx_offset += 2 * len(v_path) - else: - e_vertex_colors.extend([col for v in v_path]) - e_vertices.extend(v_path) - - for i in range(len(vecs)-1): - e_indices.append([i + idx_offset, i + 1 + idx_offset]) - if cyclic: - e_indices.append([len(v_path)-1 + idx_offset, 0 + idx_offset]) - idx_offset += len(v_path) points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) @@ -296,6 +283,7 @@ def splitted_polygons_geom(polygon_indices, original_idx, v_path, cols, idx_offs total_p_verts += len(p) return p_vertices, vertex_colors, indices, total_p_verts + def get_axis_index(plane): if plane == 'XY': axis1 = 0 @@ -309,30 +297,59 @@ def get_axis_index(plane): return axis1, axis2 -def generate_mesh_geom(config, paths, polygons_s, poly_color): +def polygons_geom(config, vecs, polygons, p_vertices, p_vertex_colors, p_indices, v_path, p_cols, idx_p_offset): + if config.color_per_polygon and not config.polygon_use_vertex_color: + polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) + p_v, v_c, idx, total_p_verts = splitted_polygons_geom(polygon_indices, original_idx, v_path, p_cols, idx_p_offset[0]) + p_vertices.extend(p_v) + p_vertex_colors.extend(v_c) + p_indices.extend(idx) + else: + polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) + p_vertices.extend(v_path) + p_vertex_colors.extend([p_cols for v in v_path]) + p_indices.extend([[c + idx_p_offset[0] for c in p] for p in polygon_indices]) + total_p_verts = len(vecs) + idx_p_offset[0] += total_p_verts + + +def edges_geom(config, edges, e_col, v_path, e_vertices, e_vertex_colors, e_indices, idx_e_offset): + + if config.color_per_edge and not config.edges_use_vertex_color: + for (v, v1), col in zip(edges, cycle(e_col)): + e_vertices.extend([v_path[v], v_path[v1]]) + e_vertex_colors.extend([col, col]) + e_indices.append([len(e_vertices)-2, len(e_vertices)-1]) + + else: + e_vertices.extend(v_path) + e_vertex_colors.extend([e_col for v in v_path]) + e_indices.extend([[c + idx_e_offset[0] for c in e] for e in edges ]) + idx_e_offset[0] += len(v_path) + + +def generate_mesh_geom(config, vecs_in): geom = lambda: None x, y = config.loc - size = 140 * config.scale scale = config.scale - # back_color, grid_color, line_color = config.palette sys_scale = config.sys_scale if config.color_per_polygon: - pol_color = poly_color + pol_color = config.poly_color else: - pol_color = poly_color[0] + pol_color = config.poly_color[0] if config.color_per_edge: edge_color = config.edge_color else: edge_color = config.edge_color[0] edges_s = config.edges + polygons_s = config.polygons axis1, axis2 = get_axis_index(config.plane) - all_vecs = [v for vecs in paths for v in vecs ] + all_vecs = [v for vecs in vecs_in for v in vecs ] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) # background geom - w = size - h = size + w = (maxmin[axis1][0]- maxmin[axis1][1]) * scale h = (maxmin[axis2][0]- maxmin[axis2][1]) * scale margin = 10 * sys_scale @@ -340,62 +357,38 @@ def generate_mesh_geom(config, paths, polygons_s, poly_color): v_vertices = [] e_vertices, e_vertex_colors, e_indices = [], [], [] - p_vertices = [] - p_vertex_colors = [] - p_indices = [] + p_vertices, p_vertex_colors, p_indices = [], [], [] + _x = x + margin - idx_p_offset = 0 - idx_e_offset = 0 + idx_p_offset = [0] + idx_e_offset = [0] - for vecs, polygons, edges, p_cols, e_col in zip(paths, polygons_s, edges_s, cycle(pol_color), cycle(edge_color)): + for vecs, polygons, edges, p_cols, e_col in zip(vecs_in, cycle(polygons_s), cycle(edges_s), cycle(pol_color), cycle(edge_color)): v_path = transformed_verts(vecs, _x, y, maxmin, scale, axis1, axis2) v_vertices.extend(v_path) - if config.color_per_edge and not config.edges_use_vertex_color: - for (v, v1), col in zip(edges, cycle(e_col)): - e_vertices.extend([v_path[v], v_path[v1]]) - e_vertex_colors.extend([col, col]) - e_indices.append([len(e_vertices)-2, len(e_vertices)-1]) + if config.draw_edges: + edges_geom(config, edges, e_col, v_path, e_vertices, e_vertex_colors, e_indices, idx_e_offset) + if config.draw_polys: + polygons_geom(config, vecs, polygons, p_vertices, p_vertex_colors, p_indices, v_path, p_cols, idx_p_offset) - else: - e_vertices.extend(v_path) - e_vertex_colors.extend([e_col for v in v_path]) - e_indices.extend([[c + idx_e_offset for c in e] for e in edges ]) - idx_e_offset += len(v_path) - - - if config.color_per_polygon and not config.polygon_use_vertex_color: - polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) - p_v, v_c, idx, total_p_verts = splitted_polygons_geom(polygon_indices, original_idx, v_path, p_cols, idx_p_offset) - p_vertices.extend(p_v) - p_vertex_colors.extend(v_c) - p_indices.extend(idx) - else: - polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) - p_vertices.extend(v_path) - p_vertex_colors.extend([p_cols for v in v_path]) - p_indices.extend([[c + idx_p_offset for c in p] for p in polygon_indices]) - total_p_verts = len(vecs) - - idx_p_offset += total_p_verts - - points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) - if config.polygon_use_vertex_color: - p_vertex_colors = points_color - if config.edges_use_vertex_color: - e_vertex_colors = points_color - geom.points_color = points_color - geom.points_vertices = v_vertices + points_color = fill_points_colors(config.vector_color, vecs_in, config.color_per_point) if config.draw_verts: config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') config.v_batch = batch_for_shader(config.v_shader, 'POINTS', {"pos": v_vertices, "color": points_color}) + if config.draw_edges: + if config.edges_use_vertex_color and e_vertices: + e_vertex_colors = points_color config.e_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') config.e_batch = batch_for_shader(config.e_shader, 'LINES', {"pos": e_vertices, "color": e_vertex_colors}, indices=e_indices) if config.draw_polys: + if config.polygon_use_vertex_color: + p_vertex_colors = points_color config.p_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') config.p_batch = batch_for_shader(config.p_shader, 'TRIS', {"pos": p_vertices, "color": p_vertex_colors}, indices=p_indices) + return geom @@ -420,7 +413,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): ] - n_id: StringProperty(default='') def update_mode(self, context): self.update_sockets() @@ -493,7 +485,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): size=4, min=0.0, max=1.0, subtype='COLOR' ) vector_toggle: BoolProperty( - update=updateNode, name='', default=True + update=updateNode, name='Display Vertices', default=True ) color_per_point: BoolProperty( update=updateNode, name='Color per point', default=True @@ -516,40 +508,33 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): size=4, min=0.0, max=1.0, subtype='COLOR' ) edge_toggle: BoolProperty( - update=updateNode, name='', default=True + update=updateNode, name='Display Edges', default=True ) polygon_color: FloatVectorProperty( update=updateNode, name='', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) polygon_toggle: BoolProperty( - update=updateNode, name='', default=True + update=updateNode, name='Display Polygons', default=True ) background_color: FloatVectorProperty( - update=updateNode, name='', default=(.05, .05, .05, 1.0), + update=updateNode, name='', default=(.01, .01, .01, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) - selected_theme_mode: EnumProperty( - items=enum_item_4(["default", "scope", "sniper"]), default="default", update=updateNode - ) - - def custom_draw_socket(self, socket, context, l): - info = socket.get_socket_info() - - r = l.row(align=True) - split = r.split(factor=0.85) - r1 = split.row(align=True) - r1.prop(self, 'activate', icon='NORMALIZE_FCURVES', text="") - if info: - r2 = split.row() - r2.label(text=info) + draw_background: BoolProperty( + update=updateNode, name='Display Background', default=True + ) def draw_buttons(self, context, layout): r0 = layout.row() r0.prop(self, "activate", text="", icon="HIDE_" + ("OFF" if self.activate else "ON")) r0.prop(self, "mode") c0 = layout.column(align=True) - c0.prop(self, "background_color") + row = c0.row(align=True) + row.prop(self, "draw_background", text='', icon='WORLD') + if self.draw_background: + row.prop(self, "background_color") + if self.mode == 'Number': row = c0.row(align=True) @@ -576,9 +561,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): if self.mode == "Curve": layout.prop(self, "curve_samples") - def draw_buttons_ext(self, context, l): - l.prop(self, "selected_theme_mode") - def sv_init(self, context): self.inputs.new('SvStringsSocket', "Number") self.inputs.new('SvVerticesSocket', "Vecs") @@ -596,6 +578,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): vc2.custom_draw = 'draw_color_socket' self.get_and_set_gl_scale_info() self.update_sockets() + def draw_color_socket(self, socket, context, layout): socket_info = socket_dict[socket.prop_name] layout.prop(self, socket_info[0], text="", icon=socket_info[1]) @@ -622,105 +605,98 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): x, y = [x * multiplier, y * multiplier] return x, y, scale, multiplier - - def generate_shader(self, geom, gl_Type): - shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') - batch = batch_for_shader(shader, gl_Type, {"pos": geom.vertices, "color": geom.vertex_colors}, indices=geom.indices) - return batch, shader - + def create_config(self): + config = lambda: None + x, y, scale, multiplier = self.get_drawing_attributes() + margin = 10* scale + config.mode = self.mode + config.loc = (x, y - margin) + config.sys_scale = scale + config.scale = scale * self.draw_scale + config.cyclic = self.cyclic + config.background_color = self.background_color + config.draw_background = self.draw_background + config.plane = self.working_plane + config.draw_verts = self.vector_toggle + config.draw_edges = self.edge_toggle + config.draw_polys = self.polygon_toggle and self.inputs['Polygons'].is_linked + config.point_size = self.point_size + config.edge_width = self.edge_width + config.color_per_point = self.color_per_point + config.color_per_edge = self.color_per_edge + config.color_per_polygon = self.color_per_polygon + config.polygon_use_vertex_color = self.polygon_use_vertex_color + config.edges_use_vertex_color = self.edges_use_vertex_color + + return x, y, config def process(self): n_id = node_id(self) nvBGL.callback_disable(n_id) + inputs = self.inputs + # end early + if not self.activate: + return if self.mode == 'Number': - if not self.inputs['Number'].is_linked: + if not inputs['Number'].is_linked: return - p = self.inputs['Number'].sv_get(default=[[]]) + numbers = inputs['Number'].sv_get(default=[[]]) elif self.mode == 'Curve': - if not self.inputs['Curve'].is_linked: + if not inputs['Curve'].is_linked: return - curves = self.inputs['Curve'].sv_get(default=[[]]) + curves = inputs['Curve'].sv_get(default=[[]]) else: - if not self.inputs['Vecs'].is_linked: + if not inputs['Vecs'].is_linked: return - p = self.inputs['Vecs'].sv_get(default=[[]]) - # if self.mode == 'Edges': - # edges = self.inputs['Edges'].sv_get(default=[[]]) - # if self.mode == 'Mesh': - edges = self.inputs['Edges'].sv_get(default=[[]]) - polygons_s = self.inputs['Polygons'].sv_get(default=[[]]) - poly_color = self.inputs['Polygon Color'].sv_get(default=[[self.polygon_color]]) - # fullList(poly_color, len(p)) + vecs = inputs['Vecs'].sv_get(default=[[]]) - vector_color = self.inputs['Vector Color'].sv_get(default=[[self.vector_color]]) - path_color = self.inputs['Edge Color'].sv_get(default=[[self.edge_color]]) - # fullList(vector_color, len(p)) - # fullList(path_color, len(p)) + edges = inputs['Edges'].sv_get(default=[[]]) + polygons = inputs['Polygons'].sv_get(default=[[]]) + vector_color = inputs['Vector Color'].sv_get(default=[[self.vector_color]]) + edge_color = inputs['Edge Color'].sv_get(default=[[self.edge_color]]) + poly_color = inputs['Polygon Color'].sv_get(default=[[self.polygon_color]]) + x, y, config = self.create_config() - # end early + config.vector_color = vector_color + config.edge_color = edge_color + config.poly_color = poly_color + config.edges = edges + + + if self.mode == 'Number': + config.size = self.drawing_size + config.continuous = self.continuous + geom = generate_number_geom(config, numbers) + elif self.mode == 'Path': + geom = generate_graph_geom(config, vecs) + elif self.mode == 'Curve': + paths = [] + for curve in curves: + t_min, t_max = curve.get_u_bounds() + ts = np_linspace(t_min, t_max, num=self.curve_samples, dtype=np_float64) + paths.append(curve.evaluate_array(ts).tolist()) + + geom = generate_graph_geom(config, paths) + + else: + config.polygons = polygons + if not inputs['Edges'].is_linked and self.edge_toggle: + config.edges = polygons_to_edges(polygons, unique_edges=True) + + geom = generate_mesh_geom(config, vecs) - if self.activate: - - config = lambda: None - x, y, scale, multiplier = self.get_drawing_attributes() - margin = 10* scale - config.mode = self.mode - config.loc = (x, y - margin) - config.palette = palette_dict.get(self.selected_theme_mode)[:] - config.sys_scale = scale - config.scale = scale*self.draw_scale - config.cyclic = self.cyclic - config.background_color = self.background_color - config.plane = self.working_plane - config.vector_color = vector_color - config.edge_color = path_color - config.draw_verts = self.vector_toggle - config.draw_edges = self.edge_toggle - config.draw_polys = self.polygon_toggle - config.point_size = self.point_size - config.edge_width = self.edge_width - config.color_per_point = self.color_per_point - config.color_per_edge = self.color_per_edge - config.color_per_polygon = self.color_per_polygon - config.polygon_use_vertex_color = self.polygon_use_vertex_color - config.edges_use_vertex_color = self.edges_use_vertex_color - config.edges = edges - - - if self.mode == 'Number': - config.size = self.drawing_size - config.continuous = self.continuous - geom = generate_number_geom(config, p) - elif self.mode == 'Path': - geom = generate_graph_geom(config, p) - elif self.mode == 'Curve': - paths = [] - for curve in curves: - t_min, t_max = curve.get_u_bounds() - ts = np_linspace(t_min, t_max, num=self.curve_samples, dtype=np_float64) - paths.append(curve.evaluate_array(ts).tolist()) - - geom = generate_graph_geom(config, paths) - - else: - if not self.inputs['Edges'].is_linked and self.edge_toggle: - config.edges = polygons_to_edges(polygons_s, unique_edges=True) - - geom = generate_mesh_geom(config, p, polygons_s, poly_color) - - - - draw_data = { - 'mode': 'custom_function', - 'tree_name': self.id_data.name[:], - 'loc': (x, y), - 'custom_function': simple28_grid_xy, - 'args': (geom, config) - } - nvBGL.callback_enable(n_id, draw_data) + + draw_data = { + 'mode': 'custom_function', + 'tree_name': self.id_data.name[:], + 'loc': (x, y), + 'custom_function': view_2d_geom, + 'args': (geom, config) + } + nvBGL.callback_enable(n_id, draw_data) def sv_free(self): nvBGL.callback_disable(node_id(self)) @@ -729,15 +705,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): # reset n_id on copy self.n_id = '' - def sv_update(self): - # handle disconnecting sockets, also disconnect drawing to view? - if not ("Float" in self.inputs): - return - try: - if not self.inputs[0].other: - nvBGL.callback_disable(node_id(self)) - except: - print('Easing node update holdout (not a problem)') classes = [SvViewer2D,] -- GitLab From 9e6eba5aa21f01f2015d76460e42f515d45ee005 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 7 May 2020 22:41:54 +0200 Subject: [PATCH 09/12] renaming --- nodes/viz/{viewer2d.py => viewer_2d.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename nodes/viz/{viewer2d.py => viewer_2d.py} (100%) diff --git a/nodes/viz/viewer2d.py b/nodes/viz/viewer_2d.py similarity index 100% rename from nodes/viz/viewer2d.py rename to nodes/viz/viewer_2d.py -- GitLab From 1ae7afbfa6341af80f614f754afcd562d634275b Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 7 May 2020 23:43:10 +0200 Subject: [PATCH 10/12] cleaning and some docstrings --- nodes/viz/viewer_2d.py | 81 ++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/nodes/viz/viewer_2d.py b/nodes/viz/viewer_2d.py index 7edf01ffe..31d747d34 100644 --- a/nodes/viz/viewer_2d.py +++ b/nodes/viz/viewer_2d.py @@ -16,9 +16,9 @@ # # ##### END GPL LICENSE BLOCK ##### +from itertools import cycle from mathutils import Vector from mathutils.geometry import tessellate_polygon as tessellate -from itertools import cycle from numpy import float64 as np_float64, linspace as np_linspace import bpy from bpy.props import FloatProperty, IntProperty, EnumProperty, BoolProperty, FloatVectorProperty, IntVectorProperty @@ -38,8 +38,8 @@ from sverchok.utils.sv_mesh_utils import polygons_to_edges socket_dict = { 'vector_color': ('vector_toggle', 'UV_VERTEXSEL', 'color_per_point'), - 'edge_color': ('edge_toggle', 'UV_EDGESEL', 'color_per_edge'), - 'polygon_color': ('polygon_toggle', 'UV_FACESEL', 'color_per_polygon'), + 'edge_color': ('edge_toggle', 'UV_EDGESEL', 'color_per_edge', 'edges_use_vertex_color'), + 'polygon_color': ('polygon_toggle', 'UV_FACESEL', 'color_per_polygon', 'polygon_use_vertex_color'), } def ensure_triangles(coords, indices, handle_concave_quads): @@ -48,7 +48,7 @@ def ensure_triangles(coords, indices, handle_concave_quads): not optimized for meshes that don't contain ngons """ new_indices = [] - face_index =[] + face_index = [] concat = new_indices.append concat2 = new_indices.extend for idf, idxset in enumerate(indices): @@ -93,7 +93,10 @@ def fill_points_colors(vectors_color, data, color_per_point): def view_2d_geom(x, y, args): - """ x and y are passed by default so you could add font content """ + """ + x and y are passed by default so you could add font content + draws the batches + """ geom, config = args if config.draw_background: @@ -133,7 +136,7 @@ def generate_number_geom(config, numbers): sys_scale = config.sys_scale line_color = config.edge_color w, h = config.size - all_numbers = [n for l in numbers for n in l ] + all_numbers = [n for l in numbers for n in l] maxmin = [max(all_numbers), min(all_numbers)] margin = 10 * sys_scale geom.background_coords, geom.background_indices = background_rect(x, y, w, h, margin) @@ -229,7 +232,7 @@ def generate_graph_geom(config, paths): else: edge_color = config.edge_color[0] - all_vecs = [v for vecs in paths for v in vecs ] + all_vecs = [v for vecs in paths for v in vecs] maxmin = list(zip(map(max, *all_vecs), map(min, *all_vecs))) axis1, axis2 = get_axis_index(config.plane) # background geom @@ -276,11 +279,11 @@ def transformed_verts(vecs, x, y, maxmin, scale, axis1, axis2): def splitted_polygons_geom(polygon_indices, original_idx, v_path, cols, idx_offset): total_p_verts = 0 p_vertices, vertex_colors, indices = [], [], [] - for p, idx in zip(polygon_indices, original_idx): - p_vertices.extend([v_path[c] for c in p]) - vertex_colors.extend([cols[idx % len(cols)] for c in p]) - indices.append([c + idx_offset + total_p_verts for c in range(len(p))]) - total_p_verts += len(p) + for pol, idx in zip(polygon_indices, original_idx): + p_vertices.extend([v_path[c] for c in pol]) + vertex_colors.extend([cols[idx % len(cols)] for c in pol]) + indices.append([c + idx_offset + total_p_verts for c in range(len(pol))]) + total_p_verts += len(pol) return p_vertices, vertex_colors, indices, total_p_verts @@ -298,6 +301,7 @@ def get_axis_index(plane): def polygons_geom(config, vecs, polygons, p_vertices, p_vertex_colors, p_indices, v_path, p_cols, idx_p_offset): + '''generates polygons geometry''' if config.color_per_polygon and not config.polygon_use_vertex_color: polygon_indices, original_idx = ensure_triangles(vecs, polygons, True) p_v, v_c, idx, total_p_verts = splitted_polygons_geom(polygon_indices, original_idx, v_path, p_cols, idx_p_offset[0]) @@ -314,7 +318,7 @@ def polygons_geom(config, vecs, polygons, p_vertices, p_vertex_colors, p_indices def edges_geom(config, edges, e_col, v_path, e_vertices, e_vertex_colors, e_indices, idx_e_offset): - + '''generates edges geometry''' if config.color_per_edge and not config.edges_use_vertex_color: for (v, v1), col in zip(edges, cycle(e_col)): e_vertices.extend([v_path[v], v_path[v1]]) @@ -329,6 +333,7 @@ def edges_geom(config, edges, e_col, v_path, e_vertices, e_vertex_colors, e_indi def generate_mesh_geom(config, vecs_in): + '''generates drawing from mesh data''' geom = lambda: None x, y = config.loc scale = config.scale @@ -425,6 +430,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): self.inputs['Vecs'].hide_safe = self.mode in ['Number', 'Curve'] self.inputs['Edges'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] self.inputs['Polygons'].hide_safe = self.mode in ['Number', 'Path', 'Curve'] + mode: EnumProperty( name='Mode', items=modes, @@ -436,7 +442,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): name='Proyection Plane', items=plane, default='XY', - description="Display Mode", + description="2D plane where geometry will be projected", update=update_mode) activate: BoolProperty( @@ -448,10 +454,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): default=True, update=updateNode ) - in_float: FloatProperty( - min=0.0, max=1.0, default=0.0, name='Float Input', - description='input to the easy function', update=updateNode - ) draw_scale: FloatProperty( min=0.0, default=10.0, name='Scale', description='Drawing Scale', update=updateNode @@ -472,46 +474,48 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): min=1, default=1, name='Edge Width', description='Edge Width', update=updateNode ) - continuous: BoolProperty( - name='Continuous', description='Continuous Graph', - default=True, update=updateNode - ) + curve_samples: IntProperty( min=2, default=25, name='Samples', description='Curve Resolution', update=updateNode ) vector_color: FloatVectorProperty( - update=updateNode, name='', default=(.9, .9, .95, 1.0), + update=updateNode, name='Vertices Color', default=(.9, .9, .95, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) vector_toggle: BoolProperty( update=updateNode, name='Display Vertices', default=True ) color_per_point: BoolProperty( - update=updateNode, name='Color per point', default=True + update=updateNode, name='Color per point', default=False, + description='Toggle between color per point or per object' ) color_per_edge: BoolProperty( - update=updateNode, name='Color per point', default=True + update=updateNode, name='Color per edge', default=False, + description='Toggle between color per edge or per object' ) color_per_polygon: BoolProperty( - update=updateNode, name='Color per point', default=True + update=updateNode, name='Color per polygon', default=False, + description='Toggle between color per polygon or per object' ) polygon_use_vertex_color: BoolProperty( - update=update_mode, name='Polys Vertex Color', default=True + update=update_mode, name='Polys Vertex Color', default=False, + description='Colorize polygons using vertices color' ) edges_use_vertex_color: BoolProperty( - update=update_mode, name='Edges Vertex Color', default=True + update=update_mode, name='Edges Vertex Color', default=False, + description='Colorize edges using vertices color' ) edge_color: FloatVectorProperty( - update=updateNode, name='', default=(.9, .9, .8, 1.0), + update=updateNode, name='Edges Color', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) edge_toggle: BoolProperty( update=updateNode, name='Display Edges', default=True ) polygon_color: FloatVectorProperty( - update=updateNode, name='', default=(.9, .9, .8, 1.0), + update=updateNode, name='Ploygons Color', default=(.9, .9, .8, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) polygon_toggle: BoolProperty( @@ -543,8 +547,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): row = c0.row(align=True) row.prop(self, "point_size") row.prop(self, "edge_width") - c0.prop(self, "edges_use_vertex_color") - # elif self.mode == 'Path': + else: row = c0.row(align=True) row.prop(self, "working_plane", expand=True) @@ -553,9 +556,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): row.prop(self, "point_size") row.prop(self, "edge_width") - c0.prop(self, "edges_use_vertex_color") - if self.mode == 'Mesh': - c0.prop(self, "polygon_use_vertex_color") if self.mode in ["Path", "Curve"]: layout.prop(self, "cyclic") if self.mode == "Curve": @@ -583,7 +583,12 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): socket_info = socket_dict[socket.prop_name] layout.prop(self, socket_info[0], text="", icon=socket_info[1]) layout.prop(self, socket_info[2], text="", icon='COLOR') - if not socket.is_linked: + display_color = not socket.is_linked + if len(socket_info) > 3: + layout.prop(self, socket_info[3], text="", icon='VPAINT_HLT') + display_color = display_color and not self[socket_info[3]] + + if display_color: layout.prop(self, socket.prop_name, text="") else: layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) @@ -605,9 +610,10 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): x, y = [x * multiplier, y * multiplier] return x, y, scale, multiplier + def create_config(self): config = lambda: None - x, y, scale, multiplier = self.get_drawing_attributes() + x, y, scale, _ = self.get_drawing_attributes() margin = 10* scale config.mode = self.mode config.loc = (x, y - margin) @@ -667,7 +673,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): if self.mode == 'Number': config.size = self.drawing_size - config.continuous = self.continuous geom = generate_number_geom(config, numbers) elif self.mode == 'Path': geom = generate_graph_geom(config, vecs) -- GitLab From ea0a3bc69b66fb45470eec59e15f6b0c9ecf3fd2 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Fri, 8 May 2020 00:33:18 +0200 Subject: [PATCH 11/12] random vertex color --- docs/nodes/viz/viewer_2d.rst | 9 +++--- nodes/viz/viewer_2d.py | 60 +++++++++++++++++++++++++++--------- ui/sv_vep_connector.py | 8 +++-- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/docs/nodes/viz/viewer_2d.rst b/docs/nodes/viz/viewer_2d.rst index 21acc790b..038ff60ab 100644 --- a/docs/nodes/viz/viewer_2d.rst +++ b/docs/nodes/viz/viewer_2d.rst @@ -28,14 +28,15 @@ Scale: Drawing scale Point Size and Edge width. -Edges Vertex Color: Uses vertex color to colorize edges - -Polygons Vertex Color: Uses vertex color to colorize polygons - Cycle: Close Path (only in path mode) Vertex Color, Edge Color and Polygon Color: Color of displayed geometry. It can be color per element or color per object +Random Vertex Color: Use random vertex colors + +Edges Vertex Color: Uses vertex color to colorize edges + +Polygons Vertex Color: Uses vertex color to colorize polygons Examples -------- diff --git a/nodes/viz/viewer_2d.py b/nodes/viz/viewer_2d.py index 31d747d34..0ad5f09da 100644 --- a/nodes/viz/viewer_2d.py +++ b/nodes/viz/viewer_2d.py @@ -19,6 +19,7 @@ from itertools import cycle from mathutils import Vector from mathutils.geometry import tessellate_polygon as tessellate +from mathutils.noise import random, seed_set from numpy import float64 as np_float64, linspace as np_linspace import bpy from bpy.props import FloatProperty, IntProperty, EnumProperty, BoolProperty, FloatVectorProperty, IntVectorProperty @@ -37,7 +38,7 @@ from sverchok.utils.sv_mesh_utils import polygons_to_edges socket_dict = { - 'vector_color': ('vector_toggle', 'UV_VERTEXSEL', 'color_per_point'), + 'vector_color': ('vector_toggle', 'UV_VERTEXSEL', 'color_per_point', 'vector_random_colors', 'random_seed'), 'edge_color': ('edge_toggle', 'UV_EDGESEL', 'color_per_edge', 'edges_use_vertex_color'), 'polygon_color': ('polygon_toggle', 'UV_FACESEL', 'color_per_polygon', 'polygon_use_vertex_color'), } @@ -77,17 +78,25 @@ def background_rect(x, y, w, h, margin): return background_coords, background_indices -def fill_points_colors(vectors_color, data, color_per_point): +def fill_points_colors(vectors_color, data, color_per_point, random_colors): points_color = [] if color_per_point: for cols, sub_data in zip(cycle(vectors_color), data): - - for c, n in zip(cycle(cols), sub_data): - points_color.append(c) + if random_colors: + for n in sub_data: + points_color.append([random(), random(), random(), 1]) + else: + for c, n in zip(cycle(cols), sub_data): + points_color.append(c) else: for nums, col in zip(data, cycle(vectors_color[0])): - for n in nums: - points_color.append(col) + if random_colors: + r_color = [random(),random(),random(),1] + for n in nums: + points_color.append(r_color) + else: + for n in nums: + points_color.append(col) return points_color @@ -176,7 +185,7 @@ def generate_number_geom(config, numbers): v_vertices = e_vertices - points_color = fill_points_colors(config.vector_color, numbers, config.color_per_point) + points_color = fill_points_colors(config.vector_color, numbers, config.color_per_point, config.random_colors) geom.points_color = points_color geom.points_vertices = v_vertices geom.vertices = e_vertices @@ -252,7 +261,7 @@ def generate_graph_geom(config, paths): graph_edges(config, v_path, col, e_vertices, e_vertex_colors, e_indices, cyclic, idx_offset) - points_color = fill_points_colors(config.vector_color, paths, config.color_per_point) + points_color = fill_points_colors(config.vector_color, paths, config.color_per_point, config.random_colors) if config.draw_verts: config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') @@ -376,7 +385,7 @@ def generate_mesh_geom(config, vecs_in): if config.draw_polys: polygons_geom(config, vecs, polygons, p_vertices, p_vertex_colors, p_indices, v_path, p_cols, idx_p_offset) - points_color = fill_points_colors(config.vector_color, vecs_in, config.color_per_point) + points_color = fill_points_colors(config.vector_color, vecs_in, config.color_per_point, config.random_colors) if config.draw_verts: config.v_shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') @@ -486,6 +495,13 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): vector_toggle: BoolProperty( update=updateNode, name='Display Vertices', default=True ) + vector_random_colors: BoolProperty( + update=updateNode, name='Random Vertices Color', default=False + ) + random_seed: IntProperty( + min=1, default=1, name='Random Seed', + description='Seed of random colors', update=updateNode + ) color_per_point: BoolProperty( update=updateNode, name='Color per point', default=False, description='Toggle between color per point or per object' @@ -508,7 +524,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): ) edge_color: FloatVectorProperty( - update=updateNode, name='Edges Color', default=(.9, .9, .8, 1.0), + update=updateNode, name='Edges Color', default=(.9, .9, .35, 1.0), size=4, min=0.0, max=1.0, subtype='COLOR' ) edge_toggle: BoolProperty( @@ -584,14 +600,27 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): layout.prop(self, socket_info[0], text="", icon=socket_info[1]) layout.prop(self, socket_info[2], text="", icon='COLOR') display_color = not socket.is_linked - if len(socket_info) > 3: + draw_name = True + if len(socket_info) < 5: layout.prop(self, socket_info[3], text="", icon='VPAINT_HLT') - display_color = display_color and not self[socket_info[3]] + # display_color = display_color and ((not socket_info[3] in self) and not self[socket_info[3]] ) + else: + layout.prop(self, socket_info[3], text="", icon='MOD_NOISE') + if socket_info[3] in self and self[socket_info[3]]: + layout.prop(self, socket_info[4], text="Seed") + draw_name = False + # display_color = display_color and ((not socket_info[3] in self) and not self[socket_info[3]] ) + if socket_info[3] in self: + display_color = display_color and not self[socket_info[3]] + + + if display_color: layout.prop(self, socket.prop_name, text="") else: - layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) + if draw_name: + layout.label(text=socket.name+ '. ' + SvGetSocketInfo(socket)) def get_drawing_attributes(self): """ @@ -633,6 +662,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): config.color_per_polygon = self.color_per_polygon config.polygon_use_vertex_color = self.polygon_use_vertex_color config.edges_use_vertex_color = self.edges_use_vertex_color + config.random_colors = self.vector_random_colors return x, y, config @@ -662,7 +692,7 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): vector_color = inputs['Vector Color'].sv_get(default=[[self.vector_color]]) edge_color = inputs['Edge Color'].sv_get(default=[[self.edge_color]]) poly_color = inputs['Polygon Color'].sv_get(default=[[self.polygon_color]]) - + seed_set(self.random_seed) x, y, config = self.create_config() config.vector_color = vector_color diff --git a/ui/sv_vep_connector.py b/ui/sv_vep_connector.py index 3fdf0a270..7aa9e65c4 100644 --- a/ui/sv_vep_connector.py +++ b/ui/sv_vep_connector.py @@ -27,10 +27,14 @@ def similar_sockets(node_out, node_in, term): socket_out, socket_in = -1, -1 for i, s in enumerate(node_out.outputs): + if s.hide_safe: + continue if term in s.name.casefold().replace(' ', ''): socket_out = i break for i, s in enumerate(node_in.inputs): + if s.hide_safe: + continue if term in s.name.casefold().replace(' ', ''): socket_in = i break @@ -46,7 +50,7 @@ def verts_edges_faces_connector(operator, context): if not selected_nodes: operator.report({"ERROR_INVALID_INPUT"}, 'No selected nodes to join') return {'CANCELLED'} - + previous_state = node_tree.sv_process node_tree.sv_process = False # find out which sockets to connect @@ -75,7 +79,7 @@ def verts_edges_faces_connector(operator, context): socket_out, socket_in = similar_sockets(node_out, node_in, 'facedata') if socket_out != -1 and socket_in != -1: links.new(node_out.outputs[socket_out], node_in.inputs[socket_in]) - + node_tree.sv_process = previous_state node_tree.update() -- GitLab From 03a59defe56146d0ad559c010aec45bad95223bb Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Fri, 8 May 2020 00:46:01 +0200 Subject: [PATCH 12/12] cleaning comments --- nodes/viz/viewer_2d.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nodes/viz/viewer_2d.py b/nodes/viz/viewer_2d.py index 0ad5f09da..66c02a816 100644 --- a/nodes/viz/viewer_2d.py +++ b/nodes/viz/viewer_2d.py @@ -229,6 +229,7 @@ def graph_edges(config, v_path, col, e_vertices, e_vertex_colors, e_indices, cyc e_indices.append([len(v_path)-1 + offset, 0 + offset]) idx_offset[0] += len(v_path) + def generate_graph_geom(config, paths): geom = lambda: None @@ -603,19 +604,17 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): draw_name = True if len(socket_info) < 5: layout.prop(self, socket_info[3], text="", icon='VPAINT_HLT') - # display_color = display_color and ((not socket_info[3] in self) and not self[socket_info[3]] ) + else: layout.prop(self, socket_info[3], text="", icon='MOD_NOISE') if socket_info[3] in self and self[socket_info[3]]: layout.prop(self, socket_info[4], text="Seed") draw_name = False - # display_color = display_color and ((not socket_info[3] in self) and not self[socket_info[3]] ) + if socket_info[3] in self: display_color = display_color and not self[socket_info[3]] - - if display_color: layout.prop(self, socket.prop_name, text="") else: @@ -723,7 +722,6 @@ class SvViewer2D(bpy.types.Node, SverchCustomTreeNode): geom = generate_mesh_geom(config, vecs) - draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], -- GitLab