A Script to Import a CSV File and Create Meshes (for Blender 2.5x or later)

I am currently taking a course on Udemy for Deep Learning by Jose Portilla, and was thinking about building something like this, when I get some more time, I will look it over and see how feasible it would be to update it.

1 Like

Just updated what I have done so far, I was expecting that this was WORKING code in Blender 2.63 as it seems to have been stated somewhere, I do not recall where, but it would not have even worked in Blender 2.63, because they were trying to do a comparison between ‘-1’, as string, and a number!
After I got that straightened out, and loaded a csv file into it, more buttons came up. I tried the buttons and to no one’s surprise there were errors, but it is looking a lot better now, when I started, it would not even load.

From later:

I have updated a lot of the code in this, it appears to be something that was started and then shelved, because for two of the buttons they had listed, there is no code, and I actually had to create the classes, basically stubs to get the buttons to come up. That means that to getting it working in Blender 2.91, it would take a lot more coding than one would expect to have to do, because it would not be just updating old code, it would be writing new code, something I am not ready to do at the moment, I have far to many other projects going. Nevertheless, I am posting what I finished up, so if someone wants to pick up on it, it is a long ways beyond what it was when I got ahold of it. I want to finish my Udemy deep learning course . . . . that’s got priority.

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

bl_info = {
    "name": "Chart Graphics Generator",
    "author": "klibre, PKHG, thanks to JesterKing, Oscurart, Carlos Guerrero",
    "version": (0,0,5),
    "blender": (2, 6, 3),
    "api": 40101,
    "category": "Add Curve",
    "location": "View3d > Tools",
    "description": "Tool to build bar graphics from csv databases,",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "http://www.klibre.net"}


#----------------------------------------------------

import bpy
import csv
from math import pi
import mathutils
import random
import sys

#-------------------globals---------------------------------
pid2 = pi * 0.5
sce = bpy.context.scene
obj = bpy.context.object
bc = bpy.context
boo = bpy.ops.object
boc = bpy.ops.curve
bot = bpy.ops.transform
suma = 0
chartType = '' #not yet used
negativValueSeen = False
sizesCVSfile = None
colnrPKHG = -1
factorescala = 5
cvs_colums = 0
allData = None
sce.frame_start = 0
#sce.frame_end = 500
time = 20
origin = bc.scene.cursor.location

from bpy.props import IntProperty

#-------------------end globals---------------------------------
def getCSV(path):
    global sizesCVSfile, cvs_colums  
    result = False
    if(len(path)>0):
        print(path)
        try:
            csvfile =  open(path, 'r')
            dialect = csv.Sniffer().sniff(csvfile.read(1024))
            csvfile.seek(0)
            reader = csv.reader(csvfile, dialect=dialect)
            csvData = []
            for data in reader:
                csvData.append(data)
            result = csvData
            cvs_rows = len(result)
            cvs_colums = len(result[0])
            sizesCVSfile = [cvs_colums, cvs_rows]
            csvfile.close()
        except:
            print("no good csv file adress given!")
            self.report({'INFO'}, "no good csv file adress given!")
    return result
#
#
#def finalfps():
#   if bpy.ops.screen.keyframe_jump(next=True) == true :
#   
#   bpy.ops.screen.keyframe_jump(next=True)
#   
#   else :
#   
#   return {"FINISHED"}

# testpath C:\A000\example

