Не подтверждена Коммит ea520b4e создал по автору Dealga McArdle's avatar Dealga McArdle Зафиксировано автором GitHub
Просмотр файлов

shader_library_2d (#4095)

* adds file

* tabs to spaces

* test

* small streamline shaderutil

* update solid mode shader

* add placeholder funcs"

* typo

* update docstrings

* add base graphdrawing file

* adds overlay option to nvbgl callback - big step!

* make ready for blankslate nvbgl drawing callback

* adds simple overlay drawing to cb

* rm debug prints

* take into account visible width in nodeview using region.width

* make it possible to view nodes times and graph separately

* rearrange props

* remove unused import

* update comment

* shuffle imports

* remove whitespace
владелец df3b1f17
# -*- coding: utf-8 -*-
# ##### 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 #####
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import sys
import time
......@@ -34,9 +23,9 @@ from sverchok.core.update_system import (
process_from_node, process_from_nodes,
process_tree,
get_original_node_color,
is_first_run,)
from sverchok.core.links import (
SvLinks)
is_first_run)
from sverchok.core.links import SvLinks
from sverchok.core.node_id_dict import SvNodesDict
from sverchok.utils import get_node_class_reference
......@@ -48,6 +37,9 @@ from sverchok.utils.logging import debug
from sverchok.ui import color_def
from sverchok.ui.nodes_replacement import set_inputs_mapping, set_outputs_mapping
from sverchok.utils.exception_drawing_with_bgl import clear_exception_drawing_with_bgl
from sverchok.utils.nodeview_time_graph_drawing import (
configure_time_graph, disable_time_graph,
configure_node_times, disable_node_times)
class SvNodeTreeCommon(object):
......@@ -166,8 +158,17 @@ class SverchCustomTree(NodeTree, SvNodeTreeCommon):
if draft_nodes:
process_from_nodes(draft_nodes)
def set_ng_time_graph_drawing_state(self, context):
configure_time_graph(self) if self.sv_show_time_graph else disable_time_graph(self)
def set_ng_time_info_drawing_state(self, context):
configure_node_times(self) if self.sv_show_time_nodes else disable_node_times(self)
sv_animate: BoolProperty(name="Animate", default=True, description='Animate this layout')
sv_show: BoolProperty(name="Show", default=True, description='Show this layout', update=turn_off_ng)
sv_show_time_graph: BoolProperty(name="Time Graph", default=False, update=set_ng_time_graph_drawing_state)
sv_show_time_nodes: BoolProperty(name="Node times", default=False, update=set_ng_time_info_drawing_state)
# something related with heat map feature
# looks like it keeps dictionary of nodes and their user defined colors in string format
......@@ -179,20 +180,20 @@ class SverchCustomTree(NodeTree, SvNodeTreeCommon):
description="This will show Node Exceptions in the node view, right beside the node",
name="Show error in tree", default=True, update=lambda s, c: process_tree(s), options=set())
sv_show_error_details : BoolProperty(
sv_show_error_details: BoolProperty(
name = "Show error details",
description = "Display exception stack in the node view as well",
default = False,
update=lambda s, c: process_tree(s),
options=set())
sv_show_socket_menus : BoolProperty(
sv_show_socket_menus: BoolProperty(
name = "Show socket menus",
description = "Display socket dropdown menu buttons. NOTE: options that are enabled in those menus will be effective regardless of this checkbox!",
default = False,
options=set())
# if several nodes are disconnected this option determine order of their evaluation
# if a nodetree consists of several disjoint graphs this option determines the order of their evaluation.
sv_subtree_evaluation_order: EnumProperty(
name="Subtree eval order",
items=[(k, k, '', i) for i, k in enumerate(["X", "Y", "None"])],
......@@ -204,7 +205,7 @@ class SverchCustomTree(NodeTree, SvNodeTreeCommon):
default="None", update=lambda s, c: process_tree(s), options=set()
)
# this mode will replace properties of some nodes so they could have lesser values for draft mode
# draft mode replaces selected properties of certain nodes with smaller values to lighten cpu load.
sv_draft: BoolProperty(
name="Draft",
description="Draft (simplified processing) mode",
......@@ -497,8 +498,10 @@ class SverchCustomTreeNode(UpdateNodes, NodeUtils):
@property
def absolute_location(self):
"""
It can be useful in case if a node is in a frame node
does not return a vactor, it returns a: tuple(x, y)
When a node is inside a frame (and parented to it) then node.location is relative to its parent's location.
This function returns the location in absolute screen terms whether the node is framed or not.
The return type is a tuple (x, y) (not a Vector)
"""
return recursive_framed_location_finder(self, self.location[:])
......@@ -510,8 +513,7 @@ class SverchCustomTreeNode(UpdateNodes, NodeUtils):
def rclick_menu(self, context, layout):
"""
Override this method to add specific items into
node's right-click menu.
Override this method to add specific items into the node's right-click menu.
Default implementation calls `node_replacement_menu'.
"""
self.node_replacement_menu(context, layout)
......
......@@ -42,13 +42,13 @@ def tag_redraw_all_nodeviews():
region.tag_redraw()
def callback_enable(*args):
def callback_enable(*args, overlay='POST_VIEW'):
n_id = args[0]
# global callback_dict
if n_id in callback_dict:
return
handle_pixel = SpaceNodeEditor.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_VIEW')
handle_pixel = SpaceNodeEditor.draw_handler_add(draw_callback_px, args, 'WINDOW', overlay)
callback_dict[n_id] = handle_pixel
tag_redraw_all_nodeviews()
......@@ -134,6 +134,11 @@ def draw_callback_px(n_id, data):
drawing_func(x, y, args)
restore_opengl_defaults()
elif data.get('mode') == 'LEAN_AND_MEAN':
drawing_func = data.get('custom_function')
args = data.get('args', (None,))
drawing_func(*args)
restore_opengl_defaults()
elif data.get('mode') == 'custom_function_context':
'''
......
......@@ -86,6 +86,12 @@ class SV_PT_ActiveTreePanel(SverchokPanels, bpy.types.Panel):
col.prop(ng, "sv_show_error_details")
col.prop(ng, "sv_show_socket_menus")
addon = context.preferences.addons.get(sverchok.__name__)
if addon.preferences.show_debug:
col.label(text="Time graph update controls")
col.prop(ng, "sv_show_time_nodes")
col.prop(ng, "sv_show_time_graph")
class SV_PT_ProfilingPanel(SverchokPanels, bpy.types.Panel):
bl_idname = "SV_PT_ProfilingPanel"
......
......@@ -130,7 +130,8 @@ utils_modules = [
"avl_tree", "sv_nodeview_draw_helper", "sv_font_xml_parser", "exception_drawing_with_bgl",
"wfc_algorithm", "handling_nodes", "handle_blender_data", "nodes_mixins.generating_objects",
"nodes_mixins.show_3d_properties", "modules_inspection", "sv_json_export", "sv_json_import",
"meshes", "tree_walk", "mesh_functions", 'mesh.inset_faces', 'mesh.extrude_edges',
"meshes", "tree_walk", "mesh_functions", 'mesh.inset_faces', 'mesh.extrude_edges',
"nodeview_time_graph_drawing",
# UI text editor ui
"text_editor_submenu", "text_editor_plugins",
# UI operators and tools
......
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
class ShaderLib2D():
def __init__(self):
"""
docstring ?
"""
self.vectors = []
self.vertex_colors = []
self.indices = []
self.addv = self.vectors.extend
self.addc = self.vertex_colors.extend
self.addi = self.indices.extend
def add_data(self, new_vectors=None, new_colors=None, new_indices=None):
"""
input
see `add_rect` for a reference implementation
new_vectors: a list of 2d vectors as lists
new_colors: a list of colors of the same length as new_vectors
new_indices: a list of indices to make up tri-face topology
this function automatically offsets the new_indices, so you only have to write
topology for one instance of your object
"""
offset = len(self.vectors)
self.addv(new_vectors)
self.addc(new_colors)
self.addi([[offset + i for i in tri] for tri in new_indices])
def add_rect(self, x, y, w, h, color):
"""
b - c
| / |
a - d
"""
a = (x, y)
b = (x, y - h)
c = (x + w, y - h)
d = (x + w, y)
self.add_data(
new_vectors=[a, b, c, d],
new_colors=[color for _ in range(4)],
new_indices=[[0, 1, 2], [0, 2, 3]]
)
def add_rect_rounded(self, x, y, w, h, color, radius=0, precision=5):
...
def add_line(self, x1, y1, x2, y2, width, color):
...
def add_polyline(self, path, width, color):
...
def add_bezier(self, controls, width, color, samples=20, resampled=False):
...
def add_circle(self, x, y, radius, color, precision=32):
...
def add_arc(self, x, y, start_angle, end_angle, radius, width, color, precision=32):
...
def compile(self):
geom = lambda: None
geom.vectors = self.vectors
geom.vertex_colors = self.vertex_colors
geom.indices = self.indices
return geom
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import bgl
import blf
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
import sverchok
from sverchok.ui import bgl_callback_nodeview as nvBGL2
from sverchok.utils.modules.shader_utils import ShaderLib2D
def tick_display(i, whole_milliseconds):
if whole_milliseconds < 10:
return True
filter = 2
for j in range(10, whole_milliseconds + 10, 5):
if j <= whole_milliseconds < j+5:
return i % filter == 0
filter += 1
def string_from_duration(duration):
return f"{(1000*duration):.3f} ms"
def get_preferences():
from sverchok.settings import get_params
props = get_params({'render_location_xy_multiplier': 1.0})
return props.render_location_xy_multiplier
def write_time_graph():
m = sverchok.core.update_system.graphs
if len(m) == 1:
return {idx: event for idx, event in enumerate(m[0])}
else:
cumulative_dict = {}
counter = 0
for graph in m:
for event in graph:
cumulative_dict[counter] = event
counter += 1
return cumulative_dict
def get_sv_times(named_group):
ng = bpy.data.node_groups
upd = bpy.ops.node.sverchok_update_current
for g in ng:
if g.bl_idname == 'SverchCustomTreeType':
if g.name == named_group:
upd(node_group=named_group)
return write_time_graph()
def draw_text(font_id, location, text, color):
x, y = location
r, g, b = color
blf.position(font_id, x, y, 0)
level = 5 # 3, 5 or 0
blf.color(font_id, r, g, b, 1.0)
blf.enable(font_id, blf.SHADOW)
blf.shadow(font_id, level, 0, 0, 0, 1)
blf.shadow_offset(font_id, 1, -1)
blf.draw(font_id, text)
blf.disable(font_id, blf.SHADOW)
def draw_node_time_infos(*data):
data_tree = write_time_graph() # data[0]
location_theta = data[1]
node_tree = bpy.data.node_groups.get(data[2])
r, g, b = (0.9, 0.9, 0.9)
index_color = (0.98, 0.6, 0.6)
font_id = 0
text_height = 20
def get_xy_for_bgl_drawing(node):
_x, _y = node.absolute_location
_x, _y = _x, _y + (text_height - 9)
return _x * location_theta, _y * location_theta
blf.size(font_id, int(text_height), 72)
blf.color(font_id, r, g, b, 1.0)
for idx, node_data in data_tree.items():
node = node_tree.nodes.get(node_data['name'])
if not node: continue
x, y = get_xy_for_bgl_drawing(node)
x, y = int(x), int(y)
show_str = string_from_duration(node_data['duration'])
draw_text(font_id, (x, y), show_str, (r, g, b))
process_index = str(idx)
index_width, _ = blf.dimensions(font_id, process_index)
padding = 9
draw_text(font_id, (x - padding - index_width, y), process_index, index_color)
def draw_overlay(*data):
# bpy.context.area.height & area.width = total
region = bpy.context.region
# visible width ( T panel is not included, only N panel)
region_width = region.width
data_tree = write_time_graph() # data[0]
node_tree = bpy.data.node_groups.get(data[1])
shader = data[2]
white = (1.0, 1.0, 1.0, 1.0)
left_offset = 140
right_padding = 50
time_domain_px = region_width - left_offset - right_padding
r, g, b = (0.9, 0.9, 0.95)
font_id = 0
text_height = 10
line_height = 10 + 3
blf.size(font_id, int(text_height), 72)
blf.color(font_id, r, g, b, 1.0)
x, y = 20, 50
cumsum = 0.0
used_idx = 0
display_info = {}
for idx in sorted(data_tree, key=lambda value: data_tree.get(value).get("start")):
node_data = data_tree.get(idx)
node = node_tree.nodes.get(node_data['name'])
if not node: continue
cumsum += node_data['duration']
txt_width, txt_height = blf.dimensions(font_id, node_data['name'])
display_info[used_idx] = (x, y, node_data, txt_width)
y += line_height
used_idx += 1
if cumsum == 0.0:
return
y = 26
cum_duration = string_from_duration(cumsum)
draw_text(font_id, (20, y), f"total: {cum_duration}", (r, g, b))
px_per_ms = time_domain_px / cumsum
canvas = ShaderLib2D()
bar_start_offset = 0
orange = (0.8, 0.3, 0.2, 1.0)
darker = (0.4, 0.4, 0.4, 1.0)
offwhite = (0.1, 0.5, 0.6, 1.0)
starts = {}
for key, value in display_info.items():
(x, y, node_data, txt_width) = value
bar_width = px_per_ms * node_data['duration']
canvas.add_rect(left_offset + bar_start_offset, y+10, bar_width, 13, offwhite)
starts[key] = left_offset + bar_start_offset
bar_start_offset += bar_width
# draw time axis
canvas.add_rect(left_offset, 40, time_domain_px, 1, white)
# draw time ticks
milliseconds = cumsum * 1000
whole_milliseconds = int(milliseconds)
graph_height = line_height * len(display_info)
for i in range(whole_milliseconds + 1):
tick_location = px_per_ms * i/1000
final_tick_x = left_offset + tick_location
# this is where we skip ticks if they get too dense.
if tick_display(i, whole_milliseconds):
canvas.add_rect(final_tick_x, 42, 1, 5, white)
canvas.add_rect(final_tick_x, 42, 1, -graph_height, darker)
time_width, _ = blf.dimensions(font_id, str(i))
time_str_offset = final_tick_x - (time_width/2)
draw_text(font_id, (time_str_offset, 26), str(i), (r, g, b))
geom = canvas.compile()
batch = batch_for_shader(shader, 'TRIS',
{"pos": geom.vectors,
"color": geom.vertex_colors},
indices=geom.indices
)
batch.draw(shader)
for key, value in display_info.items():
(x, y, node_data, text_width) = value
x_right_aligned = left_offset - 10 - text_width
draw_text(font_id, (x_right_aligned, y), node_data['name'], (r, g, b))
xpos = starts[key]
duration_as_str = string_from_duration(node_data['duration'])
draw_text(font_id, (xpos + 3, y), duration_as_str, (r, g, b))
def configure_node_times(ng):
named_tree = ng.name
data_time_infos = (get_sv_times(named_tree), 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 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 disable_time_graph(ng):
nvBGL2.callback_disable(f"{ng.tree_id}_time_graph_overlay")
def disable_node_times(ng):
nvBGL2.callback_disable(f"{ng.tree_id}_node_time_info")
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать