b9febb54a4
With this commit, curve objects support the geometry nodes modifier. Curves objects now evaluate to `CurveEval` unless there was a previous implicit conversion (tessellating modifiers, mesh modifiers, or the settings in the curve "Geometry" panel). In the new code, curves are only considered to be the wire edges-- any generated surface is a mesh instead, stored in the evaluated geometry set. The consolidation of concepts mentioned above allows remove a lot of code that had to do with maintaining the `DispList` type temporarily for modifiers and rendering. Instead, render engines see a separate object for the mesh from the mesh geometry component, and when the curve object evaluates to a curve, the `CurveEval` is always used for drawing wire edges. However, currently the `DispList` type is still maintained and used as an intermediate step in implicit mesh conversion. In the future, more uses of it could be changed to use `CurveEval` and `Mesh` instead. This is mostly not changed behavior, it is just a formalization of existing logic after recent fixes for 2.8 versions last year and two years ago. Also, in the future more functionality can be converted to nodes, removing cases of implicit conversions. For more discussion on that topic, see T89676. The `use_fill_deform` option is removed. It has not worked properly since 2.62, and the choice for filling a curve before or after deformation will work much better and be clearer with a node system. Applying the geometry nodes modifier to generate a curve is not implemented with this commit, so applying the modifier won't work at all. This is a separate technical challenge, and should be solved in a separate step. Differential Revision: https://developer.blender.org/D11597
127 lines
3.6 KiB
Python
127 lines
3.6 KiB
Python
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
#
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
import bpy
|
|
from bpy.types import Operator
|
|
|
|
|
|
def geometry_node_group_empty_new():
|
|
group = bpy.data.node_groups.new("Geometry Nodes", 'GeometryNodeTree')
|
|
group.inputs.new('NodeSocketGeometry', "Geometry")
|
|
group.outputs.new('NodeSocketGeometry', "Geometry")
|
|
input_node = group.nodes.new('NodeGroupInput')
|
|
output_node = group.nodes.new('NodeGroupOutput')
|
|
output_node.is_active_output = True
|
|
|
|
input_node.select = False
|
|
output_node.select = False
|
|
|
|
input_node.location.x = -200 - input_node.width
|
|
output_node.location.x = 200
|
|
|
|
group.links.new(output_node.inputs[0], input_node.outputs[0])
|
|
|
|
return group
|
|
|
|
|
|
def geometry_modifier_poll(context):
|
|
ob = context.object
|
|
|
|
# Test object support for geometry node modifier (No hair object support yet)
|
|
if not ob or ob.type not in {'MESH', 'POINTCLOUD', 'VOLUME', 'CURVE', 'FONT'}:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
class NewGeometryNodesModifier(Operator):
|
|
"""Create a new modifier with a new geometry node group"""
|
|
|
|
bl_idname = "node.new_geometry_nodes_modifier"
|
|
bl_label = "New Geometry Node Modifier"
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return geometry_modifier_poll(context)
|
|
|
|
def execute(self, context):
|
|
modifier = context.object.modifiers.new("GeometryNodes", "NODES")
|
|
|
|
if not modifier:
|
|
return {'CANCELLED'}
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class NewGeometryNodeTreeAssign(Operator):
|
|
"""Create a new geometry node group and assign it to the active modifier"""
|
|
|
|
bl_idname = "node.new_geometry_node_group_assign"
|
|
bl_label = "Assign New Geometry Node Group"
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return geometry_modifier_poll(context)
|
|
|
|
def execute(self, context):
|
|
if context.area.type == 'PROPERTIES':
|
|
modifier = context.modifier
|
|
else:
|
|
modifier = context.object.modifiers.active
|
|
|
|
if not modifier:
|
|
return {'CANCELLED'}
|
|
|
|
group = geometry_node_group_empty_new()
|
|
modifier.node_group = group
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class CopyGeometryNodeTreeAssign(Operator):
|
|
"""Copy the active geometry node group and assign it to the active modifier"""
|
|
|
|
bl_idname = "node.copy_geometry_node_group_assign"
|
|
bl_label = "Copy Geometry Node Group"
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return geometry_modifier_poll(context)
|
|
|
|
def execute(self, context):
|
|
modifier = context.object.modifiers.active
|
|
if modifier is None:
|
|
return {'CANCELLED'}
|
|
|
|
group = modifier.node_group
|
|
if group is None:
|
|
return {'CANCELLED'}
|
|
|
|
modifier.node_group = group.copy()
|
|
return {'FINISHED'}
|
|
|
|
|
|
classes = (
|
|
NewGeometryNodesModifier,
|
|
NewGeometryNodeTreeAssign,
|
|
CopyGeometryNodeTreeAssign,
|
|
)
|