This adds support for running a set of nodes repeatedly. The number of iterations can be controlled dynamically as an input of the repeat zone. The repeat zone can be added in via the search or from the Add > Utilities menu. The main use case is to replace long repetitive node chains with a more flexible alternative. Technically, repeat zones can also be used for many other use cases. However, due to their serial nature, performance is very sub-optimal when they are used to solve problems that could be processed in parallel. Better solutions for such use cases will be worked on separately. Repeat zones are similar to simulation zones. The major difference is that they have no concept of time and are always evaluated entirely in the current frame, while in simulations only a single iteration is evaluated per frame. Stopping the repetition early using a dynamic condition is not yet supported. "Break" functionality can be implemented manually using Switch nodes in the loop for now. It's likely that this functionality will be built into the repeat zone in the future. For now, things are kept more simple. Remaining Todos after this first version: * Improve socket inspection and viewer node support. Currently, only the first iteration is taken into account for socket inspection and the viewer. * Make loop evaluation more lazy. Currently, the evaluation is eager, meaning that it evaluates some nodes even though their output may not be required. Pull Request: https://projects.blender.org/blender/blender/pulls/109164
107 lines
2.6 KiB
C++
107 lines
2.6 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/**
|
|
* This file implements some specific compute contexts for concepts in Blender.
|
|
*/
|
|
|
|
#include <optional>
|
|
|
|
#include "BLI_compute_context.hh"
|
|
|
|
struct bNode;
|
|
|
|
namespace blender::bke {
|
|
|
|
class ModifierComputeContext : public ComputeContext {
|
|
private:
|
|
static constexpr const char *s_static_type = "MODIFIER";
|
|
|
|
/**
|
|
* Use modifier name instead of something like `session_uuid` for now because:
|
|
* - It's more obvious that the name matches between the original and evaluated object.
|
|
* - We might want that the context hash is consistent between sessions in the future.
|
|
*/
|
|
std::string modifier_name_;
|
|
|
|
public:
|
|
ModifierComputeContext(const ComputeContext *parent, std::string modifier_name);
|
|
|
|
private:
|
|
void print_current_in_line(std::ostream &stream) const override;
|
|
};
|
|
|
|
class NodeGroupComputeContext : public ComputeContext {
|
|
private:
|
|
static constexpr const char *s_static_type = "NODE_GROUP";
|
|
|
|
int32_t node_id_;
|
|
|
|
#ifdef DEBUG
|
|
std::string debug_node_name_;
|
|
#endif
|
|
|
|
public:
|
|
NodeGroupComputeContext(const ComputeContext *parent,
|
|
int32_t node_id,
|
|
const std::optional<ComputeContextHash> &cached_hash = {});
|
|
NodeGroupComputeContext(const ComputeContext *parent, const bNode &node);
|
|
|
|
int32_t node_id() const
|
|
{
|
|
return node_id_;
|
|
}
|
|
|
|
private:
|
|
void print_current_in_line(std::ostream &stream) const override;
|
|
};
|
|
|
|
class SimulationZoneComputeContext : public ComputeContext {
|
|
private:
|
|
static constexpr const char *s_static_type = "SIMULATION_ZONE";
|
|
|
|
int32_t output_node_id_;
|
|
|
|
public:
|
|
SimulationZoneComputeContext(const ComputeContext *parent, int output_node_id);
|
|
SimulationZoneComputeContext(const ComputeContext *parent, const bNode &node);
|
|
|
|
int32_t output_node_id() const
|
|
{
|
|
return output_node_id_;
|
|
}
|
|
|
|
private:
|
|
void print_current_in_line(std::ostream &stream) const override;
|
|
};
|
|
|
|
class RepeatZoneComputeContext : public ComputeContext {
|
|
private:
|
|
static constexpr const char *s_static_type = "REPEAT_ZONE";
|
|
|
|
int32_t output_node_id_;
|
|
int iteration_;
|
|
|
|
public:
|
|
RepeatZoneComputeContext(const ComputeContext *parent, int32_t output_node_id, int iteration);
|
|
RepeatZoneComputeContext(const ComputeContext *parent, const bNode &node, int iteration);
|
|
|
|
int32_t output_node_id() const
|
|
{
|
|
return output_node_id_;
|
|
}
|
|
|
|
int iteration() const
|
|
{
|
|
return iteration_;
|
|
}
|
|
|
|
private:
|
|
void print_current_in_line(std::ostream &stream) const override;
|
|
};
|
|
|
|
} // namespace blender::bke
|