2023-08-16 00:20:26 +10:00
|
|
|
# SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
2023-06-15 13:09:04 +10:00
|
|
|
#
|
2022-09-26 12:36:13 -05:00
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
2023-06-15 13:09:04 +10:00
|
|
|
|
2025-05-08 04:28:22 +02:00
|
|
|
import bpy
|
2022-09-26 12:36:13 -05:00
|
|
|
from bpy.types import Menu
|
|
|
|
|
from bl_ui import node_add_menu
|
2023-03-03 14:44:21 +01:00
|
|
|
from bpy.app.translations import (
|
|
|
|
|
pgettext_iface as iface_,
|
|
|
|
|
contexts as i18n_contexts,
|
|
|
|
|
)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_ATTRIBUTE"
|
|
|
|
|
bl_label = "Attribute"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeAttributeStatistic")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize")
|
|
|
|
|
layout.separator()
|
2022-12-07 18:22:44 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeBlurAttribute")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCaptureAttribute")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute")
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedAttribute", search_weight=1.0)
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_COLOR(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_COLOR"
|
|
|
|
|
bl_label = "Color"
|
|
|
|
|
|
2025-05-09 04:02:50 +02:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
2023-12-13 10:10:06 +01:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeBlackbody")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
|
|
|
|
|
layout.separator()
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeCombineColor")
|
2025-05-09 04:02:50 +02:00
|
|
|
node_add_menu.add_color_mix_node(context, layout)
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeSeparateColor")
|
2024-05-29 05:44:47 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Color")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_CURVE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_CURVE"
|
|
|
|
|
bl_label = "Curve"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_CURVE_READ")
|
2023-02-03 16:26:30 -05:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_CURVE_SAMPLE")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_CURVE_WRITE")
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.separator()
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_CURVE_OPERATIONS")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_curve_topology")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_CURVE_READ(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_READ"
|
|
|
|
|
bl_label = "Read"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveHandlePositions")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveLength")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputTangent")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveTilt")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveEndpointSelection")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveHandleTypeSelection")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineCyclic")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSplineLength")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSplineParameter")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineResolution")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Read")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
2023-01-16 14:39:10 +01:00
|
|
|
|
2023-02-03 16:26:30 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_CURVE_SAMPLE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_SAMPLE"
|
|
|
|
|
bl_label = "Sample"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleCurve")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Sample")
|
2023-02-03 16:26:30 -05:00
|
|
|
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_CURVE_WRITE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_WRITE"
|
|
|
|
|
bl_label = "Write"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2022-10-03 15:50:21 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveNormal")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveRadius")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveTilt")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveHandlePositions")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveSetHandles")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineCyclic")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineResolution")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveSplineType")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Write")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_CURVE_OPERATIONS(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_OPERATIONS"
|
|
|
|
|
bl_label = "Operations"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-07-22 12:29:26 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurvesToGreasePencil")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveToMesh")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveToPoints")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDeformCurvesOnSurface")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFillCurve")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFilletCurve")
|
2023-01-20 12:09:29 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInterpolateCurves")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeResampleCurve")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeReverseCurve")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideCurve")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeTrimCurve")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Operations")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE"
|
2023-01-09 18:09:22 +01:00
|
|
|
bl_label = "Primitives"
|
2022-09-26 12:36:13 -05:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveArc")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveBezierSegment")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveCircle")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveLine")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveSpiral")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveQuadraticBezier")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveQuadrilateral")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveStar")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Primitives")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-28 14:38:27 -05:00
|
|
|
class NODE_MT_geometry_node_curve_topology(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_curve_topology"
|
2023-01-09 18:09:22 +01:00
|
|
|
bl_label = "Topology"
|
2022-09-28 14:38:27 -05:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCurveOfPoint")
|
2023-08-24 16:09:58 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeOffsetPointInCurve")
|
2022-09-28 14:38:27 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePointsOfCurve")
|
2023-09-26 17:05:36 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Curve/Topology")
|
2022-09-28 14:38:27 -05:00
|
|
|
|
|
|
|
|
|
2025-04-08 09:51:28 -04:00
|
|
|
class NODE_MT_geometry_node_grease_pencil_read(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_grease_pencil_read"
|
2025-03-25 16:38:18 +01:00
|
|
|
bl_label = "Read"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputNamedLayerSelection")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Read")
|
|
|
|
|
|
|
|
|
|
|
2025-04-08 09:51:28 -04:00
|
|
|
class NODE_MT_geometry_node_grease_pencil_write(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_grease_pencil_write"
|
2025-04-05 12:11:26 +02:00
|
|
|
bl_label = "Write"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetGreasePencilColor")
|
2025-04-08 15:24:51 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetGreasePencilDepth")
|
2025-04-05 12:11:26 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Write")
|
|
|
|
|
|
|
|
|
|
|
2025-04-08 09:51:28 -04:00
|
|
|
class NODE_MT_geometry_node_grease_pencil_operations(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_grease_pencil_operations"
|
2025-03-25 16:38:18 +01:00
|
|
|
bl_label = "Operations"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGreasePencilToCurves")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMergeLayers")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Operations")
|
|
|
|
|
|
|
|
|
|
|
2025-04-08 09:51:28 -04:00
|
|
|
class NODE_MT_geometry_node_grease_pencil(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_grease_pencil"
|
2025-03-25 16:38:18 +01:00
|
|
|
bl_label = "Grease Pencil"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2025-04-08 09:51:28 -04:00
|
|
|
layout.menu("NODE_MT_geometry_node_grease_pencil_read")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_grease_pencil_write")
|
2025-03-25 16:38:18 +01:00
|
|
|
layout.separator()
|
2025-04-08 09:51:28 -04:00
|
|
|
layout.menu("NODE_MT_geometry_node_grease_pencil_operations")
|
2025-03-25 16:38:18 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY"
|
|
|
|
|
bl_label = "Geometry"
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_READ")
|
2023-02-03 16:26:30 -05:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_WRITE")
|
2023-01-16 12:23:50 +01:00
|
|
|
layout.separator()
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS")
|
|
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGeometryToInstance")
|
2024-04-16 12:18:45 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeJoinGeometry", search_weight=1.0)
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
2023-01-16 14:39:10 +01:00
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_GEOMETRY_READ(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_READ"
|
|
|
|
|
bl_label = "Read"
|
|
|
|
|
|
2023-08-24 13:34:15 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputID")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputIndex")
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputNamedAttribute", search_weight=1.0)
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputNormal")
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputPosition", search_weight=1.0)
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputRadius")
|
2023-08-24 13:34:15 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolSelection")
|
2024-05-20 21:01:30 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolActiveElement")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Read")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_GEOMETRY_WRITE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_WRITE"
|
|
|
|
|
bl_label = "Write"
|
|
|
|
|
|
2023-08-24 13:34:15 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
2024-07-09 17:03:54 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetGeometryName")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetID")
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetPosition", search_weight=1.0)
|
2023-08-24 13:34:15 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolSetSelection")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Write")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
2023-01-16 14:39:10 +01:00
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS"
|
|
|
|
|
bl_label = "Operations"
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2023-12-18 13:01:06 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeBake")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeBoundBox")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeConvexHull")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDeleteGeometry")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDuplicateElements")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMergeByDistance")
|
2024-01-12 14:30:34 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSortElements")
|
2024-04-16 12:18:45 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeTransform", search_weight=1.0)
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSeparateGeometry")
|
2023-10-18 10:26:23 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSplitToInstances")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Operations")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
2023-01-16 14:39:10 +01:00
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE"
|
|
|
|
|
bl_label = "Sample"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeProximity")
|
2023-04-22 13:11:51 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeIndexOfNearest")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeRaycast")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleIndex")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearest")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Sample")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_INPUT(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INPUT"
|
|
|
|
|
bl_label = "Input"
|
|
|
|
|
|
2024-06-10 20:47:37 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INPUT_CONSTANT")
|
Geometry Nodes: support attaching gizmos to input values
This adds support for attaching gizmos for input values. The goal is to make it
easier for users to set input values intuitively in the 3D viewport.
We went through multiple different possible designs until we settled on the one
implemented here. We picked it for it's flexibility and ease of use when using
geometry node assets. The core principle in the design is that **gizmos are
attached to existing input values instead of being the input value themselves**.
This actually fits the existing concept of gizmos in Blender well, but may be a
bit unintutitive in a node setup at first. The attachment is done using links in
the node editor.
The most basic usage of the node is to link a Value node to the new Linear Gizmo
node. This attaches the gizmo to the input value and allows you to change it
from the 3D view. The attachment is indicated by the gizmo icon in the sockets
which are controlled by a gizmo as well as the back-link (notice the double
link) when the gizmo is active.
The core principle makes it straight forward to control the same node setup from
the 3D view with gizmos, or by manually changing input values, or by driving the
input values procedurally.
If the input value is controlled indirectly by other inputs, it's often possible
to **automatically propagate** the gizmo to the actual input.
Backpropagation does not work for all nodes, although more nodes can be
supported over time.
This patch adds the first three gizmo nodes which cover common use cases:
* **Linear Gizmo**: Creates a gizmo that controls a float or integer value using
a linear movement of e.g. an arrow in the 3D viewport.
* **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be
rotated to change the attached angle input.
* **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale.
In the future, more built-in gizmos and potentially the ability for custom
gizmos could be added.
All gizmo nodes have a **Transform** geometry output. Using it is optional but
it is recommended when the gizmo is used to control inputs that affect a
geometry. When it is used, Blender will automatically transform the gizmos
together with the geometry that they control. To achieve this, the output should
be merged with the generated geometry using the *Join Geometry* node. The data
contained in *Transform* output is not visible geometry, but just internal
information that helps Blender to give a better user experience when using
gizmos.
The gizmo nodes have a multi-input socket. This allows **controlling multiple
values** with the same gizmo.
Only a small set of **gizmo shapes** is supported initially. It might be
extended in the future but one goal is to give the gizmos used by different node
group assets a familiar look and feel. A similar constraint exists for
**colors**. Currently, one can choose from a fixed set of colors which can be
modified in the theme settings.
The set of **visible gizmos** is determined by a multiple factors because it's
not really feasible to show all possible gizmos at all times. To see any of the
geometry nodes gizmos, the "Active Modifier" option has to be enabled in the
"Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of
the following is true:
* The gizmo controls an input of the active modifier of the active object.
* The gizmo controls a value in a selected node in an open node editor.
* The gizmo controls a pinned value in an open node editor. Pinning works by
clicking the gizmo icon next to the value.
Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
|
|
|
if context.space_data.geometry_nodes_type != 'TOOL':
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INPUT_GIZMO")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INPUT_GROUP")
|
2025-03-17 13:54:48 +01:00
|
|
|
layout.menu("NODE_MT_category_import")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INPUT_SCENE")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_INPUT_CONSTANT(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_CONSTANT"
|
|
|
|
|
bl_label = "Constant"
|
2023-03-03 14:44:21 +01:00
|
|
|
bl_translation_context = i18n_contexts.id_nodetree
|
2023-01-09 18:09:22 +01:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputBool")
|
2024-12-04 15:01:44 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputCollection")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputColor")
|
2022-12-09 15:50:00 -06:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputImage")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputInt")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterial")
|
2024-12-04 15:01:44 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputObject")
|
2024-05-06 19:04:30 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputRotation")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputString")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputVector")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Input/Constant")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_INPUT_GROUP(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_GROUP"
|
|
|
|
|
bl_label = "Group"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "NodeGroupInput")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Input/Group")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_INPUT_SCENE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_SCENE"
|
|
|
|
|
bl_label = "Scene"
|
|
|
|
|
|
2023-08-24 13:34:15 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
2023-08-24 13:34:15 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeTool3DCursor")
|
2023-12-12 19:11:06 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputActiveCamera")
|
2025-03-28 22:54:13 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCameraInfo")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCollectionInfo")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImageInfo")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeIsViewport")
|
2024-04-26 20:14:25 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolMousePosition")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeObjectInfo")
|
2025-05-15 20:56:33 +02:00
|
|
|
node_add_menu.add_node_type_with_subnames(context, layout, "GeometryNodeInputSceneTime", ["Frame", "Seconds"])
|
2023-08-24 16:09:58 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSelfObject")
|
2024-04-26 19:47:19 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeViewportTransform")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Input/Scene")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
Geometry Nodes: support attaching gizmos to input values
This adds support for attaching gizmos for input values. The goal is to make it
easier for users to set input values intuitively in the 3D viewport.
We went through multiple different possible designs until we settled on the one
implemented here. We picked it for it's flexibility and ease of use when using
geometry node assets. The core principle in the design is that **gizmos are
attached to existing input values instead of being the input value themselves**.
This actually fits the existing concept of gizmos in Blender well, but may be a
bit unintutitive in a node setup at first. The attachment is done using links in
the node editor.
The most basic usage of the node is to link a Value node to the new Linear Gizmo
node. This attaches the gizmo to the input value and allows you to change it
from the 3D view. The attachment is indicated by the gizmo icon in the sockets
which are controlled by a gizmo as well as the back-link (notice the double
link) when the gizmo is active.
The core principle makes it straight forward to control the same node setup from
the 3D view with gizmos, or by manually changing input values, or by driving the
input values procedurally.
If the input value is controlled indirectly by other inputs, it's often possible
to **automatically propagate** the gizmo to the actual input.
Backpropagation does not work for all nodes, although more nodes can be
supported over time.
This patch adds the first three gizmo nodes which cover common use cases:
* **Linear Gizmo**: Creates a gizmo that controls a float or integer value using
a linear movement of e.g. an arrow in the 3D viewport.
* **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be
rotated to change the attached angle input.
* **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale.
In the future, more built-in gizmos and potentially the ability for custom
gizmos could be added.
All gizmo nodes have a **Transform** geometry output. Using it is optional but
it is recommended when the gizmo is used to control inputs that affect a
geometry. When it is used, Blender will automatically transform the gizmos
together with the geometry that they control. To achieve this, the output should
be merged with the generated geometry using the *Join Geometry* node. The data
contained in *Transform* output is not visible geometry, but just internal
information that helps Blender to give a better user experience when using
gizmos.
The gizmo nodes have a multi-input socket. This allows **controlling multiple
values** with the same gizmo.
Only a small set of **gizmo shapes** is supported initially. It might be
extended in the future but one goal is to give the gizmos used by different node
group assets a familiar look and feel. A similar constraint exists for
**colors**. Currently, one can choose from a fixed set of colors which can be
modified in the theme settings.
The set of **visible gizmos** is determined by a multiple factors because it's
not really feasible to show all possible gizmos at all times. To see any of the
geometry nodes gizmos, the "Active Modifier" option has to be enabled in the
"Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of
the following is true:
* The gizmo controls an input of the active modifier of the active object.
* The gizmo controls a value in a selected node in an open node editor.
* The gizmo controls a pinned value in an open node editor. Pinning works by
clicking the gizmo icon next to the value.
Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
|
|
|
class NODE_MT_geometry_node_GEO_INPUT_GIZMO(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_GIZMO"
|
|
|
|
|
bl_label = "Gizmo"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGizmoDial")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGizmoLinear")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGizmoTransform")
|
2025-05-14 16:12:29 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Input/Gizmo")
|
Geometry Nodes: support attaching gizmos to input values
This adds support for attaching gizmos for input values. The goal is to make it
easier for users to set input values intuitively in the 3D viewport.
We went through multiple different possible designs until we settled on the one
implemented here. We picked it for it's flexibility and ease of use when using
geometry node assets. The core principle in the design is that **gizmos are
attached to existing input values instead of being the input value themselves**.
This actually fits the existing concept of gizmos in Blender well, but may be a
bit unintutitive in a node setup at first. The attachment is done using links in
the node editor.
The most basic usage of the node is to link a Value node to the new Linear Gizmo
node. This attaches the gizmo to the input value and allows you to change it
from the 3D view. The attachment is indicated by the gizmo icon in the sockets
which are controlled by a gizmo as well as the back-link (notice the double
link) when the gizmo is active.
The core principle makes it straight forward to control the same node setup from
the 3D view with gizmos, or by manually changing input values, or by driving the
input values procedurally.
If the input value is controlled indirectly by other inputs, it's often possible
to **automatically propagate** the gizmo to the actual input.
Backpropagation does not work for all nodes, although more nodes can be
supported over time.
This patch adds the first three gizmo nodes which cover common use cases:
* **Linear Gizmo**: Creates a gizmo that controls a float or integer value using
a linear movement of e.g. an arrow in the 3D viewport.
* **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be
rotated to change the attached angle input.
* **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale.
In the future, more built-in gizmos and potentially the ability for custom
gizmos could be added.
All gizmo nodes have a **Transform** geometry output. Using it is optional but
it is recommended when the gizmo is used to control inputs that affect a
geometry. When it is used, Blender will automatically transform the gizmos
together with the geometry that they control. To achieve this, the output should
be merged with the generated geometry using the *Join Geometry* node. The data
contained in *Transform* output is not visible geometry, but just internal
information that helps Blender to give a better user experience when using
gizmos.
The gizmo nodes have a multi-input socket. This allows **controlling multiple
values** with the same gizmo.
Only a small set of **gizmo shapes** is supported initially. It might be
extended in the future but one goal is to give the gizmos used by different node
group assets a familiar look and feel. A similar constraint exists for
**colors**. Currently, one can choose from a fixed set of colors which can be
modified in the theme settings.
The set of **visible gizmos** is determined by a multiple factors because it's
not really feasible to show all possible gizmos at all times. To see any of the
geometry nodes gizmos, the "Active Modifier" option has to be enabled in the
"Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of
the following is true:
* The gizmo controls an input of the active modifier of the active object.
* The gizmo controls a value in a selected node in an open node editor.
* The gizmo controls a pinned value in an open node editor. Pinning works by
clicking the gizmo icon next to the value.
Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_INSTANCE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_INSTANCE"
|
|
|
|
|
bl_label = "Instances"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInstanceOnPoints", search_weight=2.0)
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInstancesToPoints")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeRealizeInstances", search_weight=1.0)
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeRotateInstances")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeScaleInstances")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeTranslateInstances")
|
2024-05-28 16:34:37 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetInstanceTransform")
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.separator()
|
2025-04-17 13:34:26 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceBounds")
|
2024-05-31 12:55:40 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInstanceTransform")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceRotation")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceScale")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MATERIAL"
|
|
|
|
|
bl_label = "Material"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeReplaceMaterial")
|
|
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterialIndex")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMaterialSelection")
|
|
|
|
|
layout.separator()
|
2024-04-22 18:22:05 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterial", search_weight=1.0)
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterialIndex")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_MESH(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MESH"
|
|
|
|
|
bl_label = "Mesh"
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MESH_READ")
|
2023-02-03 16:26:30 -05:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MESH_SAMPLE")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MESH_WRITE")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MESH_OPERATIONS")
|
|
|
|
|
layout.menu("NODE_MT_category_PRIMITIVES_MESH")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_mesh_topology")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_UV")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_MESH_READ(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MESH_READ"
|
|
|
|
|
bl_label = "Read"
|
|
|
|
|
|
2023-08-24 13:34:15 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeAngle")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeNeighbors")
|
2023-08-24 16:09:58 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeVertices")
|
2023-08-24 16:15:43 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEdgesToFaceGroups")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceArea")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshFaceSetBoundaries")
|
2023-08-24 16:09:58 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceNeighbors")
|
2023-08-24 13:34:15 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolFaceSet")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceIsPlanar")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputShadeSmooth")
|
2023-09-06 17:12:27 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputEdgeSmooth")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshIsland")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputShortestEdgePaths")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Read")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
2023-02-03 16:26:30 -05:00
|
|
|
class NODE_MT_geometry_node_GEO_MESH_SAMPLE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MESH_SAMPLE"
|
|
|
|
|
bl_label = "Sample"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearestSurface")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleUVSurface")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Sample")
|
2023-02-03 16:26:30 -05:00
|
|
|
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_MESH_WRITE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MESH_WRITE"
|
|
|
|
|
bl_label = "Write"
|
|
|
|
|
|
2023-08-24 13:34:15 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
2023-08-24 13:34:15 +02:00
|
|
|
if context.space_data.geometry_nodes_type == 'TOOL':
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeToolSetFaceSet")
|
Mesh: Add "free" custom normals
Add a "dumb vector" storage option for custom normals, with the
"custom_normal" attribute. Adjust the mesh normals caching to
provide this attribute if it's available, and add a geometry node to
store custom normals.
## Free Normals
They're called "free" in the sense that they're just direction vectors
in the object's local space, rather than the existing "smooth corner
fan space" storage. They're also "free" in that they make further
normals calculation very inexpensive, since we just use the custom
normals instead. That's a big improvement from the existing custom
normals storage, which usually significantly decreases
viewport performance. For example, in a simple test file just storing
the vertex normals on a UV sphere, using free normals gives 25 times
better playback performance and 10% lower memory usage.
Free normals are adjusted when applying a transformation to the entire
mesh or when realizing instances, but in general they're not updated for
vertex deformations.
## Set Mesh Normal Node
The new geometry node allows storing free custom normals as well as
the existing corner fan space normals. When free normals are chosen,
free normals can be stored on vertices, faces, or face corners. Using
the face corner domain is necessary to bake existing mixed sharp and
smooth edges into the custom normal vectors.
The node also has a mode for storing edge and mesh sharpness, meant
as a "soft" replacement to the "Set Shade Smooth" node that's a bit
more convenient.
## Normal Input Node
The normal node outputs free custom normals mixed to whatever domain is
requested. A "true normal" output that ignores custom normals and
sharpness is added as well.
Across Blender, custom normals are generally accessed via face and
vertex normals, when "true normals" are not requested explicitly.
In many cases that means they are mixed from the face corner domain.
## Future Work
1. There are many places where propagation of free normals could be
improved. They should probably be normalized after mixing, and it
may be useful to not just use 0 vectors for new elements. To keep
the scope of this change smaller, that sort of thing generally isn't
handled here. Searching `CD_NORMAL` gives a hint of where better
propagation could be useful.
2. Free normals are displayed properly in edit mode, but the existing
custom normal editing operators don't work with free normals yet.
This will hopefully be fairly straightforward since custom normals
are usually converted to `float3` for editing anyway. Edit mode
changes aren't included here because they're unnecessary for the
procedural custom normals use cases.
3. Most importers can probably switch to using free normals instead,
or at least provide an option for it. That will give a significant
import performance improvement, and an improvement of Blender's
FPS for imported scenes too.
Pull Request: https://projects.blender.org/blender/blender/pulls/132583
2025-04-04 19:16:51 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetMeshNormal")
|
2023-11-04 11:02:59 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetShadeSmooth")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Write")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_MESH_OPERATIONS"
|
|
|
|
|
bl_label = "Operations"
|
|
|
|
|
|
2023-03-23 15:31:14 +11:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDualMesh")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToCurves")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToSelection")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeExtrudeMesh")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFlipFaces")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
|
2024-02-28 22:15:10 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshToDensityGrid")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
|
2024-02-28 22:15:10 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFGrid")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideMesh")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSubdivisionSurface")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeTriangulate")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Operations")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_PRIMITIVES_MESH(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_PRIMITIVES_MESH"
|
2023-01-09 18:09:22 +01:00
|
|
|
bl_label = "Primitives"
|
2022-09-26 12:36:13 -05:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshCone")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshCube")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshCylinder")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshGrid")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshIcoSphere")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshCircle")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshLine")
|
2022-10-05 10:53:12 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMeshUVSphere")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Primitives")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2024-06-10 15:38:43 -04:00
|
|
|
|
|
|
|
|
class NODE_MT_category_import(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_import"
|
2024-06-10 20:47:37 +02:00
|
|
|
bl_label = "Import"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2025-03-17 13:54:48 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportCSV", label="CSV (.csv)")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportOBJ", label="Wavefront (.obj)")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportPLY", label="Stanford PLY (.ply)")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportSTL", label="STL (.stl)")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportText", label="Text (.txt)")
|
2025-05-06 04:13:11 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImportVDB", label="OpenVDB (.vdb)")
|
2024-06-10 20:47:37 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Input/Import")
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2024-06-10 15:38:43 -04:00
|
|
|
|
2022-09-28 14:38:27 -05:00
|
|
|
class NODE_MT_geometry_node_mesh_topology(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_mesh_topology"
|
2023-01-09 18:09:22 +01:00
|
|
|
bl_label = "Topology"
|
2022-09-28 14:38:27 -05:00
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2023-05-31 15:25:48 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfEdge")
|
2023-04-13 13:14:05 +10:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfFace")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfVertex")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfCorner")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfVertex")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Topology")
|
2022-09-28 14:38:27 -05:00
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_OUTPUT(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_OUTPUT"
|
|
|
|
|
bl_label = "Output"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "NodeGroupOutput")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeViewer")
|
2024-08-29 16:03:25 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeWarning")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_POINT(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_POINT"
|
|
|
|
|
bl_label = "Point"
|
|
|
|
|
|
2023-03-23 15:31:14 +11:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
2024-03-05 16:11:01 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInVolume")
|
2024-02-29 01:20:27 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInGrid")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsOnFaces")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePoints")
|
2023-08-29 16:52:20 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
|
2024-02-28 22:15:10 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFGrid")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
|
|
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
Geometry Nodes: add simulation support
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.
A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.
The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.
The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
to initialize the simulation state. In later frames these sockets are not
evaluated anymore. The `Delta Time` at the first frame is zero, but the
simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
state of the previous frame. Nodes in the simulation zone can edit that
data in arbitrary ways, also taking into account the `Delta Time`. The new
simulation state has to be passed to the `Simulation Output` node where it
is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
zone are not evaluated, because the `Simulation Output` node can return
the previously cached data directly.
It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.
Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.
There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.
All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.
The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.
Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.
Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
|
|
|
class NODE_MT_category_simulation(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_simulation"
|
|
|
|
|
bl_label = "Simulation"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-09-30 17:09:00 +02:00
|
|
|
node_add_menu.add_simulation_zone(layout, label="Simulation")
|
Geometry Nodes: add simulation support
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.
A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.
The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.
The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
to initialize the simulation state. In later frames these sockets are not
evaluated anymore. The `Delta Time` at the first frame is zero, but the
simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
state of the previous frame. Nodes in the simulation zone can edit that
data in arbitrary ways, also taking into account the `Delta Time`. The new
simulation state has to be passed to the `Simulation Output` node where it
is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
zone are not evaluated, because the `Simulation Output` node can return
the previously cached data directly.
It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.
Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.
There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.
All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.
The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.
Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.
Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_TEXT(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_TEXT"
|
|
|
|
|
bl_label = "Text"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeStringJoin")
|
2025-04-03 02:57:39 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeMatchString")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeReplaceString")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeSliceString")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeStringLength")
|
2024-12-24 17:12:19 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeFindInString")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeStringToCurves")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeValueToString")
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInputSpecialCharacters")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Text")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_TEXTURE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_TEXTURE"
|
|
|
|
|
bl_label = "Texture"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
2024-08-14 08:48:17 +02:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexGabor")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeImageTexture")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_UTILITIES(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UTILITIES"
|
|
|
|
|
bl_label = "Utilities"
|
|
|
|
|
|
2024-02-13 18:59:36 +01:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_COLOR")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_TEXT")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_VECTOR")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_UTILITIES_FIELD")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_UTILITIES_MATH")
|
2024-04-17 10:34:13 +02:00
|
|
|
layout.menu("NODE_MT_category_utilities_matrix")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
|
2024-02-06 19:08:01 +01:00
|
|
|
layout.menu("NODE_MT_category_GEO_UTILITIES_DEPRECATED")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
2025-04-03 15:44:06 +02:00
|
|
|
if context.preferences.experimental.use_bundle_and_closure_nodes:
|
|
|
|
|
node_add_menu.add_closure_zone(layout, label="Closure")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeEvaluateClosure")
|
2024-09-30 17:09:00 +02:00
|
|
|
node_add_menu.add_foreach_geometry_element_zone(layout, label="For Each Element")
|
2024-01-29 14:17:10 -05:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeIndexSwitch")
|
2024-01-26 12:40:01 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeMenuSwitch")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
|
2024-09-30 17:09:00 +02:00
|
|
|
node_add_menu.add_repeat_zone(layout, label="Repeat")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSwitch")
|
2025-04-03 15:44:06 +02:00
|
|
|
if context.preferences.experimental.use_bundle_and_closure_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeCombineBundle")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSeparateBundle")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
|
|
|
|
|
|
|
|
|
2024-02-06 19:08:01 +01:00
|
|
|
class NODE_MT_category_GEO_UTILITIES_DEPRECATED(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UTILITIES_DEPRECATED"
|
|
|
|
|
bl_label = "Deprecated"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2024-04-30 15:52:11 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeAlignEulerToVector")
|
2024-02-06 19:08:01 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
|
2024-06-06 23:39:00 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Deprecated")
|
2024-02-06 19:08:01 +01:00
|
|
|
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_category_GEO_UTILITIES_FIELD(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UTILITIES_FIELD"
|
|
|
|
|
bl_label = "Field"
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeAccumulateField")
|
2023-01-09 18:09:22 +01:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFieldAtIndex")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFieldOnDomain")
|
2025-04-08 17:12:08 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFieldAverage")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFieldMinAndMax")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeFieldVariance")
|
2024-05-29 05:44:47 +02:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Field")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UTILITIES_ROTATION"
|
|
|
|
|
bl_label = "Rotation"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-04-30 15:52:11 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeAlignRotationToVector")
|
2024-05-08 13:34:14 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeAxesToRotation")
|
2023-08-24 14:58:55 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeAxisAngleToRotation")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeEulerToRotation")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInvertRotation")
|
2024-02-01 14:29:30 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotateRotation")
|
2023-08-24 14:58:55 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotateVector")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotationToAxisAngle")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotationToEuler")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeRotationToQuaternion")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeQuaternionToRotation")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Rotation")
|
2023-01-09 18:09:22 +01:00
|
|
|
|
2023-01-16 14:39:10 +01:00
|
|
|
|
2024-02-13 18:59:36 +01:00
|
|
|
class NODE_MT_category_utilities_matrix(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_utilities_matrix"
|
|
|
|
|
bl_label = "Matrix"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
2024-05-01 21:31:08 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeCombineMatrix")
|
2024-02-13 18:59:36 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeCombineTransform")
|
2024-09-30 21:30:10 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeMatrixDeterminant", label="Determinant")
|
2024-02-13 18:59:36 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeInvertMatrix")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMultiply")
|
2024-04-24 15:56:33 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeProjectPoint")
|
2024-05-01 21:31:08 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeSeparateMatrix")
|
2024-02-13 18:59:36 +01:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeSeparateTransform")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeTransformPoint")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeTransposeMatrix")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Matrix")
|
|
|
|
|
|
|
|
|
|
|
2023-01-09 18:09:22 +01:00
|
|
|
class NODE_MT_category_GEO_UTILITIES_MATH(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UTILITIES_MATH"
|
|
|
|
|
bl_label = "Math"
|
|
|
|
|
|
2025-05-08 04:28:22 +02:00
|
|
|
def draw(self, context):
|
2023-01-09 18:09:22 +01:00
|
|
|
layout = self.layout
|
2025-05-08 04:28:22 +02:00
|
|
|
node_add_menu.add_node_type_with_searchable_enum(context, layout, "FunctionNodeBooleanMath", "operation")
|
|
|
|
|
node_add_menu.add_node_type_with_searchable_enum(context, layout, "FunctionNodeIntegerMath", "operation")
|
2022-09-29 11:08:21 +02:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeCompare")
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
|
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeFloatToInt")
|
2024-08-30 16:42:29 +02:00
|
|
|
node_add_menu.add_node_type(layout, "FunctionNodeHashValue")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
2025-05-08 04:28:22 +02:00
|
|
|
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Math")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_UV(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_UV"
|
|
|
|
|
bl_label = "UV"
|
|
|
|
|
|
|
|
|
|
def draw(self, _context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeUVPackIslands")
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeUVUnwrap")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Mesh/UV")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_VECTOR(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_VECTOR"
|
|
|
|
|
bl_label = "Vector"
|
|
|
|
|
|
2025-05-08 04:28:22 +02:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
2025-05-08 04:28:22 +02:00
|
|
|
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
2022-09-26 12:36:13 -05:00
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
|
|
|
|
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=iface_("Mix Vector"))
|
|
|
|
|
ops = props.settings.add()
|
|
|
|
|
ops.name = "data_type"
|
|
|
|
|
ops.value = "'VECTOR'"
|
|
|
|
|
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
2023-09-26 17:01:30 -04:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Vector")
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_VOLUME(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_VOLUME"
|
|
|
|
|
bl_label = "Volume"
|
2023-02-23 22:00:57 +01:00
|
|
|
bl_translation_context = i18n_contexts.id_id
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2023-03-23 15:31:14 +11:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
2023-12-20 22:33:17 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_READ")
|
2024-02-22 17:58:09 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_volume_sample")
|
2023-12-20 22:33:17 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_WRITE")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2023-12-20 22:33:17 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_VOLUME_READ(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_READ"
|
|
|
|
|
bl_label = "Read"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGetNamedGrid")
|
2025-05-12 13:46:40 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGridInfo")
|
2023-12-20 22:33:17 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Volume/Read")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_VOLUME_WRITE(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_WRITE"
|
|
|
|
|
bl_label = "Write"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedGrid")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Volume/Write")
|
|
|
|
|
|
|
|
|
|
|
2024-02-22 17:58:09 +01:00
|
|
|
class NODE_MT_geometry_node_volume_sample(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_volume_sample"
|
|
|
|
|
bl_label = "Sample"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleGrid")
|
2024-05-07 21:53:22 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSampleGridIndex")
|
2024-02-22 17:58:09 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Volume/Sample")
|
|
|
|
|
|
|
|
|
|
|
2023-12-20 22:33:17 +01:00
|
|
|
class NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS"
|
|
|
|
|
bl_label = "Operations"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
2024-02-29 01:20:27 +01:00
|
|
|
if context.preferences.experimental.use_new_volume_nodes:
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeGridToMesh")
|
2024-04-23 14:48:59 +02:00
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeSDFGridBoolean")
|
2023-12-20 22:33:17 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Volume/Operations")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES"
|
|
|
|
|
bl_label = "Primitives"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
|
|
|
|
|
node_add_menu.draw_assets_for_catalog(layout, "Volume/Primitives")
|
|
|
|
|
|
|
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_category_GEO_GROUP(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_category_GEO_GROUP"
|
|
|
|
|
bl_label = "Group"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
node_add_menu.draw_node_group_add_menu(context, layout)
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
2022-09-27 16:36:27 +10:00
|
|
|
|
2022-09-26 12:36:13 -05:00
|
|
|
class NODE_MT_geometry_node_add_all(Menu):
|
|
|
|
|
bl_idname = "NODE_MT_geometry_node_add_all"
|
|
|
|
|
bl_label = ""
|
|
|
|
|
|
2023-08-04 20:59:04 +02:00
|
|
|
def draw(self, context):
|
2022-09-26 12:36:13 -05:00
|
|
|
layout = self.layout
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_ATTRIBUTE")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INPUT")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_category_GEO_OUTPUT")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY")
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_CURVE")
|
2025-04-08 09:51:28 -04:00
|
|
|
layout.menu("NODE_MT_geometry_node_grease_pencil")
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_INSTANCE")
|
|
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MESH")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_POINT")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_category_GEO_VOLUME")
|
|
|
|
|
layout.separator()
|
Geometry Nodes: add simulation support
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.
A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.
The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.
The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
to initialize the simulation state. In later frames these sockets are not
evaluated anymore. The `Delta Time` at the first frame is zero, but the
simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
state of the previous frame. Nodes in the simulation zone can edit that
data in arbitrary ways, also taking into account the `Delta Time`. The new
simulation state has to be passed to the `Simulation Output` node where it
is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
zone are not evaluated, because the `Simulation Output` node can return
the previously cached data directly.
It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.
Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.
There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.
All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.
The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.
Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.
Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
|
|
|
layout.menu("NODE_MT_category_simulation")
|
|
|
|
|
layout.separator()
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.menu("NODE_MT_geometry_node_GEO_MATERIAL")
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.menu("NODE_MT_category_GEO_TEXTURE")
|
|
|
|
|
layout.menu("NODE_MT_category_GEO_UTILITIES")
|
2023-01-09 18:09:22 +01:00
|
|
|
layout.separator()
|
2022-09-26 12:36:13 -05:00
|
|
|
layout.menu("NODE_MT_category_GEO_GROUP")
|
2023-09-01 20:46:12 +02:00
|
|
|
layout.menu("NODE_MT_category_layout")
|
2022-11-01 16:09:49 +01:00
|
|
|
node_add_menu.draw_root_assets(layout)
|
2022-09-26 12:36:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
classes = (
|
|
|
|
|
NODE_MT_geometry_node_add_all,
|
|
|
|
|
NODE_MT_geometry_node_GEO_ATTRIBUTE,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_INPUT,
|
|
|
|
|
NODE_MT_geometry_node_GEO_INPUT_CONSTANT,
|
|
|
|
|
NODE_MT_geometry_node_GEO_INPUT_GROUP,
|
|
|
|
|
NODE_MT_geometry_node_GEO_INPUT_SCENE,
|
|
|
|
|
NODE_MT_category_GEO_OUTPUT,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_geometry_node_GEO_CURVE,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_CURVE_READ,
|
2023-02-03 16:26:30 -05:00
|
|
|
NODE_MT_geometry_node_GEO_CURVE_SAMPLE,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_CURVE_WRITE,
|
|
|
|
|
NODE_MT_geometry_node_GEO_CURVE_OPERATIONS,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE,
|
2022-09-28 14:38:27 -05:00
|
|
|
NODE_MT_geometry_node_curve_topology,
|
2025-04-08 09:51:28 -04:00
|
|
|
NODE_MT_geometry_node_grease_pencil,
|
|
|
|
|
NODE_MT_geometry_node_grease_pencil_read,
|
|
|
|
|
NODE_MT_geometry_node_grease_pencil_write,
|
|
|
|
|
NODE_MT_geometry_node_grease_pencil_operations,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_geometry_node_GEO_GEOMETRY,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_GEOMETRY_READ,
|
|
|
|
|
NODE_MT_geometry_node_GEO_GEOMETRY_WRITE,
|
|
|
|
|
NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS,
|
|
|
|
|
NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_geometry_node_GEO_INSTANCE,
|
|
|
|
|
NODE_MT_geometry_node_GEO_MESH,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_MESH_READ,
|
2023-02-03 16:26:30 -05:00
|
|
|
NODE_MT_geometry_node_GEO_MESH_SAMPLE,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_MESH_WRITE,
|
|
|
|
|
NODE_MT_geometry_node_GEO_MESH_OPERATIONS,
|
|
|
|
|
NODE_MT_category_GEO_UV,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_category_PRIMITIVES_MESH,
|
2024-06-10 15:38:43 -04:00
|
|
|
NODE_MT_category_import,
|
2022-09-28 14:38:27 -05:00
|
|
|
NODE_MT_geometry_node_mesh_topology,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_category_GEO_POINT,
|
Geometry Nodes: add simulation support
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.
A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.
The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.
The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
to initialize the simulation state. In later frames these sockets are not
evaluated anymore. The `Delta Time` at the first frame is zero, but the
simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
state of the previous frame. Nodes in the simulation zone can edit that
data in arbitrary ways, also taking into account the `Delta Time`. The new
simulation state has to be passed to the `Simulation Output` node where it
is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
zone are not evaluated, because the `Simulation Output` node can return
the previously cached data directly.
It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.
Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.
There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.
All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.
The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.
Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.
Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
|
|
|
NODE_MT_category_simulation,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_category_GEO_VOLUME,
|
2023-12-20 22:33:17 +01:00
|
|
|
NODE_MT_geometry_node_GEO_VOLUME_READ,
|
2024-02-22 17:58:09 +01:00
|
|
|
NODE_MT_geometry_node_volume_sample,
|
2023-12-20 22:33:17 +01:00
|
|
|
NODE_MT_geometry_node_GEO_VOLUME_WRITE,
|
|
|
|
|
NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS,
|
|
|
|
|
NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_MATERIAL,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_category_GEO_TEXTURE,
|
|
|
|
|
NODE_MT_category_GEO_UTILITIES,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_geometry_node_GEO_COLOR,
|
|
|
|
|
NODE_MT_category_GEO_TEXT,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_category_GEO_VECTOR,
|
2023-01-09 18:09:22 +01:00
|
|
|
NODE_MT_category_GEO_UTILITIES_FIELD,
|
|
|
|
|
NODE_MT_category_GEO_UTILITIES_MATH,
|
|
|
|
|
NODE_MT_category_GEO_UTILITIES_ROTATION,
|
Geometry Nodes: support attaching gizmos to input values
This adds support for attaching gizmos for input values. The goal is to make it
easier for users to set input values intuitively in the 3D viewport.
We went through multiple different possible designs until we settled on the one
implemented here. We picked it for it's flexibility and ease of use when using
geometry node assets. The core principle in the design is that **gizmos are
attached to existing input values instead of being the input value themselves**.
This actually fits the existing concept of gizmos in Blender well, but may be a
bit unintutitive in a node setup at first. The attachment is done using links in
the node editor.
The most basic usage of the node is to link a Value node to the new Linear Gizmo
node. This attaches the gizmo to the input value and allows you to change it
from the 3D view. The attachment is indicated by the gizmo icon in the sockets
which are controlled by a gizmo as well as the back-link (notice the double
link) when the gizmo is active.
The core principle makes it straight forward to control the same node setup from
the 3D view with gizmos, or by manually changing input values, or by driving the
input values procedurally.
If the input value is controlled indirectly by other inputs, it's often possible
to **automatically propagate** the gizmo to the actual input.
Backpropagation does not work for all nodes, although more nodes can be
supported over time.
This patch adds the first three gizmo nodes which cover common use cases:
* **Linear Gizmo**: Creates a gizmo that controls a float or integer value using
a linear movement of e.g. an arrow in the 3D viewport.
* **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be
rotated to change the attached angle input.
* **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale.
In the future, more built-in gizmos and potentially the ability for custom
gizmos could be added.
All gizmo nodes have a **Transform** geometry output. Using it is optional but
it is recommended when the gizmo is used to control inputs that affect a
geometry. When it is used, Blender will automatically transform the gizmos
together with the geometry that they control. To achieve this, the output should
be merged with the generated geometry using the *Join Geometry* node. The data
contained in *Transform* output is not visible geometry, but just internal
information that helps Blender to give a better user experience when using
gizmos.
The gizmo nodes have a multi-input socket. This allows **controlling multiple
values** with the same gizmo.
Only a small set of **gizmo shapes** is supported initially. It might be
extended in the future but one goal is to give the gizmos used by different node
group assets a familiar look and feel. A similar constraint exists for
**colors**. Currently, one can choose from a fixed set of colors which can be
modified in the theme settings.
The set of **visible gizmos** is determined by a multiple factors because it's
not really feasible to show all possible gizmos at all times. To see any of the
geometry nodes gizmos, the "Active Modifier" option has to be enabled in the
"Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of
the following is true:
* The gizmo controls an input of the active modifier of the active object.
* The gizmo controls a value in a selected node in an open node editor.
* The gizmo controls a pinned value in an open node editor. Pinning works by
clicking the gizmo icon next to the value.
Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
|
|
|
NODE_MT_geometry_node_GEO_INPUT_GIZMO,
|
2024-02-13 18:59:36 +01:00
|
|
|
NODE_MT_category_utilities_matrix,
|
2024-02-06 19:08:01 +01:00
|
|
|
NODE_MT_category_GEO_UTILITIES_DEPRECATED,
|
2022-09-26 12:36:13 -05:00
|
|
|
NODE_MT_category_GEO_GROUP,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
|
|
|
from bpy.utils import register_class
|
|
|
|
|
for cls in classes:
|
|
|
|
|
register_class(cls)
|