def process(self): data = self.inputs['data'].sv_get(deepcopy=False, default=[]) items = self.inputs['Item'].sv_get(deepcopy=False, default=[]) if not all((data, items)): self.outputs['Index'].sv_set([]) return start_indexes = self.inputs['Start index'].sv_get(deepcopy=False) end_indexes = self.inputs['End index'].sv_get(deepcopy=False) unpack_data = list(list_level_iter(data, self.level)) max_len = max(len(unpack_data), len(items), len(start_indexes), len(end_indexes)) out_indexes = [] for lst, its, starts, ends in zip(repeat_last(unpack_data), fixed_iter(items, max_len), fixed_iter(start_indexes, max_len), fixed_iter(end_indexes, max_len)): indexes = [] for it, s, e in zip(its, repeat_last(starts), repeat_last(ends)): try: indexes.append( lst.index(it, *([s, e] if self.use_range else []))) except ValueError: indexes.append(-1) out_indexes.append(indexes) self.outputs['Index'].sv_set(out_indexes)
def apply_nested_matrices_np( vertices: np.ndarray, edges: np.ndarray, faces: List[PyFaces], matrices: List[List[Matrix]], do_join: bool ) -> Tuple[List[np.ndarray], List[np.ndarray], List[PyFaces]]: # Get list of Sverchok meshes and list of list of matrices # List of matrices applies to a mesh, each matrices copy the mesh inside an object max_objects = max( [len(func_input) for func_input in [vertices, edges, faces, matrices]]) vertices = repeat_last(vertices) edges = repeat_last(edges) faces = repeat_last(faces) matrices = repeat_last(matrices) meshes: List[Tuple[PyVertices, PyEdges, PyFaces]] = [] for i, obj_vertices, obj_edges, obj_faces, obj_matrices in zip( range(max_objects), vertices, edges, faces, matrices): meshes.append( copy_object_and_transform_np(obj_vertices, obj_edges, obj_faces, obj_matrices)) if do_join: mesh = mesh_join_np(*list(zip(*meshes)), False) return [[mesh_element] for mesh_element in mesh] else: return list(zip(*meshes))
def process(self): if not all([node.inputs.values, node.inputs.data]): # it would be better to place such checking into class decorator but too lazy node.outputs.closest_values, node.outputs.closest_indexes = [], [] return extended_data = np.array(node.inputs.data + [-np.inf, np.inf]) sorting_indexes = np.argsort(extended_data) if node.props.mode == 'range': if not node.inputs.range: node.outputs.closest_values, node.outputs.closest_indexes = [], [] return len_input = max([len(node.inputs.values), len(node.inputs.range)]) values = np.fromiter(repeat_last(node.inputs.values), float, count=len_input) range_values = np.fromiter(repeat_last(node.inputs.range), float, count=len_input) l_values = values - range_values l_indexes = np.searchsorted(extended_data, l_values, side='right', sorter=sorting_indexes) r_values = values + range_values r_indexes = np.searchsorted(extended_data, r_values, side='right', sorter=sorting_indexes) closest_indexes = [[sorting_indexes[i] for i in range(l, r)] for l, r in zip(l_indexes, r_indexes)] node.outputs.closest_indexes = closest_indexes node.outputs.closest_values = [extended_data[ci].tolist() for ci in closest_indexes] else: right_indexes = np.searchsorted(extended_data, node.inputs.values, sorter=sorting_indexes) left_indexes = right_indexes - 1 left_distance = node.inputs.values - extended_data[sorting_indexes[left_indexes]] left_distance = np.where(left_distance < 0, -left_distance, left_distance) right_distance = extended_data[sorting_indexes[right_indexes]] - node.inputs.values right_distance = np.where(right_distance < 0, -right_distance, right_distance) result_indexes = np.where(left_distance < right_distance, left_indexes, right_indexes) node.outputs.closest_indexes = sorting_indexes[result_indexes].tolist() node.outputs.closest_values = extended_data[node.outputs.closest_indexes].tolist()
def regenerate_curve(self, curve_name: str, vertices: Union[List[list], List[np.ndarray]], spline_type: str = 'POLY', vertices_radius: Union[List[list], List[np.ndarray]] = None, close_spline: Union[List[bool], List[int]] = None, use_smooth: bool = True, tilt: Union[List[list], List[np.ndarray]] = None): # Be aware that curve consists multiple splines if not self.curve: self.curve = bpy.data.curves.new( name=curve_name, type='CURVE') # type ['CURVE', 'SURFACE', 'FONT'] if len(self.curve.splines) != len(vertices) \ or any(len(s.points) != len(v) for s, v in zip(self.curve.splines, vertices)): # if at least on spline has wrong number of points whole list of splines should be recreated # thanks to Blender API self.curve.splines.clear() [self.curve.splines.new(spline_type) for _ in range(len(vertices))] [ s.points.add(len(v) - 1) for s, v in zip(self.curve.splines, vertices) ] for s, v, r, t, c in zip(self.curve.splines, vertices, repeat_last(vertices_radius or [None]), repeat_last(tilt or [None]), repeat_last(close_spline)): v = np.asarray(v, dtype=np.float32) if r is None: r = np.ones(len(v), dtype=np.float32) r = np.asarray(r, dtype=np.float32) self._regenerate_spline(s, v, spline_type, r, t, c, use_smooth)
def process(self): vals = self.inputs['Values'].sv_get(deepcopy=False) data = self.inputs['Data'].sv_get(deepcopy=False, default=[]) _range = self.inputs['Range'].sv_get(deepcopy=False) obj_n = max(len(vals), len(data), len(_range)) out = [] ind_out = [] for v, d, r in zip(fixed_iter(vals, obj_n, []), fixed_iter(data, obj_n, []), fixed_iter(_range, obj_n, [])): if not all((v, d, r)): break extended_data = np.array(d + [-np.inf, np.inf]) sorting_indexes = np.argsort(extended_data) if self.mode == 'range': len_input = max([len(v), len(r)]) values = np.fromiter(repeat_last(v), float, count=len_input) range_values = np.fromiter(repeat_last(r), float, count=len_input) l_values = values - range_values l_indexes = np.searchsorted(extended_data, l_values, side='right', sorter=sorting_indexes) r_values = values + range_values r_indexes = np.searchsorted(extended_data, r_values, side='right', sorter=sorting_indexes) closest_indexes = [[sorting_indexes[i] for i in range(l, r)] for l, r in zip(l_indexes, r_indexes)] ind_out.append(closest_indexes) out.append( [extended_data[ci].tolist() for ci in closest_indexes]) else: right_indexes = np.searchsorted(extended_data, v, sorter=sorting_indexes) left_indexes = right_indexes - 1 left_distance = v - extended_data[ sorting_indexes[left_indexes]] left_distance = np.where(left_distance < 0, -left_distance, left_distance) right_distance = extended_data[ sorting_indexes[right_indexes]] - v right_distance = np.where(right_distance < 0, -right_distance, right_distance) result_indexes = np.where(left_distance < right_distance, left_indexes, right_indexes) ind_out.append(sorting_indexes[result_indexes].tolist()) out.append(extended_data[ind_out[-1]].tolist()) self.outputs['Closest values'].sv_set(out) self.outputs['Closest indexes'].sv_set(ind_out)
def get(self, data, new_items, level, items, f): if level == 1: item_iter = repeat_last(items) new_item_iter = repeat_last(new_items) return [self.get(obj, next(new_item_iter), level-1, next(item_iter), f) for obj in data] elif level: return [self.get(obj, new_items, level-1, items, f) for obj in data] else: return f(data, new_items, items)
def set_uv_edit_mode(verts: list, faces: list, mesh: bpy.types.Mesh, uv_name: str, matrix=None): with bmesh_from_edit_mesh(mesh) as bm: uv_layer = bm.loops.layers.uv.get(uv_name) for f, bmf in zip(repeat_last(faces), bm.faces): for i, bml in zip(repeat_last(f), bmf.loops): co = verts[i] uv = Vector( co[:2]) if matrix is None else (matrix @ Vector(co))[:2] bml[uv_layer].uv = uv
def get_(self, data, level, indexes, func): # get is build-in method of Node class """iterative function to get down to the requested level""" if level == 1: obj_num = max(len(data), len(indexes)) index_iter = repeat_last(indexes) data_iter = repeat_last(data) return [ self.get_(next(data_iter), level - 1, next(index_iter), func) for _ in range(obj_num) ] elif level: return [self.get_(obj, level - 1, indexes, func) for obj in data] else: return func(data, indexes)
def process(self): color_socket = self.inputs["Color"] index_socket = self.inputs["Index"] # self upgrade, shall only be called once if encountered. if color_socket.bl_idname == 'StringsSocket': color_socket.replace_socket('SvColorSocket') objects = self.inputs["Object"].sv_get() color_data = color_socket.sv_get(deepcopy=False, default=[None]) index_data = index_socket.sv_get(deepcopy=False, default=[None]) num_components = int(len(self.vcol_size)) for obj, input_colors, indices in zip(objects, repeat_last(color_data), repeat_last(index_data)): if not input_colors: continue loops = obj.data.loops loop_count = len(loops) vertex_color = self.get_vertex_color_layer(obj) colors = np.empty(loop_count * num_components, dtype=np.float32) # we have index and colors, set colors of incoming index # first get all colors so we can write to them if self.clear: colors.shape = (loop_count, num_components) colors[:] = self.clear_c[:num_components] elif index_socket.is_linked: vertex_color.data.foreach_get("color", colors) colors.shape = (loop_count, num_components) standard_params = obj, index_socket, indices, input_colors, colors if self.mode == "vertices": set_vertices(loop_count, *standard_params) elif self.mode == "polygons": set_polygons(len(obj.data.polygons), *standard_params) elif self.mode == "loops": set_loops(loop_count, *standard_params) # write out data colors.shape = (loop_count * num_components, ) vertex_color.data.foreach_set("color", colors) obj.data.update()
def process(self): if not any(s.is_linked for s in self.outputs): return if self.inputs['Vertices'].is_linked: verts = self.inputs['Vertices'].sv_get() verts = dataCorrect(verts) t_ins = self.inputs['Interval'].sv_get() verts_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): pts = np.array(v).T tmp = np.apply_along_axis(np.linalg.norm, 0, pts[:, :-1]-pts[:, 1:]) t = np.insert(tmp, 0, 0).cumsum() t = t/t[-1] t_corr = [min(1, max(t_c, 0)) for t_c in t_in] # this should also be numpy if self.mode == 'LIN': out = [np.interp(t_corr, t, pts[i]) for i in range(3)] verts_out.append(list(zip(*out))) else: # SPL spl = cubic_spline(v, t) out = eval_spline(spl, t, t_corr) verts_out.append(out) self.outputs['Vertices'].sv_set(verts_out)
def process(self): if not any(s.is_linked for s in self.outputs): return if self.inputs["Vertices"].is_linked and self.inputs["Poly Egde"].is_linked: verts = self.inputs["Vertices"].sv_get() poly = self.inputs["Poly Egde"].sv_get() verts = dataCorrect(verts) poly = dataCorrect(poly) self.inputs["Mask"].sv_get(default=[[1, 0]]) has_true_out = True has_false_out = False verts_out = [] poly_edge_out = [] for ve, pe, ma in zip(verts, poly, repeat_last(mask)): current_mask = islice(cycle(ma), len(ve)) vert_index = [i for i, m in enumerate(current_mask) if m] if len(vert_index) < len(ve): index_set = set(vert_index) if has_true_out: vert_dict = {j: i for i, j in enumerate(vert_index)} new_vert = [ve[i] for i in vert_index] is_ss = index_set.issuperset new_pe = [[vert_dict[n] for n in fe] for fe in pe if is_ss(fe)] verts_out.append(new_vert) poly_edge_out.append(new_pe) else: # no reprocessing needed verts_out.append(ve) poly_edge_out.append(pe) self.outputs["Vertices"].sv_set(verts_out) self.outputs["Poly Egde"].sv_set(poly_edge_out)
def process(self): if not any(s.is_linked for s in self.outputs): return if not self.inputs['Vertices'].is_linked: return verts = Vector_generate(self.inputs['Vertices'].sv_get()) polys = self.inputs['PolyEdge'].sv_get(default=[[]]) distance = self.inputs['Distance'].sv_get(default=[self.distance])[0] has_double_out = self.outputs['Doubles'].is_linked verts_out = [] edges_out = [] polys_out = [] d_out = [] for v, p, d in zip(verts, polys, repeat_last(distance)): res = remove_doubles(v, p, d, has_double_out) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) d_out.append(res[3]) self.outputs['Vertices'].sv_set(verts_out) # restrict setting this output when there is no such input if self.inputs['PolyEdge'].is_linked: self.outputs['Edges'].sv_set(edges_out) self.outputs['Polygons'].sv_set(polys_out) if self.outputs['Doubles'].is_linked: self.outputs['Doubles'].sv_set(d_out)
def process(self): if 'vertices' in self.inputs and self.inputs['vertices'].is_linked and \ 'edges' in self.inputs and self.inputs['edges'].is_linked: verts = dataCorrect( SvGetSocketAnyType(self, self.inputs['vertices'])) edges = dataCorrect(SvGetSocketAnyType(self, self.inputs['edges'])) sides = repeat_last(self.inputs['Sides'].sv_get()[0]) verts_out = [] edges_out = [] polys_out = [] for v, e, s in zip(verts, edges, sides): res = fill_holes(v, e, int(s)) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) if 'vertices' in self.outputs and self.outputs[ 'vertices'].is_linked: SvSetSocketAnyType(self, 'vertices', verts_out) if 'edges' in self.outputs and self.outputs['edges'].is_linked: SvSetSocketAnyType(self, 'edges', edges_out) if 'polygons' in self.outputs and self.outputs[ 'polygons'].is_linked: SvSetSocketAnyType(self, 'polygons', polys_out)
def process(self): if not any(s.is_linked for s in self.outputs): return if self.inputs['Vertices'].is_linked and self.inputs[ 'Poly Egde'].is_linked: verts = self.inputs['Vertices'].sv_get() poly = self.inputs['Poly Egde'].sv_get() verts = dataCorrect(verts) poly = dataCorrect(poly) self.inputs['Mask'].sv_get(default=[[1, 0]]) has_true_out = True has_false_out = False verts_out = [] poly_edge_out = [] for ve, pe, ma in zip(verts, poly, repeat_last(mask)): current_mask = islice(cycle(ma), len(ve)) vert_index = [i for i, m in enumerate(current_mask) if m] if len(vert_index) < len(ve): index_set = set(vert_index) if has_true_out: vert_dict = {j: i for i, j in enumerate(vert_index)} new_vert = [ve[i] for i in vert_index] is_ss = index_set.issuperset new_pe = [[vert_dict[n] for n in fe] for fe in pe if is_ss(fe)] verts_out.append(new_vert) poly_edge_out.append(new_pe) else: # no reprocessing needed verts_out.append(ve) poly_edge_out.append(pe) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Poly Egde'].sv_set(poly_edge_out)
def process(self): inputs, outputs = self.inputs, self.outputs if not all(s.is_linked for s in [inputs['vertices'], inputs['polygons']]): return poly_or_edge_linked = (outputs['edges'].is_linked or outputs['polygons'].is_linked) if not (outputs['vertices'].is_linked and poly_or_edge_linked): # doesn't make a lot of sense to process or even # output edges/polygons without the assocated vertex locations return verts = Vector_generate(inputs['vertices'].sv_get()) polys = inputs['polygons'].sv_get() thickness = inputs['thickness'].sv_get()[0] verts_out = [] edges_out = [] polys_out = [] for v, p, t in zip(verts, polys, repeat_last(thickness)): res = wireframe(v, p, t, self) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) outputs['vertices'].sv_set(verts_out) outputs['edges'].sv_set(edges_out) outputs['polygons'].sv_set(polys_out)
def process(self): color_socket = self.inputs["Color"] index_socket = self.inputs["Index"] # self upgrade, shall only be called once if encountered. if color_socket.bl_idname == 'StringsSocket': color_socket.replace_socket('SvColorSocket') objects = self.inputs["Object"].sv_get() color_data = color_socket.sv_get(deepcopy=False, default=[None]) index_data = index_socket.sv_get(deepcopy=False, default=[None]) num_components = int(len(self.vcol_size)) for obj, input_colors, indices in zip(objects, repeat_last(color_data), repeat_last(index_data)): if not input_colors: continue loops = obj.data.loops loop_count = len(loops) vertex_color = self.get_vertex_color_layer(obj) colors = np.empty(loop_count * num_components, dtype=np.float32) # we have index and colors, set colors of incoming index # first get all colors so we can write to them if self.clear: colors.shape = (loop_count, num_components) colors[:] = self.clear_c[:num_components] elif index_socket.is_linked: vertex_color.data.foreach_get("color", colors) colors.shape = (loop_count, num_components) standard_params = obj, index_socket, indices, input_colors, colors if self.mode == "vertices": set_vertices(loop_count, *standard_params) elif self.mode == "polygons": set_polygons(len(obj.data.polygons), *standard_params) elif self.mode == "loops": set_loops(loop_count, *standard_params) # write out data colors.shape = (loop_count * num_components,) vertex_color.data.foreach_set("color", colors) obj.data.update()
def get(self, data, level, items, f): if level == 1: item_iter = repeat_last(items) return [self.get(obj, level-1, next(item_iter), f) for obj in data] elif level: return [self.get(obj, level-1, items, f) for obj in data] else: return f(data, items)
def process(self): if not any((s.is_linked for s in self.outputs)): return calc_tanget = self.outputs['Tanget'].is_linked or self.outputs['Unit Tanget'].is_linked norm_tanget = self.outputs['Unit Tanget'].is_linked h = self.h if self.inputs['Vertices'].is_linked: verts = self.inputs['Vertices'].sv_get() verts = dataCorrect(verts) t_ins = self.inputs['Interval'].sv_get() if self.infer_from_integer_input: t_ins = [make_range(int(value)) for value in t_ins[0]] if len(t_ins) > len(verts): new_verts = verts[:] for i in range(len(t_ins) - len(verts)): new_verts.append(verts[-1]) verts = new_verts verts_out = [] tanget_out = [] norm_tanget_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): t_corr = np.array(t_in).clip(0, 1) if self.mode == 'LIN': spline = LinearSpline(v, metric = self.knot_mode, is_cyclic = self.is_cyclic) out = spline.eval(t_corr) verts_out.append(out.tolist()) if calc_tanget: tanget_out.append(spline.tangent(t_corr).tolist()) else: # SPL spline = CubicSpline(v, metric = self.knot_mode, is_cyclic = self.is_cyclic) out = spline.eval(t_corr) verts_out.append(out.tolist()) if calc_tanget: tangent = spline.tangent(t_corr, h) if norm_tanget: norm = np.linalg.norm(tangent, axis=1) norm_tanget_out.append((tangent / norm[:, np.newaxis]).tolist()) tanget_out.append(tangent.tolist()) outputs = self.outputs if outputs['Vertices'].is_linked: outputs['Vertices'].sv_set(verts_out) if outputs['Tanget'].is_linked: outputs['Tanget'].sv_set(tanget_out) if outputs['Unit Tanget'].is_linked: outputs['Unit Tanget'].sv_set(norm_tanget_out)
def get(self, data, level, indexes, func): '''iterative fucntion to get down to the requested level''' if level == 1: index_iter = repeat_last(indexes) return [self.get(obj, level-1, next(index_iter), func) for obj in data] elif level: return [self.get(obj, level-1, indexes, func) for obj in data] else: return func(data, indexes)
def process(self): vertices = self.inputs['Vertices'].sv_get(default=[], deepcopy=False) edges = self.inputs['Edges'].sv_get(default=[], deepcopy=False) faces = self.inputs['Faces'].sv_get(default=[], deepcopy=False) matrices = self.inputs['Matrices'].sv_get(default=[], deepcopy=False) object_number = max([len(vertices), len(matrices)]) if vertices else 0 meshes = [] for i, *elements, matrix in zip(range(object_number), repeat_last(vertices), repeat_last(edges or [[]]), repeat_last(faces or [[]]), repeat_last(matrices or [[]])): if matrix: if not isinstance(matrix, (list, tuple)): # most likely it is Matrix or np.ndarray # but the node expects list of list of matrices as input matrix = [matrix] sub_meshes = [] for mat in matrix: mesh = me.to_mesh( *elements ) if self.implementation != 'NumPy' else me.NpMesh( *elements) mesh.apply_matrix(mat) sub_meshes.append(mesh) sub_mesh = reduce(lambda m1, m2: m1.add_mesh(m2), sub_meshes) else: sub_mesh = me.to_mesh( *elements ) if self.implementation != 'NumPy' else me.NpMesh(*elements) meshes.append(sub_mesh) if self.do_join and meshes: meshes = [reduce(lambda m1, m2: m1.add_mesh(m2), meshes)] self.outputs['Vertices'].sv_set([m.vertices.data for m in meshes]) self.outputs['Edges'].sv_set([m.edges.data for m in meshes]) self.outputs['Faces'].sv_set([m.polygons.data for m in meshes])
def process(self): inputs = self.inputs outputs = self.outputs # no outputs, end early. if not outputs['Value'].is_linked: return value_in = iter(inputs[0].sv_get()) param = [repeat_last(inputs[i].sv_get()[0]) for i in range(1, 5)] out = [self.map_range(*args) for args in zip(value_in, *param)] self.outputs['Value'].sv_set(out)
def process(self): objects = self.inputs['Object'].sv_get(deepcopy=False, default=[]) v_normals = self.inputs['Vert normals'].sv_get(deepcopy=False, default=[]) faces = self.inputs['Faces'].sv_get(deepcopy=False, default=[]) for obj, v_ns, fs in zip(objects, repeat_last(v_normals), repeat_last(faces)): obj.data.use_auto_smooth = True n_per_loop = [(0, 0, 0) for _ in range(len(obj.data.loops))] for me_p, f in zip(obj.data.polygons, fs): for l_i, f_i in zip(range(me_p.loop_start, me_p.loop_start + me_p.loop_total), repeat_last(f)): try: normal = v_ns[f_i] except IndexError: normal = v_ns[-1] n_per_loop[l_i] = Vector(normal).normalized() if self.normalize else normal obj.data.normals_split_custom_set(n_per_loop) self.outputs['Object'].sv_set(objects)
def interpol(self, verts, t_ins): verts_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): pts = np.array(v).T tmp = np.apply_along_axis(np.linalg.norm, 0, pts[:, :-1] - pts[:, 1:]) t = np.insert(tmp, 0, 0).cumsum() t = t / t[-1] t_corr = [min(1, max(t_c, 0)) for t_c in t_in] spl = cubic_spline(v, t) out = eval_spline(spl, t, t_corr) verts_out.append(out) return verts_out
def process(self): objects = self.inputs["Object"].sv_get() color_socket = self.inputs["Color"] index_socket = self.inputs["Index"] color_data = color_socket.sv_get(deepcopy=False, default=[None]) index_data = index_socket.sv_get(deepcopy=False, default=[None]) for obj, input_colors, indices in zip(objects, repeat_last(color_data), repeat_last(index_data)): if not input_colors: continue loops = obj.data.loops loop_count = len(loops) vertex_color = self.get_vertex_color_layer(obj) colors = np.empty(loop_count * 4, dtype=np.float32) # we have index and colors, set colors of incoming index # first get all colors so we can write to them if self.clear: colors.shape = (loop_count, 4) colors[:] = self.clear_c elif index_socket.is_linked: vertex_color.data.foreach_get("color", colors) colors.shape = (loop_count, 4) standard_params = obj, index_socket, indices, input_colors, colors if self.mode == "vertices": set_vertices(loop_count, *standard_params) elif self.mode == "polygons": set_polygons(len(obj.data.polygons), *standard_params) elif self.mode == "loops": set_loops(loop_count, *standard_params) # write out data colors.shape = (loop_count * 4,) vertex_color.data.foreach_set("color", colors) obj.data.update()
def process(self): if 'Unit Tanget' not in self.outputs: return if not any((s.is_linked for s in self.outputs)): return calc_tanget = self.outputs['Tanget'].is_linked or self.outputs['Unit Tanget'].is_linked norm_tanget = self.outputs['Unit Tanget'].is_linked h = self.h if self.inputs['Vertices'].is_linked: verts = self.inputs['Vertices'].sv_get() verts = dataCorrect(verts) t_ins = self.inputs['Interval'].sv_get() verts_out = [] tanget_out = [] norm_tanget_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): t_corr = np.array(t_in).clip(0, 1) if self.mode == 'LIN': spline = LinearSpline(v, metric = self.knot_mode, is_cyclic = self.is_cyclic) out = spline.eval(t_corr) verts_out.append(out.tolist()) if calc_tanget: tanget_out.append(spline.tangent(t_corr).tolist()) else: # SPL spline = CubicSpline(v, metric = self.knot_mode, is_cyclic = self.is_cyclic) out = spline.eval(t_corr) verts_out.append(out.tolist()) if calc_tanget: tangent = spline.tangent(t_corr, h) if norm_tanget: norm = np.linalg.norm(tangent, axis=1) norm_tanget_out.append((tangent / norm[:, np.newaxis]).tolist()) tanget_out.append(tangent.tolist()) outputs = self.outputs if outputs['Vertices'].is_linked: outputs['Vertices'].sv_set(verts_out) if outputs['Tanget'].is_linked: outputs['Tanget'].sv_set(tanget_out) if outputs['Unit Tanget'].is_linked: outputs['Unit Tanget'].sv_set(norm_tanget_out)
def set_polygons(polygon_count, obj, index_socket, indices, input_colors, colors): p_start = np.empty(polygon_count, dtype=int) p_total = np.empty(polygon_count, dtype=int) obj.data.polygons.foreach_get("loop_start", p_start) obj.data.polygons.foreach_get("loop_total", p_total) if index_socket.is_linked: for idx, color in zip(indices, input_colors): start_slice = p_start[idx] stop_slice = start_slice + p_total[idx] colors[start_slice:stop_slice] = color else: for start_slice, total_slice, color in zip(p_start, p_total, repeat_last(input_colors)): colors[start_slice:start_slice + total_slice] = color
def get(self, data, level, size): if not isinstance(data, (list, tuple)): return data if not isinstance(data[0], (list, tuple)): return data if level > 1: # find level to work on return [self.get(d, level - 1, size) for d in data] elif level == 1: # execute the chosen function sizes = repeat_last(size) if self.unwrap: return list(chain.from_iterable((split(d, next(sizes)) for d in data))) else: return [split(d, next(sizes)) for d in data] else: # Fail return None
def get(self, data, level, size): if not isinstance(data, (list, tuple)): return data if not isinstance(data[0], (list, tuple, np.ndarray)): return data if level > 1: # find level to work on return [self.get(d, level - 1, size) for d in data] elif level == 1: # execute the chosen function sizes = repeat_last(size) if self.unwrap: return list(chain.from_iterable((split(d, next(sizes)) for d in data))) else: return [split(d, next(sizes)) for d in data] else: # Fail return None
def interpol(self, verts, t_ins): verts_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): pts = np.array(v).T tmp = np.apply_along_axis(np.linalg.norm, 0, pts[:, :-1]-pts[:, 1:]) t = np.insert(tmp, 0, 0).cumsum() t = t/t[-1] t_corr = [min(1, max(t_c, 0)) for t_c in t_in] # this should also be numpy if self.mode == 'LIN': out = [np.interp(t_corr, t, pts[i]) for i in range(3)] verts_out.append(list(zip(*out))) else: # SPL spl = cubic_spline(v, t) out = eval_spline(spl, t, t_corr) verts_out.append(out) return verts_out
def process(self): obj_to = self.inputs['Object To'].sv_get(deepcopy=False, default=[]) obj_from = self.inputs['Object From'].sv_get(deepcopy=False, default=[]) for to, _from in zip(obj_to, repeat_last(obj_from)): # test changes, should prevent from useless mesh reevaluations presumably is_valid = True for mod_from in _from.modifiers: if mod_from.name not in to.modifiers: is_valid = False break mod_to = to.modifiers[mod_from.name] if BlModifier(mod_to) != BlModifier(mod_from): is_valid = False break else: if len(to.modifiers) != len(_from.modifiers): is_valid = False # reapply modifiers if not is_valid: to.modifiers.clear() for mod_from in _from.modifiers: mod_to = to.modifiers.new(mod_from.name, mod_from.type) # apply modifier properties for prop in (p for p in mod_from.bl_rna.properties if not p.is_readonly): setattr(mod_to, prop.identifier, getattr(mod_from, prop.identifier)) if mod_from.type == 'NODES' and mod_from.node_group: for tree_inp in mod_from.node_group.inputs[1:]: prop_name = tree_inp.identifier mod_to[prop_name] = mod_from[prop_name] mod_to[f"{prop_name}_use_attribute"] = mod_from[ f"{prop_name}_use_attribute"] mod_to[f"{prop_name}_attribute_name"] = mod_from[ f"{prop_name}_attribute_name"] for tree_out in mod_from.node_group.outputs[1:]: prop_name = tree_out.identifier mod_to[f"{prop_name}_attribute_name"] = mod_from[ f"{prop_name}_attribute_name"] self.outputs['Object'].sv_set(obj_to)
def set_uv(verts, faces, obj, uv_name, matrix=None): # Apply coordinates to UV layer unpack_uv = np.zeros((len(obj.data.loops) * 2), dtype=float) in_loops = [] # it requires checking whether given faces have the same number of loops as in the object # otherwise loops array of one polygon will shift to another what makes it difficult to debug for face, obj_face in zip(faces or [], obj.data.polygons): for i, _ in zip(repeat_last(face), obj_face.vertices): in_loops.append(verts[i]) if verts and faces: for i, co in zip(range(0, len(obj.data.loops) * 2, 2), in_loops): uv = Vector( co[:2]) if matrix is None else (matrix @ Vector(co))[:2] unpack_uv[i:i + 2] = uv obj.data.uv_layers[uv_name].data.foreach_set("uv", unpack_uv)
def process(self): if not any([s.is_linked for s in self.outputs]): return if ( "Vertices" in self.inputs and self.inputs["Vertices"].is_linked and "PolyEdge" in self.inputs and self.inputs["PolyEdge"].is_linked ): verts = Vector_generate(SvGetSocketAnyType(self, self.inputs["Vertices"])) polys = SvGetSocketAnyType(self, self.inputs["PolyEdge"]) if "Distance" in self.inputs: distance = self.inputs["Distance"].sv_get()[0] else: distance = [self.distance] if "Doubles" in self.outputs: has_double_out = bool("Doubles" in self.outputs) verts_out = [] edges_out = [] polys_out = [] d_out = [] for v, p, d in zip(verts, polys, repeat_last(distance)): res = remove_doubles(v, p, d, has_double_out) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) d_out.append(res[3]) if "Vertices" in self.outputs and self.outputs["Vertices"].is_linked: SvSetSocketAnyType(self, "Vertices", verts_out) if "Edges" in self.outputs and self.outputs["Edges"].is_linked: SvSetSocketAnyType(self, "Edges", edges_out) if "Polygons" in self.outputs and self.outputs["Polygons"].is_linked: SvSetSocketAnyType(self, "Polygons", polys_out) if "Doubles" in self.outputs and self.outputs["Doubles"].is_linked: SvSetSocketAnyType(self, "Doubles", d_out)
def process(self): if not any([s.is_linked for s in self.outputs]): return if 'Vertices' in self.inputs and self.inputs['Vertices'].is_linked and \ 'PolyEdge' in self.inputs and self.inputs['PolyEdge'].is_linked: verts = Vector_generate( SvGetSocketAnyType(self, self.inputs['Vertices'])) polys = SvGetSocketAnyType(self, self.inputs['PolyEdge']) if 'Distance' in self.inputs: distance = self.inputs['Distance'].sv_get()[0] else: distance = [self.distance] if 'Doubles' in self.outputs: has_double_out = bool('Doubles' in self.outputs) verts_out = [] edges_out = [] polys_out = [] d_out = [] for v, p, d in zip(verts, polys, repeat_last(distance)): res = remove_doubles(v, p, d, has_double_out) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) d_out.append(res[3]) if 'Vertices' in self.outputs and self.outputs[ 'Vertices'].is_linked: SvSetSocketAnyType(self, 'Vertices', verts_out) if 'Edges' in self.outputs and self.outputs['Edges'].is_linked: SvSetSocketAnyType(self, 'Edges', edges_out) if 'Polygons' in self.outputs and self.outputs[ 'Polygons'].is_linked: SvSetSocketAnyType(self, 'Polygons', polys_out) if 'Doubles' in self.outputs and self.outputs['Doubles'].is_linked: SvSetSocketAnyType(self, 'Doubles', d_out)
def process(self): if not self.inputs['Vectors'].is_linked: return vertices = self.inputs['Vectors'].sv_get(deepcopy=False) matrices = self.inputs['Matrixes'].sv_get(deepcopy=False, default=[]) is_py_input = isinstance(vertices[0], (list, tuple)) meshes = (meshes_py if is_py_input or not self.output_numpy else meshes_np)(vertices) object_number = max([len(vertices), len(matrices)]) if vertices else 0 meshes = repeat_meshes(meshes, object_number) if matrices: is_flat = not isinstance(matrices[0], (list, tuple)) meshes = (apply_matrix if is_flat else apply_matrices)( meshes, repeat_last(matrices)) out_vertices, *_ = to_elements(meshes) self.outputs['Vectors'].sv_set(out_vertices)
def process(self): if not any([s.is_linked for s in self.outputs]): return if 'Vertices' in self.inputs and self.inputs['Vertices'].is_linked and \ 'PolyEdge' in self.inputs and self.inputs['PolyEdge'].is_linked: verts = Vector_generate(SvGetSocketAnyType(self, self.inputs['Vertices'])) polys = SvGetSocketAnyType(self, self.inputs['PolyEdge']) if 'Distance' in self.inputs: distance = self.inputs['Distance'].sv_get()[0] else: distance = [self.distance] if 'Doubles' in self.outputs: has_double_out = bool('Doubles' in self.outputs) verts_out = [] edges_out = [] polys_out = [] d_out = [] for v, p, d in zip(verts, polys, repeat_last(distance)): res = remove_doubles(v, p, d, has_double_out) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) d_out.append(res[3]) if 'Vertices' in self.outputs and self.outputs['Vertices'].is_linked: SvSetSocketAnyType(self, 'Vertices', verts_out) if 'Edges' in self.outputs and self.outputs['Edges'].is_linked: SvSetSocketAnyType(self, 'Edges', edges_out) if 'Polygons' in self.outputs and self.outputs['Polygons'].is_linked: SvSetSocketAnyType(self, 'Polygons', polys_out) if 'Doubles' in self.outputs and self.outputs['Doubles'].is_linked: SvSetSocketAnyType(self, 'Doubles', d_out)
def process(self): if not any((s.is_linked for s in self.outputs)): return if self.inputs['Vertices'].is_linked and self.inputs['Poly Egde'].is_linked: verts = SvGetSocketAnyType(self, self.inputs['Vertices']) poly = SvGetSocketAnyType(self, self.inputs['Poly Egde']) verts = dataCorrect(verts) poly = dataCorrect(poly) if self.inputs['Mask'].is_linked: mask = SvGetSocketAnyType(self, self.inputs['Mask']) else: mask = [[1, 0]] has_true_out = True has_false_out = False verts_out = [] poly_edge_out = [] for ve, pe, ma in zip(verts, poly, repeat_last(mask)): current_mask = islice(cycle(ma), len(ve)) vert_index = [i for i, m in enumerate(current_mask) if m] if len(vert_index) < len(ve): index_set = set(vert_index) if has_true_out: vert_dict = {j: i for i, j in enumerate(vert_index)} new_vert = [ve[i] for i in vert_index] is_ss = index_set.issuperset new_pe = [[vert_dict[n] for n in fe] for fe in pe if is_ss(fe)] verts_out.append(new_vert) poly_edge_out.append(new_pe) else: # no reprocessing needed verts_out.append(ve) poly_edge_out.append(pe) if 'Vertices' in self.outputs and self.outputs['Vertices'].is_linked: SvSetSocketAnyType(self, 'Vertices', verts_out) if 'Poly Egde' in self.outputs and self.outputs['Poly Egde'].is_linked: if poly_edge_out: SvSetSocketAnyType(self, 'Poly Egde', poly_edge_out)
def process(self): if not (self.inputs['vertices'].is_linked and self.inputs['edges'].is_linked): return verts = dataCorrect(self.inputs['vertices'].sv_get()) edges = dataCorrect(self.inputs['edges'].sv_get()) sides = repeat_last(self.inputs['Sides'].sv_get()[0]) verts_out = [] edges_out = [] polys_out = [] for v, e, s in zip(verts, edges, sides): res = fill_holes(v, e, int(s)) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) self.outputs['vertices'].sv_set(verts_out) self.outputs['edges'].sv_set(edges_out) self.outputs['polygons'].sv_set(polys_out)
def process(self): vertices = self.inputs['Vertices'].sv_get(default=[], deepcopy=False) edges = self.inputs['Edges'].sv_get(default=[], deepcopy=False) faces = self.inputs['Faces'].sv_get(default=[], deepcopy=False) matrices = self.inputs['Matrices'].sv_get(default=[], deepcopy=False) object_number = max([len(vertices), len(matrices)]) if vertices else 0 meshes = (meshes_py if self.implementation == 'Python' else meshes_np)( vertices, edges, faces) meshes = repeat_meshes(meshes, object_number) if matrices: is_flat_list = not isinstance(matrices[0], (list, tuple)) meshes = (apply_matrix if is_flat_list else apply_matrices)( meshes, repeat_last(matrices)) if self.do_join: meshes = join_meshes(meshes) out_vertices, out_edges, out_polygons = to_elements(meshes) self.outputs['Vertices'].sv_set(out_vertices) self.outputs['Edges'].sv_set(out_edges) self.outputs['Faces'].sv_set(out_polygons)
def process(self): if not ('vertices' in self.outputs and self.outputs['vertices'].links or 'edges' in self.outputs and self.outputs['edges'].links or 'polygons' in self.outputs and self.outputs['polygons'].links): return if 'vertices' in self.inputs and self.inputs['vertices'].links and \ 'polygons' in self.inputs and self.inputs['polygons'].links: verts = Vector_generate(SvGetSocketAnyType(self, self.inputs['vertices'])) polys = SvGetSocketAnyType(self, self.inputs['polygons']) if 'thickness' in self.inputs: thickness = self.inputs['thickness'].sv_get()[0] else: thickness = [self.thickness] verts_out = [] edges_out = [] polys_out = [] for v, p, t in zip(verts, polys, repeat_last(thickness)): res = wireframe(v, p, t, self.offset, self.replace, self.boundary, self.even_offset, self.relative_offset) if not res: return verts_out.append(res[0]) edges_out.append(res[1]) polys_out.append(res[2]) if 'vertices' in self.outputs and self.outputs['vertices'].links: SvSetSocketAnyType(self, 'vertices', verts_out) if 'edges' in self.outputs and self.outputs['edges'].links: SvSetSocketAnyType(self, 'edges', edges_out) if 'polygons' in self.outputs and self.outputs['polygons'].links: SvSetSocketAnyType(self, 'polygons', polys_out)
def process(self): if 'Unit Tanget' not in self.outputs: return if not any((s.is_linked for s in self.outputs)): return calc_tanget = self.outputs['Tanget'].is_linked or self.outputs['Unit Tanget'].is_linked norm_tanget = self.outputs['Unit Tanget'].is_linked h = self.h if self.inputs['Vertices'].is_linked: verts = self.inputs['Vertices'].sv_get() verts = dataCorrect(verts) t_ins = self.inputs['Interval'].sv_get() verts_out = [] tanget_out = [] norm_tanget_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): t_corr = np.array(t_in).clip(0, 1) if self.mode == 'LIN': if self.is_cyclic: pts = np.array(v + [v[0]]) else: pts = np.array(v) tknots = create_knots(pts, metric=self.knot_mode) out = eval_linear_spline(pts, tknots, t_corr) verts_out.append(out.tolist()) else: # SPL if self.is_cyclic: pts = np.array(v[-4:] + v + v[:4]) tknots = create_knots(pts, metric=self.knot_mode) scale = 1 / (tknots[-4] - tknots[4]) base = tknots[4] tknots -= base tknots *= scale else: pts = np.array(v) tknots = create_knots(pts, metric=self.knot_mode) spl = cubic_spline(pts, tknots) out = eval_spline(spl, tknots, t_corr) verts_out.append(out.tolist()) if calc_tanget: tanget = calc_spline_tanget(spl, tknots, t_corr, h) if norm_tanget: norm = np.linalg.norm(tanget, axis=1) norm_tanget_out.append((tanget / norm[:, np.newaxis]).tolist()) tanget_out.append(tanget.tolist()) outputs = self.outputs if outputs['Vertices'].is_linked: outputs['Vertices'].sv_set(verts_out) if outputs['Tanget'].is_linked: outputs['Tanget'].sv_set(tanget_out) if outputs['Unit Tanget'].is_linked: outputs['Unit Tanget'].sv_set(norm_tanget_out)
def process(self): if 'Vertices' in self.inputs and self.inputs['Vertices'].links: verts = SvGetSocketAnyType(self, self.inputs['Vertices']) if 'PolyEdge' in self.inputs and self.inputs['PolyEdge'].links: poly_edge = SvGetSocketAnyType(self, self.inputs['PolyEdge']) polyIn = True else: polyIn = False poly_edge = repeat_last([[]]) verts_out = [] poly_edge_out = [] item_order = [] polyOutput = bool(polyIn and 'PolyEdge' in self.outputs and self.outputs['PolyEdge'].links) orderOutput = bool('Item order' in self.outputs and self.outputs['Item order'].links) vertOutput = bool('Vertices' in self.outputs and self.outputs['Vertices'].links) if not any((vertOutput, orderOutput, polyOutput)): return if self.mode == 'XYZ': # should be user settable op_order = [(0, False), (1, False), (2, False)] for v, p in zip(verts, poly_edge): s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) for item_index, rev in op_order: s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev) verts_out.append([v[:3] for v in s_v]) if polyOutput: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if orderOutput: item_order.append([i[-1] for i in s_v]) if self.mode == 'DIST': if 'Base Point' in self.inputs and self.inputs['Base Point'].links: base_points = SvGetSocketAnyType(self, self.inputs['Base Point']) bp_iter = repeat_last(base_points[0]) else: bp = [(0, 0, 0)] bp_iter = repeat_last(bp) for v, p, v_base in zip(verts, poly_edge, bp_iter): s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base)) verts_out.append([vert[0] for vert in s_v]) if polyOutput: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if orderOutput: item_order.append([i[-1] for i in s_v]) if self.mode == 'AXIS': if 'Mat' in self.inputs and self.inputs['Mat'].links: mat = Matrix_generate(SvGetSocketAnyType(self, self.inputs['Mat'])) else: mat = [Matrix. Identity(4)] mat_iter = repeat_last(mat) def f(axis, q): if axis.dot(q.axis) > 0: return q.angle else: return -q.angle for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter): axis = m * Vector((0, 0, 1)) axis_norm = m * Vector((1, 0, 0)) base_point = m * Vector((0, 0, 0)) intersect_d = [intersect_point_line(v_c, base_point, axis) for v_c in v] rotate_d = [f(axis, (axis_norm+v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d)] s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d))) s_v = sorted(s_v, key=itemgetter(0, 1)) verts_out.append([v[i[-1]].to_tuple() for i in s_v]) if polyOutput: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if orderOutput: item_order.append([i[-1] for i in s_v]) if self.mode == 'USER': if 'Index Data' in self.inputs and self.inputs['Index Data'].links: index = SvGetSocketAnyType(self, self.inputs['Index Data']) else: return for v, p, i in zip(verts, poly_edge, index): s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0)) verts_out.append([obj[1] for obj in s_v]) if polyOutput: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([[v_index[k] for k in pe] for pe in p]) if orderOutput: item_order.append([i[-1] for i in s_v]) if vertOutput: SvSetSocketAnyType(self, 'Vertices', verts_out) if polyOutput: SvSetSocketAnyType(self, 'PolyEdge', poly_edge_out) if orderOutput: SvSetSocketAnyType(self, 'Item order', item_order)
def process(self): verts = self.inputs['Vertices'].sv_get() if self.inputs['PolyEdge'].is_linked: poly_edge = self.inputs['PolyEdge'].sv_get() poly_in = True else: poly_in = False poly_edge = repeat_last([[]]) verts_out = [] poly_edge_out = [] item_order = [] poly_output = poly_in and self.outputs['PolyEdge'].is_linked order_output = self.outputs['Item order'].is_linked vert_output = self.outputs['Vertices'].is_linked if not any((vert_output, order_output, poly_output)): return if self.mode == 'XYZ': # should be user settable op_order = [(0, False), (1, False), (2, False)] for v, p in zip(verts, poly_edge): s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) for item_index, rev in op_order: s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'DIST': if self.inputs['Base Point'].is_linked: base_points = self.inputs['Base Point'].sv_get() bp_iter = repeat_last(base_points[0]) else: bp = [(0, 0, 0)] bp_iter = repeat_last(bp) for v, p, v_base in zip(verts, poly_edge, bp_iter): s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base)) verts_out.append([vert[0] for vert in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'AXIS': if self.inputs['Mat'].is_linked: mat = Matrix_generate(self.inputs['Mat'].sv_get()) else: mat = [Matrix. Identity(4)] mat_iter = repeat_last(mat) def f(axis, q): if axis.dot(q.axis) > 0: return q.angle else: return -q.angle for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter): axis = m * Vector((0, 0, 1)) axis_norm = m * Vector((1, 0, 0)) base_point = m * Vector((0, 0, 0)) intersect_d = [intersect_point_line(v_c, base_point, axis) for v_c in v] rotate_d = [f(axis, (axis_norm + v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d)] s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d))) s_v = sorted(s_v, key=itemgetter(0, 1)) verts_out.append([v[i[-1]].to_tuple() for i in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'USER': if self.inputs['Index Data'].is_linked: index = self.inputs['Index Data'].sv_get() else: return for v, p, i in zip(verts, poly_edge, index): s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0)) verts_out.append([obj[1] for obj in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([[v_index[k] for k in pe] for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'CONNEX': if self.inputs['PolyEdge'].is_linked: edges = self.inputs['PolyEdge'].sv_get() for v, p in zip(verts, edges): pols = [] if len(p[0]) > 2: pols = [p[:]] p = pols_edges([p], True)[0] vect_new, pol_edge_new, index_new = sort_vertices_by_connexions(v, p, self.limit_mode) if len(pols) > 0: new_pols = [] for pol in pols[0]: new_pol = [] for i in pol: new_pol.append(index_new.index(i)) new_pols.append(new_pol) pol_edge_new = [new_pols] verts_out.append(vect_new) poly_edge_out.append(pol_edge_new) item_order.append(index_new) if vert_output: self.outputs['Vertices'].sv_set(verts_out) if poly_output: self.outputs['PolyEdge'].sv_set(poly_edge_out) if order_output: self.outputs['Item order'].sv_set(item_order)
def process(self): objects = self.inputs["Object"].sv_get() color_socket = self.inputs["Color"] index_socket = self.inputs["Index"] color_data = color_socket.sv_get(deepcopy=False, default=[None]) index_data = index_socket.sv_get(deepcopy=False, default=[None]) for obj, input_colors, indices in zip(objects, repeat_last(color_data), repeat_last(index_data)): loops = obj.data.loops loop_count = len(loops) if obj.data.vertex_colors: if self.use_active and obj.data.vertex_colors.active: vertex_color = obj.data.vertex_colors.active else: vertex_color = obj.data.vertex_colors.get(self.vertex_color) if not vertex_color: vertex_color = obj.data.vertex_colors.new(name=self.vertex_color) else: vertex_color = obj.data.vertex_colors.new(name=self.vertex_color) colors = np.empty(loop_count * 3, dtype=np.float32) if input_colors: # we have index and colors, set colors of incoming index # first get all colors so we can write to them if self.clear: colors.shape = (loop_count, 3) colors[:] = self.clear_c elif index_socket.is_linked: vertex_color.data.foreach_get("color", colors) colors.shape = (loop_count, 3) if self.mode == "vertices": vertex_index = np.zeros(loop_count, dtype=int) # would be good to check exackt type loops.foreach_get("vertex_index", vertex_index) if index_socket.is_linked: idx_lookup = collections.defaultdict(list) for idx, v_idx in enumerate(vertex_index): idx_lookup[v_idx].append(idx) for idx, col in zip(indices, input_colors): colors[idx_lookup[idx]] = col else: if len(obj.data.vertices) > len(input_colors): fullList(input_colors, len(obj.data.vertices)) for idx, v_idx in enumerate(vertex_index): colors[idx] = input_colors[v_idx] elif self.mode == "polygons": polygon_count = len(obj.data.polygons) p_start = np.empty(polygon_count, dtype=int) p_total = np.empty(polygon_count, dtype=int) obj.data.polygons.foreach_get("loop_start", p_start) obj.data.polygons.foreach_get("loop_total", p_total) if index_socket.is_linked: for idx, color in zip(indices, input_colors): start_slice = p_start[idx] stop_slice = start_slice + p_total[idx] colors[start_slice:stop_slice] = color else: if len(input_colors) < polygon_count: fullList(input_colors, polygon_count) for idx in range(polygon_count): color = input_colors[idx] start_slice = p_start[idx] stop_slice = start_slice + p_total[idx] colors[start_slice:stop_slice] = color elif self.mode == "loops": if index_socket.is_linked: for idx, color in zip(indices, input_colors): colors[idx] = color else: if len(input_colors) < loop_count: fullList(input_colors, loop_count) elif len(input_colors) > loop_count: input_colors = input_colors[:loop_count] colors[:] = input_colors # write out data colors.shape = (loop_count * 3,) vertex_color.data.foreach_set("color", colors) obj.data.update() """