class PANEL_PT_ForUI(bpy.types.Panel):
    bl_label = "Graph Generator"
    bl_idname = "PANEL_PT_ForUI"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    #
    def draw(self, context):
        global colnrPKHG, allData, cvs_colums, time
        layout = self.layout		
        col = layout.column(align=1)
        row = layout.row()
        split=row.split()
        col.label(text="CSV file path:")
        row.operator("lee.ruta",icon="FILE_SCRIPT")
        col = split.column()				
        col.prop(bc.scene,"importPydataPath")
        row = layout.row()
        row.prop(bc.scene,"useColumnNr")
        colnrPKHG = bpy.context.scene.useColumnNr
        path = bc.scene.importPydataPath
        check = getCSV(path)  
        if colnrPKHG >= cvs_colums:
            print("column ", colnrPKHG," not possible")
        elif check:
            allData = check
            row=layout.row()
            split=row.split()
            colL0 = split.column()
            colL0.label(text="Graphic Type:")
            row = layout.row()
            row.prop(bc.scene,"scaleFactor")
            factorescala = bc.scene.scaleFactor
            row=layout.row()
            split=row.split()
            colL1 = split.column()  
            colL1.operator("importador.cubos", icon="MESH_CUBE")
            colR1 = split.column()
            colR1.operator("importador.cilindros", icon="MESH_CYLINDER")
            colL3 = split.column()
            colL3.operator("import.curves", icon="SMOOTHCURVE")  # icon="CURVE_DATA"
            colL6 = split.column()
            colL6.operator("import.circle", icon="MESH_CIRCLE")  # icon="MESH_CIRCLE"
            row=layout.row()
            split=row.split()
            colL5 = split.column()  
        #    
        if suma <= 1:
            print("build graphic before")		   
        elif check:
            allData = check
            colL5.label("Configuration:")
            row=layout.row()
            split=row.split()
            colR2 = split.column()
            colR2.operator("calculo.porcentajes", icon="LINENUMBERS_ON")
            split=row.split()
            colL4 = split.column()
            colL4.operator("align.data", icon="FONTPREVIEW")
            colL5 = split.column()
            colL5.operator("colorear.grafica", icon="MATERIAL")
            row=layout.row()



class leeruta (bpy.types.Operator):
    bl_idname = "lee.ruta"
    bl_label = "Get File" 
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global path
        path = bc.scene.importPydataPath
        return {"FINISHED"}


# format data for values
class formatcurves (bpy.types.Operator):
    bl_idname = "format.curves"
    bl_label = "format curves" 
    #
    def execute(self,context):  
        # boo.convert(target='CURVE', keep_original=False)
        bc.selected_objects[0].data.extrude = 0.01
        bc.selected_objects[0].data.bevel_depth = 0.005
        return {"FINISHED"}


# importa data, Build cubes with data
class importadorcubos(bpy.types.Operator):
    bl_idname = "importador.cubos"
    bl_label = "Cubes"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = 'cubes'
        distancia= 0
        iescalado = 0
        bpy.ops.ver.nombres()
        bpy.ops.calculo.total()
        offset = bpy.context.scene.cursor.location.copy() #scris de mine dupa printscreenuri
        for data in allData:
            distancia += 3
            escalando = float(data[colnrPKHG])/factorescala   
            bpy.context.scene.cursor.location = (offset[0],offset[1]+2,offset[2])#scris de mine dupa printscreenuri
            if escalando >= 0:
                boo.text_add(location=((origin[0] + distancia),(origin[1]+1.5),(origin[2]+((escalando)*2)+0.2)),rotation=(pid2, 0, 0))
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=data[colnrPKHG], accent=False)  
                boo.editmode_toggle()
                bpy.ops.mesh.primitive_cube_add(location=((origin[0]+distancia),(origin[1]+1.5),(origin[2]+escalando)))
                bot.resize(value=(1,1,escalando))
                xmat = random.uniform(0.05,0.95)
                ymat = random.uniform(0.05,0.95)
                zmat = random.uniform(0.05,0.95)
                colordifuso = bpy.data.materials.new('RandomColor')
                colordifuso.diffuse_color = (xmat,ymat,zmat)
                colordifuso.specular_color = ((xmat+0.4),(ymat+0.4),(zmat+0.4))
                colordifuso.specular_intensity = (0.7)
                bc.object.data.materials.append(colordifuso)
                boo.select_all(action='DESELECT')
            else:
                negativValueSeen = True
                self.report({'WARNING'}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}	
        #    
        return {"FINISHED"}

