Last active
August 29, 2015 14:26
-
-
Save zeffii/174c1b348ce712e61a61 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.