svn merge ^/trunk/blender -r55372:55392

This commit is contained in:
Campbell Barton 2013-03-18 22:37:04 +00:00
commit ae25aa2210
314 changed files with 13722 additions and 9186 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)

@ -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

@ -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)

@ -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,

@ -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)

@ -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 {

@ -468,6 +468,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
parameter(param_name.c_str(), input->value_string);
break;
case SHADER_SOCKET_CLOSURE:
case SHADER_SOCKET_UNDEFINED:
break;
}
}

@ -172,17 +172,25 @@ extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens
float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles)
{
*dens = fluid->_density;
*fuel = fluid->_fuel;
*react = fluid->_react;
*flame = fluid->_flame;
*heat = fluid->_heat;
*heatold = fluid->_heatOld;
if(fuel)
*fuel = fluid->_fuel;
if(react)
*react = fluid->_react;
if(flame)
*flame = fluid->_flame;
if(heat)
*heat = fluid->_heat;
if(heatold)
*heatold = fluid->_heatOld;
*vx = fluid->_xVelocity;
*vy = fluid->_yVelocity;
*vz = fluid->_zVelocity;
*r = fluid->_color_r;
*g = fluid->_color_g;
*b = fluid->_color_b;
if(r)
*r = fluid->_color_r;
if(g)
*g = fluid->_color_g;
if(b)
*b = fluid->_color_b;
*obstacles = fluid->_obstacles;
*dt = fluid->_dt;
*dx = fluid->_dx;
@ -195,12 +203,18 @@ extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **r
return;
*dens = wt->_densityBig;
*fuel = wt->_fuelBig;
*react = wt->_reactBig;
*flame = wt->_flameBig;
*r = wt->_color_rBig;
*g = wt->_color_gBig;
*b = wt->_color_bBig;
if(fuel)
*fuel = wt->_fuelBig;
if(react)
*react = wt->_reactBig;
if(flame)
*flame = wt->_flameBig;
if(r)
*r = wt->_color_rBig;
if(g)
*g = wt->_color_gBig;
if(b)
*b = wt->_color_bBig;
*tcu = wt->_tcU;
*tcv = wt->_tcV;
*tcw = wt->_tcW;

@ -163,7 +163,7 @@ class SpellChecker():
"uncomment",
"undeformed",
"undistort", "undistortion",
"ungroup",
"ungroup", "ungrouped",
"unhide",
"unindent",
"unkeyed",

@ -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'

@ -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'}

@ -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()

@ -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

@ -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,15 +476,16 @@ 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);
int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id);
bool nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id);
void nodeClearActive(struct bNodeTree *ntree);
void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
@ -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);

@ -61,8 +61,8 @@ struct World;
void BKE_texture_free(struct Tex *t);
void init_colorband(struct ColorBand *coba, int rangetype);
struct ColorBand *add_colorband(int rangetype);
void init_colorband(struct ColorBand *coba, bool rangetype);
struct ColorBand *add_colorband(bool rangetype);
int do_colorband(const struct ColorBand *coba, float in, float out[4]);
void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
struct CBData *colorband_element_add(struct ColorBand *coba, float position);

@ -1152,7 +1152,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
{
CBData *ramp;
brush->paint_ramp = add_colorband(0);
brush->paint_ramp = add_colorband(false);
if (!brush->paint_ramp)
return 0;
ramp = brush->paint_ramp->data;
@ -1168,7 +1168,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
{
CBData *ramp;
brush->vel_ramp = add_colorband(0);
brush->vel_ramp = add_colorband(false);
if (!brush->vel_ramp)
return 0;
ramp = brush->vel_ramp->data;

@ -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) {

@ -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);

@ -1015,7 +1015,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);
}
}
@ -1049,7 +1049,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);
}
}

@ -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