# importa data, fabica  cilidros y los textcurves con la data
class importcylinders(bpy.types.Operator):
    bl_idname = "importador.cilindros"
    bl_label = "Cylinders"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = 'cylinders'
        distancia= 0
        iescalado = 0
        bpy.ops.ver.nombres()
        bpy.ops.calculo.total()
        offset = bpy.context.scene.cursor.location.copy() #scris de mine dupa printscreenuri
        #
        for data in allData:
            distancia += 3
            escalando = float(data[colnrPKHG])/factorescala  
            bpy.context.scene.cursor.location = (offset[0],offset[1]+2,offset[2])#scris de mine dupa printscreenuri
            if escalando >= 0:
                boo.text_add(location=((origin[0] + distancia),(origin[1]+1.5),(origin[2]+((escalando)*2)+0.2)),rotation=(pid2, 0, 0))
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=data[colnrPKHG], accent=False) 
                boo.editmode_toggle()
                bpy.ops.mesh.primitive_cylinder_add(location=((origin[0]+distancia+1),(origin[1]+1.5),(origin[2]+escalando)))
                bot.resize(value=(1,1,escalando))
                xmat = random.uniform(0.05,0.95)
                ymat = random.uniform(0.05,0.95)
                zmat = random.uniform(0.05,0.95)
                colordifuso = bpy.data.materials.new('RandomColor')
                colordifuso.diffuse_color = (xmat,ymat,zmat)
                colordifuso.specular_color = ((xmat+0.4),(ymat+0.4),(zmat+0.4))
                colordifuso.specular_intensity = (0.7)
                bc.object.data.materials.append(colordifuso)
                boo.select_all(action='DESELECT')
            else:
                negativValueSeen = True
                self.report({'WARNING'}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}	
        #    
        return {"FINISHED"}
    
# THIS IS JUST A STUB, CODE IS NOT DONE YET!
# import data, Build curves with data
class importcurves(bpy.types.Operator):
    bl_idname = "import.curves"
    bl_label = "Curves"
    bl_options = {"REGISTER", "UNDO"} 
    #
    def execute(self,context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = 'curves'
        distancia= 0
        iescalado = 0

# THIS IS JUST A STUB, CODE IS NOT DONE YET!
# import data, Build mesh circle with data
class importcircle(bpy.types.Operator):
    bl_idname = "import.circle"
    bl_label = "Circle"
    bl_options = {"REGISTER", "UNDO"} 
    #
    def execute(self,context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = 'circle'
        distancia= 0
        iescalado = 0

# muestra la suma total de los elementos
class calculototal (bpy.types.Operator):
    bl_idname = "calculo.total"
    bl_label = "Total"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global colnrPKHG, allData, suma , negativValueSeen, factorescala, origin
        negativValueSeen = False #assume OK at start
        suma = 0
        offset = bpy.context.scene.cursor.location.copy()
        for data in allData:
            bpy.context.scene.cursor.location.copy()
            print('colnrPKHG = ' + colnrPKHG)
            print('colnrPKHG = ' + colnrPKHG)
            print('colnrPKHG = ' + colnrPKHG)
            tmp = float(data[colnrPKHG])   
            if tmp < 0:
                negativValueSeen = True
                self.report({'WARNING'}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}
            suma += tmp
            sumados ="total:" + str(suma)
        boo.text_add(location=((origin[0]-2.5),origin[1]+2,(origin[2] + 3)),rotation=(pid2, 0, 0))
        boo.editmode_toggle()
        bpy.ops.font.delete()
        bpy.ops.font.text_insert(text=(sumados), accent=False)
        boo.editmode_toggle()
        bpy.ops.format.curves()
        sce.frame_end = suma + 30
        boo.select_all(action='DESELECT')
        return {"FINISHED"}
    
class calculoporcentajes (bpy.types.Operator): # calcul procentaj
    bl_idname = "calculo.porcentajes"
    bl_label = "percentages"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global colnrPKHG, allData, suma, negativValueSeen, factorescala, origin
        distancia= 0
        bpy.ops.calculo.total()
        offset = bpy.context.scene.cursor.location.copy()
        print("\n?????? negativValueSeen", negativValueSeen)
        if negativValueSeen:
            self.report({'WARNING'}, "negative value occured")
            return {'CANCELLED'}
        for data in allData:
            bpy.context.scene.cursor.location = (offset[0],offset[1]+2,offset[2])
            distancia += 3 
            sumando = float(data[colnrPKHG])
            if sumando >= 0:
                porciento = '{:.2%}.'.format(sumando/suma)
                escalado = float(data[colnrPKHG])/factorescala  
                boo.text_add(location=((origin[0]+0.5 + distancia),(origin[1]-3),(origin[2] + (escalado*2)+0.5)),rotation=(pid2, 0, 0))  
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=(porciento), accent=False)
                boo.editmode_toggle()
                bot.resize(value=(0.6,0.6,0.6))
                bpy.ops.format.curves()
                boo.select_all(action='DESELECT')
            else:
                print("negativ value for percentage not meaningful+ ")
        return {"FINISHED"}

        
# importa data, fabica  cilidros y los textcurves con la data
class vernombres (bpy.types.Operator):
    bl_idname = "ver.nombres"
    bl_label = "Names"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        global factorescala, origin 
        path = bc.scene.importPydataPath
        print('path = ' + bc.scene.importPydataPath)
        print('path = ' + bc.scene.importPydataPath)
        print('path = ' + bc.scene.importPydataPath)
        reader = csv.reader(open(path, 'r'))
        distancia= 0	
        offset = bpy.context.scene.cursor.location.copy()
        #separacion de las cajitas
        for data in reader:
            bpy.context.scene.cursor.location = (offset[0],offset[1]+2,offset[2])
            distancia += 3  
            data[0]=data[0].replace(' ', '\n')
            boo.text_add(location=((origin[0]+0.2 + distancia),origin[1]+4,(origin[2]+0)),rotation=(pid2, 0, 0))
            boo.editmode_toggle()
            bpy.ops.font.delete()
            bpy.ops.font.text_insert(text=data[0], accent=False)
            boo.editmode_toggle()
            bot.resize(value=(0.6,0.6,0.6))
            bpy.ops.format.curves()
            boo.select_all(action='DESELECT')
        return {"FINISHED"}
            
# asigna un material a la grafica azar
#   Material by http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Materials_and_textures
class coloreargrafica (bpy.types.Operator):
    bl_idname = "colorear.grafica"
    bl_label = "Paint it!"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        
        for ob in bpy.data.objects:
            if ob.type == 'CURVE' or ob.type == 'MESH':
                bpy.ops.object.material_slot_copy()
            else:
                self.report({'INFO'}, "Please. select any object before")   
        return{'FINISHED'}  

# Align data to camera        
class aligncurvestocamera (bpy.types.Operator):
    bl_idname = "align.data"
    bl_label = "Align data" 
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self,context):
        boo.select_by_type(type='FONT')
        if  bc.selected_objects[0].type == 'FONT':
            boo.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
            boo.visual_transform_apply()
            bot.select_orientation(orientation='VIEW')
            bot.transform(mode='ALIGN', constraint_orientation='VIEW')
            boo.select_all(action='DESELECT')
