Merge of the PyNodes branch (aka "custom nodes") into trunk.

PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements.

=== Dynamic node type registration ===
Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes.

Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2].

=== Node group improvements ===
Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3].

The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there.

[1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes
[2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender
[3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
This commit is contained in:
Lukas Toenne
2013-03-18 16:34:57 +00:00
parent 7bfef29f2f
commit 4638e5f99a
293 changed files with 13411 additions and 9059 deletions
@@ -0,0 +1,23 @@
"""
Poll Function
+++++++++++++++
The :class:`NodeTree.poll` function determines if a node tree is visible
in the given context (similar to how :class:`Panel.poll`
and :class:`Menu.poll` define visibility). If it returns False,
the node tree type will not be selectable in the node editor.
A typical condition for shader nodes would be to check the active render engine
of the scene and only show nodes of the renderer they are designed for.
"""
import bpy
class CyclesNodeTree(bpy.types.NodeTree):
""" This operator is only visible when Cycles is the selected render engine"""
bl_label = "Cycles Node Tree"
@classmethod
def poll(cls, context):
return context.scene.render.engine == 'CYCLES'
bpy.utils.register_class(CyclesNodeTree)
+57 -36
View File
@@ -207,6 +207,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args)
}
#ifdef WITH_OSL
static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
{
PyObject *pynodegroup, *pynode;
@@ -248,17 +249,19 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* determine socket type */
BL::NodeSocket::type_enum socket_type;
float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f};
std::string socket_type;
BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
float default_float = 0.0f;
int default_int = 0;
std::string default_string = "";
if(param->isclosure) {
socket_type = BL::NodeSocket::type_SHADER;
socket_type = "NodeSocketShader";
}
else if(param->type.vecsemantics == TypeDesc::COLOR) {
socket_type = BL::NodeSocket::type_RGBA;
socket_type = "NodeSocketColor";
data_type = BL::NodeSocket::type_RGBA;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -269,7 +272,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
else if(param->type.vecsemantics == TypeDesc::POINT ||
param->type.vecsemantics == TypeDesc::VECTOR ||
param->type.vecsemantics == TypeDesc::NORMAL) {
socket_type = BL::NodeSocket::type_VECTOR;
socket_type = "NodeSocketVector";
data_type = BL::NodeSocket::type_VECTOR;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -279,17 +283,20 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
else if(param->type.aggregate == TypeDesc::SCALAR) {
if(param->type.basetype == TypeDesc::INT) {
socket_type = BL::NodeSocket::type_INT;
socket_type = "NodeSocketInt";
data_type = BL::NodeSocket::type_INT;
if(param->validdefault)
default_int = param->idefault[0];
}
else if(param->type.basetype == TypeDesc::FLOAT) {
socket_type = BL::NodeSocket::type_VALUE;
socket_type = "NodeSocketFloat";
data_type = BL::NodeSocket::type_VALUE;
if(param->validdefault)
default_float = param->fdefault[0];
}
else if(param->type.basetype == TypeDesc::STRING) {
socket_type = BL::NodeSocket::type_STRING;
socket_type = "NodeSocketString";
data_type = BL::NodeSocket::type_STRING;
if(param->validdefault)
default_string = param->sdefault[0];
}
@@ -300,38 +307,52 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* find socket socket */
BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput);
/* remove if type no longer matches */
if(b_sock && b_sock.type() != socket_type) {
b_node.remove_socket(b_sock);
b_sock = BL::NodeSocket(PointerRNA_NULL);
BL::NodeSocket b_sock(PointerRNA_NULL);
if (param->isoutput) {
b_sock = b_node.outputs[param->name];
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
b_node.outputs.remove(b_sock);
b_sock = BL::NodeSocket(PointerRNA_NULL);
}
if (!b_sock) {
/* create new socket */
b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
}
}
else {
b_sock = b_node.inputs[param->name];
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
b_node.inputs.remove(b_sock);
b_sock = BL::NodeSocket(PointerRNA_NULL);
}
if (!b_sock) {
/* create new socket */
b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
}
}
/* create new socket */
if(!b_sock) {
b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput);
/* set default value */
if(socket_type == BL::NodeSocket::type_VALUE) {
BL::NodeSocketFloatNone b_float_sock(b_sock.ptr);
b_float_sock.default_value(default_float);
/* set default value */
if(b_sock) {
if(data_type == BL::NodeSocket::type_VALUE) {
set_float(b_sock.ptr, "default_value", default_float);
}
else if(socket_type == BL::NodeSocket::type_INT) {
BL::NodeSocketIntNone b_int_sock(b_sock.ptr);
b_int_sock.default_value(default_int);
else if(data_type == BL::NodeSocket::type_INT) {
set_int(b_sock.ptr, "default_value", default_int);
}
else if(socket_type == BL::NodeSocket::type_RGBA) {
BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr);
b_rgba_sock.default_value(default_float4);
else if(data_type == BL::NodeSocket::type_RGBA) {
set_float4(b_sock.ptr, "default_value", default_float4);
}
else if(socket_type == BL::NodeSocket::type_VECTOR) {
BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr);
b_vector_sock.default_value(default_float4);
else if(data_type == BL::NodeSocket::type_VECTOR) {
set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
}
else if(socket_type == BL::NodeSocket::type_STRING) {
BL::NodeSocketStringNone b_string_sock(b_sock.ptr);
b_string_sock.default_value(default_string);
else if(data_type == BL::NodeSocket::type_STRING) {
set_string(b_sock.ptr, "default_value", default_string);
}
}
@@ -349,7 +370,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
b_node.remove_socket(*b_input);
b_node.inputs.remove(*b_input);
removed = true;
break;
}
@@ -357,7 +378,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
b_node.remove_socket(*b_output);
b_node.outputs.remove(*b_output);
removed = true;
break;
}
File diff suppressed because it is too large Load Diff
+58 -2
View File
@@ -202,30 +202,60 @@ static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_a
return layer;
}
#if 0
static inline float3 get_float3(PointerRNA& ptr, const char *name)
{
float3 f;
RNA_float_get_array(&ptr, name, &f.x);
return f;
}
#endif
static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
{
RNA_float_set_array(&ptr, name, &value.x);
}
static inline float4 get_float4(PointerRNA& ptr, const char *name)
{
float4 f;
RNA_float_get_array(&ptr, name, &f.x);
return f;
}
static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
{
RNA_float_set_array(&ptr, name, &value.x);
}
static inline bool get_boolean(PointerRNA& ptr, const char *name)
{
return RNA_boolean_get(&ptr, name)? true: false;
}
static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
{
RNA_boolean_set(&ptr, name, (int)value);
}
static inline float get_float(PointerRNA& ptr, const char *name)
{
return RNA_float_get(&ptr, name);
}
static inline void set_float(PointerRNA& ptr, const char *name, float value)
{
RNA_float_set(&ptr, name, value);
}
static inline int get_int(PointerRNA& ptr, const char *name)
{
return RNA_int_get(&ptr, name);
}
static inline void set_int(PointerRNA& ptr, const char *name, int value)
{
RNA_int_set(&ptr, name, value);
}
static inline int get_enum(PointerRNA& ptr, const char *name)
{
return RNA_enum_get(&ptr, name);
@@ -242,6 +272,32 @@ static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
return string(identifier);
}
static inline void set_enum(PointerRNA& ptr, const char *name, int value)
{
RNA_enum_set(&ptr, name, value);
}
static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
{
RNA_enum_set_identifier(&ptr, name, identifier.c_str());
}
static inline string get_string(PointerRNA& ptr, const char *name)
{
char cstrbuf[1024];
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
string str(cstr);
if (cstr != cstrbuf)
MEM_freeN(cstr);
return str;
}
static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
{
RNA_string_set(&ptr, name, value.c_str());
}
/* Relative Paths */
static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
+2
View File
@@ -43,6 +43,8 @@ class OSLCompiler;
* Data type for inputs and outputs */
enum ShaderSocketType {
SHADER_SOCKET_UNDEFINED,
SHADER_SOCKET_FLOAT,
SHADER_SOCKET_INT,
SHADER_SOCKET_COLOR,
+4 -5
View File
@@ -1242,15 +1242,14 @@ void ConvertNode::compile(OSLCompiler& compiler)
/* Proxy */
ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_)
ProxyNode::ProxyNode(ShaderSocketType type_)
: ShaderNode("proxy")
{
from = from_;
to = to_;
type = type_;
special_type = SHADER_SPECIAL_TYPE_PROXY;
add_input("Input", from);
add_output("Output", to);
add_input("Input", type);
add_output("Output", type);
}
void ProxyNode::compile(SVMCompiler& compiler)
+2 -2
View File
@@ -190,10 +190,10 @@ public:
class ProxyNode : public ShaderNode {
public:
ProxyNode(ShaderSocketType from, ShaderSocketType to);
ProxyNode(ShaderSocketType type);
SHADER_NODE_BASE_CLASS(ProxyNode)
ShaderSocketType from, to;
ShaderSocketType type;
};
class BsdfNode : public ShaderNode {
+144 -11
View File
@@ -485,17 +485,6 @@ class Text(bpy_types.ID):
)
class NodeSocket(StructRNA): # , metaclass=RNAMeta
__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))
# values are module: [(cls, path, line), ...]
TypeMap = {}
@@ -757,3 +746,147 @@ class Region(StructRNA):
return None
class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup):
__slots__ = ()
class NodeSocketTemplate():
type = 'UNDEFINED'
# Default implementation:
# Create a single property using the socket template's 'value_property' attribute
# value_property should be created in the __init__ function
#
# If necessary this function can be overloaded in subclasses, e.g. to create multiple value properties
def define_node_properties(self, node_type, prefix):
if hasattr(self, "value_property"):
setattr(node_type, prefix+"value", self.value_property)
def init_socket(self, socket):
socket.type = self.type
if hasattr(self, "value_property"):
socket.value_property = self.value_property[1]['attr']
def gen_valid_identifier(seq):
# get an iterator
itr = iter(seq)
# pull characters until we get a legal one for first in identifer
for ch in itr:
if ch == '_' or ch.isalpha():
yield ch
break
# pull remaining characters and yield legal ones for identifier
for ch in itr:
if ch == '_' or ch.isalpha() or ch.isdigit():
yield ch
def sanitize_identifier(name):
return ''.join(gen_valid_identifier(name))
def unique_identifier(name, identifier_list):
# First some basic sanitation, to make a usable identifier string from the name
base = sanitize_identifier(name)
# Now make a unique identifier by appending an unused index
identifier = base
index = 0
while identifier in identifier_list:
index += 1
identifier = base + str(index)
return identifier
class RNAMetaNode(RNAMetaPropGroup):
def __new__(cls, name, bases, classdict, **args):
# Wrapper for node.init, to add sockets from templates
def create_sockets(self):
inputs = getattr(self, 'input_templates', None)
if inputs:
for temp in inputs:
socket = self.inputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
temp.init_socket(socket)
outputs = getattr(self, 'output_templates', None)
if outputs:
for temp in outputs:
socket = self.outputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
temp.init_socket(socket)
init_base = classdict.get('init', None)
if init_base:
def init_node(self, context):
create_sockets(self)
init_base(self, context)
else:
def init_node(self, context):
create_sockets(self)
classdict['init'] = init_node
# Create the regular class
result = RNAMetaPropGroup.__new__(cls, name, bases, classdict)
# Add properties from socket templates
inputs = classdict.get('input_templates', None)
if inputs:
for i, temp in enumerate(inputs):
temp.identifier = unique_identifier(temp.name, [t.identifier for t in inputs[0:i]])
temp.define_node_properties(result, "input_"+temp.identifier+"_")
outputs = classdict.get('output_templates', None)
if outputs:
for i, temp in enumerate(outputs):
temp.identifier = unique_identifier(temp.name, [t.identifier for t in outputs[0:i]])
temp.define_node_properties(result, "output_"+temp.identifier+"_")
return result
class Node(StructRNA, metaclass=RNAMetaNode):
__slots__ = ()
@classmethod
def poll(cls, ntree):
return True
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__ = ()
# These are intermediate subclasses, need a bpy type too
class CompositorNode(Node):
__slots__ = ()
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'CompositorNodeTree'
def update(self):
self.tag_need_exec()
class ShaderNode(Node):
__slots__ = ()
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'ShaderNodeTree'
class TextureNode(Node):
__slots__ = ()
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'TextureNodeTree'
+95 -101
View File
@@ -100,75 +100,55 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
return result
# XXX These node item lists should actually be generated by a callback at
# operator execution time (see node_type_items below),
# using the active node tree from the context.
# Due to a difficult bug in bpy this is not possible
# (item list memory gets freed too early),
# so for now just copy the static item lists to these global variables.
#
# In the custom_nodes branch, the static per-tree-type node items are replaced
# by a single independent type list anyway (with a poll function to limit node
# types to the respective trees). So this workaround is only temporary.
# lazy init
node_type_items_dict = {}
# Prefixes used to distinguish base node types and node groups
node_type_prefix = 'NODE_'
node_group_prefix = 'GROUP_'
def node_classes_iter(base=bpy.types.Node):
"""
Yields all true node classes by checking for the is_registered_node_type classmethod.
Node types can use specialized subtypes of bpy.types.Node, which are not usable
nodes themselves (e.g. CompositorNode).
"""
if base.is_registered_node_type():
yield base
for subclass in base.__subclasses__():
for node_class in node_classes_iter(subclass):
yield node_class
# Generate a list of enum items for a given node class
# Copy existing type enum, adding a prefix to distinguish from node groups
# Skip the base node group type,
# node groups will be added below for all existing group trees
def node_type_items(node_class):
return [(node_type_prefix + item.identifier, item.name, item.description)
for item in node_class.bl_rna.properties['type'].enum_items
if item.identifier != 'GROUP']
def node_class_items_iter(node_class, context):
identifier = node_class.bl_rna.identifier
# XXX Checking for explicit group node types is stupid.
# This should be replaced by a generic system of generating
# node items via callback.
# Group node_tree pointer should also use a poll function to filter the library list,
# but cannot do that without a node instance here. A node callback could just use the internal poll function.
if identifier in {'ShaderNodeGroup', 'CompositorNodeGroup', 'TextureNodeGroup'}:
tree_idname = context.space_data.edit_tree.bl_idname
for group in bpy.data.node_groups:
if group.bl_idname == tree_idname:
yield (group.name, "", {"node_tree":group}) # XXX empty string should be replaced by description from tree
else:
yield (node_class.bl_rna.name, node_class.bl_rna.description, {})
# Generate items for node group types
# Filter by the given tree_type
# Node group trees don't have a description property yet
# (could add this as a custom property though)
def node_group_items(tree_type):
return [(node_group_prefix + group.name, group.name, '')
for group in bpy.data.node_groups if group.type == tree_type]
# Returns the enum item list for the edited tree in the context
def node_type_items_cb(self, context):
def node_items_iter(context):
snode = context.space_data
if not snode:
return ()
return
tree = snode.edit_tree
if not tree:
return ()
return
# Lists of basic node types for each
if not node_type_items_dict:
node_type_items_dict.update({
'SHADER': node_type_items(bpy.types.ShaderNode),
'COMPOSITING': node_type_items(bpy.types.CompositorNode),
'TEXTURE': node_type_items(bpy.types.TextureNode),
})
# XXX Does not work correctly, see comment above
'''
return [(item.identifier, item.name, item.description, item.value)
for item in
tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items]
'''
if tree.type in node_type_items_dict:
return node_type_items_dict[tree.type] + node_group_items(tree.type)
else:
return ()
for node_class in node_classes_iter():
if node_class.poll(tree):
for item in node_class_items_iter(node_class, context):
yield (node_class,) + item
class NODE_OT_add_search(Operator):
# Create an enum list from node class items
def node_type_items_cb(self, context):
return [(str(index), item[1], item[2]) for index, item in enumerate(node_items_iter(context))]
class NODE_OT_add_search(NodeAddOperator, Operator):
'''Add a node to the active tree'''
bl_idname = "node.add_search"
bl_label = "Search and Add Node"
@@ -182,57 +162,50 @@ class NODE_OT_add_search(Operator):
items=node_type_items_cb,
)
_node_type_items_dict = None
def create_node(self, context):
space = context.space_data
tree = space.edit_tree
# Enum item identifier has an additional prefix to
# distinguish base node types from node groups
item = self.type
if item.startswith(node_type_prefix):
# item means base node type
node = tree.nodes.new(type=item[len(node_type_prefix):])
elif item.startswith(node_group_prefix):
# item means node group type
node = tree.nodes.new(
type='GROUP',
group=bpy.data.node_groups[item[len(node_group_prefix):]])
else:
return None
for n in tree.nodes:
if n == node:
node.select = True
tree.nodes.active = node
else:
node.select = False
node.location = space.cursor_location
return node
@classmethod
def poll(cls, context):
space = context.space_data
# needs active node editor and a tree to add nodes to
return (space.type == 'NODE_EDITOR' and space.edit_tree)
def execute(self, context):
self.create_node(context)
for index, item in enumerate(node_items_iter(context)):
if str(index) == self.type:
node = self.create_node(context, item[0].bl_rna.identifier)
for prop,value in item[3].items():
setattr(node, prop, value)
break
return {'FINISHED'}
def invoke(self, context, event):
space = context.space_data
v2d = context.region.view2d
# convert mouse position to the View2D for later node placement
space.cursor_location = v2d.region_to_view(event.mouse_region_x,
event.mouse_region_y)
self.store_mouse_cursor(context, event)
# Delayed execution in the search popup
context.window_manager.invoke_search_popup(self)
return {'CANCELLED'}
# Simple basic operator for adding a node without further initialization
class NODE_OT_add_node(NodeAddOperator, bpy.types.Operator):
'''Add a node to the active tree'''
bl_idname = "node.add_node"
bl_label = "Add Node"
type = StringProperty(name="Node Type", description="Node type")
def execute(self, context):
node = self.create_node(context, self.type)
return {'FINISHED'}
class NODE_OT_add_group_node(NodeAddOperator, bpy.types.Operator):
'''Add a group node to the active tree'''
bl_idname = "node.add_group_node"
bl_label = "Add Group Node"
type = StringProperty(name="Node Type", description="Node type")
grouptree = StringProperty(name="Group tree", description="Group node tree name")
def execute(self, context):
node = self.create_node(context, self.type)
node.node_tree = bpy.data.node_groups[self.grouptree]
return {'FINISHED'}
class NODE_OT_collapse_hide_unused_toggle(Operator):
'''Toggle collapsed nodes and hide unused sockets'''
bl_idname = "node.collapse_hide_unused_toggle"
@@ -261,3 +234,24 @@ class NODE_OT_collapse_hide_unused_toggle(Operator):
socket.hide = hide
return {'FINISHED'}
class NODE_OT_tree_path_parent(Operator):
'''Go to parent node tree'''
bl_idname = "node.tree_path_parent"
bl_label = "Parent Node Tree"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
space = context.space_data
# needs active node editor and a tree
return (space.type == 'NODE_EDITOR' and len(space.path) > 1)
def execute(self, context):
space = context.space_data
space.path.pop()
return {'FINISHED'}
+37 -6
View File
@@ -44,8 +44,8 @@ class NODE_HT_header(Header):
row.menu("NODE_MT_node")
layout.prop(snode, "tree_type", text="", expand=True)
if snode.tree_type == 'SHADER':
if snode.tree_type == 'ShaderNodeTree':
if scene.render.use_shading_nodes:
layout.prop(snode, "shader_type", text="", expand=True)
@@ -65,7 +65,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'TEXTURE':
elif snode.tree_type == 'TextureNodeTree':
layout.prop(snode, "texture_type", text="", expand=True)
if id_from:
@@ -76,7 +76,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'COMPOSITING':
elif snode.tree_type == 'CompositorNodeTree':
layout.prop(snode_id, "use_nodes")
layout.prop(snode_id.render, "use_free_unused_nodes", text="Free Unused")
layout.prop(snode, "show_backdrop")
@@ -84,6 +84,13 @@ class NODE_HT_header(Header):
row = layout.row(align=True)
row.prop(snode, "backdrop_channels", text="", expand=True)
layout.prop(snode, "use_auto_render")
else:
# Custom node tree is edited as independent ID block
layout.template_ID(snode, "node_tree", new="node.new_node_tree")
layout.prop(snode, "pin", text="")
layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
layout.separator()
@@ -182,6 +189,7 @@ class NODE_MT_node(Menu):
layout.operator("node.group_edit")
layout.operator("node.group_ungroup")
layout.operator("node.group_make")
layout.operator("node.group_insert")
layout.separator()
@@ -208,7 +216,7 @@ class NODE_PT_properties(Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
return snode.tree_type == 'COMPOSITING'
return snode.tree_type == 'CompositorNodeTree'
def draw_header(self, context):
snode = context.space_data
@@ -237,7 +245,7 @@ class NODE_PT_quality(bpy.types.Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
return snode.tree_type == 'COMPOSITING' and snode.node_tree is not None
return snode.tree_type == 'CompositorNodeTree' and snode.node_tree is not None
def draw(self, context):
layout = self.layout
@@ -276,5 +284,28 @@ class NODE_MT_node_color_specials(Menu):
layout.operator("node.node_copy_color", icon='COPY_ID')
class NODE_UL_interface_sockets(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
socket = item
color = socket.draw_color(context)
if self.layout_type in {'DEFAULT', 'COMPACT'}:
row = layout.row(align=True)
# inputs get icon on the left
if socket.in_out == 'IN':
row.template_node_socket(color)
row.label(text=socket.name, icon_value=icon)
# outputs get icon on the right
if socket.in_out == 'OUT':
row.template_node_socket(color)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.template_node_socket(color)
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
@@ -0,0 +1,159 @@
import bpy
# XXX these don't work yet ...
#from bpy_types import NodeTree, Node, NodeSocket
# Implementation of custom nodes from Python
# Shortcut for node type menu
def add_nodetype(layout, type):
layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier
# Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc.
class MyCustomTree(bpy.types.NodeTree):
# Description string
'''A custom node tree type that will show up in the node editor header'''
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomTreeType'
# Label for nice name display
bl_label = 'Custom Node Tree'
# Icon identifier
# NOTE: If no icon is defined, the node tree will not show up in the editor header!
# This can be used to make additional tree types for groups and similar nodes (see below)
# Only one base tree class is needed in the editor for selecting the general category
bl_icon = 'NODETREE'
def draw_add_menu(self, context, layout):
layout.label("Hello World!")
add_nodetype(layout, bpy.types.CustomNodeType)
add_nodetype(layout, bpy.types.MyCustomGroup)
# Custom socket type
class MyCustomSocket(bpy.types.NodeSocket):
# Description string
'''Custom node socket type'''
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomSocketType'
# Label for nice name display
bl_label = 'Custom Node Socket'
# Socket color
bl_color = (1.0, 0.4, 0.216, 0.5)
# Enum items list
my_items = [
("DOWN", "Down", "Where your feet are"),
("UP", "Up", "Where your head should be"),
("LEFT", "Left", "Not right"),
("RIGHT", "Right", "Not left")
]
myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
# Optional function for drawing the socket input value
def draw(self, context, layout, node):
layout.prop(self, "myEnumProperty", text=self.name)
# Base class for all custom nodes in this tree type.
# Defines a poll function to enable instantiation.
class MyCustomTreeNode :
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'CustomTreeType'
# Derived from the Node base type.
class MyCustomNode(bpy.types.Node, MyCustomTreeNode):
# === Basics ===
# Description string
'''A custom node'''
# Optional identifier string. If not explicitly defined, the python class name is used.
bl_idname = 'CustomNodeType'
# Label for nice name display
bl_label = 'Custom Node'
# Icon identifier
bl_icon = 'SOUND'
# === Custom Properties ===
# These work just like custom properties in ID data blocks
# Extensive information can be found under
# http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
myStringProperty = bpy.props.StringProperty()
myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
# === Optional Functions ===
# Initialization function, called when a new node is created.
# This is the most common place to create the sockets for a node, as shown below.
# NOTE: this is not the same as the standard __init__ function in Python, which is
# a purely internal Python method and unknown to the node system!
def init(self, context):
self.inputs.new('CustomSocketType', "Hello")
self.inputs.new('NodeSocketFloat', "World")
self.inputs.new('NodeSocketVector', "!")
self.outputs.new('NodeSocketColor', "How")
self.outputs.new('NodeSocketColor', "are")
self.outputs.new('NodeSocketFloat', "you")
# Copy function to initialize a copied node from an existing one.
def copy(self, node):
print("Copying from node ", node)
# Free function to clean up on removal.
def free(self):
print("Removing node ", self, ", Goodbye!")
# Additional buttons displayed on the node.
def draw_buttons(self, context, layout):
layout.label("Node settings")
layout.prop(self, "myFloatProperty")
# Detail buttons in the sidebar.
# If this function is not defined, the draw_buttons function is used instead
def draw_buttons_ext(self, context, layout):
layout.prop(self, "myFloatProperty")
# myStringProperty button will only be visible in the sidebar
layout.prop(self, "myStringProperty")
# A customized group-like node.
class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode):
# === Basics ===
# Description string
'''A custom group node'''
# Label for nice name display
bl_label = 'Custom Group Node'
bl_group_tree_idname = 'CustomTreeType'
orks = bpy.props.IntProperty(default=3)
dwarfs = bpy.props.IntProperty(default=12)
wizards = bpy.props.IntProperty(default=1)
# Additional buttons displayed on the node.
def draw_buttons(self, context, layout):
col = layout.column(align=True)
col.prop(self, "orks")
col.prop(self, "dwarfs")
col.prop(self, "wizards")
layout.label("The Node Tree:")
layout.prop(self, "node_tree", text="")
def register():
bpy.utils.register_class(MyCustomTree)
bpy.utils.register_class(MyCustomSocket)
bpy.utils.register_class(MyCustomNode)
bpy.utils.register_class(MyCustomGroup)
def unregister():
bpy.utils.unregister_class(MyCustomTree)
bpy.utils.unregister_class(MyCustomSocket)
bpy.utils.unregister_class(MyCustomNode)
bpy.utils.unregister_class(MyCustomGroup)
if __name__ == "__main__":
register()
+1 -1
View File
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 266
#define BLENDER_SUBVERSION 1
#define BLENDER_SUBVERSION 2
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
+345 -140
View File
@@ -32,8 +32,21 @@
* \ingroup bke
*/
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
#include "DNA_listBase.h"
/* for FOREACH_NODETREE */
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "RNA_types.h"
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
@@ -43,7 +56,10 @@ struct bNodeLink;
struct bNodeSocket;
struct bNodeStack;
struct bNodeTree;
struct bNodeTreeType;
struct bNodeTreeExec;
struct bNodeExecContext;
struct bNodeExecData;
struct GPUMaterial;
struct GPUNode;
struct GPUNodeStack;
@@ -65,6 +81,7 @@ struct ARegion;
struct Object;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
struct bNodeInstanceHash;
/* ************** NODE TYPE DEFINITIONS ***** */
@@ -72,9 +89,9 @@ struct ColorManagedDisplaySettings;
* Can be used to quickly define a list of static sockets for a node,
* which are added to each new node of that type.
*
* \deprecated New nodes should add default sockets in the initialization
* function instead. This struct is mostly kept for old nodes and should
* be removed some time.
* \deprecated This struct is used by C nodes to define templates as simple
* static struct lists. These are converted to the new template collections
* in RNA types automatically.
*/
typedef struct bNodeSocketTemplate {
int type, limit;
@@ -86,38 +103,38 @@ typedef struct bNodeSocketTemplate {
/* after this line is used internal only */
struct bNodeSocket *sock; /* used to hold verified socket */
char identifier[64]; /* generated from name */
} bNodeSocketTemplate;
typedef void (*NodeSocketButtonFunction)(const struct bContext *C, struct uiBlock *block,
struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock,
const char *name, int x, int y, int width);
/** Defines a socket type.
* Defines the appearance and behavior of a socket in the UI.
*/
typedef struct bNodeSocketType {
int type;
char ui_name[64]; /* MAX_NAME */
char ui_description[128];
int ui_icon;
char ui_color[4];
char idname[64]; /* identifier name */
const char *value_structname;
int value_structsize;
void (*draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr);
void (*draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color);
NodeSocketButtonFunction buttonfunc;
void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr);
void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color);
void (*interface_register_properties)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct StructRNA *data_srna);
void (*interface_init_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock, const char *data_path);
void (*interface_from_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock);
/* RNA integration */
ExtensionRNA ext_socket;
ExtensionRNA ext_interface;
/* for standard socket types in C */
int type, subtype;
} bNodeSocketType;
/** Template for creating a node.
* Stored required parameters to make a new node of a specific type.
*/
typedef struct bNodeTemplate {
int type;
struct Main *main;
struct Scene *scene;
struct bNodeTree *ngroup; /* group tree */
} bNodeTemplate;
typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr, int linked);
typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out);
/** Defines a node type.
* Initial attributes and constants for a node as well as callback functions
@@ -127,8 +144,13 @@ typedef struct bNodeType {
void *next, *prev;
short needs_free; /* set for allocated types that need to be freed */
char idname[64]; /* identifier name */
int type;
char name[64]; /* MAX_NAME */
char ui_name[64]; /* MAX_NAME */
char ui_description[256];
int ui_icon;
float width, minwidth, maxwidth;
float height, minheight, maxheight;
short nclass, flag, compatibility;
@@ -139,7 +161,8 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
/// Main draw function for the node.
void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
/// Updates the node geometry attributes according to internal state before actual drawing.
void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
/// Draw the option buttons on the node.
@@ -150,8 +173,11 @@ typedef struct bNodeType {
void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Draw a node socket. Default draws the input value button.
NodeSocketButtonFunction drawinputfunc;
NodeSocketButtonFunction drawoutputfunc;
/* XXX deprecated, only used for the OutputFile node,
* should be removed at some point.
*/
NodeSocketDrawFunction drawinputfunc;
NodeSocketDrawFunction drawoutputfunc;
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
@@ -168,45 +194,42 @@ typedef struct bNodeType {
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
/// Initialize a new node instance of this type after creation.
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
/// Free the custom storage data.
void (*freestoragefunc)(struct bNode *node);
/// Make a copy of the custom storage data.
void (*copystoragefunc)(struct bNode *node, struct bNode *target);
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
/// Free the node instance.
void (*freefunc)(struct bNode *node);
/// Make a copy of the node instance.
void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
/// Create a template from an existing node.
struct bNodeTemplate (*templatefunc)(struct bNode *);
/** If a node can be made from the template in the given node tree.
* \note Node groups can not be created inside their own node tree.
*/
int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
/* Registerable API callback versions, called in addition to C callbacks */
void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr);
void (*freefunc_api)(struct PointerRNA *ptr);
void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node);
/// Initialize a node tree associated to this node type.
void (*inittreefunc)(struct bNodeTree *ntree);
/// Update a node tree associated to this node type.
void (*updatetreefunc)(struct bNodeTree *ntree);
/* group edit callbacks for operators */
/* XXX this is going to be changed as required by the UI */
struct bNodeTree *(*group_edit_get)(struct bNode *node);
struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit);
void (*group_edit_clear)(struct bNode *node);
/* can this node type be added to a node tree */
int (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree);
/* can this node be added to a node tree */
int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
/* **** execution callbacks **** */
void *(*initexecfunc)(struct bNode *node);
void (*freeexecfunc)(struct bNode *node, void *nodedata);
void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
/* XXX this alternative exec function has been added to avoid changing all node types.
* when a final generic version of execution code is defined, this will be changed anyway
*/
void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **);
NodeInitExecFunction initexecfunc;
NodeFreeExecFunction freeexecfunc;
NodeExecFunction execfunc;
/* gpu */
int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
/* extended gpu function */
int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out);
NodeGPUExecFunction gpufunc;
/* Group type static info
*
* XXX This data is needed by group operators. If these operators could be implemented completely in Python,
* the static data could instead be stored in Python classes and would need no special treatment.
* Due to the way group operators move nodes between data blocks this is currently not possible.
*/
char group_tree_idname[64]; /* tree type associated to the group node type */
/* RNA integration */
ExtensionRNA ext;
} bNodeType;
/* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -245,6 +268,7 @@ typedef struct bNodeType {
#define NODE_CLASS_TRANSFORM 30
#define NODE_CLASS_COMBINE 31
#define NODE_CLASS_SCRIPT 32
#define NODE_CLASS_INTERFACE 33
#define NODE_CLASS_SHADER 40
#define NODE_CLASS_LAYOUT 100
@@ -258,10 +282,6 @@ typedef struct bNodeType {
#define NODE_RESIZE_RIGHT 4
#define NODE_RESIZE_LEFT 8
/* enum values for input/output */
#define SOCK_IN 1
#define SOCK_OUT 2
typedef enum eNodeSizePreset {
NODE_SIZE_DEFAULT,
NODE_SIZE_SMALL,
@@ -270,19 +290,26 @@ typedef enum eNodeSizePreset {
struct bNodeTreeExec;
typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name);
typedef struct bNodeTreeType {
int type; /* type identifier */
char idname[64]; /* id name for RNA identification */
ListBase node_types; /* type definitions */
char idname[64]; /* identifier name */
char ui_name[64];
char ui_description[256];
int ui_icon;
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
void (*foreach_nodetree)(struct Main *main, void *calldata, bNodeTreeCallback func); /* iteration over all node trees */
void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
/* Add menu for this node tree. */
void (*draw_add_menu)(const struct bContext *C, struct uiLayout *layout, struct bNodeTree *ntree);
/* Check visibility in the node editor */
int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
/* Select a node tree from the context */
void (*get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype,
struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from);
/* calls allowing threaded composite */
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
@@ -291,23 +318,37 @@ typedef struct bNodeTreeType {
/* Tree update. Overrides nodetype->updatetreefunc! */
void (*update)(struct bNodeTree *ntree);
/* Node update. Overrides nodetype->updatefunc! */
void (*update_node)(struct bNodeTree *ntree, struct bNode *node);
int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
/* Default internal linking. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
/* RNA integration */
ExtensionRNA ext;
} bNodeTreeType;
/* ************** GENERIC API, TREES *************** */
struct bNodeTreeType *ntreeGetType(int type);
struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
struct bNodeSocketType *ntreeGetSocketType(int type);
struct bNodeTreeType *ntreeTypeFind(const char *idname);
void ntreeTypeAdd(struct bNodeTreeType* nt);
void ntreeTypeFreeLink(struct bNodeTreeType* nt);
struct GHashIterator *ntreeTypeGetIterator(void);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, int type, int nodetype);
void ntreeInitTypes(struct bNodeTree *ntree);
/* helper macros for iterating over tree types */
#define NODE_TREE_TYPES_BEGIN(ntype) \
{ \
GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \
for (; BLI_ghashIterator_notDone(__node_tree_type_iter__); BLI_ghashIterator_step(__node_tree_type_iter__)) { \
bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__);
#define NODE_TREE_TYPES_END \
} \
BLI_ghashIterator_free(__node_tree_type_iter__); \
}
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
int ntreeIsValid(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user);
@@ -337,8 +378,6 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode *
* new tree types have a per-output socket flag to indicate the final output to use explicitly.
*/
void ntreeSetOutput(struct bNodeTree *ntree);
void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize);
void ntreeClearPreview(struct bNodeTree *ntree);
void ntreeFreeCache(struct bNodeTree *ntree);
@@ -348,29 +387,86 @@ struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree);
/* ************** NODE TREE INTERFACE *************** */
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree, int in_out, const char *identifier);
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname, const char *name);
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree, int in_out, const char *idname,
struct bNodeSocket *next_sock, const char *name);
struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock);
struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock,
struct bNode *from_node, struct bNodeSocket *from_sock);
void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
/* ************** GENERIC API, NODES *************** */
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *name, int type);
struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, struct bNodeSocket *next_sock, const char *name, int type);
struct bNodeType *nodeTypeFind(const char *idname);
void nodeRegisterType(struct bNodeType* ntype);
void nodeUnregisterType(struct bNodeType* ntype);
struct GHashIterator *nodeTypeGetIterator(void);
/* helper macros for iterating over node types */
#define NODE_TYPES_BEGIN(ntype) \
{ \
GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \
for (; BLI_ghashIterator_notDone(__node_type_iter__); BLI_ghashIterator_step(__node_type_iter__)) { \
bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__);
#define NODE_TYPES_END \
} \
BLI_ghashIterator_free(__node_type_iter__); \
}
struct bNodeSocketType *nodeSocketTypeFind(const char *idname);
void nodeRegisterSocketType(struct bNodeSocketType* stype);
void nodeUnregisterSocketType(struct bNodeSocketType* stype);
struct GHashIterator *nodeSocketTypeGetIterator(void);
const char * nodeStaticSocketType(int type, int subtype);
const char * nodeStaticSocketInterfaceType(int type, int subtype);
/* helper macros for iterating over node types */
#define NODE_SOCKET_TYPES_BEGIN(stype) \
{ \
GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \
for (; BLI_ghashIterator_notDone(__node_socket_type_iter__); BLI_ghashIterator_step(__node_socket_type_iter__)) { \
bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__);
#define NODE_SOCKET_TYPES_END \
} \
BLI_ghashIterator_free(__node_socket_type_iter__); \
}
void nodeMakeDynamicType(struct bNode *node);
int nodeDynamicUnlinkText(struct ID *txtid);
struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier);
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
const char *identifier, const char *name);
struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
struct bNodeSocket *next_sock, const char *identifier, const char *name);
struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
const char *identifier, const char *name);
struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
struct bNodeSocket *next_sock, const char *identifier, const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage);
struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
void nodeRegisterType(struct bNodeTreeType *ttype, struct bNodeType *ntype);
void nodeMakeDynamicType(struct bNode *node);
int nodeDynamicUnlinkText(struct ID *txtid);
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
int nodeLinkIsHidden(struct bNodeLink *link);
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -380,11 +476,12 @@ void nodeAttachNode(struct bNode *node, struct bNode *parent);
void nodeDetachNode(struct bNode *node);
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex, int *in_out);
int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
void nodeSetSelected(struct bNode *node, int select);
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeGetActive(struct bNodeTree *ntree);
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
@@ -396,11 +493,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
void nodeFreePreview(struct bNode *node);
void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -412,78 +507,189 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void);
const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
/* Node Instance Hash */
typedef struct bNodeInstanceHash
{
GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */
} bNodeInstanceHash;
typedef void (*bNodeInstanceValueFP)(void *value);
extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, struct bNodeTree *ntree, struct bNode *node);
bNodeInstanceHash * BKE_node_instance_hash_new(const char *info);
void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value);
void* BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key);
int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp);
void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
void* BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key);
int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key);
int BKE_node_instance_hash_size(bNodeInstanceHash *hash);
void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash);
void BKE_node_instance_hash_tag(bNodeInstanceHash *hash, void *value);
int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key);
void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
typedef GHashIterator bNodeInstanceHashIterator;
BLI_INLINE bNodeInstanceHashIterator *BKE_node_instance_hash_iterator_new(bNodeInstanceHash *hash) { return BLI_ghashIterator_new(hash->ghash); }
BLI_INLINE void BKE_node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter, bNodeInstanceHash *hash) { BLI_ghashIterator_init(iter, hash->ghash); }
BLI_INLINE void BKE_node_instance_hash_iterator_free(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_free(iter); }
BLI_INLINE bNodeInstanceKey BKE_node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter) { return *(bNodeInstanceKey *)BLI_ghashIterator_getKey(iter); }
BLI_INLINE void* BKE_node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_getValue(iter); }
BLI_INLINE void BKE_node_instance_hash_iterator_step(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_step(iter); }
BLI_INLINE bool BKE_node_instance_hash_iterator_not_done(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_notDone(iter); }
#define NODE_INSTANCE_HASH_ITER(iter_, hash_) \
for (BKE_node_instance_hash_iterator_init(&iter_, hash_); \
BKE_node_instance_hash_iterator_not_done(&iter_); \
BKE_node_instance_hash_iterator_step(&iter_))
/* Node Previews */
int BKE_node_preview_used(struct bNode *node);
bNodePreview* BKE_node_preview_verify(struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create);
bNodePreview* BKE_node_preview_copy(struct bNodePreview *preview);
void BKE_node_preview_free(struct bNodePreview *preview);
void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, int create_previews);
void BKE_node_preview_free_tree(struct bNodeTree *ntree);
void BKE_node_preview_remove_unused(struct bNodeTree *ntree);
void BKE_node_preview_clear(struct bNodePreview *preview);
void BKE_node_preview_clear_tree(struct bNodeTree *ntree);
void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, int do_manage);
/* ************** NODE TYPE ACCESS *************** */
struct bNodeTemplate nodeMakeTemplate(struct bNode *node);
int nodeValid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
const char *nodeLabel(struct bNode *node);
struct bNodeTree *nodeGroupEditGet(struct bNode *node);
struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit);
void nodeGroupEditClear(struct bNode *node);
int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree);
/* Init a new node type struct with default values and callbacks */
void node_type_base(struct bNodeTreeType *ttype, struct bNodeType *ntype, int type,
const char *name, short nclass, short flag);
void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
void node_type_base_custom(struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag);
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs);
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth);
void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size);
void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp));
void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp));
void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node));
void node_type_storage(struct bNodeType *ntype,
const char *storagename,
void (*freestoragefunc)(struct bNode *),
void (*copystoragefunc)(struct bNode *, struct bNode *));
void (*freefunc)(struct bNode *node),
void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node));
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *));
void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *));
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id));
void node_type_tree(struct bNodeType *ntype,
void (*inittreefunc)(struct bNodeTree *),
void (*updatetreefunc)(struct bNodeTree *));
void node_type_group_edit(struct bNodeType *ntype,
struct bNodeTree *(*group_edit_get)(struct bNode *node),
struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
void (*group_edit_clear)(struct bNode *node));
void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **,
struct bNodeStack **));
void node_type_exec_new(struct bNodeType *ntype,
void *(*initexecfunc)(struct bNode *node),
void (*freeexecfunc)(struct bNode *node, void *nodedata),
void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata,
struct bNodeStack **, struct bNodeStack **));
void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc);
void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc);
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node,
struct GPUNodeStack *in, struct GPUNodeStack *out));
void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node,
void *nodedata, struct GPUNodeStack *in,
struct GPUNodeStack *out));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
/* ************** COMMON NODES *************** */
#define NODE_UNDEFINED -2 /* node type is not registered */
#define NODE_CUSTOM -1 /* for dynamically registered custom types */
#define NODE_GROUP 2
#define __NODE_FORLOOP 3 /* deprecated */
#define __NODE_FORLOOP 3 /* deprecated */
#define __NODE_WHILELOOP 4 /* deprecated */
#define NODE_FRAME 5
#define NODE_REROUTE 6
#define NODE_GROUP_INPUT 7
#define NODE_GROUP_OUTPUT 8
/* look up a socket on a group node by the internal group socket */
struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock);
struct bNodeSocket *node_group_find_output(struct bNode *gnode, struct bNodeSocket *gsock);
void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out);
void node_group_expose_all_sockets(struct bNodeTree *ngroup);
void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock);
/* Utility macro for visiting every node tree in the library data, including local bNodeTree blocks in other IDs.
* This avoids the need for callback functions and allows executing code in a single inner code block.
*
* Variables:
*
* nodetree: The actual bNodeTree data block.
* Check nodetree->idname or nodetree->typeinfo to use only specific types.
*
* id: The owner of the bNodeTree data block.
* Same as nodetree if it's a linkable node tree from the library.
*
* Examples:
*
* FOREACH_NODETREE(bmain, nodetree)
* if (id == nodetree)
* printf("This is a linkable node tree");
* FOREACH_NODETREE_END
*
* FOREACH_NODETREE(bmain, nodetree)
* if (nodetree->idname == "ShaderNodeTree")
* printf("This is a shader node tree);
* if (GS(id) == ID_MA)
* printf(" and it's owned by a material");
* FOREACH_NODETREE_END
*/
/* in node_common.c */
void register_node_type_frame(struct bNodeTreeType *ttype);
void register_node_type_reroute(struct bNodeTreeType *ttype);
#define FOREACH_NODETREE(bmain, _nodetree, _id) \
{ \
bNodeTree *_nodetree; \
ID *_id; \
bNodeTree *_ngroup = bmain->nodetree.first; \
Scene *_scene = bmain->scene.first; \
Material *_mat = bmain->mat.first; \
Tex *_tex = bmain->tex.first; \
Lamp *_lamp = bmain->lamp.first; \
World *_world = bmain->world.first; \
/* avoid compiler warning about unused variables */ \
(void)_id; \
(void)_nodetree; \
do { \
if (_ngroup) { \
_nodetree = _ngroup; \
_id = (ID *)_ngroup; \
_ngroup = _ngroup->id.next; \
} \
else if (_scene) { \
_nodetree = _scene->nodetree; \
_id = (ID *)_scene; \
_scene = _scene->id.next; \
} \
else if (_mat) { \
_nodetree = _mat->nodetree; \
_id = (ID *)_mat; \
_mat = _mat->id.next; \
} \
else if (_tex) { \
_nodetree = _tex->nodetree; \
_id = (ID *)_tex; \
_tex = _tex->id.next; \
} \
else if (_lamp) { \
_nodetree = _lamp->nodetree; \
_id = (ID *)_lamp; \
_lamp = _lamp->id.next; \
} \
else if (_world) { \
_nodetree = _world->nodetree; \
_id = (ID *)_world; \
_world = _world->id.next; \
} \
else \
break; \
if (_nodetree) {
void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
#define FOREACH_NODETREE_END \
} \
} while (TRUE); \
}
/* ************** SHADER NODES *************** */
@@ -583,11 +789,10 @@ struct ShadeResult;
/* API */
struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
void nodeShaderSynchronizeID(struct bNode *node, int copyto);
/* switch material render loop */
extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
@@ -798,8 +1003,8 @@ struct TexResult;
int ntreeTexTagAnimated(struct bNodeTree *ntree);
void ntreeTexCheckCyclics(struct bNodeTree *ntree);
struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
float coord[3], float dxt[3], float dyt[3], int osatex, const short thread,
struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
+1 -1
View File
@@ -2171,7 +2171,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
}
else if (sa->spacetype == SPACE_NODE) {
SpaceNode *snode = sa->spacedata.first;
if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) {
if (snode->nodetree && snode->nodetree->type==NTREE_COMPOSIT) {
bNode *node;
for (node = snode->nodetree->nodes.first; node; node = node->next) {
if (node->id && node->type == CMP_NODE_IMAGE) {
+5 -4
View File
@@ -57,6 +57,8 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
#include "NOD_composite.h"
static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
{
if (point == &points_array[spline->tot_point - 1]) {
@@ -966,10 +968,9 @@ void BKE_mask_free(Main *bmain, Mask *mask)
}
}
{
bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb);
}
FOREACH_NODETREE(bmain, ntree, id) {
BKE_node_tree_unlink_id((ID *)mask, ntree);
} FOREACH_NODETREE_END
/* free mask data */
BKE_mask_layer_free_list(&mask->masklayers);
+2 -2
View File
@@ -1012,7 +1012,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
}
}
@@ -1046,7 +1046,7 @@ void end_render_material(Material *mat)
{
if (mat && mat->nodetree && mat->use_nodes) {
if (mat->nodetree->execdata)
ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
ntreeShaderEndExecTree(mat->nodetree->execdata);
}
}
+5 -4
View File
@@ -86,6 +86,8 @@
#include "intern/openexr/openexr_multi.h"
#endif
#include "NOD_composite.h"
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -1401,10 +1403,9 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
}
}
{
bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb);
}
FOREACH_NODETREE(bmain, ntree, id) {
BKE_node_tree_unlink_id((ID *)clip, ntree);
} FOREACH_NODETREE_END
clip->id.us = 0;
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -695,7 +695,7 @@ Tex *BKE_texture_copy(Tex *tex)
if (tex->nodetree) {
if (tex->nodetree->execdata) {
ntreeTexEndExecTree(tex->nodetree->execdata, 1);
ntreeTexEndExecTree(tex->nodetree->execdata);
}
texn->nodetree = ntreeCopyTree(tex->nodetree);
}
+1
View File
@@ -70,6 +70,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfre
void BLI_ghash_insert(GHash *gh, void *key, void *val);
void *BLI_ghash_lookup(GHash *gh, const void *key);
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp);
bool BLI_ghash_haskey(GHash *gh, const void *key);
int BLI_ghash_size(GHash *gh);
+3
View File
@@ -23,10 +23,13 @@
#
# ***** END GPL LICENSE BLOCK *****
# XXX allowing blenkernel and RNA includes in blenlib is a hack,
# but needed in a few places atm (bpath.c for instance)
set(INC
.
# ../blenkernel # dont add this back!
../makesdna
../makesrna
../../../intern/ghost
../../../intern/guardedalloc
../../../extern/wcwidth
+28 -4
View File
@@ -62,8 +62,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
gh->buckets = MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
return gh;
}
@@ -88,8 +87,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
int i, nold = gh->nbuckets;
gh->nbuckets = hashsizes[++gh->cursize];
gh->buckets = (Entry **)MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
for (i = 0; i < nold; i++) {
for (e = old[i]; e; ) {
@@ -148,6 +146,32 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
return false;
}
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
int i;
if (keyfreefp || valfreefp) {
for (i = 0; i < gh->nbuckets; i++) {
Entry *e;
for (e = gh->buckets[i]; e; ) {
Entry *n = e->next;
if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
e = n;
}
}
}
gh->cursize = 0;
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
gh->buckets = MEM_recallocN(gh->buckets, gh->nbuckets * sizeof(*gh->buckets));
}
/* same as above but return the value,
* no free value argument since it will be returned */
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
File diff suppressed because it is too large Load Diff
@@ -152,7 +152,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
void blo_do_version_old_trackto_to_constraints(struct Object *ob);
void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions);
void blo_do_versions_nodetree_default_value(struct bNodeTree *ntree);
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
+155 -25
View File
@@ -672,13 +672,90 @@ static void do_version_bone_roll_256(Bone *bone)
do_version_bone_roll_256(child);
}
static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree)
/* deprecated, only keep this for readfile.c */
/* XXX Deprecated function to add a socket in ntree->inputs/ntree->outputs list
* (previously called node_group_add_socket). This function has been superseded
* by the implementation of proxy nodes. It is still necessary though
* for do_versions of pre-2.56.2 code (r35033), so later proxy nodes
* can be generated consistently from ntree socket lists.
*/
static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup, const char *name, int type, int in_out)
{
// bNodeSocketType *stype = ntreeGetSocketType(type);
bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
BLI_strncpy(gsock->name, name, sizeof(gsock->name));
gsock->type = type;
gsock->next = gsock->prev = NULL;
gsock->new_sock = NULL;
gsock->link = NULL;
/* assign new unique index */
gsock->own_index = ngroup->cur_index++;
gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
// if (stype->value_structsize > 0)
// gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
return gsock;
}
/* Create default_value structs for node sockets from the internal bNodeStack value.
* These structs were used from 2.59.2 on, but are replaced in the subsequent do_versions for custom nodes
* by generic ID property values. This conversion happened _after_ do_versions originally due to messy type initialization
* for node sockets. Now created here intermediately for convenience and to keep do_versions consistent.
*
* Node compatibility code is gross ...
*/
static void do_versions_socket_default_value_259(bNodeSocket *sock)
{
bNodeSocketValueFloat *valfloat;
bNodeSocketValueVector *valvector;
bNodeSocketValueRGBA *valrgba;
if (sock->default_value)
return;
switch (sock->type) {
case SOCK_FLOAT:
valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
valfloat->value = sock->ns.vec[0];
valfloat->min = sock->ns.min;
valfloat->max = sock->ns.max;
valfloat->subtype = PROP_NONE;
break;
case SOCK_VECTOR:
valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
copy_v3_v3(valvector->value, sock->ns.vec);
valvector->min = sock->ns.min;
valvector->max = sock->ns.max;
valvector->subtype = PROP_NONE;
break;
case SOCK_RGBA:
valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
copy_v4_v4(valrgba->value, sock->ns.vec);
break;
}
}
static void do_versions_nodetree_default_value_259(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
for (sock = ntree->inputs.first; sock; sock = sock->next)
sock->flag |= SOCK_DYNAMIC;
for (sock = ntree->outputs.first; sock; sock = sock->next)
sock->flag |= SOCK_DYNAMIC;
for (node=ntree->nodes.first; node; node=node->next) {
for (sock=node->inputs.first; sock; sock=sock->next)
do_versions_socket_default_value_259(sock);
for (sock=node->outputs.first; sock; sock=sock->next)
do_versions_socket_default_value_259(sock);
}
for (sock=ntree->inputs.first; sock; sock=sock->next)
do_versions_socket_default_value_259(sock);
for (sock=ntree->outputs.first; sock; sock=sock->next)
do_versions_socket_default_value_259(sock);
}
void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
@@ -2289,16 +2366,79 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
bNodeTree *ntree;
bNode *node;
bNodeSocket *sock, *gsock;
bNodeLink *link;
/* node sockets are not exposed automatically any more,
* this mimics the old behavior by adding all unlinked sockets to groups.
*/
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
/* XXX Only setting a flag here. Actual adding of group sockets
* is done in lib_verify_nodetree, because at this point the internal
* nodes may not be up-to-date! (missing lib-link)
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
/* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
/* first make sure the own_index for new sockets is valid */
for (node=ntree->nodes.first; node; node=node->next) {
for (sock=node->inputs.first; sock; sock=sock->next)
if (sock->own_index >= ntree->cur_index)
ntree->cur_index = sock->own_index+1;
for (sock=node->outputs.first; sock; sock=sock->next)
if (sock->own_index >= ntree->cur_index)
ntree->cur_index = sock->own_index+1;
}
/* add ntree->inputs/ntree->outputs sockets for all unlinked sockets in the group tree. */
for (node=ntree->nodes.first; node; node=node->next) {
for (sock=node->inputs.first; sock; sock=sock->next) {
if (!sock->link && !nodeSocketIsHidden(sock)) {
gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_IN);
/* initialize the default socket value */
copy_v4_v4(gsock->ns.vec, sock->ns.vec);
/* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
* have to create these directly here. These links are updated again in subsequent do_version!
*/
link= MEM_callocN(sizeof(bNodeLink), "link");
BLI_addtail(&ntree->links, link);
link->fromnode= NULL;
link->fromsock= gsock;
link->tonode= node;
link->tosock= sock;
ntree->update |= NTREE_UPDATE_LINKS;
sock->link = link;
}
}
for (sock=node->outputs.first; sock; sock=sock->next) {
if (nodeCountSocketLinks(ntree, sock)==0 && !nodeSocketIsHidden(sock)) {
gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_OUT);
/* initialize the default socket value */
copy_v4_v4(gsock->ns.vec, sock->ns.vec);
/* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
* have to create these directly here. These links are updated again in subsequent do_version!
*/
link= MEM_callocN(sizeof(bNodeLink), "link");
BLI_addtail(&ntree->links, link);
link->fromnode= node;
link->fromsock= sock;
link->tonode= NULL;
link->tosock= gsock;
ntree->update |= NTREE_UPDATE_LINKS;
gsock->link = link;
}
}
}
/* XXX The external group node sockets needs to adjust their own_index to point at
* associated ntree inputs/outputs internal sockets. However, this can only happen
* after lib-linking (needs access to internal node group tree)!
* Setting a temporary flag here, actual do_versions happens in lib_verify_nodetree.
*/
ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE;
ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
}
}
@@ -2601,39 +2741,29 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bNodeTree *ntree;
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
blo_do_versions_nodetree_default_value(ntree);
do_versions_nodetree_default_value_259(ntree);
ntree->update |= NTREE_UPDATE;
}
for (sce = main->scene.first; sce; sce = sce->id.next)
if (sce->nodetree) {
blo_do_versions_nodetree_default_value(sce->nodetree);
do_versions_nodetree_default_value_259(sce->nodetree);
sce->nodetree->update |= NTREE_UPDATE;
}
for (mat = main->mat.first; mat; mat = mat->id.next)
if (mat->nodetree) {
blo_do_versions_nodetree_default_value(mat->nodetree);
do_versions_nodetree_default_value_259(mat->nodetree);
mat->nodetree->update |= NTREE_UPDATE;
}
for (tex = main->tex.first; tex; tex = tex->id.next)
if (tex->nodetree) {
blo_do_versions_nodetree_default_value(tex->nodetree);
do_versions_nodetree_default_value_259(tex->nodetree);
tex->nodetree->update |= NTREE_UPDATE;
}
}
/* add SOCK_DYNAMIC flag to existing group sockets */
{
bNodeTree *ntree;
/* only need to do this for trees in main, local trees are not used as groups */
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
do_versions_nodetree_dynamic_sockets(ntree);
ntree->update |= NTREE_UPDATE;
}
}
{
/* Initialize group tree nodetypes.
* These are used to distinguish tree types and
+188 -45
View File
@@ -74,6 +74,7 @@
#include <math.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -151,6 +152,7 @@
#include "BKE_curve.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
#include "BKE_idprop.h"
#include "BKE_library.h" // for set_listbasepointers
#include "BKE_main.h"
#include "BKE_node.h"
@@ -162,6 +164,13 @@
#include "BKE_pointcache.h"
#include "BKE_mesh.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
#include "NOD_common.h"
#include "NOD_socket.h" /* for sock->default_value data */
#endif
#include "RNA_access.h"
#include "BLO_writefile.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -670,46 +679,54 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
write_curvemapping_curves(wd, cumap);
}
static void write_node_socket(WriteData *wd, bNodeSocket *sock)
static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock)
{
bNodeSocketType *stype= ntreeGetSocketType(sock->type);
#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* forward compatibility code, so older blenders still open */
sock->stack_type = 1;
if (sock->default_value) {
bNodeSocketValueFloat *valfloat;
bNodeSocketValueVector *valvector;
bNodeSocketValueRGBA *valrgba;
switch (sock->type) {
case SOCK_FLOAT:
valfloat = sock->default_value;
sock->ns.vec[0] = valfloat->value;
sock->ns.min = valfloat->min;
sock->ns.max = valfloat->max;
break;
case SOCK_VECTOR:
valvector = sock->default_value;
copy_v3_v3(sock->ns.vec, valvector->value);
sock->ns.min = valvector->min;
sock->ns.max = valvector->max;
break;
case SOCK_RGBA:
valrgba = sock->default_value;
copy_v4_v4(sock->ns.vec, valrgba->value);
sock->ns.min = 0.0f;
sock->ns.max = 1.0f;
break;
if (node->type == NODE_GROUP) {
bNodeTree *ngroup = (bNodeTree *)node->id;
if (ngroup) {
/* for node groups: look up the deprecated groupsock pointer */
sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
BLI_assert(sock->groupsock != NULL);
/* node group sockets now use the generic identifier string to verify group nodes,
* old blender uses the own_index.
*/
sock->own_index = sock->groupsock->own_index;
}
}
#endif
/* actual socket writing */
writestruct(wd, DATA, "bNodeSocket", 1, sock);
if (sock->default_value)
writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
}
if (sock->prop)
IDP_WriteProperty(sock->prop, wd);
if (sock->default_value)
writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
}
static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), bNodeSocket *sock)
{
#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* forward compatibility code, so older blenders still open */
sock->stack_type = 1;
/* Reconstruct the deprecated default_value structs in socket interface DNA. */
if (sock->default_value == NULL && sock->typeinfo) {
node_socket_init_default_value(sock);
}
#endif
/* actual socket writing */
writestruct(wd, DATA, "bNodeSocket", 1, sock);
if (sock->prop)
IDP_WriteProperty(sock->prop, wd);
}
/* this is only direct data, tree itself should have been written */
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
@@ -721,18 +738,19 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
if (ntree->adt) write_animdata(wd, ntree->adt);
for (node= ntree->nodes.first; node; node= node->next)
for (node= ntree->nodes.first; node; node= node->next) {
writestruct(wd, DATA, "bNode", 1, node);
for (node= ntree->nodes.first; node; node= node->next) {
if (node->prop)
IDP_WriteProperty(node->prop, wd);
for (sock= node->inputs.first; sock; sock= sock->next)
write_node_socket(wd, sock);
write_node_socket(wd, ntree, node, sock);
for (sock= node->outputs.first; sock; sock= sock->next)
write_node_socket(wd, sock);
write_node_socket(wd, ntree, node, sock);
for (link = node->internal_links.first; link; link = link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
if (node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
@@ -741,10 +759,6 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
if (nss->bytecode)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
if (nss->prop)
IDP_WriteProperty(nss->prop, wd);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
@@ -773,11 +787,10 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
for (link= ntree->links.first; link; link= link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
/* external sockets */
for (sock= ntree->inputs.first; sock; sock= sock->next)
write_node_socket(wd, sock);
for (sock= ntree->outputs.first; sock; sock= sock->next)
write_node_socket(wd, sock);
for (sock = ntree->inputs.first; sock; sock = sock->next)
write_node_socket_interface(wd, ntree, sock);
for (sock = ntree->outputs.first; sock; sock = sock->next)
write_node_socket_interface(wd, ntree, sock);
}
static void current_screen_compat(Main *mainvar, bScreen **screen)
@@ -2518,7 +2531,12 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "SpaceTime", 1, sl);
}
else if (sl->spacetype==SPACE_NODE) {
writestruct(wd, DATA, "SpaceNode", 1, sl);
SpaceNode *snode = (SpaceNode *)sl;
bNodeTreePath *path;
writestruct(wd, DATA, "SpaceNode", 1, snode);
for (path=snode->treepath.first; path; path=path->next)
writestruct(wd, DATA, "bNodeTreePath", 1, path);
}
else if (sl->spacetype==SPACE_LOGIC) {
writestruct(wd, DATA, "SpaceLogic", 1, sl);
@@ -2770,6 +2788,118 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
}
}
#ifdef USE_NODE_COMPAT_CUSTOMNODES
static void customnodes_add_deprecated_nodetree_data(bNodeTree *ntree)
{
bNodeLink *link, *last_link = ntree->links.last;
/* Forward compatibility for group nodes: add links to node tree interface sockets.
* These links are invalid by new rules (missing node pointer)!
* They will be removed again in customnodes_free_deprecated_data,
* cannot do this directly lest bNodeLink pointer mapping becomes ambiguous.
* When loading files with such links in a new Blender version
* they will be removed as well.
*/
for (link = ntree->links.first; link; link = link->next) {
bNode *fromnode = link->fromnode, *tonode = link->tonode;
bNodeSocket *fromsock = link->fromsock, *tosock = link->tosock;
/* check both sides of the link, to handle direct input-to-output links */
if (fromnode->type == NODE_GROUP_INPUT) {
fromnode = NULL;
fromsock = ntreeFindSocketInterface(ntree, SOCK_IN, fromsock->identifier);
}
/* only the active output node defines links */
if (tonode->type == NODE_GROUP_OUTPUT && (tonode->flag & NODE_DO_OUTPUT)) {
tonode = NULL;
tosock = ntreeFindSocketInterface(ntree, SOCK_OUT, tosock->identifier);
}
if (!fromnode || !tonode) {
/* Note: not using nodeAddLink here, it asserts existing node pointers */
bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "group node link");
tlink->fromnode = fromnode;
tlink->fromsock = fromsock;
tlink->tonode = tonode;
tlink->tosock= tosock;
tosock->link = tlink;
tlink->flag |= NODE_LINK_VALID;
BLI_addtail(&ntree->links, tlink);
}
/* don't check newly created compatibility links */
if (link == last_link)
break;
}
}
static void customnodes_add_deprecated_data(Main *mainvar)
{
bNodeTree *ntree;
Scene *scene;
Material *mat;
World *world;
Lamp *lamp;
Tex *tex;
for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
customnodes_add_deprecated_nodetree_data(ntree);
for (scene = mainvar->scene.first; scene; scene = scene->id.next)
if (scene->nodetree)
customnodes_add_deprecated_nodetree_data(scene->nodetree);
for (mat = mainvar->mat.first; mat; mat = mat->id.next)
if (mat->nodetree)
customnodes_add_deprecated_nodetree_data(mat->nodetree);
for (world = mainvar->world.first; world; world = world->id.next)
if (world->nodetree)
customnodes_add_deprecated_nodetree_data(world->nodetree);
for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
if (lamp->nodetree)
customnodes_add_deprecated_nodetree_data(lamp->nodetree);
for (tex = mainvar->tex.first; tex; tex = tex->id.next)
if (tex->nodetree)
customnodes_add_deprecated_nodetree_data(tex->nodetree);
}
static void customnodes_free_deprecated_nodetree_data(bNodeTree *ntree)
{
bNodeLink *link, *next_link;
for (link = ntree->links.first; link; link = next_link) {
next_link = link->next;
if (link->fromnode == NULL || link->tonode == NULL)
nodeRemLink(ntree, link);
}
}
static void customnodes_free_deprecated_data(Main *mainvar)
{
bNodeTree *ntree;
Scene *scene;
Material *mat;
World *world;
Lamp *lamp;
Tex *tex;
for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
customnodes_free_deprecated_nodetree_data(ntree);
for (scene = mainvar->scene.first; scene; scene = scene->id.next)
if (scene->nodetree)
customnodes_free_deprecated_nodetree_data(scene->nodetree);
for (mat = mainvar->mat.first; mat; mat = mat->id.next)
if (mat->nodetree)
customnodes_free_deprecated_nodetree_data(mat->nodetree);
for (world = mainvar->world.first; world; world = world->id.next)
if (world->nodetree)
customnodes_free_deprecated_nodetree_data(world->nodetree);
for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
if (lamp->nodetree)
customnodes_free_deprecated_nodetree_data(lamp->nodetree);
for (tex = mainvar->tex.first; tex; tex = tex->id.next)
if (tex->nodetree)
customnodes_free_deprecated_nodetree_data(tex->nodetree);
}
#endif
static void write_brushes(WriteData *wd, ListBase *idbase)
{
Brush *brush;
@@ -2981,6 +3111,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
#endif
#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* deprecated forward compat data is freed again below */
customnodes_add_deprecated_data(mainvar);
#endif
sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION);
mywrite(wd, buf, 12);
@@ -3026,6 +3161,14 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
/* dna as last, because (to be implemented) test for which structs are written */
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* Ugly, forward compatibility code generates deprecated data during writing,
* this has to be freed again. Can not be done directly after writing, otherwise
* the data pointers could be reused and not be mapped correctly.
*/
customnodes_free_deprecated_data(mainvar);
#endif
/* end of file */
memset(&bhead, 0, sizeof(BHead));
bhead.code= ENDB;
@@ -29,7 +29,6 @@ CompositorContext::CompositorContext()
this->m_rd = NULL;
this->m_quality = COM_QUALITY_HIGH;
this->m_hasActiveOpenCLDevices = false;
this->m_activegNode = NULL;
this->m_fastCalculation = false;
this->m_viewSettings = NULL;
this->m_displaySettings = NULL;
@@ -64,11 +64,12 @@ private:
* @see ExecutionSystem
*/
bNodeTree *m_bnodetree;
/**
* @brief activegNode the group node that is currently being edited.
* @brief Preview image hash table
* This field is initialized in ExecutionSystem and must only be read from that point on.
*/
bNode *m_activegNode;
bNodeInstanceHash *m_previews;
/**
* @brief does this system have active opencl devices?
@@ -114,21 +115,21 @@ public:
*/
const bNodeTree *getbNodeTree() const { return this->m_bnodetree; }
/**
* @brief set the active groupnode of the context
*/
void setActivegNode(bNode *gnode) { this->m_activegNode = gnode; }
/**
* @brief get the active groupnode of the context
*/
const bNode *getActivegNode() const { return this->m_activegNode; }
/**
* @brief get the scene of the context
*/
const RenderData *getRenderData() const { return this->m_rd; }
/**
* @brief set the preview image hash table
*/
void setPreviewHash(bNodeInstanceHash *previews) { this->m_previews = previews; }
/**
* @brief get the preview image hash table
*/
bNodeInstanceHash *getPreviewHash() const { return this->m_previews; }
/**
* @brief set view settings of color color management
*/
@@ -124,7 +124,7 @@
Node *Converter::convert(bNode *b_node, bool fast)
{
Node *node;
Node *node = NULL;
if (b_node->flag & NODE_MUTED) {
node = new MuteNode(b_node);
@@ -226,6 +226,10 @@ Node *Converter::convert(bNode *b_node, bool fast)
case NODE_GROUP:
node = new GroupNode(b_node);
break;
case NODE_GROUP_INPUT:
case NODE_GROUP_OUTPUT:
/* handled in GroupNode::ungroup */
break;
case CMP_NODE_NORMAL:
node = new NormalNode(b_node);
break;
@@ -399,7 +403,6 @@ Node *Converter::convert(bNode *b_node, bool fast)
node = new PixelateNode(b_node);
break;
default:
node = new MuteNode(b_node);
break;
}
return node;
@@ -49,7 +49,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
{
this->m_context.setbNodeTree(editingtree);
this->m_context.setPreviewHash(editingtree->previews);
this->m_context.setFastCalculation(fastcalculation);
#if 0 /* XXX TODO find a better way to define visible output nodes from all editors */
bNode *gnode;
for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = gnode->next) {
if (gnode->type == NODE_GROUP && gnode->typeinfo->group_edit_get(gnode)) {
@@ -57,6 +59,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
break;
}
}
#endif
/* initialize the CompositorContext */
if (rendering) {
@@ -68,7 +71,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
this->m_context.setRendering(rendering);
this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL));
ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL);
ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NODE_INSTANCE_KEY_BASE);
this->m_context.setRenderData(rd);
this->m_context.setViewSettings(viewSettings);
@@ -26,7 +26,6 @@
#include <stdio.h>
#include "PIL_time.h"
#include "BKE_node.h"
#include "COM_Converter.h"
#include "COM_NodeOperation.h"
@@ -39,18 +38,25 @@
#include "COM_ReadBufferOperation.h"
#include "COM_ViewerBaseOperation.h"
void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode)
extern "C" {
#include "BKE_node.h"
}
void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
{
vector<Node *>& nodes = system.getNodes();
vector<SocketConnection *>& links = system.getConnections();
const bNode *activeGroupNode = system.getContext().getActivegNode();
bool isActiveGroup = activeGroupNode == groupnode;
/* add all nodes of the tree to the node list */
bNode *node = (bNode *)tree->nodes.first;
while (node != NULL) {
/* XXX TODO replace isActiveGroup by a more accurate check, all visible editors should do this! */
bool isActiveGroup = true;
Node *nnode = addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation());
nnode->setbNodeGroup(groupnode);
if (nnode) {
nnode->setbNodeTree(tree);
nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node));
}
node = node->next;
}
@@ -81,8 +87,10 @@ void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
{
Node *node = Converter::convert(b_node, fast);
node->setIsInActiveGroup(inActiveGroup);
addNode(nodes, node);
if (node) {
node->setIsInActiveGroup(inActiveGroup);
addNode(nodes, node);
}
return node;
}
void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
@@ -109,43 +117,21 @@ void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *re
static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
if (bnode != NULL) {
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
if (node->getbNode() == bnode)
return node->findInputSocketBybNodeSocket(bsocket);
}
}
else {
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
if (node->isProxyNode()) {
InputSocket *proxySocket = node->getInputSocket(0);
if (proxySocket->getbNodeSocket() == bsocket)
return proxySocket;
}
}
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
InputSocket *input = node->findInputSocketBybNodeSocket(bsocket);
if (input)
return input;
}
return NULL;
}
static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
if (bnode != NULL) {
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
if (node->getbNode() == bnode)
return node->findOutputSocketBybNodeSocket(bsocket);
}
}
else {
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
if (node->isProxyNode()) {
OutputSocket *proxySocket = node->getOutputSocket(0);
if (proxySocket->getbNodeSocket() == bsocket)
return proxySocket;
}
}
for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket);
if (output)
return output;
}
return NULL;
}
@@ -190,7 +176,7 @@ void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
tot = system->getNodes().size();
for (int i = 0; i < tot; i++) {
node = system->getNodes()[i];
printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name);
printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
}
tot = system->getOperations().size();
for (int i = 0; i < tot; i++) {
@@ -48,7 +48,7 @@ public:
* @param tree bNodeTree to add
* @return Node representing the "Compositor node" of the maintree. or NULL when a subtree is added
*/
static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode);
static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
/**
* @brief add an editor node to the system.
@@ -157,24 +157,3 @@ NodeOperation *InputSocket::getOperation() const
return NULL;
}
}
float *InputSocket::getStaticValues()
{
/* XXX only works for socket types with actual float input values.
* currently all compositor socket types (value, rgba, vector) support this.
*/
bNodeSocket *b_socket = this->getbNodeSocket();
static float default_null = 0.0f;
switch (this->getDataType()) {
case COM_DT_VALUE:
return &((bNodeSocketValueFloat *)b_socket->default_value)->value;
case COM_DT_COLOR:
return ((bNodeSocketValueRGBA *)b_socket->default_value)->value;
case COM_DT_VECTOR:
return ((bNodeSocketValueVector *)b_socket->default_value)->value;
default:
/* XXX this should never happen, just added to please the compiler */
return &default_null;
}
}
@@ -143,7 +143,6 @@ public:
bool isStatic();
float *getStaticValues();
SocketReader *getReader();
NodeOperation *getOperation() const;
};
+18 -15
View File
@@ -67,10 +67,9 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase()
void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetValueOperation *operation = new SetValueOperation();
bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)bSock->default_value;
operation->setValue(val->value);
operation->setValue(input->getEditorValueFloat());
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
@@ -79,11 +78,13 @@ void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *conte
{
if (this->isInActiveGroup()) {
if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes.
if (this->getbNode()->flag & NODE_PREVIEW) {
bNodeInstanceHash *previews = context->getPreviewHash();
if (previews && (this->getbNode()->flag & NODE_PREVIEW)) {
PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings());
system->addOperation(operation);
operation->setbNode(this->getbNode());
operation->setbNodeTree(system->getContext().getbNodeTree());
operation->verifyPreview(previews, this->getInstanceKey());
this->addLink(system, outputSocket, operation->getInputSocket(0));
}
}
@@ -114,25 +115,27 @@ SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSock
void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetColorOperation *operation = new SetColorOperation();
bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)bSock->default_value;
operation->setChannel1(val->value[0]);
operation->setChannel2(val->value[1]);
operation->setChannel3(val->value[2]);
operation->setChannel4(val->value[3]);
float col[4];
input->getEditorValueColor(col);
operation->setChannel1(col[0]);
operation->setChannel2(col[1]);
operation->setChannel3(col[2]);
operation->setChannel4(col[3]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
bNodeSocketValueVector *val = (bNodeSocketValueVector *)bSock->default_value;
InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetVectorOperation *operation = new SetVectorOperation();
operation->setX(val->value[0]);
operation->setY(val->value[1]);
operation->setZ(val->value[2]);
float vec[3];
input->getEditorValueVector(vec);
operation->setX(vec[0]);
operation->setY(vec[1]);
operation->setZ(vec[2]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
+6 -6
View File
@@ -53,12 +53,11 @@ private:
* @brief Is this node part of the active group
*/
bool m_inActiveGroup;
/**
* @brief The group node this node belongs to.
* @note: used to find the links in the current subtree for muting nodes
* @brief Instance key to identify the node in an instance hash table
*/
bNode *m_bNodeGroup;
bNodeInstanceKey m_instanceKey;
public:
Node(bNode *editorNode, bool create_sockets = true);
@@ -145,8 +144,9 @@ public:
*/
OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
inline void setbNodeGroup(bNode *group) {this->m_bNodeGroup = group;}
inline bNode *getbNodeGroup() {return this->m_bNodeGroup;}
void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
protected:
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
@@ -59,6 +59,11 @@ private:
*/
bNode *m_editorNode;
/**
* @brief stores the reference to the SDNA bNode struct
*/
bNodeTree *m_editorNodeTree;
protected:
/**
* @brief get access to the vector of input sockets
@@ -82,14 +87,25 @@ public:
/**
* @brief get the reference to the SDNA bNode struct
*/
bNode *getbNode() {return m_editorNode;}
bNode *getbNode() const {return m_editorNode;}
/**
* @brief get the reference to the SDNA bNodeTree struct
*/
bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
/**
* @brief set the reference to the bNode
* @note used in Node instances to receive the storage/settings and complex node for highlight during execution
* @param bNode
*/
void setbNode(bNode *bNode) {this->m_editorNode = bNode;}
void setbNode(bNode *node) {this->m_editorNode = node;}
/**
* @brief set the reference to the bNodeTree
* @param bNodeTree
*/
void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
/**
* @brief is this node an operation?
@@ -24,6 +24,10 @@
#include "COM_Node.h"
#include "COM_SocketConnection.h"
extern "C" {
#include "RNA_access.h"
}
Socket::Socket(DataType datatype)
{
this->m_datatype = datatype;
@@ -41,3 +45,24 @@ int Socket::isOutputSocket() const { return false; }
const int Socket::isConnected() const { return false; }
void Socket::setNode(NodeBase *node) { this->m_node = node; }
NodeBase *Socket::getNode() const { return this->m_node; }
float Socket::getEditorValueFloat()
{
PointerRNA ptr;
RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
return RNA_float_get(&ptr, "default_value");
}
void Socket::getEditorValueColor(float *value)
{
PointerRNA ptr;
RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
return RNA_float_get_array(&ptr, "default_value", value);
}
void Socket::getEditorValueVector(float *value)
{
PointerRNA ptr;
RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
return RNA_float_get_array(&ptr, "default_value", value);
}
@@ -36,6 +36,7 @@
using namespace std;
class SocketConnection;
class NodeBase;
struct PointerRNA;
/**
* @brief Base class for InputSocket and OutputSocket.
@@ -86,6 +87,10 @@ public:
void setEditorSocket(bNodeSocket *editorSocket) { this->m_editorSocket = editorSocket; }
bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
float getEditorValueFloat();
void getEditorValueColor(float *value);
void getEditorValueVector(float *value);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Socket")
#endif
@@ -21,9 +21,9 @@
*/
#include "BKE_node.h"
extern "C" {
#include "BLI_threads.h"
#include "BKE_node.h"
#include "BLI_threads.h"
}
#include "BKE_main.h"
#include "BKE_global.h"
@@ -63,6 +63,11 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
return;
}
/* Make sure node tree has previews.
* Don't create previews in advance, this is done when adding preview operations.
*/
BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, COM_PREVIEW_SIZE, FALSE);
/* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL);
WorkScheduler::initialize(use_opencl);
@@ -85,7 +90,6 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
}
}
ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings);
system->execute();
delete system;
@@ -45,8 +45,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
InputSocket *inputSizeSocket = this->getInputSocket(1);
bool connectedSizeSocket = inputSizeSocket->isConnected();
const bNodeSocket *sock = this->getInputSocket(1)->getbNodeSocket();
const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
const float size = this->getInputSocket(1)->getEditorValueFloat();
CompositorQuality quality = context->getQuality();
NodeOperation *input_operation = NULL, *output_operation = NULL;
@@ -60,21 +60,17 @@ void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContex
else {
BokehBlurOperation *operation = new BokehBlurOperation();
const bNodeSocket *sock = this->getInputSocket(2)->getbNodeSocket();
const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(3), 2, graph);
this->getInputSocket(3)->relinkConnections(operation->getInputSocket(2), 3, graph);
//operation->setSize(((bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value);
operation->setQuality(context->getQuality());
operation->setbNode(this->getbNode());
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
if (!connectedSizeSocket) {
operation->setSize(size);
operation->setSize(this->getInputSocket(2)->getEditorValueFloat());
}
}
}
@@ -50,10 +50,11 @@ void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorConte
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)this->getInputSocket(2)->getbNodeSocket()->default_value;
operation->setBlackLevel(val->value);
val = (bNodeSocketValueRGBA *)this->getInputSocket(3)->getbNodeSocket()->default_value;
operation->setWhiteLevel(val->value);
float col[4];
this->getInputSocket(2)->getEditorValueColor(col);
operation->setBlackLevel(col);
this->getInputSocket(3)->getEditorValueColor(col);
operation->setWhiteLevel(col);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
@@ -32,9 +32,10 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
void ColorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetColorOperation *operation = new SetColorOperation();
bNodeSocket *socket = this->getEditorOutputSocket(0);
bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)socket->default_value;
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setChannels(dval->value);
OutputSocket *output = this->getOutputSocket(0);
output->relinkConnections(operation->getOutputSocket());
float col[4];
output->getEditorValueColor(col);
operation->setChannels(col);
graph->addOperation(operation);
}
@@ -20,6 +20,8 @@
* Monique Dewanchand
*/
#include "BKE_node.h"
#include "COM_GroupNode.h"
#include "COM_SocketProxyNode.h"
#include "COM_SetColorOperation.h"
@@ -37,13 +39,38 @@ void GroupNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
}
}
static int find_group_input(GroupNode *gnode, const char *identifier, InputSocket **r_sock)
{
int index;
for (index = 0; index < gnode->getNumberOfInputSockets(); ++index) {
InputSocket *sock = gnode->getInputSocket(index);
if (strcmp(sock->getbNodeSocket()->identifier, identifier)==0) {
*r_sock = sock;
return index;
}
}
*r_sock = NULL;
return -1;
}
static int find_group_output(GroupNode *gnode, const char *identifier, OutputSocket **r_sock)
{
int index;
for (index = 0; index < gnode->getNumberOfOutputSockets(); ++index) {
OutputSocket *sock = gnode->getOutputSocket(index);
if (strcmp(sock->getbNodeSocket()->identifier, identifier)==0) {
*r_sock = sock;
return index;
}
}
*r_sock = NULL;
return -1;
}
void GroupNode::ungroup(ExecutionSystem &system)
{
bNode *bnode = this->getbNode();
bNodeTree *subtree = (bNodeTree *)bnode->id;
vector<InputSocket *> &inputsockets = this->getInputSockets();
vector<OutputSocket *> &outputsockets = this->getOutputSockets();
unsigned int index;
/* get the node list size _before_ adding proxy nodes, so they are available for linking */
int nodes_start = system.getNodes().size();
@@ -54,26 +81,44 @@ void GroupNode::ungroup(ExecutionSystem &system)
return;
}
for (index = 0; index < inputsockets.size(); index++) {
InputSocket *inputSocket = inputsockets[index];
bNodeSocket *editorInput = inputSocket->getbNodeSocket();
if (editorInput->groupsock) {
SocketProxyNode *proxy = new SocketProxyNode(bnode, editorInput, editorInput->groupsock, false);
inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system);
ExecutionSystemHelper::addNode(system.getNodes(), proxy);
}
}
const bool groupnodeBuffering = system.getContext().isGroupnodeBufferEnabled();
for (index = 0; index < outputsockets.size(); index++) {
OutputSocket *outputSocket = outputsockets[index];
bNodeSocket *editorOutput = outputSocket->getbNodeSocket();
if (editorOutput->groupsock) {
SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput, groupnodeBuffering);
outputSocket->relinkConnections(proxy->getOutputSocket(0));
ExecutionSystemHelper::addNode(system.getNodes(), proxy);
/* create proxy nodes for group input/output nodes */
for (bNode *bionode = (bNode *)subtree->nodes.first; bionode; bionode = bionode->next) {
if (bionode->type == NODE_GROUP_INPUT) {
for (bNodeSocket *bsock = (bNodeSocket *)bionode->outputs.first; bsock; bsock = bsock->next) {
InputSocket *gsock;
int gsock_index = find_group_input(this, bsock->identifier, &gsock);
/* ignore virtual sockets */
if (gsock) {
SocketProxyNode *proxy = new SocketProxyNode(bionode, gsock->getbNodeSocket(), bsock, false);
ExecutionSystemHelper::addNode(system.getNodes(), proxy);
gsock->relinkConnectionsDuplicate(proxy->getInputSocket(0), gsock_index, &system);
}
}
}
if (bionode->type == NODE_GROUP_OUTPUT && (bionode->flag & NODE_DO_OUTPUT)) {
for (bNodeSocket *bsock = (bNodeSocket *)bionode->inputs.first; bsock; bsock = bsock->next) {
OutputSocket *gsock;
find_group_output(this, bsock->identifier, &gsock);
/* ignore virtual sockets */
if (gsock) {
SocketProxyNode *proxy = new SocketProxyNode(bionode, bsock, gsock->getbNodeSocket(), groupnodeBuffering);
ExecutionSystemHelper::addNode(system.getNodes(), proxy);
gsock->relinkConnections(proxy->getOutputSocket(0));
}
}
}
}
ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, bnode);
/* unlink the group node itself, input links have been duplicated */
for (int index = 0; index < this->getNumberOfInputSockets(); ++index) {
InputSocket *sock = this->getInputSocket(index);
sock->unlinkConnections(&system);
}
ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, this->getInstanceKey());
}
@@ -51,8 +51,8 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC
operation->setData(data);
if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected())) {
// no nodes connected to the distortion and dispersion. We can precalculate some values
float distortion = ((const bNodeSocketValueFloat *)this->getInputSocket(1)->getbNodeSocket()->default_value)->value;
float dispersion = ((const bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value;
float distortion = this->getInputSocket(1)->getEditorValueFloat();
float dispersion = this->getInputSocket(2)->getEditorValueFloat();
operation->setDistortionAndDispersion(distortion, dispersion);
}
@@ -36,15 +36,13 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
InputSocket *inputSocket = this->getInputSocket(0);
OutputSocket *outputSocket = this->getOutputSocket(0);
OutputSocket *outputSocketDotproduct = this->getOutputSocket(1);
bNode *editorNode = this->getbNode();
SetVectorOperation *operationSet = new SetVectorOperation();
bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first;
bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value;
float normal[3];
outputSocket->getEditorValueVector(normal);
/* animation can break normalization, this restores it */
normalize_v3_v3(normal, dval->value);
normalize_v3(normal);
operationSet->setX(normal[0]);
operationSet->setY(normal[1]);
@@ -50,54 +50,54 @@ void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorCont
{
OutputSocket *outputsocket = this->getOutputSocket(0);
InputSocket *inputsocket = this->getInputSocket(0);
if (outputsocket->isConnected()) {
if (inputsocket->isConnected()) {
SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
inputsocket->relinkConnections(operation->getInputSocket(0));
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
if (m_buffer) {
WriteBufferOperation *writeOperation = new WriteBufferOperation();
ReadBufferOperation *readOperation = new ReadBufferOperation();
readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket());
addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0));
graph->addOperation(writeOperation);
graph->addOperation(readOperation);
}
if (inputsocket->isConnected()) {
SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
inputsocket->relinkConnections(operation->getInputSocket(0));
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
if (m_buffer) {
WriteBufferOperation *writeOperation = new WriteBufferOperation();
ReadBufferOperation *readOperation = new ReadBufferOperation();
readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket());
addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0));
graph->addOperation(writeOperation);
graph->addOperation(readOperation);
}
else {
/* If input is not connected, add a constant value operation instead */
switch (outputsocket->getDataType()) {
case COM_DT_VALUE:
{
SetValueOperation *operation = new SetValueOperation();
bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)inputsocket->getbNodeSocket()->default_value;
operation->setValue(dval->value);
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
case COM_DT_COLOR:
{
SetColorOperation *operation = new SetColorOperation();
bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)inputsocket->getbNodeSocket()->default_value;
operation->setChannels(dval->value);
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
case COM_DT_VECTOR:
{
SetVectorOperation *operation = new SetVectorOperation();
bNodeSocketValueVector *dval = (bNodeSocketValueVector *)inputsocket->getbNodeSocket()->default_value;
operation->setVector(dval->value);
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
}
else if (outputsocket->isConnected()) {
/* If input is not connected, add a constant value operation instead */
switch (outputsocket->getDataType()) {
case COM_DT_VALUE:
{
SetValueOperation *operation = new SetValueOperation();
operation->setValue(inputsocket->getEditorValueFloat());
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
case COM_DT_COLOR:
{
SetColorOperation *operation = new SetColorOperation();
float col[4];
inputsocket->getEditorValueColor(col);
operation->setChannels(col);
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
case COM_DT_VECTOR:
{
SetVectorOperation *operation = new SetVectorOperation();
float vec[3];
inputsocket->getEditorValueVector(vec);
operation->setVector(vec);
outputsocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
break;
}
}
}
@@ -32,9 +32,8 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode)
void ValueNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetValueOperation *operation = new SetValueOperation();
bNodeSocket *socket = this->getEditorOutputSocket(0);
bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)socket->default_value;
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setValue(dval->value);
OutputSocket *output = this->getOutputSocket(0);
output->relinkConnections(operation->getOutputSocket());
operation->setValue(output->getEditorValueFloat());
graph->addOperation(operation);
}
@@ -36,42 +36,47 @@ extern "C" {
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
#include "BKE_node.h"
}
PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
this->m_preview = NULL;
this->m_outputBuffer = NULL;
this->m_input = NULL;
this->m_divider = 1.0f;
this->m_node = NULL;
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
}
void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key)
{
/* Size (0, 0) ensures the preview rect is not allocated in advance,
* this is set later in initExecution once the resolution is determined.
*/
this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, TRUE);
}
void PreviewOperation::initExecution()
{
this->m_input = getInputSocketReader(0);
if (!this->m_node->preview) {
this->m_node->preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview");
}
else {
if (this->getWidth() == (unsigned int)this->m_node->preview->xsize &&
this->getHeight() == (unsigned int)this->m_node->preview->ysize)
{
this->m_outputBuffer = this->m_node->preview->rect;
}
if (this->getWidth() == (unsigned int)this->m_preview->xsize &&
this->getHeight() == (unsigned int)this->m_preview->ysize)
{
this->m_outputBuffer = this->m_preview->rect;
}
if (this->m_outputBuffer == NULL) {
this->m_outputBuffer = (unsigned char *)MEM_callocN(sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation");
if (this->m_node->preview->rect) {
MEM_freeN(this->m_node->preview->rect);
if (this->m_preview->rect) {
MEM_freeN(this->m_preview->rect);
}
this->m_node->preview->xsize = getWidth();
this->m_node->preview->ysize = getHeight();
this->m_node->preview->rect = this->m_outputBuffer;
this->m_preview->xsize = getWidth();
this->m_preview->ysize = getHeight();
this->m_preview->rect = this->m_outputBuffer;
}
}
@@ -35,7 +35,7 @@ protected:
/**
* @brief holds reference to the SDNA bNode, where this nodes will render the preview image for
*/
bNode *m_node;
bNodePreview *m_preview;
SocketReader *m_input;
float m_divider;
@@ -43,6 +43,8 @@ protected:
const ColorManagedDisplaySettings *m_displaySettings;
public:
PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
bool isOutputOperation(bool rendering) const { return !G.background; }
void initExecution();
void deinitExecution();
@@ -50,7 +52,6 @@ public:
void executeRegion(rcti *rect, unsigned int tileNumber);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
void setbNode(bNode *node) { this->m_node = node; }
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
bool isPreviewOperation() { return true; }
+29 -6
View File
@@ -39,7 +39,10 @@ struct Tex;
struct bContext;
struct bNodeTree;
struct bNode;
struct bNodeType;
struct bNodeSocketType;
struct bNodeTree;
struct bNodeTreeType;
struct ScrArea;
struct Scene;
struct View2D;
@@ -51,15 +54,30 @@ typedef enum {
NODE_RIGHT = 8
} NodeBorder;
/* space_node.c */
int ED_node_tree_path_length(struct SpaceNode *snode);
void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length);
void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from);
void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode);
void ED_node_tree_pop(struct SpaceNode *snode);
int ED_node_tree_depth(struct SpaceNode *snode);
struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level);
/* drawnode.c */
void ED_node_init_butfuncs(void);
void ED_init_custom_node_type(struct bNodeType *ntype);
void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
/* node_draw.c */
void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene);
void ED_node_changed_update(struct ID *id, struct bNode *node);
void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
void ED_node_tree_update(const struct bContext *C);
void ED_node_tag_update_id(struct ID *id);
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree);
void ED_node_sort(struct bNodeTree *ntree);
/* node_relationships.c */
@@ -67,9 +85,14 @@ void ED_node_link_intersect_test(struct ScrArea *sa, int test);
void ED_node_link_insert(struct ScrArea *sa);
/* node_edit.c */
void ED_node_shader_default(struct Scene *scene, struct ID *id);
void ED_node_composit_default(struct Scene *sce);
void ED_node_texture_default(struct Tex *tex);
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
int ED_node_is_compositor(struct SpaceNode *snode);
int ED_node_is_shader(struct SpaceNode *snode);
int ED_node_is_texture(struct SpaceNode *snode);
void ED_node_shader_default(const struct bContext *C, struct ID *id);
void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
void ED_node_texture_default(const struct bContext *C, struct Tex *tex);
int ED_node_select_check(ListBase *lb);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
@@ -259,7 +259,8 @@ typedef enum {
WAVEFORM = (49 << 9),
VECTORSCOPE = (50 << 9),
PROGRESSBAR = (51 << 9),
SEARCH_MENU_UNLINK = (52 << 9)
SEARCH_MENU_UNLINK = (52 << 9),
NODESOCKET = (53 << 9)
} eButType;
#define BUTTYPE (63 << 9)
@@ -835,6 +836,8 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
@@ -144,6 +144,7 @@ enum {
TH_NODE,
TH_NODE_IN_OUT,
TH_NODE_INTERFACE,
TH_NODE_OPERATOR,
TH_NODE_CONVERTOR,
TH_NODE_GROUP,
+4 -1
View File
@@ -167,7 +167,7 @@ View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d);
void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels);
void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
void UI_view2d_grid_free(View2DGrid *grid);
@@ -200,6 +200,9 @@ struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
void UI_view2d_getscale_inverse(struct View2D *v2d, float *x, float *y);
void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y);
void UI_view2d_setcenter(struct View2D *v2d, float x, float y);
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_colortools.h"
#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
@@ -1685,6 +1686,71 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glDisable(GL_BLEND);
}
void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
{
static const float size = 5.0f;
/* 16 values of sin function */
static float si[16] = {
0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
-0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
-0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
};
/* 16 values of cos function */
static float co[16] = {
1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
-0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
-0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
};
unsigned char *col = but->col;
int a;
GLint scissor[4];
rcti scissor_new;
float x, y;
x = 0.5f * (recti->xmin + recti->xmax);
y = 0.5f * (recti->ymin + recti->ymax);
/* need scissor test, can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
scissor_new.xmin = ar->winrct.xmin + recti->xmin;
scissor_new.ymin = ar->winrct.ymin + recti->ymin;
scissor_new.xmax = ar->winrct.xmin + recti->xmax;
scissor_new.ymax = ar->winrct.ymin + recti->ymax;
BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
glScissor(scissor_new.xmin,
scissor_new.ymin,
BLI_rcti_size_x(&scissor_new),
BLI_rcti_size_y(&scissor_new));
glColor4ubv(col);
glEnable(GL_BLEND);
glBegin(GL_POLYGON);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
glDisable(GL_BLEND);
glColor4ub(0, 0, 0, 150);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_LINE_LOOP);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
glLineWidth(1.0f);
/* restore scissortest */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
/* ****************************************************** */
@@ -5434,6 +5434,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case LISTROW:
case BUT_IMAGE:
case PROGRESSBAR:
case NODESOCKET:
retval = ui_do_but_EXIT(C, but, data, event);
break;
case HISTOGRAM:
@@ -510,6 +510,7 @@ void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -57,6 +58,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
@@ -3064,3 +3066,65 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0);
}
/********************************* Component Menu *************************************/
typedef struct ComponentMenuArgs {
PointerRNA ptr;
char propname[64]; /* XXX arbitrary */
} ComponentMenuArgs;
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
{
ComponentMenuArgs *args = (ComponentMenuArgs*)args_v;
uiBlock *block;
uiLayout *layout;
block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, UI_GetStyle()), 0);
uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
uiBoundsBlock(block, 6);
uiBlockSetDirection(block, UI_DOWN);
uiEndBlock(C, block);
return block;
}
void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
{
ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
uiBlock *block;
args->ptr = *ptr;
BLI_strncpy(args->propname, propname, sizeof(args->propname));
block = uiLayoutGetBlock(layout);
uiBlockBeginAlign(block);
uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
uiBlockEndAlign(block);
}
/************************* Node Socket Icon **************************/
void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
{
uiBlock *block;
uiBut *but;
block = uiLayoutGetBlock(layout);
uiBlockBeginAlign(block);
/* XXX using explicit socket colors is not quite ideal.
* Eventually it should be possible to use theme colors for this purpose,
* but this requires a better design for extendable color palettes in user prefs.
*/
but = uiDefBut(block, NODESOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
rgba_float_to_uchar(but->col, color);
uiBlockEndAlign(block);
}
@@ -3367,6 +3367,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
break;
case NODESOCKET:
ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
break;
default:
wt = widget_type(UI_WTYPE_REGULAR);
}
+11 -1
View File
@@ -389,6 +389,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxv; break;
case TH_NODE_GROUP:
cp = ts->syntaxc; break;
case TH_NODE_INTERFACE:
cp= ts->console_output; break;
case TH_NODE_FRAME:
cp = ts->movie; break;
case TH_NODE_MATTE:
@@ -951,7 +953,7 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
/* space node, re-uses syntax color storage */
/* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
@@ -960,6 +962,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
rgba_char_args_set(btheme->tnode.console_output, 190, 190, 80, 255); /* group input/output */
btheme->tnode.noodle_curving = 5;
/* space logic */
@@ -2149,6 +2152,13 @@ void init_userdef_do_versions(void)
}
}
if (U.versionfile < 266 || (U.versionfile == 266 && U.subversionfile < 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
}
}
/* NOTE!! from now on use U.versionfile and U.subversionfile */
+28 -3
View File
@@ -1368,7 +1368,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d)
}
/* Draw a multi-level grid in given 2d-region */
void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totlevels)
void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
int offset = -10;
float lstep = step;
@@ -1378,7 +1378,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
int i;
float start;
UI_ThemeColorShade(TH_BACK, offset);
UI_ThemeColorShade(colorid, offset);
i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
start = i * lstep;
@@ -1402,7 +1402,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
}
/* X and Y axis */
UI_ThemeColorShade(TH_BACK, offset - 8);
UI_ThemeColorShade(colorid, offset - 8);
glVertex2f(0.0f, v2d->cur.ymin);
glVertex2f(0.0f, v2d->cur.ymax);
glVertex2f(v2d->cur.xmin, 0.0f);
@@ -2075,6 +2075,31 @@ void UI_view2d_getscale_inverse(View2D *v2d, float *x, float *y)
if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
}
/* Simple functions for consistent center offset access.
* Used by node editor to shift view center for each individual node tree.
*/
void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y)
{
/* get center */
if (x) *x = 0.5f*(v2d->cur.xmin + v2d->cur.xmax);
if (y) *y = 0.5f*(v2d->cur.ymin + v2d->cur.ymax);
}
void UI_view2d_setcenter(struct View2D *v2d, float x, float y)
{
/* get delta from current center */
float dx = x - 0.5f*(v2d->cur.xmin + v2d->cur.xmax);
float dy = y - 0.5f*(v2d->cur.ymin + v2d->cur.ymax);
/* add to cur */
v2d->cur.xmin += dx;
v2d->cur.xmax += dx;
v2d->cur.ymin += dy;
v2d->cur.ymax += dy;
/* make sure that 'cur' rect is in a valid state as a result of these changes */
UI_view2d_curRect_validate(v2d);
}
/* Check if mouse is within scrollers
* - Returns appropriate code for match
* 'h' = in horizontal scroller
+1 -1
View File
@@ -852,7 +852,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(scene, &la->id);
ED_node_shader_default(C, &la->id);
la->use_nodes = TRUE;
}
@@ -378,8 +378,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->lay = 1 << mat->pr_type;
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
}
@@ -442,8 +442,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_LA) {
@@ -479,8 +479,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey);
ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey);
BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_WO) {
@@ -497,8 +497,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey);
ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey);
BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
@@ -379,7 +379,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_add(bmain, "Material");
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(scene, &ma->id);
ED_node_shader_default(C, &ma->id);
ma->use_nodes = TRUE;
}
}
@@ -481,7 +481,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
wo = add_world(bmain, "World");
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(scene, &wo->id);
ED_node_shader_default(C, &wo->id);
wo->use_nodes = TRUE;
}
}
@@ -377,7 +377,7 @@ static void texture_changed(Main *bmain, Tex *tex)
if (scene->use_nodes && scene->nodetree) {
for (node = scene->nodetree->nodes.first; node; node = node->next) {
if (node->id == &tex->id)
ED_node_changed_update(&scene->id, node);
ED_node_tag_update_id(&scene->id);
}
}
+3 -1
View File
@@ -47,6 +47,7 @@
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
@@ -54,6 +55,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -252,7 +254,7 @@ int ED_operator_node_active(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
if (snode && snode->edittree)
if (snode && ntreeIsValid(snode->edittree))
return 1;
return 0;
@@ -407,7 +407,7 @@ void paint_brush_init_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
}
}
@@ -416,7 +416,7 @@ void paint_brush_exit_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
}
+2 -2
View File
@@ -4073,7 +4073,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
/* init mtex nodes */
if (mtex->tex && mtex->tex->nodetree)
ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
/* TODO: Shouldn't really have to do this at the start of every
* stroke, but sculpt would need some sort of notification when
@@ -4249,7 +4249,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
@@ -113,7 +113,7 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
{
bNode *node;
if (ntree) {
if (ntreeIsValid(ntree)) {
for (node = ntree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
PointerRNA ptr;
File diff suppressed because it is too large Load Diff
+98 -103
View File
@@ -62,62 +62,60 @@
#include "node_intern.h" /* own include */
/* can be called from menus too, but they should do own undopush and redraws */
bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene,
bNodeTemplate *ntemp, float locx, float locy)
/* XXX Does some additional initialization on top of nodeAddNode
* Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead.
* Can be called from menus too, but they should do own undopush and redraws.
*/
bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy)
{
bNode *node = NULL, *gnode;
SpaceNode *snode = CTX_wm_space_node(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bNode *node = NULL;
node_deselect_all(snode);
node = nodeAddNode(snode->edittree, ntemp);
if (idname)
node = nodeAddNode(C, snode->edittree, idname);
else
node = nodeAddStaticNode(C, snode->edittree, type);
BLI_assert(node && node->typeinfo);
/* generics */
if (node) {
node_select(node);
/* node location is mapped */
locx /= UI_DPI_FAC;
locy /= UI_DPI_FAC;
node->locx = locx;
node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node
nodeSetSelected(node, TRUE);
/* node location is mapped */
locx /= UI_DPI_FAC;
locy /= UI_DPI_FAC;
node->locx = locx;
node->locy = locy + 60.0f;
ntreeUpdateTree(snode->edittree);
ED_node_set_active(bmain, snode->edittree, node);
if (snode->nodetree->type == NTREE_COMPOSIT) {
if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
node->id = &scene->id;
}
else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
node->id = (ID *)scene->clip;
}
gnode = node_tree_get_editgroup(snode->nodetree);
// arbitrary y offset of 60 so its visible
if (gnode) {
node_from_view(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
}
else {
node->locx = locx;
node->locy = locy + 60.0f;
}
ntreeUpdateTree(snode->edittree);
ED_node_set_active(bmain, snode->edittree, node);
if (snode->nodetree->type == NTREE_COMPOSIT) {
if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
node->id = &scene->id;
}
else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
node->id = (ID *)scene->clip;
}
ntreeCompositForceHidden(snode->edittree, scene);
}
if (node->id)
id_us_plus(node->id);
if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
node->flag &= ~NODE_PREVIEW;
snode_update(snode, node);
ntreeCompositForceHidden(snode->edittree, scene);
}
if (node->id)
id_us_plus(node->id);
snode_update(snode, node);
if (snode->nodetree->type == NTREE_TEXTURE) {
ntreeTexCheckCyclics(snode->edittree);
}
return node;
}
@@ -183,9 +181,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
/* create the reroute node for this cursock */
if (!reroute_node) {
bNodeTemplate ntemp;
ntemp.type = NODE_REROUTE;
reroute_node = nodeAddNode(ntree, &ntemp);
reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
/* add a single link to/from the reroute node to replace multiple links */
if (in_out == SOCK_OUT) {
@@ -213,18 +209,11 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
}
if (num_links > 0) {
bNode *gnode = node_tree_get_editgroup(snode->nodetree);
/* average cut point from shared links */
mul_v2_fl(insert_point, 1.0f / num_links);
if (gnode) {
node_from_view(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy);
}
else {
reroute_node->locx = insert_point[0];
reroute_node->locy = insert_point[1];
}
reroute_node->locx = insert_point[0];
reroute_node->locy = insert_point[1];
}
return socklink;
@@ -266,6 +255,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
output_links.first = output_links.last = NULL;
input_links.first = input_links.last = NULL;
for (link = ntree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
@@ -330,12 +321,10 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
static int node_add_file_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Image *ima = NULL;
bNodeTemplate ntemp;
int type= 0;
/* check input variables */
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -367,36 +356,35 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
ntemp.type = SH_NODE_TEX_IMAGE;
type = SH_NODE_TEX_IMAGE;
break;
case NTREE_TEXTURE:
ntemp.type = TEX_NODE_IMAGE;
type = TEX_NODE_IMAGE;
break;
case NTREE_COMPOSIT:
ntemp.type = CMP_NODE_IMAGE;
type = CMP_NODE_IMAGE;
break;
default:
return OPERATOR_CANCELLED;
}
ED_preview_kill_jobs(C);
node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]);
node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
if (!node) {
BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
return OPERATOR_CANCELLED;
}
node->id = (ID *)ima;
id_us_plus(node->id);
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
snode_notify(C, snode);
snode_dag_update(C, snode);
return OPERATOR_FINISHED;
}
@@ -404,11 +392,11 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name"))
return node_add_file_exec(C, op);
else
@@ -435,35 +423,35 @@ void NODE_OT_add_file(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
/********************** New node tree operator *********************/
static int new_node_tree_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode;
SpaceNode *snode= CTX_wm_space_node(C);
Main *bmain = CTX_data_main(C);
bNodeTree *ntree;
Main *bmain;
PointerRNA ptr, idptr;
PropertyRNA *prop;
int treetype;
const char *idname;
char treename[MAX_ID_NAME - 2] = "NodeTree";
/* retrieve state */
snode = CTX_wm_space_node(C);
bmain = CTX_data_main(C);
if (RNA_struct_property_is_set(op->ptr, "type"))
treetype = RNA_enum_get(op->ptr, "type");
else
treetype = snode->treetype;
if (RNA_struct_property_is_set(op->ptr, "type")) {
prop = RNA_struct_find_property(op->ptr, "type");
RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
}
else if (snode)
idname = snode->tree_idname;
if (RNA_struct_property_is_set(op->ptr, "name"))
RNA_string_get(op->ptr, "name", treename);
ntree = ntreeAddTree(bmain, treename, treetype, 0);
if (!ntree)
if (!ntreeTypeFind(idname)) {
BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
return OPERATOR_CANCELLED;
}
ntree = ntreeAddTree(bmain, treename, idname);
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -477,29 +465,36 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
Scene *scene = CTX_data_scene(C);
snode->nodetree = ntree;
ED_node_tree_update(snode, scene);
ED_node_tree_update(C);
}
return OPERATOR_FINISHED;
}
static EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
return rna_node_tree_type_itemf(NULL, NULL, free);
}
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "New Node Tree";
ot->idname = "NODE_OT_new_node_tree";
ot->description = "Create a new node tree";
/* api callbacks */
ot->exec = new_node_tree_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
}
@@ -62,7 +62,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
return (snode && snode->nodetree);
return (snode && ntreeIsValid(snode->nodetree));
}
/* poll callback for active node */
@@ -70,7 +70,7 @@ static int active_node_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
return (snode && snode->edittree && nodeGetActive(snode->edittree));
return (snode && ntreeIsValid(snode->edittree) && nodeGetActive(snode->edittree));
}
/* active node */
@@ -160,6 +160,86 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
}
}
static int node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode= CTX_wm_space_node(C);
return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first));
}
static int node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out)
{
bNodeSocket *sock;
for (sock = ntree->inputs.first; sock; sock = sock->next) {
if (sock->flag & SELECT) {
*r_sock = sock;
*r_in_out = SOCK_IN;
return TRUE;
}
}
for (sock = ntree->outputs.first; sock; sock = sock->next) {
if (sock->flag & SELECT) {
*r_sock = sock;
*r_in_out = SOCK_OUT;
return TRUE;
}
}
*r_sock = NULL;
*r_in_out = 0;
return FALSE;
}
static void node_tree_interface_panel(const bContext *C, Panel *pa)
{
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree= (snode) ? snode->edittree : NULL;
bNodeSocket *sock;
int in_out;
uiLayout *layout= pa->layout, *row, *split, *col;
PointerRNA ptr, sockptr, opptr;
if(!ntree)
return;
RNA_id_pointer_create((ID *)ntree, &ptr);
node_tree_find_active_socket(ntree, &sock, &in_out);
RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
row = uiLayoutRow(layout, FALSE);
split = uiLayoutRow(row, TRUE);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, "Inputs:", ICON_NONE);
uiTemplateList(col, (bContext*)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, "Outputs:", ICON_NONE);
uiTemplateList(col, (bContext*)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
col = uiLayoutColumn(row, TRUE);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 1);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 2);
if (sock) {
row = uiLayoutRow(layout, TRUE);
uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
uiItemS(layout);
if (sock->typeinfo->interface_draw)
sock->typeinfo->interface_draw((bContext*)C, layout, &sockptr);
}
}
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
@@ -180,7 +260,14 @@ void node_buttons_register(ARegionType *art)
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
strcpy(pt->idname, "NODE_PT_node_tree_interface");
strcpy(pt->label, "Interface");
pt->draw= node_tree_interface_panel;
pt->poll= node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
strcpy(pt->idname, "NODE_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
+361 -221
View File
@@ -29,10 +29,14 @@
* \brief higher level node drawing for the node editor.
*/
#include "DNA_lamp_types.h"
#include "DNA_node_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -44,6 +48,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BLF_api.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -52,6 +58,7 @@
#include "ED_node.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_resources.h"
@@ -65,25 +72,49 @@
/* XXX interface.h */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
/* XXX update functions for node editor are a mess, needs a clear concept */
void ED_node_tree_update(SpaceNode *snode, Scene *scene)
void ED_node_tree_update(const bContext *C)
{
snode_set_context(snode, scene);
SpaceNode *snode = CTX_wm_space_node(C);
snode_set_context(C);
if (snode->nodetree && snode->nodetree->id.us == 0)
snode->nodetree->id.us = 1;
}
void ED_node_changed_update(ID *id, bNode *node)
/* id is supposed to contain a node tree */
static bNodeTree *node_tree_from_ID(ID *id)
{
bNodeTree *nodetree, *edittree;
int treetype;
if (id) {
short idtype = GS(id->name);
switch (idtype) {
case ID_NT:
return (bNodeTree*)id;
case ID_MA:
return ((Material*)id)->nodetree;
case ID_LA:
return ((Lamp*)id)->nodetree;
case ID_WO:
return ((World*)id)->nodetree;
case ID_SCE:
return ((Scene*)id)->nodetree;
case ID_TE:
return ((Tex*)id)->nodetree;
}
}
return NULL;
}
node_tree_from_ID(id, &nodetree, &edittree, &treetype);
if (treetype == NTREE_SHADER) {
void ED_node_tag_update_id(ID *id)
{
bNodeTree *ntree = node_tree_from_ID(id);
if (id == NULL)
return;
if (ntree->type == NTREE_SHADER) {
DAG_id_tag_update(id, 0);
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, id);
else if (GS(id->name) == ID_LA)
@@ -91,18 +122,10 @@ void ED_node_changed_update(ID *id, bNode *node)
else if (GS(id->name) == ID_WO)
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, id);
}
else if (treetype == NTREE_COMPOSIT) {
if (node)
nodeUpdate(edittree, node);
/* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
node = node_tree_get_editgroup(nodetree);
if (node)
nodeUpdateID(nodetree, node->id);
else if (ntree->type == NTREE_COMPOSIT) {
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
else if (treetype == NTREE_TEXTURE) {
else if (ntree->type == NTREE_TEXTURE) {
DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
@@ -123,25 +146,17 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
typedef struct NodeUpdateCalldata {
bNodeTree *ntree;
bNode *node;
} NodeUpdateCalldata;
static void node_generic_update_cb(void *calldata, ID *owner_id, bNodeTree *ntree)
void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
{
NodeUpdateCalldata *cd = (NodeUpdateCalldata *)calldata;
/* check if nodetree uses the group stored in calldata */
if (has_nodetree(ntree, cd->ntree))
ED_node_changed_update(owner_id, cd->node);
}
void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node)
{
bNodeTreeType *tti = ntreeGetType(ntree->type);
NodeUpdateCalldata cd;
cd.ntree = ntree;
cd.node = node;
if (!ntreeIsValid(ntree))
return;
/* look through all datablocks, to support groups */
tti->foreach_nodetree(bmain, &cd, node_generic_update_cb);
FOREACH_NODETREE(bmain, tntree, id) {
/* check if nodetree uses the group */
if (has_nodetree(tntree, ntree))
ED_node_tag_update_id(id);
} FOREACH_NODETREE_END
if (ntree->type == NTREE_TEXTURE)
ntreeTexCheckCyclics(ntree);
@@ -251,12 +266,12 @@ void ED_node_sort(bNodeTree *ntree)
}
static void do_node_internal_buttons(bContext *C, void *node_v, int event)
static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
{
if (event == B_NODE_EXEC) {
SpaceNode *snode = CTX_wm_space_node(C);
if (snode && snode->id)
ED_node_changed_update(snode->id, node_v);
ED_node_tag_update_id(snode->id);
}
}
@@ -296,13 +311,15 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
uiLayout *layout;
PointerRNA ptr;
uiLayout *layout, *row;
PointerRNA nodeptr, sockptr;
bNodeSocket *nsock;
float locx, locy;
float dy;
int buty;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* get "global" coords */
node_to_view(node, 0.0f, 0.0f, &locx, &locy);
dy = locy;
@@ -313,14 +330,36 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* little bit space in top */
if (node->outputs.first)
dy -= NODE_DYS / 2;
/* output sockets */
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
if (!nodeSocketIsHidden(nsock)) {
nsock->locx = locx + NODE_WIDTH(node);
nsock->locy = dy - NODE_DYS;
dy -= NODE_DY;
}
if (nodeSocketIsHidden(nsock))
continue;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx+NODE_DYS, dy, NODE_WIDTH(node)-NODE_DY, NODE_DY, UI_GetStyle());
/* context pointers for current node and socket */
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
/* align output buttons to the right */
row = uiLayoutRow(layout, 1);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
/* ensure minimum socket height in case layout is empty */
buty = MIN2(buty, dy - NODE_DY);
nsock->locx = locx + NODE_WIDTH(node);
/* place the socket circle in the middle of the layout */
nsock->locy = 0.5f * (dy + buty);
dy = buty;
}
node->prvr.xmin = locx + NODE_DYS;
@@ -328,43 +367,32 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* preview rect? */
if (node->flag & NODE_PREVIEW) {
if (node->preview && node->preview->rect) {
float aspect = 1.0f;
if (node->preview && node->preview->xsize && node->preview->ysize)
aspect = (float)node->preview->ysize / (float)node->preview->xsize;
dy -= NODE_DYS / 2;
node->prvr.ymax = dy;
if (aspect <= 1.0f)
node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
else {
/* width correction of image */
/* XXX huh? (ton) */
float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
node->prvr.xmin += 0.5f * dx;
node->prvr.xmax -= 0.5f * dx;
}
dy = node->prvr.ymin - NODE_DYS / 2;
/* make sure that maximums are bigger or equal to minimums */
if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
float aspect = 1.0f;
if (node->preview_xsize && node->preview_ysize)
aspect = (float)node->preview_ysize / (float)node->preview_xsize;
dy -= NODE_DYS / 2;
node->prvr.ymax = dy;
if (aspect <= 1.0f)
node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
else {
float oldh = BLI_rctf_size_y(&node->prvr);
if (oldh == 0.0f)
oldh = 0.6f * NODE_WIDTH(node) - NODE_DY;
dy -= NODE_DYS / 2;
node->prvr.ymax = dy;
node->prvr.ymin = dy - oldh;
dy = node->prvr.ymin - NODE_DYS / 2;
/* width correction of image */
/* XXX huh? (ton) */
float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
node->prvr.xmin += 0.5f * dx;
node->prvr.xmax -= 0.5f * dx;
}
dy = node->prvr.ymin - NODE_DYS / 2;
/* make sure that maximums are bigger or equal to minimums */
if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
/* buttons rect? */
@@ -378,14 +406,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.ymin = 0;
node->butr.ymax = 0;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle());
uiLayoutSetContextPointer(layout, "node", &ptr);
uiLayoutSetContextPointer(layout, "node", &nodeptr);
node->typeinfo->uifunc(layout, (bContext *)C, &ptr);
node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr);
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -395,11 +421,29 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* input sockets */
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
if (!nodeSocketIsHidden(nsock)) {
nsock->locx = locx;
nsock->locy = dy - NODE_DYS;
dy -= NODE_DY;
}
if (nodeSocketIsHidden(nsock))
continue;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx+NODE_DYS, dy, NODE_WIDTH(node)-NODE_DY, NODE_DY, UI_GetStyle());
/* context pointers for current node and socket */
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
/* ensure minimum socket height in case layout is empty */
buty = MIN2(buty, dy - NODE_DY);
nsock->locx = locx;
/* place the socket circle in the middle of the layout */
nsock->locy = 0.5f * (dy + buty);
dy = buty;
}
/* little bit space in end */
@@ -510,6 +554,7 @@ int node_get_colorid(bNode *node)
case NODE_CLASS_OP_VECTOR:
case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR;
case NODE_CLASS_GROUP: return TH_NODE_GROUP;
case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
case NODE_CLASS_MATTE: return TH_NODE_MATTE;
case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
default: return TH_NODE;
@@ -534,7 +579,7 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
}
/* this might have some more generic use */
static void node_circle_draw(float x, float y, float size, char *col, int highlight)
static void node_circle_draw(float x, float y, float size, float *col, int highlight)
{
/* 16 values of sin function */
static float si[16] = {
@@ -552,12 +597,14 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
};
int a;
glColor3ub(col[0], col[1], col[2]);
glColor4fv(col);
glEnable(GL_BLEND);
glBegin(GL_POLYGON);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
glDisable(GL_BLEND);
if (highlight) {
UI_ThemeColor(TH_TEXT_HI);
@@ -577,66 +624,93 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
glLineWidth(1.0f);
}
void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
{
bNodeSocketType *stype = ntreeGetSocketType(sock->type);
node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
PointerRNA ptr, node_ptr;
float color[4];
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
node_circle_draw(sock->locx, sock->locy, size, color, highlight);
}
/* ************** Socket callbacks *********** */
/* not a callback */
static void node_draw_preview(bNodePreview *preview, rctf *prv)
static void node_draw_preview_background(float tile, rctf *rect)
{
float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize);
float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize);
float tile = BLI_rctf_size_x(prv) / 10.0f;
float x, y;
/* draw checkerboard backdrop to show alpha */
glColor3ub(120, 120, 120);
glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glColor3ub(160, 160, 160);
for (y = prv->ymin; y < prv->ymax; y += tile * 2) {
for (x = prv->xmin; x < prv->xmax; x += tile * 2) {
for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
if (x + tile > prv->xmax)
tilex = prv->xmax - x;
if (y + tile > prv->ymax)
tiley = prv->ymax - y;
if (x + tile > rect->xmax)
tilex = rect->xmax - x;
if (y + tile > rect->ymax)
tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
for (y = prv->ymin + tile; y < prv->ymax; y += tile * 2) {
for (x = prv->xmin + tile; x < prv->xmax; x += tile * 2) {
for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
if (x + tile > prv->xmax)
tilex = prv->xmax - x;
if (y + tile > prv->ymax)
tiley = prv->ymax - y;
if (x + tile > rect->xmax)
tilex = rect->xmax - x;
if (y + tile > rect->ymax)
tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
}
/* not a callback */
static void node_draw_preview(bNodePreview *preview, rctf *prv)
{
float xrect = BLI_rctf_size_x(prv);
float yrect = BLI_rctf_size_y(prv);
float xscale = xrect / ((float)preview->xsize);
float yscale = yrect / ((float)preview->ysize);
float scale;
rctf draw_rect;
/* uniform scale and offset */
draw_rect = *prv;
if (xscale < yscale) {
float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
draw_rect.ymin += offset;
draw_rect.ymax -= offset;
scale = xscale;
}
else {
float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
draw_rect.xmin += offset;
draw_rect.xmax -= offset;
scale = yscale;
}
node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
glPixelZoom(xscale, yscale);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
glColor4f(1.0, 1.0, 1.0, 1.0);
glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
glPixelZoom(scale, scale);
glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
glPixelZoom(1.0f, 1.0f);
UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
}
/* common handle function for operator buttons that need to select the node first */
@@ -669,8 +743,9 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
}
}
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
@@ -680,9 +755,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
/* hurmf... another candidate for callback, have to see how this works first */
if (node->id && node->block && snode->treetype == NTREE_SHADER)
nodeShaderSynchronizeID(node, 0);
/* XXX hack: copy values from linked ID data where displayed as sockets */
if (node->block)
nodeSynchronizeID(node, false);
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) {
@@ -823,11 +898,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx + (NODE_DYS), sock->locy - NODE_DYS,
NODE_WIDTH(node) - NODE_DY);
node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* socket outputs */
@@ -835,17 +906,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx - NODE_WIDTH(node) + (NODE_DYS), sock->locy - NODE_DYS,
NODE_WIDTH(node) - NODE_DY);
node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* preview */
if (node->flag & NODE_PREVIEW) {
if (node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr))
node_draw_preview(node->preview, &node->prvr);
bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL;
if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr))
node_draw_preview(preview, &node->prvr);
}
UI_ThemeClearColor(color_id);
@@ -855,7 +923,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
node->block = NULL;
}
static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
rctf *rct = &node->totr;
@@ -957,12 +1025,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
for (sock = node->outputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
uiEndBlock(C, node->block);
@@ -989,7 +1057,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
bNodeSocket *sock;
int cursor = CURSOR_STD;
if (ntree) {
if (ntreeIsValid(ntree)) {
if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) {
/* pass */
}
@@ -1009,12 +1077,12 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
WM_cursor_set(win, cursor);
}
void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->flag & NODE_HIDDEN)
node_draw_hidden(C, ar, snode, ntree, node);
node_draw_hidden(C, ar, snode, ntree, node, key);
else
node_draw_basis(C, ar, snode, ntree, node);
node_draw_basis(C, ar, snode, ntree, node, key);
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
@@ -1023,34 +1091,28 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
node->typeinfo->drawupdatefunc(C, ntree, node);
}
void node_update_nodetree(const bContext *C, bNodeTree *ntree, float offsetx, float offsety)
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
/* XXX little hack (not used anyore?) */
node->locx += offsetx;
node->locy += offsety;
node_update(C, ntree, node);
node->locx -= offsetx;
node->locy -= offsety;
}
}
static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->typeinfo->drawfunc)
node->typeinfo->drawfunc(C, ar, snode, ntree, node);
node->typeinfo->drawfunc(C, ar, snode, ntree, node, key);
}
#define USE_DRAW_TOT_UPDATE
void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNode *node;
bNodeInstanceKey key;
bNodeLink *link;
int a;
@@ -1073,122 +1135,200 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
if (!(node->flag & NODE_BACKGROUND))
continue;
key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
node_draw(C, ar, snode, ntree, node);
node_draw(C, ar, snode, ntree, node, key);
}
/* node lines */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
for (link = ntree->links.first; link; link = link->next)
node_draw_link(&ar->v2d, snode, link);
for (link = ntree->links.first; link; link = link->next) {
if (!nodeLinkIsHidden(link))
node_draw_link(&ar->v2d, snode, link);
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
/* draw foreground nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
if (node->flag & NODE_BACKGROUND)
continue;
key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
node_draw(C, ar, snode, ntree, node);
node_draw(C, ar, snode, ntree, node, key);
}
}
void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
/* draw tree path info in lower left corner */
static void draw_tree_path(SpaceNode *snode)
{
char info[256];
ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
UI_ThemeColor(TH_TEXT_HI);
BLF_draw_default(30, 30, 0.0f, info, sizeof(info));
}
static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, float centerx, float centery)
{
View2D *v2d = &ar->v2d;
/* shift view to node tree center */
UI_view2d_setcenter(v2d, centerx, centery);
UI_view2d_view_ortho(v2d);
/* aspect+font, set each time */
snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
// XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
}
static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
SpaceNode *snode = CTX_wm_space_node(C);
node_uiblocks_init(C, ntree);
#ifdef WITH_COMPOSITOR
if (ntree->type == NTREE_COMPOSIT) {
COM_startReadHighlights();
}
#endif
node_update_nodetree(C, ntree);
node_draw_nodetree(C, ar, snode, ntree, parent_key);
}
/* shade the parent node group and add a uiBlock to clip mouse events */
static void draw_group_overlay(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
rctf rect = v2d->cur;
uiBlock *block;
/* shade node groups to separate them visually */
UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
uiSetRoundBox(0);
uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
glDisable(GL_BLEND);
/* set the block bounds to clip mouse events from underlying nodes */
block = uiBeginBlock(C, ar, "node tree bounds block", UI_EMBOSS);
uiExplicitBoundsBlock(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
uiBlockSetFlag(block, UI_BLOCK_CLIP_EVENTS);
uiEndBlock(C, block);
}
void drawnodespace(const bContext *C, ARegion *ar)
{
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
bNodeLinkDrag *nldrag;
LinkData *linkdata;
View2D *v2d = &ar->v2d;
UI_ThemeClearColor(TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
//uiFreeBlocksWin(&sa->uiblocks, sa->win);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MAP1_VERTEX_3);
/* aspect+font, set each time */
snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
// XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
/* grid */
UI_view2d_multi_grid_draw(v2d, U.widget_unit, 5, 2);
/* backdrop */
draw_nodespace_back_pix(C, ar, snode);
/* nodes */
snode_set_context(snode, CTX_data_scene(C));
snode_set_context(C);
if (snode->nodetree) {
bNode *node;
/* void **highlights = 0; */ /* UNUSED */
/* draw parent node trees */
if (snode->treepath.last) {
static const int max_depth = 2;
bNodeTreePath *path;
int depth, curdepth;
float center[2];
bNodeTree *ntree;
bNodeLinkDrag *nldrag;
LinkData *linkdata;
node_uiblocks_init(C, snode->nodetree);
/* current View2D center, will be set temporarily for parent node trees */
UI_view2d_getcenter(v2d, &center[0], &center[1]);
/* uiBlocks must be initialized in drawing order for correct event clipping.
* Node group internal blocks added after the main group block.
*/
for (node = snode->nodetree->nodes.first; node; node = node->next) {
if (node->flag & NODE_GROUP_EDIT)
node_uiblocks_init(C, (bNodeTree *)node->id);
/* store new view center in current edittree */
if (snode->edittree)
copy_v2_v2(snode->edittree->view_center, center);
depth = 0;
path = snode->treepath.last;
while (path->prev && depth < max_depth) {
path = path->prev;
++depth;
}
/* parent node trees in the background */
for (curdepth = depth; curdepth >= 0; path = path->next, --curdepth) {
ntree = path->nodetree;
if (ntreeIsValid(ntree)) {
snode_setup_v2d(snode, ar, ntree->view_center[0], ntree->view_center[1]);
if (curdepth == 0) {
/* grid, uses theme color based on node path depth */
UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2);
/* backdrop */
draw_nodespace_back_pix(C, ar, snode);
}
draw_nodetree(C, ar, ntree, path->parent_key);
if (curdepth > 0)
draw_group_overlay(C, ar);
}
}
node_update_nodetree(C, snode->nodetree, 0.0f, 0.0f);
#ifdef WITH_COMPOSITOR
if (snode->nodetree->type == NTREE_COMPOSIT) {
COM_startReadHighlights();
}
#endif
node_draw_nodetree(C, ar, snode, snode->nodetree);
/* reset View2D */
UI_view2d_setcenter(v2d, center[0], center[1]);
#if 0
/* active group */
for (node = snode->nodetree->nodes.first; node; node = node->next) {
if (node->flag & NODE_GROUP_EDIT)
node_draw_group(C, ar, snode, snode->nodetree, node);
/* temporary links */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next)
node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
}
#endif
}
/* temporary links */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
node_draw_link(&ar->v2d, snode, (bNodeLink *)linkdata->data);
}
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
if (snode->flag & SNODE_SHOW_GPENCIL) {
/* draw grease-pencil ('canvas' strokes) */
if (snode->nodetree) {
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
if (snode->flag & SNODE_SHOW_GPENCIL) {
/* draw grease-pencil ('canvas' strokes) */
draw_gpencil_view2d(C, TRUE);
}
}
else {
/* default grid */
UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2);
/* backdrop */
draw_nodespace_back_pix(C, ar, snode);
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
if (snode->flag & SNODE_SHOW_GPENCIL) {
/* draw grease-pencil (screen strokes, and also paintbuffer) */
if (snode->nodetree) {
if (snode->treepath.last) {
if (snode->flag & SNODE_SHOW_GPENCIL) {
/* draw grease-pencil (screen strokes, and also paintbuffer) */
draw_gpencil_view2d(C, FALSE);
}
}
/* tree path info */
draw_tree_path(snode);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -171
View File
@@ -58,186 +58,21 @@
/* ************************ add menu *********************** */
static void do_node_add(bContext *C, bNodeTemplate *ntemp)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
bNode *node, *node_new;
/* get location to add node at mouse */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_WINDOW) {
wmWindow *win = CTX_wm_window(C);
int x = win->eventstate->x - ar->winrct.xmin;
int y = win->eventstate->y - ar->winrct.ymin;
if (y < 60) y += 60;
UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]);
}
}
/* store selection in temp test flag */
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_SELECT) node->flag |= NODE_TEST;
else node->flag &= ~NODE_TEST;
}
node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]);
/* select previous selection before autoconnect */
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST) node->flag |= NODE_SELECT;
}
/* deselect after autoconnection */
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
}
/* once this is called from an operator, this should be removed */
if (node_new) {
char undostr[BKE_UNDO_STR_MAX];
BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new));
BKE_write_undo(C, undostr);
}
snode_notify(C, snode);
snode_dag_update(C, snode);
}
static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
ntemp.type = event;
ntemp.main = bmain;
ntemp.scene = scene;
do_node_add(C, &ntemp);
}
static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
{
SpaceNode *snode = CTX_wm_space_node(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
if (event >= 0) {
ntemp.ngroup = BLI_findlink(&G.main->nodetree, event);
ntemp.type = ntemp.ngroup->nodetype;
}
else {
ntemp.type = -event;
switch (ntemp.type) {
case NODE_GROUP:
ntemp.ngroup = ntreeAddTree(bmain, "Group", snode->treetype, ntemp.type);
break;
default:
ntemp.ngroup = NULL;
}
}
if (!ntemp.ngroup)
return;
ntemp.main = bmain;
ntemp.scene = scene;
do_node_add(C, &ntemp);
}
static int node_tree_has_type(int treetype, int nodetype)
{
bNodeTreeType *ttype = ntreeGetType(treetype);
bNodeType *ntype;
for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
if (ntype->type == nodetype)
return 1;
}
return 0;
}
static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree;
int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
int event, compatibility = 0;
ntree = snode->nodetree;
if (!ntree) {
uiItemS(layout);
return;
}
if (ntree->type == NTREE_SHADER) {
if (BKE_scene_use_new_shading_nodes(scene))
compatibility = NODE_NEW_SHADING;
else
compatibility = NODE_OLD_SHADING;
}
if (nodeclass == NODE_CLASS_GROUP) {
bNodeTree *ngroup;
uiLayoutSetFunc(layout, do_node_add_group, NULL);
/* XXX hack: negative numbers used for empty group types */
if (node_tree_has_type(ntree->type, NODE_GROUP))
uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP);
uiItemS(layout);
for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
/* only use group trees */
if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) {
uiItemV(layout, ngroup->id.name + 2, 0, event);
}
}
}
else {
bNodeType *ntype;
uiLayoutSetFunc(layout, do_node_add_static, NULL);
for (ntype = ntreeGetType(ntree->type)->node_types.first; ntype; ntype = ntype->next) {
if (ntype->nclass == nodeclass && ntype->name) {
if (!compatibility || (ntype->compatibility & compatibility)) {
uiItemV(layout, IFACE_(ntype->name), 0, ntype->type);
}
}
}
}
}
static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name)
{
uiLayout *layout = calldata;
uiItemMenuF(layout, IFACE_(name), 0, node_add_menu, SET_INT_IN_POINTER(nclass));
}
static void node_menu_add(const bContext *C, Menu *menu)
{
Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
uiLayout *layout = menu->layout;
bNodeTreeType *ntreetype = ntreeGetType(snode->treetype);
bNodeTree *ntree = snode->edittree;
if (!snode->nodetree)
if (!ntree || !ntree->typeinfo || !ntree->typeinfo->draw_add_menu) {
uiLayoutSetActive(layout, FALSE);
return;
}
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Search ..."), 0, "NODE_OT_add_search");
if (ntreetype && ntreetype->foreach_nodeclass)
ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb);
ntree->typeinfo->draw_add_menu(C, layout, ntree);
}
void node_menus_register(void)
+20 -18
View File
@@ -32,6 +32,7 @@
#define __NODE_INTERN_H__
#include <stddef.h> /* for size_t */
#include "BKE_node.h"
#include "UI_interface.h"
/* internal exports only */
@@ -43,7 +44,6 @@ struct bContext;
struct wmWindow;
struct wmWindowManager;
struct wmEvent;
struct bNodeTemplate;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
@@ -66,21 +66,26 @@ typedef struct bNodeLinkDrag {
ARegion *node_has_buttons_region(ScrArea *sa);
ARegion *node_has_tools_region(ScrArea *sa);
void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transform between View2Ds in the tree path */
/* node_header.c */
void node_menus_register(void);
/* node_draw.c */
int node_get_colorid(struct bNode *node);
void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight);
void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
struct bNodeSocket *sock, float size, int highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety);
void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree);
void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, bNodeInstanceKey parent_key);
void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
/* DPI scaled coords */
@@ -100,8 +105,6 @@ void node_operatortypes(void);
void node_keymap(struct wmKeyConfig *keyconf);
/* node_select.c */
void node_select(struct bNode *node);
void node_deselect(struct bNode *node);
void node_deselect_all(struct SpaceNode *snode);
void node_socket_select(struct bNode *node, struct bNodeSocket *sock);
void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, int deselect_node);
@@ -138,13 +141,15 @@ void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struc
/* node_add.c */
bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene,
struct bNodeTemplate *ntemp, float locx, float locy);
bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy);
void NODE_OT_add_reroute(struct wmOperatorType *ot);
void NODE_OT_add_file(struct wmOperatorType *ot);
void NODE_OT_new_node_tree(struct wmOperatorType *ot);
/* node_group.c */
void NODE_OT_group_make(struct wmOperatorType *ot);
void NODE_OT_group_insert(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
@@ -154,11 +159,6 @@ void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
/* note_add.c */
void NODE_OT_add_file(struct wmOperatorType *ot);
void NODE_OT_new_node_tree(struct wmOperatorType *ot);
/* node_relationships.c */
void NODE_OT_link(struct wmOperatorType *ot);
void NODE_OT_link_make(struct wmOperatorType *ot);
@@ -175,11 +175,9 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
/* node_edit.c */
void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype);
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
void snode_set_context(struct SpaceNode *snode, Scene *scene);
void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode);
void snode_set_context(const struct bContext *C);
bNode *node_tree_get_editgroup(bNodeTree *ntree);
void snode_update(struct SpaceNode *snode, struct bNode *node);
@@ -215,6 +213,10 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
void NODE_OT_viewer_border(struct wmOperatorType *ot);
+42 -10
View File
@@ -84,13 +84,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_add_reroute);
WM_operatortype_append(NODE_OT_group_make);
WM_operatortype_append(NODE_OT_group_insert);
WM_operatortype_append(NODE_OT_group_ungroup);
WM_operatortype_append(NODE_OT_group_separate);
WM_operatortype_append(NODE_OT_group_edit);
WM_operatortype_append(NODE_OT_group_socket_add);
WM_operatortype_append(NODE_OT_group_socket_remove);
WM_operatortype_append(NODE_OT_group_socket_move_up);
WM_operatortype_append(NODE_OT_group_socket_move_down);
WM_operatortype_append(NODE_OT_link_viewer);
@@ -122,6 +119,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_shader_script_update);
WM_operatortype_append(NODE_OT_viewer_border);
WM_operatortype_append(NODE_OT_tree_socket_add);
WM_operatortype_append(NODE_OT_tree_socket_remove);
WM_operatortype_append(NODE_OT_tree_socket_move);
}
void ED_operatormacros_node(void)
@@ -198,6 +199,29 @@ static void node_select_keymap(wmKeyMap *keymap, int extend)
}
}
/* register group operators for a specific group node type */
static void node_group_operators(wmKeyMap *keymap, const char *node_type)
{
wmKeyMapItem *kmi;
kmi = WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "node_type", node_type);
kmi = WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
RNA_string_set(kmi->ptr, "node_type", node_type);
kmi = WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "node_type", node_type);
kmi= WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "node_type", node_type);
RNA_boolean_set(kmi->ptr, "exit", FALSE);
kmi= WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "node_type", node_type);
RNA_boolean_set(kmi->ptr, "exit", TRUE);
}
void node_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
@@ -230,9 +254,18 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
/* each of these falls through if not handled... */
WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "detach", FALSE);
RNA_boolean_set(kmi->ptr, "expose", FALSE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", TRUE);
RNA_boolean_set(kmi->ptr, "expose", FALSE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "detach", FALSE);
RNA_boolean_set(kmi->ptr, "expose", TRUE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", TRUE);
RNA_boolean_set(kmi->ptr, "expose", TRUE);
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -288,11 +321,10 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
node_group_operators(keymap, "ShaderNodeGroup");
node_group_operators(keymap, "CompositorNodeGroup");
node_group_operators(keymap, "TextureNodeGroup");
WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
@@ -54,6 +54,7 @@
#include "UI_view2d.h"
#include "node_intern.h" /* own include */
#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -323,13 +324,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (sock) {
/* add a new viewer if none exists yet */
if (!node) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
ntemp.type = CMP_NODE_VIEWER;
/* XXX location is a quick hack, just place it next to the linked socket */
node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
if (!node)
return OPERATOR_CANCELLED;
@@ -364,7 +360,7 @@ static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
node = editnode_get_active(snode->edittree);
node = nodeGetActive(snode->edittree);
if (!node)
return OPERATOR_CANCELLED;
@@ -434,18 +430,6 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
}
}
static int outside_group_rect(SpaceNode *snode)
{
bNode *gnode = node_tree_get_editgroup(snode->nodetree);
if (gnode) {
return (snode->cursor[0] < gnode->totr.xmin ||
snode->cursor[0] >= gnode->totr.xmax ||
snode->cursor[1] < gnode->totr.ymin ||
snode->cursor[1] >= gnode->totr.ymax);
}
return 0;
}
/* loop that adds a nodelink, called by function below */
/* in_out = starting socket */
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -459,55 +443,41 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
bNodeLink *link;
LinkData *linkdata;
int in_out;
int expose;
in_out = nldrag->in_out;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
expose = RNA_boolean_get(op->ptr, "expose");
switch (event->type) {
case MOUSEMOVE:
if (in_out == SOCK_OUT) {
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
/* skip if this is already the target socket */
if (link->tosock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->fromnode == tnode)
continue;
/* attach links to the socket */
link->tonode = tnode;
link->tosock = tsock;
/* add it to the node tree temporarily */
if (BLI_findindex(&ntree->links, link) < 0)
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_LINKS;
}
ntreeUpdateTree(ntree);
}
else {
int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
if (link->tonode || link->tosock) {
BLI_remlink(&ntree->links, link);
link->prev = link->next = NULL;
link->tonode = NULL;
link->tosock = NULL;
ntree->update |= NTREE_UPDATE_LINKS;
do_update = TRUE;
}
}
if (do_update) {
ntreeUpdateTree(ntree);
link->tonode = NULL;
link->tosock = NULL;
}
}
}
@@ -515,108 +485,126 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
/* skip if this is already the target socket */
if (link->fromsock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->tonode == tnode)
continue;
/* attach links to the socket */
link->fromnode = tnode;
link->fromsock = tsock;
/* add it to the node tree temporarily */
if (BLI_findindex(&ntree->links, link) < 0)
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_LINKS;
}
ntreeUpdateTree(ntree);
}
else {
int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
if (link->fromnode || link->fromsock) {
BLI_remlink(&ntree->links, link);
link->prev = link->next = NULL;
link->fromnode = NULL;
link->fromsock = NULL;
ntree->update |= NTREE_UPDATE_LINKS;
do_update = TRUE;
}
}
if (do_update) {
ntreeUpdateTree(ntree);
link->fromnode = NULL;
link->fromsock = NULL;
}
}
}
ED_region_tag_redraw(ar);
break;
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
{
/* XXX expose + detach could have some ugly corner cases and is not great.
* The first link will define the exposed socket type, which is arbitrary.
* Some of the resulting links may turn out to be invalid.
*/
bNode *ionode = NULL;
bNodeSocket *iosock = NULL, *gsock;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
if (link->tosock && link->fromsock) {
/* send changed events for original tonode and new */
if (link->tonode)
snode_update(snode, link->tonode);
/* add link to the node tree */
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_LINKS;
/* tag tonode for update */
link->tonode->update |= NODE_UPDATE;
/* we might need to remove a link */
if (in_out == SOCK_OUT)
node_remove_extra_links(snode, link->tosock, link);
/* when linking to group outputs, update the socket type */
/* XXX this should all be part of a generic update system */
if (!link->tonode) {
if (link->tosock->type != link->fromsock->type)
nodeSocketSetType(link->tosock, link->fromsock->type);
}
}
else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
/* automatically add new group socket */
if (link->tonode && link->tosock) {
link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
link->fromnode = NULL;
if (BLI_findindex(&ntree->links, link) < 0)
BLI_addtail(&ntree->links, link);
else if (expose) {
if (link->tosock) {
if (!ionode) {
ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_INPUT);
gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->tonode, link->tosock);
node_group_input_verify(snode->edittree, ionode, (ID *)snode->edittree);
iosock = node_group_input_find_socket(ionode, gsock->identifier);
{
/* place the node at the mouse pointer */
float sockx = 42.f + 3*HIDDEN_RAD; /* XXX totally arbitrary initial hidden node size ... */
float socky = -HIDDEN_RAD;
ionode->locx = snode->cursor[0] - sockx;
ionode->locy = snode->cursor[1] - socky;
}
}
link->fromnode = ionode;
link->fromsock = iosock;
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
}
else if (link->fromnode && link->fromsock) {
link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
link->tonode = NULL;
if (BLI_findindex(&ntree->links, link) < 0)
BLI_addtail(&ntree->links, link);
else if (link->fromsock) {
if (!ionode) {
ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_OUTPUT);
gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->fromnode, link->fromsock);
node_group_output_verify(snode->edittree, ionode, (ID *)snode->edittree);
iosock = node_group_output_find_socket(ionode, gsock->identifier);
{
/* place the node at the mouse pointer */
float sockx = 0;
float socky = -HIDDEN_RAD;
ionode->locx = snode->cursor[0] - sockx;
ionode->locy = snode->cursor[1] - socky;
}
}
link->tonode = ionode;
link->tosock = iosock;
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
}
else {
nodeRemLink(snode->edittree, link);
}
}
else
nodeRemLink(ntree, link);
}
ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
BLI_remlink(&snode->linkdrag, nldrag);
/* links->data pointers are either held by the tree or freed already */
BLI_freelistN(&nldrag->links);
MEM_freeN(nldrag);
return OPERATOR_FINISHED;
}
}
return OPERATOR_RUNNING_MODAL;
}
@@ -646,6 +634,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
oplink->flag |= NODE_LINK_VALID;
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
}
@@ -659,6 +649,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->fromnode = node;
oplink->fromsock = sock;
oplink->flag |= NODE_LINK_VALID;
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -678,9 +670,11 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
oplink->flag |= NODE_LINK_VALID;
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
/* send changed event to original link->tonode */
if (node)
snode_update(snode, node);
@@ -695,6 +689,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->tonode = node;
oplink->tosock = sock;
oplink->flag |= NODE_LINK_VALID;
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -760,6 +756,7 @@ void NODE_OT_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links");
RNA_def_boolean(ot->srna, "expose", FALSE, "Expose", "Expose the socket as an interface node");
}
/* ********************** Make Link operator ***************** */
@@ -845,6 +842,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
if (nodeLinkIsHidden(link))
continue;
if (cut_links_intersect(link, mcoords, i)) {
@@ -1075,11 +1074,8 @@ static void node_join_attach_recursive(bNode *node, bNode *frame)
static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bNodeTree *ntree = snode->edittree;
bNode *node, *frame;
bNodeTemplate ntemp;
/* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1089,10 +1085,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
}
ntemp.main = bmain;
ntemp.scene = scene;
ntemp.type = NODE_FRAME;
frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
/* reset tags */
for (node = ntree->nodes.first; node; node = node->next)
@@ -1310,6 +1303,9 @@ static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
/* test node for links */
for (link = snode->edittree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
if (link->tonode == *select || link->fromnode == *select)
return NULL;
}
@@ -1350,7 +1346,9 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
/* we only tag a single link for intersect now */
/* idea; use header dist when more? */
for (link = snode->edittree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
if (selink)
break;
@@ -1415,11 +1413,12 @@ void ED_node_link_insert(ScrArea *sa)
link->tonode = select;
link->tosock = socket_best_match(&select->inputs);
node_remove_extra_links(snode, link->tosock, link);
link->flag &= ~NODE_LINKFLAG_HILITE;
nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
ntreeUpdateTree(snode->edittree); /* needed for pointers */
snode_update(snode, select);
ED_node_changed_update(snode->id, select);
ED_node_tag_update_id(snode->id);
}
}
+22 -52
View File
@@ -82,30 +82,9 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
return NULL;
}
void node_select(bNode *node)
{
node->flag |= SELECT;
}
void node_deselect(bNode *node)
{
bNodeSocket *sock;
node->flag &= ~SELECT;
/* deselect sockets too */
for (sock = node->inputs.first; sock; sock = sock->next)
sock->flag &= ~SELECT;
for (sock = node->outputs.first; sock; sock = sock->next)
sock->flag &= ~SELECT;
}
static void node_toggle(bNode *node)
{
if (node->flag & SELECT)
node_deselect(node);
else
node_select(node);
nodeSetSelected(node, !(node->flag & SELECT));
}
void node_socket_select(bNode *node, bNodeSocket *sock)
@@ -157,7 +136,7 @@ void node_deselect_all(SpaceNode *snode)
bNode *node;
for (node = snode->edittree->nodes.first; node; node = node->next)
node_deselect(node);
nodeSetSelected(node, FALSE);
}
void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
@@ -189,9 +168,6 @@ void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
for (sock = snode->edittree->outputs.first; sock; sock = sock->next)
sock->flag &= ~SELECT;
}
void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
@@ -223,9 +199,6 @@ void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
for (sock = snode->edittree->inputs.first; sock; sock = sock->next)
sock->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
@@ -249,12 +222,12 @@ int node_select_same_type(SpaceNode *snode)
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw = 1;
node_deselect(p);
nodeSetSelected(p, FALSE);
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw = 1;
node_select(p);
nodeSetSelected(p, TRUE);
}
}
return(redraw);
@@ -296,8 +269,8 @@ int node_select_same_type_np(SpaceNode *snode, int dir)
if (p) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != p)
node_deselect(tnode);
node_select(p);
nodeSetSelected(tnode, FALSE);
nodeSetSelected(p, TRUE);
return(1);
}
return(0);
@@ -311,8 +284,8 @@ void node_select_single(bContext *C, bNode *node)
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != node)
node_deselect(tnode);
node_select(node);
nodeSetSelected(tnode, FALSE);
nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
@@ -387,8 +360,8 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
if (node) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
node_deselect(tnode);
node_select(node);
nodeSetSelected(tnode, FALSE);
nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
selected = 1;
}
@@ -477,13 +450,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (BLI_rctf_isect(&rectf, &node->totr, NULL)) {
if (gesture_mode == GESTURE_MODAL_SELECT)
node_select(node);
else
node_deselect(node);
nodeSetSelected(node, (gesture_mode == GESTURE_MODAL_SELECT));
}
else if (!extend) {
node_deselect(node);
nodeSetSelected(node, FALSE);
}
}
@@ -566,11 +536,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
if (select)
node_select(node);
else
node_deselect(node);
nodeSetSelected(node, select);
change = TRUE;
}
}
@@ -642,13 +608,13 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
for (node = node_lb->first; node; node = node->next) {
switch (action) {
case SEL_SELECT:
node_select(node);
nodeSetSelected(node, TRUE);
break;
case SEL_DESELECT:
node_deselect(node);
nodeSetSelected(node, FALSE);
break;
case SEL_INVERT:
((node->flag & SELECT) ? node_deselect : node_select)(node);
nodeSetSelected(node, !(node->flag & SELECT));
break;
}
}
@@ -688,13 +654,15 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
link->tonode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
node_select(node);
nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
@@ -730,13 +698,15 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
link->fromnode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
node_select(node);
nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
@@ -130,7 +130,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
ED_node_generic_update(bmain, ntree, node_to);
ED_node_tag_update_nodetree(bmain, ntree);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -145,11 +145,11 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
ED_node_generic_update(bmain, ntree, node_to);
ED_node_tag_update_nodetree(bmain, ntree);
}
/* add new node connected to this socket, or replace an existing one */
static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num)
{
bNode *node_from;
bNodeSocket *sock_from_tmp;
@@ -163,24 +163,29 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
/* find existing node that we can use */
for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
if (node_from->type == ntemp->type)
if (node_from->type == type)
break;
if (node_from)
if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
node_from = NULL;
if (node_prev && node_prev->type == ntemp->type &&
(ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id))
{
/* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */
if (node_prev && node_prev->type == type &&
(type != NODE_GROUP || node_prev->id == &ngroup->id)) {
/* keep the previous node if it's the same type */
node_from = node_prev;
}
else if (!node_from) {
node_from = nodeAddNode(ntree, ntemp);
node_from = nodeAddStaticNode(C, ntree, type);
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy;
/* XXX bad, should be dispatched to generic operator or something ... */
if (type==NODE_GROUP) {
node_from->id = (ID*)ngroup;
}
if (node_from->id)
id_us_plus(node_from->id);
}
@@ -209,9 +214,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeRemLink(ntree, link);
}
node_socket_free_default_value(sock_from->type, sock_from->default_value);
sock_from->default_value = node_socket_make_default_value(sock_from->type);
node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
#if 0 /* XXX TODO */
node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value);
sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo);
node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value);
#endif
}
}
}
@@ -231,7 +238,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
ED_node_generic_update(bmain, ntree, node_to);
ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
}
/****************************** Node Link Menu *******************************/
@@ -262,19 +269,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
bNodeSocket *sock_to = arg->sock;
bNodeTree *ntree = arg->ntree;
int event = GET_INT_FROM_POINTER(event_p);
bNodeTemplate ntemp;
ntemp.type = arg->type;
ntemp.ngroup = arg->ngroup;
ntemp.scene = CTX_data_scene(C);
ntemp.main = CTX_data_main(C);
if (event == UI_NODE_LINK_DISCONNECT)
node_socket_disconnect(bmain, ntree, node_to, sock_to);
else if (event == UI_NODE_LINK_REMOVE)
node_socket_remove(bmain, ntree, node_to, sock_to);
else
node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output);
node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output);
ED_undo_push(C, "Node input modify");
}
@@ -289,10 +290,10 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
if (node->id)
BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR);
else
BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR);
BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR);
}
else
BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR);
if (node->inputs.first == NULL &&
node->outputs.first != node->outputs.last)
@@ -316,19 +317,16 @@ static int ui_compatible_sockets(int typeA, int typeB)
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
Main *bmain = arg->bmain;
bNodeTree *ntree = arg->ntree;
bNodeSocket *sock = arg->sock;
uiLayout *layout = arg->layout;
uiLayout *column = NULL;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
bNodeType *ntype;
bNodeTree *ngroup;
NodeLinkArg *argN;
int first = 1;
int compatibility = 0;
if (ntree->type == NTREE_SHADER) {
if (BKE_scene_use_new_shading_nodes(arg->scene))
compatibility = NODE_NEW_SHADING;
@@ -336,114 +334,58 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
compatibility = NODE_OLD_SHADING;
}
if (nclass == NODE_CLASS_GROUP) {
for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
bNodeSocket *gsock;
char name[UI_MAX_NAME_STR];
int i, j, num = 0;
if (ngroup->type != ntree->type)
NODE_TYPES_BEGIN(ntype)
bNodeSocketTemplate *stemp;
char name[UI_MAX_NAME_STR];
int i, j, num = 0;
if (compatibility && !(ntype->compatibility & compatibility))
continue;
if (ntype->nclass != nclass)
continue;
for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
if (ui_compatible_sockets(stemp->type, sock->type))
num++;
for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
if (!ui_compatible_sockets(stemp->type, sock->type))
continue;
for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next)
if (ui_compatible_sockets(gsock->type, sock->type))
num++;
for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) {
if (!ui_compatible_sockets(gsock->type, sock->type))
continue;
if (first) {
column = uiLayoutColumn(layout, FALSE);
uiBlockSetCurLayout(block, column);
uiItemL(column, IFACE_(cname), ICON_NODE);
if (first) {
column = uiLayoutColumn(layout, 0);
uiBlockSetCurLayout(block, column);
uiItemL(column, IFACE_(cname), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
first = 0;
}
if (num > 1) {
if (j == 0) {
uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
first = 0;
}
if (num > 1) {
if (j == 0) {
uiItemL(column, ngroup->id.name + 2, ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
}
BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name);
j++;
}
else
BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR);
but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
argN = MEM_dupallocN(arg);
argN->type = NODE_GROUP;
argN->ngroup = ngroup;
argN->output = i;
uiButSetNFunc(but, ui_node_link, argN, NULL);
BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
j++;
}
else
BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR);
but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
argN = MEM_dupallocN(arg);
argN->type = ntype->type;
argN->output = i;
uiButSetNFunc(but, ui_node_link, argN, NULL);
}
}
else {
bNodeTreeType *ttype = ntreeGetType(ntree->type);
for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
bNodeSocketTemplate *stemp;
char name[UI_MAX_NAME_STR];
int i, j, num = 0;
if (compatibility && !(ntype->compatibility & compatibility))
continue;
if (ntype->nclass != nclass)
continue;
for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
if (ui_compatible_sockets(stemp->type, sock->type))
num++;
for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
if (!ui_compatible_sockets(stemp->type, sock->type))
continue;
if (first) {
column = uiLayoutColumn(layout, FALSE);
uiBlockSetCurLayout(block, column);
uiItemL(column, IFACE_(cname), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
first = 0;
}
if (num > 1) {
if (j == 0) {
uiItemL(column, IFACE_(ntype->name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
}
BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
j++;
}
else
BLI_strncpy(name, IFACE_(ntype->name), UI_MAX_NAME_STR);
but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
argN = MEM_dupallocN(arg);
argN->type = ntype->type;
argN->output = i;
uiButSetNFunc(but, ui_node_link, argN, NULL);
}
}
}
NODE_TYPES_END
}
static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -463,7 +405,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
uiLayout *split, *column;
NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
bNodeSocket *sock = arg->sock;
bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type);
bNodeTreeType *ntreetype = arg->ntree->typeinfo;
uiBlockSetCurLayout(block, layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -557,7 +499,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
PointerRNA inputptr;
PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *bt;
uiLayout *split, *row, *col;
@@ -579,6 +521,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
/* socket RNA pointer */
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
memset(label, ' ', indent);
@@ -627,16 +570,25 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
}
else {
/* input not linked, show value */
if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
if (input->type == SOCK_VECTOR) {
row = uiLayoutRow(split, FALSE);
col = uiLayoutColumn(row, FALSE);
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
}
else {
if (!(input->flag & SOCK_HIDE_VALUE)) {
switch (input->type) {
case SOCK_FLOAT:
case SOCK_INT:
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING:
row = uiLayoutRow(split, TRUE);
uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
break;
case SOCK_VECTOR:
row = uiLayoutRow(split, FALSE);
col = uiLayoutColumn(row, FALSE);
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
break;
default:
row = uiLayoutRow(split, FALSE);
break;
}
}
else
@@ -653,7 +605,7 @@ void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *
{
bNode *tnode;
if (!ntree)
if (!ntreeIsValid(ntree))
return;
/* clear for cycle check */
@@ -61,6 +61,7 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
#include "NOD_composite.h"
/* **************** View All Operator ************** */
@@ -370,7 +371,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
float fx, fy, bufx, bufy;
int ret = FALSE;
if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) {
if (strcmp(snode->tree_idname, ntreeType_Composite->idname)==0 || (snode->flag & SNODE_BACKDRAW) == 0) {
/* use viewer image for color sampling only if we're in compositor tree
* with backdrop enabled
*/
@@ -524,7 +525,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
ImageSampleInfo *info;
if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW))
return OPERATOR_CANCELLED;
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
+215 -27
View File
@@ -45,10 +45,10 @@
#include "BKE_node.h"
#include "ED_space_api.h"
#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_node.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -59,6 +59,168 @@
#include "node_intern.h" /* own include */
/* ******************** tree path ********************* */
void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
{
bNodeTreePath *path, *path_next;
for (path=snode->treepath.first; path; path=path_next) {
path_next = path->next;
MEM_freeN(path);
}
snode->treepath.first = snode->treepath.last = NULL;
if (ntree) {
path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
path->nodetree = ntree;
path->parent_key = NODE_INSTANCE_KEY_BASE;
if (id)
BLI_strncpy(path->node_name, id->name+2, sizeof(path->node_name));
BLI_addtail(&snode->treepath, path);
}
/* update current tree */
snode->nodetree = snode->edittree = ntree;
snode->id = id;
snode->from = from;
/* listener updates the View2D center from edittree */
WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
}
void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
{
bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
bNodeTreePath *prev_path = snode->treepath.last;
path->nodetree = ntree;
if (gnode) {
if (prev_path)
path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
else
path->parent_key = NODE_INSTANCE_KEY_BASE;
BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
}
else
path->parent_key = NODE_INSTANCE_KEY_BASE;
BLI_addtail(&snode->treepath, path);
/* update current tree */
snode->edittree = ntree;
/* listener updates the View2D center from edittree */
WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
}
void ED_node_tree_pop(SpaceNode *snode)
{
bNodeTreePath *path = snode->treepath.last;
/* don't remove root */
if (path == snode->treepath.first)
return;
BLI_remlink(&snode->treepath, path);
MEM_freeN(path);
/* update current tree */
path = snode->treepath.last;
snode->edittree = path->nodetree;
/* listener updates the View2D center from edittree */
WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
}
int ED_node_tree_depth(SpaceNode *snode)
{
return BLI_countlist(&snode->treepath);
}
bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
{
bNodeTreePath *path;
int i;
for (path = snode->treepath.last, i = 0; path; path=path->prev, ++i) {
if (i == level)
return path->nodetree;
}
return NULL;
}
int ED_node_tree_path_length(SpaceNode *snode)
{
bNodeTreePath *path;
int length = 0;
int i;
for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
length += strlen(path->node_name);
if (i > 0)
length += 1; /* for separator char */
}
return length;
}
void ED_node_tree_path_get(SpaceNode *snode, char *value)
{
bNodeTreePath *path;
int i;
value[0] = '\0';
for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
if (i == 0) {
strcpy(value, path->node_name);
value += strlen(path->node_name);
}
else {
sprintf(value, "/%s", path->node_name);
value += strlen(path->node_name) + 1;
}
}
}
void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
{
bNodeTreePath *path;
int size, i;
value[0] = '\0';
for (path=snode->treepath.first, i=0; path; path=path->next, ++i) {
if (i == 0) {
BLI_strncpy(value, path->node_name, max_length);
size = strlen(path->node_name);
}
else {
BLI_snprintf(value, max_length, "/%s", path->node_name);
size = strlen(path->node_name) + 1;
}
max_length -= size;
if (max_length <= 0)
break;
value += size;
}
}
void snode_group_offset(SpaceNode *snode, float *x, float *y)
{
bNodeTreePath *path = snode->treepath.last;
float cx, cy;
if (path) {
cx = path->nodetree->view_center[0];
cy = path->nodetree->view_center[1];
if (path->prev) {
*x = cx - path->prev->nodetree->view_center[0];
*y = cy - path->prev->nodetree->view_center[1];
return;
}
}
*x = *y = 0.0f;
}
/* ******************** manage regions ********************* */
ARegion *node_has_buttons_region(ScrArea *sa)
@@ -124,6 +286,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
/* backdrop */
snode->zoom = 1.0f;
/* select the first tree type for valid type */
NODE_TREE_TYPES_BEGIN(treetype)
strcpy(snode->tree_idname, treetype->idname);
break;
NODE_TREE_TYPES_END
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for node");
@@ -167,10 +335,15 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
return (SpaceLink *)snode;
}
/* not spacelink itself */
static void node_free(SpaceLink *UNUSED(sl))
static void node_free(SpaceLink *sl)
{
SpaceNode *snode = (SpaceNode*)sl;
bNodeTreePath *path, *path_next;
for (path=snode->treepath.first; path; path=path_next) {
path_next = path->next;
MEM_freeN(path);
}
}
@@ -184,14 +357,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
{
/* note, ED_area_tag_refresh will re-execute compositor */
SpaceNode *snode = sa->spacedata.first;
int type = snode->treetype;
short shader_type = snode->shaderfrom;
/* preview renders */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
case ND_NODES:
case ND_NODES: {
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
/* shift view to node tree center */
if (ar && snode->edittree)
UI_view2d_setcenter(&ar->v2d, snode->edittree->view_center[0], snode->edittree->view_center[1]);
ED_area_tag_refresh(sa);
break;
}
case ND_FRAME:
ED_area_tag_refresh(sa);
break;
@@ -199,7 +379,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
break;
case ND_TRANSFORM_DONE:
if (type == NTREE_COMPOSIT) {
if (ED_node_is_compositor(snode)) {
if (snode->flag & SNODE_AUTO_RENDER) {
snode->recalc = 1;
ED_area_tag_refresh(sa);
@@ -211,7 +391,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
/* future: add ID checks? */
case NC_MATERIAL:
if (type == NTREE_SHADER) {
if (ED_node_is_shader(snode)) {
if (wmn->data == ND_SHADING)
ED_area_tag_refresh(sa);
else if (wmn->data == ND_SHADING_DRAW)
@@ -224,18 +404,18 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_TEXTURE:
if (type == NTREE_SHADER || type == NTREE_TEXTURE) {
if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
if (wmn->data == ND_NODES)
ED_area_tag_refresh(sa);
}
break;
case NC_WORLD:
if (type == NTREE_SHADER && shader_type == SNODE_SHADER_WORLD) {
if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
ED_area_tag_refresh(sa);
}
break;
case NC_OBJECT:
if (type == NTREE_SHADER) {
if (ED_node_is_shader(snode)) {
if (wmn->data == ND_OB_SHADING)
ED_area_tag_refresh(sa);
}
@@ -261,7 +441,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
if (type == NTREE_COMPOSIT) {
if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
ED_area_tag_refresh(sa);
}
}
@@ -269,7 +449,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_IMAGE:
if (wmn->action == NA_EDITED) {
if (type == NTREE_COMPOSIT) {
if (ED_node_is_compositor(snode)) {
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
@@ -281,7 +461,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_MOVIECLIP:
if (wmn->action == NA_EDITED) {
if (type == NTREE_COMPOSIT) {
if (ED_node_is_compositor(snode)) {
if (nodeUpdateID(snode->nodetree, wmn->reference))
ED_area_tag_refresh(sa);
}
@@ -294,11 +474,13 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
{
/* default now: refresh node is starting preview */
SpaceNode *snode = sa->spacedata.first;
ED_preview_kill_jobs(C);
snode_set_context(C);
snode_set_context(snode, CTX_data_scene(C));
if (snode->nodetree) {
if (snode->treetype == NTREE_SHADER) {
if (ntreeIsValid(snode->nodetree)) {
if (snode->nodetree->type == NTREE_SHADER) {
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes)
@@ -315,7 +497,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
else if (snode->treetype == NTREE_COMPOSIT) {
else if (snode->nodetree->type == NTREE_COMPOSIT) {
Scene *scene = (Scene *)snode->id;
if (scene->use_nodes) {
/* recalc is set on 3d view changes for auto compo */
@@ -328,7 +510,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
}
}
}
else if (snode->treetype == NTREE_TEXTURE) {
else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
@@ -339,11 +521,14 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
SpaceNode *snoden = MEM_dupallocN(sl);
SpaceNode *snode = (SpaceNode*)sl;
SpaceNode *snoden = MEM_dupallocN(snode);
/* clear or remove stuff from old */
snoden->nodetree = NULL;
snoden->linkdrag.first = snoden->linkdrag.last = NULL;
BLI_duplicatelist(&snoden->treepath, &snode->treepath);
return (SpaceLink *)snoden;
}
@@ -415,9 +600,7 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
static void node_main_area_draw(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
drawnodespace(C, ar, v2d);
drawnodespace(C, ar);
}
@@ -469,11 +652,8 @@ static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
static void node_header_area_draw(const bContext *C, ARegion *ar)
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
/* find and set the context */
snode_set_context(snode, scene);
snode_set_context(C);
ED_region_header(C, ar);
}
@@ -549,6 +729,14 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
return 1;
}
else if (CTX_data_equals(member, "node_previews")) {
if (snode->nodetree) {
CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
}
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
return 1;
}
return 0;
}
+1 -1
View File
@@ -159,7 +159,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
if (node && is_image_texture_node(node)) {
node->id = &ima->id;
ED_node_generic_update(bmain, ma->nodetree, node);
ED_node_tag_update_nodetree(bmain, ma->nodetree);
}
}
+159 -36
View File
@@ -44,11 +44,19 @@ struct SpaceNode;
struct bNodeLink;
struct bNodeType;
struct bNodeTreeExec;
struct bNodePreview;
struct bNodeInstanceHash;
struct AnimData;
struct bGPdata;
struct uiBlock;
struct Image;
/* In writefile.c: write deprecated DNA data,
* to ensure forward compatibility in 2.6x versions.
* Will be removed eventually.
*/
#define USE_NODE_COMPAT_CUSTOMNODES
#define NODE_MAXSTR 64
typedef struct bNodeStack {
@@ -79,13 +87,22 @@ typedef struct bNodeStack {
typedef struct bNodeSocket {
struct bNodeSocket *next, *prev, *new_sock;
IDProperty *prop; /* user-defined properties */
char identifier[64]; /* unique identifier for mapping */
char name[64]; /* MAX_NAME */
/* XXX deprecated, only used for the Image and OutputFile nodes,
* should be removed at some point.
*/
void *storage; /* custom storage */
short type, flag;
short limit; /* max. number of links */
short pad1;
short in_out; /* input/output type */
struct bNodeSocketType *typeinfo; /* runtime type information */
char idname[64]; /* runtime type identifier */
float locx, locy;
@@ -98,11 +115,14 @@ typedef struct bNodeSocket {
int resizemode; /* compositor resize mode of the socket */
void *cache; /* cached data from execution */
/* internal data to retrieve relations and groups */
int own_index; /* group socket identifiers, to find matching pairs after reading files */
/* internal data to retrieve relations and groups
* DEPRECATED, now uses the generic identifier string instead
*/
int own_index DNA_DEPRECATED; /* group socket identifiers, to find matching pairs after reading files */
/* XXX deprecated, only used for restoring old group node links */
int to_index DNA_DEPRECATED;
struct bNodeSocket *groupsock;
/* XXX deprecated, still forward compatible since verification restores pointer from matching own_index. */
struct bNodeSocket *groupsock DNA_DEPRECATED;
struct bNodeLink *link; /* a link pointer, set in ntreeUpdateTree */
@@ -111,31 +131,34 @@ typedef struct bNodeSocket {
} bNodeSocket;
/* sock->type */
#define SOCK_CUSTOM -1 /* socket has no integer type */
#define SOCK_FLOAT 0
#define SOCK_VECTOR 1
#define SOCK_RGBA 2
#define SOCK_SHADER 3
#define SOCK_BOOLEAN 4
#define SOCK_MESH 5
#define __SOCK_MESH 5 /* deprecated */
#define SOCK_INT 6
#define SOCK_STRING 7
#define NUM_SOCKET_TYPES 8 /* must be last! */
/* socket side (input/output) */
#define SOCK_IN 1
#define SOCK_OUT 2
typedef enum eNodeSocketInOut {
SOCK_IN = 1,
SOCK_OUT = 2
} eNodeSocketInOut;
/* sock->flag, first bit is select */
/* hidden is user defined, to hide unused */
#define SOCK_HIDDEN 2
/* for quick check if socket is linked */
#define SOCK_IN_USE 4 /* XXX deprecated */
#define SOCK_IN_USE 4
/* unavailable is for dynamic sockets */
#define SOCK_UNAVAIL 8
/* dynamic socket (can be modified by user) */
#define SOCK_DYNAMIC 16
/* group socket should not be exposed */
#define SOCK_INTERNAL 32
/* DEPRECATED dynamic socket (can be modified by user) */
#define __SOCK_DYNAMIC 16
/* DEPRECATED group socket should not be exposed */
#define __SOCK_INTERNAL 32
/* socket collapsed in UI */
#define SOCK_COLLAPSED 64
/* hide socket value, if it gets auto default */
@@ -144,19 +167,18 @@ typedef struct bNodeSocket {
/* DEPRECATED, only kept here to avoid reusing the flag */
#define SOCK_AUTO_HIDDEN__DEPRECATED 256
typedef struct bNodePreview {
unsigned char *rect;
short xsize, ysize;
int pad;
} bNodePreview;
/* limit data in bNode to what we want to see saved? */
typedef struct bNode {
struct bNode *next, *prev, *new_node;
IDProperty *prop; /* user-defined properties */
struct bNodeType *typeinfo; /* runtime type information */
char idname[64]; /* runtime type identifier */
char name[64]; /* MAX_NAME */
int flag;
short type, pad2;
short type, pad;
short done, level; /* both for dependency and sorting */
short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */
short stack_index; /* for groupnode, offset in global caller stack */
@@ -186,10 +208,17 @@ typedef struct bNode {
rctf totr; /* entire boundbox (worldspace) */
rctf butr; /* optional buttons area */
rctf prvr; /* optional preview area */
bNodePreview *preview; /* optional preview image */
/* XXX TODO
* Node totr size depends on the prvr size, which in turn is determined from preview size.
* In earlier versions bNodePreview was stored directly in nodes, but since now there can be
* multiple instances using different preview images it is possible that required node size varies between instances.
* preview_xsize, preview_ysize defines a common reserved size for preview rect for now,
* could be replaced by more accurate node instance drawing, but that requires removing totr from DNA
* and replacing all uses with per-instance data.
*/
short preview_xsize, preview_ysize; /* reserved size of the preview rect */
int pad2;
struct uiBlock *block; /* runtime during drawing */
struct bNodeType *typeinfo; /* lookup of callbacks and defaults */
} bNode;
/* node->flag */
@@ -200,7 +229,7 @@ typedef struct bNode {
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
#define NODE_DO_OUTPUT 64
#define NODE_GROUP_EDIT 128
#define __NODE_GROUP_EDIT 128 /* DEPRECATED */
/* free test flag, undefined */
#define NODE_TEST 256
/* node is disabled */
@@ -221,6 +250,12 @@ typedef struct bNode {
#define NODE_ACTIVE_TEXTURE (1<<14)
/* use a custom color for the node */
#define NODE_CUSTOM_COLOR (1<<15)
/* Node has been initialized
* This flag indicates the node->typeinfo->init function has been called.
* In case of undefined type at creation time this can be delayed until
* until the node type is registered.
*/
#define NODE_INIT (1<<16)
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
@@ -229,6 +264,36 @@ typedef struct bNode {
#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */
#define NODE_UPDATE_ID 1 /* associated id data block has changed */
/* Unique hash key for identifying node instances
* Defined as a struct because DNA does not support other typedefs.
*/
typedef struct bNodeInstanceKey
{
unsigned int value;
} bNodeInstanceKey;
/* Base struct for entries in node instance hash.
* WARNING: pointers are cast to this struct internally,
* it must be first member in hash entry structs!
*/
typedef struct bNodeInstanceHashEntry {
bNodeInstanceKey key;
/* tags for cleaning the cache */
short tag;
short pad;
} bNodeInstanceHashEntry;
typedef struct bNodePreview {
bNodeInstanceHashEntry hash_entry; /* must be first */
unsigned char *rect;
short xsize, ysize;
int pad;
} bNodePreview;
typedef struct bNodeLink {
struct bNodeLink *next, *prev;
@@ -263,7 +328,13 @@ typedef struct bNodeTree {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
struct bNodeTreeType *typeinfo; /* runtime type information */
char idname[64]; /* runtime type identifier */
struct StructRNA *interface_type; /* runtime RNA type of the group interface */
struct bGPdata *gpd; /* grease pencil data */
float view_center[2]; /* node tree stores own offset for consistent editor view */
ListBase nodes, links;
@@ -272,8 +343,11 @@ typedef struct bNodeTree {
* will increase this counter */
int flag;
int update; /* update flags */
short is_updating; /* flag to prevent reentrant update calls */
short done; /* generic temporary flag for recursion check (DFS/BFS) */
int pad2;
int nodetype; /* specific node type this tree is used for */
int nodetype DNA_DEPRECATED; /* specific node type this tree is used for */
short edit_quality; /* Quality setting when editing */
short render_quality; /* Quality setting when rendering */
@@ -281,7 +355,16 @@ typedef struct bNodeTree {
rctf viewer_border;
ListBase inputs, outputs; /* external sockets for group nodes */
/* Lists of bNodeSocket to hold default values and own_index.
* Warning! Don't make links to these sockets, input/output nodes are used for that.
* These sockets are used only for generating external interfaces.
*/
ListBase inputs, outputs;
/* Node preview hash table
* Only available in base node trees (e.g. scene->node_tree)
*/
struct bNodeInstanceHash *previews;
/* execution data */
/* XXX It would be preferable to completely move this data out of the underlying node tree,
@@ -302,10 +385,10 @@ typedef struct bNodeTree {
} bNodeTree;
/* ntree->type, index */
#define NTREE_CUSTOM -1 /* for dynamically registered custom types */
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
#define NTREE_TEXTURE 2
#define NUM_NTREE_TYPES 3
/* ntree->init, flag */
#define NTREE_TYPE_INIT 1
@@ -320,18 +403,24 @@ typedef struct bNodeTree {
/* XXX not nice, but needed as a temporary flags
* for group updates after library linking.
*/
#define NTREE_DO_VERSIONS_GROUP_EXPOSE 1024
#define NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 1024 /* changes from r35033 */
#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP 2048 /* custom_nodes branch: remove links to node tree sockets */
#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE 4096 /* custom_nodes branch: create group input/output nodes */
/* ntree->update */
#define NTREE_UPDATE 0xFFFF /* generic update flag (includes all others) */
#define NTREE_UPDATE_LINKS 1 /* links have been added or removed */
#define NTREE_UPDATE_NODES 2 /* nodes or sockets have been added or removed */
#define NTREE_UPDATE_GROUP_IN 16 /* group inputs have changed */
#define NTREE_UPDATE_GROUP_OUT 32 /* group outputs have changed */
#define NTREE_UPDATE_GROUP 48 /* group has changed (generic flag including all other group flags) */
typedef enum eNodeTreeUpdate {
NTREE_UPDATE = 0xFFFF, /* generic update flag (includes all others) */
NTREE_UPDATE_LINKS = 1, /* links have been added or removed */
NTREE_UPDATE_NODES = 2, /* nodes or sockets have been added or removed */
NTREE_UPDATE_GROUP_IN = 16, /* group inputs have changed */
NTREE_UPDATE_GROUP_OUT = 32, /* group outputs have changed */
NTREE_UPDATE_GROUP = 48 /* group has changed (generic flag including all other group flags) */
} eNodeTreeUpdate;
/* socket value structs for input buttons */
/* socket value structs for input buttons
* DEPRECATED now using ID properties
*/
typedef struct bNodeSocketValueInt {
int subtype; /* RNA subtype */
@@ -731,8 +820,6 @@ typedef struct NodeShaderScript {
char bytecode_hash[64];
char *bytecode;
IDProperty *prop;
} NodeShaderScript;
typedef struct NodeShaderTangent {
@@ -758,6 +845,9 @@ typedef struct NodeShaderNormalMap {
#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */
#define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */
/* proxy node flags */
#define NODE_PROXY_AUTOTYPE 1 /* automatically change output type based on link */
/* comp channel matte */
#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1
#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2
@@ -857,6 +947,39 @@ typedef struct NodeShaderNormalMap {
#define CMP_NODE_MASK_MBLUR_SAMPLES_MAX 64
/* geometry output socket defines */
#define GEOM_OUT_GLOB 0
#define GEOM_OUT_LOCAL 1
#define GEOM_OUT_VIEW 2
#define GEOM_OUT_ORCO 3
#define GEOM_OUT_UV 4
#define GEOM_OUT_NORMAL 5
#define GEOM_OUT_VCOL 6
#define GEOM_OUT_VCOL_ALPHA 7
#define GEOM_OUT_FRONTBACK 8
/* material input socket defines */
#define MAT_IN_COLOR 0
#define MAT_IN_SPEC 1
#define MAT_IN_REFL 2
#define MAT_IN_NORMAL 3
#define MAT_IN_MIR 4
#define MAT_IN_AMB 5
#define MAT_IN_EMIT 6
#define MAT_IN_SPECTRA 7
#define MAT_IN_RAY_MIRROR 8
#define MAT_IN_ALPHA 9
#define MAT_IN_TRANSLUCENCY 10
#define NUM_MAT_IN 11 /* for array size */
/* material output socket defines */
#define MAT_OUT_COLOR 0
#define MAT_OUT_ALPHA 1
#define MAT_OUT_NORMAL 2
#define MAT_OUT_DIFFUSE 3
#define MAT_OUT_SPEC 4
#define MAT_OUT_AO 5
/* image */
#define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT 1
+27 -2
View File
@@ -43,6 +43,7 @@
#include "DNA_image_types.h" /* ImageUser */
#include "DNA_movieclip_types.h" /* MovieClipUser */
#include "DNA_sequence_types.h" /* SequencerScopes */
#include "DNA_node_types.h" /* for bNodeInstanceKey */
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@@ -880,6 +881,17 @@ typedef struct SpaceScript {
/* Nodes Editor =========================================== */
/* Node Editor */
typedef struct bNodeTreePath {
struct bNodeTreePath *next, *prev;
struct bNodeTree *nodetree;
bNodeInstanceKey parent_key; /* base key for nodes in this tree instance */
int pad;
/* XXX this is not automatically updated when node names are changed! */
char node_name[64]; /* MAX_NAME */
} bNodeTreePath;
typedef struct SpaceNode {
SpaceLink *next, *prev;
ListBase regionbase; /* storage of regions for inactive spaces */
@@ -897,12 +909,24 @@ typedef struct SpaceNode {
float zoom; /* zoom for backdrop */
float cursor[2]; /* mouse pos for drawing socketless link and adding nodes */
/* XXX nodetree pointer info is all in the path stack now,
* remove later on and use bNodeTreePath instead. For now these variables are set when pushing/popping
* from path stack, to avoid having to update all the functions and operators. Can be done when
* design is accepted and everything is properly tested.
*/
ListBase treepath;
struct bNodeTree *nodetree, *edittree;
int treetype; /* treetype: as same nodetree->type */
/* tree type for the current node tree */
char tree_idname[64];
int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */
int pad3;
short texfrom; /* texfrom object, world or brush */
short shaderfrom; /* shader from object or world */
short recalc; /* currently on 0/1, for auto compo */
short pad[3];
short pad4;
ListBase linkdrag; /* temporary data for modal linking operator */
struct bGPdata *gpd; /* grease-pencil data */
@@ -921,6 +945,7 @@ typedef enum eSpaceNode_Flag {
SNODE_SHOW_HIGHLIGHT = (1 << 6),
SNODE_USE_HIDDEN_PREVIEW = (1 << 10),
SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
} eSpaceNode_Flag;
/* snode->texfrom */
+9 -3
View File
@@ -363,14 +363,13 @@ extern StructRNA RNA_NearSensor;
extern StructRNA RNA_NlaStrip;
extern StructRNA RNA_NlaTrack;
extern StructRNA RNA_Node;
extern StructRNA RNA_NodeForLoop;
extern StructRNA RNA_NodeGroup;
extern StructRNA RNA_NodeOutputFileSlotFile;
extern StructRNA RNA_NodeOutputFileSlotLayer;
extern StructRNA RNA_NodeInstanceHash;
extern StructRNA RNA_NodeLink;
extern StructRNA RNA_NodeSocket;
extern StructRNA RNA_NodeSocketInterface;
extern StructRNA RNA_NodeTree;
extern StructRNA RNA_NodeWhileLoop;
extern StructRNA RNA_NoiseTexture;
extern StructRNA RNA_NorController;
extern StructRNA RNA_Object;
@@ -655,7 +654,9 @@ StructRNA *RNA_struct_find(const char *identifier);
const char *RNA_struct_identifier(StructRNA *type);
const char *RNA_struct_ui_name(StructRNA *type);
const char *RNA_struct_ui_name_raw(StructRNA *type);
const char *RNA_struct_ui_description(StructRNA *type);
const char *RNA_struct_ui_description_raw(StructRNA *type);
const char *RNA_struct_translation_context(StructRNA *type);
int RNA_struct_ui_icon(StructRNA *type);
@@ -721,7 +722,9 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name);
int RNA_property_string_maxlength(PropertyRNA *prop);
const char *RNA_property_ui_name(PropertyRNA *prop);
const char *RNA_property_ui_name_raw(PropertyRNA *prop);
const char *RNA_property_ui_description(PropertyRNA *prop);
const char *RNA_property_ui_description_raw(PropertyRNA *prop);
const char *RNA_property_translation_context(PropertyRNA *prop);
int RNA_property_ui_icon(PropertyRNA *prop);
@@ -976,9 +979,11 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
/* check if the idproperty exists, for operators */
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost);
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop);
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost);
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
bool RNA_property_is_idprop(PropertyRNA *prop);
void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
/* python compatible string representation of this property, (must be freed!) */
char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index);
@@ -995,6 +1000,7 @@ char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func, Poi
const char *RNA_function_identifier(FunctionRNA *func);
const char *RNA_function_ui_description(FunctionRNA *func);
const char *RNA_function_ui_description_raw(FunctionRNA *func);
int RNA_function_flag(FunctionRNA *func);
int RNA_function_defined(FunctionRNA *func);
+2
View File
@@ -223,6 +223,8 @@ const char *RNA_property_typename(PropertyType type);
#define IS_DNATYPE_FLOAT_COMPAT(_str) (strcmp(_str, "float") == 0 || strcmp(_str, "double") == 0)
#define IS_DNATYPE_INT_COMPAT(_str) (strcmp(_str, "int") == 0 || strcmp(_str, "short") == 0 || strcmp(_str, "char") == 0)
void RNA_identifier_sanitize(char *identifier, int property);
/* max size for dynamic defined type descriptors,
* this value is arbitrary */
#define RNA_DYN_DESCR_MAX 240
+21 -2
View File
@@ -29,6 +29,10 @@
#include "RNA_types.h"
struct bNodeTreeType;
struct bNodeType;
struct bNodeSocketType;
/* Types */
extern EnumPropertyItem id_type_items[];
@@ -128,8 +132,23 @@ extern EnumPropertyItem gameproperty_type_items[];
extern EnumPropertyItem viewport_shade_items[];
extern EnumPropertyItem nodetree_type_items[];
extern EnumPropertyItem node_socket_type_items[];
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
int rna_node_tree_idname_to_enum(const char *idname);
struct bNodeTreeType *rna_node_tree_type_from_enum(int value);
EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, struct bNodeTreeType *), int *free);
int rna_node_type_to_enum(struct bNodeType *typeinfo);
int rna_node_idname_to_enum(const char *idname);
struct bNodeType *rna_node_type_from_enum(int value);
EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, struct bNodeType*), int *free);
int rna_node_socket_type_to_enum(struct bNodeSocketType *typeinfo);
int rna_node_socket_idname_to_enum(const char *idname);
struct bNodeSocketType *rna_node_socket_type_from_enum(int value);
EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, struct bNodeSocketType*), int *free);
extern EnumPropertyItem node_socket_in_out_items[];
extern EnumPropertyItem node_icon_items[];
extern EnumPropertyItem node_math_items[];
extern EnumPropertyItem node_vec_math_items[];
@@ -259,6 +259,7 @@ blender_include_dirs(
../../imbuf
../../ikplugin
../../makesdna
../../nodes/
../../windowmanager
../../editors/include
../../render/extern/include
@@ -296,7 +297,6 @@ set(SRC
${SRC_RNA_INC}
rna_internal.h
rna_internal_types.h
rna_nodetree_types.h
rna_mesh_utils.h
)
+58 -3
View File
@@ -282,6 +282,20 @@ static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
return NULL;
}
static void rna_idproperty_free(PointerRNA *ptr, const char *name)
{
IDProperty *group = RNA_struct_idprops(ptr, 0);
if (group) {
IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
if (idprop) {
IDP_RemFromGroup(group, idprop);
IDP_FreeProperty(idprop);
MEM_freeN(idprop);
}
}
}
static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->magic == RNA_MAGIC) {
@@ -477,7 +491,7 @@ static const char *rna_ensure_property_description(PropertyRNA *prop)
description = ((IDProperty *)prop)->name; /* XXX - not correct */
}
return TIP_(description);
return description;
}
static const char *rna_ensure_property_name(PropertyRNA *prop)
@@ -489,7 +503,7 @@ static const char *rna_ensure_property_name(PropertyRNA *prop)
else
name = ((IDProperty *)prop)->name;
return CTX_IFACE_(prop->translation_context, name);
return name;
}
/* Structs */
@@ -515,6 +529,11 @@ const char *RNA_struct_ui_name(StructRNA *type)
return CTX_IFACE_(type->translation_context, type->name);
}
const char *RNA_struct_ui_name_raw(StructRNA *type)
{
return type->name;
}
int RNA_struct_ui_icon(StructRNA *type)
{
if (type)
@@ -528,6 +547,11 @@ const char *RNA_struct_ui_description(StructRNA *type)
return TIP_(type->description);
}
const char *RNA_struct_ui_description_raw(StructRNA *type)
{
return type->description;
}
const char *RNA_struct_translation_context(StructRNA *type)
{
return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT;
@@ -778,7 +802,7 @@ const char *RNA_property_identifier(PropertyRNA *prop)
const char *RNA_property_description(PropertyRNA *prop)
{
return rna_ensure_property_description(prop);
return TIP_(rna_ensure_property_description(prop));
}
PropertyType RNA_property_type(PropertyRNA *prop)
@@ -1400,11 +1424,21 @@ int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, Property
}
const char *RNA_property_ui_name(PropertyRNA *prop)
{
return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
}
const char *RNA_property_ui_name_raw(PropertyRNA *prop)
{
return rna_ensure_property_name(prop);
}
const char *RNA_property_ui_description(PropertyRNA *prop)
{
return TIP_(rna_ensure_property_description(prop));
}
const char *RNA_property_ui_description_raw(PropertyRNA *prop)
{
return rna_ensure_property_description(prop);
}
@@ -4797,6 +4831,13 @@ bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
}
}
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->flag & PROP_IDPROPERTY) {
rna_idproperty_free(ptr, prop->identifier);
}
}
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
@@ -4825,6 +4866,15 @@ bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
}
}
void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
if (prop) {
RNA_property_unset(ptr, prop);
}
}
bool RNA_property_is_idprop(PropertyRNA *prop)
{
return (prop->magic != RNA_MAGIC);
@@ -5189,6 +5239,11 @@ const char *RNA_function_identifier(FunctionRNA *func)
}
const char *RNA_function_ui_description(FunctionRNA *func)
{
return TIP_(func->description);
}
const char *RNA_function_ui_description_raw(FunctionRNA *func)
{
return func->description;
}
+1 -1
View File
@@ -298,7 +298,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
for (node = ntree->nodes.first; node; node = node->next) {
if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
ED_node_generic_update(bmain, ntree, node);
ED_node_tag_update_nodetree(bmain, ntree);
}
}
}
@@ -458,6 +458,78 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop
return 1;
}
void RNA_identifier_sanitize(char *identifier, int property)
{
int a = 0;
/* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
static const char *kwlist[] = {
/* "False", "None", "True", */
"and", "as", "assert", "break",
"class", "continue", "def", "del", "elif", "else", "except",
"finally", "for", "from", "global", "if", "import", "in",
"is", "lambda", "nonlocal", "not", "or", "pass", "raise",
"return", "try", "while", "with", "yield", NULL
};
if (!isalpha(identifier[0])) {
/* first character failed isalpha() check */
identifier[0] = '_';
}
for (a = 0; identifier[a]; a++) {
if (DefRNA.preprocess && property) {
if (isalpha(identifier[a]) && isupper(identifier[a])) {
/* property names must contain lower case characters only */
identifier[a] = tolower(identifier[a]);
}
}
if (identifier[a] == '_') {
continue;
}
if (identifier[a] == ' ') {
/* spaces are not okay in identifier names */
identifier[a] = '_';
}
if (isalnum(identifier[a]) == 0) {
/* one of the characters failed an isalnum() check and is not an underscore */
identifier[a] = '_';
}
}
for (a = 0; kwlist[a]; a++) {
if (strcmp(identifier, kwlist[a]) == 0) {
/* this keyword is reserved by python.
* just replace the last character by '_' to keep it readable.
*/
identifier[strlen(identifier)-1] = '_';
break;
}
}
if (property) {
static const char *kwlist_prop[] = {
/* not keywords but reserved all the same because py uses */
"keys", "values", "items", "get",
NULL
};
for (a = 0; kwlist_prop[a]; a++) {
if (strcmp(identifier, kwlist_prop[a]) == 0) {
/* this keyword is reserved by python.
* just replace the last character by '_' to keep it readable.
*/
identifier[strlen(identifier)-1] = '_';
break;
}
}
}
}
/* Blender Data Definition */
BlenderRNA *RNA_create(void)
+5 -3
View File
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -169,14 +170,14 @@ static void rna_Lamp_spot_size_set(PointerRNA *ptr, float value)
la->spotsize = RAD2DEGF(value);
}
static void rna_Lamp_use_nodes_update(Main *blain, Scene *scene, PointerRNA *ptr)
static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Lamp *la = (Lamp *)ptr->data;
if (la->use_nodes && la->nodetree == NULL)
ED_node_shader_default(scene, &la->id);
ED_node_shader_default(C, &la->id);
rna_Lamp_update(blain, scene, ptr);
rna_Lamp_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
@@ -414,6 +415,7 @@ static void rna_def_lamp(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the lamp");
RNA_def_property_update(prop, 0, "rna_Lamp_use_nodes_update");
+24 -16
View File
@@ -235,23 +235,32 @@ static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerR
}
}
static bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
static EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
bNodeTree *tree = ntreeAddTree(bmain, name, type, NODE_GROUP);
id_us_min(&tree->id);
return tree;
return rna_node_tree_type_itemf(NULL, NULL, free);
}
static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr)
static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
{
bNodeTree *tree = tree_ptr->data;
if (ID_REAL_USERS(tree) <= 0) {
BKE_libblock_free(&bmain->nodetree, tree);
RNA_POINTER_INVALIDATE(tree_ptr);
bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type);
if (typeinfo) {
bNodeTree *ntree = ntreeAddTree(bmain, name, typeinfo->idname);
id_us_min(&ntree->id);
return ntree;
}
else
return NULL;
}
static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *ntree_ptr)
{
bNodeTree *ntree = ntree_ptr->data;
if (ID_REAL_USERS(ntree) <= 0) {
BKE_libblock_free(&bmain->nodetree, ntree);
RNA_POINTER_INVALIDATE(ntree_ptr);
}
else {
BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d",
tree->id.name + 2, ID_REAL_USERS(tree));
ntree->id.name + 2, ID_REAL_USERS(ntree));
}
}
@@ -1069,10 +1078,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *parm;
PropertyRNA *prop;
static EnumPropertyItem node_nodetree_items[] = {
{0, "SHADER", 0, "Shader", ""},
{1, "COMPOSITE", 0, "Composite", ""},
{2, "TEXTURE", 0, "Texture", ""},
static EnumPropertyItem dummy_items[] = {
{0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1085,7 +1092,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new node tree to the main database");
parm = RNA_def_string(func, "name", "NodeGroup", 0, "", "New name for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_enum(func, "type", node_nodetree_items, 0, "Type", "The type of node_group to add");
parm = RNA_def_enum(func, "type", dummy_items, 0, "Type", "The type of node_group to add");
RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_Main_nodetree_type_itemf");
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
parm = RNA_def_pointer(func, "tree", "NodeTree", "", "New node tree datablock");
@@ -82,6 +82,7 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -111,7 +112,7 @@ static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *
Material *ma = ptr->id.data;
if (ma->nodetree)
ntreeClearPreview(ma->nodetree);
BKE_node_preview_clear_tree(ma->nodetree);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
@@ -287,14 +288,14 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value)
ma->ramp_spec = add_colorband(0);
}
static void rna_Material_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
if (ma->use_nodes && ma->nodetree == NULL)
ED_node_shader_default(scene, &ma->id);
ED_node_shader_default(C, &ma->id);
rna_Material_update(bmain, scene, ptr);
rna_Material_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED(C), PointerRNA *ptr,
@@ -2024,6 +2025,7 @@ void RNA_def_material(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material");
RNA_def_property_update(prop, 0, "rna_Material_use_nodes_update");
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -1173,13 +1173,12 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
rna_Scene_glsl_update(bmain, activescene, ptr);
}
static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value)
static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
scene->use_nodes = value;
if (scene->use_nodes && scene->nodetree == NULL)
ED_node_composit_default(scene);
ED_node_composit_default(C, scene);
}
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -4533,9 +4532,9 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_use_nodes_set");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Enable the compositing node tree");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_nodes_update");
/* Sequencer */
prop = RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE);
+155 -13
View File
@@ -25,6 +25,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
@@ -32,6 +33,7 @@
#include "BKE_key.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "DNA_action_types.h"
#include "DNA_key_types.h"
@@ -1014,20 +1016,91 @@ static void rna_BackgroundImage_clear(View3D *v3d)
/* Space Node Editor */
static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, PointerRNA value)
static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, const PointerRNA value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL);
}
static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
bNodeTree *ntree = (bNodeTree *)value.data;
/* exclude group trees, only trees of the active type */
return (ntree->nodetype == 0 && ntree->type == snode->treetype);
/* node tree type must match the selected type in node editor */
return (strcmp(snode->tree_idname, ntree->idname) == 0);
}
static void rna_SpaceNodeEditor_node_tree_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *UNUSED(ptr))
{
SpaceNode *snode = (SpaceNode *)ptr->data;
ED_node_tree_update(C);
}
static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr)
{
SpaceNode *snode= (SpaceNode*)ptr->data;
return rna_node_tree_idname_to_enum(snode->tree_idname);
}
static void rna_SpaceNodeEditor_tree_type_set(PointerRNA *ptr, int value)
{
SpaceNode *snode= (SpaceNode*)ptr->data;
ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
}
static int rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type)
{
bContext *C = (bContext *)Cv;
if (type->poll)
return type->poll(C, type);
else
return TRUE;
}
static EnumPropertyItem *rna_SpaceNodeEditor_tree_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, free);
}
static void rna_SpaceNodeEditor_path_get(PointerRNA *ptr, char *value)
{
SpaceNode *snode = ptr->data;
ED_node_tree_path_get(snode, value);
}
static int rna_SpaceNodeEditor_path_length(PointerRNA *ptr)
{
SpaceNode *snode = ptr->data;
return ED_node_tree_path_length(snode);
}
void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C)
{
ED_node_tree_start(snode, NULL, NULL, NULL);
ED_node_tree_update(C);
}
void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree)
{
ED_node_tree_start(snode, (bNodeTree *)node_tree->data, NULL, NULL);
ED_node_tree_update(C);
}
void rna_SpaceNodeEditor_path_push(SpaceNode *snode, bContext *C, ReportList *reports, PointerRNA *node)
{
PointerRNA tree_ptr;
ED_node_tree_update(snode, scene);
tree_ptr = RNA_pointer_get(node, "node_tree");
if (!tree_ptr.data) {
BKE_reportf(reports, RPT_WARNING, "Missing node group tree in node %s", ((bNode *)node->data)->name);
return;
}
ED_node_tree_push(snode, (bNodeTree *)tree_ptr.data, (bNode *)node->data);
ED_node_tree_update(C);
}
void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C)
{
ED_node_tree_pop(snode);
ED_node_tree_update(C);
}
static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, PointerRNA *UNUSED(ptr),
@@ -3077,6 +3150,58 @@ static void rna_def_space_userpref(BlenderRNA *brna)
}
static void rna_def_node_tree_path(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "NodeTreePath", NULL);
RNA_def_struct_sdna(srna, "bNodeTreePath");
RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path");
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
}
static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop, *parm;
FunctionRNA *func;
RNA_def_property_srna(cprop, "SpaceNodeEditorPath");
srna = RNA_def_struct(brna, "SpaceNodeEditorPath", NULL);
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_ui_text(srna, "Space Node Editor Path", "History of node trees in the editor");
prop = RNA_def_property(srna, "to_string", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_SpaceNodeEditor_path_get", "rna_SpaceNodeEditor_path_length", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_ui_text(srna, "Path", "Get the node tree path as a string");
func = RNA_def_function(srna, "clear", "rna_SpaceNodeEditor_path_clear");
RNA_def_function_ui_description(func, "Reset the node tree path");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
func = RNA_def_function(srna, "start", "rna_SpaceNodeEditor_path_start");
RNA_def_function_ui_description(func, "Set the root node tree");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
func = RNA_def_function(srna, "push", "rna_SpaceNodeEditor_path_push");
RNA_def_function_ui_description(func, "Append a node group tree to the path");
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "node", "NodeGroup", "Node", "Group node");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
func = RNA_def_function(srna, "pop", "rna_SpaceNodeEditor_path_pop");
RNA_def_function_ui_description(func, "Remove the last node tree from the path");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
}
static void rna_def_space_node(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3106,13 +3231,17 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem dummy_items[] = {
{0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "SpaceNodeEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_ui_text(srna, "Space Node Editor", "Node editor space data");
prop = RNA_def_property(srna, "tree_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "treetype");
RNA_def_property_enum_items(prop, nodetree_type_items);
RNA_def_property_enum_items(prop, dummy_items);
RNA_def_property_enum_funcs(prop, "rna_SpaceNodeEditor_tree_type_get", "rna_SpaceNodeEditor_tree_type_set", "rna_SpaceNodeEditor_tree_type_itemf");
RNA_def_property_ui_text(prop, "Tree Type", "Node tree type to display and edit");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
@@ -3137,17 +3266,29 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "ID From", "Datablock from which the edited datablock is linked");
prop= RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL);
RNA_def_property_struct_type(prop, "NodeTreePath");
RNA_def_property_ui_text(prop, "Node Tree Path", "Path from the data block to the currently edited node tree");
rna_def_space_node_path_api(brna, prop);
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceNodeEditor_node_tree_set", NULL, "rna_SpaceNodeEditor_node_tree_poll");
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_SpaceNodeEditor_node_tree_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Node Tree", "Node tree being displayed");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, "rna_SpaceNodeEditor_node_tree_update");
prop = RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE);
prop= RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "edittree");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Edit Tree", "Edited node tree");
RNA_def_property_ui_text(prop, "Edit Tree", "Node tree being displayed and edited");
prop= RNA_def_property(srna, "pin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_PIN);
RNA_def_property_ui_text(prop, "Pinned", "Use the pinned node tree");
RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1);
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE, NULL);
prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_BACKDRAW);
@@ -3544,6 +3685,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_console_line(brna);
rna_def_space_info(brna);
rna_def_space_userpref(brna);
rna_def_node_tree_path(brna);
rna_def_space_node(brna);
rna_def_space_logic(brna);
rna_def_space_clip(brna);

Some files were not shown because too many files have changed in this diff Show More