def process(self): n_id = node_id(self) nvBGL2.callback_disable(n_id) if self.end_early(): return self.terminal_text_to_config() self.get_font_texture() self.init_texture(256, 256) config = lambda: None texture = lambda: None texture.texture_dict = self.texture_dict lexer = self.get_lexer() grid = self.prepare_for_grid() x, y, width, height = self.adjust_position_and_dimensions(*self.dims) verts = process_grid_for_shader(grid, loc=(x, y)) uvs = process_uvs_for_shader(self) batch, shader = generate_batch_shader(self, (verts, uvs, lexer)) config.loc = (x, y) config.batch = batch config.shader = shader config.syntax_mode = self.syntax_mode draw_data = { 'tree_name': self.id_data.name[:], 'mode': 'custom_function_context', 'custom_function': simple_console_xy, 'args': (texture, config) } nvBGL2.callback_enable(n_id, draw_data)
def start_exception_drawing_with_bgl(ng, node_name, error_text, err): """ start drawing the exception data beside the node """ node = ng.nodes[node_name] config = lambda: None text = lambda: None text.final_error_message = str(err) if "\n" in error_text: text.body = error_text.splitlines() else: text.body = error_text x, y, scale = adjust_position_and_dimensions(node, xyoffset(node)) config.scale = scale def get_desired_xy(node): nx, ny = xyoffset(node) return nx * scale, ny * scale show_stack = ng.sv_show_error_details ng_id = exception_nodetree_id(ng) draw_data = { 'tree_name': ng.name[:], 'node_name': node_name, 'loc': get_desired_xy, 'mode': 'custom_function_context', 'custom_function': simple_exception_display, 'args': (text, config, show_stack) } nvBGL2.callback_enable(ng_id, draw_data)
def process(self): if not self.inputs['Float'].is_linked: return n_id = node_id(self) self.delete_texture() nvBGL2.callback_disable(n_id) size_tex = 0 width = 0 height = 0 # why is cMode a sequence like (bool,) ? see uniform_bool(name, seq) in # https://docs.blender.org/api/blender2.8/gpu.types.html is_multi_channel = self.color_mode in ('RGB', 'RGBA') cMode = (is_multi_channel, ) if self.to_image_viewer: mode = self.color_mode pixels = np.array( self.inputs['Float'].sv_get(deepcopy=False)).flatten() width, height = self.texture_width_height resized_np_array = np.resize(pixels, self.calculate_total_size()) transfer_to_image(resized_np_array, self.texture_name, width, height, mode) if self.activate: texture = self.get_buffer() width, height = self.texture_width_height # x, y = self.xy_offset gl_color_constant = gl_color_dict.get(self.color_mode) name = bgl.Buffer(bgl.GL_INT, 1) bgl.glGenTextures(1, name) self.texture[n_id] = name[0] init_texture(width, height, name[0], texture, gl_color_constant) width, height = self.get_dimensions(width, height) batch, shader = generate_batch_shader((width, height)) draw_data = { 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'mode': 'custom_function_context', 'custom_function': simple_screen, 'loc': get_drawing_location, 'args': (texture, self.texture[n_id], width, height, batch, shader, cMode) } nvBGL2.callback_enable(n_id, draw_data)
def process(self): # upgrades older versions of ProfileMK3 to the version that has self.file_pointer if self.image and not self.image_pointer: image = self.get_bpy_data_from_name(self.image, bpy.data.images) if image: self.image_pointer = image n_id = node_id(self) self.delete_texture() nvBGL2.callback_disable(n_id) # why is cMode a sequence like (bool,) ? see uniform_bool(name, seq) in # https://docs.blender.org/api/blender2.8/gpu.types.html gl_color_constant = gl_color_dict.get(self.color_mode) is_multi_channel = self.color_mode in ('RGB', 'RGBA') cMode = (is_multi_channel, ) if self.output_mode == 'bgl': # x, y = self.xy_offset width, height, colm = self.width_custom_tex, self.height_custom_tex, self.color_mode total_size = width * height * factor_buffer_dict.get(colm) texture = bgl.Buffer( bgl.GL_FLOAT, total_size, np.resize(self.inputs[0].sv_get(), total_size).tolist()) name = bgl.Buffer(bgl.GL_INT, 1) bgl.glGenTextures(1, name) self.texture[n_id] = name[0] init_texture(width, height, name[0], texture, gl_color_constant) width, height = self.get_dimensions(width, height) batch, shader = generate_batch_shader((width, height)) draw_data = { 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'mode': 'custom_function_context', 'custom_function': simple_screen, 'loc': get_drawing_location, 'args': (texture, self.texture[n_id], width, height, batch, shader, cMode) } nvBGL2.callback_enable(n_id, draw_data) else: Im = bpy.data.images[self.image] Im.pixels = np.resize(self.inputs[0].sv_get(), len(Im.pixels))
def start_node_times(ng): named_tree = ng.name data_time_infos = (None, get_preferences(), named_tree) config_node_info = { 'tree_name': named_tree, 'mode': 'LEAN_AND_MEAN', 'custom_function': draw_node_time_infos, 'args': data_time_infos } nvBGL2.callback_enable(f"{ng.tree_id}_node_time_info", config_node_info)
def process(self): inputs = self.inputs n_id = node_id(self) # end early nvBGL.callback_disable(n_id) if self.activate and inputs[0].is_linked: scale, location_theta = self.get_preferences() # gather vertices from input data = inputs[0].sv_get(deepcopy=False) self.num_elements = len(data) if self.selected_mode == 'text-based': props = lambda: None props.line_width = self.line_width props.compact = self.compact props.depth = self.depth or None processed_data = nvBGL.parse_socket( inputs[0], self.rounding, self.element_index, self.view_by_element, props ) else: # # implement another nvBGL parses for gfx processed_data = data # adjust proposed text location in case node is framed. # take into consideration the hidden state node_width = self.width _x, _y = recursive_framed_location_finder(self, self.location[:]) _x, _y = Vector((_x, _y)) + Vector((node_width + 20, 0)) # this alters location based on DPI/Scale settings. location = adjust_location(_x, _y, location_theta) draw_data = { 'tree_name': self.id_data.name[:], 'content': processed_data, 'location': location, 'color': self.text_color[:], 'scale' : float(scale), 'mode': self.selected_mode[:], 'font_id': int(self.font_id) } nvBGL.callback_enable(n_id, draw_data)
def configure_time_graph(ng): ng.update_gl_scale_info(origin=f"configure_time_graph, tree: {ng.name}") named_tree = ng.name shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') data_overlay = (None, named_tree, shader) config_graph_overlay = { 'tree_name': named_tree, 'mode': 'LEAN_AND_MEAN', 'custom_function': draw_overlay, 'args': data_overlay } nvBGL2.callback_enable(f"{ng.tree_id}_time_graph_overlay", config_graph_overlay, overlay="POST_PIXEL")
def process(self): inputs = self.inputs n_id = node_id(self) # end early nvBGL.callback_disable(n_id) if self.activate and inputs[0].is_linked: scale, self.location_theta = self.get_preferences() # gather vertices from input data = inputs[0].sv_get(deepcopy=False) self.num_elements = len(data) if self.selected_mode == 'text-based': props = lambda: None props.line_width = self.line_width props.compact = self.compact props.depth = self.depth or None props.chop_up = self.chop_up processed_data = parse_socket( inputs[0], self.rounding, self.element_index, self.view_by_element, props ) elif self.selected_mode == "sv++": nvBGL.callback_enable(n_id, self.draw_data) return else: # display the __repr__ version of the incoming data processed_data = data draw_data = { 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'content': processed_data, 'location': get_xy_for_bgl_drawing, 'color': self.text_color[:], 'scale' : float(scale), 'mode': self.selected_mode[:], 'font_id': int(self.font_id) } nvBGL.callback_enable(n_id, draw_data)
def configure_time_graph(ng): # ensure most recent gl scale. from sverchok.node_tree import SverchCustomTreeNode SverchCustomTreeNode.get_and_set_gl_scale_info(None, origin="time graph") named_tree = ng.name shader = gpu.shader.from_builtin('2D_SMOOTH_COLOR') data_overlay = (get_sv_times(named_tree), named_tree, shader) config_graph_overlay = { 'tree_name': named_tree, 'mode': 'LEAN_AND_MEAN', 'custom_function': draw_overlay, 'args': data_overlay } nvBGL2.callback_enable(f"{ng.tree_id}_time_graph_overlay", config_graph_overlay, overlay="POST_PIXEL")
def process(self): p = self.inputs['Float'].sv_get() n_id = node_id(self) # end early nvBGL.callback_disable(n_id) float_out = self.outputs['Float'] easing_func = easing_dict.get(int(self.selected_mode)) if float_out.is_linked: out = [] for obj in p: r = [] for i in obj: r.append(easing_func(i)) out.append(r) float_out.sv_set(out) else: float_out.sv_set([[None]]) if self.activate and self.inputs[0].is_linked: config = lambda: None scale = self.get_drawing_attributes() config.loc = (0, 0) config.palette = palette_dict.get(self.selected_theme_mode)[:] config.scale = scale config.easing_func = easing_func geom = self.generate_graph_geom(config) # config.batch, config.shader = self.generate_shader(geom) draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'loc': get_drawing_location, 'custom_function': simple28_grid_xy, 'args': (geom, config) } nvBGL.callback_enable(n_id, draw_data)
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 inputs['Number'].is_linked: return numbers = inputs['Number'].sv_get(default=[[]]) elif self.mode == 'Curve': if not inputs['Curve'].is_linked: return curves = inputs['Curve'].sv_get(default=[[]]) else: if not inputs['Vecs'].is_linked: return vecs = inputs['Vecs'].sv_get(default=[[]]) 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]]) seed_set(self.random_seed) x, y, config = self.create_config() 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 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) 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 process(self): n_id = node_id(self) nvBGL.callback_disable(n_id) if self.activate: if not self.inputs[0].other: return # parameter containers config = lambda: None geom = lambda: None palette = lambda: None palette.high_colour = (0.33, 0.33, 0.33, 1.0) palette.low_colour = (0.1, 0.1, 0.1, 1.0) scale = self.get_drawing_attributes() # some aliases w = self.graph_width h = self.graph_height dims = (w, h) loc = (0, 0) config.scale = scale grid_data = gridshader(dims, loc, palette, self.num_channels) # this is for drawing only. wave_data = self.get_wavedata(raw=False) wave_params = self.get_waveparams() wave_data_processed = self.generate_2d_drawing_data( wave_data, wave_params, dims, loc) scope_tick_data = self.generate_tick_data(wave_data, dims, loc) # GRAPH PART - Background config.background_shader = get_2d_smooth_color_shader() config.background_batch = batch_for_shader( config.background_shader, 'TRIS', { "pos": grid_data.background_coords, "color": grid_data.background_colors }, indices=grid_data.background_indices) if scope_tick_data.verts: params, kw_params = (('LINES', { "pos": scope_tick_data.verts }), { "indices": scope_tick_data.indices }) config.tick_shader = get_2d_uniform_color_shader() config.tick_batch = batch_for_shader(config.tick_shader, *params, **kw_params) # LINE PART coords = wave_data_processed.verts indices = wave_data_processed.indices config.line_shader = get_2d_uniform_color_shader() params, kw_params = (('LINES', { "pos": coords }), { "indices": indices }) if indices else (('LINE_STRIP', { "pos": coords }), {}) config.line_batch = batch_for_shader(config.line_shader, *params, **kw_params) # -------------- final draw data accumulation and pass to callback ------------------ draw_data = { 'mode': 'custom_function_context', 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'loc': get_offset_xy, 'custom_function': advanced_grid_xy, 'args': (geom, config) } nvBGL.callback_enable(self.n_id, draw_data)
def draw_statistics(self, names, values): """ Draw the statistics in the node editor The statistics data can be either single or vectorized. * single: [ [sum], [avg], ... [[b1, b2, .. bN]] ] * vectorized: [ [sum1... sumM], [avg1... avgM], ... [[b11... b1N]... [bM1... bMN]] ] Q: how can we tell statistics are simple or vectorized? A: if the values[0] is a list with length > 1 then it's vectorized """ nvBGL.callback_disable(node_id(self)) # clear drawing if len(values) == 0: return if self.show_statistics: max_width = max(len(name) for name in names) # used for text alignment info = [] # for now let's treat single and vectorized separately (optimize later) is_vectorized = len(values[0]) > 1 if is_vectorized: for n, v in zip(names, values): if n in ["Histogram", "HIS"]: line_format = "{0:>{x}} : [{1}]" histogram_lines = [] for a in v: # for each histogram set if self.mode == "FLOAT": value_format = "{:.{p}f}" else: value_format = "{}" histogram_values = ", ".join([ value_format.format(aa, p=self.precision) for aa in a ]) histogram_lines.append( "[{}]".format(histogram_values)) line = line_format.format(n, ", ".join(histogram_lines), x=max_width) info.append(line) else: line_format = "{0:>{x}} : [{1}]" if n in ["Count", "CNT"]: value_format = "{}" else: if self.mode == "FLOAT": value_format = "{:.{p}f}" else: value_format = "{}" value_line = ", ".join([ value_format.format(vv, p=self.precision) for vv in v ]) line = line_format.format(n, value_line, x=max_width) info.append(line) else: # single values for n, v in zip(names, values): if n in ["Histogram", "HIS"]: # print("drawing histogram") line_format = "{0:>{x}} : [{1}]" if self.normalize: value_format = "{:.{p}f}" else: value_format = "{}" histogram_values = ", ".join([ value_format.format(a, p=self.precision) for a in v[0] ]) line = line_format.format(n, histogram_values, x=max_width) info.append(line) else: if n in ["Count", "CNT"]: line_format = "{0:>{x}} : {1}" else: if self.mode == "FLOAT": line_format = "{0:>{x}} : {1:.{p}f}" else: line_format = "{0:>{x}} : {1}" line = line_format.format(n, v[0], x=max_width, p=self.precision) info.append(line) draw_data = { 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'content': info, 'location': get_text_drawing_location, 'color': self.text_color[:], 'scale': self.text_scale * get_dpi_factor(), 'font_id': int(self.selected_font_id()) } nvBGL.callback_enable(node_id(self), draw_data)