//----------------------------------------------------------------------------- // Copyright (c) 2013 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "2d/assets/ParticleAssetFieldCollection.h" //----------------------------------------------------------------------------- // Set custom property name. static StringTableEntry particleAssetFieldNodeName = StringTable->insert("Fields"); //----------------------------------------------------------------------------- ParticleAssetFieldCollection::ParticleAssetFieldCollection() : mpSelectedField( NULL ) { } //----------------------------------------------------------------------------- ParticleAssetFieldCollection::~ParticleAssetFieldCollection() { } //------------------------------------------------------------------------------ void ParticleAssetFieldCollection::copyTo( ParticleAssetFieldCollection& fieldCollection ) { // Iterate the fields. for( typeFieldHash::iterator fieldItr = mFields.begin(); fieldItr != mFields.end(); ++fieldItr ) { // Fetch field. ParticleAssetField* pParticleAssetField = fieldItr->value; // Find target field. ParticleAssetField* pTargetParticleAssetField = fieldCollection.findField( fieldItr->key ); // Sanity! AssertFatal( pTargetParticleAssetField != NULL, "ParticleAssetFieldCollection::copyTo() - Could not find target particle asset field." ); // Copy field. pParticleAssetField->copyTo( *pTargetParticleAssetField ); } // Select the same field name. if ( getSelectedField() != NULL ) fieldCollection.selectField( getSelectedField()->getFieldName() ); } //------------------------------------------------------------------------------ void ParticleAssetFieldCollection::addField( ParticleAssetField& particleAssetField, const char* pFieldName, F32 maxTime, F32 minValue, F32 maxValue, F32 defaultValue ) { // Sanity! AssertFatal( pFieldName != NULL, "ParticleAssetFieldCollection::addField() - Field name cannot be NULL or empty." ); // Set the field name. particleAssetField.setFieldName( pFieldName ); // Sanity! AssertFatal( !mFields.contains( particleAssetField.getFieldName() ), "ParticleAssetFieldCollection::addField() - The particle field name already exists." ); // Add to fields. mFields.insert( particleAssetField.getFieldName(), &particleAssetField ); // Initialize the field. particleAssetField.initialize( maxTime, minValue, maxValue, defaultValue ); } //----------------------------------------------------------------------------- ParticleAssetField* ParticleAssetFieldCollection::selectField( const char* pFieldName ) { // Sanity! AssertFatal( pFieldName != NULL, "ParticleAssetFieldCollection::selectField() - Field name cannot be NULL or empty." ); // Has a field-name been specified? if ( dStrlen(pFieldName) > 0 ) { // Yes, so find the field. mpSelectedField = findField( pFieldName ); // Did we find the field? if ( mpSelectedField == NULL ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::selectField() - Could not find the field name '%s'.", pFieldName ); } } else { // No, so reset the field. mpSelectedField = NULL; } return mpSelectedField; } //----------------------------------------------------------------------------- ParticleAssetField* ParticleAssetFieldCollection::findField( const char* pFieldName ) { // Sanity! AssertFatal( pFieldName != NULL, "ParticleAssetFieldCollection::findField() - Cannot find NULL field." ); // Find the field. typeFieldHash::iterator fieldItr = mFields.find( StringTable->insert( pFieldName ) ); // Return the field if it was found. return fieldItr == mFields.end() ? NULL : fieldItr->value; } //----------------------------------------------------------------------------- S32 ParticleAssetFieldCollection::setSingleDataKey( F32 value ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::setSingleKey() - No field selected." ); return -1; } // Set single data key. return mpSelectedField->setSingleDataKey( value ); } //----------------------------------------------------------------------------- S32 ParticleAssetFieldCollection::addDataKey( F32 time, F32 value ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::addDataKey() - No field selected." ); return -1; } // Add Data Key. return mpSelectedField->addDataKey( time, value ); } //----------------------------------------------------------------------------- bool ParticleAssetFieldCollection::removeDataKey( S32 index ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::removeDataKey() - No field selected." ); return false; } // Remove Data Key. return mpSelectedField->removeDataKey( index ); } //----------------------------------------------------------------------------- bool ParticleAssetFieldCollection::clearDataKeys( void ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::clearDataKeys() - No field selected." ); return false; } // Clear Data Keys mpSelectedField->clearDataKeys(); // Return Okay. return true; } //----------------------------------------------------------------------------- bool ParticleAssetFieldCollection::setDataKey( S32 index, F32 value ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::setDataKey() - No field selected." ); return false; } // Set the data-key value. return mpSelectedField->setDataKeyValue( index, value ); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getDataKeyValue( S32 index ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getDataKeyValue() - No field selected." ); return 0.0f; } // Get the data-key value. return mpSelectedField->getDataKeyValue( index ); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getDataKeyTime( S32 index ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getDataKeyTime() - No field selected." ); return 0.0f; } // Get the data-key time. return mpSelectedField->getDataKeyTime( index ); } //----------------------------------------------------------------------------- const ParticleAssetField::DataKey& ParticleAssetFieldCollection::getDataKey( const U32 index ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getDataKey() - No field selected." ); return ParticleAssetField::BadDataKey; } // Get the data-key. return mpSelectedField->getDataKey( index ); } //----------------------------------------------------------------------------- U32 ParticleAssetFieldCollection::getDataKeyCount( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getDataKeyCount() - No field selected." ); return -1; } // Get the data-key count. return mpSelectedField->getDataKeyCount(); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getMinValue( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getMinValue() - No field selected." ); return 0.0f; } // Get Min Value. return mpSelectedField->getMinValue(); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getMaxValue( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getMaxValue() - No field selected." ); return 0.0f; } // Get Max Value. return mpSelectedField->getMaxValue(); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getMinTime( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getMinTime() - No field selected." ); return 0.0f; } // Get Min Time. return mpSelectedField->getMinTime(); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getMaxTime( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getMaxTime() - No field selected." ); return 0.0f; } // Get Max Time. return mpSelectedField->getMaxTime(); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getFieldValue( F32 time ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getFieldValue() - No field selected." ); return 0.0f; } // Get Graph Value. return mpSelectedField->getFieldValue( time ); } //----------------------------------------------------------------------------- bool ParticleAssetFieldCollection::setRepeatTime( const F32 repeatTime ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::setRepeatTime() - No field selected." ); return false; } // Set repeat time. return mpSelectedField->setRepeatTime( repeatTime ); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getRepeatTime( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getRepeatTime() - No field selected." ); return 0.0f; } // Get repeat time. return mpSelectedField->getRepeatTime(); } //----------------------------------------------------------------------------- bool ParticleAssetFieldCollection::setValueScale( const F32 valueScale ) { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::setValueScale() - No field selected." ); return false; } // Set Value Scale. return mpSelectedField->setValueScale( valueScale ); } //----------------------------------------------------------------------------- F32 ParticleAssetFieldCollection::getValueScale( void ) const { // Have we got a valid field selected? if ( !mpSelectedField ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::getValueScale() - No field selected." ); return 0.0f; } // Get Value Scale. return mpSelectedField->getValueScale(); } //------------------------------------------------------------------------------ void ParticleAssetFieldCollection::onTamlCustomWrite( TamlCustomNodes& customNodes ) { // Debug Profiling. PROFILE_SCOPE(ParticleAssetFieldCollection_OnTamlCustomWrite); // Finish if there no fields. if ( mFields.size() == 0 ) return; // Add particle asset custom node. TamlCustomNode* pParticleAssetCustomNode = customNodes.addNode( particleAssetFieldNodeName ); // Iterate the fields. for( typeFieldHash::iterator fieldItr = mFields.begin(); fieldItr != mFields.end(); ++fieldItr ) { fieldItr->value->onTamlCustomWrite( pParticleAssetCustomNode ); } } //----------------------------------------------------------------------------- void ParticleAssetFieldCollection::onTamlCustomRead( const TamlCustomNodes& customNodes ) { // Debug Profiling. PROFILE_SCOPE(ParticleAssetFieldCollection_OnTamlCustomRead); // Find the particle asset custom node. const TamlCustomNode* pParticleAssetCustomNode = customNodes.findNode( particleAssetFieldNodeName ); // Finish if we don't have a custom node. if ( pParticleAssetCustomNode == NULL ) return; // Fetch children. const TamlCustomNodeVector& children = pParticleAssetCustomNode->getChildren(); // Iterate the custom properties. for( TamlCustomNodeVector::const_iterator childNodeItr = children.begin(); childNodeItr != children.end(); ++childNodeItr ) { // Fetch child node. TamlCustomNode* pChildNode = *childNodeItr; // Fetch node name. StringTableEntry nodeName = pChildNode->getNodeName(); // Find the field. ParticleAssetField* pParticleAssetField = findField( nodeName ); // Did we find the field? if ( pParticleAssetField == NULL ) { // No, so warn. Con::warnf( "ParticleAssetFieldCollection::onTamlCustomRead() - Cannot find data field '%s'.", nodeName ); continue; } // Read the alias. pParticleAssetField->onTamlCustomRead( pChildNode ); } } //----------------------------------------------------------------------------- void ParticleAssetFieldCollection::WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) const { // Sanity! AssertFatal( pClassRep != NULL, "ParticleAssetFieldCollection::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); AssertFatal( pParentElement != NULL, "ParticleAssetFieldCollection::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); char buffer[1024]; // Create Fields node element. TiXmlElement* pFieldsNodeElement = new TiXmlElement( "xs:element" ); dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), particleAssetFieldNodeName ); pFieldsNodeElement->SetAttribute( "name", buffer ); pFieldsNodeElement->SetAttribute( "minOccurs", 0 ); pFieldsNodeElement->SetAttribute( "maxOccurs", 1 ); pParentElement->LinkEndChild( pFieldsNodeElement ); // Create complex type. TiXmlElement* pFieldsNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); pFieldsNodeElement->LinkEndChild( pFieldsNodeComplexTypeElement ); // Create choice element. TiXmlElement* pFieldsNodeChoiceElement = new TiXmlElement( "xs:choice" ); pFieldsNodeChoiceElement->SetAttribute( "minOccurs", 0 ); pFieldsNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); pFieldsNodeComplexTypeElement->LinkEndChild( pFieldsNodeChoiceElement ); // Iterate the fields. for( typeFieldHash::const_iterator fieldItr = mFields.begin(); fieldItr != mFields.end(); ++fieldItr ) { // Write schema for the field. fieldItr->value->WriteCustomTamlSchema( pClassRep, pFieldsNodeChoiceElement ); } }