Closed ly29 closed 8 years ago
The only real question here is the syntax, to make it sensible. For tomorrow.
So perhaps the sane way is just to declare the bpy.props.FloatProperty
directly.
Like so:
import numpy as np
from bpy.props import BoolProperty
def linspace(start: float = 0.0, stop: float = 1.0, count: int = 10,
endpoint: BoolProperty() = True) -> [("linspace", np.ndarray)]:
return np.linspace(start, stop, count, endpoint=endpoint)
What happens here:
>>> linspace.__annotations__["endpoint"]
(<built-in function BoolProperty>, {})
It creates a tuple with function and a keyword dict to pass along to blender when the class becomes registered as a proper blender class. This dict can be modified to include the name and default parameters which when know from introspection/annotations removing the need to auto supply them.
Where the name
update
and default
can be auto filled.
Auto generated property in, now it just needs to get passed to the execution engine.
Working, also with multiple properties.
import numpy as np
from bpy.props import BoolProperty, FloatProperty
def linspace(start: float = 0.0, stop: float = 1.0, count: int = 10,
endpoint: BoolProperty() = True,
test: FloatProperty(description="test", subtype="ANGLE") = 2.0
) -> [("linspace", np.ndarray)]:
return np.linspace(start, stop, count, endpoint=endpoint)
linspace.label = "Linear space"
SvRxFunc = [linspace]
@zeffii Is this sane?
@ly29 I don't see why not. It's definitely still comprehensible.
I'm likely to declare nodes one param per line tho..I find it reads more pleasantly.
import numpy as np
from bpy.props import BoolProperty, FloatProperty
def linspace(
start: float = 0.0,
stop: float = 1.0,
count: int = 10,
endpoint: BoolProperty() = True,
test: FloatProperty(description="test", subtype="ANGLE") = 2.0
) -> [("linspace", np.ndarray)]:
return np.linspace(start, stop, count, endpoint=endpoint)
linspace.label = "Linear space"
SvRxFunc = [linspace]
unless ofcourse the params fit on one line. (+/-100 chars)
My only concern is the undocumented behavior of the property functions, but if they change a change to something like the following would be simple enough.
def linspace(start: float = 0.0,
stop: float = 1.0,
count: int = 10,
endpoint: (BoolProperty, {}) = True,
test: (FloatProperty, {description: "test", subtype: "ANGLE"}) = 2.0
) -> [("linspace", np.ndarray)]:
return np.linspace(start, stop, count, endpoint=endpoint)
endpoint: (BoolProperty, {}) = True,
test: (FloatProperty, {description: "test", subtype: "ANGLE"}) = 2.0
how is that supposed to work, are you doing preprocessing? The tuple notation?
It that case the property would be created with func(dict)
Right now this syntax works because bpy.props.FloatProperty
etc. are returning (func, kwargs)
`>>> bpy.props.FloatProperty(name="test", default=10.0)
(<built-in function FloatProperty>, {'default': 10.0, 'name': 'test'})
Well, how it should work if things changes are problem for a later day. But there needs to be note about the expected behavior of the property functions.
right - i follow now. I've seen that plenty of times in the REPL.
That part of the bpy api seems fairly cemented now, it's more likely that bpy gets new props than modifying existing ones to have a different signature.
This went much quicker than I expected and the syntax ended up being nicer. Now onwards.
Right now I store them in the node with a svrx_
prefix to avoid name collisions with the standard node properties.
The dict taken from the annotation is updated with the name
and default
taken from the inspection, also an update
method is supplied.
prop = annotations[name]
prop[1].update({"name": name,
"default": parameter.default,
"update": execute_tree})
properties["svrx_{}".format(name)] = prop
Some props will need a custom update method, so they can do some action after or before the execute_tree is called.
Yeah, good point. That function would have to chain the default. Hmm
https://github.com/nortikin/sverchok/blob/master/nodes/basic_data/dupli_instances.py#L44-L53 for instance, because of the alternative update=
https://github.com/nortikin/sverchok/blob/master/nodes/basic_data/dupli_instances.py#L59-L61
I realize the execution model is different, but it might still be necessary to have that option..
Yeah, also allowing get/set.
Of course right now changing any property results in a total recompilation of everything, I would like to move this to a model where at least values of properties are updated somewhat more clever.
Stopped the overriding, of user supplied data. Even though giving two different defaults should probably be considered an error I will leave that for now.
func, kwargs = annotations[name]
defaults = {"name": name,
"default": parameter.default,
"update": execute_tree}
for key, value in defaults.items():
if key not in kwargs:
kwargs[key] = value
if a property has ext=True
it will be drawn in with draw_buttons_ext
, instead of in the node.
With this I close this, the node based property control I leave for later.
Right now nodes are wonderfully simple. I would like to keep them that way, but at the same time I realize there are limits too how simple they can be. But as a general rule simplicity is a good starting point and then only adding complexity as needed.
Properties
First up are properties. It is easy enough to imagine something along the lines of the following for simple properties, like integer, float, bool and string.
The current:
But if we look at the
np.linspace
documentation there are some additional parameters available, for now let us considerendpoint: bool
which specifies if the generated linear space will be[start, ... ,stop]
or[start, ..., stop-step]
Like this.For me this seems like perfect candidate for an input that does not need to be a socket.
From this a property could automatically be generated, as well as a
draw_buttons
that automatically draws the properties.Resulting in class corresponding the following:
In the compile stage these could then be put into a
kwargs
dict and passed along to the function along these lines.This has the, positive, side effect that all properties must be placed after the socket inputs, as well a giving and order for the drawing of them.
Additional parameters for which things to only draw in the
draw_buttons_ext
as well as passing along a dict for the property creation/drawing could be supported.For more complex case supplying a custom
draw_buttons
could be supported.Also, perhaps far out, making something along these lines makes the properties easily inspectable, it is easy enough to imagine a properties socket being made available and creating an additional node, as needed, for drawing the parameters there.
The sole purpose of this node being to be able to control multiple linspace nodes and vary the arguments of the properties as needed. For linspace this might not the most useful thing but for other cases it could very well offer an extreme additional flexibility while keeping a simple default case. The parameter dicts would the be treated and matched as other parts of the data tree.