Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stethoscope console #4511

Merged
merged 56 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
a68b1bf
add steps to include consoledrawing code in stethoscope
zeffii Jun 3, 2022
a0565b8
experimental only
zeffii Jun 4, 2022
7229f25
bgl drawing works
zeffii Jun 4, 2022
36c6645
add everything needed to display lexed text
zeffii Jun 5, 2022
0e05304
remove commented code
zeffii Jun 5, 2022
d07f7d2
adds index element
zeffii Jun 5, 2022
39c8462
adds threshold and summary limit
zeffii Jun 5, 2022
6f7ebff
adds configurations to drawbuttons
zeffii Jun 5, 2022
937e0d1
option to suppress the <list> ident in mixed lists
zeffii Jun 5, 2022
90cd3ff
remove list entirely, non greedy form
zeffii Jun 5, 2022
61f093c
streamline advanced_parser_socket
zeffii Jun 6, 2022
2ecb1b1
parts can be cached when the console doesn't change size between updates
zeffii Jun 6, 2022
0f2b818
specify location of dict
zeffii Jun 6, 2022
153b8bf
restructure sv++ func
zeffii Jun 6, 2022
4499370
correct order
zeffii Jun 6, 2022
afd19e3
revert
zeffii Jun 6, 2022
3414b02
fix data index to be always valid
zeffii Jun 6, 2022
d50f11a
updates before mixing
zeffii Jun 6, 2022
081f6df
small comment
zeffii Jun 6, 2022
b995558
cleanup imports
zeffii Jun 6, 2022
0e6e1ff
cleanup imports
zeffii Jun 6, 2022
a6a039c
cleanup imports
zeffii Jun 6, 2022
28664e3
cleanups to imports
zeffii Jun 6, 2022
353ac6a
simplify code
zeffii Jun 6, 2022
43a5030
faster uv_indices generation using itertools
zeffii Jun 7, 2022
e68992e
remove double code
zeffii Jun 7, 2022
c1a2d22
revert whitespace
zeffii Jun 7, 2022
120c056
remove further whitespace
zeffii Jun 7, 2022
98203c8
rename consolemixin
zeffii Jun 7, 2022
c14f7c3
add file
zeffii Jun 7, 2022
1043ea5
small ui formatting
zeffii Jun 7, 2022
e720aa7
Merge branch 'master' into stethoschope_console
zeffii Jun 7, 2022
044f93e
numba speeds up uv creation
zeffii Jun 7, 2022
97defae
add multiline to cprint
zeffii Jun 7, 2022
55b3b0c
Merge branch 'master' into stethoschope_console
zeffii Jun 7, 2022
d697ed4
add njit to get_console_grid
zeffii Jun 7, 2022
7e9cac5
two functions njitted
zeffii Jun 7, 2022
7b0e84a
remove njit
zeffii Jun 7, 2022
749632c
wtf. cached buffer
zeffii Jun 7, 2022
66c0bb5
remove prints
zeffii Jun 7, 2022
f8b2ce7
remove profile
zeffii Jun 7, 2022
66ff853
fstring stringrounding
zeffii Jun 8, 2022
9f35f6e
revert fstr rounding for now..
zeffii Jun 8, 2022
de4006e
revert fstring rounding
zeffii Jun 8, 2022
618ac9d
streamline passthru
zeffii Jun 8, 2022
74e4b5b
remove console_print from snlite
zeffii Jun 8, 2022
bf3ab0b
missing import
zeffii Jun 8, 2022
3d9949b
name clash
zeffii Jun 8, 2022
1e414d7
rounding if pretty
zeffii Jun 8, 2022
9f0c7f8
add preps for threshold
zeffii Jun 8, 2022
dd116d2
changed order of console_print params
zeffii Jun 8, 2022
ff0bb53
snlite alias, arg order fix
zeffii Jun 8, 2022
215338a
add console_print to reloadables
zeffii Jun 8, 2022
d05e856
add chopup function, and move around some UI
zeffii Jun 9, 2022
d02a971
add basic chopping
zeffii Jun 9, 2022
8a8ba00
fixes tokenizer changes
zeffii Jun 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 3 additions & 26 deletions nodes/script/script1_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

from sverchok.utils.snlite_utils import vectorize, ddir, sv_njit, sv_njit_clear
from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata, pydata_from_bmesh
from sverchok.utils.console_print import console_print
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode

Expand All @@ -47,31 +48,6 @@
template_categories = ['demo', 'bpy_stuff', 'bmesh', 'utils']