#   
#	   else:
#		   message = "You have to build data before"
#		   self.report({'WARNING'}, message)
#	   
        return{'FINISHED'}


#-----REGISTROS------------------------
def register():
    #soft_max number of graphics that can appear
    bpy.types.Scene.useColumnNr=bpy.props.IntProperty(name="Num of column to use",min = 1, max = 100, soft_max = 100, default = 1)
    bpy.types.Scene.scaleFactor=bpy.props.IntProperty(name = "Scale factor",min = 1, max = 1000, soft_max = 100, default = 10)
    bpy.types.Scene.importPydataPath=bpy.props.StringProperty(default="C:\A000\example")
    bpy.utils.register_class(PANEL_PT_ForUI)
    bpy.utils.register_class(leeruta)
    bpy.utils.register_class(formatcurves)
    bpy.utils.register_class(importadorcubos)
    bpy.utils.register_class(importcylinders)
    bpy.utils.register_class(importcurves)
    bpy.utils.register_class(importcircle)
    bpy.utils.register_class(calculototal)
    bpy.utils.register_class(calculoporcentajes)
    bpy.utils.register_class(vernombres)
    bpy.utils.register_class(coloreargrafica)
    bpy.utils.register_class(aligncurvestocamera)
    ## REGISTRA CLASSES
    burc = bpy.utils.register_class


