From ec51175f1fd6c91d53b0d24daccfd5cc9bddf59d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 7 May 2016 19:47:37 +0200 Subject: Code refactor: add generic Cycles node infrastructure. Differential Revision: https://developer.blender.org/D2016 --- intern/cycles/graph/CMakeLists.txt | 22 +++ intern/cycles/graph/node.cpp | 354 +++++++++++++++++++++++++++++++++++++ intern/cycles/graph/node.h | 90 ++++++++++ intern/cycles/graph/node_enum.h | 48 +++++ intern/cycles/graph/node_type.cpp | 190 ++++++++++++++++++++ intern/cycles/graph/node_type.h | 252 ++++++++++++++++++++++++++ 6 files changed, 956 insertions(+) create mode 100644 intern/cycles/graph/CMakeLists.txt create mode 100644 intern/cycles/graph/node.cpp create mode 100644 intern/cycles/graph/node.h create mode 100644 intern/cycles/graph/node_enum.h create mode 100644 intern/cycles/graph/node_type.cpp create mode 100644 intern/cycles/graph/node_type.h (limited to 'intern/cycles/graph') diff --git a/intern/cycles/graph/CMakeLists.txt b/intern/cycles/graph/CMakeLists.txt new file mode 100644 index 00000000000..401bdb47392 --- /dev/null +++ b/intern/cycles/graph/CMakeLists.txt @@ -0,0 +1,22 @@ + +set(INC + . + ../util +) + +set(SRC + node.cpp + node_type.cpp +) + +set(SRC_HEADERS + node.h + node_enum.h + node_type.h +) + +include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) + +add_library(cycles_graph ${SRC} ${SRC_HEADERS}) + diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp new file mode 100644 index 00000000000..d9a6bde4fcd --- /dev/null +++ b/intern/cycles/graph/node.cpp @@ -0,0 +1,354 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "node.h" +#include "node_type.h" + +#include "util_foreach.h" +#include "util_param.h" +#include "util_transform.h" + +CCL_NAMESPACE_BEGIN + +/* Node Type */ + +Node::Node(const NodeType *type_, ustring name_) +: name(name_), type(type_) +{ + assert(type); + + /* assign non-empty name, convenient for debugging */ + if(name.empty()) { + name = type->name; + } + + /* initialize default values */ + typedef unordered_map map_type; + foreach(const map_type::value_type& it, type->inputs) { + const SocketType& socket = it.second; + const void *src = socket.default_value; + void *dst = ((char*)this) + socket.struct_offset; + memcpy(dst, src, socket.size()); + } +} + +Node::~Node() +{ +} + +template +static T& get_socket_value(const Node *node, const SocketType& socket) +{ + return (T&)*(((char*)node) + socket.struct_offset); +} + +static bool is_socket_float3(const SocketType& socket) +{ + return socket.type == SocketType::COLOR || + socket.type == SocketType::POINT || + socket.type == SocketType::VECTOR || + socket.type == SocketType::NORMAL; +} + +static bool is_socket_array_float3(const SocketType& socket) +{ + return socket.type == SocketType::COLOR_ARRAY || + socket.type == SocketType::POINT_ARRAY || + socket.type == SocketType::VECTOR_ARRAY || + socket.type == SocketType::NORMAL_ARRAY; +} + +/* set values */ +void Node::set(const SocketType& input, bool value) +{ + assert(input.type == SocketType::BOOLEAN); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, int value) +{ + assert((input.type == SocketType::INT || input.type == SocketType::ENUM)); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, float value) +{ + assert(input.type == SocketType::FLOAT); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, float2 value) +{ + assert(input.type == SocketType::FLOAT); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, float3 value) +{ + assert(is_socket_float3(input)); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, ustring value) +{ + if(input.type == SocketType::STRING) { + get_socket_value(this, input) = value; + } + else if(input.type == SocketType::ENUM) { + const NodeEnum& enm = *input.enum_values; + if(enm.exists(value)) { + get_socket_value(this, input) = enm[value]; + } + else { + assert(0); + } + } + else { + assert(0); + } +} + +void Node::set(const SocketType& input, const Transform& value) +{ + assert(input.type == SocketType::TRANSFORM); + get_socket_value(this, input) = value; +} + +void Node::set(const SocketType& input, Node *value) +{ + assert(input.type == SocketType::TRANSFORM); + get_socket_value(this, input) = value; +} + +/* set array values */ +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::BOOLEAN_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::INT_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::FLOAT_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::FLOAT_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(is_socket_array_float3(input)); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::STRING_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array& value) +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + get_socket_value >(this, input).steal_data(value); +} + +/* get values */ +bool Node::get_bool(const SocketType& input) const +{ + assert(input.type == SocketType::BOOLEAN); + return get_socket_value(this, input); +} + +int Node::get_int(const SocketType& input) const +{ + assert(input.type == SocketType::INT || input.type == SocketType::ENUM); + return get_socket_value(this, input); +} + +float Node::get_float(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT); + return get_socket_value(this, input); +} + +float2 Node::get_float2(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT); + return get_socket_value(this, input); +} + +float3 Node::get_float3(const SocketType& input) const +{ + assert(is_socket_float3(input)); + return get_socket_value(this, input); +} + +ustring Node::get_string(const SocketType& input) const +{ + if(input.type == SocketType::STRING) { + return get_socket_value(this, input); + } + else if(input.type == SocketType::ENUM) { + const NodeEnum& enm = *input.enum_values; + int intvalue = get_socket_value(this, input); + return (enm.exists(intvalue)) ? enm[intvalue] : ustring(); + } + else { + assert(0); + return ustring(); + } +} + +Transform Node::get_transform(const SocketType& input) const +{ + assert(input.type == SocketType::TRANSFORM); + return get_socket_value(this, input); +} + +Node *Node::get_node(const SocketType& input) const +{ + assert(input.type == SocketType::NODE); + return get_socket_value(this, input); +} + +/* get array values */ +const array& Node::get_bool_array(const SocketType& input) const +{ + assert(input.type == SocketType::BOOLEAN_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_int_array(const SocketType& input) const +{ + assert(input.type == SocketType::INT_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_float_array(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_float2_array(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_float3_array(const SocketType& input) const +{ + assert(is_socket_array_float3(input)); + return get_socket_value >(this, input); +} + +const array& Node::get_string_array(const SocketType& input) const +{ + assert(input.type == SocketType::STRING_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_transform_array(const SocketType& input) const +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + return get_socket_value >(this, input); +} + +const array& Node::get_node_array(const SocketType& input) const +{ + assert(input.type == SocketType::NODE_ARRAY); + return get_socket_value >(this, input); +} + +/* default values */ +bool Node::has_default_value(const SocketType& input) const +{ + const void *src = input.default_value; + void *dst = &get_socket_value(this, input); + return memcmp(dst, src, input.size()) == 0; +} + +template +static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket) +{ + const array* a = (const array*)(((char*)node) + socket.struct_offset); + const array* b = (const array*)(((char*)other) + socket.struct_offset); + return *a == *b; +} + +/* modified */ +bool Node::modified(const Node& other) +{ + assert(type == other.type); + + typedef unordered_map map_type; + foreach(const map_type::value_type& it, type->inputs) { + const SocketType& socket = it.second; + + if(socket.is_array()) { + bool equal = true; + + switch(socket.type) + { + case SocketType::BOOLEAN_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::FLOAT_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::INT_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::COLOR_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::VECTOR_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::POINT_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::NORMAL_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::POINT2_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::STRING_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::TRANSFORM_ARRAY: equal = is_array_equal(this, &other, socket); break; + case SocketType::NODE_ARRAY: equal = is_array_equal(this, &other, socket); break; + default: assert(0); break; + } + + if(!equal) { + return true; + } + } + else { + const void *a = ((char*)this) + socket.struct_offset; + const void *b = ((char*)&other) + socket.struct_offset; + if(memcmp(a, b, socket.size()) != 0) { + return true; + } + } + } + + return false; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h new file mode 100644 index 00000000000..33971fa714a --- /dev/null +++ b/intern/cycles/graph/node.h @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "node_type.h" + +#include "util_map.h" +#include "util_param.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +struct Node; +struct NodeType; +struct Transform; + +/* Node */ + +struct Node +{ + explicit Node(const NodeType *type, ustring name = ustring()); + virtual ~Node(); + + /* set values */ + void set(const SocketType& input, bool value); + void set(const SocketType& input, int value); + void set(const SocketType& input, float value); + void set(const SocketType& input, float2 value); + void set(const SocketType& input, float3 value); + void set(const SocketType& input, ustring value); + void set(const SocketType& input, const Transform& value); + void set(const SocketType& input, Node *value); + + /* set array values. the memory from the input array will taken over + * by the node and the input array will be empty after return */ + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + void set(const SocketType& input, array& value); + + /* get values */ + bool get_bool(const SocketType& input) const; + int get_int(const SocketType& input) const; + float get_float(const SocketType& input) const; + float2 get_float2(const SocketType& input) const; + float3 get_float3(const SocketType& input) const; + ustring get_string(const SocketType& input) const; + Transform get_transform(const SocketType& input) const; + Node *get_node(const SocketType& input) const; + + /* get array values */ + const array& get_bool_array(const SocketType& input) const; + const array& get_int_array(const SocketType& input) const; + const array& get_float_array(const SocketType& input) const; + const array& get_float2_array(const SocketType& input) const; + const array& get_float3_array(const SocketType& input) const; + const array& get_string_array(const SocketType& input) const; + const array& get_transform_array(const SocketType& input) const; + const array& get_node_array(const SocketType& input) const; + + /* default values */ + bool has_default_value(const SocketType& input) const; + + /* modified */ + bool modified(const Node& other); + + ustring name; + const NodeType *type; +}; + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_enum.h b/intern/cycles/graph/node_enum.h new file mode 100644 index 00000000000..2bae531c036 --- /dev/null +++ b/intern/cycles/graph/node_enum.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "util_map.h" +#include "util_param.h" + +CCL_NAMESPACE_BEGIN + +/* Enum + * + * Utility class for enum values. */ + +struct NodeEnum { + bool empty() const { return left.empty(); } + void insert(const char *x, int y) { + left[ustring(x)] = y; + right[y] = ustring(x); + } + + bool exists(ustring x) const { return left.find(x) != left.end(); } + bool exists(int y) const { return right.find(y) != right.end(); } + + int operator[](const char *x) const { return left.find(ustring(x))->second; } + int operator[](ustring x) const { return left.find(x)->second; } + ustring operator[](int y) const { return right.find(y)->second; } + +private: + unordered_map left; + unordered_map right; +}; + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp new file mode 100644 index 00000000000..dc879655d7f --- /dev/null +++ b/intern/cycles/graph/node_type.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "node_type.h" +#include "util_foreach.h" +#include "util_transform.h" + +CCL_NAMESPACE_BEGIN + +/* Node Socket Type */ + +size_t SocketType::size() const +{ + return size(type); +} + +bool SocketType::is_array() const +{ + return (type >= BOOLEAN_ARRAY); +} + +size_t SocketType::size(Type type) +{ + switch(type) + { + case UNDEFINED: return 0; + + case BOOLEAN: return sizeof(bool); + case FLOAT: return sizeof(float); + case INT: return sizeof(int); + case COLOR: return sizeof(float3); + case VECTOR: return sizeof(float3); + case POINT: return sizeof(float3); + case NORMAL: return sizeof(float3); + case POINT2: return sizeof(float2); + case CLOSURE: return 0; + case STRING: return sizeof(ustring); + case ENUM: return sizeof(int); + case TRANSFORM: return sizeof(Transform); + case NODE: return sizeof(void*); + + case BOOLEAN_ARRAY: return sizeof(array); + case FLOAT_ARRAY: return sizeof(array); + case INT_ARRAY: return sizeof(array); + case COLOR_ARRAY: return sizeof(array); + case VECTOR_ARRAY: return sizeof(array); + case POINT_ARRAY: return sizeof(array); + case NORMAL_ARRAY: return sizeof(array); + case POINT2_ARRAY: return sizeof(array); + case STRING_ARRAY: return sizeof(array); + case TRANSFORM_ARRAY: return sizeof(array); + case NODE_ARRAY: return sizeof(array); + } + + assert(0); + return 0; +} + +size_t SocketType::max_size() +{ + return sizeof(Transform); +} + +void *SocketType::zero_default_value() +{ + static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}; + return &zero_transform; +} + +ustring SocketType::type_name(Type type) +{ + static ustring names[] = { + ustring("undefined"), + + ustring("boolean"), + ustring("float"), + ustring("int"), + ustring("color"), + ustring("vector"), + ustring("point"), + ustring("normal"), + ustring("point2"), + ustring("closure"), + ustring("string"), + ustring("enum"), + ustring("transform"), + ustring("node"), + + ustring("array_boolean"), + ustring("array_float"), + ustring("array_int"), + ustring("array_color"), + ustring("array_vector"), + ustring("array_point"), + ustring("array_normal"), + ustring("array_point2"), + ustring("array_string"), + ustring("array_transform"), + ustring("array_node")}; + + return names[(int)type]; +} + +/* Node Type */ + +NodeType::NodeType() +{ +} + +NodeType::~NodeType() +{ +} + +void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, + const void *default_value, const NodeEnum *enum_values, + const NodeType **node_type, int flags, int extra_flags) +{ + SocketType socket; + socket.name = name; + socket.ui_name = ui_name; + socket.type = type; + socket.struct_offset = struct_offset; + socket.default_value = default_value; + socket.enum_values = enum_values; + socket.node_type = node_type; + socket.flags = flags | extra_flags; + inputs[name] = socket; +} + +void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type) +{ + SocketType socket; + socket.name = name; + socket.ui_name = ui_name; + socket.type = type; + socket.struct_offset = 0; + socket.default_value = NULL; + socket.enum_values = NULL; + socket.node_type = NULL; + socket.flags = SocketType::LINKABLE; + outputs[name] = socket; +} + +/* Node Type Registry */ + +unordered_map& NodeType::types() +{ + static unordered_map _types; + return _types; +} + +NodeType *NodeType::add(const char *name_, CreateFunc create_) +{ + ustring name(name_); + + if(types().find(name) != types().end()) { + fprintf(stderr, "Node type %s registered twice!\n", name_); + assert(0); + return NULL; + } + + types()[name] = NodeType(); + + NodeType *type = &types()[name]; + type->name = name; + type->create = create_; + return type; +} + +const NodeType *NodeType::find(ustring name) +{ + unordered_map::iterator it = types().find(name); + return (it == types().end()) ? NULL : &it->second; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h new file mode 100644 index 00000000000..82ddd29da33 --- /dev/null +++ b/intern/cycles/graph/node_type.h @@ -0,0 +1,252 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "node_enum.h" + +#include "util_map.h" +#include "util_param.h" +#include "util_string.h" + +CCL_NAMESPACE_BEGIN + +struct Node; +struct NodeType; + +/* Socket Type */ + +struct SocketType +{ + enum Type + { + UNDEFINED, + + BOOLEAN, + FLOAT, + INT, + COLOR, + VECTOR, + POINT, + NORMAL, + POINT2, + CLOSURE, + STRING, + ENUM, + TRANSFORM, + NODE, + + BOOLEAN_ARRAY, + FLOAT_ARRAY, + INT_ARRAY, + COLOR_ARRAY, + VECTOR_ARRAY, + POINT_ARRAY, + NORMAL_ARRAY, + POINT2_ARRAY, + STRING_ARRAY, + TRANSFORM_ARRAY, + NODE_ARRAY, + }; + + enum Flags { + LINKABLE = (1 << 0), + ANIMATABLE = (1 << 1), + + SVM_INTERNAL = (1 << 2), + OSL_INTERNAL = (1 << 3), + INTERNAL = (1 << 2) | (1 << 3), + + LINK_TEXTURE_GENERATED = (1 << 4), + LINK_TEXTURE_UV = (1 << 5), + LINK_INCOMING = (1 << 6), + LINK_NORMAL = (1 << 7), + LINK_POSITION = (1 << 8), + LINK_TANGENT = (1 << 9), + DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) + }; + + ustring name; + Type type; + int struct_offset; + const void *default_value; + const NodeEnum *enum_values; + const NodeType **node_type; + int flags; + ustring ui_name; + + size_t size() const; + bool is_array() const; + static size_t size(Type type); + static size_t max_size(); + static ustring type_name(Type type); + static void *zero_default_value(); +}; + +/* Node Type */ + +struct NodeType +{ + explicit NodeType(); + ~NodeType(); + + void register_input(ustring name, ustring ui_name, SocketType::Type type, + int struct_offset, const void *default_value, + const NodeEnum *enum_values = NULL, + const NodeType **node_type = NULL, + int flags = 0, int extra_flags = 0); + void register_output(ustring name, ustring ui_name, SocketType::Type type); + + typedef Node *(*CreateFunc)(const NodeType *type); + typedef unordered_map SocketMap; + + ustring name; + SocketMap inputs; + SocketMap outputs; + CreateFunc create; + + static NodeType *add(const char *name, CreateFunc create); + static const NodeType *find(ustring name); + static unordered_map& types(); +}; + +/* Node Definition Macros */ + +#define NODE_DECLARE \ +template \ +static const NodeType *register_type(); \ +static Node *create(const NodeType *type); \ +static const NodeType *node_type; + +#define NODE_DEFINE(structname) \ +const NodeType *structname::node_type = structname::register_type(); \ +Node *structname::create(const NodeType*) { return new structname(); } \ +template \ +const NodeType *structname::register_type() + +/* Sock Definition Macros */ + +#define SOCKET_OFFSETOF(T, name) (((char *)&(((T *)1)->name)) - (char *)1) +#define SOCKET_SIZEOF(T, name) (sizeof(((T *)1)->name)) +#define SOCKET_DEFINE(name, ui_name, default_value, datatype, TYPE, flags, ...) \ + { \ + static datatype defval = default_value; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(datatype)); \ + type->register_input(ustring(#name), ustring(ui_name), TYPE, SOCKET_OFFSETOF(T, name), &defval, NULL, NULL, flags, ##__VA_ARGS__); \ + } + +#define SOCKET_BOOLEAN(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, 0, ##__VA_ARGS__) +#define SOCKET_INT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, 0, ##__VA_ARGS__) +#define SOCKET_FLOAT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, 0, ##__VA_ARGS__) +#define SOCKET_COLOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, 0, ##__VA_ARGS__) +#define SOCKET_VECTOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, 0, ##__VA_ARGS__) +#define SOCKET_POINT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, 0, ##__VA_ARGS__) +#define SOCKET_NORMAL(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, 0, ##__VA_ARGS__) +#define SOCKET_POINT2(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float2, SocketType::POINT2, 0, ##__VA_ARGS__) +#define SOCKET_STRING(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, 0, ##__VA_ARGS__) +#define SOCKET_TRANSFORM(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, Transform, SocketType::TRANSFORM, 0, ##__VA_ARGS__) +#define SOCKET_ENUM(name, ui_name, values, default_value, ...) \ + { \ + static int defval = default_value; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(int)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::ENUM, SOCKET_OFFSETOF(T, name), &defval, &values, NULL, ##__VA_ARGS__); \ + } +#define SOCKET_NODE(name, ui_name, node_type, ...) \ + { \ + static Node *defval = NULL; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \ + } + +#define SOCKET_BOOLEAN_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::BOOLEAN_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_INT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::INT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::FLOAT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_COLOR_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::COLOR_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_VECTOR_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::VECTOR_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_POINT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::POINT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_NORMAL_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::NORMAL_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_POINT2_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::POINT2_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_STRING_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::STRING_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_TRANSFORM_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array, SocketType::TRANSFORM_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_NODE_ARRAY(name, ui_name, node_type, ...) \ + { \ + static Node *defval = NULL; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE_ARRAY, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \ + } + +#define SOCKET_IN_BOOLEAN(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_INT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_FLOAT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_COLOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_VECTOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_POINT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_NORMAL(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_STRING(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_CLOSURE(name, ui_name, ...) \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::CLOSURE, 0, NULL, NULL, NULL, SocketType::LINKABLE, ##__VA_ARGS__) + +#define SOCKET_OUT_BOOLEAN(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::BOOLEAN); } +#define SOCKET_OUT_INT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::INT); } +#define SOCKET_OUT_FLOAT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::FLOAT); } +#define SOCKET_OUT_COLOR(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::COLOR); } +#define SOCKET_OUT_VECTOR(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::VECTOR); } +#define SOCKET_OUT_POINT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::POINT); } +#define SOCKET_OUT_NORMAL(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::NORMAL); } +#define SOCKET_OUT_CLOSURE(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::CLOSURE); } +#define SOCKET_OUT_STRING(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::STRING); } +#define SOCKET_OUT_ENUM(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::ENUM); } + +CCL_NAMESPACE_END + -- cgit v1.2.3