p2or
8/8/2015 - 9:12 AM

weak_impl_pie_makes_nodes.py

import bpy
import random
from mathutils import Vector

''' 
text should be something like this (int or float, should add up to 100)
- either provide three color components (rgb)
- provide one, automatic greyscale is made
- provide none, random color is returned.

20.0,   0.2, 0.5, 0.2
20,     0.3, 0.2, 0.5
20.0,   0.1, 0.4, 0.1
20,     0.5
20
'''


def get_random_color():
    RAN = random.random
    return RAN(), RAN(), RAN(), 1.0

def greyscale(ft):
    ft = float(ft)
    return (ft, ft, ft, 1.0)

def generate_pie_nodes(context, nodes):

    def new_node(t):
        return nodes.new(type=t)
    
    TextureCoordinate = new_node("ShaderNodeTexCoord")
    GradientTexture = new_node("ShaderNodeTexGradient")
    ColorRamp = new_node("ShaderNodeValToRGB")
    DiffuseBSDF = new_node("ShaderNodeBsdfDiffuse")

    x, y = context.space_data.cursor_location

    TextureCoordinate.location  = Vector((0.0000+x, 0.0000+y))
    GradientTexture.location  = Vector((175.1804+x, 3.6965+y))
    ColorRamp.location  = Vector((353.9348+x, 2.7287+y))
    DiffuseBSDF.location = Vector((609.6481+x, 6.6672+y))

    ''' hook up nodes '''
    node_tree = context.space_data.node_tree

    a = TextureCoordinate.outputs['Object']
    b = GradientTexture.inputs['Vector']
    node_tree.links.new(a, b)

    a = GradientTexture.outputs['Fac']
    GradientTexture.gradient_type = 'RADIAL'
    b = ColorRamp.inputs['Fac']
    node_tree.links.new(a, b)

    a = ColorRamp.outputs['Color']
    ColorRamp.color_ramp.interpolation = 'CONSTANT'
    b = DiffuseBSDF.inputs[0]
    node_tree.links.new(a, b)
    
    a = DiffuseBSDF.outputs[0]
    b = nodes.get("Material Output").inputs[0]
    node_tree.links.new(a, b)


def make_slices(ctx, nodes):

    cRamp = nodes.get('ColorRamp')
    if not cRamp:
        generate_pie_nodes(ctx, nodes)
        elements = nodes['ColorRamp'].color_ramp.elements
    else:
        elements = cRamp.color_ramp.elements

    pitems_str = bpy.data.texts[ctx.scene.PIE_CHART_pcts_name].as_string()
    pitems = pitems_str.split('\n')

    pc = []
    for i in pitems:
        temp = []
        psplit = i.split(',')
        splits = len(psplit)
        if splits == 1:
            temp.extend([float(psplit[0]), get_random_color()])
        elif splits == 2:
            temp.extend([float(psplit[0]), greyscale(psplit[1])])
        elif splits == 4:
            r, g, b = [float(psplit[c]) for c in range(1,4)]
            temp.extend([float(psplit[0]), (r, g, b, 1.0)])
        else:
            temp.extend([float(i.strip()), get_random_color()])
        pc.append(temp)

    procents_and_colors = pc

    # this sections adds or removes elements if you update your 
    # procents_and_colors list with more / fewer elements
    diff = len(elements) - len(procents_and_colors)
    if diff > 0:
        for i in range(abs(diff)):
            elements.remove(elements[-1])
    elif diff < 0:
        for i in range(abs(diff)):
            elements.new(position=0.0)
     
    # --------------------
    position = 0
    for idx, section in enumerate(procents_and_colors):
        elements[idx].color = section[1]
        elements[idx].position = position
        # instead of 100 , if you precalc the sum it would produce the relative 
        # splits for you...
        position += (section[0] / 100.0)    


class PieChartDemoOps(bpy.types.Operator):
    bl_label = "Pie Chart Operator"
    bl_idname = "scene.piechart_pusher"
    
    @classmethod
    def poll(self, context):
        return context.scene.PIE_CHART_pcts_name in bpy.data.texts
    
    def execute(self, context):
        space = context.space_data
        node_tree = space.node_tree
        nodes = node_tree.nodes
        make_slices(context, nodes)
        return {'FINISHED'}


class PieChartDemoPanel(bpy.types.Panel):
    """Creates a Panel in the scene context of the properties editor"""
    bl_label = "Pie Chart Demo"
    bl_idname = "PIECHART_PT_loader"
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'UI'
    
    @classmethod
    def poll(self, context):
        try:
            return context.space_data.edit_tree.name == 'Shader Nodetree'
        except:
            return false

    def draw(self, context):
        layout = self.layout
        scn = context.scene

        layout.label(text=" Use text file: ( .pts )")
        layout.prop_search(scn, "PIE_CHART_pcts_name", bpy.data, "texts", text="")
        if context.scene.PIE_CHART_pcts_name:
            f = layout.operator("scene.piechart_pusher", text='make me!')
        

def register():
    bpy.types.Scene.PIE_CHART_pcts_name = bpy.props.StringProperty()
    bpy.utils.register_class(PieChartDemoPanel)
    bpy.utils.register_class(PieChartDemoOps)


def unregister():
    bpy.utils.unregister_class(PieChartDemoOps)
    bpy.utils.unregister_class(PieChartDemoPanel)
    del bpy.types.Scene.PIE_CHART_pcts_name


if __name__ == "__main__":
    register()