Skip to content

Instantly share code, notes, and snippets.

@zeffii
Last active August 29, 2015 14:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeffii/174c1b348ce712e61a61 to your computer and use it in GitHub Desktop.
Save zeffii/174c1b348ce712e61a61 to your computer and use it in GitHub Desktop.
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()
@zeffii
Copy link
Author

zeffii commented Aug 8, 2015

notes.. this will attache the relative nodes to the mouse cursor position. This means if you use the button to 'Make me!'' the nodes will appear where you probably don't want them. A current solution is to pick the text file, then navigate to the nodeview, then hit space and type 'Pie C', it will autofill to Pie Chart Operator, hit enter and BAM! it make the nodes,, connected, and also reads the text file and makes the coloramp elements.

None, dynamically ofcourse, but this could be done with relative ease -- but not by me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment