diff options
Diffstat (limited to 'render_povray/scripting.py')
-rwxr-xr-x | render_povray/scripting.py | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/render_povray/scripting.py b/render_povray/scripting.py new file mode 100755 index 00000000..02ca6444 --- /dev/null +++ b/render_povray/scripting.py @@ -0,0 +1,529 @@ +# ***** 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 #**** + +# <pep8 compliant> + +"""Support POV Scene Description Language snippets or full includes: import, + +load, create or edit""" + +import bpy +from bpy.props import StringProperty, BoolProperty, CollectionProperty +from bpy_extras.io_utils import ImportHelper + +from mathutils import Vector +from math import pi + + +def export_custom_code(file): + """write all POV user defined custom code to exported file """ + # Write CurrentAnimation Frame for use in Custom POV Code + file.write("#declare CURFRAMENUM = %d;\n" % bpy.context.scene.frame_current) + # Change path and uncomment to add an animated include file by hand: + file.write("//#include \"/home/user/directory/animation_include_file.inc\"\n") + for txt in bpy.data.texts: + if txt.pov.custom_code == 'both': + # Why are the newlines needed? + file.write("\n") + file.write(txt.as_string()) + file.write("\n") + + +#############################IMPORT + + +class ImportPOV(bpy.types.Operator, ImportHelper): + """Load Povray files""" + + bl_idname = "import_scene.pov" + bl_label = "POV-Ray files (.pov/.inc)" + bl_options = {'PRESET', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + # ----------- + # File props. + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'} + ) + directory: StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}) + + filename_ext = {".pov", ".inc"} + filter_glob: StringProperty(default="*.pov;*.inc", options={'HIDDEN'}) + + import_at_cur: BoolProperty( + name="Import at Cursor Location", description="Ignore Object Matrix", default=False + ) + + def execute(self, context): + from mathutils import Matrix + + verts = [] + faces = [] + materials = [] + blend_mats = [] ############## + pov_mats = [] ############## + colors = [] + mat_names = [] + lenverts = None + lenfaces = None + suffix = -1 + name = 'Mesh2_%s' % suffix + name_search = False + verts_search = False + faces_search = False + plane_search = False + box_search = False + cylinder_search = False + sphere_search = False + cone_search = False + tex_search = False ################## + cache = [] + matrixes = {} + write_matrix = False + index = None + value = None + # file_pov = bpy.path.abspath(self.filepath) #was used for single files + + def mat_search(cache): + r = g = b = 0.5 + f = t = 0 + color = None + + for item, value in enumerate(cache): + + if value == 'texture': + pass + + if value == 'pigment': + + if cache[item + 2] in {'rgb', 'srgb'}: + pass + + elif cache[item + 2] in {'rgbf', 'srgbf'}: + pass + + elif cache[item + 2] in {'rgbt', 'srgbt'}: + try: + r, g, b, t = ( + float(cache[item + 3]), + float(cache[item + 4]), + float(cache[item + 5]), + float(cache[item + 6]), + ) + except BaseException as e: + print(e.__doc__) + print('An exception occurred: {}'.format(e)) + r = g = b = t = float(cache[item + 2]) + color = (r, g, b, t) + + elif cache[item + 2] in {'rgbft', 'srgbft'}: + pass + + else: + pass + + if colors == [] or (colors != [] and color not in colors): + colors.append(color) + name = ob.name + "_mat" + mat_names.append(name) + mat = bpy.data.materials.new(name) + mat.diffuse_color = (r, g, b) + mat.alpha = 1 - t + if mat.alpha != 1: + mat.use_transparency = True + ob.data.materials.append(mat) + + else: + for i, value in enumerate(colors): + if color == value: + ob.data.materials.append(bpy.data.materials[mat_names[i]]) + + for file in self.files: + print("Importing file: " + file.name) + file_pov = self.directory + file.name + for line in open(file_pov): + string = line.replace("{", " ") + string = string.replace("}", " ") + string = string.replace("<", " ") + string = string.replace(">", " ") + string = string.replace(",", " ") + lw = string.split() + # lenwords = len(lw) # Not used... why written? + if lw: + if lw[0] == "object": + write_matrix = True + if write_matrix: + if lw[0] not in {"object", "matrix"}: + index = lw[0] + if lw[0] in {"matrix"}: + value = [ + float(lw[1]), + float(lw[2]), + float(lw[3]), + float(lw[4]), + float(lw[5]), + float(lw[6]), + float(lw[7]), + float(lw[8]), + float(lw[9]), + float(lw[10]), + float(lw[11]), + float(lw[12]), + ] + matrixes[index] = value + write_matrix = False + for line in open(file_pov): + S = line.replace("{", " { ") + S = S.replace("}", " } ") + S = S.replace(",", " ") + S = S.replace("<", "") + S = S.replace(">", " ") + S = S.replace("=", " = ") + S = S.replace(";", " ; ") + S = S.split() + # lenS = len(S) # Not used... why written? + for i, word in enumerate(S): + ##################Primitives Import################## + if word == 'cone': + cone_search = True + name_search = False + if cone_search: + cache.append(word) + if cache[-1] == '}': + try: + x0 = float(cache[2]) + y0 = float(cache[3]) + z0 = float(cache[4]) + r0 = float(cache[5]) + x1 = float(cache[6]) + y1 = float(cache[7]) + z1 = float(cache[8]) + r1 = float(cache[9]) + # Y is height in most pov files, not z + bpy.ops.pov.cone_add(base=r0, cap=r1, height=(y1 - y0)) + ob = context.object + ob.location = (x0, y0, z0) + # ob.scale = (r,r,r) + mat_search(cache) + except ValueError: + pass + cache = [] + cone_search = False + if word == 'plane': + plane_search = True + name_search = False + if plane_search: + cache.append(word) + if cache[-1] == '}': + try: + bpy.ops.pov.addplane() + ob = context.object + mat_search(cache) + except ValueError: + pass + cache = [] + plane_search = False + if word == 'box': + box_search = True + name_search = False + if box_search: + cache.append(word) + if cache[-1] == '}': + try: + x0 = float(cache[2]) + y0 = float(cache[3]) + z0 = float(cache[4]) + x1 = float(cache[5]) + y1 = float(cache[6]) + z1 = float(cache[7]) + # imported_corner_1=(x0, y0, z0) + # imported_corner_2 =(x1, y1, z1) + center = ((x0 + x1) / 2, (y0 + y1) / 2, (z0 + z1) / 2) + bpy.ops.pov.addbox() + ob = context.object + ob.location = center + mat_search(cache) + + except ValueError: + pass + cache = [] + box_search = False + if word == 'cylinder': + cylinder_search = True + name_search = False + if cylinder_search: + cache.append(word) + if cache[-1] == '}': + try: + x0 = float(cache[2]) + y0 = float(cache[3]) + z0 = float(cache[4]) + x1 = float(cache[5]) + y1 = float(cache[6]) + z1 = float(cache[7]) + imported_cyl_loc = (x0, y0, z0) + imported_cyl_loc_cap = (x1, y1, z1) + + r = float(cache[8]) + + vec = Vector(imported_cyl_loc_cap) - Vector(imported_cyl_loc) + depth = vec.length + rot = Vector((0, 0, 1)).rotation_difference( + vec + ) # Rotation from Z axis. + trans = rot @ Vector( # XXX Not used, why written? + (0, 0, depth / 2) + ) # Such that origin is at center of the base of the cylinder. + # center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2) + scale_z = sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2 + (z1 - z0) ** 2) / 2 + bpy.ops.pov.addcylinder( + R=r, + imported_cyl_loc=imported_cyl_loc, + imported_cyl_loc_cap=imported_cyl_loc_cap, + ) + ob = context.object + ob.location = (x0, y0, z0) + ob.rotation_euler = rot.to_euler() + ob.scale = (1, 1, scale_z) + + # scale data rather than obj? + # bpy.ops.object.mode_set(mode='EDIT') + # bpy.ops.mesh.reveal() + # bpy.ops.mesh.select_all(action='SELECT') + # bpy.ops.transform.resize(value=(1,1,scale_z), orient_type='LOCAL') + # bpy.ops.mesh.hide(unselected=False) + # bpy.ops.object.mode_set(mode='OBJECT') + + mat_search(cache) + + except ValueError: + pass + cache = [] + cylinder_search = False + if word == 'sphere': + sphere_search = True + name_search = False + if sphere_search: + cache.append(word) + if cache[-1] == '}': + x = y = z = r = 0 + try: + x = float(cache[2]) + y = float(cache[3]) + z = float(cache[4]) + r = float(cache[5]) + + except ValueError: + pass + except: + x = y = z = float(cache[2]) + r = float(cache[3]) + bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z)) + ob = context.object + ob.location = (x, y, z) + ob.scale = (r, r, r) + mat_search(cache) + cache = [] + sphere_search = False + ##################End Primitives Import################## + if word == '#declare': + name_search = True + if name_search: + cache.append(word) + if word == 'mesh2': + name_search = False + if cache[-2] == '=': + name = cache[-3] + else: + suffix += 1 + cache = [] + if word in {'texture', ';'}: + name_search = False + cache = [] + if word == 'vertex_vectors': + verts_search = True + if verts_search: + cache.append(word) + if word == '}': + verts_search = False + lenverts = cache[2] + cache.pop() + cache.pop(0) + cache.pop(0) + cache.pop(0) + for j in range(int(lenverts)): + x = j * 3 + y = (j * 3) + 1 + z = (j * 3) + 2 + verts.append((float(cache[x]), float(cache[y]), float(cache[z]))) + cache = [] + # if word == 'face_indices': + # faces_search = True + if word == 'texture_list': ######## + tex_search = True ####### + if tex_search: ######### + if ( + word not in {'texture_list', 'texture', '{', '}', 'face_indices'} + and not word.isdigit() + ): ############## + pov_mats.append(word) ################# + if word == 'face_indices': + tex_search = False ################ + faces_search = True + if faces_search: + cache.append(word) + if word == '}': + faces_search = False + lenfaces = cache[2] + cache.pop() + cache.pop(0) + cache.pop(0) + cache.pop(0) + lf = int(lenfaces) + var = int(len(cache) / lf) + for k in range(lf): + if var == 3: + v0 = k * 3 + v1 = k * 3 + 1 + v2 = k * 3 + 2 + faces.append((int(cache[v0]), int(cache[v1]), int(cache[v2]))) + if var == 4: + v0 = k * 4 + v1 = k * 4 + 1 + v2 = k * 4 + 2 + m = k * 4 + 3 + materials.append((int(cache[m]))) + faces.append((int(cache[v0]), int(cache[v1]), int(cache[v2]))) + if var == 6: + v0 = k * 6 + v1 = k * 6 + 1 + v2 = k * 6 + 2 + m0 = k * 6 + 3 + m1 = k * 6 + 4 + m2 = k * 6 + 5 + materials.append( + (int(cache[m0]), int(cache[m1]), int(cache[m2])) + ) + faces.append((int(cache[v0]), int(cache[v1]), int(cache[v2]))) + # mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False) + # ob = object_utils.object_data_add(context, mesh, operator=None) + + me = bpy.data.meshes.new(name) ######## + ob = bpy.data.objects.new(name, me) ########## + bpy.context.collection.objects.link(ob) ######### + me.from_pydata(verts, [], faces) ############ + + for mat in bpy.data.materials: ############## + blend_mats.append(mat.name) ############# + for m_name in pov_mats: ##################### + if m_name not in blend_mats: ########### + povMat = bpy.data.materials.new(m_name) ################# + mat_search(cache) + ob.data.materials.append( + bpy.data.materials[m_name] + ) ################### + if materials: ################## + for l, val in enumerate(materials): #################### + try: ################### + ob.data.polygons[ + l + ].material_index = val #################### + except TypeError: ################### + ob.data.polygons[l].material_index = int( + val[0] + ) ################## + + blend_mats = [] ######################### + pov_mats = [] ######################### + materials = [] ######################### + cache = [] + name_search = True + if name in matrixes and not self.import_at_cur: + global_matrix = Matrix.Rotation(pi / 2.0, 4, 'X') + ob = bpy.context.object + matrix = ob.matrix_world + v = matrixes[name] + matrix[0][0] = v[0] + matrix[1][0] = v[1] + matrix[2][0] = v[2] + matrix[0][1] = v[3] + matrix[1][1] = v[4] + matrix[2][1] = v[5] + matrix[0][2] = v[6] + matrix[1][2] = v[7] + matrix[2][2] = v[8] + matrix[0][3] = v[9] + matrix[1][3] = v[10] + matrix[2][3] = v[11] + matrix = global_matrix * ob.matrix_world + ob.matrix_world = matrix + verts = [] + faces = [] + + # if word == 'pigment': + # try: + # #all indices have been incremented once to fit a bad test file + # r,g,b,t = float(S[2]),float(S[3]),float(S[4]),float(S[5]) + # color = (r,g,b,t) + + # except IndexError: + # #all indices have been incremented once to fit alternate test file + # r,g,b,t = float(S[3]),float(S[4]),float(S[5]),float(S[6]) + # color = (r,g,b,t) + # except UnboundLocalError: + # # In case no transmit is specified ? put it to 0 + # r,g,b,t = float(S[2]),float(S[3]),float(S[4],0) + # color = (r,g,b,t) + + # except ValueError: + # color = (0.8,0.8,0.8,0) + # pass + + # if colors == [] or (colors != [] and color not in colors): + # colors.append(color) + # name = ob.name+"_mat" + # mat_names.append(name) + # mat = bpy.data.materials.new(name) + # mat.diffuse_color = (r,g,b) + # mat.alpha = 1-t + # if mat.alpha != 1: + # mat.use_transparency=True + # ob.data.materials.append(mat) + # print (colors) + # else: + # for m in range(len(colors)): + # if color == colors[m]: + # ob.data.materials.append(bpy.data.materials[mat_names[m]]) + + ##To keep Avogadro Camera angle: + # for obj in bpy.context.view_layer.objects: + # if obj.type == "CAMERA": + # track = obj.constraints.new(type = "TRACK_TO") + # track.target = ob + # track.track_axis ="TRACK_NEGATIVE_Z" + # track.up_axis = "UP_Y" + # obj.location = (0,0,0) + return {'FINISHED'} + + +def register(): + bpy.utils.register_class(ImportPOV) + + +def unregister(): + bpy.utils.unregister_class(ImportPOV) |