def unregister():
    bpy.utils.unregister_class(PANEL_PT_ForUI)
    bpy.utils.unregister_class(leeruta)
    bpy.utils.unregister_class(formatcurves)
    bpy.utils.unregister_class(importadorcubos)
    bpy.utils.unregister_class(importcylinders)
    bpy.utils.unregister_class(importcurves)
    bpy.utils.unregister_class(importcircle)
    bpy.utils.unregister_class(calculototal)
    bpy.utils.unregister_class(calculoporcentajes)
    bpy.utils.unregister_class(vernombres)
    bpy.utils.unregister_class(coloreargrafica)
    bpy.utils.unregister_class(aligncurvestocamera)
    burc = bpy.utils.unregister_class

if __name__ == "__main__":
    register()

A hint on updating old scripts: I ran the code in this add-on and cought a few things: https://github.com/tin2tin/Update_Check_2.80
Ex. version number, icon, class registration needed an update. And then I used Black auto-formatting: https://black.now.sh
The file open button doesn’t work, but you can find an example in the python examples in the Text Editor. Other than that I do not know or need the functionality of this script, so good luck from here with it.

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

bl_info = {
    "name": "Chart Graphics Generator",
    "author": "klibre, PKHG, thanks to JesterKing, Oscurart, Carlos Guerrero",
    "version": (0, 0, 5),
    "blender": (2, 80, 3),
    "api": 40101,
    "category": "Add Curve",
    "location": "View3d > Tools",
    "description": "Tool to build bar graphics from csv databases,",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "http://www.klibre.net",
}


# ----------------------------------------------------

import bpy
import csv
from math import pi
import mathutils
import random
import sys

# -------------------globals---------------------------------
pid2 = pi * 0.5
sce = bpy.context.scene
obj = bpy.context.object
bc = bpy.context
boo = bpy.ops.object
boc = bpy.ops.curve
bot = bpy.ops.transform
suma = 0
chartType = ""  # not yet used
negativValueSeen = False
sizesCVSfile = None
colnrPKHG = -1
factorescala = 5
cvs_colums = 0
allData = None
sce.frame_start = 0
# sce.frame_end = 500
time = 20
origin = bc.scene.cursor.location

from bpy.props import IntProperty

# -------------------end globals---------------------------------
def getCSV(path):
    global sizesCVSfile, cvs_colums
    result = False
    if len(path) > 0:
        print(path)
        try:
            csvfile = open(path, "r")
            dialect = csv.Sniffer().sniff(csvfile.read(1024))
            csvfile.seek(0)
            reader = csv.reader(csvfile, dialect=dialect)
            csvData = []
            for data in reader:
                csvData.append(data)
            result = csvData
            cvs_rows = len(result)
            cvs_colums = len(result[0])
            sizesCVSfile = [cvs_colums, cvs_rows]
            csvfile.close()
        except:
            print("no good csv file adress given!")
            self.report({"INFO"}, "No good csv file adress given!")
    return result


#
#
# def finalfps():
#   if bpy.ops.screen.keyframe_jump(next=True) == true :
#
#   bpy.ops.screen.keyframe_jump(next=True)
#
#   else :
#
#   return {"FINISHED"}

# testpath C:\A000\example


class PANEL_PT_ForUI(bpy.types.Panel):
    bl_label = "Graph Generator"
    bl_idname = "PANEL_PT_ForUI"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    #
    def draw(self, context):
        global colnrPKHG, allData, cvs_colums, time
        layout = self.layout

        layout.label(text="CSV file path:")

        row = layout.row(align=True)
        row.prop(bc.scene, "importPydataPath", text="Path")
        row.operator("lee.ruta", icon="FILE_FOLDER", text="")
        layout.prop(bc.scene, "useColumnNr")
        colnrPKHG = bpy.context.scene.useColumnNr
        path = bc.scene.importPydataPath
        check = getCSV(path)
        if colnrPKHG >= cvs_colums:
            print("column ", colnrPKHG, " not possible")
        elif check:
            allData = check
            row = layout.row()
            split = row.split()
            colL0 = split.column()
            colL0.label(text="Graphic Type:")
            row = layout.row()
            row.prop(bc.scene, "scaleFactor")
            factorescala = bc.scene.scaleFactor
            row = layout.row()
            split = row.split()
            colL1 = split.column()
            colL1.operator("importador.cubos", icon="MESH_CUBE")
            colR1 = split.column()
            colR1.operator("importador.cilindros", icon="MESH_CYLINDER")
            colL3 = split.column()
            colL3.operator("import.curves", icon="SMOOTHCURVE")  # icon="CURVE_DATA"
            colL6 = split.column()
            colL6.operator("import.circle", icon="MESH_CIRCLE")  # icon="MESH_CIRCLE"
            row = layout.row()
            split = row.split()
            colL5 = split.column()
        #
        if suma <= 1:
            print("build graphic before")
        elif check:
            allData = check
            colL5.label("Configuration:")
            row = layout.row()
            split = row.split()
            colR2 = split.column()
            colR2.operator("calculo.porcentajes", icon="LINENUMBERS_ON")
            split = row.split()
            colL4 = split.column()
            colL4.operator("align.data", icon="FONTPREVIEW")
            colL5 = split.column()
            colL5.operator("colorear.grafica", icon="MATERIAL")
            row = layout.row()