@ -657,6 +657,85 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
return ret;
}
/* read old smoke cache from 2.64 */
static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
SmokeDomainSettings *sds = smd->domain;
if (sds->fluid) {
size_t res = sds->res[0]*sds->res[1]*sds->res[2];
float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
unsigned char *obstacles;
unsigned int out_len = (unsigned int)res * sizeof(float);
float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
int fluid_fields = smoke_get_data_flags(sds);
/* Part part of the new cache header */
sds->active_color[0] = 0.7f;
sds->active_color[1] = 0.7f;
sds->active_color[2] = 0.7f;
smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles);
ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
if (fluid_fields & SM_ACTIVE_HEAT)
{
ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
}
else
{
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
}
ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
ptcache_file_read(pf, &dt, 1, sizeof(float));
ptcache_file_read(pf, &dx, 1, sizeof(float));
MEM_freeN(tmp_array);
if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
int res = sds->res[0]*sds->res[1]*sds->res[2];
int res_big, res_big_array[3];
float *dens, *tcu, *tcv, *tcw;
unsigned int out_len = sizeof(float)*(unsigned int)res;
unsigned int out_len_big;
unsigned char *tmp_array_big;
smoke_turbulence_get_res(sds->wt, res_big_array);
res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
out_len_big = sizeof(float) * (unsigned int)res_big;
tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
MEM_freeN(tmp_array_big);
}
}
return 1;
}
static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
@ -671,7 +750,13 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
/* version header */
ptcache_file_read(pf, version, 4, sizeof(char));
if (strncmp(version, SMOKE_CACHE_VERSION, 4)) return 0;
if (strncmp(version, SMOKE_CACHE_VERSION, 4))
{
/* reset file pointer */
fseek(pf->fp, -4, SEEK_CUR);
return ptcache_smoke_read_old(pf, smoke_v);
}
/* fluid info */
ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
ptcache_file_read(pf, &active_fields, 1, sizeof(int));
@ -1362,7 +1447,7 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
newname += len;
}
if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
idname = (pid->ob->id.name+2);
idname = (pid->ob->id.name + 2);
/* convert chars to hex so they are always a valid filename */
while ('\0' != *idname) {
BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));

@ -148,7 +148,7 @@ void default_color_mapping(ColorMapping *colormap)
{
memset(colormap, 0, sizeof(ColorMapping));
init_colorband(&colormap->coba, 1);
init_colorband(&colormap->coba, true);
colormap->bright = 1.0;
colormap->contrast = 1.0;
@ -163,7 +163,7 @@ void default_color_mapping(ColorMapping *colormap)
/* ****************** COLORBAND ******************* */
void init_colorband(ColorBand *coba, int rangetype)
void init_colorband(ColorBand *coba, bool rangetype)
{
int a;
@ -205,7 +205,7 @@ void init_colorband(ColorBand *coba, int rangetype)
}
ColorBand *add_colorband(int rangetype)
ColorBand *add_colorband(bool rangetype)
{
ColorBand *coba;
@ -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);
}
@ -1285,7 +1285,7 @@ PointDensity *BKE_add_pointdensity(void)
pd->noise_depth = 1;
pd->noise_fac = 1.0f;
pd->noise_influence = TEX_PD_NOISE_STATIC;
pd->coba = add_colorband(1);
pd->coba = add_colorband(true);
pd->speed_scale = 1.0f;
pd->totpoints = 0;
pd->object = NULL;

@ -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);

@ -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

@ -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);

@ -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 (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)
sock->flag |= SOCK_DYNAMIC;
do_versions_socket_default_value_259(sock);
for (sock = ntree->outputs.first; sock; sock = sock->next)
sock->flag |= SOCK_DYNAMIC;
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

