Hi,
This is my first attempt on this site. I’ll have to see whether I can find how to show code.
I am totally new to blender python, I DID peruse the IDE documentation, and I still can’t resolve two issues:
I create a reference object (a very thin plane that is supposed to be a line).
Then I duplicate the reference line, called LineRef in the code, a number of time (after moving it to (0, 0)), and each new copy is placed on the periphery of an imaginary circle, equidistant from the others ,and rotated so that they form a polygon inscribed in the circle. They are Line_0_0, Line_0_1, and so on.
Then, I give them materials.
The two issues I have are:
-
When I am done creating all the “lines”, the last line I created and the reference line seem to be swapped. I don’t know what I did wrong.
-
When I look at each line’s material, I can see that the original BSDF node is still there. How can I get rid of it?
Here is the code
import bpy
from math import sin, cos, tau, sqrt
import os
os.system("cls")
showDebug = False # for debug: show points and line lengths arrays
showColMats = False # for debug: show colors and materials
emission_mat = []
lineNr = 0
mats = bpy.data.materials
points = []
numPoints = 7 # The number of points to be distributed equidistantly on the circumference of the circle of radius defined below
radius = 100 # The radius of the circle the points will sit on
# The consecutive values, from index 1, of the array below have the length of a side from a point to a point index away from it
sidesLen = []
sidesLen.append(0) # Array of sides lengths [0] has 0, see note 3 lines above
colors_and_strengths = [((1, 1, 1, 1), 50, "white"),
((1, 0, 0, 1), 50, "red"),
((0, 1, 0, 1), 50, "green"),
((0, 0, 1, 1), 50, "blue"),
((1, 1, 0, 1), 50, "yellow"),
((1, 0, 1, 1), 50, "purple"),
((.008, .008, .008, 1), 50, "gray") ]
##### REMOVE OLD LINES FUNCTION
def removeOldLines():
objs = bpy.data.objects
for obj in objs:
if obj.name != 'Camera' and obj.name != 'Arrow' and obj.name != 'Light':
bpy.data.objects.remove(obj, do_unlink=True)
##### END OF REMOVE OLD LINES FUNCTION
##### START OF PURGEOLDMATERIALS FUNCTION, FROM https://blenderartists.org/t/deleting-all-materials-in-script/594160/2
def purgeOldMaterials():
for mat in mats:
mats.remove(bpy.data.materials[0])
##### END OF PURGEOLDMATERIALS FUNCTION
##### START OF POPULATEPOINTSANDLINELENGTHS FUNCTION
def populatePointsAndLineLengths():
global radius
global sideLen
for i in range(numPoints):
points.append((round(radius * cos(i * tau/numPoints)), round(radius * sin(i * tau/numPoints)), 0))
if showDebug == True:
for i in range(len(points)):
print("I have points[", str(i), "]:", points[i])
# Build sidesLen array for EVEN numPoints
if numPoints % 2 == 0:
numPointsOver2 = int (numPoints/2)
# Fill from 0 to numPoints/2 excluded
for i in range(1, numPointsOver2):
sidesLen.append(round(sqrt((points[i][0] - points[0][0]) * (points[i][0] - points[0][0]) + (points[i][1] - points[0][1]) * (points[i][1] - points[0][1]))))
# Fill numPoints/2, the lone longest segment
sidesLen.append(round(sqrt((points[numPointsOver2][0] - points[0][0]) * (points[numPointsOver2][0] - points[0][0]) + (points[numPointsOver2][1] - points[0][1]) * (points[numPointsOver2][1] - points[0][1]))))
# Fill numPoints/2 + 1 to numPoints - 1
for i in range(numPointsOver2 + 1, numPoints - 0):
sidesLen.append(sidesLen[numPoints - i])
# END OF BUILD SIDES LENGTHS ARRAY FOR EVEN numPoints
# Build sidesLen array for ODD numPoints
if numPoints % 2 != 0:
numPointsOver2 = int (numPoints / 2)
# Fill from 0 to numPoints/2 INCLUDED
for i in range(1, numPointsOver2 + 1):
sidesLen.append(round(sqrt((points[i][0] - points[0][0]) * (points[i][0] - points[0][0]) + (points[i][1] - points[0][1]) * (points[i][1] - points[0][1]))))
# Fill numPoints/2 + 1 to numPoints - 1
for i in range(numPointsOver2 + 1, numPoints):
sidesLen.append(sidesLen[numPoints - i])
# END OF BUILD SIDES LENGTHS ARRAY FOR ODD numPoints
if showDebug == True:
for i in range(len(sidesLen)):
print("sidesLen[", str(i), "]:", sidesLen[i])
##### END OF POPULATEPOINTSANDLINELENGTHS FUNCTION
##### START OF createRefLine FUNCTION
def createRefLine():
bpy.ops.mesh.primitive_plane_add(enter_editmode=True, align='WORLD', location=(0, 0, 0), scale=(100, 100, 10))
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.transform.resize(value=(50, 0.9, 1))
bpy.ops.transform.translate(value=(50, 0, 0))
bpy.ops.object.editmode_toggle()
bpy.context.object.name="LineRef"
##### END OF createRefLine FUNCTION
##### CREATE SHADERS FUNCTION
def createShaders():
# EMISSION SHADER: CREATE AN EMISSION SHADER SO THAT WE CAN SEE THE LINE
# EMISSION SHADER: NEW SHADER
COLOR = 0
STRENGTH = 1
COLOR_NAME = 2
if showColMats == True:
print("------->I have the following colors:")
for i in range(len(colors_and_strengths)):
print("------------>", colors_and_strengths[i])
global emission_mat
nodes = []
material_output = []
node_emission = []
links = []
# create as many materials as we have colors
for col_or in range(len(colors_and_strengths)):
emission_mat.append(bpy.data.materials.new(name="Emission_" + colors_and_strengths[col_or][COLOR_NAME]))
emission_mat[col_or].use_nodes = True
nodes.append(emission_mat[col_or].node_tree.nodes)
material_output.append(nodes[col_or].get('Material Output'))
node_emission.append(nodes[col_or].new(type='ShaderNodeEmission'))
node_emission[col_or].inputs[0].default_value = colors_and_strengths[col_or][COLOR] # RGB + Alpha
node_emission[col_or].inputs[1].default_value = colors_and_strengths[col_or][STRENGTH] # strength
links.append(emission_mat[col_or].node_tree.links)
new_link = links[col_or].new(node_emission[col_or].outputs[0], material_output[col_or].inputs[0])
if showColMats == True:
for i in range(len(emission_mat)):
print("Material:", emission_mat[i])
##### EN OF CREATE SHADERS FUNCTION
##### START OF DUPANDMOVEANDROTATELINE FUNCTION
def dupAndMoveAndRotateLine(objectGiven, contextGiven, xGiven, yGiven, angleGiven, size):
#bpy.ops.object.delete(use_global=True, confirm=False)
global lineNr
objectGiven.duplicate_move()
bpy.context.object.name="Line_0_" + str(lineNr)
lineNr += 1
objectGiven.rotation_clear()
contextGiven.rotation_euler[2] = angleGiven
objectGiven.scale_clear()
bpy.ops.transform.resize(value=size)
contextGiven.location[0] = xGiven
contextGiven.location[1] = yGiven
##### END OF DUPANDMOVEANDROTATELINE FUNCTION
# LET'S HAVE FUN NOW!
purgeOldMaterials() # print("\n\n------->Calling purgeOldMaterials...")
removeOldLines() # print("------->Calling removeOldLines...")
populatePointsAndLineLengths() # print("------->Calling populatePointsAndLineLengths...")
createRefLine() # print("------->Calling createRefLine...")
createShaders() # print("------->Calling createShaders...")
bpy.data.objects['LineRef'].data.materials.append(emission_mat[0]) # ASSIGN EMISSION SHADER TO THE REFERENCE LINE..
# NOW WE HAVE A REFERENCE LINE WITH AN EMISSION SHADER, LET'S MOVE IT OUT OF THE WAY
bpy.ops.transform.translate(value=(-sidesLen[1] / 2, 0, 0)) # Move the reference line out of the way
bpy.ops.transform.resize(value=(2, 1, 1)) # Resize the reference line
# draw numPoints lines on periphery
for i in range(numPoints):
dupAndMoveAndRotateLine(bpy.ops.object, bpy.context.object, points[i][0], points[i][1], (i) * tau * (1 / numPoints) + (tau / 2) * (1 / 2 + 1/numPoints), (sidesLen[1] / 100, 1, 1))
# Apply materials to lines
for i in range(numPoints):
bpy.data.objects['Line_0_' + str(i)].data.materials.clear()
bpy.data.objects['Line_0_' + str(i)].data.materials.append(emission_mat[i % len(emission_mat) - 0])
Summary
This text will be hidden