forked from bartvdbraak/blender
svn merge ^/trunk/blender -r55372:55392
This commit is contained in:
commit
ae25aa2210
23
doc/python_api/examples/bpy.types.NodeTree.py
Normal file
23
doc/python_api/examples/bpy.types.NodeTree.py
Normal file
@ -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__)
|
||||
|
159
release/scripts/templates_py/custom_nodes.py
Normal file
159
release/scripts/templates_py/custom_nodes.py
Normal file
@ -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, ¢er[0], ¢er[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
Loading…
Reference in New Issue
Block a user