@ -2306,7 +2306,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Image *ima;
for (ima = main->image.first; ima; ima = ima->id.next)
if (strcmp(ima->name, "Compositor") == 0) {
strcpy(ima->id.name+2, "Viewer Node");
strcpy(ima->id.name + 2, "Viewer Node");
strcpy(ima->name, "Viewer Node");
}
}
@ -2495,11 +2495,11 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ima->gen_x = 256; ima->gen_y = 256;
ima->gen_type = 1;
if (0 == strncmp(ima->id.name+2, "Viewer Node", sizeof(ima->id.name) - 2)) {
if (0 == strncmp(ima->id.name + 2, "Viewer Node", sizeof(ima->id.name) - 2)) {
ima->source = IMA_SRC_VIEWER;
ima->type = IMA_TYPE_COMPOSITE;
}
if (0 == strncmp(ima->id.name+2, "Render Result", sizeof(ima->id.name) - 2)) {
if (0 == strncmp(ima->id.name + 2, "Render Result", sizeof(ima->id.name) - 2)) {
ima->source = IMA_SRC_VIEWER;
ima->type = IMA_TYPE_R_RESULT;
}

@ -74,6 +74,7 @@
#include <math.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@ -154,6 +155,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"
@ -165,6 +167,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"
@ -673,46 +682,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)
{
@ -724,18 +741,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))
@ -744,10 +762,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))
@ -763,12 +777,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
if (node->type==CMP_NODE_OUTPUT_FILE) {
/* inputs have own storage data */
for (sock=node->inputs.first; sock; sock=sock->next)
for (sock = node->inputs.first; sock; sock = sock->next)
writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage);
}
if (node->type==CMP_NODE_IMAGE) {
/* write extra socket info */
for (sock=node->outputs.first; sock; sock=sock->next)
for (sock = node->outputs.first; sock; sock = sock->next)
writestruct(wd, DATA, "NodeImageLayer", 1, sock->storage);
}
}
@ -776,11 +790,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)
@ -2538,7 +2551,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);
@ -2790,6 +2808,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;
@ -3204,6 +3334,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);
@ -3252,6 +3387,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;

@ -353,7 +353,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
size_t prim_poly_count = mpvc->getFaceCount();
size_t prim_loop_count = 0;
for(int index=0; index < prim_poly_count; index++) {
for (int index=0; index < prim_poly_count; index++) {
prim_loop_count += get_vertex_count(mpvc, index);
}

@ -178,7 +178,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
GroupObject *go = NULL;
Group *gr = ob->dup_group;
/* printf("group detected '%s'\n", gr->id.name+2); */
/* printf("group detected '%s'\n", gr->id.name + 2); */
for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) {
printf("\t%s\n", go->ob->id.name);
}

@ -143,7 +143,7 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh
Mesh *tmpmesh;
CustomDataMask mask = CD_MASK_MESH;
DerivedMesh *dm = NULL;
if(apply_modifiers) {
if (apply_modifiers) {
switch (export_mesh_type) {
case BC_MESH_TYPE_VIEW: {
dm = mesh_create_derived_view(scene, ob, mask);

@ -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;

@ -26,7 +26,9 @@
#include "PIL_time.h"
#include "BLI_utildefines.h"
extern "C" {
#include "BKE_node.h"
}
#include "COM_Converter.h"
#include "COM_NodeOperation.h"
@ -49,7 +51,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 +61,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
break;
}
}
#endif
/* initialize the CompositorContext */
if (rendering) {
@ -68,7 +73,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;
};

@ -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);
}

@ -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 (STREQ(sock->getbNodeSocket()->identifier, identifier)) {
*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 (STREQ(sock->getbNodeSocket()->identifier, identifier)) {
*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; }

@ -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,

@ -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"
@ -3073,3 +3075,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);
}

