3628 lines
127 KiB
Python
3628 lines
127 KiB
Python
#!BPY
|
|
|
|
"""
|
|
Name: 'COLLADA 1.3.1 (.dae) ...'
|
|
Blender: 240
|
|
Group: 'Export'
|
|
Tooltip: 'Export scene to COLLADA format (.dae)'
|
|
"""
|
|
|
|
__author__ = "Mikael Lagre"
|
|
__url__ = ("blender", "blenderartists.org", "Project homepage, http://colladablender.sourceforge.net", "Official Collada site, http://www.collada.org")
|
|
__version__ = "0.4"
|
|
__bpydoc__ = """
|
|
Description:
|
|
|
|
Exports Blender scene to the COLLADA 1.3.1 format.
|
|
|
|
Usage: run the script from the menu or inside Blender.
|
|
|
|
Notes: the script does not export animations yet.
|
|
"""
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Collada exporter version 0.4
|
|
# --------------------------------------------------------------------------
|
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
#
|
|
# Copyright (C) 2005: Mikael Lagre' contactme@mikaellagre.com
|
|
#
|
|
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
#
|
|
# ***** END GPL LICENCE BLOCK *****
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
_ERROR = False
|
|
|
|
try:
|
|
import math
|
|
except:
|
|
print "Error! Could not find math module"
|
|
_ERROR = True
|
|
try:
|
|
import Blender
|
|
from Blender import *
|
|
except:
|
|
print "Error! Could not find Blender modules!"
|
|
_ERROR = True
|
|
try:
|
|
from xml.dom.minidom import Document, Element, Childless, Text, _write_data
|
|
except:
|
|
print "\nError! Could not find XML modules!"
|
|
_ERROR = True
|
|
|
|
if _ERROR:
|
|
from sys import version_info
|
|
version = '%s.%s' % version_info[0:2]
|
|
print """
|
|
This script requires the xml module that is part of a
|
|
default standalone Python install.
|
|
|
|
To run the collada importer and exporter you need to have
|
|
Python version %s installed in your system. It can be downloaded from:
|
|
|
|
http://www.python.org
|
|
|
|
Notes:
|
|
- The minor (third) version number doesn't matter, you can have either
|
|
Python %s.1 or %s.2 or higher.
|
|
- If you do have Python %s installed and still can't run the scripts, then
|
|
make sure Blender's Python interpreter is finding the standalone modules
|
|
(run 'System Information' from Blender's Help -> System menu).
|
|
""" % (version, version, version, version)
|
|
Draw.PupMenu("Please install full version of python %t | Check the console for more info")
|
|
|
|
|
|
# === GLOBAL EXPORT SETTINGS ===
|
|
exportBakedTransform = True # Export <matrix> element transform
|
|
exportSelected = False # Export selected objects only
|
|
niceFormat = False # Creates a more readable document
|
|
# ==============================
|
|
|
|
# Global FPS for animation export (exporter uses render->anim settings)
|
|
fps = 25
|
|
|
|
# ----------------------------------------------
|
|
# Class structures
|
|
# ----------------------------------------------
|
|
class COLLADADocument( Document ):
|
|
""" A COLLADA Document ( DAE - Digital Asset Exangche) """
|
|
__file_ref = None
|
|
|
|
def openFile( self, file ):
|
|
self.__file_ref = open( file, "w" )
|
|
return
|
|
|
|
def buildXML( self ):
|
|
if not ( self.__file_ref == None ):
|
|
self.writexml( self.__file_ref, "", "\t", '\n', "utf-8" )
|
|
return
|
|
|
|
def cleanUp( self ):
|
|
self.unlink()
|
|
self.__file_ref.close()
|
|
return
|
|
|
|
# Definition of create[ColladaElementTypes]
|
|
def createCOLLADAElement( self, version=None ):
|
|
e = _COLLADAElement( version )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSceneElement( self, id=None, name=None ):
|
|
e = _SceneElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createNodeElement( self, name=None, id=None, nodeType=None ):
|
|
e = _NodeElement( name, id, nodeType )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createBoundingBoxElement( self ):
|
|
e = _BoundingBoxElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCameraElement( self, id=None, name=None ):
|
|
e = _CameraElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createOpticsElement( self ):
|
|
e = _OpticsElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createImagerElement( self ):
|
|
e = _ImagerElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createInstanceElement( self, url ):
|
|
e = _InstanceElement( url )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createLibraryElement( self, type ):
|
|
e = _LibraryElement( type )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createAnimationElement( self, id=None, name=None ):
|
|
e = _AnimationElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createChannelElement( self, id=None, name=None, source=None, target=None ):
|
|
e = _ChannelElement( id, name, source, target )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSamplerElement( self, id=None, name=None ):
|
|
e = _SamplerElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createControllerElement( self ):
|
|
e = _ControllerElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSkinElement( self ):
|
|
e = _SkinElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCombinerElement( self ):
|
|
e = _CombinerElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createJointsElement( self ):
|
|
e = _JointsElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createGeometryElement( self, id=None, name=None ):
|
|
e = _GeometryElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createMeshElement( self, id=None, name=None ):
|
|
e = _MeshElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createLinesElement( self ):
|
|
e = _LinesElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createLinestripsElement( self ):
|
|
e = _LinestripsElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createPolygonsElement( self, count=0, material=None ):
|
|
e = _PolygonsElement( count, material )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createPElement( self ):
|
|
e = _PElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTrianglesElement( self ):
|
|
e = _TrianglesElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTrifansElement( self ):
|
|
e = _TrifansElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTristripsElement( self ):
|
|
e = _TristripsElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createVerticesElement( self, id, name, count ):
|
|
e = _VerticesElement( id, name, count )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSourceElement( self, id=None, name=None ):
|
|
e = _SourceElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createAccessorElement( self, count=0, source="", id=None, offset=None, stride=None ):
|
|
e = _AccessorElement( count, id, offset, source, stride)
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createArrayElement( self ):
|
|
e = _ArrayElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createBoolArrayElement( self ):
|
|
e = _BoolArrayElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createFloatArrayElement( self, count, id=None, name=None, digits=None,
|
|
magnitude=None ):
|
|
e = _FloatArrayElement( count, id, name, digits, magnitude)
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createIntArrayElement( self ):
|
|
e = _IntArrayElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createNameArrayElement( self ):
|
|
e = _NameArrayElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createInputElement( self, idx=None, semantic=None, source=None ):
|
|
e = _InputElement( idx, semantic, source )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createMaterialElement( self, id=None, name=None ):
|
|
e = _MaterialElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createShaderElement( self, id=None, name=None ):
|
|
e = _ShaderElement( id, name )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createPassElement( self ):
|
|
e = _PassElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTechniqueElement( self, profile=None ):
|
|
e = _TechniqueElement( profile )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createImageElement( self, id=None, name=None, height=None, width=None,
|
|
depth=None, source=None, format=None ):
|
|
e = _ImageElement( id, name, height, width, depth, source, format )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createLightElement( self, id=None, name=None, type=None ):
|
|
e = _LightElement( id, name, type )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTextureElement( self, id=None, name=None ):
|
|
e = _TextureElement( id, name, )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createProgramElement( self, id=None, name=None, url=None ):
|
|
e = _ProgramElement( id, name, url )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCodeElement( self ):
|
|
e = _CodeElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createEntryElement( self ):
|
|
e = _EntryElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createParamElement( self, id=None, name=None, type=None, flow=None,
|
|
semantic=None, sid=None ):
|
|
e = _ParamElement( id, name, type, flow, semantic, sid )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createMatrixElement( self, sid=None ):
|
|
e = _MatrixElement( sid )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createLookAtElement( self ):
|
|
e = _LookAtElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createPerspectiveElement( self ):
|
|
e = _PerspectiveElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createRotateElement( self, sid=None ):
|
|
e = _RotateElement( sid )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createScaleElement( self, sid=None ):
|
|
e = _ScaleElement( sid )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSkewElement( self ):
|
|
e = _SkewElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTranslateElement( self, sid=None ):
|
|
e = _TranslateElement( sid )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createAssetElement( self ):
|
|
e = _AssetElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createAuthorElement( self, data=None ):
|
|
e = _AuthorElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createAuthoringToolElement( self, data=None ):
|
|
e = _AuthoringToolElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCreatedElement( self, data=None ):
|
|
e = _CreatedElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createModifiedElement( self, data=None ):
|
|
e = _ModifiedElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createRevisionElement( self, data=None ):
|
|
e = _RevisionElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSourceDataElement( self, data=None ):
|
|
e = _SourceDataElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createElement( self, data=None ):
|
|
e = _( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCopyrightElement( self, data=None ):
|
|
e = _CopyrightElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createTitleElement( self, data=None ):
|
|
e = _TitleElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createSubjectElement( self, data=None ):
|
|
e = _SubjectElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createKeywordsElement( self, data=None ):
|
|
e = _KeywordsElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createCommentsElement( self, data=None ):
|
|
e = _CommentsElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createUnitElement( self, name=None, meter=None ):
|
|
e = _UnitElement( name, meter )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
def createUpAxisElement( self, data=None ):
|
|
e = _UpAxisElement( data )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
|
|
def createExtraElement( self ):
|
|
e = _ExtraElement( )
|
|
e.ownerDocument = self
|
|
return e
|
|
|
|
|
|
# COLLADA Common Profile constants strings
|
|
# ( for COLLADA specification 1.3.1 )
|
|
# Also in this collada common profile class is library type constants
|
|
# flow types and other xs:NMTOKEN constants definied in the schema
|
|
class _CommonProfile:
|
|
|
|
COMMON = 1
|
|
BLENDER = 2
|
|
|
|
str = [ "", "COMMON", "BLENDER" ]
|
|
|
|
class _ParamName:
|
|
A = 1
|
|
AMBIENT = 2
|
|
ANGLE = 3
|
|
ATTENUATION = 4
|
|
ATTENUATION_SCALE = 5
|
|
B = 6
|
|
BOTTOM = 7
|
|
COLOR = 8
|
|
DIFFUSE = 9
|
|
EMISSION = 10
|
|
FALLOFF = 11
|
|
FALLOFF_SCALE = 12
|
|
G = 13
|
|
LEFT = 14
|
|
P = 15
|
|
Q = 16
|
|
R = 17
|
|
REFLECTIVE = 18
|
|
REFLECTIVITY = 19
|
|
RIGHT = 20
|
|
S = 21
|
|
SHININESS = 22
|
|
SPECULAR = 23
|
|
T = 24
|
|
TANGENT_X = 25
|
|
TANGENT_Y = 26
|
|
TANGENT_Z = 27
|
|
TIME = 28
|
|
TOP = 29
|
|
TRANSPARENCY = 30
|
|
TRANSPARENT = 31
|
|
U = 32
|
|
V = 33
|
|
W = 34
|
|
X = 35
|
|
XFOV = 36
|
|
Y = 37
|
|
YFOV = 38
|
|
Z = 39
|
|
ZFAR = 40
|
|
ZNEAR = 41
|
|
MATRIX4X4 = 42 # Not in Common Profile really but here for baked animation param name
|
|
|
|
str = [ "", "A", "AMBIENT", "ANGLE", "ATTENUATION",
|
|
"ATTENUATION_SCALE", "B", "BOTTOM", "COLOR", "DIFFUSE",
|
|
"EMISSION", "FALLOFF", "FALLOFF_SCALE", "G", "LEFT",
|
|
"P", "Q", "R", "REFLECTIVE", "REFLECTIVITY", "RIGHT", "S",
|
|
"SHININESS", "SPECULAR", "T", "TANGENT.X", "TANGENT.Y",
|
|
"TANGENT.Z", "TIME", "TOP", "TRANSPARENCY", "TRANSPARENT",
|
|
"U", "V", "W", "X", "XFOV", "Y", "YFOV", "Z", "ZFAR", "ZNEAR", "matrix" ]
|
|
|
|
class _ProgramIDAndURL:
|
|
ANGLE_MAP = 1
|
|
BEZIER = 2
|
|
BSPLINE = 3
|
|
CARDINAL = 4
|
|
CONSTANT = 5
|
|
CUBE_MAP = 6
|
|
FISH_EYE = 7
|
|
HERMITE = 8
|
|
LAMBERT = 9
|
|
LINEAR = 10
|
|
ORTHOGRAPHIC = 11
|
|
PANORAMA = 12
|
|
PERSPECTIVE = 13
|
|
PHONG = 14
|
|
REAR_FISH_EYE = 15
|
|
SPHERICAL = 16
|
|
|
|
str = [ "", "ANGLE_MAP", "BEZIER", "BSPLINE", "CARDINAL", "CONSTANT",
|
|
"CUBE_MAP", "FISH_EYE", "HERMITE", "LAMBERT", "LINEAR",
|
|
"ORTHOGRAPHIC", "PANORAMA", "PERSPECTIVE", "PHONG",
|
|
"REAR_FISH_EYE", "SPHERICAL" ]
|
|
|
|
class _CodeAndEntrySemantic:
|
|
FRAGMENT_PROGRAM = 1
|
|
VERTEX_PROGRAM = 2
|
|
|
|
class _InputSemantic:
|
|
BIND_SHAPE_NORMAL = 1
|
|
BIND_SHAPE_POSITION = 2
|
|
BINORMAL = 3
|
|
COLOR = 4
|
|
IMAGE = 5
|
|
INPUT = 6
|
|
IN_TANGENT = 7
|
|
INTERPOLATION = 8
|
|
INV_BIND_MATRIX = 9
|
|
JOINT = 10
|
|
JOINTS_AND_WEIGHTS = 11
|
|
NORMAL = 12
|
|
OUTPUT = 13
|
|
OUT_TANGENT = 14
|
|
POSITION = 15
|
|
TANGENT = 16
|
|
TEXCOORD = 17
|
|
TEXTURE = 18
|
|
UV = 19
|
|
VERTEX = 20
|
|
WEIGHT = 21
|
|
|
|
str = [ "", "BIND_SHAPE_NORMAL", "BIND_SHAPE_POSITION", "BINORMAL",
|
|
"COLOR", "IMAGE", "INPUT", "IN_TANGENT", "INETRPOLATION",
|
|
"INV_BIND_MATRIX", "JOINT", "JOINTS_AND_WEIGHTS", "NORMAL",
|
|
"OUTPUT", "OUT_TANGENT", "POSITION", "TANGENT", "TEXCOORD",
|
|
"TEXTURE", "UV", "VERTEX", "WEIGHT" ]
|
|
|
|
class _ChannelAndControllerTarget:
|
|
#( # )[( # )]
|
|
A = 1
|
|
ANGLE = 2
|
|
B = 3
|
|
G = 4
|
|
P = 5
|
|
Q = 6
|
|
R = 7
|
|
S = 8
|
|
T = 9
|
|
TIME = 10
|
|
U = 11
|
|
V = 12
|
|
W = 13
|
|
X = 14
|
|
Y = 15
|
|
Z = 16
|
|
|
|
class _LibraryType:
|
|
ANIMATION = 1
|
|
CAMERA = 2
|
|
CODE = 3
|
|
CONTROLLER = 4
|
|
GEOMETRY = 5
|
|
IMAGE = 6
|
|
LIGHT = 7
|
|
MATERIAL = 8
|
|
PROGRAM = 9
|
|
TEXTURE = 10
|
|
|
|
str = [ "", "ANIMATION", "CAMERA", "CODE", "CONTROLLER", "GEOMETRY",
|
|
"IMAGE", "LIGHT", "MATERIAL", "PROGRAM", "TEXTURE" ]
|
|
|
|
|
|
class _FlowType:
|
|
IN = 1
|
|
OUT = 2
|
|
INOUT = 3
|
|
|
|
str = [ "", "IN", "OUT", "INOUT" ]
|
|
|
|
class _NodeType:
|
|
NODE = 1
|
|
JOINT = 2
|
|
|
|
str = [ "", "NODE", "JOINT" ]
|
|
|
|
class _LightType:
|
|
AMBIENT = 1
|
|
DIRECTIONAL = 2
|
|
POINT = 3
|
|
SPOT = 4
|
|
|
|
str = [ "", "AMBIENT", "DIRECTIONAL", "POINT", "SPOT" ]
|
|
|
|
|
|
# Definition of modules for easier access in code
|
|
# Note: This is pretty stupid I know ...
|
|
|
|
class PN( _ParamName ):
|
|
pass
|
|
class PIAU( _ProgramIDAndURL ):
|
|
pass
|
|
class CAES( _CodeAndEntrySemantic ):
|
|
pass
|
|
class IS( _InputSemantic ):
|
|
pass
|
|
class CACT( _ChannelAndControllerTarget ):
|
|
pass
|
|
class LT( _LibraryType ):
|
|
pass
|
|
class FT( _FlowType ):
|
|
pass
|
|
class NT( _NodeType ):
|
|
pass
|
|
class LIGHT( _LightType ):
|
|
pass
|
|
|
|
# Common Profile
|
|
class CP( _CommonProfile ):
|
|
pass
|
|
|
|
|
|
# Element types
|
|
# Note that attributes are local here defined as their types (string, float)
|
|
# and not Attr object types. Every element
|
|
# has defined set and get methods for their types to create a better interface
|
|
# for its element type
|
|
|
|
# NOTE: Do not create instances of these class directly. Use the create...
|
|
# functions in COLLADADocument
|
|
|
|
class _COLLADAElement( Element ):
|
|
|
|
__version = "1.3.1"
|
|
__xmlns = "http://www.collada.org/2005/COLLADASchema"
|
|
__xmlbase = None
|
|
|
|
def setVersion( self, version ):
|
|
self.__version = version
|
|
self.setAttribute( "version", self.__version )
|
|
return
|
|
|
|
def getVersion( self ):
|
|
return self.__version
|
|
|
|
def __init__( self, version=None ):
|
|
Element.__init__( self, "COLLADA" )
|
|
self.__version = version
|
|
if ( self.__version == None ):
|
|
self.__version = "1.3.1"
|
|
self.setAttribute( "version", self.__version )
|
|
self.setAttribute( "xmlns", self.__xmlns )
|
|
|
|
class _SceneElement( Element ):
|
|
|
|
_name = ""
|
|
_id = ""
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "scene" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _NodeElement( Element ):
|
|
|
|
_name = None
|
|
_id = None
|
|
_nodeType = None
|
|
|
|
def __init__( self, name, id, nodeType ):
|
|
Element.__init__( self, "node" )
|
|
self._id = id
|
|
self._name = name
|
|
self._nodeType = nodeType
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
if not ( self._nodeType == None ):
|
|
self.setAttribute( "type", CP.NT.str[ self._nodeType ] )
|
|
|
|
class _BoundingBoxElement( Element ):
|
|
pass
|
|
|
|
class _CameraElement( Element ):
|
|
|
|
_name = ""
|
|
_id = ""
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "camera" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _OpticsElement( Element) :
|
|
|
|
def __init__( self ):
|
|
Element.__init__( self, "optics" )
|
|
|
|
|
|
class _ImagerElement( Element ):
|
|
pass
|
|
|
|
class _InstanceElement( Element, Childless ):
|
|
|
|
_url = None
|
|
|
|
def __init__( self, url ):
|
|
Element.__init__( self, "instance" )
|
|
self._url = url
|
|
if not ( self._url == None ):
|
|
self.setAttribute( "url", "#" + self._url )
|
|
|
|
class _LibraryElement( Element ):
|
|
|
|
_libraryType = None
|
|
_name = None
|
|
_id = None
|
|
|
|
def __init__( self, libraryType ):
|
|
Element.__init__( self, "library" )
|
|
self._libraryType = libraryType
|
|
self.setAttribute( "type", CP.LT.str[ self._libraryType ] )
|
|
|
|
|
|
class _AnimationElement( Element ):
|
|
|
|
_name = None
|
|
_id = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "animation" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _ChannelElement( Element ):
|
|
|
|
_name = None
|
|
_id = None
|
|
_source = None
|
|
_target = None
|
|
|
|
def __init__( self, id, name, source, target ):
|
|
Element.__init__( self, "channel" )
|
|
self._id = id
|
|
self._name = name
|
|
self._source = source
|
|
self._target = target
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._source == None ):
|
|
self.setAttribute( "source", '#' + self._source )
|
|
if not ( self._target == None ):
|
|
self.setAttribute( "target", self._target )
|
|
|
|
|
|
class _SamplerElement( Element ):
|
|
|
|
_name = None
|
|
_id = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "sampler" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
|
|
class _ControllerElement( Element ):
|
|
pass
|
|
|
|
class _SkinElement( Element ):
|
|
pass
|
|
|
|
class _CombinerElement( Element ):
|
|
pass
|
|
|
|
class _JointsElement( Element ):
|
|
pass
|
|
|
|
class _GeometryElement( Element ):
|
|
|
|
_name = ""
|
|
_id = ""
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "geometry" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _MeshElement( Element ):
|
|
|
|
_name = ""
|
|
_id = ""
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "mesh" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _LinesElement( Element ):
|
|
pass
|
|
|
|
class _LinestripsElement( Element ):
|
|
pass
|
|
|
|
class _PolygonsElement( Element ):
|
|
|
|
_count = None
|
|
_material = None
|
|
|
|
def __init__( self, count, material ):
|
|
Element.__init__( self, "polygons" )
|
|
self._count = count
|
|
self._material = material
|
|
|
|
if not ( self._count == None ):
|
|
self.setAttribute( "count", "%i" % self._count )
|
|
if not ( self._material == None ):
|
|
self.setAttribute( "material", "#" + self._material )
|
|
|
|
class _PElement( Element, Childless ):
|
|
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self ):
|
|
Element.__init__( self, "p" )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _TrianglesElement( Element ):
|
|
pass
|
|
|
|
class _TrifansElement( Element ):
|
|
pass
|
|
|
|
class _TristripsElement( Element ):
|
|
pass
|
|
|
|
class _VerticesElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
_count = None
|
|
|
|
def __init__( self, id, name, count ):
|
|
Element.__init__( self, "vertices" )
|
|
self._id = id
|
|
self._name = name
|
|
self._count = count
|
|
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._count == None ):
|
|
self.setAttribute( "count", "%i" % self._count )
|
|
|
|
|
|
class _SourceElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "source" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
class _AccessorElement( Element ):
|
|
|
|
_count = None
|
|
_id = None
|
|
_offset = None
|
|
_source = None
|
|
_stride = None
|
|
|
|
def __init__( self, count, id, offset, source, stride ):
|
|
Element.__init__( self, "accessor" )
|
|
self._count = count
|
|
self._id = id
|
|
self._offset = offset
|
|
self._source = source
|
|
self._stride = stride
|
|
if not ( self._count == None ):
|
|
self.setAttribute( "count", "%i" % self._count )
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._offset == None ):
|
|
self.setAttribute( "offset", "%i" % self._offset )
|
|
if not ( self._source == None ):
|
|
self.setAttribute( "source", "#" + self._source )
|
|
if not ( self._stride == None ):
|
|
self.setAttribute( "stride", "%i" % self._stride )
|
|
|
|
|
|
class _ArrayElement( Element ):
|
|
pass
|
|
|
|
class _BoolArrayElement( Element ):
|
|
pass
|
|
|
|
class _FloatArrayElement( Element ):
|
|
|
|
_count = None
|
|
_id = None
|
|
_name = None
|
|
_digits = None
|
|
_magnitude = None
|
|
_data = None
|
|
_dataType = 'STRING'
|
|
#_fps = 25
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def setDataType( self, dataType ):
|
|
self._dataType = dataType
|
|
|
|
def setCount( self, count ):
|
|
self._count = count
|
|
self.setAttribute( "count", "%i" % self._count )
|
|
|
|
# def setFPS( self, fps ):
|
|
# self._fps = fps
|
|
|
|
def __init__( self, count, id, name, digits, magnitude ):
|
|
Element.__init__( self, "float_array" )
|
|
self._count = count
|
|
self._id = id
|
|
self._name = name
|
|
self._digits = digits
|
|
self._magnitude = magnitude
|
|
if not ( self._count == None ):
|
|
self.setAttribute( "count", "%i" % self._count )
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._digits == None ):
|
|
self.setAttribute( "digits", "%i" % self._digits )
|
|
if not ( self._magnitude == None ):
|
|
self.setAttribute( "magnitude", "%i" % self._magnitude )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
|
|
global niceFormat
|
|
global fps
|
|
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
|
|
|
|
# writer.write(">%s%s</%s>%s" % ( self._data, newl + indent, self.tagName, newl ) )
|
|
writer.write( ">" )
|
|
dataString = ''
|
|
if ( self._dataType == 'POSITION' ):
|
|
if ( niceFormat ):
|
|
for v in self._data:
|
|
dataString = "\n%.6f %.6f %.6f" % ( v.co[0], v.co[1], v.co[2] )
|
|
writer.write( dataString )
|
|
else:
|
|
v = self._data
|
|
dataString = "%.6f %.6f %.6f " % ( v[0].co[0], v[0].co[1], v[0].co[2] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = "%.6f %.6f %.6f " % ( v[i].co[0], v[i].co[1], v[i].co[2] )
|
|
writer.write( dataString )
|
|
dataString = "%.6f %.6f %.6f" % ( v[size-1].co[0], v[size-1].co[1], v[size-1].co[2] )
|
|
writer.write( dataString )
|
|
|
|
elif ( self._dataType == 'NORMAL' ):
|
|
if ( niceFormat ):
|
|
for n in self._data:
|
|
dataString = "\n%.6f %.6f %.6f" % ( n[0], n[1], n[2] )
|
|
writer.write( dataString )
|
|
else:
|
|
n = self._data
|
|
dataString = "%.6f %.6f %.6f " % ( n[0][0], n[0][1], n[0][2] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = "%.6f %.6f %.6f " % ( n[i][0], n[i][1], n[i][2] )
|
|
writer.write( dataString )
|
|
dataString = "%.6f %.6f %.6f" % ( n[size-1][0], n[size-1][1], n[size-1][2] )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'UV' ):
|
|
if ( niceFormat ):
|
|
for uv in self._data:
|
|
dataString = "\n%.6f %.6f" % ( uv[0], uv[1] )
|
|
writer.write( dataString )
|
|
else:
|
|
uv = self._data
|
|
dataString = "%.6f %.6f " % ( uv[0][0], uv[0][1] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = "%.6f %.6f " % ( uv[i][0], uv[i][1] )
|
|
writer.write( dataString )
|
|
dataString = "%.6f %.6f" % ( uv[size-1][0], uv[size-1][1] )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONINPUT-MATRIX' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( tValue / fps )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
size = len( self._data )
|
|
if ( size > 1 ):
|
|
dataString = '%.6f ' % ( tValue[0] / fps )
|
|
writer.write( dataString )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( tValue[i] / fps )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( tValue[size-1] / fps )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONINPUT' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( tValue.pt[0] / fps )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
size = len( self._data )
|
|
if ( size > 1 ):
|
|
dataString = '%.6f ' % ( tValue[0].pt[0] / fps )
|
|
writer.write( dataString )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( tValue[i].pt[0] / fps )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( tValue[size-1].pt[0] / fps )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONOUTPUT-MATRIX' ):
|
|
if ( niceFormat ):
|
|
dataString = ''
|
|
for m in self._data:
|
|
dataString = '\n%.6f %.6f %.6f %.6f\n%.6f %.6f %.6f %.6f\n%.6f %.6f %.6f %.6f\n%.6f %.6f %.6f %.6f' % ( m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3] )
|
|
writer.write( dataString )
|
|
else:
|
|
m = self._data[ 0 ]
|
|
dataString = '%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f ' % ( m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
m = self._data[ i ]
|
|
dataString = '%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f ' % ( m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3] )
|
|
writer.write( dataString )
|
|
m = self._data[ size - 1 ]
|
|
dataString = '%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f' % ( m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3] )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONOUTPUT-SHININESS' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( tValue.pt[1] / 4.0 )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
dataString = "%.6f " % ( tValue[0].pt[1] / 4.0 )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( tValue[i].pt[1] / 4.0 )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( tValue[size-1].pt[1] / 4.0 )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONOUTPUT-ALPHA' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( 1.0 - tValue.pt[1] )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
dataString = "%.6f " % ( 1.0 - tValue[0].pt[1] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( 1.0 - tValue[i].pt[1] )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( 1.0 - tValue[size-1].pt[1] )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONOUTPUT-ROTATION' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( tValue.pt[1] * 10.0 )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
dataString = "%.6f " % ( tValue[0].pt[1] * 10.0 )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( tValue[i].pt[1] * 10.0 )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( tValue[size-1].pt[1] * 10.0 )
|
|
writer.write( dataString )
|
|
elif ( self._dataType == 'ANIMATIONOUTPUT' ):
|
|
if ( niceFormat ):
|
|
for tValue in self._data:
|
|
dataString = "\n%.6f" % ( tValue.pt[1] )
|
|
writer.write( dataString )
|
|
else:
|
|
tValue = self._data
|
|
dataString = "%.6f " % ( tValue[0].pt[1] )
|
|
writer.write( dataString )
|
|
size = len( self._data )
|
|
for i in range( 1, size - 1 ):
|
|
dataString = '%.6f ' % ( tValue[i].pt[1] )
|
|
writer.write( dataString )
|
|
dataString = "%.6f" % ( tValue[size-1].pt[1] )
|
|
writer.write( dataString )
|
|
else:
|
|
# Replace '\n' with '\n + indent + addindent'
|
|
if ( niceFormat ):
|
|
replaceString = '\n' + indent + addindent
|
|
self._data = self._data.replace( '\n', replaceString )
|
|
_write_data( writer, self._data )
|
|
|
|
if ( niceFormat ):
|
|
writer.write("%s</%s>%s" % ( newl + indent, self.tagName, newl ) )
|
|
else:
|
|
writer.write("</%s>%s" % ( self.tagName, newl ) )
|
|
|
|
|
|
class _IntArrayElement( Element ):
|
|
pass
|
|
|
|
class _NameArrayElement( Element ):
|
|
pass
|
|
|
|
class _InputElement( Element ):
|
|
|
|
_idx = None
|
|
_semantic = None
|
|
_source = None
|
|
|
|
def __init__( self, idx, semantic, source ):
|
|
Element.__init__( self, "input" )
|
|
self._idx = idx
|
|
self._semantic = semantic
|
|
self._source = source
|
|
if not ( self._idx == None ):
|
|
self.setAttribute( "idx", "%i" % (self._idx) )
|
|
if not ( self._semantic == None ):
|
|
self.setAttribute( "semantic", CP.IS.str[ self._semantic ] )
|
|
if not ( self._source == None ):
|
|
self.setAttribute( "source", "#" + self._source )
|
|
|
|
class _MaterialElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "material" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", name )
|
|
|
|
|
|
class _ShaderElement( Element ):
|
|
_id = None
|
|
_name = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "shader" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "id", self._name )
|
|
|
|
class _PassElement( Element ):
|
|
def __init__( self ):
|
|
Element.__init__( self, "pass" )
|
|
|
|
class _TechniqueElement( Element ):
|
|
|
|
_profile = None
|
|
|
|
def setProfile( self, profile ):
|
|
self._profile = profile
|
|
|
|
def __init__( self, profile ):
|
|
Element.__init__( self, "technique" )
|
|
self._profile = profile
|
|
if not ( self._profile == None ):
|
|
self.setAttribute( "profile", CP.str[ self._profile ] )
|
|
|
|
class _ImageElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
_height = None
|
|
_width = None
|
|
_depth = None
|
|
_source = None
|
|
_format = None
|
|
|
|
def setIdAndName( self, arg ):
|
|
_id = arg
|
|
_name = arg
|
|
self.setAttribute( "id", _id )
|
|
self.setAttribute( "name", _name )
|
|
|
|
def setWidth( self, width ):
|
|
self._width = width
|
|
self.setAttribute( "width", "%i" % (self._width) )
|
|
|
|
def setHeight( self, height ):
|
|
self._height = height
|
|
self.setAttribute( "height", "%i" % (self._height) )
|
|
|
|
def setSource( self, source ):
|
|
self._source = source
|
|
self.setAttribute( "source", self._source )
|
|
|
|
def __init__( self, id, name, height, width, depth,
|
|
source, format ):
|
|
Element.__init__( self, "image" )
|
|
|
|
self._id = id
|
|
self._name = name
|
|
self._height = height
|
|
self._width = width
|
|
self._depth = depth
|
|
self._source = source
|
|
self._format = format
|
|
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._height == None ):
|
|
self.setAttribute( "height", "%i" % self._height )
|
|
if not ( self._width == None ):
|
|
self.setAttribute( "width", "%i" % self._width )
|
|
if not ( self._depth == None ):
|
|
self.setAttribute( "depth", "%i" % self._depth )
|
|
if not ( self._source == None ):
|
|
self.setAttribute( "source", self._source )
|
|
if not ( self._format == None ):
|
|
self.setAttribute( "format", self._format )
|
|
|
|
class _LightElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
_type = None
|
|
|
|
def __init__( self, id, name, type ):
|
|
Element.__init__( self, "light" )
|
|
self._id = id
|
|
self._name = name
|
|
self._type = type
|
|
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._type == None ):
|
|
self.setAttribute( "type", "%s" % CP.LIGHT.str[ self._type ] )
|
|
|
|
class _TextureElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
|
|
def __init__( self, id, name ):
|
|
Element.__init__( self, "texture" )
|
|
self._id = id
|
|
self._name = name
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
|
|
class _ProgramElement( Element ):
|
|
|
|
_id = None
|
|
_name = None
|
|
_url = None
|
|
|
|
def __init__( self, id, name, url ):
|
|
Element.__init__( self, "program" )
|
|
self._id = id
|
|
self._name = name
|
|
self._url = url
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._url == None ):
|
|
self.setAttribute( "url", self._url )
|
|
|
|
class _CodeElement( Element ):
|
|
pass
|
|
|
|
class _EntryElement( Element ):
|
|
pass
|
|
|
|
class _ParamElement( Element, Childless ):
|
|
|
|
_id = None
|
|
_name = None
|
|
_type = None
|
|
_flow = None
|
|
_semantic = None
|
|
_sid = None
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self, id, name, type, flow, semantic, sid ):
|
|
Element.__init__( self, "param" )
|
|
self._id = id
|
|
self._name = name
|
|
self._type = type
|
|
self._flow = flow
|
|
self._semantic = semantic
|
|
self._sid = sid
|
|
if not ( self._id == None ):
|
|
self.setAttribute( "id", self._id )
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", CP.PN.str[ self._name ] )
|
|
if not ( self._type == None ):
|
|
self.setAttribute( "type", self._type )
|
|
if not ( self._flow == None ):
|
|
self.setAttribute( "flow", CP.FT.str[ self._flow ] )
|
|
if not ( self._semantic == None ):
|
|
self.setAttribute( "semantic", self._semantic )
|
|
if not ( self._sid == None ):
|
|
self.setAttribute( "sid", self._sid )
|
|
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _MatrixElement( Element, Childless ):
|
|
|
|
_sid = None
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self, sid ):
|
|
Element.__init__( self, "matrix" )
|
|
self._sid = sid
|
|
if not ( self._sid == None ):
|
|
self.setAttribute( "sid", self._sid )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
|
|
global niceFormat
|
|
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
# Replace '\n' with '\n + indent + addindent'
|
|
if ( niceFormat ):
|
|
replaceString = '\n' + indent + addindent
|
|
self._data = self._data.replace( '\n', replaceString )
|
|
writer.write(">%s%s</%s>%s" % ( self._data, newl + indent, self.tagName, newl ) )
|
|
else:
|
|
writer.write(">%s</%s>%s" % ( self._data, self.tagName, newl ) )
|
|
|
|
|
|
class _LookAtElement( Element ):
|
|
pass
|
|
|
|
class _PerspectiveElement( Element ):
|
|
pass
|
|
|
|
class _RotateElement( Element, Childless ):
|
|
|
|
_sid = None
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self, sid ):
|
|
Element.__init__( self, "rotate" )
|
|
self._sid = sid
|
|
if not ( self._sid == None ):
|
|
self.setAttribute( "sid", self._sid )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _ScaleElement( Element, Childless ):
|
|
|
|
_sid = None
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self, sid ):
|
|
Element.__init__( self, "scale" )
|
|
self._sid = sid
|
|
if not ( self._sid == None ):
|
|
self.setAttribute( "sid", self._sid )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _SkewElement( Element ):
|
|
pass
|
|
|
|
class _TranslateElement( Element, Childless ):
|
|
|
|
_sid = None
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self, data ):
|
|
return self._data
|
|
|
|
def __init__( self, sid ):
|
|
Element.__init__( self, "translate" )
|
|
self._sid = sid
|
|
if not ( self._sid == None ):
|
|
self.setAttribute( "sid", self._sid )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
|
|
class _AuthorElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "author" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _AuthoringToolElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "authoring_tool" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _CreatedElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "created" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _ModifiedElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "modified" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _RevisionElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "modified" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _SourceDataElement( Element, Childless ):
|
|
|
|
_data = None
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "source_data" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
|
|
# Fast data write
|
|
# writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
writer.write( ">" )
|
|
_write_data( writer, self._data )
|
|
writer.write( "</%s>%s" % (self.tagName, newl ) )
|
|
|
|
class _CopyrightElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "copyright" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _TitleElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "title" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
|
|
class _SubjectElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "subject" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _KeywordsElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "keywords" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _CommentsElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "comments" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _UnitElement( Element, Childless ):
|
|
|
|
_name = None
|
|
_meter = None
|
|
|
|
def __init__( self, name, meter ):
|
|
Element.__init__( self, "unit" )
|
|
|
|
self._name = name
|
|
self._meter = meter
|
|
|
|
if not ( self._name == None ):
|
|
self.setAttribute( "name", self._name )
|
|
if not ( self._meter == None ):
|
|
self.setAttribute( "meter", self._meter )
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
|
|
writer.write( "/>%s" % newl )
|
|
|
|
class _UpAxisElement( Element, Childless ):
|
|
|
|
_data = ""
|
|
|
|
def setData( self, data ):
|
|
self._data = data
|
|
|
|
def getData( self ):
|
|
return self._data
|
|
|
|
def __init__( self, data ):
|
|
Element.__init__( self, "up_axis" )
|
|
if not ( data == None ):
|
|
self._data = data
|
|
|
|
# Overloaded writexml function so we can keep data within one line
|
|
# This implementation was taken from the Python 2.3 minidom impl.
|
|
# of class Element
|
|
def writexml( self, writer, indent="", addindent="", newl="" ):
|
|
writer.write(indent+"<" + self.tagName)
|
|
|
|
attrs = self._get_attributes()
|
|
a_names = attrs.keys()
|
|
a_names.sort()
|
|
|
|
for a_name in a_names:
|
|
writer.write(" %s=\"" % a_name)
|
|
_write_data( writer, attrs[a_name].value)
|
|
writer.write("\"")
|
|
if ( self._data == None ):
|
|
writer.write( "/>%s" % newl )
|
|
else:
|
|
writer.write(">%s</%s>%s" % (self._data, self.tagName, newl ) )
|
|
|
|
class _AssetElement( Element ):
|
|
|
|
def __init__( self ):
|
|
Element.__init__( self, "asset" )
|
|
|
|
|
|
|
|
class _ExtraElement( Element ):
|
|
pass
|
|
|
|
|
|
# ----------------------------------------------
|
|
# Utility functions
|
|
# ----------------------------------------------
|
|
def toAngle( radians ):
|
|
return ( radians * 180 ) / 3.14159265
|
|
|
|
|
|
""" Return True if IPO curveName applies to a transform """
|
|
def isTransformCurve( curveName ):
|
|
if ( curveName == 'LocX' or
|
|
curveName == 'LocY' or
|
|
curveName == 'LocZ' or
|
|
curveName == 'RotX' or
|
|
curveName == 'RotY' or
|
|
curveName == 'RotZ' or
|
|
curveName == 'SizeX' or
|
|
curveName == 'SizeY' or
|
|
curveName == 'SizeZ' ):
|
|
return True
|
|
return False
|
|
|
|
""" Return True if IPO curveName applies to a translate """
|
|
def isTranslateCurve( curveName ):
|
|
if ( curveName == 'LocX' or
|
|
curveName == 'LocY' or
|
|
curveName == 'LocZ' ):
|
|
return True
|
|
return False
|
|
|
|
""" Return True if IPO curveName applies to a rotation """
|
|
def isRotationCurve( curveName ):
|
|
if ( curveName == 'RotX' or
|
|
curveName == 'RotY' or
|
|
curveName == 'RotZ' ):
|
|
return True
|
|
return False
|
|
|
|
""" Return a COLLADA param element from IPO curve name """
|
|
def getParamElementFromCurveName( curveName ):
|
|
|
|
# Output TIME if no correct output could be found... (yes kind of stupid
|
|
# I know)
|
|
paramOutput = dae.createParamElement( None, CP.PN.TIME, "float", CP.FT.OUT )
|
|
if ( curveName == 'LocX' or curveName == 'SizeX'):
|
|
paramOutput = dae.createParamElement( None, CP.PN.X, "float", CP.FT.OUT )
|
|
elif ( curveName == 'LocY' or curveName == 'SizeY' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.Y, "float", CP.FT.OUT )
|
|
elif ( curveName == 'LocZ' or curveName == 'SizeZ' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.Z, "float", CP.FT.OUT )
|
|
elif ( curveName == 'RotX' or curveName == 'RotY' or curveName == 'RotZ' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.ANGLE, "float", CP.FT.OUT )
|
|
elif ( curveName == 'R' or curveName == 'ColR' or curveName == 'SpecR' or curveName == 'MirR' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.R, "float", CP.FT.OUT )
|
|
elif ( curveName == 'G' or curveName == 'ColG' or curveName == 'SpecG' or curveName == 'MirG' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.G, "float", CP.FT.OUT )
|
|
elif ( curveName == 'B' or curveName == 'ColB' or curveName == 'SpecB' or curveName == 'MirB' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.B, "float", CP.FT.OUT )
|
|
elif ( curveName == 'Alpha' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.A, "float", CP.FT.OUT )
|
|
elif ( curveName == 'Ref' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.REFLECTIVITY, "float", CP.FT.OUT )
|
|
elif ( curveName == 'Hard' ):
|
|
paramOutput = dae.createParamElement( None, CP.PN.SHININESS, "float", CP.FT.OUT )
|
|
|
|
return paramOutput
|
|
|
|
"""
|
|
Return a COLLADA Target written
|
|
according to the Address Syntax specification.
|
|
The sid values (except the Common Profile constants)
|
|
are my own Blender specific values. However they follow
|
|
the Maya plug-in sid transform syntax.
|
|
"""
|
|
def getTargetNameFromCurveName( curveName ):
|
|
if ( curveName == 'LocX' ): return 'translate.X'
|
|
elif ( curveName == 'LocY' ): return 'translate.Y'
|
|
elif ( curveName == 'LocZ' ): return 'translate.Z'
|
|
elif ( curveName == 'RotX' ): return 'rotateX.ANGLE'
|
|
elif ( curveName == 'RotY' ): return 'rotateY.ANGLE'
|
|
elif ( curveName == 'RotZ' ): return 'rotateZ.ANGLE'
|
|
elif ( curveName == 'SizeX' ): return 'scale.X'
|
|
elif ( curveName == 'SizeY' ): return 'scale.Y'
|
|
elif ( curveName == 'SizeZ' ): return 'scale.Z'
|
|
elif ( curveName == 'R' ): return 'diffuse.R'
|
|
elif ( curveName == 'G' ): return 'diffuse.G'
|
|
elif ( curveName == 'B' ): return 'diffuse.B'
|
|
elif ( curveName == 'Alpha' ): return 'transparency'
|
|
elif ( curveName == 'SpecR' ): return 'specular.R'
|
|
elif ( curveName == 'SpecG' ): return 'specular.G'
|
|
elif ( curveName == 'SpecB' ): return 'specular.B'
|
|
elif ( curveName == 'MirR' ): return 'reflective.R'
|
|
elif ( curveName == 'MirR' ): return 'reflective.G'
|
|
elif ( curveName == 'MirR' ): return 'reflective.B'
|
|
elif ( curveName == 'Ref' ): return 'reflectivity'
|
|
elif ( curveName == 'Hard' ): return 'shininess'
|
|
else:
|
|
return ''
|
|
|
|
|
|
|
|
# ----------------------------------------------
|
|
# BLENDER to COLLADA helper functions
|
|
# ----------------------------------------------
|
|
|
|
# --- Write mesh information to dae file ---
|
|
def writeLight( libraryElement, light ):
|
|
|
|
lightName = light.name
|
|
lightID = lightName + "-Lib"
|
|
lightType = light.getType( )
|
|
lightFlags = light.getMode( )
|
|
distance = light.getDist( )
|
|
energy = light.getEnergy( )
|
|
quad1 = light.getQuad1( )
|
|
quad2 = light.getQuad2( )
|
|
|
|
# Blender LAMP type --> Collada POINT type
|
|
if ( lightType == 0 ):
|
|
lightElement = dae.createLightElement( lightID, lightName, CP.LIGHT.POINT )
|
|
colorParam = dae.createParamElement( None, CP.PN.COLOR, "float3", CP.FT.IN, None, None )
|
|
colorParam.setData( "%.6f %.6f %.6f" % ( light.col[ 0 ], light.col[ 1 ], light.col[ 2 ] ) )
|
|
attenuationParam = dae.createParamElement( None, CP.PN.ATTENUATION, "token", CP.FT.IN, None, None )
|
|
attenuationScaleParam = dae.createParamElement( None, CP.PN.ATTENUATION_SCALE, "float", CP.FT.IN, None, None )
|
|
|
|
if ( lightFlags & light.Modes[ 'Quad' ] ):
|
|
attenuationScale = 2.0 / ( quad2 * distance * energy )
|
|
attenuationParam.setData( "QUADRATIC" )
|
|
attenuationScaleParam.setData( "%.6f" % ( attenuationScale ) )
|
|
else:
|
|
attenuationScale = 2.0 / ( distance * energy )
|
|
attenuationParam.setData( "LINEAR" )
|
|
attenuationScaleParam.setData( "%.6f" % ( attenuationScale ) )
|
|
|
|
lightElement.appendChild( colorParam )
|
|
lightElement.appendChild( attenuationParam )
|
|
lightElement.appendChild( attenuationScaleParam )
|
|
libraryElement.appendChild( lightElement )
|
|
|
|
# Blender SUN type --> Collada DIRECTIONAL type
|
|
elif ( lightType == 1 ):
|
|
lightElement = dae.createLightElement( lightID, lightName, CP.LIGHT.DIRECTIONAL )
|
|
colorParam = dae.createParamElement( None, CP.PN.COLOR, "float3", CP.FT.IN, None, None )
|
|
colorParam.setData( "%.6f %.6f %.6f" % ( light.col[ 0 ], light.col[ 1 ], light.col[ 2 ] ) )
|
|
|
|
lightElement.appendChild( colorParam )
|
|
libraryElement.appendChild( lightElement )
|
|
|
|
# Blender SPOT type --> Collada SPOT type
|
|
elif ( lightType == 2 ):
|
|
lightElement = dae.createLightElement( lightID, lightName, CP.LIGHT.SPOT )
|
|
colorParam = dae.createParamElement( None, CP.PN.COLOR, "float3", CP.FT.IN, None, None )
|
|
colorParam.setData( "%.6f %.6f %.6f" % ( light.col[ 0 ], light.col[ 1 ], light.col[ 2 ] ) )
|
|
|
|
attenuationParam = dae.createParamElement( None, CP.PN.ATTENUATION, "token", CP.FT.IN, None, None )
|
|
attenuationScaleParam = dae.createParamElement( None, CP.PN.ATTENUATION_SCALE, "float", CP.FT.IN, None, None )
|
|
|
|
# Is this the correct attenuation algorithm?
|
|
if ( lightFlags & light.Modes[ 'Quad' ] ):
|
|
attenuationScale = 2.0 / ( quad2 * distance * energy )
|
|
attenuationParam.setData( "QUADRATIC" )
|
|
attenuationScaleParam.setData( "%.6f" % ( attenuationScale ) )
|
|
else:
|
|
attenuationScale = 2.0 / ( distance * energy )
|
|
attenuationParam.setData( "LINEAR" )
|
|
attenuationScaleParam.setData( "%.6f" % ( attenuationScale ) )
|
|
|
|
# Export ANGLE, FALLOFF and FALLOFF_SCALE
|
|
angle = light.getSpotSize( )
|
|
angleParam = dae.createParamElement( None, CP.PN.ANGLE, "float", CP.FT.IN, None, None )
|
|
angleParam.setData( "%.6f" % angle )
|
|
|
|
|
|
falloff = light.getSpotSize( )
|
|
falloffParam = dae.createParamElement( None, CP.PN.FALLOFF, "token", CP.FT.IN, None, None )
|
|
falloffParam.setData( "LINEAR" )
|
|
|
|
falloffScale = light.getSpotBlend( ) * 128.0
|
|
falloffScaleParam = dae.createParamElement( None, CP.PN.FALLOFF_SCALE, "float", CP.FT.IN, None, None )
|
|
falloffScaleParam.setData( "%.6f" % falloffScale )
|
|
|
|
lightElement.appendChild( colorParam )
|
|
lightElement.appendChild( attenuationParam )
|
|
lightElement.appendChild( attenuationScaleParam )
|
|
lightElement.appendChild( angleParam )
|
|
lightElement.appendChild( falloffParam )
|
|
lightElement.appendChild( falloffScaleParam )
|
|
libraryElement.appendChild( lightElement )
|
|
|
|
elif ( lightType == 3 ):
|
|
lightElement = dae.createLightElement( lightID, lightName, CP.LIGHT.AMBIENT )
|
|
colorParam = dae.createParamElement( None, CP.PN.COLOR, "float3", CP.FT.IN, None, None )
|
|
colorParam.setData( "%.6f %.6f %.6f" % ( light.col[ 0 ], light.col[ 1 ], light.col[ 2 ] ) )
|
|
lightElement.appendChild( colorParam )
|
|
libraryElement.appendChild( lightElement )
|
|
elif ( lightType == 4 ):
|
|
print "Warning! Export of light type Area not supported! Light will not export."
|
|
elif ( lightType == 5 ):
|
|
print "Warning! Export of light type Photon not supported! Light will not export."
|
|
|
|
|
|
# --- Write mesh information to dae file ---
|
|
def writeMesh( libraryElement, mesh ):
|
|
|
|
meshName = mesh.name
|
|
meshID = mesh.name + "-Lib"
|
|
hasFaceUV = mesh.hasFaceUV()
|
|
nrVerts = len( mesh.verts )
|
|
nrFaces = len( mesh.faces )
|
|
geometry = dae.createGeometryElement( meshID, meshName )
|
|
meshElement = dae.createMeshElement( )
|
|
posID = meshName + "-Pos"
|
|
normalID = meshName + "-Normal"
|
|
uvID = meshName + "-UV1"
|
|
position = dae.createSourceElement( posID, posID )
|
|
normal = dae.createSourceElement( normalID, normalID )
|
|
uv = dae.createSourceElement( uvID, uvID )
|
|
posArrayID = posID + "-Array"
|
|
noArrayID = normalID + "-Array"
|
|
uvArrayID = uvID + "-Array"
|
|
floatArrayPos = dae.createFloatArrayElement( nrVerts * 3, posArrayID, posArrayID )
|
|
floatArrayNo = dae.createFloatArrayElement( -1, noArrayID, noArrayID )
|
|
floatArrayUV = dae.createFloatArrayElement( -1, uvArrayID, uvArrayID )
|
|
|
|
|
|
# Set elements data as list data for faster output!
|
|
floatArrayPos.setDataType( 'POSITION' )
|
|
floatArrayNo.setDataType( 'NORMAL' )
|
|
floatArrayUV.setDataType( 'UV' )
|
|
|
|
# Output nice format for vertex data
|
|
# TODO: Make this routine better
|
|
# startTime = sys.time()
|
|
# posDataArray = array('f')
|
|
# posData = ""
|
|
## for v in mesh.verts:
|
|
## #posDataArray.append( v.co[ 0 ] )
|
|
## #posDataArray.append( v.co[ 1 ] )
|
|
## #posDataArray.append( v.co[ 2 ] )
|
|
## posData += "\n%.6f %.6f %.6f" % ( v.co[0], v.co[1], v.co[2] )
|
|
|
|
posData = mesh.verts
|
|
|
|
# Get normal and UV data
|
|
#no = ""
|
|
no = []
|
|
#st = ""
|
|
st = []
|
|
nrExclusiveVertices = 0
|
|
nrUVCoords = 0
|
|
faceNr = 0
|
|
for f in mesh.faces:
|
|
nrVert = len( f.v )
|
|
if ( (nrVert == 3) or (nrVert == 4 ) ):
|
|
if ( f.smooth != 0 ): # If smooth than fetch normal for every vertex in face
|
|
for v2 in f.v:
|
|
#no += "\n%.6f %.6f %.6f" % ( v2.no[0], v2.no[1], v2.no[2] )
|
|
no.append( v2.no )
|
|
nrExclusiveVertices += 1
|
|
elif ( f.smooth == 0 ):
|
|
# FIXME: There is unknown bug here...
|
|
for i in f.v:
|
|
if ( len( f.no ) > 0 ):
|
|
#no += "\n%.6f %.6f %.6f" % ( f.no[0], f.no[1], f.no[2] )
|
|
no.append( f.no )
|
|
else:
|
|
print "Warning! Face has no normal. Outputing (0,0,0) as normal instead!"
|
|
# TODO: Calculate normal instead!
|
|
#no += "\n%.6f %.6f %.6f" % ( 0.0, 0.0, 0.0 )
|
|
no.append( [ 0.0, 0.0, 0.0 ] )
|
|
nrExclusiveVertices += 1
|
|
|
|
if ( hasFaceUV ): # Mesh has face UV set so let's export UV coordinates
|
|
for i in range( nrVert ):
|
|
#st += "\n%.6f %.6f" % ( f.uv[i][0], f.uv[i][1] )
|
|
st.append( f.uv[i] )
|
|
nrUVCoords += 1
|
|
else:
|
|
print "Warning: Face in %s" % meshName + " is not a triangle or quad! Face ignored."
|
|
# endTime = sys.time( )
|
|
# print "Getting mesh data time: %.6f" % ( endTime - startTime )
|
|
|
|
floatArrayNo.setCount( nrExclusiveVertices * 3 )
|
|
floatArrayNo.setData( no )
|
|
floatArrayPos.setData( posData )
|
|
#floatArrayPos.setData( posDataArray.tostring( ) )
|
|
normal.appendChild( floatArrayNo )
|
|
position.appendChild( floatArrayPos )
|
|
|
|
if ( hasFaceUV ):
|
|
floatArrayUV.setCount( nrUVCoords * 2 )
|
|
floatArrayUV.setData( st )
|
|
uv.appendChild( floatArrayUV )
|
|
|
|
meshElement.appendChild( position )
|
|
meshElement.appendChild( normal )
|
|
|
|
|
|
# Write COMMON technique elements
|
|
techniquePos = dae.createTechniqueElement( CP.COMMON )
|
|
techniqueNormal = dae.createTechniqueElement( CP.COMMON )
|
|
accessorPos = dae.createAccessorElement( nrExclusiveVertices, posArrayID, posArrayID + "-Accessor", 0, 3 )
|
|
accessorNormal = dae.createAccessorElement( nrExclusiveVertices, noArrayID, noArrayID + "-Accessor", 0 , 3 )
|
|
|
|
paramPosX = dae.createParamElement( None, CP.PN.X, "float", None )
|
|
paramPosY = dae.createParamElement( None, CP.PN.Y, "float", None )
|
|
paramPosZ = dae.createParamElement( None, CP.PN.Z, "float", None )
|
|
|
|
paramNoX = dae.createParamElement( None, CP.PN.X, "float", None )
|
|
paramNoY = dae.createParamElement( None, CP.PN.Y, "float", None )
|
|
paramNoZ = dae.createParamElement( None, CP.PN.Z, "float", None )
|
|
|
|
accessorPos.appendChild( paramPosX )
|
|
accessorPos.appendChild( paramPosY )
|
|
accessorPos.appendChild( paramPosZ )
|
|
|
|
accessorNormal.appendChild( paramNoX )
|
|
accessorNormal.appendChild( paramNoY )
|
|
accessorNormal.appendChild( paramNoZ )
|
|
|
|
|
|
techniquePos.appendChild( accessorPos )
|
|
position.appendChild( techniquePos )
|
|
techniqueNormal.appendChild( accessorNormal )
|
|
normal.appendChild( techniqueNormal )
|
|
|
|
if ( hasFaceUV ):
|
|
meshElement.appendChild( uv )
|
|
techniqueUV = dae.createTechniqueElement( CP.COMMON )
|
|
accessorUV = dae.createAccessorElement( nrUVCoords, uvArrayID, uvArrayID + "-Accessor", 0, 2 )
|
|
|
|
paramS = dae.createParamElement( None, CP.PN.S, "float", None )
|
|
paramT = dae.createParamElement( None, CP.PN.T, "float", None )
|
|
|
|
accessorUV.appendChild( paramS )
|
|
accessorUV.appendChild( paramT )
|
|
|
|
techniqueUV.appendChild( accessorUV )
|
|
uv.appendChild( techniqueUV )
|
|
|
|
|
|
# Write vertices and polygons information
|
|
verticesName = meshName + "-Vertices"
|
|
vertices = dae.createVerticesElement( verticesName, verticesName, nrExclusiveVertices )
|
|
vInput = dae.createInputElement( None, CP.IS.POSITION, posID )
|
|
|
|
# TODO: Write UV here if we have sticky vertices. Also write normal data
|
|
# if the whole mesh is smooth
|
|
|
|
# Write polygon element
|
|
materials = mesh.getMaterials( 1 )
|
|
|
|
if ( len( materials ) > 1 ):
|
|
print "Warning! Mesh has multiple materials. Will only export the first one"
|
|
|
|
# TODO: Write polygon element for each material
|
|
material = None
|
|
polygons = None
|
|
if len( materials ) > 0:
|
|
material = materials[ 0 ]
|
|
if ( material != None ):
|
|
materialSource = material.getName( ) + "-Lib"
|
|
polygons = dae.createPolygonsElement( nrFaces, materialSource )
|
|
else:
|
|
polygons = dae.createPolygonsElement( nrFaces )
|
|
else:
|
|
polygons = dae.createPolygonsElement( nrFaces )
|
|
|
|
# Write input semantics for polygons
|
|
vertexInput = dae.createInputElement( 0, CP.IS.VERTEX, verticesName )
|
|
normalInput = dae.createInputElement( 1, CP.IS.NORMAL, normalID )
|
|
polygons.appendChild( vertexInput )
|
|
polygons.appendChild( normalInput )
|
|
|
|
if ( hasFaceUV ):
|
|
uvInput = dae.createInputElement( 2, CP.IS.TEXCOORD, uvID )
|
|
polygons.appendChild( uvInput )
|
|
|
|
|
|
# Write <p> elements
|
|
# NOTE: index here points to normal and (if present) texcoord index in floatarray
|
|
index = -1
|
|
for f in mesh.faces:
|
|
pData = ""
|
|
nrVertices = len( f.v )
|
|
if ( (nrVertices == 3) or (nrVertices == 4 ) ):
|
|
for v in f.v:
|
|
index += 1
|
|
if ( hasFaceUV ):
|
|
pData = pData + "%i %i %i" % ( v.index, index, index ) + " "
|
|
else:
|
|
pData = pData + "%i %i" % ( v.index, index ) + " "
|
|
|
|
pData = pData.strip()
|
|
p = dae.createPElement( )
|
|
p.setData( pData )
|
|
polygons.appendChild( p )
|
|
|
|
|
|
vertices.appendChild( vInput )
|
|
meshElement.appendChild( vertices )
|
|
meshElement.appendChild( polygons )
|
|
geometry.appendChild( meshElement )
|
|
libraryElement.appendChild( geometry )
|
|
|
|
# Blender to OpenGL materials
|
|
# With help from Nathan (Waffler at Elysiun)
|
|
def writeMaterial( libraryElement, material ):
|
|
name = material.getName( )
|
|
id = name + "-Lib"
|
|
materialElement = dae.createMaterialElement( id, name )
|
|
|
|
# Create common phong shader with one phong pass
|
|
shaderElement = dae.createShaderElement( None, name + "-Phong" )
|
|
technique = dae.createTechniqueElement( CP.COMMON )
|
|
|
|
# Get material data
|
|
col = material.getRGBCol( )
|
|
speccol = material.getSpecCol( )
|
|
spec = material.getSpec( ) * 0.5
|
|
ambient = material.getAmb( )
|
|
emit = material.getEmit( )
|
|
transparency = 1.0 - material.getAlpha( )
|
|
ref = material.getRef( )
|
|
refcol = material.getMirCol()
|
|
shininess = material.getHardness() / 4.0
|
|
# refID = material.getIOR()
|
|
|
|
|
|
mtextures = material.getTextures( )
|
|
passElement = dae.createPassElement( )
|
|
|
|
# TODO: Perhaps add an option to split texture channels into
|
|
# different <pass> elements instead
|
|
|
|
# Input semantics for texture channel(s)
|
|
for mtex in mtextures:
|
|
if not ( mtex == None ):
|
|
texture = mtex.tex
|
|
if ( texture.type == Texture.Types.IMAGE ):
|
|
texSource = texture.getName() + "-Lib"
|
|
input = dae.createInputElement( None, CP.IS.TEXTURE, texSource )
|
|
passElement.appendChild( input )
|
|
|
|
|
|
# Appereantly I cannot access the shaders so ... output
|
|
# PHONG for now
|
|
|
|
phongProgram = dae.createProgramElement( None, None,
|
|
CP.PIAU.str[ CP.PIAU.PHONG ] )
|
|
|
|
# PHONG PARAMS
|
|
colorParam = dae.createParamElement( None, CP.PN.COLOR, "float3", CP.FT.IN, None, 'color' )
|
|
colorParam.setData( "%.6f %.6f %.6f" % ( col[0], col[1], col[2] ) )
|
|
ambientParam = dae.createParamElement( None, CP.PN.AMBIENT, "float3", CP.FT.IN, None, 'ambient' )
|
|
ambientParam.setData( "%.6f %.6f %.6f" % ( ambient * col[0], ambient * col[1], ambient * col[2] ) )
|
|
diffuseParam = dae.createParamElement( None, CP.PN.DIFFUSE, "float3", CP.FT.IN, None, 'diffuse' )
|
|
diffuseParam.setData( "%.6f %.6f %.6f" % ( col[0], col[1], col[2] ) )
|
|
#transparencyParam = dae.createParamElement( None, CP.PN.TRANSPARENCY, "float", CP.FT.IN )
|
|
#transparencyParam.setData( "%.6f" % transparency )
|
|
specularParam = dae.createParamElement( None, CP.PN.SPECULAR, "float3", CP.FT.IN, None, 'specular' )
|
|
specularParam.setData( "%.6f %.6f %.6f" % ( speccol[0] * spec, speccol[1] * spec, speccol[2] * spec ) )
|
|
emissionParam = dae.createParamElement( None, CP.PN.EMISSION, "float3", CP.FT.IN, None, 'emission' )
|
|
emissionParam.setData( "%.6f %.6f %.6f" % ( emit * col[0], emit * col[1], emit * col[2] ) )
|
|
|
|
shininessParam = dae.createParamElement( None, CP.PN.SHININESS, "float", CP.FT.IN, None, 'shininess' )
|
|
shininessParam.setData( "%.6f" % ( shininess ) )
|
|
|
|
# Output color as transparent color for now
|
|
transparentParam = dae.createParamElement( None, CP.PN.TRANSPARENT, "float", CP.FT.IN, None, 'transparent' )
|
|
transparentParam.setData( "%.6f %.6f %.6f" % ( col[0], col[1], col[2] ) )
|
|
transparencyParam = dae.createParamElement( None, CP.PN.TRANSPARENCY, "float", CP.FT.IN, None, 'transparency' )
|
|
transparencyParam.setData( "%.6f" % ( transparency ) )
|
|
|
|
|
|
reflectParam = dae.createParamElement( None, CP.PN.REFLECTIVE, "float3", CP.FT.IN, None, 'reflective' )
|
|
reflectParam.setData( "%.6f %.6f %.6f" % ( refcol[0], refcol[1], refcol[2] ) )
|
|
reflectivityParam = dae.createParamElement( None, CP.PN.REFLECTIVITY, "float", CP.FT.IN, None,'reflectivity' )
|
|
reflectivityParam.setData( "%.6f" % ( ref ) )
|
|
|
|
# refractiveParam = dae.createParamElement( None, CP.PN.REFRACTIVEINDEX, "float3", CP.FT.IN )
|
|
# refractiveParam.setData( "%.6f %.6f %.6f" % ( refID[0], refID[1], refID[2] ) )
|
|
|
|
# TODO: Output SHININESS here. Perhaps calc from
|
|
# Specular HARDNESS and SPECULARITY (?)
|
|
phongProgram.appendChild( colorParam )
|
|
phongProgram.appendChild( diffuseParam )
|
|
phongProgram.appendChild( ambientParam )
|
|
phongProgram.appendChild( transparencyParam )
|
|
phongProgram.appendChild( specularParam )
|
|
phongProgram.appendChild( emissionParam )
|
|
phongProgram.appendChild( shininessParam )
|
|
phongProgram.appendChild( transparentParam )
|
|
phongProgram.appendChild( transparencyParam )
|
|
phongProgram.appendChild( reflectParam )
|
|
phongProgram.appendChild( reflectivityParam )
|
|
# phongProgram.appendChild( refractiveParam )
|
|
passElement.appendChild( phongProgram )
|
|
technique.appendChild( passElement )
|
|
|
|
|
|
shaderElement.appendChild( technique )
|
|
materialElement.appendChild( shaderElement )
|
|
libraryElement.appendChild( materialElement )
|
|
|
|
# --- Write Image information to dae file ---
|
|
def writeImage( libraryElement, image ):
|
|
name = image.getName( )
|
|
id = name + "-Lib"
|
|
imageElement = dae.createImageElement( id, name )
|
|
|
|
# Getting the image size seems to generate
|
|
# python errors sometimes (for some reason)...
|
|
# imageElement.setWidth( image.size[0] )
|
|
# imageElement.setHeight( image.size[1] )
|
|
filename = sys.expandpath( image.getFilename( ) )
|
|
filename = filename.replace( "//", "/" )
|
|
filename = filename.replace( sys.sep, "/" )
|
|
filename = "file://" + filename
|
|
imageElement.setSource( filename )
|
|
libraryElement.appendChild( imageElement )
|
|
|
|
|
|
|
|
def writeTexture( libraryElement, texture ):
|
|
name = texture.getName( )
|
|
id = name + "-Lib"
|
|
|
|
if ( texture.getType() == "Image" ):
|
|
# Create DIFFUSE texture element
|
|
texID = name + "-Lib"
|
|
textureElement = dae.createTextureElement( texID, name )
|
|
|
|
# TODO: Depending on type here create different params and techniques
|
|
textureParamElement = dae.createParamElement( None, CP.PN.DIFFUSE, "float3", CP.FT.OUT )
|
|
textureElement.appendChild( textureParamElement )
|
|
|
|
# Create COMMON Technique
|
|
technique = dae.createTechniqueElement( CP.COMMON )
|
|
textureElement.appendChild( technique )
|
|
|
|
source = texture.getImage( )
|
|
if not ( source == None ):
|
|
sourceName = source.getName( ) + "-Lib"
|
|
input = dae.createInputElement( None, CP.IS.IMAGE, sourceName )
|
|
technique.appendChild( input )
|
|
|
|
libraryElement.appendChild( textureElement )
|
|
else:
|
|
print "Warning! Texture is not of Image type. Texture not exported!"
|
|
|
|
|
|
""" Write animation information to dae file """
|
|
def writeAnimation( libraryElement, ipo, ipoOwner ):
|
|
|
|
global fps
|
|
global exportBakedTransform
|
|
|
|
ipoName = ipo.getName()
|
|
ipoID = ipoName + "-Lib"
|
|
curves = ipo.getCurves( )
|
|
animationElement = dae.createAnimationElement( ipoID, ipoName )
|
|
transformInputElement = None
|
|
transformOutputElement = None
|
|
transformSamplerElement = None
|
|
transformChannelElement = None
|
|
|
|
|
|
# Store information about curves before creating sources
|
|
transformCurves = []
|
|
otherCurves = []
|
|
|
|
transformXMin = 10000
|
|
transformXMax = -10000
|
|
|
|
# Get curve types
|
|
for curve in curves:
|
|
curveName = curve.getName( )
|
|
if ( exportBakedTransform and isTransformCurve( curveName ) ):
|
|
transformCurves.append( curve )
|
|
|
|
# Get control points (keyframes)
|
|
keyFrames = curve.getPoints( )
|
|
nrKeyFrames = len( keyFrames )
|
|
|
|
# Get the min and max values from this curve
|
|
|
|
for keyFrame in keyFrames:
|
|
points = keyFrame.getPoints( )
|
|
if ( points[ 0 ] < transformXMin ):
|
|
transformXMin = int( points[ 0 ] )
|
|
if ( points[ 0 ] > transformXMax ):
|
|
transformXMax = int( points[ 0 ] )
|
|
else:
|
|
otherCurves.append( curve )
|
|
|
|
|
|
# Check for curves...
|
|
nrTransformCurves = len( transformCurves )
|
|
nrOtherCurves = len( otherCurves )
|
|
nrCurves = nrTransformCurves + nrOtherCurves
|
|
if ( nrCurves == 0 ):
|
|
return
|
|
|
|
# Calculate and Write baked transform sources
|
|
if ( exportBakedTransform and ( nrTransformCurves > 0 ) ):
|
|
|
|
animationInput = []
|
|
animationOutput = []
|
|
|
|
sourceID = ipoName + '-Transform-Input'
|
|
transformInputElement = dae.createSourceElement( sourceID, sourceID )
|
|
floatArrayName = sourceID + "-Array"
|
|
nrKeyFrames = ( transformXMax + 1 ) - transformXMin
|
|
floatArrayTime = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
floatArrayTime.setData( animationInput )
|
|
floatArrayTime.setDataType( 'ANIMATIONINPUT-MATRIX' )
|
|
transformInputElement.appendChild( floatArrayTime )
|
|
|
|
# Create common profile technique
|
|
technique = dae.createTechniqueElement( CP.COMMON )
|
|
|
|
# Create accessor element with TIME param
|
|
accessorTime = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
paramTime = dae.createParamElement( None, CP.PN.TIME, "float", CP.FT.OUT )
|
|
|
|
accessorTime.appendChild( paramTime )
|
|
technique.appendChild( accessorTime )
|
|
transformInputElement.appendChild( technique )
|
|
# animationElement.appendChild( sourceElement )
|
|
|
|
|
|
|
|
# Loop through Xmin to XMax
|
|
for frame in range( transformXMin, transformXMax + 1 ):
|
|
time = float( frame )
|
|
animationInput.append( time )
|
|
|
|
translateXYZ = Blender.Mathutils.Vector( )
|
|
rotateXYZ = Blender.Mathutils.Vector( )
|
|
sizeXYZ = Blender.Mathutils.Vector( )
|
|
|
|
# Gather data
|
|
for curve in transformCurves:
|
|
curveName = curve.name
|
|
value = curve[time]
|
|
# print '%s: Time: %i Value: %f' % ( curveName, time, value )
|
|
if ( curveName == 'LocX' ): translateXYZ.x = value
|
|
elif ( curveName == 'LocY' ): translateXYZ.y = value
|
|
elif ( curveName == 'LocZ' ): translateXYZ.z = value
|
|
elif ( curveName == 'RotX' ): rotateXYZ.x = value * 10.0
|
|
elif ( curveName == 'RotY' ): rotateXYZ.y = value * 10.0
|
|
elif ( curveName == 'RotZ' ): rotateXYZ.z = value * 10.0
|
|
elif ( curveName == 'SizeX' ): sizeXYZ.x = value
|
|
elif ( curveName == 'SizeY' ): sizeXYZ.y = value
|
|
elif ( curveName == 'SizeZ' ): sizeXYZ.z = value
|
|
|
|
# Now add these values to our transformMatrix
|
|
transformMatrix = Blender.Mathutils.ScaleMatrix( sizeXYZ.x, 4, Mathutils.Vector( 1.0, 0.0, 0.0 ) )
|
|
transformMatrix *= Blender.Mathutils.ScaleMatrix( sizeXYZ.y, 4, Mathutils.Vector( 0.0, 1.0, 0.0 ) )
|
|
transformMatrix *= Blender.Mathutils.ScaleMatrix( sizeXYZ.z, 4, Mathutils.Vector( 0.0, 0.0, 1.0 ) )
|
|
transformMatrix *= Blender.Mathutils.RotationMatrix( rotateXYZ.x, 4, 'x' )
|
|
transformMatrix *= Blender.Mathutils.RotationMatrix( rotateXYZ.y, 4, 'y' )
|
|
transformMatrix *= Blender.Mathutils.RotationMatrix( rotateXYZ.z, 4, 'z' )
|
|
transformMatrix *= Blender.Mathutils.TranslationMatrix( translateXYZ )
|
|
|
|
# print transformMatrix
|
|
animationOutput.append( transformMatrix )
|
|
|
|
# Write animation output source...
|
|
sourceID2 = ipoName + '-Transform-Output'
|
|
transformOutputElement = dae.createSourceElement( sourceID2, sourceID2 )
|
|
floatArrayName = sourceID2 + "-Array"
|
|
floatArrayOutput = dae.createFloatArrayElement( nrKeyFrames * 16, floatArrayName, floatArrayName )
|
|
floatArrayOutput.setData( animationOutput )
|
|
floatArrayOutput.setDataType( 'ANIMATIONOUTPUT-MATRIX' )
|
|
|
|
transformOutputElement.appendChild( floatArrayOutput )
|
|
|
|
# Create common profile technique
|
|
techniqueOutput = dae.createTechniqueElement( CP.COMMON )
|
|
|
|
# Create accessor element with output param
|
|
accessorOutput = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 16 )
|
|
|
|
# Create float4x4 param element
|
|
paramOutput = dae.createParamElement( None, CP.PN.MATRIX4X4, "float4x4", CP.FT.OUT )
|
|
|
|
|
|
accessorOutput.appendChild( paramOutput )
|
|
techniqueOutput.appendChild( accessorOutput )
|
|
transformOutputElement.appendChild( techniqueOutput )
|
|
# animationElement.appendChild( sourceElement )
|
|
|
|
# Create sampler and channel elements for this baked transform
|
|
|
|
|
|
sourceID = ipoName + '-Transform'
|
|
samplerID = ipoName + '-Transform-Sampler'
|
|
|
|
transformSamplerElement = dae.createSamplerElement( samplerID, samplerID )
|
|
inputInput = dae.createInputElement( None, CP.IS.INPUT, sourceID + '-Input' )
|
|
inputOutput = dae.createInputElement( None, CP.IS.OUTPUT, sourceID + '-Output' )
|
|
transformSamplerElement.appendChild( inputInput )
|
|
transformSamplerElement.appendChild( inputOutput )
|
|
#animationElement.appendChild( samplerElement )
|
|
|
|
|
|
# Create channel element
|
|
channelID = ipoName + '-Transform-Channel'
|
|
|
|
|
|
target = ipoOwner + '/transform'
|
|
transformChannelElement = dae.createChannelElement( channelID, channelID, samplerID, target )
|
|
|
|
# Add transform sources first
|
|
animationElement.appendChild( transformInputElement )
|
|
animationElement.appendChild( transformOutputElement )
|
|
|
|
|
|
## # Else if transform is not baked:
|
|
## else:
|
|
## for curve in transformCurves:
|
|
##
|
|
## curveName = curve.getName( )
|
|
## keyFrames = curve.getPoints( )
|
|
## nrKeyFrames = len( keyFrames )
|
|
##
|
|
## # Create input source element
|
|
## # TODO: If keyframe-input are same (same position-points) then perhaps create one input source?
|
|
## sourceID = ipoName + "-" + curveName + "-Input"
|
|
## sourceElement = dae.createSourceElement( sourceID, sourceID )
|
|
## floatArrayName = sourceID + "-Array"
|
|
## floatArrayTime = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
## floatArrayTime.setData( keyFrames )
|
|
## floatArrayTime.setDataType( 'ANIMATIONINPUT' )
|
|
## sourceElement.appendChild( floatArrayTime )
|
|
##
|
|
## # Create common profile technique
|
|
## technique = dae.createTechniqueElement( CP.COMMON )
|
|
##
|
|
## # Create accessor element with TIME param
|
|
## accessorTime = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
## paramTime = dae.createParamElement( None, CP.PN.TIME, "float", CP.FT.OUT )
|
|
##
|
|
## accessorTime.appendChild( paramTime )
|
|
## technique.appendChild( accessorTime )
|
|
## sourceElement.appendChild( technique )
|
|
## animationElement.appendChild( sourceElement )
|
|
##
|
|
##
|
|
## # Create output source element
|
|
## sourceID2 = ipoName + "-" + curveName + "-Output"
|
|
## sourceElement = dae.createSourceElement( sourceID2, sourceID2 )
|
|
## floatArrayName = sourceID2 + "-Array"
|
|
## floatArrayOutput = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
## floatArrayOutput.setData( keyFrames )
|
|
## if ( curveName == 'Hard' ):
|
|
## floatArrayOutput.setDataType( 'ANIMATIONOUTPUT-SHININESS' )
|
|
## else:
|
|
## floatArrayOutput.setDataType( 'ANIMATIONOUTPUT' )
|
|
##
|
|
## sourceElement.appendChild( floatArrayOutput )
|
|
##
|
|
## # Create common profile technique
|
|
## techniqueOutput = dae.createTechniqueElement( CP.COMMON )
|
|
##
|
|
## # Create accessor element with output param
|
|
## accessorOutput = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
##
|
|
## # Create different params depending on curve name (this should be driven channel for objects but
|
|
## # for now let's use the curve name because that seems to work)
|
|
## paramOutput = getParamElementFromCurveName( curveName )
|
|
##
|
|
##
|
|
## accessorOutput.appendChild( paramOutput )
|
|
## techniqueOutput.appendChild( accessorOutput )
|
|
## sourceElement.appendChild( techniqueOutput )
|
|
## animationElement.appendChild( sourceElement )
|
|
|
|
|
|
|
|
# Now that we have written transform channels write every other channel
|
|
# TODO: Combine channels if possible (for example RGB sources -> material diffuse channel)
|
|
for curve in otherCurves:
|
|
curveName = curve.getName( )
|
|
keyFrames = curve.getPoints( )
|
|
nrKeyFrames = len( keyFrames )
|
|
|
|
# Create input source element
|
|
# TODO: If keyframe-input are same (same position-points) then perhaps create one input source?
|
|
sourceID = ipoName + "-" + curveName + "-Input"
|
|
sourceElement = dae.createSourceElement( sourceID, sourceID )
|
|
floatArrayName = sourceID + "-Array"
|
|
floatArrayTime = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
floatArrayTime.setData( keyFrames )
|
|
floatArrayTime.setDataType( 'ANIMATIONINPUT' )
|
|
sourceElement.appendChild( floatArrayTime )
|
|
|
|
# Create common profile technique
|
|
technique = dae.createTechniqueElement( CP.COMMON )
|
|
|
|
# Create accessor element with TIME param
|
|
accessorTime = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
paramTime = dae.createParamElement( None, CP.PN.TIME, "float", CP.FT.OUT )
|
|
|
|
accessorTime.appendChild( paramTime )
|
|
technique.appendChild( accessorTime )
|
|
sourceElement.appendChild( technique )
|
|
animationElement.appendChild( sourceElement )
|
|
|
|
|
|
# Create output source element
|
|
sourceID2 = ipoName + "-" + curveName + "-Output"
|
|
sourceElement = dae.createSourceElement( sourceID2, sourceID2 )
|
|
floatArrayName = sourceID2 + "-Array"
|
|
floatArrayOutput = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
floatArrayOutput.setData( keyFrames )
|
|
if ( curveName == 'Hard' ):
|
|
floatArrayOutput.setDataType( 'ANIMATIONOUTPUT-SHININESS' )
|
|
elif ( curveName == 'Alpha' ):
|
|
floatArrayOutput.setDataType( 'ANIMATIONOUTPUT-ALPHA' )
|
|
elif ( isRotationCurve( curveName ) ):
|
|
floatArrayOutput.setDataType( 'ANIMATIONOUTPUT-ROTATION' )
|
|
else:
|
|
floatArrayOutput.setDataType( 'ANIMATIONOUTPUT' )
|
|
sourceElement.appendChild( floatArrayOutput )
|
|
|
|
# Create common profile technique
|
|
techniqueOutput = dae.createTechniqueElement( CP.COMMON )
|
|
|
|
# Create accessor element with output param
|
|
accessorOutput = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
|
|
# Create different params depending on curve name (this should be driven channel for objects but
|
|
# for now let's use the curve name because that seems to work)
|
|
paramOutput = getParamElementFromCurveName( curveName )
|
|
|
|
|
|
accessorOutput.appendChild( paramOutput )
|
|
techniqueOutput.appendChild( accessorOutput )
|
|
sourceElement.appendChild( techniqueOutput )
|
|
animationElement.appendChild( sourceElement )
|
|
|
|
|
|
|
|
# Add transform sampler element first
|
|
if ( transformSamplerElement != None ):
|
|
animationElement.appendChild( transformSamplerElement )
|
|
|
|
# Add other samples
|
|
for curve in otherCurves:
|
|
|
|
curveName = curve.getName( )
|
|
sourceID = ipoName + "-" + curveName
|
|
|
|
# Create sampler element
|
|
samplerID = ipoName + "-" + curveName + '-Sampler'
|
|
samplerElement = dae.createSamplerElement( samplerID, samplerID )
|
|
|
|
# Create input semantics
|
|
inputInput = dae.createInputElement( None, CP.IS.INPUT, sourceID + '-Input' )
|
|
inputOutput = dae.createInputElement( None, CP.IS.OUTPUT, sourceID + '-Output' )
|
|
|
|
samplerElement.appendChild( inputInput )
|
|
samplerElement.appendChild( inputOutput )
|
|
animationElement.appendChild( samplerElement )
|
|
|
|
|
|
# Add transform channel element first
|
|
if ( transformChannelElement != None ):
|
|
animationElement.appendChild( transformChannelElement )
|
|
|
|
# TODO: Write other channels here
|
|
for curve in otherCurves:
|
|
|
|
curveName = curve.getName( )
|
|
sourceID = ipoName + "-" + curveName + '-Sampler'
|
|
|
|
# Create channel element
|
|
channelID = ipoName + "-" + curveName + '-Channel'
|
|
|
|
# Get IPO Curve driver object
|
|
# Important! If this is a animation channel that is not targetet against
|
|
# a transform then target lib instead (add '-Lib' to target id)
|
|
if ( not isTransformCurve( curveName ) ):
|
|
target = ipoOwner + '-Lib/' + getTargetNameFromCurveName( curveName )
|
|
else:
|
|
target = ipoOwner + '/' + getTargetNameFromCurveName( curveName )
|
|
|
|
|
|
channelElement = dae.createChannelElement( channelID, channelID, sourceID, target )
|
|
animationElement.appendChild( channelElement )
|
|
|
|
libraryElement.appendChild( animationElement )
|
|
|
|
# Write transform animation first
|
|
## if ( exportBakedTransform ):
|
|
##
|
|
## transformXMin = 1000.0
|
|
## transformXMax = -1000.0
|
|
##
|
|
## # Store which IPO curves that are transform based
|
|
## transformCurves = []
|
|
##
|
|
## # Create sources for each curve
|
|
## for curve in curves:
|
|
##
|
|
## # Get information about our Ipo curve
|
|
## curveName = curve.getName( )
|
|
##
|
|
## # Get control points (keyframes)
|
|
## keyFrames = curve.getPoints( )
|
|
## nrKeyFrames = len( keyFrames )
|
|
##
|
|
## # Get the min and max values from this curve
|
|
## if ( exportBakedTransform ):
|
|
## if ( isTransformCurve( curveName ) ):
|
|
## for keyFrame in keyFrames:
|
|
## points = keyFrame.getPoints( )
|
|
## if ( points[ 0 ] < transformXMin ):
|
|
## transformXMin = points[ 0 ]
|
|
## if ( points[ 0 ] > transformXMax ):
|
|
## transformXMax = points[ 0 ]
|
|
## print curveName + ' has Xmin[%f] and Xmax[%f]' % ( transformXMin, transformXMax )
|
|
## else:
|
|
## # Create input source element
|
|
## # TODO: If keyframe-input are same (same position-points) then perhaps create one input source?
|
|
## sourceID = ipoName + "-" + curveName + "-Input"
|
|
## sourceElement = dae.createSourceElement( sourceID, sourceID )
|
|
## floatArrayName = sourceID + "-Array"
|
|
## floatArrayTime = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
## floatArrayTime.setData( keyFrames )
|
|
## floatArrayTime.setDataType( 'ANIMATIONINPUT' )
|
|
## sourceElement.appendChild( floatArrayTime )
|
|
##
|
|
## # Create common profile technique
|
|
## technique = dae.createTechniqueElement( CP.COMMON )
|
|
##
|
|
## # Create accessor element with TIME param
|
|
## accessorTime = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
## paramTime = dae.createParamElement( None, CP.PN.TIME, "float", CP.FT.OUT )
|
|
##
|
|
## accessorTime.appendChild( paramTime )
|
|
## technique.appendChild( accessorTime )
|
|
## sourceElement.appendChild( technique )
|
|
## animationElement.appendChild( sourceElement )
|
|
##
|
|
##
|
|
## # Create output source element
|
|
## sourceID2 = ipoName + "-" + curveName + "-Output"
|
|
## sourceElement = dae.createSourceElement( sourceID2, sourceID2 )
|
|
## floatArrayName = sourceID2 + "-Array"
|
|
## floatArrayOutput = dae.createFloatArrayElement( nrKeyFrames, floatArrayName, floatArrayName )
|
|
## floatArrayOutput.setData( keyFrames )
|
|
## floatArrayOutput.setDataType( 'ANIMATIONOUTPUT' )
|
|
##
|
|
## sourceElement.appendChild( floatArrayOutput )
|
|
##
|
|
## # Create common profile technique
|
|
## techniqueOutput = dae.createTechniqueElement( CP.COMMON )
|
|
##
|
|
## # Create accessor element with output param
|
|
## accessorOutput = dae.createAccessorElement( nrKeyFrames, floatArrayName, floatArrayName + "-Accessor", 0 , 1 )
|
|
##
|
|
## # Create different params depending on curve name (this should be driven channel for objects but
|
|
## # for now let's use the curve name because that seems to work)
|
|
## paramOutput = getParamElementFromCurveName( curveName )
|
|
##
|
|
##
|
|
## accessorOutput.appendChild( paramOutput )
|
|
## techniqueOutput.appendChild( accessorOutput )
|
|
## sourceElement.appendChild( techniqueOutput )
|
|
## animationElement.appendChild( sourceElement )
|
|
##
|
|
##
|
|
## # If baking animation:
|
|
## # Loop through
|
|
## # if ( exportBakedTransform ):
|
|
##
|
|
##
|
|
##
|
|
##
|
|
## # Create sampler element
|
|
## for curve in curves:
|
|
##
|
|
## curveName = curve.getName( )
|
|
##
|
|
## sourceID = ipoName + "-" + curveName
|
|
##
|
|
## # Create sampler element
|
|
## samplerID = ipoName + "-" + curveName + '-Sampler'
|
|
## samplerElement = dae.createSamplerElement( samplerID, samplerID )
|
|
##
|
|
## # Create input semantics
|
|
## inputInput = dae.createInputElement( None, CP.IS.INPUT, sourceID + '-Input' )
|
|
## inputOutput = dae.createInputElement( None, CP.IS.OUTPUT, sourceID + '-Output' )
|
|
##
|
|
## samplerElement.appendChild( inputInput )
|
|
## samplerElement.appendChild( inputOutput )
|
|
## animationElement.appendChild( samplerElement )
|
|
##
|
|
##
|
|
## # Create channel element
|
|
## for curve in curves:
|
|
##
|
|
## curveName = curve.getName( )
|
|
##
|
|
## sourceID = ipoName + "-" + curveName + '-Sampler'
|
|
##
|
|
## # Create channel element
|
|
## channelID = ipoName + "-" + curveName + '-Channel'
|
|
##
|
|
## # Get IPO Curve driver object
|
|
## target = ipoOwner + '/' + getTargetNameFromCurveName( curveName )
|
|
## channelElement = dae.createChannelElement( channelID, channelID, sourceID, target )
|
|
##
|
|
## animationElement.appendChild( channelElement )
|
|
##
|
|
##
|
|
## libraryElement.appendChild( animationElement )
|
|
|
|
|
|
# Write camera information to dae file
|
|
def writeCamera( libraryElement, camera ):
|
|
|
|
cameraName = camera.getName()
|
|
cameraID = cameraName + "-Lib"
|
|
cameraType = camera.getType()
|
|
cameraElement = dae.createCameraElement( cameraID, cameraName )
|
|
technique = dae.createTechniqueElement( CP.COMMON )
|
|
optics = dae.createOpticsElement( )
|
|
|
|
# Create PERSPECTIVE camera or ORTHO camera
|
|
program = None
|
|
|
|
# PERSPECTIVE Camera
|
|
# print cameraType
|
|
if ( cameraType == 0 ):
|
|
program = dae.createProgramElement( None, None, CP.PIAU.str[ CP.PIAU.PERSPECTIVE ] )
|
|
paramYFOV = dae.createParamElement( None, CP.PN.YFOV, "float", CP.FT.IN, None, None )
|
|
#paramXFOV = dae.createParamElement( None, CP.PN.XFOV, "float", CP.FT.IN, None, None )
|
|
|
|
# Calculate Y-FOV based on LENS value
|
|
lens = camera.getLens( )
|
|
yfov = 2 * ( math.atan( 16.0 / lens ) ) * ( 180.0 / 3.1415926 )
|
|
|
|
paramYFOV.setData( "%.6f" % yfov )
|
|
program.appendChild( paramYFOV )
|
|
|
|
#paramXFOV.setData( "%.6f" % xfov )
|
|
#program.appendChild( paramXFOV )
|
|
|
|
else:
|
|
print "Warning! Orthographic cameras not supported. Camera not exported! "
|
|
return
|
|
#program = dae.createProgramElement( None, CP.PIAU.str[ CP.PIAU.ORTHOGRAPHIC ], None )
|
|
|
|
paramZNear = dae.createParamElement( None, CP.PN.ZNEAR, "float", CP.FT.IN, None, None )
|
|
paramZFar = dae.createParamElement( None, CP.PN.ZFAR, "float", CP.FT.IN, None, None )
|
|
znear = camera.getClipStart( )
|
|
zfar = camera.getClipEnd( )
|
|
paramZNear.setData( "%.6f" % znear )
|
|
paramZFar.setData( "%.6f" % zfar )
|
|
program.appendChild( paramZNear )
|
|
program.appendChild( paramZFar )
|
|
optics.appendChild( program )
|
|
technique.appendChild( optics )
|
|
cameraElement.appendChild( technique )
|
|
libraryElement.appendChild( cameraElement )
|
|
|
|
|
|
|
|
|
|
# --- Write header information to dae file ---
|
|
def writeHeader( colladaElement ):
|
|
|
|
# Write asset information
|
|
asset = dae.createAssetElement( )
|
|
|
|
author = dae.createAuthorElement( __author__ )
|
|
authoringtooldata = "Blender " + "%i" % Blender.Get( 'version' ) + " COLLADA Exporter"
|
|
authoringtool = dae.createAuthoringToolElement( authoringtooldata )
|
|
|
|
# Can I change this in Blender?
|
|
upaxisdata = "Z_UP"
|
|
upaxis = dae.createUpAxisElement( upaxisdata )
|
|
|
|
# createddata = date( 2005, 12, 21)
|
|
# created = dae.createCreatedElement( createddata )
|
|
|
|
# Create a unit element (mostly for Maya import to work better )
|
|
unit = dae.createUnitElement( 'centimeter', '%s' % 0.01 )
|
|
|
|
|
|
asset.appendChild( author )
|
|
asset.appendChild( authoringtool )
|
|
asset.appendChild( upaxis )
|
|
asset.appendChild( unit )
|
|
colladaElement.appendChild( asset )
|
|
|
|
# --- Write libraries to dae file ---
|
|
def writeLibrary( colladaElement ):
|
|
|
|
|
|
imageLibraryElement = dae.createLibraryElement( CP.LT.IMAGE )
|
|
textureLibraryElement = dae.createLibraryElement( CP.LT.TEXTURE )
|
|
materialLibraryElement = dae.createLibraryElement( CP.LT.MATERIAL )
|
|
geometryLibraryElement = dae.createLibraryElement( CP.LT.GEOMETRY )
|
|
animationLibraryElement = dae.createLibraryElement( CP.LT.ANIMATION )
|
|
lightLibraryElement = dae.createLibraryElement( CP.LT.LIGHT )
|
|
cameraLibraryElement = dae.createLibraryElement( CP.LT.CAMERA )
|
|
|
|
meshes = dict()
|
|
lights = dict()
|
|
cameras = dict()
|
|
ipos = dict()
|
|
|
|
for obj in objects:
|
|
objType = obj.getType( )
|
|
dataName = obj.getData( True )
|
|
data = obj.getData( False )
|
|
ipo = obj.getIpo( )
|
|
objName = obj.name
|
|
if ( ipo != None ):
|
|
ipos[ objName ] = ipo
|
|
if ( objType == 'Mesh' ):
|
|
meshes[ dataName ] = NMesh.GetRaw( dataName )
|
|
elif ( objType == 'Lamp' ):
|
|
lights[ dataName ] = data
|
|
elif ( objType == 'Camera' ):
|
|
cameras[ dataName ] = data
|
|
|
|
|
|
|
|
# Get raw meshes
|
|
materials = dict()
|
|
nrMeshes = len( meshes )
|
|
if ( nrMeshes > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrMeshes
|
|
Window.DrawProgressBar( 0.0, "Writing mesh data..." )
|
|
for key in meshes:
|
|
rawMesh = meshes[ key ]
|
|
if ( rawMesh.users > 0 ):
|
|
writeMesh( geometryLibraryElement, rawMesh )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting geometry %.0f %%..." % ( progress * 100.0 ) )
|
|
meshMaterials = rawMesh.getMaterials( -1 )
|
|
for material in meshMaterials:
|
|
if material==None:
|
|
continue
|
|
|
|
key = material.getName( )
|
|
materials[ key ] = material
|
|
|
|
# Ipo on material?
|
|
ipo = material.getIpo( )
|
|
if ( ipo != None ):
|
|
ipos[ key ] = ipo
|
|
|
|
|
|
# Get materials
|
|
textures = dict()
|
|
nrMaterials = len( materials )
|
|
if ( nrMaterials > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrMaterials
|
|
for key in materials:
|
|
material = materials[ key ]
|
|
writeMaterial( materialLibraryElement, material )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting materials %.0f %%..." % ( progress * 100.0 ) )
|
|
materialTextures = material.getTextures( )
|
|
for texture in materialTextures:
|
|
if not ( texture == None ):
|
|
if ( texture.tex.type == Texture.Types.IMAGE ):
|
|
key = texture.tex.getName( )
|
|
textures[ key ] = texture.tex
|
|
|
|
# Ipo on texture?
|
|
ipo = texture.tex.getIpo( )
|
|
if ( ipo != None ):
|
|
ipos[ key ] = ipo
|
|
|
|
|
|
# Write textures
|
|
images = dict()
|
|
nrTextures = len( textures )
|
|
if ( nrTextures > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrTextures
|
|
for key in textures:
|
|
texture = textures[ key ]
|
|
writeTexture( textureLibraryElement, texture )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting textures %.0f %%..." % ( progress * 100.0 ) )
|
|
image = texture.getImage( )
|
|
if ( image != None ):
|
|
imageName = image.getName( )
|
|
images[ imageName ] = image
|
|
|
|
|
|
|
|
# Write images
|
|
nrImages = len( images )
|
|
if ( nrImages > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrImages
|
|
for key in images:
|
|
image = images[ key ]
|
|
writeImage( imageLibraryElement, image )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting images %.0f %%..." % ( progress * 100.0 ) )
|
|
|
|
|
|
# Write lights
|
|
nrLights = len( lights )
|
|
if ( nrLights > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrLights
|
|
for key in lights:
|
|
light = lights[ key ]
|
|
writeLight( lightLibraryElement, light )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting lights %.0f %%..." % ( progress * 100.0 ) )
|
|
|
|
# Write cameras
|
|
nrCameras = len( cameras )
|
|
if ( nrCameras > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrCameras
|
|
for key in cameras:
|
|
camera = cameras[ key ]
|
|
writeCamera( cameraLibraryElement, camera )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting cameras %.0f %%..." % ( progress * 100.0 ) )
|
|
|
|
|
|
# Write animations
|
|
nrAnimations = len( ipos )
|
|
if ( nrAnimations > 0 ):
|
|
progress = 0.0
|
|
addProgress = 1.0 / nrAnimations
|
|
for key in ipos:
|
|
ipo = ipos[ key ]
|
|
writeAnimation( animationLibraryElement, ipo, key )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting animation %.0f %%..." % ( progress * 100.0 ) )
|
|
|
|
# Write library element. Put animation first...
|
|
|
|
|
|
colladaElement.appendChild( imageLibraryElement )
|
|
colladaElement.appendChild( textureLibraryElement )
|
|
colladaElement.appendChild( materialLibraryElement )
|
|
colladaElement.appendChild( geometryLibraryElement )
|
|
colladaElement.appendChild( lightLibraryElement )
|
|
colladaElement.appendChild( cameraLibraryElement )
|
|
colladaElement.appendChild( animationLibraryElement )
|
|
|
|
# --- Write node to dae ---
|
|
def writeNode( object, parentNode ):
|
|
|
|
global exportBakedTransform
|
|
|
|
newNodeName = object.name
|
|
# newNodeName = object.name + "-Node"
|
|
newNode = dae.createNodeElement( newNodeName, newNodeName, CP.NT.NODE )
|
|
|
|
#print "Creating %s" % newNodeName
|
|
|
|
# Create data for this node here
|
|
url = object.getData( True )
|
|
if not ( url == None ):
|
|
url += "-Lib"
|
|
instance = dae.createInstanceElement( url )
|
|
newNode.appendChild( instance )
|
|
|
|
|
|
# No need to check for IPO connection here simply output sid values anyway.
|
|
# sid values are according to target values in library and these
|
|
# names follows the naming convention that the Maya exporter use
|
|
|
|
#sidTranslate = newNodeName + "-Translate"
|
|
#sidRotateX = newNodeName + "-Rotate-X"
|
|
if ( exportBakedTransform ):
|
|
matrixElement = dae.createMatrixElement( 'transform' )
|
|
matrix = object.getMatrix( 'localspace' )
|
|
data = ""
|
|
matrix.transpose()
|
|
if ( niceFormat ):
|
|
for i in range( 4 ):
|
|
data += "\n%.6f %.6f %.6f %.6f" % ( matrix[ i ].x, matrix[ i ].y,
|
|
matrix[ i ].z, matrix[ i ].w )
|
|
else:
|
|
data += "%.6f %.6f %.6f %.6f " % ( matrix[ 0 ].x, matrix[ 0 ].y,
|
|
matrix[ 0 ].z, matrix[ 0 ].w )
|
|
data += "%.6f %.6f %.6f %.6f " % ( matrix[ 1 ].x, matrix[ 1 ].y,
|
|
matrix[ 1 ].z, matrix[ 1 ].w )
|
|
data += "%.6f %.6f %.6f %.6f " % ( matrix[ 2 ].x, matrix[ 2 ].y,
|
|
matrix[ 2 ].z, matrix[ 2 ].w )
|
|
data += "%.6f %.6f %.6f %.6f" % ( matrix[ 3 ].x, matrix[ 3 ].y,
|
|
matrix[ 3 ].z, matrix[ 3 ].w )
|
|
|
|
|
|
matrixElement.setData( data )
|
|
newNode.appendChild( matrixElement )
|
|
else:
|
|
translate = dae.createTranslateElement( 'translate' )
|
|
rotateX = dae.createRotateElement( 'rotateX' )
|
|
rotateY = dae.createRotateElement( 'rotateY' )
|
|
rotateZ = dae.createRotateElement( 'rotateZ' )
|
|
scale = dae.createScaleElement( 'scale' )
|
|
location = object.getLocation()
|
|
rotation = object.getEuler()
|
|
size = object.getSize()
|
|
data = "%.6f %.6f %.6f" % ( location[ 0 ], location[ 1 ], location[ 2 ] )
|
|
dataX = "1 0 0 %.6f" % ( toAngle( rotation[ 0 ] ) )
|
|
dataY = "0 1 0 %.6f" % ( toAngle( rotation[ 1 ] ) )
|
|
dataZ = "0 0 1 %.6f" % ( toAngle( rotation[ 2 ] ) )
|
|
dataScale = "%.6f %.6f %.6f" % ( size[ 0 ], size[ 1 ], size[ 2 ] )
|
|
translate.setData( data )
|
|
rotateX.setData( dataX )
|
|
rotateY.setData( dataY )
|
|
rotateZ.setData( dataZ )
|
|
scale.setData( dataScale )
|
|
newNode.appendChild( translate )
|
|
newNode.appendChild( rotateX )
|
|
newNode.appendChild( rotateY )
|
|
newNode.appendChild( rotateZ )
|
|
newNode.appendChild( scale )
|
|
|
|
# Check if anyone has Me as Parent
|
|
returnNode = None
|
|
for child in objects:
|
|
parent = child.getParent()
|
|
if ( object == parent ):
|
|
returnNode = writeNode( child, newNode )
|
|
if not ( returnNode == None ):
|
|
newNode.appendChild( returnNode )
|
|
|
|
parentNode.appendChild( newNode )
|
|
|
|
return newNode
|
|
|
|
# --- Write scene to dae file ---
|
|
def writeScene( colladaElement ):
|
|
|
|
# Write <scene> element
|
|
currentScene = Scene.GetCurrent( )
|
|
sceneName = currentScene.getName( )
|
|
sceneElement = dae.createSceneElement( sceneName, sceneName )
|
|
colladaElement.appendChild( sceneElement )
|
|
|
|
|
|
# Write nodes
|
|
if not ( objects == None ):
|
|
nrObjects = len( objects )
|
|
if ( nrObjects > 0 ):
|
|
addProgress = 1.0 / nrObjects
|
|
progress = 0.0
|
|
Window.DrawProgressBar( 0.0, "Exporting Scene 0.0% ..." )
|
|
for object in objects:
|
|
if ( object.getParent() == None ):
|
|
writeNode( object, sceneElement )
|
|
progress += addProgress
|
|
Window.DrawProgressBar( progress, "Exporting Scene %.0f%% ..." % ( progress * 100.0 ) )
|
|
Window.DrawProgressBar( 1.0, "Finished!" )
|
|
|
|
# print objects
|
|
|
|
# ----------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ----------------------------------------------
|
|
# HELPER FUNCTIONS
|
|
# ----------------------------------------------
|
|
|
|
# --- Set id and name tag to element ---
|
|
#def setIdAndName( element, string ):
|
|
|
|
# element.setAttribute( "id", string )
|
|
# element.setAttribute( "name", string )
|
|
|
|
# return
|
|
|
|
# --- Create COMMON Technique element ---
|
|
#def createCommonTechnique( ):
|
|
# technique = dae.createElement( "technique" )
|
|
# technique.setAttribute( "profile", "COMMON" )
|
|
#
|
|
# return technique
|
|
|
|
# --- Create Param element ---
|
|
#def createParamElement( name, type ):
|
|
# param = dae.createElement( "param" )
|
|
# param.setAttribute( "name", name )
|
|
# param.setAttribute( "type", type )
|
|
#
|
|
# return param
|
|
|
|
|
|
|
|
# ----------------------------------------------
|
|
# --- MAIN ---
|
|
def main( filePath ):
|
|
global dae
|
|
global objects
|
|
global exportSelected
|
|
global fps
|
|
|
|
if not ( filePath == None ):
|
|
|
|
print "Exporting: " + filePath + "..."
|
|
|
|
startTime = sys.time()
|
|
|
|
dae = COLLADADocument()
|
|
dae.openFile( filePath )
|
|
|
|
# Build node tree here
|
|
collada = dae.createCOLLADAElement( )
|
|
dae.appendChild( collada )
|
|
|
|
if ( exportSelected == True ):
|
|
objects = Object.GetSelected( )
|
|
# print "Selected objects only!"
|
|
else:
|
|
objects = Object.Get( )
|
|
|
|
# Write header information
|
|
writeHeader( collada )
|
|
|
|
# Set fps
|
|
scn = Scene.GetCurrent( )
|
|
context = scn.getRenderingContext( )
|
|
fps = context.framesPerSec( )
|
|
|
|
#Write library information
|
|
writeLibrary( collada )
|
|
|
|
# Write scene information
|
|
writeScene( collada )
|
|
|
|
dae.buildXML( )
|
|
dae.cleanUp( )
|
|
|
|
|
|
# Get scene objects
|
|
# objects = Object.Get()
|
|
|
|
endTime = sys.time()
|
|
|
|
exportTime = endTime - startTime
|
|
print "Export time: %.6f" % (exportTime )
|
|
#print "</COLLADA Exporter v0.1>"
|
|
|
|
# Window.DrawProgressBar( 1.0, "" )
|
|
|
|
|
|
def callback_fileselector( filename ):
|
|
if ( sys.exists( filename ) == 1 ):
|
|
overwrite = Draw.PupMenu( "File Already Exists, Overwrite?%t|Yes%x1|No%x0" )
|
|
if ( overwrite == 1 ):
|
|
main( filename )
|
|
else:
|
|
main( filename )
|
|
|
|
|
|
def ExportGUI( ):
|
|
global exportSelected, exportBakedTransform
|
|
|
|
# Window.DrawProgressBar( 0.0, ">>> COLLADA-" )
|
|
|
|
# print "<COLLADA Exporter v0.1>"
|
|
|
|
# Export selected or all
|
|
progressString = "COLLADA-"
|
|
answer = Draw.PupMenu( "Export what?%t|All%x1|Selected only%x0" )
|
|
if ( answer == 1 ):
|
|
exportSelected = False
|
|
progressString += "All-"
|
|
elif ( answer == 0 ):
|
|
exportSelected = True
|
|
progressString +="Selected-"
|
|
else:
|
|
# print "</COLLADA Exporter v0.1>"
|
|
# Window.DrawProgressBar( 1.0, "" )
|
|
return
|
|
|
|
# Window.DrawProgressBar( 0.0, progressString )
|
|
answer2 = Draw.PupMenu( "Export as matrix element?%t|Yes%x1|No%x0" )
|
|
if ( answer2 == 1 ):
|
|
exportBakedTransform = True
|
|
progressString +="Matrix"
|
|
elif ( answer2 == 0 ):
|
|
exportBakedTransform = False
|
|
progressString +="Transform"
|
|
else:
|
|
# print "</COLLADA Exporter v0.1>"
|
|
# Window.DrawProgressBar( 1.0, "" )
|
|
return
|
|
|
|
# Window.DrawProgressBar( 0.0, progressString )
|
|
|
|
print "Export options: " + progressString
|
|
|
|
defaultFileName = Blender.Get('filename') + ".dae"
|
|
defaultFileName = defaultFileName.replace( '.blend', '' )
|
|
Window.FileSelector( callback_fileselector, 'Export .dae', defaultFileName )
|
|
|
|
|
|
|
|
|
|
# Run the script
|
|
if not ( _ERROR == True ):
|
|
ExportGUI()
|
|
|
|
#main( 'C:\\ColladaBlender\\test.xml' )
|