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()