1 /*
2 	Copyright (C) 2005-2007 Feeling Software Inc.
3 	Portions of the code are:
4 	Copyright (C) 2005-2007 Sony Computer Entertainment America
5 
6 	MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8 
9 #include "StdAfx.h"
10 #include "FArchiveXML.h"
11 #include "FCDocument/FCDAnimated.h"
12 #include "FCDocument/FCDExtra.h"
13 #include "FCDocument/FCDLight.h"
14 #include "FCDocument/FCDLightTools.h"
15 
LoadLight(FCDObject * object,xmlNode * lightNode)16 bool FArchiveXML::LoadLight(FCDObject* object, xmlNode* lightNode)
17 {
18 	if (!FArchiveXML::LoadTargetedEntity(object, lightNode)) return false;
19 
20 	bool status = true;
21 	FCDLight* light = (FCDLight*)object;
22 	if (!IsEquivalent(lightNode->name, DAE_LIGHT_ELEMENT))
23 	{
24 		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LIGHT_LIB_ELEMENT, lightNode->line);
25 		return status;
26 	}
27 
28 	// Retrieve the <technique_common> element.
29 	xmlNode* commonTechniqueNode = FindChildByType(lightNode, DAE_TECHNIQUE_COMMON_ELEMENT);
30 
31 	// Look for the <point>, <directional>, <spot> or <ambient> element under the common-profile technique
32 	xmlNode* lightParameterNode = NULL;
33 	for (xmlNode* child = commonTechniqueNode->children; child != NULL; child = child->next)
34 	{
35 		if (child->type != XML_ELEMENT_NODE) continue;
36 		if (IsEquivalent(child->name, DAE_LIGHT_POINT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::POINT); break; }
37 		else if (IsEquivalent(child->name, DAE_LIGHT_SPOT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::SPOT); break; }
38 		else if (IsEquivalent(child->name, DAE_LIGHT_AMBIENT_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::AMBIENT); break; }
39 		else if (IsEquivalent(child->name, DAE_LIGHT_DIRECTIONAL_ELEMENT)) { lightParameterNode = child; light->SetLightType(FCDLight::DIRECTIONAL); break; }
40 		else
41 		{
42 			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LT_ELEMENT, child->line);
43 		}
44 	}
45 
46 	// Verify the light's basic structures are found
47 	if (lightParameterNode == NULL)
48 	{
49 		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_ELEMENT, lightNode->line);
50 	}
51 
52 	// Retrieve the common light parameters
53 	StringList parameterNames;
54 	xmlNodeList parameterNodes;
55 	FindParameters(lightParameterNode, parameterNames, parameterNodes);
56 
57 	// Parse the common light parameters
58 	size_t parameterCount = parameterNodes.size();
59 	for (size_t i = 0; i < parameterCount; ++i)
60 	{
61 		xmlNode* parameterNode = parameterNodes[i];
62 		const fm::string& parameterName = parameterNames[i];
63 		const char* content = ReadNodeContentDirect(parameterNode);
64 		if (parameterName == DAE_COLOR_LIGHT_PARAMETER)
65 		{
66 			light->SetColor(FUStringConversion::ToVector3(content));
67 			FArchiveXML::LoadAnimatable(&light->GetColor(), parameterNode);
68 		}
69 		else if (parameterName == DAE_CONST_ATTENUATION_LIGHT_PARAMETER)
70 		{
71 			light->SetConstantAttenuationFactor(FUStringConversion::ToFloat(content));
72 			FArchiveXML::LoadAnimatable(&light->GetConstantAttenuationFactor(), parameterNode);
73 		}
74 		else if (parameterName == DAE_LIN_ATTENUATION_LIGHT_PARAMETER)
75 		{
76 			light->SetLinearAttenuationFactor(FUStringConversion::ToFloat(content));
77 			FArchiveXML::LoadAnimatable(&light->GetLinearAttenuationFactor(), parameterNode);
78 		}
79 		else if (parameterName == DAE_QUAD_ATTENUATION_LIGHT_PARAMETER)
80 		{
81 			light->SetQuadraticAttenuationFactor(FUStringConversion::ToFloat(content));
82 			FArchiveXML::LoadAnimatable(&light->GetQuadraticAttenuationFactor(), parameterNode);
83 		}
84 		else if (parameterName == DAE_FALLOFFEXPONENT_LIGHT_PARAMETER)
85 		{
86 			light->SetFallOffExponent(FUStringConversion::ToFloat(content));
87 			FArchiveXML::LoadAnimatable(&light->GetFallOffExponent(), parameterNode);
88 		}
89 		else if (parameterName == DAE_FALLOFFANGLE_LIGHT_PARAMETER)
90 		{
91 			light->SetFallOffAngle(FUStringConversion::ToFloat(content));
92 			FArchiveXML::LoadAnimatable(&light->GetFallOffAngle(), parameterNode);
93 		}
94 		else
95 		{
96 			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_LIGHT_PROG_PARAM, parameterNode->line);
97 		}
98 	}
99 
100 	// Process and remove the known extra parameters
101 	StringList extraParameterNames;
102 	FCDENodeList extraParameters;
103 	FCDExtra* extra = light->GetExtra();
104 	size_t techniqueCount = extra->GetDefaultType()->GetTechniqueCount();
105 	for (size_t t = 0; t < techniqueCount; ++t)
106 	{
107 		FCDETechnique* technique = extra->GetDefaultType()->GetTechnique(t);
108 		technique->FindParameters(extraParameters, extraParameterNames);
109 	}
110 
111 	FCDENode* penumbraNode = NULL;
112 
113 	size_t extraParameterCount = extraParameters.size();
114 	for (size_t p = 0; p < extraParameterCount; ++p)
115 	{
116 		FCDENode* extraParameterNode = extraParameters[p];
117 		const fm::string& parameterName = extraParameterNames[p];
118 		const fchar* content = extraParameterNode->GetContent();
119 		FCDParameterAnimatableFloat* fpValue = NULL;
120 
121 		if (parameterName == DAE_FALLOFFEXPONENT_LIGHT_PARAMETER)
122 		{
123 			fpValue = &light->GetFallOffExponent();
124 		}
125 		else if (parameterName == DAE_FALLOFFANGLE_LIGHT_PARAMETER)
126 		{
127 			fpValue = &light->GetFallOffAngle();
128 		}
129 		else if (parameterName == DAE_CONST_ATTENUATION_LIGHT_PARAMETER)
130 		{
131 			fpValue = &light->GetConstantAttenuationFactor();
132 		}
133 		else if (parameterName == DAE_LIN_ATTENUATION_LIGHT_PARAMETER)
134 		{
135 			fpValue = &light->GetLinearAttenuationFactor();
136 		}
137 		else if (parameterName == DAE_QUAD_ATTENUATION_LIGHT_PARAMETER)
138 		{
139 			fpValue = &light->GetQuadraticAttenuationFactor();
140 		}
141 		else if (parameterName == DAEFC_INTENSITY_LIGHT_PARAMETER)
142 		{
143 			fpValue = &light->GetIntensity();
144 		}
145 		else if (parameterName == DAEMAX_OUTERCONE_LIGHT_PARAMETER)
146 		{
147 			fpValue = &light->GetOuterAngle();
148 		}
149 		else if (parameterName == DAEMAYA_PENUMBRA_LIGHT_PARAMETER)
150 		{
151 			// back-ward compatibility, penumbra is now represented with outerAngle and FallOffAngle
152 			penumbraNode = extraParameterNode;
153 			continue; // do not delete the parameter node since we need it for penumbra animations
154 		}
155 		else if (parameterName == DAEMAYA_DROPOFF_LIGHT_PARAMETER)
156 		{
157 			fpValue = &light->GetDropoff();
158 		}
159 		else continue;
160 
161 		// If we have requested a value, convert and animate it
162 		if (fpValue != NULL)
163 		{
164 			*fpValue = FUStringConversion::ToFloat(content);
165 			if (extraParameterNode->GetAnimated()->HasCurve())
166 			{
167 				extraParameterNode->GetAnimated()->Clone(fpValue->GetAnimated());
168 			}
169 		}
170 
171 		// We have processed this extra node: remove it from the extra tree.
172 		SAFE_RELEASE(extraParameterNode);
173 	}
174 
175 	if (penumbraNode != NULL)
176 	{
177 		float penumbraValue = FUStringConversion::ToFloat(penumbraNode->GetContent());
178 		FCDAnimated* penumbraAnimatedValue = penumbraNode->GetAnimated();
179 		FCDLightTools::LoadPenumbra(light, penumbraValue, penumbraAnimatedValue, false);
180 		SAFE_RELEASE(penumbraNode);
181 	}
182 
183 	light->SetDirtyFlag();
184 	return status;
185 }
186