last_print = {}

def console_print(node, message, kind='OUTPUT'):
"""
this function finds an open console in Blender and writes to it, useful for debugging small stuff.
but beware what you throw at it.
"""

if (previously_printed_text := last_print.get(hash(node))):
# i do not need to see repeat text
if message == previously_printed_text: return

last_print[hash(node)] = message

AREA = 'CONSOLE'
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in window.screen.areas:
if not area.type == AREA: continue

for region in area.regions:
if region.type == 'WINDOW':
override = {'window': window, 'screen': screen, 'area': area, 'region': region}
bpy.ops.console.scrollback_append(override, text=f"{message}", type=kind)
break


class SNLITE_EXCEPTION(Exception): pass
Expand Down Expand Up @@ -480,7 +456,8 @@ def process_script(self):
'ddir': ddir,
'get_user_dict': self.get_user_dict,
'reset_user_dict': self.reset_user_dict,
'cprint': lambda message: console_print(self, message),
'cprint': lambda message: console_print(message, self),
'console_print': console_print,
'sv_njit': sv_njit,
'sv_njit_clear': sv_njit_clear,
'bmesh_from_pydata': bmesh_from_pydata,
Expand Down
99 changes: 57 additions & 42 deletions nodes/text/stethoscope_v28.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,54 +16,60 @@
#
# ##### END GPL LICENSE BLOCK #####

import numpy as np
import pprint
import re

import bpy
import blf

from bpy.props import BoolProperty, FloatVectorProperty, StringProperty, IntProperty
from bpy.props import FloatProperty
from mathutils import Vector

from sverchok.settings import get_params
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import node_id, updateNode
from sverchok.data_structure import node_id, updateNode, enum_item_5
from sverchok.ui import bgl_callback_nodeview as nvBGL

from sverchok.utils.sv_nodeview_draw_helper import SvNodeViewDrawMixin, get_xy_for_bgl_drawing
from sverchok.utils.nodes_mixins.console_mixin import LexMixin
from sverchok.utils.profile import profile

# status colors
FAIL_COLOR = (0.1, 0.05, 0)
READY_COLOR = (1, 0.3, 0)

def chop_up_data(data):

def adjust_location(_x, _y, location_theta):
return _x * location_theta, _y * location_theta

def get_xy_for_bgl_drawing(node):
# adjust proposed text location in case node is framed.
# take into consideration the hidden state
node_width = node.width
_x, _y = node.absolute_location
_x, _y = Vector((_x, _y)) + Vector((node_width + 20, 0))
"""
if data is large (either due to many small lists or n big lists) here it is sliced up
remember the user is already comfortable with seeing their data being abbreviated when big
"""
if len(data) == 1:
if len(data[0]) > 24:
data = [data[0][:12] + data[0][-12:]]
elif len(data) > 1:
n = -1
if len(data[0]) > 12 and len(data[n]) > 12:
data = [data[0][:12], data[n][-12:]]

# could be cleverer, because this is now optimized for the above scenarios only. they are common.

# this alters location based on DPI/Scale settings.
draw_location = adjust_location(_x, _y, node.location_theta)
return draw_location
return data

def parse_socket(socket, rounding, element_index, view_by_element, props):

data = socket.sv_get(deepcopy=False)

num_data_items = len(data)
if num_data_items > 0 and view_by_element:
if element_index < num_data_items:
data = data[element_index]

str_width = props.line_width
if props.chop_up:
data = chop_up_data(data)

# okay, here we should be more clever and extract part of the list
# to avoid the amount of time it take to format it.

content_str = pprint.pformat(data, width=str_width, depth=props.depth, compact=props.compact)
content_str = pprint.pformat(data, width=props.line_width, depth=props.depth, compact=props.compact)
content_array = content_str.split('\n')

if len(content_array) > 20:
Expand All @@ -82,16 +88,12 @@ def parse_socket(socket, rounding, element_index, view_by_element, props):
# http://stackoverflow.com/a/7584567/1243487
rounded_vals = re.compile(r"\d*\.\d+")

def mround(match):
format_string = "{{:.{0}g}}".format(rounding)
return format_string.format(float(match.group()))
def mround(match): return f"{float(match.group()):.{rounding}g}"

out = []
for line in display_text:
if (rounding == 0) or ("bpy." in line):
out.append(line)
else:
out.append(re.sub(rounded_vals, mround, line))
passthru = (rounding == 0) or ("bpy." in line)
out.append(line if passthru else re.sub(rounded_vals, mround, line))
return out


