moved files around
This commit is contained in:
366
Extras/FCollada/FCDocument/FCDExtra.cpp
Normal file
366
Extras/FCollada/FCDocument/FCDExtra.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDExtra.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDExtra::FCDExtra(FCDocument* document) : FCDObject(document, "FCDExtra")
|
||||
{
|
||||
}
|
||||
|
||||
FCDExtra::~FCDExtra()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(techniques);
|
||||
}
|
||||
|
||||
// Adds a technique of the given profile (or return the existing technique with this profile).
|
||||
FCDETechnique* FCDExtra::AddTechnique(const char* profile)
|
||||
{
|
||||
FCDETechnique* technique = FindTechnique(profile);
|
||||
if (technique == NULL)
|
||||
{
|
||||
technique = new FCDETechnique(GetDocument(), profile);
|
||||
techniques.push_back(technique);
|
||||
}
|
||||
return technique;
|
||||
}
|
||||
|
||||
// Releases a technique contained within the extra tree.
|
||||
void FCDExtra::ReleaseTechnique(FCDETechnique* technique)
|
||||
{
|
||||
FCDETechniqueList::iterator it = std::find(techniques.begin(), techniques.end(), technique);
|
||||
if (it != techniques.end())
|
||||
{
|
||||
delete (*it);
|
||||
techniques.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for a profile-specific technique
|
||||
FCDETechnique* FCDExtra::FindTechnique(const char* profile)
|
||||
{
|
||||
for (FCDETechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
if (IsEquivalent((*itT)->GetProfile(), profile)) return *itT;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDETechnique* FCDExtra::FindTechnique(const char* profile) const
|
||||
{
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
if (IsEquivalent((*itT)->GetProfile(), profile)) return *itT;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search for a root node with a specific element name
|
||||
FCDENode* FCDExtra::FindRootNode(const char* name)
|
||||
{
|
||||
FCDENode* rootNode = NULL;
|
||||
for (FCDETechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
rootNode = (*itT)->FindChildNode(name);
|
||||
if (rootNode != NULL) break;
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
const FCDENode* FCDExtra::FindRootNode(const char* name) const
|
||||
{
|
||||
FCDENode* rootNode = NULL;
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
rootNode = (*itT)->FindChildNode(name);
|
||||
if (rootNode != NULL) break;
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
// Read in/Write to a COLLADA xml document
|
||||
FUStatus FCDExtra::LoadFromXML(xmlNode* extraNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the techniques
|
||||
xmlNodeList techniqueNodes;
|
||||
FindChildrenByType(extraNode, DAE_TECHNIQUE_ELEMENT, techniqueNodes);
|
||||
for (xmlNodeList::iterator itN = techniqueNodes.begin(); itN != techniqueNodes.end(); ++itN)
|
||||
{
|
||||
xmlNode* techniqueNode = (*itN);
|
||||
FCDETechnique* technique = AddTechnique(ReadNodeProperty(techniqueNode, DAE_PROFILE_ATTRIBUTE));
|
||||
status.AppendStatus(technique->LoadFromXML(techniqueNode));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDExtra::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
if (techniques.empty()) return NULL;
|
||||
|
||||
// Add the <extra> element and its techniques
|
||||
xmlNode* extraNode = AddChildOnce(parentNode, DAE_EXTRA_ELEMENT);
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
(*itT)->WriteToXML(extraNode);
|
||||
}
|
||||
return extraNode;
|
||||
}
|
||||
|
||||
FCDENode::FCDENode(FCDocument* document, FCDENode* _parent) : FCDObject(document, "FCDENode")
|
||||
{
|
||||
parent = _parent;
|
||||
animated = NULL;
|
||||
}
|
||||
|
||||
FCDENode::~FCDENode()
|
||||
{
|
||||
GetDocument()->UnregisterAnimatedValue(animated);
|
||||
SAFE_DELETE(animated);
|
||||
parent = NULL;
|
||||
|
||||
CLEAR_POINTER_VECTOR(children);
|
||||
CLEAR_POINTER_VECTOR(attributes);
|
||||
}
|
||||
|
||||
void FCDENode::Release()
|
||||
{
|
||||
if (parent != NULL)
|
||||
{
|
||||
parent->ReleaseChildNode(this);
|
||||
}
|
||||
|
||||
// Otherwise, we have a technique so don't release
|
||||
}
|
||||
|
||||
void FCDENode::SetContent(const fchar* _content)
|
||||
{
|
||||
// As COLLADA doesn't allow for mixed content, release all the children.
|
||||
while (!children.empty())
|
||||
{
|
||||
children.back()->Release();
|
||||
}
|
||||
|
||||
content = _content;
|
||||
}
|
||||
|
||||
// Search for a children with a specific name
|
||||
FCDENode* FCDENode::FindChildNode(const char* name)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
if (IsEquivalent((*itN)->GetName(), name)) return (*itN);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDENode* FCDENode::FindChildNode(const char* name) const
|
||||
{
|
||||
for (FCDENodeList::const_iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
if (IsEquivalent((*itN)->GetName(), name)) return (*itN);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Adds a new child node
|
||||
FCDENode* FCDENode::AddChildNode()
|
||||
{
|
||||
FCDENode* node = new FCDENode(GetDocument(), this);
|
||||
children.push_back(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Releases a child node
|
||||
void FCDENode::ReleaseChildNode(FCDENode* childNode)
|
||||
{
|
||||
FCDENodeList::iterator itN = std::find(children.begin(), children.end(), childNode);
|
||||
if (itN != children.end())
|
||||
{
|
||||
delete (*itN);
|
||||
children.erase(itN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FCDENode* FCDENode::FindParameter(const char* name)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
FCDENode* node = (*itN);
|
||||
if (IsEquivalent(node->GetName(), name)) return node;
|
||||
else if (IsEquivalent(node->GetName(), DAE_PARAMETER_ELEMENT))
|
||||
{
|
||||
FCDEAttribute* nameAttribute = node->FindAttribute(DAE_NAME_ATTRIBUTE);
|
||||
if (nameAttribute != NULL && nameAttribute->value == TO_FSTRING(name)) return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FCDENode::FindParameters(FCDENodeList& nodes, StringList& names)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
FCDENode* node = (*itN);
|
||||
if (node->GetChildNodeCount() > 1) continue;
|
||||
|
||||
if (IsEquivalent(node->GetName(), DAE_PARAMETER_ELEMENT))
|
||||
{
|
||||
FCDEAttribute* nameAttribute = node->FindAttribute(DAE_NAME_ATTRIBUTE);
|
||||
if (nameAttribute != NULL)
|
||||
{
|
||||
nodes.push_back(node);
|
||||
names.push_back(FUStringConversion::ToString(nameAttribute->value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.push_back(node);
|
||||
names.push_back(node->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new attribute to this extra tree node.
|
||||
FCDEAttribute* FCDENode::AddAttribute(const char* _name, const fchar* _value)
|
||||
{
|
||||
FCDEAttribute* attribute = FindAttribute(_name);
|
||||
if (attribute == NULL)
|
||||
{
|
||||
attribute = new FCDEAttribute();
|
||||
attribute->name = _name;
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
attribute->value = _value;
|
||||
return attribute;
|
||||
}
|
||||
|
||||
// Releases an attribute
|
||||
void FCDENode::ReleaseAttribute(FCDEAttribute* attribute)
|
||||
{
|
||||
FCDEAttributeList::iterator it = std::find(attributes.begin(), attributes.end(), attribute);
|
||||
if (it != attributes.end())
|
||||
{
|
||||
delete *it;
|
||||
attributes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for an attribute with a specific name
|
||||
FCDEAttribute* FCDENode::FindAttribute(const char* name)
|
||||
{
|
||||
for (FCDEAttributeList::iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
if ((*itA)->name == name) return (*itA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEAttribute* FCDENode::FindAttribute(const char* name) const
|
||||
{
|
||||
for (FCDEAttributeList::const_iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
if ((*itA)->name == name) return (*itA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read in this extra node from a COLLADA xml document
|
||||
FUStatus FCDENode::LoadFromXML(xmlNode* customNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the node's name and children
|
||||
name = (const char*) customNode->name;
|
||||
ReadChildrenFromXML(customNode);
|
||||
|
||||
// If there are no child nodes, we have a tree leaf: parse in the content and its animation
|
||||
content = (children.empty()) ? TO_FSTRING(ReadNodeContentDirect(customNode)) : FS("");
|
||||
animated = FCDAnimatedCustom::Create(GetDocument(), customNode);
|
||||
|
||||
// Read in the node's attributes
|
||||
for (xmlAttr* a = customNode->properties; a != NULL; a = a->next)
|
||||
{
|
||||
AddAttribute((const char*) a->name, (a->children != NULL) ? TO_FSTRING((const char*) (a->children->content)) : FS(""));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this extra to a COLLADA xml document
|
||||
xmlNode* FCDENode::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* customNode = AddChild(parentNode, name.c_str(), content);
|
||||
|
||||
// Write out the attributes
|
||||
for (FCDEAttributeList::const_iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
const FCDEAttribute* attribute = (*itA);
|
||||
FUXmlWriter::AddAttribute(customNode, attribute->name.c_str(), attribute->value);
|
||||
}
|
||||
|
||||
// Write out the children
|
||||
WriteChildrenToXML(customNode);
|
||||
return customNode;
|
||||
}
|
||||
|
||||
// Read in the child nodes from the xml tree node
|
||||
FUStatus FCDENode::ReadChildrenFromXML(xmlNode* customNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the node's children
|
||||
for (xmlNode* k = customNode->children; k != NULL; k = k->next)
|
||||
{
|
||||
if (k->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
FCDENode* node = AddChildNode();
|
||||
status.AppendStatus(node->LoadFromXML(k));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the child nodes to the xml tree node
|
||||
void FCDENode::WriteChildrenToXML(xmlNode* customNode) const
|
||||
{
|
||||
for (FCDENodeList::const_iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
(*itN)->WriteToXML(customNode);
|
||||
}
|
||||
}
|
||||
|
||||
FCDETechnique::FCDETechnique(FCDocument* document, const char* _profile) : FCDENode(document, NULL)
|
||||
{
|
||||
profile = _profile;
|
||||
}
|
||||
|
||||
FCDETechnique::~FCDETechnique() {}
|
||||
|
||||
// Read in/Write to a COLLADA xml document
|
||||
FUStatus FCDETechnique::LoadFromXML(xmlNode* techniqueNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in only the child elements: none of the attributes
|
||||
status.AppendStatus(ReadChildrenFromXML(techniqueNode));
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDETechnique::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Create the technique for this profile and write out the children
|
||||
xmlNode* customNode = AddTechniqueChild(parentNode, profile.c_str());
|
||||
WriteChildrenToXML(customNode);
|
||||
return customNode;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user