1 /*
2     Copyright (c) 2008-2009 NetAllied Systems GmbH
3 
4     This file is part of COLLADASaxFrameworkLoader.
5 
6     Licensed under the MIT Open Source License,
7     for details please see LICENSE file or the website
8     http://www.opensource.org/licenses/mit-license.php
9 */
10 
11 #include "COLLADASaxFWLStableHeaders.h"
12 #include "COLLADASaxFWLSourceArrayLoader.h"
13 #include "COLLADAFWTypes.h"
14 
15 namespace COLLADASaxFWL
16 {
17 
18 #ifdef COLLADASAXFWL_REAL_IS_FLOAT
19 	const COLLADAFW::FloatOrDoubleArray::DataType SourceArrayLoader::DATA_TYPE_REAL = COLLADAFW::FloatOrDoubleArray::DATA_TYPE_FLOAT;
20 #else
21 	const COLLADAFW::FloatOrDoubleArray::DataType SourceArrayLoader::DATA_TYPE_REAL = COLLADAFW::FloatOrDoubleArray::DATA_TYPE_DOUBLE;
22 #endif
23 
24 
25 	//------------------------------
SourceArrayLoader(IFilePartLoader * callingFilePartLoader)26 	SourceArrayLoader::SourceArrayLoader(IFilePartLoader* callingFilePartLoader)
27 		:FilePartLoader(callingFilePartLoader),
28 		 mSourceArray( SourceArray::OWNER ),
29 		 mCurrentSoure(0)
30 	{
31 	}
32 
33 	//------------------------------
~SourceArrayLoader()34 	SourceArrayLoader::~SourceArrayLoader()
35 	{
36 		clearSources();
37 	}
38 
39 	/** Copies the values contained in @a realSource into @a realsArray .*/
40 	//------------------------------
setRealValues(COLLADAFW::FloatOrDoubleArray & realsArray,const RealSource * realSource)41 	void SourceArrayLoader::setRealValues( COLLADAFW::FloatOrDoubleArray& realsArray, const RealSource* realSource )
42 	{
43 		if ( !realsArray.empty() )
44 		{
45 			// There already must have been an input with semantic INPUT. We ignore all following.
46 			return;
47 		}
48 		realsArray.setType( SourceArrayLoader::DATA_TYPE_REAL );
49 		const RealArrayElement& realArrayElement = realSource->getArrayElement();
50 		realsArray.appendValues(realArrayElement.getValues());
51 	}
52 
53 
54 	//------------------------------
clearSources()55 	void SourceArrayLoader::clearSources()
56 	{
57 		for ( size_t i = 0, count = mSourceArray.getCount(); i < count; ++i)
58 			delete mSourceArray[i];
59 		mSourceArray.setCount(0);
60 	}
61 
62 	//------------------------------
assignSourceValuesToFloatOrDoubleArray(SourceBase * sourceBase,COLLADAFW::FloatOrDoubleArray & floatOrDoubleArray)63 	bool SourceArrayLoader::assignSourceValuesToFloatOrDoubleArray( SourceBase* sourceBase, COLLADAFW::FloatOrDoubleArray& floatOrDoubleArray )
64 	{
65 		if (sourceBase->getDataType() == SourceBase::DATA_TYPE_FLOAT)
66 		{
67 			floatOrDoubleArray.setType( COLLADAFW::FloatOrDoubleArray::DATA_TYPE_FLOAT);
68 			COLLADAFW::FloatArray* values = floatOrDoubleArray.getFloatValues();
69 			FloatSource* source = ( FloatSource* ) sourceBase;
70 			FloatArrayElement& arrayElement = source->getArrayElement();
71 			COLLADAFW::FloatArray& valuesArray = arrayElement.getValues();
72 			values->setData ( valuesArray.getData (), valuesArray.getCount () );
73 			valuesArray.yieldOwnerShip();
74 			return true;
75 		}
76 		else if (sourceBase->getDataType() == SourceBase::DATA_TYPE_DOUBLE)
77 		{
78 			floatOrDoubleArray.setType( COLLADAFW::FloatOrDoubleArray::DATA_TYPE_DOUBLE);
79 			COLLADAFW::DoubleArray* values = floatOrDoubleArray.getDoubleValues();
80 			DoubleSource* source = ( DoubleSource* ) sourceBase;
81 			DoubleArrayElement& arrayElement = source->getArrayElement();
82 			COLLADAFW::DoubleArray& valuesArray = arrayElement.getValues();
83 			values->setData ( valuesArray.getData (), valuesArray.getCount () );
84 			valuesArray.yieldOwnerShip();
85 			return true;
86 		}
87 		else
88 		{
89 			return false;
90 		}
91 	}
92 
93 	//------------------------------
getIdFromURIFragmentType(const char * uriFragment)94 	COLLADAFW::String SourceArrayLoader::getIdFromURIFragmentType( const char* uriFragment )
95 	{
96 		if ( !uriFragment )
97 			return "";
98 
99 		const char* startPos = uriFragment;
100 		while ( *startPos && GeneratedSaxParser::Utils::isWhiteSpace(*startPos))
101 			startPos++;
102 
103 		// skip leading '#' if present. (the uriFragment would be invalid if there is no '#', but we are tolerant)
104 		if ( *startPos == '#' )
105 			startPos++;
106 
107 		const char* endPos = startPos;
108 		while ( *endPos && !GeneratedSaxParser::Utils::isWhiteSpace(*endPos) )
109 			endPos++;
110 
111 		return String(startPos, endPos - startPos);
112 	}
113 
114     //------------------------------
getSourceArray() const115     const SourceArray& SourceArrayLoader::getSourceArray () const
116     {
117         return mSourceArray;
118     }
119 
120     //------------------------------
setSourceArray(const SourceArray & sourceArray)121     void SourceArrayLoader::setSourceArray ( const SourceArray& sourceArray )
122     {
123         mSourceArray = sourceArray;
124     }
125 
126     //------------------------------
getSourceById(const String & sourceId) const127     const SourceBase* SourceArrayLoader::getSourceById ( const String& sourceId ) const
128     {
129         for ( size_t i=0; i<mSourceArray.getCount (); ++i )
130         {
131             const SourceBase* source = mSourceArray [ i ];
132             if ( COLLADABU::Utils::equals ( source->getId (), sourceId ) )
133                 return source;
134         }
135         return 0;
136     }
137 
138     //------------------------------
getSourceById(const String & sourceId)139     SourceBase* SourceArrayLoader::getSourceById ( const String& sourceId )
140     {
141         for ( size_t i=0; i<mSourceArray.getCount (); ++i )
142         {
143             SourceBase* source = mSourceArray [ i ];
144             if ( COLLADABU::Utils::equals ( source->getId (), sourceId ) )
145                 return source;
146         }
147         return 0;
148     }
149 
150 	//------------------------------
beginSource(const source__AttributeData & attributes)151 	bool SourceArrayLoader::beginSource( const source__AttributeData& attributes )
152 	{
153 		if ( attributes.id )
154 			mCurrentSourceId = attributes.id;
155 		return true;
156 	}
157 
158 
159 	//------------------------------
endSource()160 	bool SourceArrayLoader::endSource( )
161 	{
162 		if ( mCurrentSoure )
163 		{
164 			mSourceArray.append(mCurrentSoure);
165 		}
166 		mCurrentSoure = 0;
167 		mCurrentSourceId.clear();
168 		mCurrentArrayId.clear();
169 		return true;
170 	}
171 
172 	//------------------------------
begin__float_array(const float_array__AttributeData & attributeData)173 	bool SourceArrayLoader::begin__float_array( const float_array__AttributeData& attributeData )
174 	{
175 		return beginArray<FloatSource>( attributeData.count, attributeData.id ) != 0;
176 	}
177 
178 	//------------------------------
end__float_array()179 	bool SourceArrayLoader::end__float_array()
180 	{
181 		// we don't need to do anything here
182 		return true;
183 	}
184 
185 	//------------------------------
data__float_array(const float * data,size_t length)186 	bool SourceArrayLoader::data__float_array( const float* data, size_t length )
187 	{
188 		FloatSource* source = (FloatSource*)mCurrentSoure;
189 		COLLADAFW::FloatArray& array  = source->getArrayElement().getValues();
190 		array.appendValues(data, length);
191 		return true;
192 	}
193 
194 	//------------------------------
begin__animation__source__technique_common()195 	bool SourceArrayLoader::begin__animation__source__technique_common()
196 	{
197 		//we don't need to do anything here
198 		return true;
199 	}
200 
201 	//------------------------------
end__animation__source__technique_common()202 	bool SourceArrayLoader::end__animation__source__technique_common()
203 	{
204 		//we don't need to do anything here
205 		return true;
206 	}
207 
208 	//------------------------------
begin__accessor(const accessor__AttributeData & attributeData)209 	bool SourceArrayLoader::begin__accessor( const accessor__AttributeData& attributeData )
210 	{
211 		// As soon as we support all array types, remove this check
212 		if ( mCurrentSoure )
213 			mCurrentSoure->setStride((int)attributeData.stride);
214 		return true;
215 	}
216 
217 	//------------------------------
end__accessor()218 	bool SourceArrayLoader::end__accessor()
219 	{
220 		//we don't need to do anything here
221 		return true;
222 	}
223 
224 	//------------------------------
begin__param(const param__AttributeData & attributeData)225 	bool SourceArrayLoader::begin__param( const param__AttributeData& attributeData )
226 	{
227 		if ( mCurrentSoure )
228 		{
229 			SourceBase::AccessorParameter accessorParameter;
230 			if ( attributeData.name && *attributeData.name )
231 			{
232 				accessorParameter.name = attributeData.name;
233 			}
234 
235 			// the type is required. We don't need to check
236 			accessorParameter.type = attributeData.type;
237 			mCurrentSoure->appendAccessorParameter( accessorParameter );
238 		}
239 		return true;
240 	}
241 
242 
243 } // namespace COLLADAFW
244