/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FArchiveXML.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDExtra.h" #include "FCDocument/FCDLight.h" #include "FCDocument/FCDLightTools.h" bool FArchiveXML::LoadLight(FCDObject* object, xmlNode* lightNode) { if (!FArchiveXML::LoadTargetedEntity(object, lightNode)) return false; bool status = true; FCDLight* light = (FCDLight*)object; if (!IsEquivalent(lightNode->name, DAE_LIGHT_ELEMENT)) { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LIGHT_LIB_ELEMENT, lightNode->line); return status; } // Retrieve the element. xmlNode* commonTechniqueNode = FindChildByType(lightNode, DAE_TECHNIQUE_COMMON_ELEMENT); // Look for the , , or element under the common-profile technique xmlNode* lightParameterNode = NULL; for (xmlNode* child = commonTechniqueNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; if (IsEquivalent(child->name, DAE_LIGHT_POINT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::POINT); break; } else if (IsEquivalent(child->name, DAE_LIGHT_SPOT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::SPOT); break; } else if (IsEquivalent(child->name, DAE_LIGHT_AMBIENT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::AMBIENT); break; } else if (IsEquivalent(child->name, DAE_LIGHT_DIRECTIONAL_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::DIRECTIONAL); break; } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LT_ELEMENT, child->line); } } // Verify the light's basic structures are found if (lightParameterNode == NULL) { FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_ELEMENT, lightNode->line); } // Retrieve the common light parameters StringList parameterNames; xmlNodeList parameterNodes; FindParameters(lightParameterNode, parameterNames, parameterNodes); // Parse the common light parameters size_t parameterCount = parameterNodes.size(); for (size_t i = 0; i < parameterCount; ++i) { xmlNode* parameterNode = parameterNodes[i]; const fm::string& parameterName = parameterNames[i]; const char* content = ReadNodeContentDirect(parameterNode); if (parameterName == DAE_COLOR_LIGHT_PARAMETER) { light->SetColor(FUStringConversion::ToVector3(content)); FArchiveXML::LoadAnimatable(&light->GetColor(), parameterNode); } else if (parameterName == DAE_CONST_ATTENUATION_LIGHT_PARAMETER) { light->SetConstantAttenuationFactor(FUStringConversion::ToFloat(content)); FArchiveXML::LoadAnimatable(&light->GetConstantAttenuationFactor(), parameterNode); } else if (parameterName == DAE_LIN_ATTENUATION_LIGHT_PARAMETER) { light->SetLinearAttenuationFactor(FUStringConversion::ToFloat(content)); FArchiveXML::LoadAnimatable(&light->GetLinearAttenuationFactor(), parameterNode); } else if (parameterName == DAE_QUAD_ATTENUATION_LIGHT_PARAMETER) { light->SetQuadraticAttenuationFactor(FUStringConversion::ToFloat(content)); FArchiveXML::LoadAnimatable(&light->GetQuadraticAttenuationFactor(), parameterNode); } else if (parameterName == DAE_FALLOFFEXPONENT_LIGHT_PARAMETER) { light->SetFallOffExponent(FUStringConversion::ToFloat(content)); FArchiveXML::LoadAnimatable(&light->GetFallOffExponent(), parameterNode); } else if (parameterName == DAE_FALLOFFANGLE_LIGHT_PARAMETER) { light->SetFallOffAngle(FUStringConversion::ToFloat(content)); FArchiveXML::LoadAnimatable(&light->GetFallOffAngle(), parameterNode); } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LIGHT_PROG_PARAM, parameterNode->line); } } // Process and remove the known extra parameters StringList extraParameterNames; FCDENodeList extraParameters; FCDExtra* extra = light->GetExtra(); size_t techniqueCount = extra->GetDefaultType()->GetTechniqueCount(); for (size_t t = 0; t < techniqueCount; ++t) { FCDETechnique* technique = extra->GetDefaultType()->GetTechnique(t); technique->FindParameters(extraParameters, extraParameterNames); } FCDENode* penumbraNode = NULL; size_t extraParameterCount = extraParameters.size(); for (size_t p = 0; p < extraParameterCount; ++p) { FCDENode* extraParameterNode = extraParameters[p]; const fm::string& parameterName = extraParameterNames[p]; const fchar* content = extraParameterNode->GetContent(); FCDParameterAnimatableFloat* fpValue = NULL; if (parameterName == DAE_FALLOFFEXPONENT_LIGHT_PARAMETER) { fpValue = &light->GetFallOffExponent(); } else if (parameterName == DAE_FALLOFFANGLE_LIGHT_PARAMETER) { fpValue = &light->GetFallOffAngle(); } else if (parameterName == DAE_CONST_ATTENUATION_LIGHT_PARAMETER) { fpValue = &light->GetConstantAttenuationFactor(); } else if (parameterName == DAE_LIN_ATTENUATION_LIGHT_PARAMETER) { fpValue = &light->GetLinearAttenuationFactor(); } else if (parameterName == DAE_QUAD_ATTENUATION_LIGHT_PARAMETER) { fpValue = &light->GetQuadraticAttenuationFactor(); } else if (parameterName == DAEFC_INTENSITY_LIGHT_PARAMETER) { fpValue = &light->GetIntensity(); } else if (parameterName == DAEMAX_OUTERCONE_LIGHT_PARAMETER) { fpValue = &light->GetOuterAngle(); } else if (parameterName == DAEMAYA_PENUMBRA_LIGHT_PARAMETER) { // back-ward compatibility, penumbra is now represented with outerAngle and FallOffAngle penumbraNode = extraParameterNode; continue; // do not delete the parameter node since we need it for penumbra animations } else if (parameterName == DAEMAYA_DROPOFF_LIGHT_PARAMETER) { fpValue = &light->GetDropoff(); } else continue; // If we have requested a value, convert and animate it if (fpValue != NULL) { *fpValue = FUStringConversion::ToFloat(content); if (extraParameterNode->GetAnimated()->HasCurve()) { extraParameterNode->GetAnimated()->Clone(fpValue->GetAnimated()); } } // We have processed this extra node: remove it from the extra tree. SAFE_RELEASE(extraParameterNode); } if (penumbraNode != NULL) { float penumbraValue = FUStringConversion::ToFloat(penumbraNode->GetContent()); FCDAnimated* penumbraAnimatedValue = penumbraNode->GetAnimated(); FCDLightTools::LoadPenumbra(light, penumbraValue, penumbraAnimatedValue, false); SAFE_RELEASE(penumbraNode); } light->SetDirtyFlag(); return status; }