Geometry Nodes: new repeat zone #109164

Merged
Jacques Lucke merged 98 commits from JacquesLucke/blender:serial-loop into main 2023-07-11 22:36:17 +02:00
45 changed files with 459 additions and 485 deletions
Showing only changes of commit 9ef2b02393 - Show all commits

View File

@ -873,7 +873,7 @@ const bTheme U_theme_default = {
.nodeclass_geometry = RGBA(0x00d6a3ff),
.nodeclass_attribute = RGBA(0x001566ff),
.node_zone_simulation = RGBA(0x66416233),
.node_zone_serial_loop = RGBA(0x41666233),
.node_zone_repeat = RGBA(0x41666233),
.movie = RGBA(0x0f0f0fcc),
.gp_vertex_size = 3,
.gp_vertex = RGBA(0x97979700),

View File

@ -350,9 +350,9 @@ class SimulationZoneItemMoveOperator(SimulationZoneOperator, Operator):
return {'FINISHED'}
class SerialLoopZoneOperator:
input_node_type = 'GeometryNodeSerialLoopInput'
output_node_type = 'GeometryNodeSerialLoopOutput'
class RepeatZoneOperator:
input_node_type = 'GeometryNodeRepeatInput'
output_node_type = 'GeometryNodeRepeatOutput'
@classmethod
def get_output_node(cls, context):
@ -377,17 +377,17 @@ class SerialLoopZoneOperator:
return True
class SerialLoopZoneItemAddOperator(SerialLoopZoneOperator, Operator):
"""Add a loop item to the serial loop zone"""
bl_idname = "node.serial_loop_zone_item_add"
bl_label = "Add Loop Item"
class RepeatZoneItemAddOperator(RepeatZoneOperator, Operator):
"""Add a repeat item to the repeat zone"""
Review

I'd go with "item" instead of "repeat item" which sounds a bit unnatural but it's not a big deal either way.

I'd go with "item" instead of "repeat item" which sounds a bit unnatural but it's not a big deal either way.
bl_idname = "node.repeat_zone_item_add"
bl_label = "Add Repeat Item"
bl_options = {'REGISTER', 'UNDO'}
default_socket_type = 'GEOMETRY'
JacquesLucke marked this conversation as resolved
Review

This should copy the active type when possible. See 0f36f44db8

This should copy the active type when possible. See 0f36f44db85635bb8616e07b0ba6b6bcce4024af
def execute(self, context):
node = self.get_output_node(context)
loop_items = node.loop_items
repeat_items = node.repeat_items
# Remember index to move the item.
if node.active_item:
@ -395,38 +395,38 @@ class SerialLoopZoneItemAddOperator(SerialLoopZoneOperator, Operator):
dst_type = node.active_item.socket_type
dst_name = node.active_item.name
else:
dst_index = len(loop_items)
dst_index = len(repeat_items)
dst_type = self.default_socket_type
# Empty name so it is based on the type.
dst_name = ""
loop_items.new(dst_type, dst_name)
loop_items.move(len(loop_items) - 1, dst_index)
repeat_items.new(dst_type, dst_name)
repeat_items.move(len(repeat_items) - 1, dst_index)
node.active_index = dst_index
return {'FINISHED'}
class SerialLoopZoneItemRemoveOperator(SerialLoopZoneOperator, Operator):
"""Remove a loop item from the serial loop zone"""
bl_idname = "node.serial_loop_zone_item_remove"
bl_label = "Remove Loop Item"
class RepeatZoneItemRemoveOperator(RepeatZoneOperator, Operator):
"""Remove a repeat item from the repeat zone"""
bl_idname = "node.repeat_zone_item_remove"
bl_label = "Remove Repeat Item"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
node = self.get_output_node(context)
loop_items = node.loop_items
repeat_items = node.repeat_items
if node.active_item:
loop_items.remove(node.active_item)
node.active_index = min(node.active_index, len(loop_items) - 1)
repeat_items.remove(node.active_item)
node.active_index = min(node.active_index, len(repeat_items) - 1)
return {'FINISHED'}
class SerialLoopZoneItemMoveOperator(SerialLoopZoneOperator, Operator):
"""Move a serial loop state item up or down in the list"""
bl_idname = "node.serial_loop_zone_item_move"
bl_label = "Move Loop Item"
class RepeatZoneItemMoveOperator(RepeatZoneOperator, Operator):
"""Move a repeat item up or down in the list"""
bl_idname = "node.repeat_zone_item_move"
bl_label = "Move Repeat Item"
bl_options = {'REGISTER', 'UNDO'}
direction: EnumProperty(
@ -437,13 +437,13 @@ class SerialLoopZoneItemMoveOperator(SerialLoopZoneOperator, Operator):
def execute(self, context):
node = self.get_output_node(context)
loop_items = node.loop_items
repeat_items = node.repeat_items
if self.direction == 'UP' and node.active_index > 0:
loop_items.move(node.active_index, node.active_index - 1)
repeat_items.move(node.active_index, node.active_index - 1)
node.active_index = node.active_index - 1
elif self.direction == 'DOWN' and node.active_index < len(loop_items) - 1:
loop_items.move(node.active_index, node.active_index + 1)
elif self.direction == 'DOWN' and node.active_index < len(repeat_items) - 1:
repeat_items.move(node.active_index, node.active_index + 1)
node.active_index = node.active_index + 1
return {'FINISHED'}
@ -456,7 +456,7 @@ classes = (
SimulationZoneItemAddOperator,
SimulationZoneItemRemoveOperator,
SimulationZoneItemMoveOperator,
SerialLoopZoneItemAddOperator,
SerialLoopZoneItemRemoveOperator,
SerialLoopZoneItemMoveOperator,
RepeatZoneItemAddOperator,
RepeatZoneItemRemoveOperator,
RepeatZoneItemMoveOperator,
)

View File

@ -198,14 +198,14 @@ class NODE_OT_add_simulation_zone(NodeAddZoneOperator, Operator):
output_node_type = "GeometryNodeSimulationOutput"
class NODE_OT_add_serial_loop_zone(NodeAddZoneOperator, Operator):
"""Add a serial loop zone that allows executing nodes a dynamic number of times"""
bl_idname = "node.add_serial_loop_zone"
bl_label = "Add Serial Loop Zone"
class NODE_OT_add_repeat_zone(NodeAddZoneOperator, Operator):
"""Add a repeat zone that allows executing nodes a dynamic number of times"""
bl_idname = "node.add_repeat_zone"
bl_label = "Add Repeat Zone"
bl_options = {'REGISTER', 'UNDO'}
input_node_type = "GeometryNodeSerialLoopInput"
output_node_type = "GeometryNodeSerialLoopOutput"
input_node_type = "GeometryNodeRepeatInput"
output_node_type = "GeometryNodeRepeatOutput"
@ -341,7 +341,7 @@ classes = (
NODE_OT_add_node,
NODE_OT_add_simulation_zone,
NODE_OT_add_serial_loop_zone,
NODE_OT_add_repeat_zone,
NODE_OT_collapse_hide_unused_toggle,
NODE_OT_panel_add,
NODE_OT_panel_remove,

View File

@ -72,8 +72,8 @@ def add_simulation_zone(layout, label):
return props
def add_serial_loop_zone(layout, label):
props = layout.operator("node.add_serial_loop_zone", text=label)
def add_repeat_zone(layout, label):
props = layout.operator("node.add_repeat_zone", text=label)
props.use_transform = True
return props

View File

@ -641,7 +641,7 @@ class NODE_MT_category_GEO_LAYOUT(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "NodeFrame")
node_add_menu.add_node_type(layout, "NodeReroute")
node_add_menu.add_serial_loop_zone(layout, label="Serial Loop")
node_add_menu.add_repeat_zone(layout, label="Repeat")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -1106,7 +1106,7 @@ class NODE_PT_simulation_zone_items(Panel):
layout.prop(active_item, "attribute_domain")
class NODE_UL_serial_loop_zone_items(bpy.types.UIList):
class NODE_UL_repeat_zone_items(bpy.types.UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
row = layout.row(align=True)
@ -1117,14 +1117,14 @@ class NODE_UL_serial_loop_zone_items(bpy.types.UIList):
layout.template_node_socket(color=item.color)
class NODE_PT_serial_loop_zone_items(Panel):
class NODE_PT_repeat_zone_items(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_category = "Node"
bl_label = "Serial Loop"
bl_label = "Repeat"
input_node_type = 'GeometryNodeSerialLoopInput'
output_node_type = 'GeometryNodeSerialLoopOutput'
input_node_type = 'GeometryNodeRepeatInput'
output_node_type = 'GeometryNodeRepeatOutput'
@classmethod
def get_output_node(cls, context):
@ -1152,25 +1152,25 @@ class NODE_PT_serial_loop_zone_items(Panel):
output_node = self.get_output_node(context)
split = layout.row()
split.template_list(
"NODE_UL_serial_loop_zone_items",
"NODE_UL_repeat_zone_items",
"",
output_node,
"loop_items",
"repeat_items",
output_node,
"active_index")
ops_col = split.column()
add_remove_col = ops_col.column(align=True)
add_remove_col.operator("node.serial_loop_zone_item_add", icon='ADD', text="")
add_remove_col.operator("node.serial_loop_zone_item_remove", icon='REMOVE', text="")
add_remove_col.operator("node.repeat_zone_item_add", icon='ADD', text="")
add_remove_col.operator("node.repeat_zone_item_remove", icon='REMOVE', text="")
ops_col.separator()
up_down_col = ops_col.column(align=True)
props = up_down_col.operator("node.serial_loop_zone_item_move", icon='TRIA_UP', text="")
props = up_down_col.operator("node.repeat_zone_item_move", icon='TRIA_UP', text="")
props.direction = 'UP'
props = up_down_col.operator("node.serial_loop_zone_item_move", icon='TRIA_DOWN', text="")
props = up_down_col.operator("node.repeat_zone_item_move", icon='TRIA_DOWN', text="")
props.direction = 'DOWN'
active_item = output_node.active_item
@ -1247,8 +1247,8 @@ classes = (
NODE_PT_panels,
NODE_UL_simulation_zone_items,
NODE_PT_simulation_zone_items,
NODE_UL_serial_loop_zone_items,
NODE_PT_serial_loop_zone_items,
NODE_UL_repeat_zone_items,
NODE_PT_repeat_zone_items,
NODE_PT_active_node_properties,
node_panel(EEVEE_MATERIAL_PT_settings),

View File

@ -91,8 +91,8 @@ class SPREADSHEET_HT_header(bpy.types.Header):
layout.label(text=ctx.ui_name, icon='NODE')
elif ctx.type == 'SIMULATION_ZONE':
layout.label(text="Simulation Zone")
elif ctx.type == 'SERIAL_LOOP_ZONE':
layout.label(text="Serial Loop")
elif ctx.type == 'REPEAT_ZONE':
layout.label(text="Repeat Zone")
elif ctx.type == 'VIEWER_NODE':
layout.label(text=ctx.ui_name)

View File

@ -78,18 +78,16 @@ class SimulationZoneComputeContext : public ComputeContext {
void print_current_in_line(std::ostream &stream) const override;
};
class SerialLoopZoneComputeContext : public ComputeContext {
class RepeatZoneComputeContext : public ComputeContext {
private:
static constexpr const char *s_static_type = "SERIAL_LOOP_ZONE";
static constexpr const char *s_static_type = "REPEAT_ZONE";
int32_t output_node_id_;
int iteration_;
public:
SerialLoopZoneComputeContext(const ComputeContext *parent,
int32_t output_node_id,
int iteration);
SerialLoopZoneComputeContext(const ComputeContext *parent, const bNode &node, int iteration);
RepeatZoneComputeContext(const ComputeContext *parent, int32_t output_node_id, int iteration);
JacquesLucke marked this conversation as resolved Outdated

int -> int32_t

`int` -> `int32_t`
RepeatZoneComputeContext(const ComputeContext *parent, const bNode &node, int iteration);
int32_t output_node_id() const
{

View File

@ -1360,8 +1360,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
#define GEO_NODE_SAMPLE_VOLUME 2103
#define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104
#define GEO_NODE_SERIAL_LOOP_INPUT 2105
#define GEO_NODE_SERIAL_LOOP_OUTPUT 2106
#define GEO_NODE_REPEAT_INPUT 2105
#define GEO_NODE_REPEAT_OUTPUT 2106
/** \} */

View File

@ -53,7 +53,7 @@ ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier(void);
GroupNodeViewerPathElem *BKE_viewer_path_elem_new_group_node(void);
SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone(void);
ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node(void);
SerialLoopZoneViewerPathElem *BKE_viewer_path_elem_new_serial_loop_zone(void);
RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone(void);
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src);
bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b);
void BKE_viewer_path_elem_free(ViewerPathElem *elem);

View File

@ -88,9 +88,9 @@ void SimulationZoneComputeContext::print_current_in_line(std::ostream &stream) c
stream << "Simulation Zone ID: " << output_node_id_;
}
SerialLoopZoneComputeContext::SerialLoopZoneComputeContext(const ComputeContext *parent,
const int32_t output_node_id,
const int iteration)
RepeatZoneComputeContext::RepeatZoneComputeContext(const ComputeContext *parent,
const int32_t output_node_id,
const int iteration)
: ComputeContext(s_static_type, parent), output_node_id_(output_node_id), iteration_(iteration)
{
/* Mix static type and node id into a single buffer so that only a single call to #mix_in is
@ -105,16 +105,16 @@ SerialLoopZoneComputeContext::SerialLoopZoneComputeContext(const ComputeContext
hash_.mix_in(buffer, buffer_size);
}
SerialLoopZoneComputeContext::SerialLoopZoneComputeContext(const ComputeContext *parent,
const bNode &node,
const int iteration)
: SerialLoopZoneComputeContext(parent, node.identifier, iteration)
RepeatZoneComputeContext::RepeatZoneComputeContext(const ComputeContext *parent,
const bNode &node,
const int iteration)
: RepeatZoneComputeContext(parent, node.identifier, iteration)
{
}
void SerialLoopZoneComputeContext::print_current_in_line(std::ostream &stream) const
void RepeatZoneComputeContext::print_current_in_line(std::ostream &stream) const
{
stream << "Serial Loop Zone ID: " << output_node_id_;
stream << "Repeat Zone ID: " << output_node_id_;
}
} // namespace blender::bke

View File

@ -676,11 +676,11 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
BLO_write_string(writer, item.name);
}
}
if (node->type == GEO_NODE_SERIAL_LOOP_OUTPUT) {
const NodeGeometrySerialLoopOutput &storage =
*static_cast<const NodeGeometrySerialLoopOutput *>(node->storage);
BLO_write_struct_array(writer, NodeSerialLoopItem, storage.items_num, storage.items);
for (const NodeSerialLoopItem &item : Span(storage.items, storage.items_num)) {
if (node->type == GEO_NODE_REPEAT_OUTPUT) {
const NodeGeometryRepeatOutput &storage = *static_cast<const NodeGeometryRepeatOutput *>(
node->storage);
BLO_write_struct_array(writer, NodeRepeatItem, storage.items_num, storage.items);
for (const NodeRepeatItem &item : Span(storage.items, storage.items_num)) {
BLO_write_string(writer, item.name);
}
}
@ -880,11 +880,11 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
}
break;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
NodeGeometrySerialLoopOutput &storage = *static_cast<NodeGeometrySerialLoopOutput *>(
case GEO_NODE_REPEAT_OUTPUT: {
NodeGeometryRepeatOutput &storage = *static_cast<NodeGeometryRepeatOutput *>(
node->storage);
BLO_read_data_address(reader, &storage.items);
for (const NodeSerialLoopItem &item : Span(storage.items, storage.items_num)) {
for (const NodeRepeatItem &item : Span(storage.items, storage.items_num)) {
BLO_read_data_address(reader, &item.name);
}
break;

View File

@ -294,14 +294,14 @@ static Vector<const bNode *> get_implicit_origin_nodes(const bNodeTree &ntree, b
}
}
}
if (node.type == GEO_NODE_SERIAL_LOOP_OUTPUT) {
for (const bNode *serial_loop_input_node :
ntree.runtime->nodes_by_type.lookup(nodeTypeFind("GeometryNodeSerialLoopInput")))
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 NodeGeometrySerialLoopInput *>(
serial_loop_input_node->storage);
const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(
repeat_input_node->storage);
if (storage.output_node_id == node.identifier) {
origin_nodes.append(serial_loop_input_node);
origin_nodes.append(repeat_input_node);
}
}
}
@ -317,10 +317,10 @@ static Vector<const bNode *> get_implicit_target_nodes(const bNodeTree &ntree, b
target_nodes.append(sim_output_node);
}
}
if (node.type == GEO_NODE_SERIAL_LOOP_INPUT) {
const auto &storage = *static_cast<const NodeGeometrySerialLoopInput *>(node.storage);
if (const bNode *serial_loop_output_node = ntree.node_by_id(storage.output_node_id)) {
target_nodes.append(serial_loop_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);
}
}
return target_nodes;

View File

@ -99,7 +99,7 @@ static const aal::RelationsInNode &get_relations_in_node(const bNode &node, Reso
}
return relations;
}
if (ELEM(node.type, GEO_NODE_SERIAL_LOOP_INPUT, GEO_NODE_SERIAL_LOOP_OUTPUT)) {
if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
aal::RelationsInNode &relations = scope.construct<aal::RelationsInNode>();
/* TODO: Add a smaller set of relations. This requires changing the inferencing algorithm to
JacquesLucke marked this conversation as resolved Outdated

Feels more natural to me to write this as a "TODO" comment like
TODO: Add a smaller set of relations. For now, adding all possible relations is correct.

Feels more natural to me to write this as a "TODO" comment like `TODO: Add a smaller set of relations. For now, adding all possible relations is correct.`
* make it aware of loops. */
@ -117,11 +117,11 @@ static const aal::RelationsInNode &get_relations_in_node(const bNode &node, Reso
}
}
else if (socket_is_field(*socket)) {
/* Reference relations are not added for the output node, because then nodes after the loop
* would have to know about the individual field sources within the loop. This is not
* necessary, because the field outputs of a loop already serve as field sources and
* anonymous attributes are extracted from them. */
if (node.type == GEO_NODE_SERIAL_LOOP_INPUT) {
/* Reference relations are not added for the output node, because then nodes after the
* repeat zone would have to know about the individual field sources within the repeat
* zone. This is not necessary, because the field outputs of a repeat zone already serve as
* field sources and anonymous attributes are extracted from them. */
if (node.type == GEO_NODE_REPEAT_INPUT) {
for (const bNodeSocket *input_socket : node.input_sockets()) {
if (socket_is_field(*input_socket)) {
relations.reference_relations.append({input_socket->index(), socket->index()});

View File

@ -319,7 +319,7 @@ static eFieldStateSyncResult simulation_nodes_field_state_sync(
return res;
}
static eFieldStateSyncResult serial_loop_field_state_sync(
static eFieldStateSyncResult repeat_field_state_sync(
const bNode &input_node,
const bNode &output_node,
const MutableSpan<SocketFieldState> field_state_by_socket_id)
@ -372,11 +372,11 @@ static bool propagate_special_data_requirements(
}
break;
}
case GEO_NODE_SERIAL_LOOP_INPUT: {
const NodeGeometrySerialLoopInput &data = *static_cast<const NodeGeometrySerialLoopInput *>(
case GEO_NODE_REPEAT_INPUT: {
const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
node.storage);
if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
const eFieldStateSyncResult sync_result = serial_loop_field_state_sync(
const eFieldStateSyncResult sync_result = repeat_field_state_sync(
node, *output_node, field_state_by_socket_id);
if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
need_update = true;
@ -384,12 +384,12 @@ static bool propagate_special_data_requirements(
}
break;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
for (const bNode *input_node : tree.nodes_by_type("GeometryNodeSerialLoopInput")) {
const NodeGeometrySerialLoopInput &data =
*static_cast<const NodeGeometrySerialLoopInput *>(input_node->storage);
case GEO_NODE_REPEAT_OUTPUT: {
for (const bNode *input_node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
input_node->storage);
if (node.identifier == data.output_node_id) {
const eFieldStateSyncResult sync_result = serial_loop_field_state_sync(
const eFieldStateSyncResult sync_result = repeat_field_state_sync(
*input_node, node, field_state_by_socket_id);
if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
need_update = true;
@ -412,7 +412,7 @@ static void propagate_data_requirements_from_right_to_left(
while (true) {
/* Node updates may require several passes due to cyclic dependencies caused by simulation or
* serial loop input/output nodes. */
* repeat input/output nodes. */
bool need_update = false;
for (const bNode *node : toposort_result) {

View File

@ -588,8 +588,8 @@ class NodeTreeMainUpdater {
}
}
}
if (node.type == GEO_NODE_SERIAL_LOOP_INPUT) {
const NodeGeometrySerialLoopInput *data = static_cast<const NodeGeometrySerialLoopInput *>(
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 (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {

View File

@ -35,7 +35,7 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
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("GeometryNodeSerialLoopOutput"));
zone_output_nodes.extend(tree.nodes_by_type("GeometryNodeRepeatOutput"));
for (const bNode *node : zone_output_nodes) {
auto zone = std::make_unique<bNodeTreeZone>();
zone->owner = &owner;
@ -53,10 +53,10 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
}
}
}
for (const bNode *node : tree.nodes_by_type("GeometryNodeSerialLoopInput")) {
const auto &storage = *static_cast<NodeGeometrySerialLoopInput *>(node->storage);
if (const bNode *loop_output_node = tree.node_by_id(storage.output_node_id)) {
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(loop_output_node, nullptr)) {
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);
}
@ -239,13 +239,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_SERIAL_LOOP_INPUT)) {
if (ELEM(node->type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_REPEAT_INPUT)) {
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_SERIAL_LOOP_OUTPUT)) {
else if (ELEM(node->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
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) {

View File

@ -88,9 +88,9 @@ void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_p
BLO_write_struct(writer, ViewerNodeViewerPathElem, typed_elem);
break;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto *typed_elem = reinterpret_cast<SerialLoopZoneViewerPathElem *>(elem);
BLO_write_struct(writer, SerialLoopZoneViewerPathElem, typed_elem);
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto *typed_elem = reinterpret_cast<RepeatZoneViewerPathElem *>(elem);
BLO_write_struct(writer, RepeatZoneViewerPathElem, typed_elem);
break;
}
}
@ -107,7 +107,7 @@ void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE:
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE:
case VIEWER_PATH_ELEM_TYPE_ID: {
break;
}
@ -133,7 +133,7 @@ void BKE_viewer_path_blend_read_lib(BlendLibReader *reader, ID *self_id, ViewerP
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
break;
}
}
@ -153,7 +153,7 @@ void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_p
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
break;
}
}
@ -173,7 +173,7 @@ void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mapping
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
break;
}
}
@ -205,8 +205,8 @@ ViewerPathElem *BKE_viewer_path_elem_new(const ViewerPathElemType type)
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
return &make_elem<ViewerNodeViewerPathElem>(type)->base;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
return &make_elem<SerialLoopZoneViewerPathElem>(type)->base;
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
return &make_elem<RepeatZoneViewerPathElem>(type)->base;
}
}
BLI_assert_unreachable();
@ -242,10 +242,10 @@ ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node()
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_VIEWER_NODE));
}
SerialLoopZoneViewerPathElem *BKE_viewer_path_elem_new_serial_loop_zone()
RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone()
{
return reinterpret_cast<SerialLoopZoneViewerPathElem *>(
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE));
return reinterpret_cast<RepeatZoneViewerPathElem *>(
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE));
}
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
@ -287,10 +287,10 @@ ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
new_elem->node_id = old_elem->node_id;
break;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto *old_elem = reinterpret_cast<const SerialLoopZoneViewerPathElem *>(src);
auto *new_elem = reinterpret_cast<SerialLoopZoneViewerPathElem *>(dst);
new_elem->loop_output_node_id = old_elem->loop_output_node_id;
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto *old_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(src);
auto *new_elem = reinterpret_cast<RepeatZoneViewerPathElem *>(dst);
new_elem->repeat_output_node_id = old_elem->repeat_output_node_id;
new_elem->iteration = old_elem->iteration;
break;
}
@ -329,10 +329,10 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b
const auto *b_elem = reinterpret_cast<const ViewerNodeViewerPathElem *>(b);
return a_elem->node_id == b_elem->node_id;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto *a_elem = reinterpret_cast<const SerialLoopZoneViewerPathElem *>(a);
const auto *b_elem = reinterpret_cast<const SerialLoopZoneViewerPathElem *>(b);
return a_elem->loop_output_node_id == b_elem->loop_output_node_id &&
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto *a_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(a);
const auto *b_elem = reinterpret_cast<const RepeatZoneViewerPathElem *>(b);
return a_elem->repeat_output_node_id == b_elem->repeat_output_node_id &&
a_elem->iteration == b_elem->iteration;
}
}
@ -346,7 +346,7 @@ void BKE_viewer_path_elem_free(ViewerPathElem *elem)
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
break;
}
case VIEWER_PATH_ELEM_TYPE_MODIFIER: {

View File

@ -116,7 +116,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
*/
{
/* Keep this block, even when empty. */
FROM_DEFAULT_V4_UCHAR(space_node.node_zone_serial_loop);
FROM_DEFAULT_V4_UCHAR(space_node.node_zone_repeat);
}
#undef FROM_DEFAULT_V4_UCHAR

View File

@ -181,7 +181,7 @@ typedef enum ThemeColorID {
TH_NODE_ATTRIBUTE,
TH_NODE_ZONE_SIMULATION,
TH_NODE_ZONE_SERIAL_LOOP,
TH_NODE_ZONE_REPEAT,
TH_SIMULATED_FRAMES,
TH_CONSOLE_OUTPUT,

View File

@ -645,8 +645,8 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_NODE_ZONE_SIMULATION:
cp = ts->node_zone_simulation;
break;
case TH_NODE_ZONE_SERIAL_LOOP:
cp = ts->node_zone_serial_loop;
case TH_NODE_ZONE_REPEAT:
cp = ts->node_zone_repeat;
break;
case TH_SIMULATED_FRAMES:
cp = ts->simulated_frames;

View File

@ -2199,8 +2199,8 @@ static void node_draw_basis(const bContext &C,
if (!ELEM(node.type,
GEO_NODE_SIMULATION_INPUT,
GEO_NODE_SIMULATION_OUTPUT,
GEO_NODE_SERIAL_LOOP_INPUT,
GEO_NODE_SERIAL_LOOP_OUTPUT))
GEO_NODE_REPEAT_INPUT,
GEO_NODE_REPEAT_OUTPUT))
{
node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
}
@ -2481,8 +2481,8 @@ static void node_draw_basis(const bContext &C,
UI_GetThemeColor4fv(TH_NODE_ZONE_SIMULATION, color_outline);
color_outline[3] = 1.0f;
}
else if (ELEM(node.type, GEO_NODE_SERIAL_LOOP_INPUT, GEO_NODE_SERIAL_LOOP_OUTPUT)) {
UI_GetThemeColor4fv(TH_NODE_ZONE_SERIAL_LOOP, color_outline);
else if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
UI_GetThemeColor4fv(TH_NODE_ZONE_REPEAT, color_outline);
color_outline[3] = 1.0f;
}
else {
@ -3232,7 +3232,7 @@ static void node_draw_zones(TreeDrawContext & /*tree_draw_ctx*/,
if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
return TH_NODE_ZONE_SIMULATION;
}
return TH_NODE_ZONE_SERIAL_LOOP;
return TH_NODE_ZONE_REPEAT;
};
const uint pos = GPU_vertformat_attr_add(

View File

@ -1273,7 +1273,7 @@ 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_SERIAL_LOOP_OUTPUT)) {
if (ELEM(item.key->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_REPEAT_OUTPUT)) {
dst_output_node_map.add_new(item.key->identifier, item.value);
}
}
@ -1293,9 +1293,8 @@ void remap_node_pairing(bNodeTree &dst_tree, const Map<const bNode *, bNode *> &
}
break;
}
case GEO_NODE_SERIAL_LOOP_INPUT: {
NodeGeometrySerialLoopInput *data = static_cast<NodeGeometrySerialLoopInput *>(
dst_node->storage);
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;

View File

@ -161,9 +161,8 @@ static void remap_pairing(bNodeTree &dst_tree,
}
break;
}
case GEO_NODE_SERIAL_LOOP_INPUT: {
NodeGeometrySerialLoopInput *data = static_cast<NodeGeometrySerialLoopInput *>(
dst_node->storage);
case GEO_NODE_REPEAT_INPUT: {
NodeGeometryRepeatInput *data = static_cast<NodeGeometryRepeatInput *>(dst_node->storage);
if (data->output_node_id == 0) {
continue;
}
@ -819,29 +818,27 @@ static bool node_group_make_test_selected(bNodeTree &ntree,
}
}
}
for (bNode *input_node : ntree.nodes_by_type("GeometryNodeSerialLoopInput")) {
const NodeGeometrySerialLoopInput &input_data =
*static_cast<const NodeGeometrySerialLoopInput *>(input_node->storage);
for (bNode *input_node : ntree.nodes_by_type("GeometryNodeRepeatInput")) {
const NodeGeometryRepeatInput &input_data = *static_cast<const NodeGeometryRepeatInput *>(
input_node->storage);
if (bNode *output_node = ntree.node_by_id(input_data.output_node_id)) {
const bool input_selected = nodes_to_group.contains(input_node);
const bool output_selected = nodes_to_group.contains(output_node);
if (input_selected && !output_selected) {
BKE_reportf(
&reports,
RPT_WARNING,
"Can not add serial loop input node '%s' to a group without its paired output '%s'",
input_node->name,
output_node->name);
BKE_reportf(&reports,
RPT_WARNING,
"Can not add repeat input node '%s' to a group without its paired output '%s'",
input_node->name,
output_node->name);
return false;
}
if (output_selected && !input_selected) {
BKE_reportf(
&reports,
RPT_WARNING,
"Can not add serial loop output node '%s' to a group without its paired input '%s'",
output_node->name,
input_node->name);
BKE_reportf(&reports,
RPT_WARNING,
"Can not add repeat output node '%s' to a group without its paired input '%s'",
output_node->name,
input_node->name);
return false;
}
}

View File

@ -327,8 +327,8 @@ void node_select_paired(bNodeTree &node_tree)
}
}
}
for (bNode *input_node : node_tree.nodes_by_type("GeometryNodeSerialLoopInput")) {
const auto *storage = static_cast<const NodeGeometrySerialLoopInput *>(input_node->storage);
for (bNode *input_node : node_tree.nodes_by_type("GeometryNodeRepeatInput")) {
const auto *storage = static_cast<const NodeGeometryRepeatInput *>(input_node->storage);
if (bNode *output_node = node_tree.node_by_id(storage->output_node_id)) {
if (input_node->flag & NODE_SELECT) {
output_node->flag |= NODE_SELECT;

View File

@ -34,9 +34,9 @@ static ViewerPathElem *viewer_path_elem_for_zone(const bNodeTreeZone &zone)
node_elem->sim_output_node_id = zone.output_node->identifier;
return &node_elem->base;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
SerialLoopZoneViewerPathElem *node_elem = BKE_viewer_path_elem_new_serial_loop_zone();
node_elem->loop_output_node_id = zone.output_node->identifier;
case GEO_NODE_REPEAT_OUTPUT: {
RepeatZoneViewerPathElem *node_elem = BKE_viewer_path_elem_new_repeat_zone();
node_elem->repeat_output_node_id = zone.output_node->identifier;
node_elem->iteration = 0;
return &node_elem->base;
}
@ -241,7 +241,7 @@ std::optional<ViewerPathForGeometryNodesViewer> parse_geometry_nodes_viewer(
if (!ELEM(elem->type,
VIEWER_PATH_ELEM_TYPE_GROUP_NODE,
VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE,
VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE))
VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE))
{
return std::nullopt;
}
@ -295,11 +295,10 @@ bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed
zone = next_zone;
break;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto &typed_elem = *reinterpret_cast<const SerialLoopZoneViewerPathElem *>(
path_elem);
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto &typed_elem = *reinterpret_cast<const RepeatZoneViewerPathElem *>(path_elem);
const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
typed_elem.loop_output_node_id);
typed_elem.repeat_output_node_id);
if (next_zone == nullptr) {
return false;
}

View File

@ -1746,7 +1746,7 @@ typedef struct NodeGeometrySimulationOutput {
#endif
} NodeGeometrySimulationOutput;
typedef struct NodeSerialLoopItem {
typedef struct NodeRepeatItem {
char *name;
/** #eNodeSocketDatatype. */
short socket_type;
@ -1761,28 +1761,28 @@ typedef struct NodeSerialLoopItem {
static bool supports_type(eNodeSocketDatatype type);
std::string identifier_str() const;
#endif
} NodeSerialLoopItem;
} NodeRepeatItem;
typedef struct NodeGeometrySerialLoopInput {
typedef struct NodeGeometryRepeatInput {
/** bNode.identifier of the corresponding output node. */
int32_t output_node_id;
} NodeGeometrySerialLoopInput;
} NodeGeometryRepeatInput;
typedef struct NodeGeometrySerialLoopOutput {
NodeSerialLoopItem *items;
typedef struct NodeGeometryRepeatOutput {
NodeRepeatItem *items;
int items_num;
int active_index;
/** Identifier to give to the next loop item. */
/** Identifier to give to the next repeat item. */
int next_identifier;
char _pad[4];
#ifdef __cplusplus
blender::Span<NodeSerialLoopItem> items_span() const;
blender::MutableSpan<NodeSerialLoopItem> items_span();
NodeSerialLoopItem *add_item(const char *name, eNodeSocketDatatype type);
void set_item_name(NodeSerialLoopItem &item, const char *name);
blender::Span<NodeRepeatItem> items_span() const;
blender::MutableSpan<NodeRepeatItem> items_span();
NodeRepeatItem *add_item(const char *name, eNodeSocketDatatype type);
void set_item_name(NodeRepeatItem &item, const char *name);
#endif
} NodeGeometrySerialLoopOutput;
} NodeGeometryRepeatOutput;
typedef struct NodeGeometryDistributePointsInVolume {
/** #GeometryNodePointDistributeVolumeMode. */

View File

@ -346,7 +346,7 @@ typedef struct ThemeSpace {
unsigned char nodeclass_geometry[4], nodeclass_attribute[4];
unsigned char node_zone_simulation[4];
unsigned char node_zone_serial_loop[4];
unsigned char node_zone_repeat[4];
unsigned char _pad9[4];
unsigned char simulated_frames[4];

View File

@ -15,7 +15,7 @@ typedef enum ViewerPathElemType {
VIEWER_PATH_ELEM_TYPE_GROUP_NODE = 2,
VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE = 3,
VIEWER_PATH_ELEM_TYPE_VIEWER_NODE = 4,
VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE = 5,
VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE = 5,
} ViewerPathElemType;
typedef struct ViewerPathElem {
@ -49,12 +49,12 @@ typedef struct SimulationZoneViewerPathElem {
char _pad1[4];
} SimulationZoneViewerPathElem;
typedef struct SerialLoopZoneViewerPathElem {
typedef struct RepeatZoneViewerPathElem {
ViewerPathElem base;
int loop_output_node_id;
int repeat_output_node_id;
int iteration;
} SerialLoopZoneViewerPathElem;
} RepeatZoneViewerPathElem;
typedef struct ViewerNodeViewerPathElem {
ViewerPathElem base;

View File

@ -4264,13 +4264,13 @@ static void rna_SimulationStateItem_update(Main *bmain, Scene * /*scene*/, Point
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
static bNode *find_node_by_serial_loop_item(PointerRNA *ptr)
static bNode *find_node_by_repeat_item(PointerRNA *ptr)
{
const NodeSerialLoopItem *item = static_cast<const NodeSerialLoopItem *>(ptr->data);
const NodeRepeatItem *item = static_cast<const NodeRepeatItem *>(ptr->data);
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
ntree->ensure_topology_cache();
for (bNode *node : ntree->nodes_by_type("GeometryNodeSerialLoopOutput")) {
auto *storage = static_cast<NodeGeometrySerialLoopOutput *>(node->storage);
for (bNode *node : ntree->nodes_by_type("GeometryNodeRepeatOutput")) {
auto *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
if (storage->items_span().contains_ptr(item)) {
return node;
}
@ -4278,10 +4278,10 @@ static bNode *find_node_by_serial_loop_item(PointerRNA *ptr)
return nullptr;
}
static void rna_SerialLoopItem_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr)
static void rna_RepeatItem_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
bNode *node = find_node_by_serial_loop_item(ptr);
bNode *node = find_node_by_repeat_item(ptr);
BKE_ntree_update_tag_node_property(ntree, node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
@ -4303,19 +4303,18 @@ static const EnumPropertyItem *rna_SimulationStateItem_socket_type_itemf(bContex
rna_SimulationStateItem_socket_type_supported);
}
static bool rna_SerialLoopItem_socket_type_supported(const EnumPropertyItem *item)
static bool rna_RepeatItem_socket_type_supported(const EnumPropertyItem *item)
{
return NodeSerialLoopItem::supports_type(eNodeSocketDatatype(item->value));
return NodeRepeatItem::supports_type(eNodeSocketDatatype(item->value));
}
static const EnumPropertyItem *rna_SerialLoopItem_socket_type_itemf(bContext * /*C*/,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
bool *r_free)
static const EnumPropertyItem *rna_RepeatItem_socket_type_itemf(bContext * /*C*/,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
bool *r_free)
{
*r_free = true;
return itemf_function_check(node_socket_data_type_items,
rna_SerialLoopItem_socket_type_supported);
return itemf_function_check(node_socket_data_type_items, rna_RepeatItem_socket_type_supported);
}
static void rna_SimulationStateItem_name_set(PointerRNA *ptr, const char *value)
@ -4329,11 +4328,11 @@ static void rna_SimulationStateItem_name_set(PointerRNA *ptr, const char *value)
NOD_geometry_simulation_output_item_set_unique_name(sim, item, value, defname);
}
static void rna_SerialLoopItem_name_set(PointerRNA *ptr, const char *value)
static void rna_RepeatItem_name_set(PointerRNA *ptr, const char *value)
{
bNode *node = find_node_by_serial_loop_item(ptr);
NodeSerialLoopItem *item = static_cast<NodeSerialLoopItem *>(ptr->data);
auto *storage = static_cast<NodeGeometrySerialLoopOutput *>(node->storage);
bNode *node = find_node_by_repeat_item(ptr);
NodeRepeatItem *item = static_cast<NodeRepeatItem *>(ptr->data);
auto *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
storage->set_item_name(*item, value);
}
@ -4345,9 +4344,9 @@ static void rna_SimulationStateItem_color_get(PointerRNA *ptr, float *values)
ED_node_type_draw_color(socket_type_idname, values);
}
static void rna_SerialLoopItem_color_get(PointerRNA *ptr, float *values)
static void rna_RepeatItem_color_get(PointerRNA *ptr, float *values)
{
NodeSerialLoopItem *item = static_cast<NodeSerialLoopItem *>(ptr->data);
NodeRepeatItem *item = static_cast<NodeRepeatItem *>(ptr->data);
const char *socket_type_idname = nodeStaticSocketType(item->socket_type, 0);
ED_node_type_draw_color(socket_type_idname, values);
@ -4363,11 +4362,11 @@ static PointerRNA rna_NodeGeometrySimulationInput_paired_output_get(PointerRNA *
return r_ptr;
}
static PointerRNA rna_NodeGeometrySerialLoopInput_paired_output_get(PointerRNA *ptr)
static PointerRNA rna_NodeGeometryRepeatInput_paired_output_get(PointerRNA *ptr)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
bNode *node = static_cast<bNode *>(ptr->data);
NodeGeometrySerialLoopInput *storage = static_cast<NodeGeometrySerialLoopInput *>(node->storage);
NodeGeometryRepeatInput *storage = static_cast<NodeGeometryRepeatInput *>(node->storage);
bNode *output_node = ntree->node_by_id(storage->output_node_id);
PointerRNA r_ptr;
RNA_pointer_create(&ntree->id, &RNA_Node, output_node, &r_ptr);
@ -4395,15 +4394,15 @@ static bool rna_GeometryNodeSimulationInput_pair_with_output(
return true;
}
static bool rna_GeometryNodeSerialLoopInput_pair_with_output(
static bool rna_GeometryNodeRepeatInput_pair_with_output(
ID *id, bNode *node, bContext *C, ReportList *reports, bNode *output_node)
{
bNodeTree *ntree = (bNodeTree *)id;
if (!NOD_geometry_serial_loop_input_pair_with_output(ntree, node, output_node)) {
if (!NOD_geometry_repeat_input_pair_with_output(ntree, node, output_node)) {
BKE_reportf(reports,
RPT_ERROR,
"Failed to pair serial loop input node %s with output node %s",
"Failed to pair repeat input node %s with output node %s",
node->name,
output_node->name);
return false;
@ -4436,12 +4435,11 @@ static NodeSimulationItem *rna_NodeGeometrySimulationOutput_items_new(
return item;
}
static NodeSerialLoopItem *rna_NodeGeometrySerialLoopOutput_items_new(
static NodeRepeatItem *rna_NodeGeometryRepeatOutput_items_new(
ID *id, bNode *node, Main *bmain, ReportList *reports, int socket_type, const char *name)
{
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
NodeSerialLoopItem *item = storage->add_item(name, eNodeSocketDatatype(socket_type));
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
NodeRepeatItem *item = storage->add_item(name, eNodeSocketDatatype(socket_type));
if (item == nullptr) {
BKE_report(reports, RPT_ERROR, "Unable to create socket");
}
@ -4472,19 +4470,18 @@ static void rna_NodeGeometrySimulationOutput_items_remove(
}
}
static void rna_NodeGeometrySerialLoopOutput_items_remove(
ID *id, bNode *node, Main *bmain, ReportList *reports, NodeSerialLoopItem *item)
static void rna_NodeGeometryRepeatOutput_items_remove(
ID *id, bNode *node, Main *bmain, ReportList *reports, NodeRepeatItem *item)
{
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
if (!storage->items_span().contains_ptr(item)) {
BKE_reportf(reports, RPT_ERROR, "Unable to locate item '%s' in node", item->name);
return;
}
const int remove_index = item - storage->items;
NodeSerialLoopItem *old_items = storage->items;
storage->items = MEM_cnew_array<NodeSerialLoopItem>(storage->items_num - 1, __func__);
NodeRepeatItem *old_items = storage->items;
storage->items = MEM_cnew_array<NodeRepeatItem>(storage->items_num - 1, __func__);
std::copy_n(old_items, remove_index, storage->items);
std::copy_n(old_items + remove_index + 1,
storage->items_num - remove_index - 1,
@ -4511,13 +4508,10 @@ static void rna_NodeGeometrySimulationOutput_items_clear(ID *id, bNode *node, Ma
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
static void rna_NodeGeometrySerialLoopOutput_items_clear(ID * /*id*/,
bNode *node,
Main * /*bmain*/)
static void rna_NodeGeometryRepeatOutput_items_clear(ID * /*id*/, bNode *node, Main * /*bmain*/)
{
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
for (NodeSerialLoopItem &item : storage->items_span()) {
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
for (NodeRepeatItem &item : storage->items_span()) {
MEM_SAFE_FREE(item.name);
}
MEM_SAFE_FREE(storage->items);
@ -4543,11 +4537,10 @@ static void rna_NodeGeometrySimulationOutput_items_move(
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
static void rna_NodeGeometrySerialLoopOutput_items_move(
static void rna_NodeGeometryRepeatOutput_items_move(
ID *id, bNode *node, Main *bmain, int from_index, int to_index)
{
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
if (from_index < 0 || from_index >= storage->items_num || to_index < 0 ||
to_index >= storage->items_num)
{
@ -4555,14 +4548,14 @@ static void rna_NodeGeometrySerialLoopOutput_items_move(
}
if (from_index < to_index) {
const NodeSerialLoopItem tmp = storage->items[from_index];
const NodeRepeatItem tmp = storage->items[from_index];
for (int i = from_index; i < to_index; i++) {
storage->items[i] = storage->items[i + 1];
}
storage->items[to_index] = tmp;
}
else if (from_index > to_index) {
const NodeSerialLoopItem tmp = storage->items[from_index];
const NodeRepeatItem tmp = storage->items[from_index];
for (int i = from_index; i > to_index; i--) {
storage->items[i] = storage->items[i - 1];
}
@ -4585,15 +4578,14 @@ static PointerRNA rna_NodeGeometrySimulationOutput_active_item_get(PointerRNA *p
return r_ptr;
}
static PointerRNA rna_NodeGeometrySerialLoopOutput_active_item_get(PointerRNA *ptr)
static PointerRNA rna_NodeGeometryRepeatOutput_active_item_get(PointerRNA *ptr)
{
bNode *node = static_cast<bNode *>(ptr->data);
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
blender::MutableSpan<NodeSerialLoopItem> items = storage->items_span();
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
blender::MutableSpan<NodeRepeatItem> items = storage->items_span();
PointerRNA r_ptr{};
if (items.index_range().contains(storage->active_index)) {
RNA_pointer_create(ptr->owner_id, &RNA_SerialLoopItem, &items[storage->active_index], &r_ptr);
RNA_pointer_create(ptr->owner_id, &RNA_RepeatItem, &items[storage->active_index], &r_ptr);
}
return r_ptr;
}
@ -4608,14 +4600,13 @@ static void rna_NodeGeometrySimulationOutput_active_item_set(PointerRNA *ptr,
static_cast<NodeSimulationItem *>(value.data));
}
static void rna_NodeGeometrySerialLoopOutput_active_item_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
static void rna_NodeGeometryRepeatOutput_active_item_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
{
bNode *node = static_cast<bNode *>(ptr->data);
NodeGeometrySerialLoopOutput *storage = static_cast<NodeGeometrySerialLoopOutput *>(
node->storage);
NodeSerialLoopItem *item = static_cast<NodeSerialLoopItem *>(value.data);
NodeGeometryRepeatOutput *storage = static_cast<NodeGeometryRepeatOutput *>(node->storage);
NodeRepeatItem *item = static_cast<NodeRepeatItem *>(value.data);
if (storage->items_span().contains_ptr(item)) {
storage->active_index = item - storage->items;
}
@ -10310,28 +10301,28 @@ static void def_geo_simulation_input(StructRNA *srna)
RNA_def_function_return(func, parm);
}
static void def_geo_serial_loop_input(StructRNA *srna)
static void def_geo_repeat_input(StructRNA *srna)
{
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_struct_sdna_from(srna, "NodeGeometrySerialLoopInput", "storage");
RNA_def_struct_sdna_from(srna, "NodeGeometryRepeatInput", "storage");
prop = RNA_def_property(srna, "paired_output", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Node");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_NodeGeometrySerialLoopInput_paired_output_get", nullptr, nullptr, nullptr);
prop, "rna_NodeGeometryRepeatInput_paired_output_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(
prop, "Paired Output", "Serial loop output node that this input node is paired with");
prop, "Paired Output", "Repeat output node that this input node is paired with");
func = RNA_def_function(
srna, "pair_with_output", "rna_GeometryNodeSerialLoopInput_pair_with_output");
RNA_def_function_ui_description(func, "Pair a serial loop input node with an output node.");
srna, "pair_with_output", "rna_GeometryNodeRepeatInput_pair_with_output");
RNA_def_function_ui_description(func, "Pair a repeat input node with an output node.");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "output_node", "GeometryNode", "Output Node", "Serial loop output node to pair with");
func, "output_node", "GeometryNode", "Output Node", "Repeat output node to pair with");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
/* return value */
parm = RNA_def_boolean(
@ -10454,47 +10445,47 @@ static void def_geo_simulation_output(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE, nullptr);
}
static void rna_def_serial_loop_item(BlenderRNA *brna)
static void rna_def_repeat_item(BlenderRNA *brna)
{
PropertyRNA *prop;
StructRNA *srna = RNA_def_struct(brna, "SerialLoopItem", nullptr);
RNA_def_struct_ui_text(srna, "Serial Loop Item", "");
RNA_def_struct_sdna(srna, "NodeSerialLoopItem");
StructRNA *srna = RNA_def_struct(brna, "RepeatItem", nullptr);
RNA_def_struct_ui_text(srna, "Repeat Item", "");
RNA_def_struct_sdna(srna, "NodeRepeatItem");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_SerialLoopItem_name_set");
RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_RepeatItem_name_set");
RNA_def_property_ui_text(prop, "Name", "");
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SerialLoopItem_update");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_RepeatItem_update");
prop = RNA_def_property(srna, "socket_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, node_socket_data_type_items);
RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_SerialLoopItem_socket_type_itemf");
RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_RepeatItem_socket_type_itemf");
RNA_def_property_ui_text(prop, "Socket Type", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SerialLoopItem_update");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_RepeatItem_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_float_funcs(prop, "rna_SerialLoopItem_color_get", nullptr, nullptr);
RNA_def_property_float_funcs(prop, "rna_RepeatItem_color_get", nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Color", "Color of the corresponding socket type in the node editor");
}
static void rna_def_geo_serial_loop_output_items(BlenderRNA *brna)
static void rna_def_geo_repeat_output_items(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
srna = RNA_def_struct(brna, "NodeGeometrySerialLoopOutputItems", nullptr);
srna = RNA_def_struct(brna, "NodeGeometryRepeatOutputItems", nullptr);
RNA_def_struct_sdna(srna, "bNode");
RNA_def_struct_ui_text(srna, "Items", "Collection of serial loop items");
RNA_def_struct_ui_text(srna, "Items", "Collection of repeat items");
func = RNA_def_function(srna, "new", "rna_NodeGeometrySerialLoopOutput_items_new");
RNA_def_function_ui_description(func, "Add a item to this serial loop zone");
func = RNA_def_function(srna, "new", "rna_NodeGeometryRepeatOutput_items_new");
RNA_def_function_ui_description(func, "Add a item to this repeat zone");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_enum(func,
"socket_type",
@ -10506,20 +10497,20 @@ static void rna_def_geo_serial_loop_output_items(BlenderRNA *brna)
parm = RNA_def_string(func, "name", nullptr, MAX_NAME, "Name", "");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
/* return value */
parm = RNA_def_pointer(func, "item", "SerialLoopItem", "Item", "New item");
parm = RNA_def_pointer(func, "item", "RepeatItem", "Item", "New item");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_NodeGeometrySerialLoopOutput_items_remove");
RNA_def_function_ui_description(func, "Remove an item from this serial loop zone");
func = RNA_def_function(srna, "remove", "rna_NodeGeometryRepeatOutput_items_remove");
RNA_def_function_ui_description(func, "Remove an item from this repeat zone");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "item", "SerialLoopItem", "Item", "The item to remove");
parm = RNA_def_pointer(func, "item", "RepeatItem", "Item", "The item to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
func = RNA_def_function(srna, "clear", "rna_NodeGeometrySerialLoopOutput_items_clear");
RNA_def_function_ui_description(func, "Remove all items from this serial loop zone");
func = RNA_def_function(srna, "clear", "rna_NodeGeometryRepeatOutput_items_clear");
RNA_def_function_ui_description(func, "Remove all items from this repeat zone");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
func = RNA_def_function(srna, "move", "rna_NodeGeometrySerialLoopOutput_items_move");
func = RNA_def_function(srna, "move", "rna_NodeGeometryRepeatOutput_items_move");
RNA_def_function_ui_description(func, "Move an item to another position");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
parm = RNA_def_int(
@ -10530,17 +10521,17 @@ static void rna_def_geo_serial_loop_output_items(BlenderRNA *brna)
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
}
static void def_geo_serial_loop_output(StructRNA *srna)
static void def_geo_repeat_output(StructRNA *srna)
{
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeGeometrySerialLoopOutput", "storage");
RNA_def_struct_sdna_from(srna, "NodeGeometryRepeatOutput", "storage");
prop = RNA_def_property(srna, "loop_items", PROP_COLLECTION, PROP_NONE);
prop = RNA_def_property(srna, "repeat_items", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, nullptr, "items", "items_num");
RNA_def_property_struct_type(prop, "SerialLoopItem");
RNA_def_property_struct_type(prop, "RepeatItem");
RNA_def_property_ui_text(prop, "Items", "");
RNA_def_property_srna(prop, "NodeGeometrySerialLoopOutputItems");
RNA_def_property_srna(prop, "NodeGeometryRepeatOutputItems");
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, nullptr, "active_index");
@ -10549,10 +10540,10 @@ static void def_geo_serial_loop_output(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE, nullptr);
prop = RNA_def_property(srna, "active_item", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "SerialLoopItem");
RNA_def_property_struct_type(prop, "RepeatItem");
RNA_def_property_pointer_funcs(prop,
"rna_NodeGeometrySerialLoopOutput_active_item_get",
"rna_NodeGeometrySerialLoopOutput_active_item_set",
"rna_NodeGeometryRepeatOutput_active_item_get",
"rna_NodeGeometryRepeatOutput_active_item_set",
nullptr,
nullptr);
RNA_def_property_flag(prop, PROP_EDITABLE);
@ -14087,7 +14078,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
rna_def_geometry_nodetree(brna);
rna_def_simulation_state_item(brna);
rna_def_serial_loop_item(brna);
rna_def_repeat_item(brna);
# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
{ \
@ -14140,7 +14131,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
rna_def_cmp_output_file_slot_file(brna);
rna_def_cmp_output_file_slot_layer(brna);
rna_def_geo_simulation_output_items(brna);
rna_def_geo_serial_loop_output_items(brna);
rna_def_geo_repeat_output_items(brna);
rna_def_node_instance_hash(brna);
}

View File

@ -3337,8 +3337,8 @@ static StructRNA *rna_viewer_path_elem_refine(PointerRNA *ptr)
return &RNA_SimulationZoneViewerPathElem;
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
return &RNA_ViewerNodeViewerPathElem;
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE:
return &RNA_SerialLoopZoneViewerPathElem;
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE:
return &RNA_RepeatZoneViewerPathElem;
}
BLI_assert_unreachable();
return nullptr;
@ -8081,7 +8081,7 @@ static const EnumPropertyItem viewer_path_elem_type_items[] = {
{VIEWER_PATH_ELEM_TYPE_GROUP_NODE, "GROUP_NODE", ICON_NONE, "Group Node", ""},
{VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE, "SIMULATION_ZONE", ICON_NONE, "Simulation Zone", ""},
{VIEWER_PATH_ELEM_TYPE_VIEWER_NODE, "VIEWER_NODE", ICON_NONE, "Viewer Node", ""},
{VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE, "SERIAL_LOOP_ZONE", ICON_NONE, "Serial Loop", ""},
{VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE, "REPEAT_ZONE", ICON_NONE, "Repeat", ""},
{0, nullptr, 0, nullptr, nullptr},
};
@ -8149,15 +8149,15 @@ static void rna_def_simulation_zone_viewer_path_elem(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simulation Output Node ID", "");
}
static void rna_def_serial_loop_zone_viewer_path_elem(BlenderRNA *brna)
static void rna_def_repeat_zone_viewer_path_elem(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SerialLoopZoneViewerPathElem", "ViewerPathElem");
srna = RNA_def_struct(brna, "RepeatZoneViewerPathElem", "ViewerPathElem");
prop = RNA_def_property(srna, "loop_output_node_id", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Loop Output Node ID", "");
prop = RNA_def_property(srna, "repeat_output_node_id", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Repeat Output Node ID", "");
}
static void rna_def_viewer_node_viewer_path_elem(BlenderRNA *brna)
@ -8181,7 +8181,7 @@ static void rna_def_viewer_path(BlenderRNA *brna)
rna_def_modifier_viewer_path_elem(brna);
rna_def_group_node_viewer_path_elem(brna);
rna_def_simulation_zone_viewer_path_elem(brna);
rna_def_serial_loop_zone_viewer_path_elem(brna);
rna_def_repeat_zone_viewer_path_elem(brna);
rna_def_viewer_node_viewer_path_elem(brna);
srna = RNA_def_struct(brna, "ViewerPath", nullptr);

View File

@ -3059,10 +3059,10 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simulation Zone", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "serial_loop_zone", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "node_zone_serial_loop");
prop = RNA_def_property(srna, "repeat_zone", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "node_zone_repeat");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Serial Loop Zone", "");
RNA_def_property_ui_text(prop, "Repeat Zone", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
}

View File

@ -482,10 +482,10 @@ static void find_side_effect_nodes_for_viewer_path(
zone = next_zone;
break;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto &typed_elem = *reinterpret_cast<const SerialLoopZoneViewerPathElem *>(elem);
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto &typed_elem = *reinterpret_cast<const RepeatZoneViewerPathElem *>(elem);
const bke::bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
typed_elem.loop_output_node_id);
typed_elem.repeat_output_node_id);
if (next_zone == nullptr) {
return;
}
@ -498,8 +498,8 @@ static void find_side_effect_nodes_for_viewer_path(
return;
}
local_side_effect_nodes.add(compute_context_builder.hash(), lf_zone_node);
compute_context_builder.push<bke::SerialLoopZoneComputeContext>(*next_zone->output_node,
typed_elem.iteration);
compute_context_builder.push<bke::RepeatZoneComputeContext>(*next_zone->output_node,
typed_elem.iteration);
zone = next_zone;
break;
}

View File

@ -24,9 +24,9 @@ bNode *NOD_geometry_simulation_input_get_paired_output(bNodeTree *node_tree,
bool NOD_geometry_simulation_input_pair_with_output(const bNodeTree *node_tree,
bNode *simulation_input_node,
const bNode *simulation_output_node);
bool NOD_geometry_serial_loop_input_pair_with_output(const bNodeTree *node_tree,
bNode *serial_loop_input_node,
const bNode *serial_loop_output_node);
bool NOD_geometry_repeat_input_pair_with_output(const bNodeTree *node_tree,
bNode *repeat_input_node,
const bNode *repeat_output_node);
/** \} */

View File

@ -396,6 +396,8 @@ DefNode(GeometryNode, GEO_NODE_PROXIMITY, def_geo_proximity, "PROXIMITY", Proxim
DefNode(GeometryNode, GEO_NODE_RAYCAST, def_geo_raycast, "RAYCAST", Raycast, "Raycast", "Cast rays from the context geometry onto a target geometry, and retrieve information from each hit point")
DefNode(GeometryNode, GEO_NODE_REALIZE_INSTANCES, 0, "REALIZE_INSTANCES", RealizeInstances, "Realize Instances", "Convert instances into real geometry data")
DefNode(GeometryNode, GEO_NODE_REMOVE_ATTRIBUTE, 0, "REMOVE_ATTRIBUTE", RemoveAttribute, "Remove Named Attribute", "Delete an attribute with a specified name from a geometry. Typically used to optimize performance")
DefNode(GeometryNode, GEO_NODE_REPEAT_INPUT, def_geo_repeat_input, "REPEAT_INPUT", RepeatInput, "Repeat Input", "")
DefNode(GeometryNode, GEO_NODE_REPEAT_OUTPUT, def_geo_repeat_output, "REPEAT_OUTPUT", RepeatOutput, "Repeat Output", "")
DefNode(GeometryNode, GEO_NODE_REPLACE_MATERIAL, 0, "REPLACE_MATERIAL", ReplaceMaterial, "Replace Material", "Swap one material with another")
DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, def_geo_curve_resample, "RESAMPLE_CURVE", ResampleCurve, "Resample Curve", "Generate a poly spline for each input spline")
DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "Change the direction of curves by swapping their start and end data")
@ -412,8 +414,6 @@ DefNode(GeometryNode, GEO_NODE_SDF_VOLUME_SPHERE, 0, "SDF_VOLUME_SPHERE", SDFVol
DefNode(GeometryNode, GEO_NODE_SELF_OBJECT, 0, "SELF_OBJECT", SelfObject, "Self Object", "Retrieve the object that contains the geometry nodes modifier currently being executed")
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components", "Split a geometry into a separate output for each type of data in the geometry")
DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "Split a geometry into two geometry outputs based on a selection")
DefNode(GeometryNode, GEO_NODE_SERIAL_LOOP_INPUT, def_geo_serial_loop_input, "SERIAL_LOOP_INPUT", SerialLoopInput, "Serial Loop Input", "")
DefNode(GeometryNode, GEO_NODE_SERIAL_LOOP_OUTPUT, def_geo_serial_loop_output, "SERIAL_LOOP_OUTPUT", SerialLoopOutput, "Serial Loop Output", "")
DefNode(GeometryNode, GEO_NODE_SET_CURVE_HANDLES, def_geo_curve_set_handle_positions, "SET_CURVE_HANDLES", SetCurveHandlePositions, "Set Handle Positions", "Set the positions for the handles of Bézier curves")
DefNode(GeometryNode, GEO_NODE_SET_CURVE_NORMAL, def_geo_set_curve_normal, "SET_CURVE_NORMAL", SetCurveNormal, "Set Curve Normal", "Set the evaluation mode for curve normals")
DefNode(GeometryNode, GEO_NODE_SET_CURVE_RADIUS, 0, "SET_CURVE_RADIUS", SetCurveRadius, "Set Curve Radius", "Set the radius of the curve at each control point")

View File

@ -152,6 +152,8 @@ set(SRC
nodes/node_geo_raycast.cc
nodes/node_geo_realize_instances.cc
nodes/node_geo_remove_attribute.cc
nodes/node_geo_repeat_input.cc
nodes/node_geo_repeat_output.cc
nodes/node_geo_rotate_instances.cc
nodes/node_geo_sample_index.cc
nodes/node_geo_sample_nearest.cc
@ -164,8 +166,6 @@ set(SRC
nodes/node_geo_self_object.cc
nodes/node_geo_separate_components.cc
nodes/node_geo_separate_geometry.cc
nodes/node_geo_serial_loop_input.cc
nodes/node_geo_serial_loop_output.cc
nodes/node_geo_set_curve_handles.cc
nodes/node_geo_set_curve_normal.cc
nodes/node_geo_set_curve_radius.cc

View File

@ -135,6 +135,8 @@ void register_geometry_nodes()
register_node_type_geo_raycast();
register_node_type_geo_realize_instances();
register_node_type_geo_remove_attribute();
register_node_type_geo_repeat_input();
register_node_type_geo_repeat_output();
register_node_type_geo_rotate_instances();
register_node_type_geo_sample_index();
register_node_type_geo_sample_nearest_surface();
@ -147,8 +149,6 @@ void register_geometry_nodes()
register_node_type_geo_self_object();
register_node_type_geo_separate_components();
register_node_type_geo_separate_geometry();
register_node_type_geo_serial_loop_input();
register_node_type_geo_serial_loop_output();
register_node_type_geo_set_curve_handles();
register_node_type_geo_set_curve_normal();
register_node_type_geo_set_curve_radius();

View File

@ -132,6 +132,8 @@ void register_node_type_geo_proximity();
void register_node_type_geo_raycast();
void register_node_type_geo_realize_instances();
void register_node_type_geo_remove_attribute();
void register_node_type_geo_repeat_input();
void register_node_type_geo_repeat_output();
void register_node_type_geo_rotate_instances();
void register_node_type_geo_sample_index();
void register_node_type_geo_sample_nearest_surface();
@ -145,8 +147,6 @@ void register_node_type_geo_select_by_handle_type();
void register_node_type_geo_self_object();
void register_node_type_geo_separate_components();
void register_node_type_geo_separate_geometry();
void register_node_type_geo_serial_loop_input();
void register_node_type_geo_serial_loop_output();
void register_node_type_geo_set_curve_handles();
void register_node_type_geo_set_curve_normal();
void register_node_type_geo_set_curve_radius();

View File

@ -154,7 +154,7 @@ void copy_with_checked_indices(const GVArray &src,
const IndexMask &mask,
GMutableSpan dst);
void socket_declarations_for_serial_loop_items(const Span<NodeSerialLoopItem> items,
NodeDeclaration &r_declaration);
void socket_declarations_for_repeat_items(const Span<NodeRepeatItem> items,
NodeDeclaration &r_declaration);
} // namespace blender::nodes

View File

@ -13,9 +13,9 @@
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_serial_loop_input_cc {
namespace blender::nodes::node_geo_repeat_input_cc {
NODE_STORAGE_FUNCS(NodeGeometrySerialLoopInput);
NODE_STORAGE_FUNCS(NodeGeometryRepeatInput);
static void node_declare_dynamic(const bNodeTree &tree,
const bNode &node,
@ -24,18 +24,18 @@ static void node_declare_dynamic(const bNodeTree &tree,
NodeDeclarationBuilder b{r_declaration};
b.add_input<decl::Int>(N_("Iterations")).min(0).default_value(1);
const NodeGeometrySerialLoopInput &storage = node_storage(node);
const NodeGeometryRepeatInput &storage = node_storage(node);
const bNode *output_node = tree.node_by_id(storage.output_node_id);
if (output_node != nullptr) {
const NodeGeometrySerialLoopOutput &output_storage =
*static_cast<const NodeGeometrySerialLoopOutput *>(output_node->storage);
socket_declarations_for_serial_loop_items(output_storage.items_span(), r_declaration);
const NodeGeometryRepeatOutput &output_storage =
*static_cast<const NodeGeometryRepeatOutput *>(output_node->storage);
socket_declarations_for_repeat_items(output_storage.items_span(), r_declaration);
}
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeGeometrySerialLoopInput *data = MEM_cnew<NodeGeometrySerialLoopInput>(__func__);
NodeGeometryRepeatInput *data = MEM_cnew<NodeGeometryRepeatInput>(__func__);
/* Needs to be initialized for the node to work. */
data->output_node_id = 0;
node->storage = data;
@ -47,11 +47,11 @@ static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
if (!output_node) {
return true;
}
auto &storage = *static_cast<NodeGeometrySerialLoopOutput *>(output_node->storage);
auto &storage = *static_cast<NodeGeometryRepeatOutput *>(output_node->storage);
if (link->tonode == node) {
if (link->tosock->identifier == StringRef("__extend__")) {
if (const NodeSerialLoopItem *item = storage.add_item(
link->fromsock->name, eNodeSocketDatatype(link->fromsock->type)))
if (const NodeRepeatItem *item = storage.add_item(link->fromsock->name,
eNodeSocketDatatype(link->fromsock->type)))
{
update_node_declaration_and_sockets(*ntree, *node);
link->tosock = nodeFindSocket(node, SOCK_IN, item->identifier_str().c_str());
@ -64,8 +64,8 @@ static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
}
if (link->fromnode == node) {
if (link->fromsock->identifier == StringRef("__extend__")) {
if (const NodeSerialLoopItem *item = storage.add_item(
link->tosock->name, eNodeSocketDatatype(link->tosock->type)))
if (const NodeRepeatItem *item = storage.add_item(link->tosock->name,
eNodeSocketDatatype(link->tosock->type)))
{
update_node_declaration_and_sockets(*ntree, *node);
link->fromsock = nodeFindSocket(node, SOCK_OUT, item->identifier_str().c_str());
@ -79,49 +79,46 @@ static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
return false;
}
} // namespace blender::nodes::node_geo_serial_loop_input_cc
} // namespace blender::nodes::node_geo_repeat_input_cc
void register_node_type_geo_serial_loop_input()
void register_node_type_geo_repeat_input()
{
namespace file_ns = blender::nodes::node_geo_serial_loop_input_cc;
namespace file_ns = blender::nodes::node_geo_repeat_input_cc;
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SERIAL_LOOP_INPUT, "Serial Loop Input", NODE_CLASS_INTERFACE);
geo_node_type_base(&ntype, GEO_NODE_REPEAT_INPUT, "Repeat Input", NODE_CLASS_INTERFACE);
ntype.initfunc = file_ns::node_init;
ntype.declare_dynamic = file_ns::node_declare_dynamic;
ntype.gather_add_node_search_ops = nullptr;
ntype.gather_link_search_ops = nullptr;
ntype.insert_link = file_ns::node_insert_link;
node_type_storage(&ntype,
"NodeGeometrySerialLoopInput",
node_free_standard_storage,
node_copy_standard_storage);
node_type_storage(
&ntype, "NodeGeometryRepeatInput", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
}
bool NOD_geometry_serial_loop_input_pair_with_output(const bNodeTree *node_tree,
bNode *serial_loop_input_node,
const bNode *serial_loop_output_node)
bool NOD_geometry_repeat_input_pair_with_output(const bNodeTree *node_tree,
bNode *repeat_input_node,
const bNode *repeat_output_node)
{
namespace file_ns = blender::nodes::node_geo_serial_loop_input_cc;
namespace file_ns = blender::nodes::node_geo_repeat_input_cc;
BLI_assert(serial_loop_input_node->type == GEO_NODE_SERIAL_LOOP_INPUT);
if (serial_loop_output_node->type != GEO_NODE_SERIAL_LOOP_OUTPUT) {
BLI_assert(repeat_input_node->type == GEO_NODE_REPEAT_INPUT);
if (repeat_output_node->type != GEO_NODE_REPEAT_OUTPUT) {
return false;
}
/* Allow only one input paired to an output. */
for (const bNode *other_input_node : node_tree->nodes_by_type("GeometryNodeSerialLoopInput")) {
if (other_input_node != serial_loop_input_node) {
const NodeGeometrySerialLoopInput &other_storage = file_ns::node_storage(*other_input_node);
if (other_storage.output_node_id == serial_loop_output_node->identifier) {
for (const bNode *other_input_node : node_tree->nodes_by_type("GeometryNodeRepeatInput")) {
if (other_input_node != repeat_input_node) {
const NodeGeometryRepeatInput &other_storage = file_ns::node_storage(*other_input_node);
if (other_storage.output_node_id == repeat_output_node->identifier) {
return false;
}
}
}
NodeGeometrySerialLoopInput &storage = file_ns::node_storage(*serial_loop_input_node);
storage.output_node_id = serial_loop_output_node->identifier;
NodeGeometryRepeatInput &storage = file_ns::node_storage(*repeat_input_node);
storage.output_node_id = repeat_output_node->identifier;
return true;
}

View File

@ -18,10 +18,8 @@
namespace blender::nodes {
static std::unique_ptr<SocketDeclaration> socket_declaration_for_serial_loop_item(
const NodeSerialLoopItem &item,
const eNodeSocketInOut in_out,
const int corresponding_input = -1)
static std::unique_ptr<SocketDeclaration> socket_declaration_for_repeat_item(
const NodeRepeatItem &item, const eNodeSocketInOut in_out, const int corresponding_input = -1)
{
const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
@ -91,43 +89,42 @@ static std::unique_ptr<SocketDeclaration> socket_declaration_for_serial_loop_ite
return decl;
}
void socket_declarations_for_serial_loop_items(const Span<NodeSerialLoopItem> items,
NodeDeclaration &r_declaration)
void socket_declarations_for_repeat_items(const Span<NodeRepeatItem> items,
NodeDeclaration &r_declaration)
{
for (const int i : items.index_range()) {
const NodeSerialLoopItem &item = items[i];
r_declaration.inputs.append(socket_declaration_for_serial_loop_item(item, SOCK_IN));
const NodeRepeatItem &item = items[i];
r_declaration.inputs.append(socket_declaration_for_repeat_item(item, SOCK_IN));
r_declaration.outputs.append(
socket_declaration_for_serial_loop_item(item, SOCK_OUT, r_declaration.inputs.size() - 1));
socket_declaration_for_repeat_item(item, SOCK_OUT, r_declaration.inputs.size() - 1));
}
r_declaration.inputs.append(decl::create_extend_declaration(SOCK_IN));
r_declaration.outputs.append(decl::create_extend_declaration(SOCK_OUT));
}
} // namespace blender::nodes
namespace blender::nodes::node_geo_serial_loop_output_cc {
namespace blender::nodes::node_geo_repeat_output_cc {
NODE_STORAGE_FUNCS(NodeGeometrySerialLoopOutput);
NODE_STORAGE_FUNCS(NodeGeometryRepeatOutput);
static void node_declare_dynamic(const bNodeTree & /*node_tree*/,
const bNode &node,
NodeDeclaration &r_declaration)
{
const NodeGeometrySerialLoopOutput &storage = node_storage(node);
socket_declarations_for_serial_loop_items(storage.items_span(), r_declaration);
const NodeGeometryRepeatOutput &storage = node_storage(node);
socket_declarations_for_repeat_items(storage.items_span(), r_declaration);
}
static void search_node_add_ops(GatherAddNodeSearchParams &params)
{
AddNodeItem item;
item.ui_name = IFACE_("Serial Loop Zone");
item.description = TIP_("Add a new serial loop input and output nodes to the node tree");
item.ui_name = IFACE_("Repeat Zone");
item.description = TIP_("Add a new repeat input and output nodes to the node tree");
item.add_fn = [](const bContext &C, bNodeTree &node_tree, float2 cursor) {
bNode *input = nodeAddNode(&C, &node_tree, "GeometryNodeSerialLoopInput");
bNode *output = nodeAddNode(&C, &node_tree, "GeometryNodeSerialLoopOutput");
static_cast<NodeGeometrySerialLoopInput *>(input->storage)->output_node_id =
output->identifier;
bNode *input = nodeAddNode(&C, &node_tree, "GeometryNodeRepeatInput");
bNode *output = nodeAddNode(&C, &node_tree, "GeometryNodeRepeatOutput");
static_cast<NodeGeometryRepeatInput *>(input->storage)->output_node_id = output->identifier;
NodeSerialLoopItem &item = node_storage(*output).items[0];
NodeRepeatItem &item = node_storage(*output).items[0];
update_node_declaration_and_sockets(node_tree, *input);
update_node_declaration_and_sockets(node_tree, *output);
@ -151,11 +148,11 @@ static void search_node_add_ops(GatherAddNodeSearchParams &params)
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeGeometrySerialLoopOutput *data = MEM_cnew<NodeGeometrySerialLoopOutput>(__func__);
NodeGeometryRepeatOutput *data = MEM_cnew<NodeGeometryRepeatOutput>(__func__);
data->next_identifier = 0;
data->items = MEM_cnew_array<NodeSerialLoopItem>(1, __func__);
data->items = MEM_cnew_array<NodeRepeatItem>(1, __func__);
data->items[0].name = BLI_strdup(DATA_("Geometry"));
data->items[0].socket_type = SOCK_GEOMETRY;
data->items[0].identifier = data->next_identifier++;
@ -166,8 +163,8 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
static void node_free_storage(bNode *node)
{
NodeGeometrySerialLoopOutput &storage = node_storage(*node);
for (NodeSerialLoopItem &item : storage.items_span()) {
NodeGeometryRepeatOutput &storage = node_storage(*node);
for (NodeRepeatItem &item : storage.items_span()) {
MEM_SAFE_FREE(item.name);
}
MEM_SAFE_FREE(storage.items);
@ -176,10 +173,10 @@ static void node_free_storage(bNode *node)
static void node_copy_storage(bNodeTree * /*dst_tree*/, bNode *dst_node, const bNode *src_node)
{
const NodeGeometrySerialLoopOutput &src_storage = node_storage(*src_node);
NodeGeometrySerialLoopOutput *dst_storage = MEM_cnew<NodeGeometrySerialLoopOutput>(__func__);
const NodeGeometryRepeatOutput &src_storage = node_storage(*src_node);
NodeGeometryRepeatOutput *dst_storage = MEM_cnew<NodeGeometryRepeatOutput>(__func__);
dst_storage->items = MEM_cnew_array<NodeSerialLoopItem>(src_storage.items_num, __func__);
dst_storage->items = MEM_cnew_array<NodeRepeatItem>(src_storage.items_num, __func__);
dst_storage->items_num = src_storage.items_num;
dst_storage->active_index = src_storage.active_index;
dst_storage->next_identifier = src_storage.next_identifier;
@ -196,11 +193,11 @@ static void node_copy_storage(bNodeTree * /*dst_tree*/, bNode *dst_node, const b
static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
{
NodeGeometrySerialLoopOutput &storage = node_storage(*node);
NodeGeometryRepeatOutput &storage = node_storage(*node);
if (link->tonode == node) {
if (link->tosock->identifier == StringRef("__extend__")) {
if (const NodeSerialLoopItem *item = storage.add_item(
link->fromsock->name, eNodeSocketDatatype(link->fromsock->type)))
if (const NodeRepeatItem *item = storage.add_item(link->fromsock->name,
eNodeSocketDatatype(link->fromsock->type)))
{
update_node_declaration_and_sockets(*ntree, *node);
link->tosock = nodeFindSocket(node, SOCK_IN, item->identifier_str().c_str());
@ -213,8 +210,8 @@ static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
}
if (link->fromnode == node) {
if (link->fromsock->identifier == StringRef("__extend__")) {
if (const NodeSerialLoopItem *item = storage.add_item(
link->tosock->name, eNodeSocketDatatype(link->tosock->type)))
if (const NodeRepeatItem *item = storage.add_item(link->tosock->name,
eNodeSocketDatatype(link->tosock->type)))
{
update_node_declaration_and_sockets(*ntree, *node);
link->fromsock = nodeFindSocket(node, SOCK_OUT, item->identifier_str().c_str());
@ -228,19 +225,19 @@ static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
return false;
}
} // namespace blender::nodes::node_geo_serial_loop_output_cc
} // namespace blender::nodes::node_geo_repeat_output_cc
blender::Span<NodeSerialLoopItem> NodeGeometrySerialLoopOutput::items_span() const
blender::Span<NodeRepeatItem> NodeGeometryRepeatOutput::items_span() const
{
return blender::Span<NodeSerialLoopItem>(items, items_num);
return blender::Span<NodeRepeatItem>(items, items_num);
}
blender::MutableSpan<NodeSerialLoopItem> NodeGeometrySerialLoopOutput::items_span()
blender::MutableSpan<NodeRepeatItem> NodeGeometryRepeatOutput::items_span()
{
return blender::MutableSpan<NodeSerialLoopItem>(items, items_num);
return blender::MutableSpan<NodeRepeatItem>(items, items_num);
}
bool NodeSerialLoopItem::supports_type(const eNodeSocketDatatype type)
bool NodeRepeatItem::supports_type(const eNodeSocketDatatype type)
{
return ELEM(type,
SOCK_FLOAT,
@ -257,23 +254,23 @@ bool NodeSerialLoopItem::supports_type(const eNodeSocketDatatype type)
SOCK_COLLECTION);
}
std::string NodeSerialLoopItem::identifier_str() const
std::string NodeRepeatItem::identifier_str() const
{
return "Item_" + std::to_string(this->identifier);
}
NodeSerialLoopItem *NodeGeometrySerialLoopOutput::add_item(const char *name,
const eNodeSocketDatatype type)
NodeRepeatItem *NodeGeometryRepeatOutput::add_item(const char *name,
const eNodeSocketDatatype type)
{
if (!NodeSerialLoopItem::supports_type(type)) {
if (!NodeRepeatItem::supports_type(type)) {
return nullptr;
}
const int insert_index = this->items_num;
NodeSerialLoopItem *old_items = this->items;
NodeRepeatItem *old_items = this->items;
this->items = MEM_cnew_array<NodeSerialLoopItem>(this->items_num + 1, __func__);
this->items = MEM_cnew_array<NodeRepeatItem>(this->items_num + 1, __func__);
std::copy_n(old_items, insert_index, this->items);
NodeSerialLoopItem &new_item = this->items[insert_index];
NodeRepeatItem &new_item = this->items[insert_index];
std::copy_n(old_items + insert_index + 1,
this->items_num - insert_index,
this->items + insert_index + 1);
@ -287,21 +284,21 @@ NodeSerialLoopItem *NodeGeometrySerialLoopOutput::add_item(const char *name,
return &new_item;
}
void NodeGeometrySerialLoopOutput::set_item_name(NodeSerialLoopItem &item, const char *name)
void NodeGeometryRepeatOutput::set_item_name(NodeRepeatItem &item, const char *name)
{
char unique_name[MAX_NAME + 4];
STRNCPY(unique_name, name);
struct Args {
NodeGeometrySerialLoopOutput *storage;
const NodeSerialLoopItem *item;
NodeGeometryRepeatOutput *storage;
const NodeRepeatItem *item;
} args = {this, &item};
const char *default_name = nodeStaticSocketLabel(item.socket_type, 0);
BLI_uniquename_cb(
[](void *arg, const char *name) {
const Args &args = *static_cast<Args *>(arg);
for (const NodeSerialLoopItem &item : args.storage->items_span()) {
for (const NodeRepeatItem &item : args.storage->items_span()) {
if (&item != args.item) {
if (STREQ(item.name, name)) {
return true;
@ -320,20 +317,17 @@ void NodeGeometrySerialLoopOutput::set_item_name(NodeSerialLoopItem &item, const
item.name = BLI_strdup(unique_name);
}
void register_node_type_geo_serial_loop_output()
void register_node_type_geo_repeat_output()
{
namespace file_ns = blender::nodes::node_geo_serial_loop_output_cc;
namespace file_ns = blender::nodes::node_geo_repeat_output_cc;
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SERIAL_LOOP_OUTPUT, "Serial Loop Output", NODE_CLASS_INTERFACE);
geo_node_type_base(&ntype, GEO_NODE_REPEAT_OUTPUT, "Repeat Output", NODE_CLASS_INTERFACE);
ntype.initfunc = file_ns::node_init;
ntype.declare_dynamic = file_ns::node_declare_dynamic;
ntype.gather_add_node_search_ops = file_ns::search_node_add_ops;
ntype.insert_link = file_ns::node_insert_link;
node_type_storage(&ntype,
"NodeGeometrySerialLoopOutput",
file_ns::node_free_storage,
file_ns::node_copy_storage);
node_type_storage(
&ntype, "NodeGeometryRepeatOutput", file_ns::node_free_storage, file_ns::node_copy_storage);
nodeRegisterType(&ntype);
}

View File

@ -837,8 +837,8 @@ std::optional<bke::sim::SimulationZoneID> get_simulation_zone_id(
if (const auto *node_context = dynamic_cast<const bke::NodeGroupComputeContext *>(context)) {
node_ids.append(node_context->node_id());
}
else if (dynamic_cast<const bke::SerialLoopZoneComputeContext *>(context) != nullptr) {
/* Simulation can't be used in a loop. */
else if (dynamic_cast<const bke::RepeatZoneComputeContext *>(context) != nullptr) {
/* Simulation can't be used in a repeat zone. */
return std::nullopt;
}
}

View File

@ -1424,9 +1424,9 @@ struct ZoneBuildInfo {
/**
* Describes what the individual inputs and outputs of the #LazyFunction mean that's created for
* the serial loop body.
* the repeat body.
*/
struct SerialLoopBodyIndices {
struct RepeatBodyIndices {
IndexRange main_inputs;
IndexRange main_outputs;
IndexRange border_link_inputs;
@ -1436,34 +1436,34 @@ struct SerialLoopBodyIndices {
IndexRange border_link_usages;
/**
JacquesLucke marked this conversation as resolved Outdated

Could use some comments IMO, this name is pretty tricky to parse

Could use some comments IMO, this name is pretty tricky to parse
* Some anonymous attribute sets are input into the loop body from the outside. These two maps
* indicate which loop body input corresponds to attribute set. Attribute sets are identified by
* either a "field source index" or "caller propagation index".
* Some anonymous attribute sets are input into the repeat body from the outside. These two maps
* indicate which repeat body input corresponds to attribute set. Attribute sets are identified
* by either a "field source index" or "caller propagation index".
*/
Map<int, int> attribute_set_input_by_field_source_index;
Map<int, int> attribute_set_input_by_caller_propagation_index;
};
class LazyFunctionForSerialLoopZone : public LazyFunction {
class LazyFunctionForRepeatZone : public LazyFunction {
private:
const bNodeTreeZone &zone_;
const bNode &loop_output_bnode_;
const bNode &repeat_output_bnode_;
const ZoneBuildInfo &zone_info_;
const LazyFunction &body_fn_;
const SerialLoopBodyIndices &body_indices_;
const RepeatBodyIndices &body_indices_;
public:
LazyFunctionForSerialLoopZone(const bNodeTreeZone &zone,
ZoneBuildInfo &zone_info,
const LazyFunction &body_fn,
const SerialLoopBodyIndices &body_indices)
LazyFunctionForRepeatZone(const bNodeTreeZone &zone,
ZoneBuildInfo &zone_info,
const LazyFunction &body_fn,
const RepeatBodyIndices &body_indices)
: zone_(zone),
loop_output_bnode_(*zone.output_node),
repeat_output_bnode_(*zone.output_node),
zone_info_(zone_info),
body_fn_(body_fn),
body_indices_(body_indices)
{
debug_name_ = "Serial Loop Zone";
debug_name_ = "Repeat Zone";
for (const bNodeSocket *socket : zone.input_node->input_sockets().drop_back(1)) {
inputs_.append_as(socket->name, *socket->typeinfo->geometry_nodes_cpp_type);
@ -1512,39 +1512,39 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
{
GeoNodesLFUserData &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
const NodeGeometrySerialLoopOutput &node_storage =
*static_cast<const NodeGeometrySerialLoopOutput *>(loop_output_bnode_.storage);
const NodeGeometryRepeatOutput &node_storage = *static_cast<const NodeGeometryRepeatOutput *>(
repeat_output_bnode_.storage);
/* Number of iterations to evaluate. */
const int iterations = std::max<int>(
0, params.get_input<ValueOrField<int>>(zone_info_.main_input_indices[0]).as_value());
const int loop_items_num = node_storage.items_num;
/* Gather data types of the loop items. */
Array<const CPPType *> loop_item_types(loop_items_num);
const int repeat_items_num = node_storage.items_num;
/* Gather data types of the repeat items. */
Array<const CPPType *> repeat_item_types(repeat_items_num);
for (const int i : body_indices_.main_inputs.index_range()) {
const int input_i = body_indices_.main_inputs[i];
const CPPType &type = *body_fn_.inputs()[input_i].type;
loop_item_types[i] = &type;
repeat_item_types[i] = &type;
}
LinearAllocator<> allocator;
Array<void *, 64> loop_item_values((iterations + 1) * loop_items_num, nullptr);
Array<void *, 64> repeat_item_values((iterations + 1) * repeat_items_num, nullptr);
/* Allocate memory for the looped values. */
for (const int iteration : IndexRange(iterations)) {
MutableSpan<void *> item_values = loop_item_values.as_mutable_span().slice(
(iteration + 1) * loop_items_num, loop_items_num);
for (const int item_i : IndexRange(loop_items_num)) {
const CPPType &type = *loop_item_types[item_i];
MutableSpan<void *> item_values = repeat_item_values.as_mutable_span().slice(
(iteration + 1) * repeat_items_num, repeat_items_num);
for (const int item_i : IndexRange(repeat_items_num)) {
const CPPType &type = *repeat_item_types[item_i];
void *buffer = allocator.allocate(type.size(), type.alignment());
item_values[item_i] = buffer;
}
}
/* Load the inputs of the first loop iteration. */
MutableSpan<void *> first_item_values = loop_item_values.as_mutable_span().take_front(
loop_items_num);
for (const int i : IndexRange(loop_items_num)) {
/* Load the inputs of the first repeat iteration. */
MutableSpan<void *> first_item_values = repeat_item_values.as_mutable_span().take_front(
repeat_items_num);
for (const int i : IndexRange(repeat_items_num)) {
/* +1 because of the iterations input. */
const int input_index = zone_info_.main_input_indices[i + 1];
void *value = params.try_get_input_data_ptr(input_index);
@ -1562,7 +1562,7 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
border_link_input_values[i] = value;
}
/* Load attribute sets that are needed to propagate attributes correctly in the loop. */
/* Load attribute sets that are needed to propagate attributes correctly in the zone. */
Map<int, bke::AnonymousAttributeSet *> attribute_set_by_field_source_index;
Map<int, bke::AnonymousAttributeSet *> attribute_set_by_caller_propagation_index;
for (const auto item : zone_info_.attribute_set_input_by_field_source_index.items()) {
@ -1578,23 +1578,23 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
const int body_inputs_num = body_fn_.inputs().size();
const int body_outputs_num = body_fn_.outputs().size();
/* Evaluate the loop eagerly, one iteration at a time.
/* Evaluate the repeat zone eagerly, one iteration at a time.
* This can be made more lazy as a separate step. */
for (const int iteration : IndexRange(iterations)) {
/* Prepare all data that has to be passed into the evaluation of the loop body. */
/* Prepare all data that has to be passed into the evaluation of the repeat zone body. */
Array<GMutablePointer> inputs(body_inputs_num);
JacquesLucke marked this conversation as resolved
Review

I think this would be easier to read if there were comments describing what each block of code did. Even if it's "obvious" when you read the code, it would help when skimming it. For example "Retrieve inputs from outside the loop" or something. "Destruct values that are not needed after the evaluation anymore" already does that here.

I think this would be easier to read if there were comments describing what each block of code did. Even if it's "obvious" when you read the code, it would help when skimming it. For example "Retrieve inputs from outside the loop" or something. "Destruct values that are not needed after the evaluation anymore" already does that here.
Array<GMutablePointer> outputs(body_outputs_num);
Array<std::optional<lf::ValueUsage>> input_usages(body_inputs_num);
Array<lf::ValueUsage> output_usages(body_outputs_num, lf::ValueUsage::Used);
Array<bool> set_outputs(body_outputs_num, false);
/* Prepare pointers to the main input and output values of the loop,
/* Prepare pointers to the main input and output values of the repeat zone,
* as well as their usages. */
Array<bool> tmp_main_input_usages(loop_items_num);
for (const int i : IndexRange(loop_items_num)) {
const CPPType &type = *loop_item_types[i];
void *prev_value = loop_item_values[iteration * loop_items_num + i];
void *next_value = loop_item_values[(iteration + 1) * loop_items_num + i];
Array<bool> tmp_main_input_usages(repeat_items_num);
for (const int i : IndexRange(repeat_items_num)) {
const CPPType &type = *repeat_item_types[i];
void *prev_value = repeat_item_values[iteration * repeat_items_num + i];
void *next_value = repeat_item_values[(iteration + 1) * repeat_items_num + i];
inputs[body_indices_.main_inputs[i]] = {type, prev_value};
outputs[body_indices_.main_outputs[i]] = {type, next_value};
outputs[body_indices_.main_input_usages[i]] = &tmp_main_input_usages[i];
@ -1604,7 +1604,7 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
/* All main outputs are used currently. */
inputs[input_index] = &static_true;
}
/* Prepare border link values for the loop body. */
/* Prepare border link values for the repeat body. */
Array<bool> tmp_border_link_usages(border_links_num);
for (const int i : IndexRange(border_links_num)) {
const int input_index = body_indices_.border_link_inputs[i];
@ -1618,7 +1618,7 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
outputs[usage_index] = &tmp_border_link_usages[i];
}
/* Prepare attribute sets that are passed into the loop body. */
/* Prepare attribute sets that are passed into the repeat body. */
for (const auto item : body_indices_.attribute_set_input_by_field_source_index.items()) {
bke::AnonymousAttributeSet &attribute_set =
*allocator
@ -1637,9 +1637,9 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
inputs[item.value] = &attribute_set;
}
/* Prepare evaluation context for the loop body. */
bke::SerialLoopZoneComputeContext body_compute_context{
user_data.compute_context, loop_output_bnode_, iteration};
/* Prepare evaluation context for the repeat body. */
bke::RepeatZoneComputeContext body_compute_context{
user_data.compute_context, repeat_output_bnode_, iteration};
GeoNodesLFUserData body_user_data = user_data;
body_user_data.compute_context = &body_compute_context;
if (user_data.modifier_data->socket_log_contexts) {
@ -1652,7 +1652,7 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
lf::BasicParams body_params{
body_fn_, inputs, outputs, input_usages, output_usages, set_outputs};
/* Actually evaluate the loop body. */
/* Actually evaluate the repeat body. */
body_fn_.execute(body_params, body_context);
/* Destruct values that are not needed after the evaluation anymore. */
@ -1668,12 +1668,12 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
}
}
/* Set outputs of the serial loop zone. */
for (const int i : IndexRange(loop_items_num)) {
void *computed_value = loop_item_values[iterations * loop_items_num + i];
/* Set outputs of the repeat zone. */
for (const int i : IndexRange(repeat_items_num)) {
void *computed_value = repeat_item_values[iterations * repeat_items_num + i];
const int output_index = zone_info_.main_output_indices[i];
void *r_value = params.get_output_data_ptr(output_index);
const CPPType &type = *loop_item_types[i];
const CPPType &type = *repeat_item_types[i];
type.move_construct(computed_value, r_value);
params.output_set(output_index);
}
@ -1686,10 +1686,10 @@ class LazyFunctionForSerialLoopZone : public LazyFunction {
/* Destruct remaining values. */
for (const int iteration : IndexRange(iterations)) {
MutableSpan<void *> item_values = loop_item_values.as_mutable_span().slice(
(iteration + 1) * loop_items_num, loop_items_num);
for (const int item_i : IndexRange(loop_items_num)) {
const CPPType &type = *loop_item_types[item_i];
MutableSpan<void *> item_values = repeat_item_values.as_mutable_span().slice(
(iteration + 1) * repeat_items_num, repeat_items_num);
for (const int item_i : IndexRange(repeat_items_num)) {
const CPPType &type = *repeat_item_types[item_i];
type.destruct(item_values[item_i]);
}
}
@ -1799,8 +1799,8 @@ struct GeometryNodesLazyFunctionGraphBuilder {
this->build_simulation_zone_function(zone);
break;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
this->build_serial_loop_zone_function(zone);
case GEO_NODE_REPEAT_OUTPUT: {
this->build_repeat_zone_function(zone);
break;
}
default: {
@ -1965,11 +1965,11 @@ struct GeometryNodesLazyFunctionGraphBuilder {
}
/**
* Builds a #LazyFunction for a serial loop zone. For that it first builds a lazy-function graph
* Builds a #LazyFunction for a repeat zone. For that it first builds a lazy-function graph
* from all the nodes in the zone, and then wraps that in another lazy-function that implements
* the looping behavior.
* the repeating behavior.
*/
void build_serial_loop_zone_function(const bNodeTreeZone &zone)
void build_repeat_zone_function(const bNodeTreeZone &zone)
{
ZoneBuildInfo &zone_info = zone_build_infos_[zone.index];
lf::Graph &lf_body_graph = scope_.construct<lf::Graph>();
@ -1978,10 +1978,10 @@ struct GeometryNodesLazyFunctionGraphBuilder {
Vector<const lf::OutputSocket *, 16> lf_body_inputs;
Vector<const lf::InputSocket *, 16> lf_body_outputs;
SerialLoopBodyIndices &body_indices = scope_.construct<SerialLoopBodyIndices>();
RepeatBodyIndices &body_indices = scope_.construct<RepeatBodyIndices>();
lf::DummyNode &lf_main_input_node = this->build_dummy_node_for_sockets(
"Loop Input", {}, zone.input_node->output_sockets().drop_back(1), lf_body_graph);
"Repeat Input", {}, zone.input_node->output_sockets().drop_back(1), lf_body_graph);
for (const int i : zone.input_node->output_sockets().drop_back(1).index_range()) {
const bNodeSocket &bsocket = zone.input_node->output_socket(i);
lf::OutputSocket &lf_socket = lf_main_input_node.output(i);
@ -1991,7 +1991,7 @@ struct GeometryNodesLazyFunctionGraphBuilder {
body_indices.main_inputs = lf_body_inputs.index_range();
lf::DummyNode &lf_main_output_node = this->build_dummy_node_for_sockets(
"Loop Output", zone.output_node->input_sockets().drop_back(1), {}, lf_body_graph);
"Repeat Output", zone.output_node->input_sockets().drop_back(1), {}, lf_body_graph);
lf_body_outputs.extend(lf_main_output_node.inputs());
body_indices.main_outputs = lf_body_outputs.index_range();
@ -2088,7 +2088,7 @@ struct GeometryNodesLazyFunctionGraphBuilder {
// std::cout << "\n\n" << lf_body_graph.to_dot() << "\n\n";
auto &fn = scope_.construct<LazyFunctionForSerialLoopZone>(
auto &fn = scope_.construct<LazyFunctionForRepeatZone>(
zone, zone_info, body_graph_fn, body_indices);
zone_info.lazy_function = &fn;
}
@ -3793,7 +3793,7 @@ const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_gr
}
for (const std::unique_ptr<bNodeTreeZone> &zone : tree_zones->zones) {
if (zone->input_node == nullptr || zone->output_node == nullptr) {
/* Simulations and serial loops need input and output nodes. */
/* Simulations and repeats need input and output nodes. */
return nullptr;
}
}

View File

@ -530,11 +530,10 @@ static void find_tree_zone_hash_recursive(
compute_context_builder.push<bke::SimulationZoneComputeContext>(*zone.output_node);
break;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
case GEO_NODE_REPEAT_OUTPUT: {
/* Only show data from the first iteration for now. */
const int iteration = 0;
compute_context_builder.push<bke::SerialLoopZoneComputeContext>(*zone.output_node,
iteration);
compute_context_builder.push<bke::RepeatZoneComputeContext>(*zone.output_node, iteration);
break;
}
}
@ -575,11 +574,11 @@ Map<const bNodeTreeZone *, ComputeContextHash> GeoModifierLog::
compute_context_builder.push<bke::SimulationZoneComputeContext>(*zone->output_node);
break;
}
case GEO_NODE_SERIAL_LOOP_OUTPUT: {
case GEO_NODE_REPEAT_OUTPUT: {
/* Only show data from the first iteration for now. */
const int loop_iteration = 0;
compute_context_builder.push<bke::SerialLoopZoneComputeContext>(*zone->output_node,
loop_iteration);
const int repeat_iteration = 0;
compute_context_builder.push<bke::RepeatZoneComputeContext>(*zone->output_node,
repeat_iteration);
break;
}
}
@ -662,10 +661,10 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP
typed_elem.sim_output_node_id);
break;
}
case VIEWER_PATH_ELEM_TYPE_SERIAL_LOOP_ZONE: {
const auto &typed_elem = *reinterpret_cast<const SerialLoopZoneViewerPathElem *>(elem);
compute_context_builder.push<bke::SerialLoopZoneComputeContext>(
typed_elem.loop_output_node_id, typed_elem.iteration);
case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: {
const auto &typed_elem = *reinterpret_cast<const RepeatZoneViewerPathElem *>(elem);
compute_context_builder.push<bke::RepeatZoneComputeContext>(
typed_elem.repeat_output_node_id, typed_elem.iteration);
break;
}
default: {

View File

@ -708,7 +708,7 @@ set(geo_node_tests
curves/interpolate_curves
geometry
instance
serial_loops
repeat_zone
mesh_primitives
mesh
mesh/extrude