@ -767,7 +767,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
const unsigned char tcol[4] = {wcol->outline[0],
wcol->outline[1],
wcol->outline[2],
UCHAR_MAX / WIDGET_AA_JITTER};
wcol->outline[3] / WIDGET_AA_JITTER};
widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
@ -1184,7 +1184,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
but->drawstr[selend_tmp] = ch;
glColor3ubv((unsigned char *)wcol->item);
glColor4ubv((unsigned char *)wcol->item);
glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2);
}
}
@ -1224,7 +1224,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
}
glColor3ubv((unsigned char *)wcol->text);
glColor4ubv((unsigned char *)wcol->text);
uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs);
@ -1272,6 +1272,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
if (but == NULL)
@ -1311,12 +1312,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr);
}
widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect);
widget_draw_icon(but, ICON_DOT, dualset ? alpha : 0.25f, rect);
}
else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
int tmp = rect->xmin;
rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
widget_draw_icon(but, ICON_LAYER_USED, alpha, rect);
rect->xmin = tmp;
}
@ -1324,7 +1325,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
* and offset the text label to accommodate it */
if (but->flag & UI_HAS_ICON) {
widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect);
widget_draw_icon(but, but->icon + but->iconadd, alpha, rect);
/* icons default draw 0.8f x height */
rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
@ -1342,7 +1343,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rcti temp = *rect;
temp.xmin = temp.xmax - BLI_rcti_size_y(rect);
widget_draw_icon(but, ICON_X, 1.0f, &temp);
widget_draw_icon(but, ICON_X, alpha, &temp);
}
/* always draw text for textbutton cursor */
@ -1379,12 +1380,12 @@ static struct uiWidgetStateColors wcol_state_colors = {
};
/* uiWidgetColors
* float outline[3];
* float inner[4];
* float inner_sel[4];
* float item[3];
* float text[3];
* float text_sel[3];
* char outline[3];
* char inner[4];
* char inner_sel[4];
* char item[3];
* char text[3];
* char text_sel[3];
*
* short shaded;
* float shadetop, shadedown;
@ -2873,12 +2874,7 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
/* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
* over the top to indicate disabled buttons */
/* XXX, this doesnt work right since the color applies to buttons outside the box too. */
glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
copy_v3_v3_char(wcol->inner, old_col);
}
@ -2941,24 +2937,6 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
}
static void widget_disabled(const rcti *rect)
{
float col[4];
glEnable(GL_BLEND);
/* can't use theme TH_BACK or TH_PANEL... undefined */
glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
glColor4f(col[0], col[1], col[2], 0.5f);
/* need -1 and +1 to make it work right for aligned buttons,
* but problem may be somewhere else? */
glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
glDisable(GL_BLEND);
}
static uiWidgetType *widget_type(uiWidgetTypeEnum type)
{
bTheme *btheme = UI_GetTheme();
@ -3171,6 +3149,23 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
return roundbox;
}
/* put all widget colors on half alpha, use local storage */
static void ui_widget_color_disabled(uiWidgetType *wt)
{
static uiWidgetColors wcol_theme_s;
wcol_theme_s = *wt->wcol_theme;
wcol_theme_s.outline[3] *= 0.5;
wcol_theme_s.inner[3] *= 0.5;
wcol_theme_s.inner_sel[3] *= 0.5;
wcol_theme_s.item[3] *= 0.5;
wcol_theme_s.text[3] *= 0.5;
wcol_theme_s.text_sel[3] *= 0.5;
wt->wcol_theme = &wcol_theme_s;
}
/* conversion from old to new buttons, so still messy */
void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
{
@ -3367,30 +3362,47 @@ 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);
}
}
if (wt) {
rcti disablerect = *rect; /* rect gets clipped smaller for text */
//rcti disablerect = *rect; /* rect gets clipped smaller for text */
int roundboxalign, state;
bool disabled = FALSE;
roundboxalign = widget_roundbox_set(but, rect);
state = but->flag;
if (but->editstr) state |= UI_TEXTINPUT;
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
if (but->dt != UI_EMBOSSP)
disabled = TRUE;
if (disabled)
ui_widget_color_disabled(wt);
wt->state(wt, state);
if (wt->custom)
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
else if (wt->draw)
wt->draw(&wt->wcol, rect, state, roundboxalign);
wt->text(fstyle, &wt->wcol, but, rect);
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
if (but->dt != UI_EMBOSSP)
widget_disabled(&disablerect);
if (disabled)
glEnable(GL_BLEND);
wt->text(fstyle, &wt->wcol, but, rect);
if (disabled)
glDisable(GL_BLEND);
// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
// if (but->dt != UI_EMBOSSP)
// widget_disabled(&disablerect);
}
}
@ -3474,7 +3486,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
}
glColor3ubv((unsigned char *)wt->wcol.text);
glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, rect, name);
/* part text right aligned */
@ -3541,9 +3553,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
glDisable(GL_BLEND);
if (state == UI_ACTIVE)
glColor3ubv((unsigned char *)wt->wcol.text);
glColor4ubv((unsigned char *)wt->wcol.text);
else
glColor3ubv((unsigned char *)wt->wcol.text_sel);
glColor4ubv((unsigned char *)wt->wcol.text_sel);
uiStyleFontDraw(fstyle, &trect, name);
}