Expand All @@ -102,7 +104,7 @@ def high_contrast_color(c):



class SvStethoscopeNodeMK2(bpy.types.Node, SverchCustomTreeNode):
class SvStethoscopeNodeMK2(bpy.types.Node, SverchCustomTreeNode, LexMixin, SvNodeViewDrawMixin):
"""
Triggers: scope
Tooltip: Display data output of a node in nodeview
Expand All @@ -128,22 +130,23 @@ class SvStethoscopeNodeMK2(bpy.types.Node, SverchCustomTreeNode):
default=True,
update=updateNode)

mode_options = [(i, i, '', idx) for idx, i in enumerate(["text-based", "graphical"])]
#mode_options = [(i, i, '', idx) for idx, i in enumerate(["text-based", "graphical", "sv++"])]
selected_mode: bpy.props.EnumProperty(
items=mode_options,
description="offers....",
items=enum_item_5(["text-based", "graphical", "sv++"], ['ALIGN_LEFT', 'ALIGN_TOP', 'SCRIPTPLUGINS']),
description="select the kind of display, text/graphical/sv++",
default="text-based", update=updateNode
)

view_by_element: BoolProperty(update=updateNode)
num_elements: IntProperty(default=0)
element_index: IntProperty(default=0, update=updateNode)
rounding: IntProperty(min=0, max=5, default=3, update=updateNode)
rounding: IntProperty(min=0, max=5, default=3, update=updateNode,
description="range 0 to 5\n : 0 performs no rounding\n : 5 rounds to 5 digits")
line_width: IntProperty(default=60, min=20, update=updateNode, name='Line Width (chars)')
compact: BoolProperty(default=False, update=updateNode)
compact: BoolProperty(default=False, update=updateNode, description="this tries to show as much data per line as the linewidth will allow")
depth: IntProperty(default=5, min=0, update=updateNode)
location_theta: FloatProperty(name='location_theta')

chop_up: BoolProperty(default=False, update=updateNode,
description="perform extra data examination to reduce size of data before pprint (pretty printing, pformat)")

def get_theme_colors_for_contrast(self):
try:
Expand All @@ -164,28 +167,35 @@ def sv_copy(self, node):
self.n_id = ''

def draw_buttons(self, context, layout):
row = layout.row()
row = layout.row(align=True)
icon = 'RESTRICT_VIEW_OFF' if self.activate else 'RESTRICT_VIEW_ON'
row.separator()
row.prop(self, "activate", icon=icon, text='')

layout.prop(self, 'selected_mode', expand=True)
row.separator()
row.prop(self, 'selected_mode', expand=True, icon_only=True)
if self.selected_mode == 'text-based':

row.prop(self, "text_color", text='')
row1 = layout.row(align=True)
row1.prop(self, "rounding")
row1.prop(self, "compact", toggle=True)
row1.prop(self, "compact", icon="ALIGN_JUSTIFY", text='', toggle=True)
row1.prop(self, "chop_up", icon="FILTER", text='')
row2 = layout.row(align=True)
row2.prop(self, "line_width")
row2.prop(self, "depth")
# layout.prop(self, "socket_name")
layout.label(text='input has {0} elements'.format(self.num_elements))
layout.label(text=f'input has {self.num_elements} elements')
layout.prop(self, 'view_by_element', toggle=True)
if self.num_elements > 0 and self.view_by_element:
layout.prop(self, 'element_index', text='get index')

elif self.selected_mode == "sv++":
row1 = layout.row(align=True)
row1.prop(self, "line_width", text='Columns')
row1.prop(self, "rounding")
layout.prop(self, 'element_index', text="index")
layout.prop(self, "local_scale")
else:
row.prop(self, "text_color", text='')
pass

def draw_buttons_ext(self, context, layout):
Expand Down Expand Up @@ -214,6 +224,7 @@ def process(self):
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],
Expand All @@ -222,11 +233,15 @@ def process(self):
self.view_by_element,
props
)

elif self.selected_mode == "sv++":
nvBGL.callback_enable(n_id, self.draw_data)
return

else:
# # implement another nvBGL parses for gfx
# display the __repr__ version of the incoming data
processed_data = data


draw_data = {
'tree_name': self.id_data.name[:],
'node_name': self.name[:],
Expand Down
14 changes: 6 additions & 8 deletions nodes/viz/console_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import os
import numpy as np
import itertools

import bpy
import bgl
Expand All @@ -22,6 +23,7 @@
from sverchok.utils.sv_update_utils import sv_get_local_path
from sverchok.utils.sv_font_xml_parser import get_lookup_dict, letters_to_uv
from sverchok.utils.sv_nodeview_draw_helper import SvNodeViewDrawMixin, get_console_grid
#from sverchok.utils.decorators_compilation import njit

def get_desired_xy(node):
x, y = node.xy_offset
Expand Down Expand Up @@ -151,7 +153,7 @@ def make_color(name, default):
else if (cIndex == 22) { test_tint = equalsColor; }
else if (cIndex == 25 || cIndex == 26) { test_tint = braceColor; }
else if (cIndex == 53 || cIndex == 54) { test_tint = opColor; }
else if (cIndex == 55 || cIndex == 60) { test_tint = commentColor; }
else if (cIndex == 55 || cIndex == 61 || cIndex == 58) { test_tint = commentColor; }
else if (cIndex == 90) { test_tint = name2Color; }
else if (cIndex == 91) { test_tint = name3Color; }
else if (cIndex == 92) { test_tint = qualifierColor; }
Expand Down Expand Up @@ -391,7 +393,6 @@ def simple_console_xy(context, args, loc):
texture, config = args
act_tex = bgl.Buffer(bgl.GL_INT, 1)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.texture_dict['texture'])

config.shader.bind()

# if not config.syntax_mode == "None":
Expand All @@ -409,21 +410,18 @@ def simple_console_xy(context, args, loc):
config.shader.uniform_int("image", act_tex)
config.batch.draw(config.shader)


#@njit(cache=True)
def process_grid_for_shader(grid):
positions, poly_indices = grid
verts = []
for poly in poly_indices:
for v_idx in poly:
verts.append(positions[v_idx][:2])
verts.append(positions[v_idx])
return verts

def process_uvs_for_shader(node):
uv_indices = terminal_text_to_uv(node.terminal_text)
uvs = []
add_uv = uvs.append
_ = [[add_uv(uv) for uv in uvset] for uvset in uv_indices]
return uvs
return list(itertools.chain.from_iterable(uv_indices))


def generate_batch_shader(node, data):
Expand Down
2 changes: 1 addition & 1 deletion utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def app_handler_ops(append=None, remove=None):
"text_editor_submenu", "text_editor_plugins",
# UI operators and tools
"sv_IO_pointer_helpers",
"sv_operator_mixins",
"sv_operator_mixins", "console_print",
"sv_gist_tools", "sv_IO_panel_tools", "sv_load_archived_blend",
"sv_help", "sv_default_macros", "sv_macro_utils", "sv_extra_search", "sv_3dview_tools",
"sv_update_utils", "sv_obj_helper", "sv_batch_primitives", "sv_idx_viewer28_draw",
Expand Down
70 changes: 70 additions & 0 deletions utils/console_print.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# 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 pprint
import bpy
import re

last_print = {}

def console_print(message, node=None, kind='OUTPUT', allow_repeats=False, pretty=False, width=80, rounding=0, compact=True, print_origin=False):
"""
this function finds an open console in Blender and writes to it, useful for debugging small stuff.
but beware what you throw at it.

