From a5a3c60bbe2cf9d723b4240486618597f06c1729 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2011 04:49:20 +0000 Subject: make x3d script less OO, also remove some commented code and improve formatting. --- io_scene_x3d/export_x3d.py | 539 ++++++++++++++++++++++----------------------- 1 file changed, 266 insertions(+), 273 deletions(-) (limited to 'io_scene_x3d') diff --git a/io_scene_x3d/export_x3d.py b/io_scene_x3d/export_x3d.py index d599db75..6ab15155 100644 --- a/io_scene_x3d/export_x3d.py +++ b/io_scene_x3d/export_x3d.py @@ -41,6 +41,32 @@ import mathutils from bpy_extras.io_utils import create_derived_objects, free_derived_objects +x3d_names_reserved = {"Anchor", "Appearance", "Arc2D", "ArcClose2D", "AudioClip", "Background", "Billboard", + "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "Box", "Circle2D", + "Collision", "Color", "ColorInterpolator", "ColorRGBA", "component", "Cone", "connect", + "Contour2D", "ContourPolyline2D", "Coordinate", "CoordinateDouble", "CoordinateInterpolator", + "CoordinateInterpolator2D", "Cylinder", "CylinderSensor", "DirectionalLight", "Disk2D", + "ElevationGrid", "EspduTransform", "EXPORT", "ExternProtoDeclare", "Extrusion", "field", + "fieldValue", "FillProperties", "Fog", "FontStyle", "GeoCoordinate", "GeoElevationGrid", + "GeoLocationLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", + "GeoTouchSensor", "GeoViewpoint", "Group", "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", + "HAnimSegment", "HAnimSite", "head", "ImageTexture", "IMPORT", "IndexedFaceSet", + "IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet", + "Inline", "IntegerSequencer", "IntegerTrigger", "IS", "KeySensor", "LineProperties", "LineSet", + "LoadSensor", "LOD", "Material", "meta", "MetadataDouble", "MetadataFloat", "MetadataInteger", + "MetadataSet", "MetadataString", "MovieTexture", "MultiTexture", "MultiTextureCoordinate", + "MultiTextureTransform", "NavigationInfo", "Normal", "NormalInterpolator", "NurbsCurve", + "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", + "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", + "NurbsSwungSurface", "NurbsTextureCoordinate", "NurbsTrimmedSurface", "OrientationInterpolator", + "PixelTexture", "PlaneSensor", "PointLight", "PointSet", "Polyline2D", "Polypoint2D", + "PositionInterpolator", "PositionInterpolator2D", "ProtoBody", "ProtoDeclare", "ProtoInstance", + "ProtoInterface", "ProximitySensor", "ReceiverPdu", "Rectangle2D", "ROUTE", "ScalarInterpolator", + "Scene", "Script", "Shape", "SignalPdu", "Sound", "Sphere", "SphereSensor", "SpotLight", "StaticGroup", + "StringSensor", "Switch", "Text", "TextureBackground", "TextureCoordinate", "TextureCoordinateGenerator", + "TextureTransform", "TimeSensor", "TimeTrigger", "TouchSensor", "Transform", "TransmitterPdu", + "TriangleFanSet", "TriangleSet", "TriangleSet2D", "TriangleStripSet", "Viewpoint", "VisibilitySensor", + "WorldInfo", "X3D", "XvlShell", "VertexShader", "FragmentShader", "MultiShaderAppearance", "ShaderAppearance"} def clamp_color(col): return tuple([max(min(c, 1.0), 0.0) for c in col]) @@ -50,6 +76,21 @@ def matrix_direction(mtx): return (mathutils.Vector((0.0, 0.0, -1.0)) * mtx.to_3x3()).normalized()[:] +def clean_str(name, prefix='rsvd_'): + """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" + + newName = name + + if newName in x3d_names_reserved: + newName = '%s%s' % (prefix, newName) + + if newName[0].isdigit(): + newName = "%s%s" % ("_", newName) + + for bad in [' ', '"', '#', "'", ', ', '.', '[', '\\', ']', '{', '}']: + newName = newName.replace(bad, "_") + return newName + ########################################################## # Functions for writing output file ########################################################## @@ -57,17 +98,13 @@ def matrix_direction(mtx): class x3d_class: + namesFog = ("", "LINEAR", "EXPONENTIAL", "") + def __init__(self, filepath): #--- public you can change these --- - self.proto = 1 - self.billnode = 0 - self.halonode = 0 - self.collnode = 0 - self.global_matrix = mathutils.Matrix.Rotation(-(math.pi / 2.0), 4, 'X') #--- class private don't touch --- - self.indentLevel = 0 # keeps track of current indenting self.filepath = filepath self.file = None if filepath.lower().endswith('.x3dz'): @@ -80,89 +117,53 @@ class x3d_class: if self.file is None: self.file = open(self.filepath, "w", encoding="utf8", newline="\n") - - self.bNav = 0 self.nodeID = 0 - self.namesReserved = {"Anchor", "Appearance", "Arc2D", "ArcClose2D", "AudioClip", "Background", "Billboard", - "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "Box", "Circle2D", - "Collision", "Color", "ColorInterpolator", "ColorRGBA", "component", "Cone", "connect", - "Contour2D", "ContourPolyline2D", "Coordinate", "CoordinateDouble", "CoordinateInterpolator", - "CoordinateInterpolator2D", "Cylinder", "CylinderSensor", "DirectionalLight", "Disk2D", - "ElevationGrid", "EspduTransform", "EXPORT", "ExternProtoDeclare", "Extrusion", "field", - "fieldValue", "FillProperties", "Fog", "FontStyle", "GeoCoordinate", "GeoElevationGrid", - "GeoLocationLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", - "GeoTouchSensor", "GeoViewpoint", "Group", "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", - "HAnimSegment", "HAnimSite", "head", "ImageTexture", "IMPORT", "IndexedFaceSet", - "IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet", - "Inline", "IntegerSequencer", "IntegerTrigger", "IS", "KeySensor", "LineProperties", "LineSet", - "LoadSensor", "LOD", "Material", "meta", "MetadataDouble", "MetadataFloat", "MetadataInteger", - "MetadataSet", "MetadataString", "MovieTexture", "MultiTexture", "MultiTextureCoordinate", - "MultiTextureTransform", "NavigationInfo", "Normal", "NormalInterpolator", "NurbsCurve", - "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", - "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", - "NurbsSwungSurface", "NurbsTextureCoordinate", "NurbsTrimmedSurface", "OrientationInterpolator", - "PixelTexture", "PlaneSensor", "PointLight", "PointSet", "Polyline2D", "Polypoint2D", - "PositionInterpolator", "PositionInterpolator2D", "ProtoBody", "ProtoDeclare", "ProtoInstance", - "ProtoInterface", "ProximitySensor", "ReceiverPdu", "Rectangle2D", "ROUTE", "ScalarInterpolator", - "Scene", "Script", "Shape", "SignalPdu", "Sound", "Sphere", "SphereSensor", "SpotLight", "StaticGroup", - "StringSensor", "Switch", "Text", "TextureBackground", "TextureCoordinate", "TextureCoordinateGenerator", - "TextureTransform", "TimeSensor", "TimeTrigger", "TouchSensor", "Transform", "TransmitterPdu", - "TriangleFanSet", "TriangleSet", "TriangleSet2D", "TriangleStripSet", "Viewpoint", "VisibilitySensor", - "WorldInfo", "X3D", "XvlShell", "VertexShader", "FragmentShader", "MultiShaderAppearance", "ShaderAppearance"} - - self.namesFog = ("", "LINEAR", "EXPONENTIAL", "") ########################################################## # Writing nodes routines ########################################################## - def writeHeader(self): + @staticmethod + def writeHeader(fw, ident): + filepath = fw.__self__.name #bfile = sys.expandpath( Blender.Get('filepath') ).replace('<', '<').replace('>', '>') - bfile = repr(os.path.basename(self.filepath).replace('<', '<').replace('>', '>'))[1:-1] # use outfile name - self.file.write("\n") - self.file.write("\n") - self.file.write("\n") - self.file.write("\n") - self.file.write("\t\n" % bfile) - self.file.write("\t\n" % bpy.app.version_string) - self.file.write("\t\n") - self.file.write("\n") - self.file.write("\n") - - # This functionality is poorly defined, disabling for now - campbell - ''' - def writeScript(self): - textEditor = Blender.Text.Get() - alltext = len(textEditor) - for i in xrange(alltext): - nametext = textEditor[i].name - nlines = textEditor[i].getNLines() - if (self.proto == 1): - if (nametext == "proto" or nametext == "proto.js" or nametext == "proto.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.write_indented(alllines[j] + "\n") - elif (self.proto == 0): - if (nametext == "route" or nametext == "route.js" or nametext == "route.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.write_indented(alllines[j] + "\n") - self.write_indented("\n") - ''' - - def writeViewpoint(self, ob, mat, scene): + bfile = repr(os.path.basename(filepath).replace('<', '<').replace('>', '>'))[1:-1] # use outfile name + fw("%s\n" % ident) + fw("%s\n" % ident) + fw("%s\n" % ident) + ident += "\t" + fw("%s\n" % ident) + ident += "\t" + fw("%s\n" % (ident, bfile)) + fw("%s\n" % (ident, bpy.app.version_string)) + fw("%s\n" % ident) + ident = ident[:-1] + fw("%s\n" % ident) + fw("%s\n" % ident) + ident += "\t" + return ident + + @staticmethod + def writeFooter(fw, ident): + ident = ident[:-1] + fw("%s\n" % ident) + ident = ident[:-1] + fw("%s" % ident) + return ident + + @staticmethod + def writeViewpoint(fw, ident, ob, mat, scene): loc, quat, scale = mat.decompose() - self.file.write("\n\n") - - def writeFog(self, world): + fw("%s\n") + + @staticmethod + def writeFog(fw, ident, world): if world: mtype = world.mist_settings.falloff mparam = world.mist_settings @@ -171,18 +172,19 @@ class x3d_class: if mparam.use_mist: mtype = 1 if mtype == 'LINEAR' else 2 - # if (mtype == 1 or mtype == 2): - self.file.write("\n\n" % mparam.depth) + fw("%s\n" % mparam.depth) else: return - def writeNavigationInfo(self, scene): - self.file.write('\n') + @staticmethod + def writeNavigationInfo(fw, ident, scene): + fw('%s\n' % ident) - def writeSpotLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) + @staticmethod + def writeSpotLight(fw, ident, ob, mtx, lamp, world): + safeName = clean_str(ob.name) if world: ambi = world.ambient_color amb_intensity = ((ambi[0] + ambi[1] + ambi[2]) / 3.0) / 2.5 @@ -202,18 +204,19 @@ class x3d_class: radius = lamp.distance * math.cos(beamWidth) # radius = lamp.dist*math.cos(beamWidth) - self.file.write("\n\n" % location) - - def writeDirectionalLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) + fw("%s\n" % location) + + @staticmethod + def writeDirectionalLight(fw, ident, ob, mtx, lamp, world): + safeName = clean_str(ob.name) if world: ambi = world.ambient_color # ambi = world.amb @@ -224,14 +227,16 @@ class x3d_class: intensity = min(lamp.energy / 1.75, 1.0) dx, dy, dz = matrix_direction(mtx) - self.file.write("\n\n" % (dx, dy, dz)) - - def writePointLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) + fw("%s\n" % (dx, dy, dz)) + + @staticmethod + def writePointLight(fw, ident, ob, mtx, lamp, world): + + safeName = clean_str(ob.name) if world: ambi = world.ambient_color # ambi = world.amb @@ -243,13 +248,13 @@ class x3d_class: intensity = min(lamp.energy / 1.75, 1.0) location = mtx.to_translation()[:] - self.file.write("\n\n" % location) + fw("intensity=\"%.4g\" " % intensity) + fw("radius=\"%.4g\" " % lamp.distance) + fw("location=\"%.4g %.4g %.4g\" />\n" % location) def secureName(self, name): name = name + str(self.nodeID) @@ -260,7 +265,7 @@ class x3d_class: else: for bad in ('"', '#', "'", ', ', '.', '[', '\\', ']', '{', '}'): name = name.replace(bad, "_") - if name in self.namesReserved: + if name in x3d_names_reserved: newname = name[0:3] + "_" + str(self.nodeID) return "%s" % (newname) elif name[0].isdigit(): @@ -270,15 +275,21 @@ class x3d_class: newname = name return "%s" % (newname) - def writeIndexedFaceSet(self, ob, mesh, mtx, world, EXPORT_TRI=False): - fw = self.file.write - shape_name_x3d = self.cleanStr(ob.name) - mesh_name_x3d = self.cleanStr(mesh.name) + def writeIndexedFaceSet(self, fw, ident, ob, mesh, mtx, world, EXPORT_TRI=False): + + shape_name_x3d = clean_str(ob.name) + mesh_name_x3d = clean_str(mesh.name) if not mesh.faces: return - texface_use_halo = texface_use_billboard = texface_use_collision = 0 + texface_use_halo = 0 + texface_use_billboard = 0 + texface_use_collision = 0 + + use_halonode = False + use_billnode = False + use_collnode = False if mesh.uv_textures.active: # if mesh.faceUV: for face in mesh.uv_textures.active.data: # for face in mesh.faces: @@ -287,15 +298,18 @@ class x3d_class: texface_use_collision |= face.use_collision # texface_use_object_color |= face.use_object_color - if texface_use_halo and self.halonode == 0: - self.write_indented("\n", 1) - self.halonode = 1 - elif texface_use_billboard and self.billnode == 0: - self.write_indented("\n", 1) - self.billnode = 1 - elif texface_use_collision and self.collnode == 0: - self.write_indented("\n", 1) - self.collnode = 1 + if texface_use_halo: + fw("%s\n" % ident) + use_halonode = True + ident += "\t" + elif texface_use_billboard: + fw("%s\n" % ident) + use_billnode = True + ident += "\t" + elif texface_use_collision: + fw("%s\n" % ident) + use_collnode = True + ident += "\t" del texface_use_halo del texface_use_billboard @@ -304,18 +318,20 @@ class x3d_class: loc, quat, sca = mtx.decompose() - self.write_indented("\n") + ident += "\t" if mesh.tag: - self.write_indented("\n" % mesh_name_x3d, 1) + fw("%s\n" % (ident, mesh_name_x3d)) else: mesh.tag = True - self.write_indented("\n" % mesh_name_x3d, 1) + fw("%s\n" % (ident, mesh_name_x3d)) + ident += "\t" is_uv = bool(mesh.uv_textures.active) # is_col, defined for each material @@ -376,7 +392,9 @@ class x3d_class: if face_group: material = mesh_materials[material_index] - self.write_indented("\n", 1) + fw("%s\n" % ident) + ident += "\t" + is_smooth = False is_col = (mesh.vertex_colors.active and (material is None or material.use_vertex_color_paint)) @@ -386,14 +404,15 @@ class x3d_class: is_smooth = True break - self.write_indented("\n", 1) + fw("%s\n" % ident) + ident += "\t" if image: - self.writeImageTexture(image) + self.writeImageTexture(fw, ident, image) if mesh_materials_use_face_texture[material_index]: if image.use_tiles: - self.write_indented("\n" % (image.tiles_x, image.tiles_y)) + fw("%s\n" % (ident, image.tiles_x, image.tiles_y)) else: # transform by mtex loc = mesh_material_mtex[material_index].offset[:2] @@ -411,21 +430,23 @@ class x3d_class: else: rot = 0.0 - self.write_indented("\n") if material: - self.writeMaterial(material, self.cleanStr(material.name, ""), world) + self.writeMaterial(fw, ident, material, clean_str(material.name, ""), world) - self.write_indented("\n", -1) + ident = ident[:-1] + fw("%s\n" % ident) #-- IndexedFaceSet or IndexedLineSet - self.write_indented("\n" % ("coord_", mesh_name_x3d)) + fw("%s\n" % (ident, "coord_", mesh_name_x3d)) else: - self.write_indented("") - self.write_indented("\n", -1) + fw("%.6g %.6g %.6g, " % v.co[:]) + fw("\" />\n") is_coords_written = True if is_uv: - self.write_indented("") - self.write_indented("\n", -1) + fw("\" />\n") if is_col: - self.write_indented("") - self.write_indented("\n", -1) + fw("\" />\n") #--- output vertexColors #--- output closing braces - self.write_indented("\n", -1) - self.write_indented("\n", -1) - - self.write_indented("\n", -1) - - self.write_indented("\n", -1) - - if self.halonode == 1: - self.write_indented("\n", -1) - self.halonode = 0 - - if self.billnode == 1: - self.write_indented("\n", -1) - self.billnode = 0 - - if self.collnode == 1: - self.write_indented("\n", -1) - self.collnode = 0 - - fw("\n") - - def writeMaterial(self, mat, matName, world): + ident = ident[:-1] + fw("%s\n" % ident) + ident = ident[:-1] + fw("%s\n" % ident) + + ident = ident[:-1] + fw("%s\n" % ident) + + ident = ident[:-1] + fw("%s\n" % ident) + + if use_halonode: + ident = ident[:-1] + fw("%s\n" % ident) + elif use_billnode: + ident = ident[:-1] + fw("%s\n" % ident) + elif use_collnode: + ident = ident[:-1] + fw("%s\n" % ident) + + + @staticmethod + def writeMaterial(fw, ident, mat, matName, world): # look up material name, use it if available if mat.tag: - self.write_indented("\n" % matName) + fw("%s\n" % (ident, matName)) else: mat.tag = True @@ -561,26 +581,26 @@ class x3d_class: shininess = 0.0 specColor = emitColor = diffuseColor - self.write_indented("" % transp) - self.write_indented("\n", -1) + fw("%s\n" % transp) - def writeImageTexture(self, image): + @staticmethod + def writeImageTexture(fw, ident, image): name = image.name if image.tag: - self.write_indented("\n" % self.cleanStr(name)) + fw("%s\n" % (ident, clean_str(name))) else: image.tag = True - self.write_indented("" % " ".join(["\"%s\"" % f.replace("\\", "/") for f in images])) - self.write_indented("\n", -1) + fw("url='%s' />\n" % " ".join(["\"%s\"" % f.replace("\\", "/") for f in images])) + + def writeBackground(self, ident, world): + fw = self.file.write - def writeBackground(self, world): if world: worldname = world.name else: @@ -607,37 +628,37 @@ class x3d_class: sky_triple = clamp_color(world.zenith_color) mix_triple = clamp_color((grd_triple[i] + sky_triple[i]) / 2.0 for i in range(3)) - self.file.write("\n\n") + fw("/>\n") ########################################################## # export routine @@ -670,6 +691,8 @@ class x3d_class: EXPORT_TRI=False, ): + fw = self.file.write + world = scene.world # tag un-exported IDs @@ -678,12 +701,15 @@ class x3d_class: bpy.data.images.tag(False) print("Info: starting X3D export to %r..." % self.filepath) - self.writeHeader() + ident = "" + ident = self.writeHeader(fw, ident) + # self.writeScript() - self.writeNavigationInfo(scene) - self.writeBackground(world) - self.writeFog(world) - self.proto = 0 + self.writeNavigationInfo(fw, ident, scene) + self.writeBackground(ident, world) + self.writeFog(fw, ident, world) + + ident = "\t\t" if use_selection: objects = (o for o in scene.objects if o.is_visible(scene) and o.select) @@ -703,7 +729,7 @@ class x3d_class: ob_mat = self.global_matrix * ob_mat if objType == 'CAMERA': - self.writeViewpoint(ob, ob_mat, scene) + self.writeViewpoint(fw, ident, ob, ob_mat, scene) elif objType in ('MESH', 'CURVE', 'SURF', 'FONT'): if (objType != 'MESH') or (use_apply_modifiers and ob.is_modified(scene, 'PREVIEW')): try: @@ -714,7 +740,7 @@ class x3d_class: me = ob.data if me is not None: - self.writeIndexedFaceSet(ob, me, ob_mat, world, EXPORT_TRI=EXPORT_TRI) + self.writeIndexedFaceSet(fw, ident, ob, me, ob_mat, world, EXPORT_TRI=EXPORT_TRI) # free mesh created with create_mesh() if me != ob.data: @@ -724,13 +750,13 @@ class x3d_class: data = ob.data datatype = data.type if datatype == 'POINT': - self.writePointLight(ob, ob_mat, data, world) + self.writePointLight(fw, ident, ob, ob_mat, data, world) elif datatype == 'SPOT': - self.writeSpotLight(ob, ob_mat, data, world) + self.writeSpotLight(fw, ident, ob, ob_mat, data, world) elif datatype == 'SUN': - self.writeDirectionalLight(ob, ob_mat, data, world) + self.writeDirectionalLight(fw, ident, ob, ob_mat, data, world) else: - self.writeDirectionalLight(ob, ob_mat, data, world) + self.writeDirectionalLight(fw, ident, ob, ob_mat, data, world) else: #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType) pass @@ -738,11 +764,7 @@ class x3d_class: if free: free_derived_objects(ob_main) - self.file.write("\n\n") - - # if use_apply_modifiers: - # if containerMesh: - # containerMesh.vertices = None + ident = self.writeFooter(fw, ident) self.cleanup() @@ -752,27 +774,8 @@ class x3d_class: def cleanup(self): self.file.close() - self.indentLevel = 0 print("Info: finished X3D export to %r" % self.filepath) - def cleanStr(self, name, prefix='rsvd_'): - """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" - - newName = name - if len(newName) == 0: - self.nNodeID += 1 - return "%s%d" % (prefix, self.nNodeID) - - if newName in self.namesReserved: - newName = '%s%s' % (prefix, newName) - - if newName[0].isdigit(): - newName = "%s%s" % ("_", newName) - - for bad in [' ', '"', '#', "'", ', ', '.', '[', '\\', ']', '{', '}']: - newName = newName.replace(bad, "_") - return newName - def faceToString(self, face): print("Debug: face.flag=0x%x (bitflags)" % face.flag) @@ -803,16 +806,6 @@ class x3d_class: return s - # For writing well formed VRML code - #------------------------------------------------------------------------ - def write_indented(self, s, inc=0): - if inc < 1: - self.indentLevel = self.indentLevel + inc - - self.file.write((self.indentLevel * "\t") + s) - - if inc > 0: - self.indentLevel = self.indentLevel + inc ########################################################## # Callbacks, needed before Main -- cgit v1.2.3