class leeruta(bpy.types.Operator):
    bl_idname = "lee.ruta"
    bl_label = "Get File"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global path
        path = bc.scene.importPydataPath
        return {"FINISHED"}


# format data for values
class formatcurves(bpy.types.Operator):
    bl_idname = "format.curves"
    bl_label = "format curves"
    #
    def execute(self, context):
        # boo.convert(target='CURVE', keep_original=False)
        bc.selected_objects[0].data.extrude = 0.01
        bc.selected_objects[0].data.bevel_depth = 0.005
        return {"FINISHED"}


# importa data, Build cubes with data
class importadorcubos(bpy.types.Operator):
    bl_idname = "importador.cubos"
    bl_label = "Cubes"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = "cubes"
        distancia = 0
        iescalado = 0
        bpy.ops.ver.nombres()
        bpy.ops.calculo.total()
        offset = (
            bpy.context.scene.cursor.location.copy()
        )  # scris de mine dupa printscreenuri
        for data in allData:
            distancia += 3
            escalando = float(data[colnrPKHG]) / factorescala
            bpy.context.scene.cursor.location = (
                offset[0],
                offset[1] + 2,
                offset[2],
            )  # scris de mine dupa printscreenuri
            if escalando >= 0:
                boo.text_add(
                    location=(
                        (origin[0] + distancia),
                        (origin[1] + 1.5),
                        (origin[2] + ((escalando) * 2) + 0.2),
                    ),
                    rotation=(pid2, 0, 0),
                )
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=data[colnrPKHG], accent=False)
                boo.editmode_toggle()
                bpy.ops.mesh.primitive_cube_add(
                    location=(
                        (origin[0] + distancia),
                        (origin[1] + 1.5),
                        (origin[2] + escalando),
                    )
                )
                bot.resize(value=(1, 1, escalando))
                xmat = random.uniform(0.05, 0.95)
                ymat = random.uniform(0.05, 0.95)
                zmat = random.uniform(0.05, 0.95)
                colordifuso = bpy.data.materials.new("RandomColor")
                colordifuso.diffuse_color = (xmat, ymat, zmat)
                colordifuso.specular_color = ((xmat + 0.4), (ymat + 0.4), (zmat + 0.4))
                colordifuso.specular_intensity = 0.7
                bc.object.data.materials.append(colordifuso)
                boo.select_all(action="DESELECT")
            else:
                negativValueSeen = True
                self.report({"WARNING"}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}
        #
        return {"FINISHED"}


