/* * 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" #include "util_vector.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(); static bool is_float3(Type type); }; /* Node Type */ struct NodeType { enum Type { NONE, SHADER }; explicit NodeType(Type type = NONE); ~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); const SocketType *find_input(ustring name) const; const SocketType *find_output(ustring name) const; typedef Node *(*CreateFunc)(const NodeType *type); ustring name; Type type; std::vector inputs; std::vector outputs; CreateFunc create; static NodeType *add(const char *name, CreateFunc create, Type type = NONE); 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