#ifndef PROC_NODES_SELECTION_NODES_H
#define PROC_NODES_SELECTION_NODES_H
#include "../graph/proc_node.h"
namespace godot {
// Delete Geometry — remove elements where selection is true
class DeleteGeometryNode : public ProcNode {
GDCLASS(DeleteGeometryNode, ProcNode);
protected:
static void _bind_methods();
int delete_domain = 0; // 0=Point, 2=Face
public:
StringName get_node_type() const override { return "DeleteGeometry"; }
String get_node_title() const override { return "Delete Geometry"; }
String get_node_category() const override { return "Geometry"; }
void set_delete_domain(int p_domain) { delete_domain = p_domain; }
int get_delete_domain() const { return delete_domain; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
DeleteGeometryNode();
};
// Bounding Box — outputs min/max corners of geometry
class BoundingBoxNode : public ProcNode {
GDCLASS(BoundingBoxNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "BoundingBox"; }
String get_node_title() const override { return "Bounding Box"; }
String get_node_category() const override { return "Geometry"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
BoundingBoxNode();
};
// Separate Components — split geometry into mesh/curves/pointcloud/instances
class SeparateComponentsNode : public ProcNode {
GDCLASS(SeparateComponentsNode, ProcNode);
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "SeparateComponents"; }
String get_node_title() const override { return "Separate Components"; }
String get_node_category() const override { return "Geometry"; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
SeparateComponentsNode();
};
// Switch — select between two inputs based on boolean
// Switch — Blender's is TYPED. `input_type` picks what flows through it, and
// only GEOMETRY makes it a geometry switch; every other setting makes it a
// field function selecting per element.
//
// This declared its False/True sockets as Geometry unconditionally, so a Float
// switch -- the ordinary way to gate a displacement -- read its value through a
// geometry socket and delivered nothing. It was the last dead link in the
// bridged mountain: every parameter arrived, every node ran, and the offset
// this fed into Set Position was zero.
// Separate Geometry — Blender's: a geometry and a selection in, the SELECTED
// half and the INVERTED half out. It was mapped onto SeparateComponents, which
// splits a geometry by COMPONENT TYPE (mesh, curve, point cloud, instances) and
// is a different node with a different shape -- one input against two, four
// outputs against two.
class SeparateGeometryNode : public ProcNode {
GDCLASS(SeparateGeometryNode, ProcNode);
int domain = 0; // 0 Point, 2 Face -- as DeleteGeometry's
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "SeparateGeometry"; }
String get_node_title() const override { return "Separate Geometry"; }
String get_node_category() const override { return "Geometry"; }
void set_domain(int p_d) { domain = p_d; }
int get_domain() const { return domain; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
SeparateGeometryNode();
};
class SwitchNode : public ProcNode {
GDCLASS(SwitchNode, ProcNode);
SocketType input_type = SocketType::Geometry;
protected:
static void _bind_methods();
public:
StringName get_node_type() const override { return "Switch"; }
String get_node_title() const override { return "Switch"; }
String get_node_category() const override { return "Utility"; }
void set_input_type(int p_type);
int get_input_type_prop() const { return (int)input_type; }
// ⛔ GEOMETRY SWITCHING IS NOT A VALUE, so only the value forms emit. A
// geometry Switch picks a BRANCH of the graph, which a per-vertex shader
// cannot express, and claiming GPU support for it would make
// compile_to_function refuse the whole graph.
//
// Why this matters beyond the density path: a batch is built backwards over
// the value cone feeding Set Position, and it stops at the first node that
// cannot emit. Measured on the bridged mountain --
//
// GPU batch REFUSED: node 31 (CombineXYZ) socket 2 is connected from
// outside the batch and has no push-constant slot
//
// -- because CombineXYZ's Z came from this node. One missing compile_glsl
// put Set Position on the CPU for 2.58M vertices: 17.8 s an evaluation.
bool supports_gpu() const override { return input_type != SocketType::Geometry; }
String compile_glsl(const GlslEmitContext &p_ctx, int p_node_idx) const override;
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
SwitchNode();
};
// Random Value — per-element random float
// Random Value — Blender's, which is FOUR data types and one of them has a
// DIFFERENT SOCKET SET: BOOLEAN drops Min and Max for a single Probability, so
// ID and Seed move from sockets 2 and 3 to 1 and 2.
class RandomValueNode : public ProcNode {
GDCLASS(RandomValueNode, ProcNode);
protected:
static void _bind_methods();
int data_type = 10; // Blender's CD_PROP_* code; FLOAT is its default
public:
StringName get_node_type() const override { return "RandomValue"; }
String get_node_title() const override { return "Random Value"; }
String get_node_category() const override { return "Utility"; }
// ON since 2026-09-05. This node's history is the reason the rest of the
// list was audited: supports_gpu() used to return true with NO
// compile_glsl override at all, so the GPU path emitted none of its
// arithmetic and said nothing. It is true again now because there is
// something behind it -- calls into blender_hash.inc, the same text
// execute() runs.
bool supports_gpu() const override { return true; }
String compile_glsl(const GlslEmitContext &p_ctx, int p_node_idx) const override;
String compile_glsl_prelude(int p_node_idx) const override;
// Rebuilds the socket LIST, not just its types.
void set_data_type(int p_type);
int get_data_type() const { return data_type; }
void execute(ProcEvalContext &p_ctx, int p_node_idx) override;
RandomValueNode();
};
} // namespace godot
#endif // PROC_NODES_SELECTION_NODES_H