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