# importa data, fabica  cilidros y los textcurves con la data
class importcylinders(bpy.types.Operator):
    bl_idname = "importador.cilindros"
    bl_label = "Cylinders"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = "cylinders"
        distancia = 0
        iescalado = 0
        bpy.ops.ver.nombres()
        bpy.ops.calculo.total()
        offset = (
            bpy.context.scene.cursor.location.copy()
        )  # scris de mine dupa printscreenuri
        #
        for data in allData:
            distancia += 3
            escalando = float(data[colnrPKHG]) / factorescala
            bpy.context.scene.cursor.location = (
                offset[0],
                offset[1] + 2,
                offset[2],
            )  # scris de mine dupa printscreenuri
            if escalando >= 0:
                boo.text_add(
                    location=(
                        (origin[0] + distancia),
                        (origin[1] + 1.5),
                        (origin[2] + ((escalando) * 2) + 0.2),
                    ),
                    rotation=(pid2, 0, 0),
                )
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=data[colnrPKHG], accent=False)
                boo.editmode_toggle()
                bpy.ops.mesh.primitive_cylinder_add(
                    location=(
                        (origin[0] + distancia + 1),
                        (origin[1] + 1.5),
                        (origin[2] + escalando),
                    )
                )
                bot.resize(value=(1, 1, escalando))
                xmat = random.uniform(0.05, 0.95)
                ymat = random.uniform(0.05, 0.95)
                zmat = random.uniform(0.05, 0.95)
                colordifuso = bpy.data.materials.new("RandomColor")
                colordifuso.diffuse_color = (xmat, ymat, zmat)
                colordifuso.specular_color = ((xmat + 0.4), (ymat + 0.4), (zmat + 0.4))
                colordifuso.specular_intensity = 0.7
                bc.object.data.materials.append(colordifuso)
                boo.select_all(action="DESELECT")
            else:
                negativValueSeen = True
                self.report({"WARNING"}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}
        #
        return {"FINISHED"}


# THIS IS JUST A STUB, CODE IS NOT DONE YET!
# import data, Build curves with data
class importcurves(bpy.types.Operator):
    bl_idname = "import.curves"
    bl_label = "Curves"
    bl_options = {"REGISTER", "UNDO"}
    #
    def execute(self, context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = "curves"
        distancia = 0
        iescalado = 0


# THIS IS JUST A STUB, CODE IS NOT DONE YET!
# import data, Build mesh circle with data
class importcircle(bpy.types.Operator):
    bl_idname = "import.circle"
    bl_label = "Circle"
    bl_options = {"REGISTER", "UNDO"}
    #
    def execute(self, context):
        global colnrPKHG, allData, chartType, origin
        factorescala = bc.scene.scaleFactor
        chartType = "circle"
        distancia = 0
        iescalado = 0


# muestra la suma total de los elementos
class calculototal(bpy.types.Operator):
    bl_idname = "calculo.total"
    bl_label = "Total"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global colnrPKHG, allData, suma, negativValueSeen, factorescala, origin
        negativValueSeen = False  # assume OK at start
        suma = 0
        offset = bpy.context.scene.cursor.location.copy()
        for data in allData:
            bpy.context.scene.cursor.location.copy()
            print("colnrPKHG = " + colnrPKHG)
            print("colnrPKHG = " + colnrPKHG)
            print("colnrPKHG = " + colnrPKHG)
            tmp = float(data[colnrPKHG])
            if tmp < 0:
                negativValueSeen = True
                self.report({"WARNING"}, "negative value occured")
                print("error: not meaningfull with negativ values")
                return {"CANCELLED"}
            suma += tmp
            sumados = "total:" + str(suma)
        boo.text_add(
            location=((origin[0] - 2.5), origin[1] + 2, (origin[2] + 3)),
            rotation=(pid2, 0, 0),
        )
        boo.editmode_toggle()
        bpy.ops.font.delete()
        bpy.ops.font.text_insert(text=(sumados), accent=False)
        boo.editmode_toggle()
        bpy.ops.format.curves()
        sce.frame_end = suma + 30
        boo.select_all(action="DESELECT")
        return {"FINISHED"}


class calculoporcentajes(bpy.types.Operator):  # calcul procentaj
    bl_idname = "calculo.porcentajes"
    bl_label = "percentages"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global colnrPKHG, allData, suma, negativValueSeen, factorescala, origin
        distancia = 0
        bpy.ops.calculo.total()
        offset = bpy.context.scene.cursor.location.copy()
        print("\n?????? negativValueSeen", negativValueSeen)
        if negativValueSeen:
            self.report({"WARNING"}, "negative value occured")
            return {"CANCELLED"}
        for data in allData:
            bpy.context.scene.cursor.location = (offset[0], offset[1] + 2, offset[2])
            distancia += 3
            sumando = float(data[colnrPKHG])
            if sumando >= 0:
                porciento = "{:.2%}.".format(sumando / suma)
                escalado = float(data[colnrPKHG]) / factorescala
                boo.text_add(
                    location=(
                        (origin[0] + 0.5 + distancia),
                        (origin[1] - 3),
                        (origin[2] + (escalado * 2) + 0.5),
                    ),
                    rotation=(pid2, 0, 0),
                )
                boo.editmode_toggle()
                bpy.ops.font.delete()
                bpy.ops.font.text_insert(text=(porciento), accent=False)
                boo.editmode_toggle()
                bot.resize(value=(0.6, 0.6, 0.6))
                bpy.ops.format.curves()
                boo.select_all(action="DESELECT")
            else:
                print("negativ value for percentage not meaningful+ ")
        return {"FINISHED"}


# importa data, fabica  cilidros y los textcurves con la data
class vernombres(bpy.types.Operator):
    bl_idname = "ver.nombres"
    bl_label = "Names"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        global factorescala, origin
        path = bc.scene.importPydataPath
        print("path = " + bc.scene.importPydataPath)
        print("path = " + bc.scene.importPydataPath)
        print("path = " + bc.scene.importPydataPath)
        reader = csv.reader(open(path, "r"))
        distancia = 0
        offset = bpy.context.scene.cursor.location.copy()
        # separacion de las cajitas
        for data in reader:
            bpy.context.scene.cursor.location = (offset[0], offset[1] + 2, offset[2])
            distancia += 3
            data[0] = data[0].replace(" ", "\n")
            boo.text_add(
                location=(
                    (origin[0] + 0.2 + distancia),
                    origin[1] + 4,
                    (origin[2] + 0),
                ),
                rotation=(pid2, 0, 0),
            )
            boo.editmode_toggle()
            bpy.ops.font.delete()
            bpy.ops.font.text_insert(text=data[0], accent=False)
            boo.editmode_toggle()
            bot.resize(value=(0.6, 0.6, 0.6))
            bpy.ops.format.curves()
            boo.select_all(action="DESELECT")
        return {"FINISHED"}


# asigna un material a la grafica azar
#   Material by http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Materials_and_textures
class coloreargrafica(bpy.types.Operator):
    bl_idname = "colorear.grafica"
    bl_label = "Paint it!"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):

        for ob in bpy.data.objects:
            if ob.type == "CURVE" or ob.type == "MESH":
                bpy.ops.object.material_slot_copy()
            else:
                self.report({"INFO"}, "Please. select any object before")
        return {"FINISHED"}


