Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
ValidateMaterialPlugin.c
Go to the documentation of this file.
2{
3 static ref array<ResourceName> materials = new array<ResourceName>;
4 static ref array<ResourceName> textures = new array<ResourceName>;
5};
6
7
9{
10 // These dependencies are not using RGB colors
11 void CheckDependencies(BaseContainer mat, out MaterialValidatorResponse material_validator)
12 {
13 // dictionary Key(Map) -> Value(Params) that depends on that map
15 dependencies["NMOMap"] = {"NormalPower"};
16 dependencies["DetailNormalMap"] = {"DetailNormalPower"};
17 dependencies["GlobalNMOMap"] = {"NormalPower"};
18 dependencies["MudNMOMap"] = {"MudDetNormal"};
19 dependencies["NMO_4"] = {"DetNormal_4"};
20 dependencies["NMO_3"] = {"DetNormal_3"};
21 dependencies["NMO_2"] = {"DetNormal_2"};
22 dependencies["NMO_1"] = {"DetNormal_1"};
23 dependencies["MaskMap"] = {"MaskRedScale","MaskGreenScale","MaskBlueScale"};
24 dependencies["NTCMap"] = {"NormalPower"};
25 dependencies["NMOMap2"] = {"NormalPower2"};
26 dependencies["DetailNormalMap2"] = {"DetailNormalPower2"};
27
28
29 for(int i = 0; i < dependencies.Count(); i++)
30 {
31 string mapVarname = dependencies.GetKey(i);
32 // if map exists in the shader
33 if(mat.GetVarIndex(mapVarname) != -1)
34 {
35 string mapValue;
36 string paramValue;
37 string defaultValue;
38 array<string> depParam = dependencies.Get(mapVarname);
39 // iterate through all params of that map
40 foreach(string paramVarname: depParam)
41 {
42 // get values from the material
43 mat.Get(mapVarname, mapValue);
44 mat.Get(paramVarname, paramValue);
45 mat.GetDefaultAsString(paramVarname, defaultValue);
46 // Map is Null and Param is set with some value that is not zero
47 if(mapValue == "" && (paramValue != "" && paramValue != "0" && paramValue != defaultValue))
48 {
49 material_validator.reports.Insert(paramVarname + " was directly set but " + mapVarname + " is missing");
50 material_validator.severity.Insert(2);
51 }
52 // Map is set
53 else if(mapValue != "")
54 {
55 // get the value of the param even if default
56 GetValue(mat,paramVarname, paramValue);
57 // param is 0 and map is set
58 if(paramValue == "0")
59 {
60 material_validator.reports.Insert(mapVarname + " was directly set but " + paramVarname + " is 0");
61 material_validator.severity.Insert(2);
62 }
63 }
64 }
65 }
66 }
67 return;
68 }
69 // Dictionary what Slots can be used for each suffix
70 map<string,ref array<string>> GetTextureConnections()
71 {
73 suffixToSlots["BCR"] = {"BCRMap","BCR_1","BCR_2","BCR_3","BCR_4","MudBCRMap","DirtBCRMap","BCRMap2","EmissiveMap"};
74 suffixToSlots["NMO"] = {"NMOMap","NMO_1","NMO_2","NMO_3","NMO_4","MudNMOMap","NMOMap2","GlobalNMOMap","DetailNormalMap","DetailNormalMap2"};
75 suffixToSlots["N"] = suffixToSlots.Get("NMO");
76 suffixToSlots["MCR"] = {"MCRMap","GlobalMCRMap","GlobalMCMap","MacroMap"};
77 suffixToSlots["NHO"] = suffixToSlots.Get("NMO");
78 suffixToSlots["MC"] = suffixToSlots.Get("MCR");
79 suffixToSlots["MC"].Insert("GlobalMCMap");
80 suffixToSlots["NTC"] = {"NTCMap"};
81 suffixToSlots["MLOD"] = {"BCRMap"};
82 suffixToSlots["VFX"] = {"VFX","VFXMap"};
83 suffixToSlots["MASK"] = {"MaskMap","Mask_2","Mask_3","Mask_4","DirtMaskMap","MudMaskMap","SubsurfaceMask"};
84 suffixToSlots["A"] = {"OpacityMap","HeightMap"};
85 suffixToSlots["CRM"] = {"CamoCRMMap"};
86 suffixToSlots["EM"] = {"EmissiveMap","ProjectionMap"};
87 suffixToSlots["H"] = {"HeightMap","PuddleHeightMap"};
88 return suffixToSlots;
89 }
90
91 // Checks if the right map is in the right slot (ex. _BCR/_MLOD in BCR Map)
92 void CheckSlots(string slot, string suffix, out MaterialValidatorResponse material_validator)
93 {
94 // Dictionary SUFFIX:[SLOT,SLOT,SLOT,..]
95 map<string,ref array<string>> connections = GetTextureConnections();
96
97
98 // get value of the suffix key (What slots can be used for the suffix)
99 array<string> slots = connections.Get(suffix);
100 // If array not null => Suffix is supported
101 // and if it doesnt contain the slot, it is wrong
102 if(slots && !slots.Contains(slot))
103 {
104 material_validator.reports.Insert("Texture with suffix " + suffix + " is in " + slot);
105 material_validator.severity.Insert(3);
106 }
107 }
108
109
110 // Checks parameters that should stay as default values(General tab, Wetness, etc..)
111 void CheckDefaults(BaseContainer cont,out MaterialValidatorResponse material_validator)
112 {
113 //https://confluence.bistudio.com/display/~phammac/Typos+in+Workbanch+parametrs
114 //DisableUserAphaInShadow
115 // Doesnt need to clear the array, since its initialized everytime the function is called
116 array<string> DefaultProperties = {"ZEnable", "ZBias", "Cull", "Sort", "SortBias", "CastShadow", "ReceiveShadow", "OccludeRain",
117 "OccludeWetness", "AddWetness", "DisableFog", "DisableInteriorProbes", "TCModFuncs", "NoDecals", "EnableClutter", "ClutterThresholdAngle",
118 "CrossFade", "WetnessScale", "PorosityScale", "CustomWetnessChannel", "SlidingDropsVisibility" };
119
120 array<string> allDefaultProperties = {"ZEnable","ZBias","Cull","Sort","SortBias","CastShadow","ReceiveShadow","OccludeRain","OccludeWetness",
121 "AddWetness","DisableFog","DisableInteriorProbes","TCModFuncs","NoDecals","EnableClutter","ClutterThresholdAngle","CrossFade",
122 "WetnessScale","PorosityScale","CustomWetnessChannel","SlidingDropsVisibility","ZWrite","AlphaTest","AlphaMul","BlendMode","AllowUserAlphaBias","BisableUserAphaInShadow","ManualCascadesShadows"};
123 string matClass = cont.GetClassName();
124 for(int i = 0; i < cont.GetNumVars(); i++)
125 {
126 string var = cont.GetVarName(i);
127 // if the prop is in General props that should be checked, check if it's set directly
128 if(allDefaultProperties.Contains(var) && cont.IsVariableSetDirectly(var))
129 {
130 material_validator.reports.Insert(var + " doesn't match the default settings");
131 material_validator.severity.Insert(1);
132 }
133 }
134 }
135
136 // Cont.Get but it if it's not set it will return default, not empty string
137 void GetValue(BaseContainer cont, string varName, out string value)
138 {
139 // get value the normal way
140 cont.Get(varName, value);
141 // if the value is empty and variable is not set get default
142 if(!cont.IsVariableSetDirectly(varName) && value == "")
143 {
144 cont.GetDefaultAsString(varName, value);
145 }
146 return;
147 }
148
149
150 // Checking all validations for all textures on material
151 void CheckTextures(BaseContainer cont, out MaterialValidatorResponse material_validator)
152 {
153 array<string> slots = {};
154 string absPath;
155 // going through properties of emat
156 for(int i = 0; i < cont.GetNumVars(); i++)
157 {
158 string var = cont.GetVarName(i);
159 ResourceName value;
160 cont.Get(var, value);
161 // get edds in emat
162 if(value.Contains(".edds"))
163 {
164 // texture value will be with anim, removing that
165 if(value.EndsWith(" 0"))
166 {
167 value = value.Substring(0, value.Length() - 2);
168 }
169
170 // checking GUID
171 string guid = value.Substring(0,18);
172 string guidtest = Workbench.GetResourceName(guid);
173 if(guid == guidtest)
174 {
175 material_validator.reports.Insert(cont.GetResourceName() + " has a wrong guid!");
176 material_validator.severity.Insert(3);
177 return;
178 }
179
180 // meta of the edds to get the right extesion
181 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
182 MetaFile meta = resourceManager.GetMetaFile(value.GetPath());
183 if(!meta)
184 {
185 material_validator.reports.Insert("Metafile for " + value + "(" + var + ") couldn't be found!");
186 material_validator.severity.Insert(3);
187 continue;
188 }
189 BaseContainerList configurations = meta.GetObjectArray("Configurations");
190 BaseContainer cfg = configurations.Get(0);
191
192 // getting extension from edds
193 string extension = cfg.GetClassName().Substring(0,3);
194 // need to get relative path for texture validator class
195 Workbench.GetAbsolutePath(value.GetPath(),absPath);
196 extension.ToLower();
197 absPath.Replace("edds",extension);
198
199 // if texture was selected and also in a material that was selected, the texture errors will be reported twice
200 // this removes the texture from validating textures itself and validates it only once with the material
201 if(ValidateMaterialPlugin.textures.Contains(absPath))
202 {
203 ValidateMaterialPlugin.textures.RemoveItem(absPath);
204 }
205
206
207 // absolute path of texture with right extension(.tif, etc..) for python
208 material_validator.abs_textures.Insert(absPath);
209 // texture suffix and its slot
210 string suffix = FilePath.StripPath(value);
211
212 suffix = suffix.Substring(suffix.LastIndexOf("_")+1, suffix.LastIndexOf(".") - suffix.LastIndexOf("_")-1);
213 string slot = var;
214 slots.Insert(slot);
215 // this is removing int from Mask1 => Mask. But I can add Mask1/2 into the dict..
216 if(suffix[suffix.Length() - 1].ToInt())
217 {
218 suffix = suffix.Substring(0,suffix.Length()-1);
219 }
220
221 CheckSlots(slot,suffix, material_validator);
222 }
223 }
224 return;
225 }
226
227 // Check extreme values of properties (NormalPower,etc...)
228 void CheckExtremes(BaseContainer cont, float min, float max,out MaterialValidatorResponse material_validator)
229 {
230 array<string> properties = {"NormalPower","MudDetNormal","DetNormal_1","DetNormal_2","DetNormal_3","DetNormal_4","DetailNormalPower","DetailNormalPower2",
231 "DetailMaskSharpness","DetailMaskOffset","DetailMaskUVScale","NormalPower2","RoughnessScale2","MetalnessScale2","RoughnessScale","MetalnessScale",
232 "MudRoughness","MudMetalness","Roughness1","Metalness_1","Roughness_2","Metalness_2","Roughness_3","Metalness_3","Roughness_4","Metalness_4",
233 "AO_1","AO_2","AO_3","AO_4",};
234 foreach(string property: properties)
235 {
236 string value;
237 // have to check if the property exists in the shader
238 if(cont.GetVarIndex(property) != -1)
239 {
240 cont.Get(property,value);
241 if(value != "" || cont.IsVariableSetDirectly(property))
242 {
243 float limitMin;
244 float limitMax;
245 float step;
246 cont.GetLimits(cont.GetVarIndex(property),limitMin,limitMax, step);
247 float newMin = limitMax * (min / 100);
248 float newMax = limitMax * (max / 100);
249 if((value.ToFloat() < newMin || value.ToFloat() > newMax) && (value.ToFloat() != 0))
250 {
251 material_validator.reports.Insert(property + " is out of limitation(" + newMin + "-" + newMax + ")");
252 material_validator.severity.Insert(2);
253 }
254 }
255 }
256 }
257 }
258
259 // Validates material UVs (Unified, Extremes)
260 void ValidateUVs(BaseContainer cont, float MinTiling, float MaxTiling,out MaterialValidatorResponse material_validator)
261 {
262 BaseContainer empty;
263
264 for(int i = 0; i < cont.GetNumVars(); i++)
265 {
266 string var = cont.GetVarName(i);
267 // getting object
268 if(cont.GetObject(var) != empty)
269 {
270 BaseContainer uvTiling = cont.GetObject(var);
271 // checking if the object is UV Transforms
272 if(uvTiling.GetClassName() == "MatUVTransform")
273 {
274 string tilingU, tilingV;
275 GetValue(uvTiling, "TilingU", tilingU);
276 GetValue(uvTiling, "TilingV", tilingV);
277 // UV tiling uniform
278 if(tilingU != tilingV)
279 {
280 material_validator.reports.Insert("UV Tiling on " + var + " is not uniform.");
281 material_validator.severity.Insert(2);
282 }
283 // UV tiling limits
284 if(MinTiling > tilingU.ToFloat() || MaxTiling < Math.AbsFloat(tilingU.ToFloat()))
285 {
286 material_validator.reports.Insert("UV Tiling on " + var + " is out of limitation, U = " + tilingU);
287 material_validator.severity.Insert(2);
288 }
289 if(MinTiling > tilingV.ToFloat() || MaxTiling < Math.AbsFloat(tilingV.ToFloat()))
290 {
291 material_validator.reports.Insert("UV Tiling on " + var + " is out of limitation, V = " + tilingV);
292 material_validator.severity.Insert(2);
293 }
294
295 }
296 }
297 string value;
298 cont.Get(var, value);
299 }
300 return;
301 }
302}
303
305{
308 {
309 RegV("mat_index");
310 }
311};
312
313
314class MaterialValidatorResponse: JsonApiStruct
315{
316 ref array<string> abs_textures = new array<string>();
317 ref array<string> reports = new array<string>();
318 ref array<int> severity = new array<int>();
319 string mat_name;
320
321 void MaterialValidatorResponse()
322 {
323 RegV("abs_textures");
324 RegV("reports");
325 RegV("severity");
326 RegV("mat_name");
327 }
328};
329
330class MaterialValidator: NetApiHandler
331{
332 override JsonApiStruct GetRequest()
333 {
334 return new MaterialValidatorRequest();
335 }
336
337 override JsonApiStruct GetResponse(JsonApiStruct request)
338 {
342
343 Resource resource = Resource.Load(ValidateMaterialPlugin.materials[req.mat_index]);
344 BaseContainer material = resource.GetResource().ToBaseContainer();
345 material_report.mat_name = material.GetName();
346
347 const int uv_min = 0;
348 const int uv_max = 5;
349 const int ext_min = 5;
350 const int ext_max = 95;
351
352 matValid.ValidateUVs(material, uv_min, uv_max, material_report); //Done
353 matValid.CheckDefaults(material, material_report);
354 matValid.CheckExtremes(material,ext_min,ext_max, material_report);
355 matValid.CheckDependencies(material, material_report);
356 matValid.CheckTextures(material, material_report);
357 return material_report;
358 }
359}
360
361
362
363
365{
368 {
369 RegV("texture_path");
370 }
371};
372
373class TextureValidatorResponse: JsonApiStruct
374{
375 ref array<string> reports = new array<string>();
376 ref array<int> severity = new array<int>();
377
378 void TextureValidatorResponse()
379 {
380 RegV("reports");
381 RegV("severity");
382 }
383};
384
385class TextureValidator: NetApiHandler
386{
387
388 void TextureImportSettings(string abs_texture_path, out TextureValidatorResponse checks)
389 {
390 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
391 MetaFile meta = resourceManager.GetMetaFile(abs_texture_path);
392
393 BaseContainerList configurations = meta.GetObjectArray("Configurations");
394 BaseContainer cfg = configurations.Get(0);
395
396 for(int i = 0; i < cfg.GetNumVars(); i++)
397 {
398 string var = cfg.GetVarName(i);
399 if(cfg.IsVariableSetDirectly(var))
400 {
401 checks.reports.Insert("Has some changes in default import config!");
402 checks.severity.Insert(1);
403 }
404 }
405
406 TextureTypes textureTypes = new TextureTypes();
407 TextureType type = textureTypes.FindTextureType(abs_texture_path);
408
409 if(type.m_PostFix == string.Empty)
410 {
411 checks.reports.Insert("Has invalid suffix!");
412 checks.severity.Insert(3);
413 }
414 return;
415 }
416
417 override JsonApiStruct GetRequest()
418 {
419 return new TextureValidatorRequest();
420 }
421
422 override JsonApiStruct GetResponse(JsonApiStruct request)
423 {
426
427 TextureImportSettings(req.texture_path, response);
428 return response;
429 }
430}
SCR_AICombatMoveRequestBase GetRequest()
EDamageType type
override int GetValue()
void MaterialValidatorRequest()
MaterialValidator texture_path
class MaterialValidatorUtils mat_index
void TextureValidatorRequest()
base classes for filtering in server browser
Definition Math.c:13
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
Definition Types.c:486