nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.25k stars 233 forks source link

Sverchok 0.5 #453

Closed ly29 closed 9 years ago

ly29 commented 10 years ago

Or how to stop abusing update in one day.

How to switch over a node to the new system. 1) Rename init to sv_init 2) Change name of update to process 3) Done

For nodes that use multi_socket of changable_socket or creates new or updates sockets an update function is still needed.

Originally I had more advanced plans for this, but they can be built upon this foundation. This obeys the KISS rule

TODO:

Nodes left:

Verify or fix updates to master.

To resolve

ly29 commented 10 years ago

Rules:

def sv_init(self, context):
    #replace the old init
def process(self):
    # like update now but the sockets exist
    # new socket creation NOT allowed in process
    # socket creation and layout inspection etc
    # must happen in update(self).
def update(self):
    # optional, for socket creation and change in layout
    # not allowed: accessing socket data
ly29 commented 10 years ago

29 done 110 to go But I must admit that the number seems higher than expected...

ly29 commented 10 years ago

This probably a good time remove some old non used code also.

ly29 commented 10 years ago

Okay, eval_knieval, which should be called something like, get or set blender property, and script to go. Then verify.

Potential areas of concern: Nodes that abuse updateNode for updating itself upon change and depend on update to do it. Check logic, vector math, and scalar math...

ly29 commented 10 years ago

voronoi, test and viewer 3d text moved to old_nodes They can be safely removed Also old listitem code moved there, from early february...

These are not loaded.

ly29 commented 10 years ago

Updated IO system, now repeated import happens equally fast. By using a special stopper node...

zeffii commented 10 years ago

" get or set blender property, and script to go. Then verify." is a bit long, so I chose EvalKnieval. I'm not super sure how these changes impact EK (it is purposely and perhaps perpetually an alpha node)

it might have made more sense to do this in three nodes

ly29 commented 10 years ago

Yeah, the main issue with EK is Line 319

    eval_str = StringProperty(update=updateNode)

Which was fine since it would result in self.update() being called. But now it leads to process, which is also fine but the socket creation etc needs to happen before it ends up here.

The called order should be

Stringprop -> eval_check(self, context) -> updateNode(self, context)

Where eval_check creates socket, checks things etc.

zeffii commented 10 years ago

EK definitely doesn't need to update itself on eval_str changes. I will get around to providing a solution soon. Also its mode switching protection uses updateNode where it could use an alternative.

EK is not IO interchange ready.

ly29 commented 10 years ago

Most of the switch to process is done. Now testing and clean up is needed and some tuning. Then we can take it to next level.

zeffii commented 10 years ago

Having implemented this in Flow, i'll be able to dig through my Sverchok nodes and make sure they behave properly.

ly29 commented 10 years ago

That will be great help. The whole core.update module needs overhaul as well.

zeffii commented 10 years ago

i'm not sure if you've explicitly stated this as a reason, if you have I just want to see if I understand.

previously we checked in update to see if the last self.outputs (or .inputs) as an indication that the node was ready, but for nodes with static input / output as soon as their update is called by the update mechanism it is safe to assume that the full UI is drawn and the checks become redundant? Yes/No? am i missing some subtle behaviour?

zeffii commented 10 years ago

please explain what you mean by EK abuses updateNode, it defers calling updateNode until the mode is different from the previous mode. Altho.. you might have answered this here : https://github.com/nortikin/sverchok/issues/453#issuecomment-58800002

it's not a simple node, it will take time to wrap the head around it again. It may be easier to drop EK and implement it as 3 separate nodes Very little is shared between the 3 states anyway.

zeffii commented 10 years ago

I get this error trying to start with this branch

***** Sverchok  loading *****
Traceback (most recent call last):
  File "C:\blender_trunk\2.72\scripts\modules\addon_utils.py", line 299, in enable
    mod = __import__(module_name)
  File "C:\blender_trunk\2.72\scripts\addons\sverchok\__init__.py", line 126, in <module>
    node_list = make_node_list()
  File "C:\blender_trunk\2.72\scripts\addons\sverchok\__init__.py", line 95, in make_node_list
    'nodes.{}'.format(category))
  File "C:\Python34\Lib\importlib\__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