@ -395,6 +395,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:
@ -961,7 +963,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 */
@ -970,6 +972,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 */
@ -1545,7 +1548,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
}
if (U.coba_weight.tot == 0)
init_colorband(&U.coba_weight, 1);
init_colorband(&U.coba_weight, true);
}
if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 11)) {
bTheme *btheme;
@ -2174,6 +2177,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 */

@ -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,28 @@ 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 = BLI_rctf_cent_x(&v2d->cur);
if (y) *y = BLI_rctf_cent_y(&v2d->cur);
}
void UI_view2d_setcenter(struct View2D *v2d, float x, float y)
{
/* get delta from current center */
float dx = x - BLI_rctf_cent_x(&v2d->cur);
float dy = y - BLI_rctf_cent_y(&v2d->cur);
/* add to cur */
BLI_rctf_translate(&v2d->cur, dx, 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

@ -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;
}

@ -604,7 +604,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
list = &pchan->constraints;
else {
//if (G.debug & G_DEBUG)
//printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name+2 : "<None>");
//printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name + 2 : "<None>");
return NULL;
}
}

@ -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);
}
}

@ -385,7 +385,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;
}
}
@ -487,7 +487,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);
}
}

@ -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);
}
}

@ -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;

@ -2321,7 +2321,7 @@ void logic_buttons(bContext *C, ARegion *ar)
uiItemR(split, &settings_ptr, "show_state_panel", UI_ITEM_R_NO_BG, "", ICON_DISCLOSURE_TRI_RIGHT);
row = uiLayoutRow(split, TRUE);
uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@ -2418,7 +2418,7 @@ void logic_buttons(bContext *C, ARegion *ar)
if ((ob->scavisflag & OB_VIS_SENS) == 0) continue;
row = uiLayoutRow(layout, TRUE);
uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@ -2489,7 +2489,7 @@ void logic_buttons(bContext *C, ARegion *ar)
}
row = uiLayoutRow(layout, TRUE);
uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);

File diff suppressed because it is too large Load Diff

@ -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");
if (sock->typeinfo->interface_draw) {
uiItemS(layout);
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");

@ -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

@ -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)

@ -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);

@ -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 *********************** */
@ -107,7 +108,7 @@ static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocke
/* check for same types */
if (sock->type == sock_target->type) {
if (strcmp(sock->name, sock_target->name) == 0)
if (STREQ(sock->name, sock_target->name))
return sock;
}
}
@ -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.0f + 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);
}
}

@ -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);
@ -386,9 +359,10 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
node = node_under_mouse_select(snode->edittree, mx, my);
if (node) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
node_deselect(tnode);
node_select(node);
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
nodeSetSelected(tnode, false);
}
nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
selected = 1;
}
@ -477,13 +451,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 +537,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 +609,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 +655,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 +699,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,30 @@ 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);
}
@ -201,7 +207,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
continue;
if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
bNodeLink *link = sock_prev->link;
if (link && link->fromnode) {
@ -209,9 +215,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 +239,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 +270,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 +291,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 +318,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 +335,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 +406,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 +500,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 +522,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 +571,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 +606,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 (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (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");

@ -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;
}

@ -5992,6 +5992,15 @@ static void draw_bb_quadric(BoundBox *bb, char type)
glScalef(radius, radius, 2.0f * size[2]);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
}
else if (type == OB_BOUND_CAPSULE) {
float radius = size[0] > size[1] ? size[0] : size[1];
float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
gluCylinder(qobj, radius, radius, length, 8, 1);
gluSphere(qobj, radius, 8, 4);
glTranslatef(0.0, 0.0, length);
gluSphere(qobj, radius, 8, 4);
}
glPopMatrix();
gluDeleteQuadric(qobj);

@ -2041,11 +2041,11 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
(dob->type == OB_DUPLIGROUP && dob->animated) ||
!(bb_tmp = BKE_object_boundbox_get(dob->ob)))
{
// printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2);
// printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
use_displist = FALSE;
}
else {
// printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2);
// printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
bb = *bb_tmp; /* must make a copy */
/* disable boundbox check for list creation */

@ -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);
}
}

@ -1264,7 +1264,7 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
static Material *gpu_active_node_material(Material *ma)
{
if (ma && ma->use_nodes && ma->nodetree) {
bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
if (node)
return (Material *)node->id;

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