555 lines
14 KiB
C++
555 lines
14 KiB
C++
/*
|
|
* Copyright 2006 Sony Computer Entertainment Inc.
|
|
*
|
|
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
|
|
* file except in compliance with the License. You may obtain a copy of the License at:
|
|
* http://research.scea.com/scea_shared_source_license.html
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing permissions and limitations under the
|
|
* License.
|
|
*/
|
|
|
|
#include <dae/daeElement.h>
|
|
#include <dae/daeArray.h>
|
|
#include <dae/daeMetaAttribute.h>
|
|
#include <dae/daeMetaElementAttribute.h>
|
|
#include <dae/daeMetaElement.h>
|
|
#include <dae/daeDatabase.h>
|
|
#include <dae/daeErrorHandler.h>
|
|
|
|
#include <dae/daeIntegrationObject.h>
|
|
#include <dae/daeURI.h>
|
|
|
|
void
|
|
daeElement::release() const
|
|
{
|
|
if (--_refCount <= 0)
|
|
delete this;
|
|
}
|
|
daeElementRef DAECreateElement(int nbytes)
|
|
{
|
|
return new(nbytes) daeElement;
|
|
}
|
|
|
|
//Contributed by Nus - Wed, 08 Nov 2006
|
|
// static daeElementRefArray resolveArray;
|
|
static daeElementRefArray* pResolveArray = NULL;
|
|
//static char StaticIndentBuf[] = "";
|
|
|
|
extern "C" void initializeResolveArray(void)
|
|
{
|
|
if(!pResolveArray) {
|
|
pResolveArray = new daeElementRefArray;
|
|
}
|
|
}
|
|
|
|
extern "C" void terminateResolveArray(void)
|
|
{
|
|
if(pResolveArray) {
|
|
delete pResolveArray;
|
|
pResolveArray = NULL;
|
|
}
|
|
}
|
|
//----------------------------------
|
|
|
|
// sthomas (see https://collada.org/public_forum/viewtopic.php?t=325&)
|
|
void daeElement::releaseElements()
|
|
{
|
|
// resolveArray.clear();
|
|
pResolveArray->clear();
|
|
}
|
|
|
|
daeIntegrationObject*
|
|
daeElement::getIntObject( IntegrationState from_state, IntegrationState to_state )
|
|
{
|
|
if ( !_intObject ) {
|
|
return NULL;
|
|
}
|
|
if ( from_state >= int_created ) {
|
|
if ( _intObject->_from_state < int_created ) {
|
|
daeErrorHandler::get()->handleWarning("Warning: getIntObject tries to get object that is not created (from)");
|
|
return NULL;
|
|
}
|
|
if ( from_state >= int_converted ) {
|
|
_intObject->fromCOLLADAChecked();
|
|
if ( from_state == int_finished ) {
|
|
_intObject->fromCOLLADAPostProcessChecked();
|
|
}
|
|
}
|
|
}
|
|
if ( to_state >= int_created ) {
|
|
if ( _intObject->_to_state < int_created ) {
|
|
daeErrorHandler::get()->handleWarning("Warning: getIntObject tries to get object that is not created (to)");
|
|
return NULL;
|
|
}
|
|
if ( to_state >= int_converted ) {
|
|
_intObject->toCOLLADAChecked();
|
|
if ( to_state == int_finished ) {
|
|
_intObject->toCOLLADAPostProcessChecked();
|
|
}
|
|
}
|
|
}
|
|
return _intObject;
|
|
}
|
|
|
|
daeElementRef
|
|
daeElement::createElement(daeString className)
|
|
{
|
|
daeElementRef elem = _meta->create(className);
|
|
// Bug #225 work around
|
|
// if ( elem != NULL)
|
|
// elem->ref(); // change premature delete into memory leak.
|
|
return elem;
|
|
}
|
|
|
|
daeElement*
|
|
daeElement::createAndPlace(daeString className)
|
|
{
|
|
daeElementRef elem = _meta->create(className);
|
|
daeBool place = false;
|
|
if (elem != NULL)
|
|
place = placeElement(elem);
|
|
if (place)
|
|
return elem;
|
|
return NULL;
|
|
}
|
|
|
|
daeElement*
|
|
daeElement::createAndPlaceAt(daeInt index, daeString className)
|
|
{
|
|
daeElementRef elem = _meta->create(className);
|
|
daeBool place = false;
|
|
if (elem != NULL)
|
|
place = placeElementAt(index, elem);
|
|
if (place)
|
|
return elem;
|
|
return NULL;
|
|
}
|
|
|
|
daeBool
|
|
daeElement::placeElement(daeElement* e)
|
|
{
|
|
if (e == NULL || e == this)
|
|
return false;
|
|
return _meta->place( this, e );
|
|
}
|
|
|
|
daeBool daeElement::placeElementAt(daeInt index, daeElement* e) {
|
|
if (e == NULL || e == this)
|
|
return false;
|
|
return _meta->placeAt( index, this, e );
|
|
}
|
|
|
|
daeBool daeElement::placeElementBefore( daeElement *marker, daeElement *element ) {
|
|
if (marker == NULL || element == NULL || marker->getXMLParentElement() != this ) {
|
|
return false;
|
|
}
|
|
//if ( _meta->getContents() != NULL ) {
|
|
// size_t idx;
|
|
// daeElementRefArray* contents =
|
|
// (daeElementRefArray*)_meta->getContents()->getWritableMemory(this);
|
|
// if ( contents->find( marker, idx ) != DAE_OK ) {
|
|
// return false;
|
|
// }
|
|
// return placeElementAt( (daeInt)idx, element );
|
|
//}
|
|
//if ( strcmp( marker->getTypeName(), element->getTypeName() ) == 0 ) {
|
|
// //same type
|
|
// daeMetaElementAttribute *mea = _meta->getChildMetaElementAttribute( element->getTypeName() );
|
|
// daeElementRefArray* era = (daeElementRefArray*)mea->getWritableMemory(this);
|
|
// size_t idx;
|
|
// if ( era->find( marker, idx ) != DAE_OK ) {
|
|
// return false;
|
|
// }
|
|
// era->insertAt( idx, element );
|
|
// return true;
|
|
//}
|
|
//return placeElement( element );
|
|
return _meta->placeBefore( marker, this, element );
|
|
}
|
|
|
|
daeBool daeElement::placeElementAfter( daeElement *marker, daeElement *element ) {
|
|
if (marker == NULL || element == NULL || marker->getXMLParentElement() != this ) {
|
|
return false;
|
|
}
|
|
/*if ( _meta->getContents() != NULL ) {
|
|
size_t idx;
|
|
daeElementRefArray* contents =
|
|
(daeElementRefArray*)_meta->getContents()->getWritableMemory(this);
|
|
if ( contents->find( marker, idx ) != DAE_OK ) {
|
|
return false;
|
|
}
|
|
return placeElementAt( (daeInt)idx+1, element );
|
|
}
|
|
if ( strcmp( marker->getTypeName(), element->getTypeName() ) == 0 ) {
|
|
daeMetaElementAttribute *mea = _meta->getChildMetaElementAttribute( element->getTypeName() );
|
|
daeElementRefArray* era = (daeElementRefArray*)mea->getWritableMemory(this);
|
|
size_t idx;
|
|
if ( era->find( marker, idx ) != DAE_OK ) {
|
|
return false;
|
|
}
|
|
era->insertAt( idx+1, element );
|
|
return true;
|
|
}*/
|
|
return _meta->placeAfter( marker, this, element );
|
|
}
|
|
|
|
daeInt daeElement::findLastIndexOf( daeString elementName ) {
|
|
if ( _meta->getContents() != NULL ) {
|
|
daeElementRefArray* contents =
|
|
(daeElementRefArray*)_meta->getContents()->getWritableMemory(this);
|
|
for ( int i = (int)contents->getCount()-1; i >= 0; --i ) {
|
|
daeString nm = contents->get(i)->getElementName();
|
|
if ( nm == NULL ) {
|
|
nm = contents->get(i)->getTypeName();
|
|
}
|
|
if ( strcmp( nm, elementName ) == 0 ) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
daeBool
|
|
daeElement::removeChildElement(daeElement* element)
|
|
{
|
|
// error traps
|
|
if(element==NULL)
|
|
return false;
|
|
if(element->_parent != this)
|
|
return false;
|
|
|
|
// Clear the element's parent pointer, if the element has references outside
|
|
// 'this' it won't go away, so we want to make sure it's parent is valid
|
|
if ( _meta->remove( this, element ) ) {
|
|
element->_parent = NULL;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// !!!ACL Added to fix mantis issue 0000416
|
|
void daeElement::setDocument( daeDocument *c ) {
|
|
if( _document == c ) {
|
|
return;
|
|
}
|
|
if (_document != NULL )
|
|
{
|
|
_document->removeElement(this);
|
|
}
|
|
_document = c;
|
|
if ( _document != NULL )
|
|
{
|
|
_document->insertElement(this);
|
|
}
|
|
|
|
daeElementRefArray ea;
|
|
getChildren( ea );
|
|
for ( size_t x = 0; x < ea.getCount(); x++ ) {
|
|
ea[x]->setDocument( c );
|
|
}
|
|
}
|
|
|
|
daeBool
|
|
daeElement::setAttribute(daeString attrName, daeString attrValue)
|
|
{
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
daeMetaAttributeRefArray& metaAttrs = _meta->getMetaAttributes();
|
|
int n = (int)metaAttrs.getCount();
|
|
int i;
|
|
for(i=0;i<n;i++) {
|
|
//fflush(stdout);
|
|
if ((metaAttrs[i]->getName() != NULL) &&
|
|
(strcmp(metaAttrs[i]->getName(),attrName)==0)) {
|
|
#if 0 //debug stuff
|
|
printf("%s(%s)->setAttr(%s,%s)\n",
|
|
(const char*)_meta->getName(),
|
|
metaAttrs[i]->getType()->getTypeString(),
|
|
attrName,
|
|
attrValue);
|
|
#endif
|
|
if (metaAttrs[i]->getType() != NULL)
|
|
{
|
|
metaAttrs[i]->set(this,attrValue);
|
|
_validAttributeArray.set(i, true);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
daeBool daeElement::isAttributeSet( daeString attrName ) {
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
daeMetaAttributeRefArray& metaAttrs = _meta->getMetaAttributes();
|
|
int n = (int)metaAttrs.getCount();
|
|
int i;
|
|
for(i=0;i<n;i++) {
|
|
if ((metaAttrs[i]->getName() != NULL) &&
|
|
(strcmp(metaAttrs[i]->getName(),attrName)==0)) {
|
|
|
|
return _validAttributeArray[i];
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
daeBool daeElement::hasAttribute( daeString attrName ) {
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
daeMetaAttributeRefArray& metaAttrs = _meta->getMetaAttributes();
|
|
int n = (int)metaAttrs.getCount();
|
|
int i;
|
|
for(i=0;i<n;i++) {
|
|
if ((metaAttrs[i]->getName() != NULL) &&
|
|
(strcmp(metaAttrs[i]->getName(),attrName)==0)) {
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
daeMemoryRef daeElement::getAttributeValue( daeString attrName ) {
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
daeMetaAttributeRefArray& metaAttrs = _meta->getMetaAttributes();
|
|
int n = (int)metaAttrs.getCount();
|
|
int i;
|
|
for(i=0;i<n;i++) {
|
|
if ((metaAttrs[i]->getName() != NULL) &&
|
|
(strcmp(metaAttrs[i]->getName(),attrName)==0)) {
|
|
|
|
return metaAttrs[i]->getWritableMemory(this);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
daeBool daeElement::hasValue() {
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
return (_meta->getValueAttribute() != NULL );
|
|
}
|
|
|
|
daeMemoryRef daeElement::getValuePointer() {
|
|
if (_meta == NULL)
|
|
return false;
|
|
|
|
if ( _meta->getValueAttribute() != NULL )
|
|
{
|
|
return _meta->getValueAttribute()->getWritableMemory(this);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
daeElement::appendResolveElement(daeElement* elem)
|
|
{
|
|
//Contributed by Nus - Wed, 08 Nov 2006
|
|
// resolveArray.append(elem);
|
|
pResolveArray->append(elem);
|
|
//----------------------
|
|
}
|
|
void
|
|
daeElement::resolveAll()
|
|
{
|
|
int cnt;
|
|
//Contributed by Nus - Wed, 08 Nov 2006
|
|
// while(resolveArray.getCount()) {
|
|
while(pResolveArray->getCount()) {
|
|
// cnt = (int)resolveArray.getCount();
|
|
cnt = (int)pResolveArray->getCount();
|
|
// daeElementRef elem = resolveArray[cnt-1];
|
|
daeElementRef elem = (*pResolveArray)[cnt-1];
|
|
// resolveArray.removeIndex(cnt-1);
|
|
pResolveArray->removeIndex(cnt-1);
|
|
//--------------------------
|
|
elem->resolve();
|
|
}
|
|
/*size_t cnt = resolveArray.getCount();
|
|
for ( size_t i =0; i < cnt; i++ ) {
|
|
resolveArray[i]->resolve();
|
|
}
|
|
resolveArray.clear();*/
|
|
}
|
|
|
|
void
|
|
daeElement::clearResolveArray()
|
|
{
|
|
//Contributed by Nus - Wed, 08 Nov 2006
|
|
// resolveArray.clear();
|
|
pResolveArray->clear();
|
|
//------------------------
|
|
}
|
|
|
|
void
|
|
daeElement::resolve()
|
|
{
|
|
if (_meta == NULL)
|
|
return;
|
|
|
|
daeMetaAttributePtrArray& maa = _meta->getMetaResolvers();
|
|
int n = (int)maa.getCount();
|
|
int i;
|
|
for(i=0;i<n;i++)
|
|
maa[i]->resolve(this);
|
|
}
|
|
|
|
void
|
|
daeElement::setup(daeMetaElement* meta)
|
|
{
|
|
if (_meta)
|
|
return;
|
|
_meta = meta;
|
|
if (meta->needsResolve())
|
|
appendResolveElement((daeElement*)this);
|
|
daeMetaElement* intlibMeta = meta->getMetaIntegration();
|
|
if (intlibMeta != NULL)
|
|
{
|
|
daeElementRef intObj = intlibMeta->create();
|
|
intObj->ref(); //inc the ref count
|
|
_intObject = (daeIntegrationObject*)(daeElement*)intObj;
|
|
}
|
|
daeMetaAttributeRefArray& attrs = meta->getMetaAttributes();
|
|
int macnt = (int)attrs.getCount();
|
|
|
|
_validAttributeArray.setCount( macnt );
|
|
|
|
int i;
|
|
for(i=0;i<macnt;i++) {
|
|
if (attrs[i]->getDefault() != NULL) {
|
|
attrs[i]->set(this, attrs[i]->getDefault());
|
|
_validAttributeArray[i] = true;
|
|
}
|
|
// else {
|
|
// _validAttributeArray[i] = false;
|
|
// }
|
|
}
|
|
|
|
#if 0
|
|
// Setup resolvers to know their containers and thus their file context
|
|
daeMetaAttributePtrArray& resolvers = meta->getMetaResolvers();
|
|
int racnt = resolvers.getCount();
|
|
for(i=0;i<racnt;i++)
|
|
((daeURI*)(resolvers[i]->getWritableMemory(this)))->_container =
|
|
this;
|
|
#endif
|
|
}
|
|
|
|
daeElement::daeElement():
|
|
_refCount(0),
|
|
_intObject(0),
|
|
_parent(NULL),
|
|
_document(NULL),
|
|
_meta(NULL),
|
|
_elementName(NULL)
|
|
{}
|
|
|
|
daeElement::~daeElement()
|
|
{
|
|
if (_intObject)
|
|
_intObject->release();
|
|
|
|
if (_elementName) {
|
|
delete[] _elementName;
|
|
_elementName = NULL;
|
|
}
|
|
}
|
|
|
|
//function used until we clarify what's a type and what's a name for an element
|
|
daeString daeElement::getTypeName() const
|
|
{
|
|
return _meta->getName();
|
|
}
|
|
daeString daeElement::getElementName() const
|
|
{
|
|
return _elementName;
|
|
}
|
|
void daeElement::setElementName( daeString nm ) {
|
|
if ( nm == NULL ) {
|
|
if ( _elementName ) delete[] _elementName;
|
|
_elementName = NULL;
|
|
return;
|
|
}
|
|
if ( !_elementName ) _elementName = new daeChar[128];
|
|
strcpy( (char*)_elementName, nm );
|
|
}
|
|
|
|
daeString daeElement::getID() const
|
|
{
|
|
if ((_meta == NULL) || (!_meta->getIDAttribute()))
|
|
return NULL;
|
|
else
|
|
return *(daeStringRef*)_meta->getIDAttribute()->getWritableMemory(const_cast<daeElement*>(this));
|
|
}
|
|
|
|
void daeElement::getChildren( daeElementRefArray &array ) {
|
|
_meta->getChildren( this, array );
|
|
}
|
|
|
|
daeSmartRef<daeElement> daeElement::clone(daeString idSuffix, daeString nameSuffix) {
|
|
//use the meta object system to create a new instance of this element
|
|
daeElementRef ret = _meta->create();
|
|
ret->setElementName( getElementName() );
|
|
//use meta system to copy attributes
|
|
daeMetaAttributeRefArray &attrs = _meta->getMetaAttributes();
|
|
for ( unsigned int i = 0; i < attrs.getCount(); i++ ) {
|
|
//memcpy( attrs[i]->getWritableMemory( ret ), attrs[i]->getWritableMemory( this ), attrs[i]->getSize() );
|
|
attrs[i]->copy( ret, this );
|
|
ret->_validAttributeArray[i] = _validAttributeArray[i];
|
|
}
|
|
if ( _meta->getValueAttribute() != NULL ) {
|
|
daeMetaAttribute *val = _meta->getValueAttribute();
|
|
//memcpy( val->getWritableMemory( ret ), val->getWritableMemory( this ), val->getSize() );
|
|
val->copy( ret, this );
|
|
}
|
|
daeElementRefArray children;
|
|
_meta->getChildren( this, children );
|
|
for ( size_t x = 0; x < children.getCount(); x++ ) {
|
|
ret->placeElement( children.get(x)->clone( idSuffix, nameSuffix ) );
|
|
}
|
|
|
|
//mangle the id
|
|
daeMetaAttribute *id = _meta->getIDAttribute();
|
|
if ( idSuffix != NULL && id != NULL ) {
|
|
daeChar str[2048];
|
|
id->getType()->memoryToString( id->getWritableMemory( ret ), str, 2048 );
|
|
if ( strcmp( str, "" ) ) {
|
|
strcat( str, idSuffix );
|
|
}
|
|
//id->getType()->stringToMemory( str, id->getWritableMemory( ret ) );
|
|
id->set( ret, str );
|
|
}
|
|
//mangle the name
|
|
daeMetaAttribute *nm = _meta->getMetaAttribute("name");
|
|
if ( nameSuffix != NULL && nm != NULL ) {
|
|
daeChar str[2048];
|
|
nm->getType()->memoryToString( nm->getWritableMemory( ret ), str, 2048 );
|
|
if ( strcmp( str, "" ) ) {
|
|
strcat( str, nameSuffix );
|
|
}
|
|
//nm->getType()->stringToMemory( str, nm->getWritableMemory( ret ) );
|
|
nm->set( ret, str );
|
|
}
|
|
//ret->_intObject = _intObject;
|
|
return ret;
|
|
}
|
|
|
|
daeURI *daeElement::getDocumentURI() const {
|
|
if ( _document == NULL ) {
|
|
return NULL;
|
|
}
|
|
return _document->getDocumentURI();
|
|
}
|