ImportError: No module named 'nodes.modifier_make.voronoi'
ly29 commented 10 years ago

Okay I will fix that error right away. Needed to make sure I clean the addon directory before, my bad.

Will have look at EK node again, but I had a hard time splitting the logic up between socket creation input verification and the actual processing. Admittedly I didn't look to long.

zeffii commented 10 years ago
'modifier_make': [
    'bisect',
    'convex_hull',
    'cross_section',
    'edges_adaptative',
    'join_tris',
    'lathe',
    'line_connect',
    'offset',
    'polygons_adaptative',
    'solidify',
    'voronoi_2d',
    #'voronoi',
    'wireframe'
],  #

?

zeffii commented 10 years ago

Don't waste time on EK.

ly29 commented 10 years ago

Yeah, but I had some other changes pending, test is also removed.

zeffii commented 10 years ago

EK is 3 (5) nodes simultaneously, and this breaks the KISS directive.

zeffii commented 10 years ago

I think EK is more like a family of concepts.. Even tho it isn't long ago, i've learned quite a bit since.

ly29 commented 10 years ago

Agreed with that, they could even share some code between them.

zeffii commented 10 years ago

Right! it seems you are still battling with the update_system then?

  File "\scripts\addons\sverchok\core\update_system.py", line 378, in sverchok_update
    do_update(update_list, nodes)
UnboundLocalError: local variable 'do_update' referenced before assignment
File "\scripts\addons\sverchok\data_structure.py", line 726, in updateNode

Also the node base-class now implements sv_init called by init ? I don't quite understand the benefit maybe a scenario would help.

ly29 commented 10 years ago

Okay, test now.

The general strategy. For each layout split nodes into separate sets make an ordered list from each set

call process for each list

ly29 commented 10 years ago

Right about sv_init if we look at the base class for all Sverchok nodes, the sv_init makes sure to set state of the node to 1 after sv_init has run. The tree level update refuses to do anything until all nodes are declared ready to stop unwanted calls to process. It can be done by each node by having in the super class and just renaming them seemed simpler than inserting the code at the end of each init

class SverchCustomTreeNode:
    @classmethod
    def poll(cls, ntree):
        return ntree.bl_idname == 'SverchCustomTreeType'
    #def draw_buttons(self, context, layout):
    #    layout.label('sverchok')    
    sv_state = IntProperty(default=0)

    def init(self, context):
        if hasattr(self, "sv_init"):
            self.sv_init(context)
        self.sv_state = 1

    def process_node(self, context):
        a = time.perf_counter()
        sverchok_update(start_node=self)
        b = time.perf_counter()
        if data_structure.DEBUG_MODE:
            print("Partial update from node", self.name, "in", round(b-a, 4))
ly29 commented 10 years ago

This ensures that all sockets is ready when process for the node is finally called. process_node is meant as an replacement to updateNode

ly29 commented 10 years ago

in the Tree update function

    def update(self):
        '''
        Rebuild and update the Sverchok node tree, used at editor changes
        '''
        # startup safety net, a lot things will just break if this isn't
        # stopped...
        try:
            l = bpy.data.node_groups[self.id_data.name]
        except:
            return
        # catch nodes that aren't ready.
        if any((not(n.sv_state) for n in self.nodes if hasattr(n, "sv_state"))):
            return
        build_update_list(tree=self)
        if self.sv_process:
            sverchok_update(tree=self)
ly29 commented 10 years ago

Okay the whole sv_init is clever but only for new node trees.

nortikin commented 10 years ago

what brings sv_state to zero?

nortikin commented 10 years ago

what branch you are working at?

zeffii commented 10 years ago

https://github.com/nortikin/sverchok/tree/toProcess

ly29 commented 10 years ago

Okay a more clever method now works, instead of setting sv_state for each node it is now possible to freeze update for a node tree, which is a more clever approah. The special stopper node removed since this feels cleaner. I think this is basically the sane approch. Naming can be argued however...

in node_tree.py

    def freeze(self):
        self["don't update"] = 1

    def is_frozen(self):
        return "don't update" in self

    def unfreeze(self):
        if "don't update" in self:
            del self["don't update"]
