First off this solution is inspired by the Interpolation From Curve Mapping node in Animation nodes which offers more info on using the curve data.
The idea is that blender offers mapping curves in various places, one that we can dynamically add items to is node trees. By creating a node that uses curve mapping data we can then access that data using layout.template_curve_mapping
in our custom panels. While Animation Nodes creates a helper material, my approach is to create a custom node group as it will only be visible in the Add->Group menu in the node editor which keeps it more out of the users view than a material.
While we can add nodes during a panels draw()
we can't alter the name, so a solution to have more useful names is to keep a dictionary to map useful names to the less helpful 'RGB Curves.12', this should be stored within a custom property in the scene so that the mapping can be kept between restarts. Another approach would be to create a group with one node for each mapping that you want to use.
import bpy
def myNodeTree():
if 'TestCurveData' not in bpy.data.node_groups:
ng = bpy.data.node_groups.new('TestCurveData', 'ShaderNodeTree')
ng.fake_user = True
return bpy.data.node_groups['TestCurveData'].nodes
curve_node_mapping = {}
def myCurveData(curve_name):
if curve_name not in curve_node_mapping:
cn = myNodeTree().new('ShaderNodeRGBCurve')
curve_node_mapping[curve_name] = cn.name
return myNodeTree()[curve_node_mapping[curve_name]]
class CurvyPanel(bpy.types.Panel):
bl_space_type = "VIEW_3D"
bl_label = "Test Curve Mapping"
bl_region_type = 'UI'
def draw(self, context):
self.layout.template_curve_mapping(myCurveData('TestOne'), "mapping")
def register():
bpy.utils.register_class(CurvyPanel)
In the parameters to template_curve_mapping
, the first is the curve based node that we use for our curve data, the second is the property that it uses to store the CurveMapping
structure.