Nodes: add internal node zone type
The goal is to reduce redundancy by abstracting over the different types of node tree zones. This makes it easier to add new zone types and makes the intend of code more clear. For example, now it is more obvious what code deals with zones in general and what does simulation specific things. Pull Request: https://projects.blender.org/blender/blender/pulls/112531
This commit is contained in:
@@ -322,6 +322,44 @@ extern bNodeTreeType NodeTreeTypeUndefined;
|
||||
extern bNodeType NodeTypeUndefined;
|
||||
extern bNodeSocketType NodeSocketTypeUndefined;
|
||||
|
||||
/**
|
||||
* Contains information about a specific kind of zone (e.g. simulation or repeat zone in geometry
|
||||
* nodes). This allows writing code that works for all kinds of zones automatically, reducing
|
||||
* redundancy and the amount of boilerplate needed when adding a new zone type.
|
||||
*/
|
||||
class bNodeZoneType {
|
||||
public:
|
||||
std::string input_idname;
|
||||
std::string output_idname;
|
||||
int input_type;
|
||||
int output_type;
|
||||
int theme_id;
|
||||
|
||||
virtual ~bNodeZoneType() = default;
|
||||
|
||||
virtual const int &get_corresponding_output_id(const bNode &input_bnode) const = 0;
|
||||
|
||||
int &get_corresponding_output_id(bNode &input_bnode) const
|
||||
{
|
||||
return const_cast<int &>(
|
||||
this->get_corresponding_output_id(const_cast<const bNode &>(input_bnode)));
|
||||
}
|
||||
|
||||
const bNode *get_corresponding_input(const bNodeTree &tree, const bNode &output_bnode) const;
|
||||
bNode *get_corresponding_input(bNodeTree &tree, const bNode &output_bnode) const;
|
||||
|
||||
const bNode *get_corresponding_output(const bNodeTree &tree, const bNode &input_bnode) const;
|
||||
bNode *get_corresponding_output(bNodeTree &tree, const bNode &input_bnode) const;
|
||||
};
|
||||
|
||||
void register_node_zone_type(const bNodeZoneType &zone_type);
|
||||
|
||||
Span<const bNodeZoneType *> all_zone_types();
|
||||
Span<int> all_zone_node_types();
|
||||
Span<int> all_zone_input_node_types();
|
||||
Span<int> all_zone_output_node_types();
|
||||
const bNodeZoneType *zone_type_by_node_type(const int node_type);
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
#define NODE_STORAGE_FUNCS(StorageT) \
|
||||
|
||||
@@ -285,26 +285,10 @@ struct ToposortNodeState {
|
||||
static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, bNode &node)
|
||||
{
|
||||
Vector<const bNode *> origin_nodes;
|
||||
if (node.type == GEO_NODE_SIMULATION_OUTPUT) {
|
||||
for (const bNode *sim_input_node :
|
||||
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeSimulationInput")))
|
||||
{
|
||||
const auto &storage = *static_cast<const NodeGeometrySimulationInput *>(
|
||||
sim_input_node->storage);
|
||||
if (storage.output_node_id == node.identifier) {
|
||||
origin_nodes.append(sim_input_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_OUTPUT) {
|
||||
for (const bNode *repeat_input_node :
|
||||
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeRepeatInput")))
|
||||
{
|
||||
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(
|
||||
repeat_input_node->storage);
|
||||
if (storage.output_node_id == node.identifier) {
|
||||
origin_nodes.append(repeat_input_node);
|
||||
}
|
||||
if (all_zone_output_node_types().contains(node.type)) {
|
||||
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
|
||||
if (const bNode *input_node = zone_type.get_corresponding_input(ntree, node)) {
|
||||
origin_nodes.append(input_node);
|
||||
}
|
||||
}
|
||||
return origin_nodes;
|
||||
@@ -313,16 +297,10 @@ static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, b
|
||||
static Vector<const bNode *> get_implicit_target_nodes(const bNodeTree &ntree, bNode &node)
|
||||
{
|
||||
Vector<const bNode *> target_nodes;
|
||||
if (node.type == GEO_NODE_SIMULATION_INPUT) {
|
||||
const auto &storage = *static_cast<const NodeGeometrySimulationInput *>(node.storage);
|
||||
if (const bNode *sim_output_node = ntree.node_by_id(storage.output_node_id)) {
|
||||
target_nodes.append(sim_output_node);
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_INPUT) {
|
||||
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(node.storage);
|
||||
if (const bNode *repeat_output_node = ntree.node_by_id(storage.output_node_id)) {
|
||||
target_nodes.append(repeat_output_node);
|
||||
if (all_zone_input_node_types().contains(node.type)) {
|
||||
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
|
||||
if (const bNode *output_node = zone_type.get_corresponding_output(ntree, node)) {
|
||||
target_nodes.append(output_node);
|
||||
}
|
||||
}
|
||||
return target_nodes;
|
||||
|
||||
@@ -588,19 +588,9 @@ class NodeTreeMainUpdater {
|
||||
}
|
||||
}
|
||||
/* Check paired simulation zone nodes. */
|
||||
if (node.type == GEO_NODE_SIMULATION_INPUT) {
|
||||
const NodeGeometrySimulationInput *data = static_cast<const NodeGeometrySimulationInput *>(
|
||||
node.storage);
|
||||
if (const bNode *output_node = ntree.node_by_id(data->output_node_id)) {
|
||||
if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type == GEO_NODE_REPEAT_INPUT) {
|
||||
const NodeGeometryRepeatInput *data = static_cast<const NodeGeometryRepeatInput *>(
|
||||
node.storage);
|
||||
if (const bNode *output_node = ntree.node_by_id(data->output_node_id)) {
|
||||
if (all_zone_input_node_types().contains(node.type)) {
|
||||
const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
|
||||
if (const bNode *output_node = zone_type.get_corresponding_output(ntree, node)) {
|
||||
if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,10 +32,13 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
|
||||
bNodeTreeZones &owner,
|
||||
Map<const bNode *, bNodeTreeZone *> &r_zone_by_inout_node)
|
||||
{
|
||||
const Span<const bNodeZoneType *> zone_types = all_zone_types();
|
||||
|
||||
Vector<std::unique_ptr<bNodeTreeZone>> zones;
|
||||
Vector<const bNode *> zone_output_nodes;
|
||||
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeSimulationOutput"));
|
||||
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeRepeatOutput"));
|
||||
for (const bNodeZoneType *zone_type : zone_types) {
|
||||
zone_output_nodes.extend(tree.nodes_by_type(zone_type->output_idname));
|
||||
}
|
||||
for (const bNode *node : zone_output_nodes) {
|
||||
auto zone = std::make_unique<bNodeTreeZone>();
|
||||
zone->owner = &owner;
|
||||
@@ -44,21 +47,13 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
|
||||
r_zone_by_inout_node.add(node, zone.get());
|
||||
zones.append_and_get_index(std::move(zone));
|
||||
}
|
||||
for (const bNode *node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
|
||||
const auto &storage = *static_cast<NodeGeometrySimulationInput *>(node->storage);
|
||||
if (const bNode *sim_output_node = tree.node_by_id(storage.output_node_id)) {
|
||||
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(sim_output_node, nullptr)) {
|
||||
zone->input_node = node;
|
||||
r_zone_by_inout_node.add(node, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const bNode *node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
|
||||
const auto &storage = *static_cast<NodeGeometryRepeatInput *>(node->storage);
|
||||
if (const bNode *repeat_output_node = tree.node_by_id(storage.output_node_id)) {
|
||||
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(repeat_output_node, nullptr)) {
|
||||
zone->input_node = node;
|
||||
r_zone_by_inout_node.add(node, zone);
|
||||
for (const bNodeZoneType *zone_type : zone_types) {
|
||||
for (const bNode *input_node : tree.nodes_by_type(zone_type->input_idname)) {
|
||||
if (const bNode *output_node = zone_type->get_corresponding_output(tree, *input_node)) {
|
||||
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(output_node, nullptr)) {
|
||||
zone->input_node = input_node;
|
||||
r_zone_by_inout_node.add(input_node, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,6 +218,9 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
|
||||
return {};
|
||||
}
|
||||
|
||||
const Span<int> input_types = all_zone_input_node_types();
|
||||
const Span<int> output_types = all_zone_output_node_types();
|
||||
|
||||
std::unique_ptr<bNodeTreeZones> tree_zones = std::make_unique<bNodeTreeZones>();
|
||||
|
||||
const Span<const bNode *> all_nodes = tree.all_nodes();
|
||||
@@ -257,13 +255,13 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
|
||||
depend_on_output_flags |= depend_on_output_flag_array[from_node_i];
|
||||
}
|
||||
}
|
||||
if (ELEM(node->type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_REPEAT_INPUT)) {
|
||||
if (input_types.contains(node->type)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* Now entering a zone, so set the corresponding bit. */
|
||||
depend_on_input_flags[zone->index].set();
|
||||
}
|
||||
}
|
||||
else if (ELEM(node->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
|
||||
else if (output_types.contains(node->type)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* The output is implicitly linked to the input, so also propagate the bits from there. */
|
||||
if (const bNode *zone_input_node = zone->input_node) {
|
||||
@@ -430,4 +428,96 @@ Vector<const bNodeTreeZone *> bNodeTreeZones::get_zone_stack_for_node(const int
|
||||
return zone_stack;
|
||||
}
|
||||
|
||||
const bNode *bNodeZoneType::get_corresponding_input(const bNodeTree &tree,
|
||||
const bNode &output_bnode) const
|
||||
{
|
||||
for (const bNode *node : tree.nodes_by_type(this->input_idname)) {
|
||||
if (this->get_corresponding_output_id(*node) == output_bnode.identifier) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bNode *bNodeZoneType::get_corresponding_output(const bNodeTree &tree,
|
||||
const bNode &input_bnode) const
|
||||
{
|
||||
return tree.node_by_id(this->get_corresponding_output_id(input_bnode));
|
||||
}
|
||||
|
||||
bNode *bNodeZoneType::get_corresponding_input(bNodeTree &tree, const bNode &output_bnode) const
|
||||
{
|
||||
return const_cast<bNode *>(
|
||||
this->get_corresponding_input(const_cast<const bNodeTree &>(tree), output_bnode));
|
||||
}
|
||||
|
||||
bNode *bNodeZoneType::get_corresponding_output(bNodeTree &tree, const bNode &input_bnode) const
|
||||
{
|
||||
return const_cast<bNode *>(
|
||||
this->get_corresponding_output(const_cast<const bNodeTree &>(tree), input_bnode));
|
||||
}
|
||||
|
||||
static Vector<const bNodeZoneType *> &get_zone_types_vector()
|
||||
{
|
||||
static Vector<const bNodeZoneType *> zone_types;
|
||||
return zone_types;
|
||||
};
|
||||
|
||||
void register_node_zone_type(const bNodeZoneType &zone_type)
|
||||
{
|
||||
get_zone_types_vector().append(&zone_type);
|
||||
}
|
||||
|
||||
Span<const bNodeZoneType *> all_zone_types()
|
||||
{
|
||||
return get_zone_types_vector();
|
||||
}
|
||||
|
||||
Span<int> all_zone_node_types()
|
||||
{
|
||||
static const Vector<int> node_types = []() {
|
||||
Vector<int> node_types;
|
||||
for (const bNodeZoneType *zone_type : all_zone_types()) {
|
||||
node_types.append(zone_type->input_type);
|
||||
node_types.append(zone_type->output_type);
|
||||
}
|
||||
return node_types;
|
||||
}();
|
||||
return node_types;
|
||||
}
|
||||
|
||||
Span<int> all_zone_input_node_types()
|
||||
{
|
||||
static const Vector<int> node_types = []() {
|
||||
Vector<int> node_types;
|
||||
for (const bNodeZoneType *zone_type : all_zone_types()) {
|
||||
node_types.append(zone_type->input_type);
|
||||
}
|
||||
return node_types;
|
||||
}();
|
||||
return node_types;
|
||||
}
|
||||
|
||||
Span<int> all_zone_output_node_types()
|
||||
{
|
||||
static const Vector<int> node_types = []() {
|
||||
Vector<int> node_types;
|
||||
for (const bNodeZoneType *zone_type : all_zone_types()) {
|
||||
node_types.append(zone_type->output_type);
|
||||
}
|
||||
return node_types;
|
||||
}();
|
||||
return node_types;
|
||||
}
|
||||
|
||||
const bNodeZoneType *zone_type_by_node_type(const int node_type)
|
||||
{
|
||||
for (const bNodeZoneType *zone_type : all_zone_types()) {
|
||||
if (ELEM(node_type, zone_type->input_type, zone_type->output_type)) {
|
||||
return zone_type;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
@@ -2672,12 +2672,7 @@ static void node_draw_basis(const bContext &C,
|
||||
}
|
||||
|
||||
/* Shadow. */
|
||||
if (!ELEM(node.type,
|
||||
GEO_NODE_SIMULATION_INPUT,
|
||||
GEO_NODE_SIMULATION_OUTPUT,
|
||||
GEO_NODE_REPEAT_INPUT,
|
||||
GEO_NODE_REPEAT_OUTPUT))
|
||||
{
|
||||
if (!bke::all_zone_node_types().contains(node.type)) {
|
||||
node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
|
||||
}
|
||||
|
||||
@@ -2986,12 +2981,8 @@ static void node_draw_basis(const bContext &C,
|
||||
else if (bke::node_type_is_undefined(&node)) {
|
||||
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
|
||||
}
|
||||
else if (ELEM(node.type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_SIMULATION_OUTPUT)) {
|
||||
UI_GetThemeColor4fv(TH_NODE_ZONE_SIMULATION, color_outline);
|
||||
color_outline[3] = 1.0f;
|
||||
}
|
||||
else if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
|
||||
UI_GetThemeColor4fv(TH_NODE_ZONE_REPEAT, color_outline);
|
||||
else if (const bke::bNodeZoneType *zone_type = bke::zone_type_by_node_type(node.type)) {
|
||||
UI_GetThemeColor4fv(zone_type->theme_id, color_outline);
|
||||
color_outline[3] = 1.0f;
|
||||
}
|
||||
else {
|
||||
@@ -3730,10 +3721,7 @@ static void node_draw_zones(TreeDrawContext & /*tree_draw_ctx*/,
|
||||
|
||||
const auto get_theme_id = [&](const int zone_i) {
|
||||
const bNode *node = zones->zones[zone_i]->output_node;
|
||||
if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
|
||||
return TH_NODE_ZONE_SIMULATION;
|
||||
}
|
||||
return TH_NODE_ZONE_REPEAT;
|
||||
return bke::zone_type_by_node_type(node->type)->theme_id;
|
||||
};
|
||||
|
||||
const uint pos = GPU_vertformat_attr_add(
|
||||
|
||||
@@ -1292,37 +1292,21 @@ void remap_node_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &
|
||||
* so we have to build a map first to find copied output nodes in the new tree. */
|
||||
Map<int32_t, bNode *> dst_output_node_map;
|
||||
for (const auto &item : node_map.items()) {
|
||||
if (ELEM(item.key->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
|
||||
if (bke::all_zone_output_node_types().contains(item.key->type)) {
|
||||
dst_output_node_map.add_new(item.key->identifier, item.value);
|
||||
}
|
||||
}
|
||||
|
||||
for (bNode *dst_node : node_map.values()) {
|
||||
switch (dst_node->type) {
|
||||
case GEO_NODE_SIMULATION_INPUT: {
|
||||
NodeGeometrySimulationInput *data = static_cast<NodeGeometrySimulationInput *>(
|
||||
dst_node->storage);
|
||||
if (const bNode *output_node = dst_output_node_map.lookup_default(data->output_node_id,
|
||||
nullptr)) {
|
||||
data->output_node_id = output_node->identifier;
|
||||
}
|
||||
else {
|
||||
data->output_node_id = 0;
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
break;
|
||||
if (bke::all_zone_input_node_types().contains(dst_node->type)) {
|
||||
const bke::bNodeZoneType &zone_type = *bke::zone_type_by_node_type(dst_node->type);
|
||||
int &output_node_id = zone_type.get_corresponding_output_id(*dst_node);
|
||||
if (const bNode *output_node = dst_output_node_map.lookup_default(output_node_id, nullptr)) {
|
||||
output_node_id = output_node->identifier;
|
||||
}
|
||||
case GEO_NODE_REPEAT_INPUT: {
|
||||
NodeGeometryRepeatInput *data = static_cast<NodeGeometryRepeatInput *>(dst_node->storage);
|
||||
if (const bNode *output_node = dst_output_node_map.lookup_default(data->output_node_id,
|
||||
nullptr)) {
|
||||
data->output_node_id = output_node->identifier;
|
||||
}
|
||||
else {
|
||||
data->output_node_id = 0;
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
break;
|
||||
else {
|
||||
output_node_id = 0;
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,31 +148,15 @@ static void remap_pairing(bNodeTree &dst_tree,
|
||||
const Map<int32_t, int32_t> &identifier_map)
|
||||
{
|
||||
for (bNode *dst_node : nodes) {
|
||||
switch (dst_node->type) {
|
||||
case GEO_NODE_SIMULATION_INPUT: {
|
||||
NodeGeometrySimulationInput *data = static_cast<NodeGeometrySimulationInput *>(
|
||||
dst_node->storage);
|
||||
if (data->output_node_id == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data->output_node_id = identifier_map.lookup_default(data->output_node_id, 0);
|
||||
if (data->output_node_id == 0) {
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
break;
|
||||
if (bke::all_zone_input_node_types().contains(dst_node->type)) {
|
||||
const bke::bNodeZoneType &zone_type = *bke::zone_type_by_node_type(dst_node->type);
|
||||
int &output_node_id = zone_type.get_corresponding_output_id(*dst_node);
|
||||
if (output_node_id == 0) {
|
||||
continue;
|
||||
}
|
||||
case GEO_NODE_REPEAT_INPUT: {
|
||||
NodeGeometryRepeatInput *data = static_cast<NodeGeometryRepeatInput *>(dst_node->storage);
|
||||
if (data->output_node_id == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data->output_node_id = identifier_map.lookup_default(data->output_node_id, 0);
|
||||
if (data->output_node_id == 0) {
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
break;
|
||||
output_node_id = identifier_map.lookup_default(output_node_id, 0);
|
||||
if (output_node_id == 0) {
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "UI_resources.hh"
|
||||
|
||||
static bool node_undefined_poll(const bNodeType * /*ntype*/,
|
||||
const bNodeTree * /*nodetree*/,
|
||||
const char ** /*r_disabled_hint*/)
|
||||
@@ -50,8 +52,54 @@ static void register_undefined_types()
|
||||
blender::bke::NodeSocketTypeUndefined.output_link_limit = 0xFFF;
|
||||
}
|
||||
|
||||
class SimulationZoneType : public blender::bke::bNodeZoneType {
|
||||
public:
|
||||
SimulationZoneType()
|
||||
{
|
||||
this->input_idname = "GeometryNodeSimulationInput";
|
||||
this->output_idname = "GeometryNodeSimulationOutput";
|
||||
this->input_type = GEO_NODE_SIMULATION_INPUT;
|
||||
this->output_type = GEO_NODE_SIMULATION_OUTPUT;
|
||||
this->theme_id = TH_NODE_ZONE_SIMULATION;
|
||||
}
|
||||
|
||||
const int &get_corresponding_output_id(const bNode &input_bnode) const override
|
||||
{
|
||||
BLI_assert(input_bnode.type == this->input_type);
|
||||
return static_cast<NodeGeometrySimulationInput *>(input_bnode.storage)->output_node_id;
|
||||
}
|
||||
};
|
||||
|
||||
class RepeatZoneType : public blender::bke::bNodeZoneType {
|
||||
public:
|
||||
RepeatZoneType()
|
||||
{
|
||||
this->input_idname = "GeometryNodeRepeatInput";
|
||||
this->output_idname = "GeometryNodeRepeatOutput";
|
||||
this->input_type = GEO_NODE_REPEAT_INPUT;
|
||||
this->output_type = GEO_NODE_REPEAT_OUTPUT;
|
||||
this->theme_id = TH_NODE_ZONE_REPEAT;
|
||||
}
|
||||
|
||||
const int &get_corresponding_output_id(const bNode &input_bnode) const override
|
||||
{
|
||||
BLI_assert(input_bnode.type == this->input_type);
|
||||
return static_cast<NodeGeometryRepeatInput *>(input_bnode.storage)->output_node_id;
|
||||
}
|
||||
};
|
||||
|
||||
static void register_zone_types()
|
||||
{
|
||||
static SimulationZoneType simulation_zone_type;
|
||||
static RepeatZoneType repeat_zone_type;
|
||||
blender::bke::register_node_zone_type(simulation_zone_type);
|
||||
blender::bke::register_node_zone_type(repeat_zone_type);
|
||||
}
|
||||
|
||||
void register_nodes()
|
||||
{
|
||||
register_zone_types();
|
||||
|
||||
register_undefined_types();
|
||||
|
||||
register_standard_node_socket_types();
|
||||
|
||||
Reference in New Issue
Block a user