ly29 commented 10 years ago

Okay, I think I am done with the update system restructure, certainly bugs might lurk but this gives a more modular approach, more powerful and ~50 lines less.

nortikin commented 10 years ago

https://github.com/nortikin/sverchok/blob/toProcess/node_tree.py#L237 what if add here draw_buttons for all as yu did for init. and update replace with general update to set color of node from node type and socket status? But colorizing can be done in init, but recolorizing from active-unactive node only from update. What to do?

nortikin commented 10 years ago

or leave colorizing active viwers only in nodes, other nodes leave with one initial color?

nortikin commented 10 years ago

still not understand diference between NodeSocket, NodeSocketStandard. matrices under simple NS, but other tho sockets are NSS... and they works

nortikin commented 10 years ago

in blender /scripts/modules/bpy_types.py there is"

class NodeSocket(StructRNA, metaclass=RNAMetaPropGroup):
    __slots__ = ()

    @property
    def links(self):
        """List of node links from or to this socket"""
        return tuple(link for link in self.id_data.links
                     if (link.from_socket == self or
                         link.to_socket == self))

class NodeSocketInterface(StructRNA, metaclass=RNAMetaPropGroup):
    __slots__ = ()
nortikin commented 10 years ago

in nodeitems_utils we have allready some veriables we maybe can use:

class NodeItem():
    def __init__(self, nodetype, label=None, settings={}, poll=None):
        self.nodetype = nodetype
        self._label = label
        self.settings = settings
        self.poll = poll

    @property
    def label(self):
        if self._label:
            return self._label
        else:
            # if no custom label is defined, fall back to the node type UI name
            return getattr(bpy.types, self.nodetype).bl_rna.name

    # NB: is a staticmethod because called with an explicit self argument
    # NodeItemCustom sets this as a variable attribute in __init__
    @staticmethod
    def draw(self, layout, context):
        default_context = bpy.app.translations.contexts.default

        props = layout.operator("node.add_node", text=self.label, text_ctxt=default_context)
        props.type = self.nodetype
        props.use_transform = True

        for setting in self.settings.items():
            ops = props.settings.add()
            ops.name = setting[0]
            ops.value = setting[1]

class NodeItemCustom():
    def __init__(self, poll=None, draw=None):
        self.poll = poll
        self.draw = draw
ly29 commented 10 years ago

How you control color is good question. Setting it in init based on category (for example) can be done quite simply. In general I think we should respect user re coloring of nodes. NoteItem could also be used to set color based on category, perhaps an even better approach actually, just pass the settings from the menu.

Updating nodes color based on state should probably be done from update.

ly29 commented 10 years ago

NodeSocketStandard is perhaps not strictly necessary, but when I introduced the exposed bpy.props in the sockets it work when I switched the class and then I didn't investigate it more. The issue is only UI.

nortikin commented 10 years ago

ok, than i agree on init() def. With cetegories from menu. I'm ok with it. Main issue - to see wgere are viewers. in layout i can lost them, i think you too. than other need not update colorization. Moreover - not all categoryes need to be colorized ))

nortikin commented 10 years ago

simple - viewers orange, data green, debug light blue. reserved for other categoryes no custom color by default

ly29 commented 10 years ago

I made quick test with node colors. some very ugly code where they reside in addon preferences and are set from init on creation. Having done this I think the setting of an initial color should be done from the menu which needs to be rebuilt whenever the settings color changes. There is some very ugly code in here, everything except the settings part basically.

nortikin commented 10 years ago

will you commit?

ly29 commented 10 years ago

I don't think it is working that well, there are many things left to do to make it work properly.

https://github.com/nortikin/sverchok/tree/nodecolors

nortikin commented 10 years ago

oh, i looked to branch "to Process"

ly29 commented 10 years ago

My fault, should have made it clear above.

nortikin commented 10 years ago

)) it is ok

ly29 commented 10 years ago

Built groups using IO tools. Proper editing/naming inputs etc still to do but it works.

groups editgroup

nortikin commented 10 years ago

i don't believe it is true o_O