# Align data to camera
class aligncurvestocamera(bpy.types.Operator):
    bl_idname = "align.data"
    bl_label = "Align data"
    bl_options = {"REGISTER", "UNDO"}  # %% ADDED
    #
    def execute(self, context):
        boo.select_by_type(type="FONT")
        if bc.selected_objects[0].type == "FONT":
            boo.origin_set(type="ORIGIN_GEOMETRY", center="MEDIAN")
            boo.visual_transform_apply()
            bot.select_orientation(orientation="VIEW")
            bot.transform(mode="ALIGN", constraint_orientation="VIEW")
            boo.select_all(action="DESELECT")
        #
        # 	   else:
        # 		   message = "You have to build data before"
        # 		   self.report({'WARNING'}, message)
        #
        return {"FINISHED"}


classes = (
    PANEL_PT_ForUI,
    leeruta,
    formatcurves,
    importadorcubos,
    importcylinders,
    importcurves,
    importcircle,
    calculototal,
    calculoporcentajes,
    vernombres,
    coloreargrafica,
    aligncurvestocamera,
)


# -----REGISTROS------------------------
def register():
    # soft_max number of graphics that can appear
    bpy.types.Scene.useColumnNr = bpy.props.IntProperty(
        name="Num of column to use", min=1, max=100, soft_max=100, default=1
    )
    bpy.types.Scene.scaleFactor = bpy.props.IntProperty(
        name="Scale factor", min=1, max=1000, soft_max=100, default=10
    )
    bpy.types.Scene.importPydataPath = bpy.props.StringProperty(
        default="C:\A000\example"
    )
    from bpy.utils import register_class

    for cls in classes:
        register_class(cls)

    ## REGISTRA CLASSES
    burc = bpy.utils.register_class


def unregister():
    from bpy.utils import unregister_class

    for cls in reversed(classes):
        unregister_class(cls)
    burc = bpy.utils.unregister_class


if __name__ == "__main__":
    register()

1 Like