Files
bullet3/Extras/FCollada/FCDocument/FCDEffectPassShader.cpp
2006-05-25 19:18:29 +00:00

149 lines
5.1 KiB
C++

/*
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/FCDEffectCode.h"
#include "FCDocument/FCDEffectPass.h"
#include "FCDocument/FCDEffectPassShader.h"
#include "FCDocument/FCDEffectProfileFX.h"
#include "FCDocument/FCDEffectTechnique.h"
#include "FUtils/FUDaeParser.h"
#include "FUtils/FUDaeWriter.h"
using namespace FUDaeParser;
using namespace FUDaeWriter;
FCDEffectPassShader::FCDEffectPassShader(FCDocument* document, FCDEffectPass* _parent) : FCDObject(document, "FCDEffectPassShader")
{
parent = _parent;
isFragment = false;
code = NULL;
}
FCDEffectPassShader::~FCDEffectPassShader()
{
parent = NULL;
code = NULL;
}
// Adds a new binding to this shader.
FCDEffectPassBind* FCDEffectPassShader::AddBinding()
{
bindings.push_back(FCDEffectPassBind());
return &bindings.back();
}
// Releases a binding contained within this shader.
void FCDEffectPassShader::ReleaseBinding(FCDEffectPassBind* binding)
{
for (FCDEffectPassBindList::iterator it = bindings.begin(); it != bindings.end(); ++it)
{
if (&(*it) == binding)
{
bindings.erase(it);
break;
}
}
}
// Cloning
FCDEffectPassShader* FCDEffectPassShader::Clone(FCDEffectPass* newParent) const
{
FCDEffectPassShader* clone = new FCDEffectPassShader(GetDocument(), newParent);
clone->isFragment = isFragment;
clone->bindings = bindings;
clone->compilerTarget = compilerTarget;
clone->compilerOptions = compilerOptions;
clone->name = name;
// Look for the new code within the parent.
if (code != NULL)
{
clone->code = newParent->GetParent()->FindCode(code->GetSid());
if (clone->code == NULL) clone->code = newParent->GetParent()->GetParent()->FindCode(code->GetSid());
}
return clone;
}
// Read in the ColladaFX pass shader from the xml node tree
FUStatus FCDEffectPassShader::LoadFromXML(xmlNode* shaderNode)
{
FUStatus status;
if (!IsEquivalent(shaderNode->name, DAE_SHADER_ELEMENT))
{
return status.Warning(FS("Pass shader contains unknown element."), shaderNode->line);
}
// Read in the shader's name and stage
xmlNode* nameNode = FindChildByType(shaderNode, DAE_FXCMN_NAME_ELEMENT);
name = ReadNodeContentDirect(nameNode);
string codeSource = ReadNodeProperty(nameNode, DAE_SOURCE_ATTRIBUTE);
if (name.empty())
{
return status.Warning(FS("Unnamed effect pass shader found."), shaderNode->line);
}
string stage = ReadNodeStage(shaderNode);
isFragment = stage == DAE_FXCMN_FRAGMENT_SHADER;
if (!isFragment && stage != DAE_FXCMN_VERTEX_SHADER)
{
return status.Warning(FS("Unknown stage for effect pass shader: ") + TO_FSTRING(name), shaderNode->line);
}
// Look-up the code filename for this shader, if available
code = parent->GetParent()->FindCode(codeSource);
if (code == NULL) code = parent->GetParent()->GetParent()->FindCode(codeSource);
// Read in the compiler-related elements
xmlNode* compilerTargetNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILERTARGET_ELEMENT);
compilerTarget = TO_FSTRING(ReadNodeContentDirect(compilerTargetNode));
xmlNode* compilerOptionsNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILEROPTIONS_ELEMENT);
compilerOptions = TO_FSTRING(ReadNodeContentDirect(compilerOptionsNode));
// Read in the bind parameters
xmlNodeList bindNodes;
FindChildrenByType(shaderNode, DAE_FXCMN_BIND_ELEMENT, bindNodes);
for (xmlNodeList::iterator itB = bindNodes.begin(); itB != bindNodes.end(); ++itB)
{
xmlNode* paramNode = FindChildByType(*itB, DAE_PARAMETER_ELEMENT);
FCDEffectPassBind& bind = *(bindings.insert(bindings.end(), FCDEffectPassBind()));
bind.symbol = ReadNodeProperty((*itB), DAE_SYMBOL_ATTRIBUTE);
bind.reference = ReadNodeProperty(paramNode, DAE_REF_ATTRIBUTE);
}
return status;
}
// Write out the pass shader to the COLLADA xml node tree
xmlNode* FCDEffectPassShader::WriteToXML(xmlNode* parentNode) const
{
xmlNode* shaderNode = AddChild(parentNode, DAE_SHADER_ELEMENT);
// Write out the compiler information and the shader's name/stage
if (!compilerTarget.empty()) AddChild(shaderNode, DAE_FXCMN_COMPILERTARGET_ELEMENT, compilerTarget);
if (!compilerOptions.empty()) AddChild(shaderNode, DAE_FXCMN_COMPILEROPTIONS_ELEMENT, compilerOptions);
AddAttribute(shaderNode, DAE_STAGE_ATTRIBUTE, isFragment ? DAE_FXCMN_FRAGMENT_SHADER : DAE_FXCMN_VERTEX_SHADER);
if (!name.empty())
{
xmlNode* nameNode = AddChild(shaderNode, DAE_FXCMN_NAME_ELEMENT, name);
if (code != NULL) AddAttribute(nameNode, DAE_SOURCE_ATTRIBUTE, code->GetSid());
}
// Write out the bindings
for (FCDEffectPassBindList::const_iterator itB = bindings.begin(); itB != bindings.end(); ++itB)
{
const FCDEffectPassBind& b = (*itB);
if (!b.reference.empty() && !b.symbol.empty())
{
xmlNode* bindNode = AddChild(shaderNode, DAE_BIND_ELEMENT);
AddAttribute(bindNode, DAE_SYMBOL_ATTRIBUTE, b.symbol);
xmlNode* paramNode = AddChild(bindNode, DAE_PARAMETER_ELEMENT);
AddAttribute(paramNode, DAE_REF_ATTRIBUTE, b.reference);
}
}
return shaderNode;
}