"node" can be a node, or any hasahable object. This is just to identify where the print comes from
"message" can be text or data
"kind" can be any of the accepted types known by scrollback_append operator.
"""
if node is None:
node = "generic"

if not allow_repeats:
if (previously_printed_text := last_print.get(hash(node))):
# i do not need to see repeat text
if message == previously_printed_text: return

if compact:
# first ten + ... + last ten
pass

if pretty:
message = pprint.pformat(message, width=width, depth=5, compact=compact)

if rounding > 0:
rounded_vals = re.compile(r"\d*\.\d+")

def mround(match): return f"{float(match.group()):.{rounding}g}"

out = []
for line in message.split("\n"):
passthru = ("bpy." in line)
out.append(line if passthru else re.sub(rounded_vals, mround, line))
message = "\n".join(out)


last_print[hash(node)] = message


AREA = 'CONSOLE'
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in window.screen.areas:
if not area.type == AREA: continue

for region in area.regions:
if region.type == 'WINDOW':
override = {'window': window, 'screen': screen, 'area': area, 'region': region}

if print_origin:
bpy.ops.console.scrollback_append(override, text=f"{node}", type=kind)

if not "\n" in f"{message}":
bpy.ops.console.scrollback_append(override, text=f"{message}", type=kind)
else:
for line in f"{message}".split("\n"):
bpy.ops.console.scrollback_append(override, text=line, type=kind)
break
Loading