12
$\begingroup$

Question

The title says it all. I want to be able to make this in Blender's UI, and sample it at specific points from an add-on:

enter image description here

Problem

There is very insufficient documentation on this, and I can't find any examples for how to create a CurveMapping property. I have worked with templates before, and I know the correct template to use, but it requires a curve mapping prop.

Extra Info

I found a few threads about this, and one gives me the impression that this cannot be done at all, but it is also very old.

https://blenderartists.org/forum/showthread.php?313871-Who-knows-how-to-Create-a-Custom-CurveMap

https://blenderartists.org/forum/showthread.php?207562-B256-How-do-I-add-a-CurveMapPoint-to-CurveMap-points

This similar question has been asked here before, but it didn't even get a comment:

Does anyone have an example of template_curve_mapping?

Is this even possible to access in python (as in only accessible in C)?

$\endgroup$
  • $\begingroup$ I've been looking around the internet and it seems that it can't be done in python: "There is no property that could store an bpy.types.CurveMapping instance, so you can't use it with python, unless you hijack an existing curve mapping and show it elsewhere." from this thread $\endgroup$ – palkonimo Aug 28 '16 at 11:52
  • $\begingroup$ and "there's no bpy.props.* property for py scripters to create such a mapping type, nor does it work if you re-create the structure with bpy.props. It's really limited to the C-code." from the thread you linked. But as you said, these threads are pretty old. $\endgroup$ – palkonimo Aug 28 '16 at 11:52
  • $\begingroup$ That's what I'm afraid of. With 7 up votes, this question should have been looked over by just about everyone who might know :( $\endgroup$ – JakeD Aug 28 '16 at 12:03
5
$\begingroup$

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.

$\endgroup$
2
$\begingroup$

Sambler mentioned a way to make a new curve by just accessing an RGB curve node. The other component to the question is about sampling the curve:

bpy.data.node_groups['TestCurveData'].nodes['RGB Curves'].mapping.curves[0]

Will be a CurveMap which has the evaluate method:

https://www.blender.org/api/blender_python_api_2_77_3/bpy.types.CurveMap.html#bpy.types.CurveMap

So to sample a curve where y = f(x) use:

ng = bpy.data.node_groups['TestCurveData']
c = ng.nodes['RGB Curves'].mapping.curves[0]
y = c.evaluate(x)
$\endgroup$
  • $\begingroup$ If you want to sample the C-curve then use index [3] not [0]!!! JakeD used the red curve, while the standard curve which appears is the C-Curve [3]. $\endgroup$ – richard Nov 16 '18 at 11:38
1
$\begingroup$

I've created a Sverchok node that does Sambler trick. https://github.com/spamrakuen/sverchok/blob/matllinknode/nodes/generators_extended/matl_link_sampler.py

Screenshot https://raw.githubusercontent.com/spamrakuen/sverchok/rgbcurvesnode/improved20190406.png

Pull request thread on sverchok github https://github.com/nortikin/sverchok/pull/2397

In order to work, a material that use nodes should be created, then just drop a RGB Curves node.

This Sverchok node will sample values from that curve(s)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.