!I (1670414, 1670415, 1670416, 1670424, 1670431):
[CRYENGINE.git] / Code / Sandbox / EditorQt / Material / MaterialPythonFuncs.cpp
blobdb6aaa70f416b5fdf7a223d32ac9290ae3c9b080
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "Material/MaterialManager.h"
5 #include "Material/MaterialHelpers.h"
6 #include "Util/BoostPythonHelpers.h"
7 #include "Util/MFCUtil.h"
9 namespace
11 void PyMaterialCreate()
13 GetIEditorImpl()->GetMaterialManager()->Command_Create();
16 void PyMaterialCreateMulti()
18 GetIEditorImpl()->GetMaterialManager()->Command_CreateMulti();
21 void PyMaterialConvertToMulti()
23 GetIEditorImpl()->GetMaterialManager()->Command_ConvertToMulti();
26 void PyMaterialDuplicateCurrent()
28 GetIEditorImpl()->GetMaterialManager()->Command_Duplicate();
31 void PyMaterialMergeSelection()
33 GetIEditorImpl()->GetMaterialManager()->Command_Merge();
36 void PyMaterialDeleteCurrent()
38 GetIEditorImpl()->GetMaterialManager()->Command_Delete();
41 void PyCreateTerrainLayer()
43 GetIEditorImpl()->GetMaterialManager()->Command_CreateTerrainLayer();
46 void PyMaterialAssignCurrentToSelection()
48 CUndo undo("Assign Material To Selection");
49 GetIEditorImpl()->GetMaterialManager()->Command_AssignToSelection();
52 void PyMaterialResetSelection()
54 GetIEditorImpl()->GetMaterialManager()->Command_ResetSelection();
57 void PyMaterialSelectObjectsWithCurrent()
59 CUndo undo("Select Objects With Current Material");
60 GetIEditorImpl()->GetMaterialManager()->Command_SelectAssignedObjects();
63 void PyMaterialSetCurrentFromObject()
65 GetIEditorImpl()->GetMaterialManager()->Command_SelectFromObject();
68 std::vector<std::string> PyGetSubMaterial(const char* pMaterialPath)
70 string materialPath = pMaterialPath;
71 CMaterial* pMaterial = GetIEditorImpl()->GetMaterialManager()->LoadMaterial(pMaterialPath, false);
72 if (!pMaterial)
74 throw std::runtime_error("Invalid multi material.");
77 std::vector<std::string> result;
78 for (int i = 0; i < pMaterial->GetSubMaterialCount(); i++)
80 if (pMaterial->GetSubMaterial(i))
82 result.push_back(static_cast<std::string>(materialPath + "\\" + pMaterial->GetSubMaterial(i)->GetName()));
85 return result;
88 CMaterial* TryLoadingMaterial(const char* pPathAndMaterialName)
90 CString varMaterialPath = pPathAndMaterialName;
91 std::deque<string> splittedMaterialPath;
92 int currentPos = 0;
93 for (string token = varMaterialPath.Tokenize("/\\", currentPos); !token.IsEmpty(); token = varMaterialPath.Tokenize("/\\", currentPos))
95 splittedMaterialPath.push_back(token);
98 CMaterial* pMaterial = GetIEditorImpl()->GetMaterialManager()->LoadMaterial(varMaterialPath, false);
99 if (!pMaterial)
101 string subMaterialName = splittedMaterialPath.back();
102 bool isSubMaterialExist(false);
104 varMaterialPath.Delete((varMaterialPath.GetLength() - subMaterialName.GetLength() - 1), varMaterialPath.GetLength());
105 string test = varMaterialPath;
106 pMaterial = GetIEditorImpl()->GetMaterialManager()->LoadMaterial(varMaterialPath, false);
108 if (!pMaterial)
110 throw std::runtime_error("Invalid multi material.");
113 for (int i = 0; i < pMaterial->GetSubMaterialCount(); i++)
115 if (pMaterial->GetSubMaterial(i)->GetName() == subMaterialName)
117 pMaterial = pMaterial->GetSubMaterial(i);
118 isSubMaterialExist = true;
122 if (!pMaterial || !isSubMaterialExist)
124 throw std::runtime_error(string("\"") + subMaterialName + "\" is an invalid sub material.");
127 GetIEditorImpl()->GetMaterialManager()->SetCurrentMaterial(pMaterial);
128 return pMaterial;
131 std::deque<string> PreparePropertyPath(const char* pPathAndPropertyName)
133 string varPathProperty = pPathAndPropertyName;
134 std::deque<string> splittedPropertyPath;
135 int currentPos = 0;
136 for (string token = varPathProperty.Tokenize("/\\", currentPos); !token.IsEmpty(); token = varPathProperty.Tokenize("/\\", currentPos))
138 splittedPropertyPath.push_back(token);
141 return splittedPropertyPath;
144 //////////////////////////////////////////////////////////////////////////
145 // Converter: Enum -> string (human readable)
146 //////////////////////////////////////////////////////////////////////////
148 string TryConvertingSEFResTextureToCString(SEfResTexture* pResTexture)
150 if (pResTexture)
152 return pResTexture->m_Name.c_str();
154 return "";
157 string TryConvertingETEX_TypeToCString(const uint8& texTypeName)
159 if (MaterialHelpers::IsTextureTypeExposed(texTypeName))
161 return MaterialHelpers::GetNameFromTextureType(texTypeName);
163 throw std::runtime_error("Invalid tex type.");
166 string TryConvertingTexFilterToCString(const int& iFilterName)
168 switch (iFilterName)
170 case FILTER_NONE:
171 return "Default";
172 case FILTER_POINT:
173 return "Point";
174 case FILTER_LINEAR:
175 return "Linear";
176 case FILTER_BILINEAR:
177 return "Bi-linear";
178 case FILTER_TRILINEAR:
179 return "Tri-linear";
180 case FILTER_ANISO2X:
181 return "Anisotropic 2x";
182 case FILTER_ANISO4X:
183 return "Anisotropic 4x";
184 case FILTER_ANISO8X:
185 return "Anisotropic 8x";
186 case FILTER_ANISO16X:
187 return "Anisotropic 16x";
188 default:
189 throw std::runtime_error("Invalid tex filter.");
193 string TryConvertingETexGenTypeToCString(const uint8& texGenType)
195 switch (texGenType)
197 case ETG_Stream:
198 return "Stream";
199 case ETG_World:
200 return "World";
201 case ETG_Camera:
202 return "Camera";
203 default:
204 throw std::runtime_error("Invalid tex gen type.");
208 string TryConvertingETexModRotateTypeToCString(const uint8& rotateType)
210 switch (rotateType)
212 case ETMR_NoChange:
213 return "No Change";
214 case ETMR_Fixed:
215 return "Fixed Rotation";
216 case ETMR_Constant:
217 return "Constant Rotation";
218 case ETMR_Oscillated:
219 return "Oscillated Rotation";
220 default:
221 throw std::runtime_error("Invalid rotate type.");
225 string TryConvertingETexModMoveTypeToCString(const uint8& oscillatorType)
227 switch (oscillatorType)
229 case ETMM_NoChange:
230 return "No Change";
231 case ETMM_Fixed:
232 return "Fixed Moving";
233 case ETMM_Constant:
234 return "Constant Moving";
235 case ETMM_Jitter:
236 return "Jitter Moving";
237 case ETMM_Pan:
238 return "Pan Moving";
239 case ETMM_Stretch:
240 return "Stretch Moving";
241 case ETMM_StretchRepeat:
242 return "Stretch-Repeat Moving";
243 default:
244 throw std::runtime_error("Invalid oscillator type.");
248 string TryConvertingEDeformTypeToCString(const EDeformType& deformType)
250 switch (deformType)
252 case eDT_Unknown:
253 return "None";
254 case eDT_SinWave:
255 return "Sin Wave";
256 case eDT_SinWaveUsingVtxColor:
257 return "Sin Wave using vertex color";
258 case eDT_Bulge:
259 return "Bulge";
260 case eDT_Squeeze:
261 return "Squeeze";
262 case eDT_Perlin2D:
263 return "Perlin 2D";
264 case eDT_Perlin3D:
265 return "Perlin 3D";
266 case eDT_FromCenter:
267 return "From Center";
268 case eDT_Bending:
269 return "Bending";
270 case eDT_ProcFlare:
271 return "Proc. Flare";
272 case eDT_AutoSprite:
273 return "Auto sprite";
274 case eDT_Beam:
275 return "Beam";
276 case eDT_FixedOffset:
277 return "FixedOffset";
278 default:
279 throw std::runtime_error("Invalid deform type.");
283 string TryConvertingEWaveFormToCString(const EWaveForm& waveForm)
285 switch (waveForm)
287 case eWF_None:
288 return "None";
289 case eWF_Sin:
290 return "Sin";
291 case eWF_HalfSin:
292 return "Half Sin";
293 case eWF_Square:
294 return "Square";
295 case eWF_Triangle:
296 return "Triangle";
297 case eWF_SawTooth:
298 return "Saw Tooth";
299 case eWF_InvSawTooth:
300 return "Inverse Saw Tooth";
301 case eWF_Hill:
302 return "Hill";
303 case eWF_InvHill:
304 return "Inverse Hill";
305 default:
306 throw std::runtime_error("Invalid wave form.");
310 //////////////////////////////////////////////////////////////////////////
311 // Converter: string -> Enum
312 //////////////////////////////////////////////////////////////////////////
314 EEfResTextures TryConvertingCStringToEEfResTextures(const string& resTextureName)
316 if (resTextureName == "Diffuse")
318 return EFTT_DIFFUSE;
320 else if (resTextureName == "Specular")
322 return EFTT_SPECULAR;
324 else if (resTextureName == "Bumpmap")
326 return EFTT_NORMALS;
328 else if (resTextureName == "Heightmap")
330 return EFTT_HEIGHT;
332 else if (resTextureName == "Environment")
334 return EFTT_ENV;
336 else if (resTextureName == "Detail")
338 return EFTT_DETAIL_OVERLAY;
340 else if (resTextureName == "Opacity")
342 return EFTT_OPACITY;
344 else if (resTextureName == "Decal")
346 return EFTT_DECAL_OVERLAY;
348 else if (resTextureName == "SubSurface")
350 return EFTT_SUBSURFACE;
352 else if (resTextureName == "Custom")
354 return EFTT_CUSTOM;
356 else if (resTextureName == "[1] Custom")
358 return EFTT_DIFFUSE;
360 else if (resTextureName == "Emittance")
362 return EFTT_EMITTANCE;
364 throw std::runtime_error("Invalid texture name.");
367 ETEX_Type TryConvertingCStringToETEX_Type(const string& texTypeName)
369 ETEX_Type texType = (ETEX_Type)MaterialHelpers::GetTextureTypeFromName(texTypeName);
370 if (texType == eTT_MaxTexType || !MaterialHelpers::IsTextureTypeExposed(texType))
372 throw std::runtime_error("Invalid tex type name.");
374 return texType;
377 signed char TryConvertingCStringToTexFilter(string filterName)
379 if (filterName == "Default")
381 return FILTER_NONE;
383 else if (filterName == "Point")
385 return FILTER_POINT;
387 else if (filterName == "Linear")
389 return FILTER_LINEAR;
391 else if (filterName == "Bi-linear")
393 return FILTER_BILINEAR;
395 else if (filterName == "Tri-linear")
397 return FILTER_TRILINEAR;
399 else if (filterName == "Anisotropic 2x")
401 return FILTER_ANISO2X;
403 else if (filterName == "Anisotropic 4x")
405 return FILTER_ANISO4X;
407 else if (filterName == "Anisotropic 8x")
409 return FILTER_ANISO8X;
411 else if (filterName == "Anisotropic 16x")
413 return FILTER_ANISO16X;
415 throw std::runtime_error("Invalid filter name.");
418 ETexGenType TryConvertingCStringToETexGenType(const string& texGenType)
420 if (texGenType == "Stream")
422 return ETG_Stream;
424 else if (texGenType == "World")
426 return ETG_World;
428 else if (texGenType == "Camera")
430 return ETG_Camera;
432 throw std::runtime_error("Invalid tex gen type name.");
435 ETexModRotateType TryConvertingCStringToETexModRotateType(const string& rotateType)
437 if (rotateType == "No Change")
439 return ETMR_NoChange;
441 else if (rotateType == "Fixed Rotation")
443 return ETMR_Fixed;
445 else if (rotateType == "Constant Rotation")
447 return ETMR_Constant;
449 else if (rotateType == "Oscillated Rotation")
451 return ETMR_Oscillated;
453 throw std::runtime_error("Invalid rotate type name.");
456 ETexModMoveType TryConvertingCStringToETexModMoveType(const string& oscillatorType)
458 if (oscillatorType == "No Change")
460 return ETMM_NoChange;
462 else if (oscillatorType == "Fixed Moving")
464 return ETMM_Fixed;
466 else if (oscillatorType == "Constant Moving")
468 return ETMM_Constant;
470 else if (oscillatorType == "Jitter Moving")
472 return ETMM_Jitter;
474 else if (oscillatorType == "Pan Moving")
476 return ETMM_Pan;
478 else if (oscillatorType == "Stretch Moving")
480 return ETMM_Stretch;
482 else if (oscillatorType == "Stretch-Repeat Moving")
484 return ETMM_StretchRepeat;
486 throw std::runtime_error("Invalid oscillator type.");
489 EDeformType TryConvertingCStringToEDeformType(const string& deformType)
491 if (deformType == "None")
493 return eDT_Unknown;
495 else if (deformType == "Sin Wave")
497 return eDT_SinWave;
499 else if (deformType == "Sin Wave using vertex color")
501 return eDT_SinWaveUsingVtxColor;
503 else if (deformType == "Bulge")
505 return eDT_Bulge;
507 else if (deformType == "Squeeze")
509 return eDT_Squeeze;
511 else if (deformType == "Perlin 2D")
513 return eDT_Perlin2D;
515 else if (deformType == "Perlin 3D")
517 return eDT_Perlin3D;
519 else if (deformType == "From Center")
521 return eDT_FromCenter;
523 else if (deformType == "Bending")
525 return eDT_Bending;
527 else if (deformType == "Proc. Flare")
529 return eDT_ProcFlare;
531 else if (deformType == "Auto sprite")
533 return eDT_AutoSprite;
535 else if (deformType == "Beam")
537 return eDT_Beam;
539 else if (deformType == "FixedOffset")
541 return eDT_FixedOffset;
543 throw std::runtime_error("Invalid deform type.");
546 EWaveForm TryConvertingCStringToEWaveForm(const string& waveForm)
548 if (waveForm == "None")
550 return eWF_None;
552 else if (waveForm == "Sin")
554 return eWF_Sin;
556 else if (waveForm == "Half Sin")
558 return eWF_HalfSin;
560 else if (waveForm == "Square")
562 return eWF_Square;
564 else if (waveForm == "Triangle")
566 return eWF_Triangle;
568 else if (waveForm == "Saw Tooth")
570 return eWF_SawTooth;
572 else if (waveForm == "Inverse Saw Tooth")
574 return eWF_InvSawTooth;
576 else if (waveForm == "Hill")
578 return eWF_Hill;
580 else if (waveForm == "Inverse Hill")
582 return eWF_InvHill;
584 throw std::runtime_error("Invalid wave form.");
587 //////////////////////////////////////////////////////////////////////////
588 // Script parser
589 //////////////////////////////////////////////////////////////////////////
591 string ParseUINameFromPublicParamsScript(const char* sUIScript)
593 string uiscript = sUIScript;
594 string element[3];
595 int p1 = 0;
596 string itemToken = uiscript.Tokenize(";", p1);
597 while (!itemToken.empty())
599 int nElements = 0;
600 int p2 = 0;
601 string token = itemToken.Tokenize(" \t\r\n=", p2);
602 while (!token.empty())
604 element[nElements++] = token;
605 if (nElements == 2)
607 element[nElements] = itemToken.substr(p2);
608 element[nElements].Trim(" =\t\"");
609 break;
611 token = itemToken.Tokenize(" \t\r\n=", p2);
614 if (stricmp(element[1], "UIName") == 0)
616 return element[2].c_str();
618 itemToken = uiscript.Tokenize(";", p1);
620 return "";
623 std::map<string, float> ParseValidRangeFromPublicParamsScript(const char* sUIScript)
625 string uiscript = sUIScript;
626 std::map<string, float> result;
627 bool isUIMinExist(false);
628 bool isUIMaxExist(false);
629 string element[3];
630 int p1 = 0;
631 string itemToken = uiscript.Tokenize(";", p1);
632 while (!itemToken.empty())
634 int nElements = 0;
635 int p2 = 0;
636 string token = itemToken.Tokenize(" \t\r\n=", p2);
637 while (!token.empty())
639 element[nElements++] = token;
640 if (nElements == 2)
642 element[nElements] = itemToken.substr(p2);
643 element[nElements].Trim(" =\t\"");
644 break;
646 token = itemToken.Tokenize(" \t\r\n=", p2);
649 if (stricmp(element[1], "UIMin") == 0)
651 result["UIMin"] = atof(element[2]);
652 isUIMinExist = true;
654 if (stricmp(element[1], "UIMax") == 0)
656 result["UIMax"] = atof(element[2]);
657 isUIMaxExist = true;
659 itemToken = uiscript.Tokenize(";", p1);
661 if (!isUIMinExist || !isUIMaxExist)
663 throw std::runtime_error("Invalid range for shader param.");
665 return result;
668 //////////////////////////////////////////////////////////////////////////
669 // Set Flags
670 //////////////////////////////////////////////////////////////////////////
672 void SetMaterialFlag(CMaterial* pMaterial, const EMaterialFlags& eFlag, const bool& bFlag)
674 if (pMaterial->GetFlags() & eFlag && bFlag == false)
676 pMaterial->SetFlags(pMaterial->GetFlags() - eFlag);
678 else if (!(pMaterial->GetFlags() & eFlag) && bFlag == true)
680 pMaterial->SetFlags(pMaterial->GetFlags() | eFlag);
684 void SetPropagationFlag(CMaterial* pMaterial, const eMTL_PROPAGATION& eFlag, const bool& bFlag)
686 if (pMaterial->GetPropagationFlags() & eFlag && bFlag == false)
688 pMaterial->SetPropagationFlags(pMaterial->GetPropagationFlags() - eFlag);
690 else if (!(pMaterial->GetPropagationFlags() & eFlag) && bFlag == true)
692 pMaterial->SetPropagationFlags(pMaterial->GetPropagationFlags() | eFlag);
696 //////////////////////////////////////////////////////////////////////////
698 bool ValidateProperty(CMaterial* pMaterial, const std::deque<string>& splittedPropertyPathParam, const SPyWrappedProperty& value)
700 std::deque<string> splittedPropertyPath = splittedPropertyPathParam;
701 std::deque<string> splittedPropertyPathSubCategory = splittedPropertyPathParam;
702 string categoryName = splittedPropertyPath.front();
703 string subCategoryName = "";
704 string subSubCategoryName = "";
705 string currentPath = "";
706 string propertyName = splittedPropertyPath.back();
708 string errorMsgInvalidValue = string("Invalid value for property \"") + propertyName + "\"";
709 string errorMsgInvalidDataType = string("Invalid data type for property \"") + propertyName + "\"";
710 string errorMsgInvalidPropertyPath = string("Invalid property path");
712 const int iMinColorValue = 0;
713 const int iMaxColorValue = 255;
715 if (splittedPropertyPathSubCategory.size() == 3)
717 splittedPropertyPathSubCategory.pop_back();
718 subCategoryName = splittedPropertyPathSubCategory.back();
719 currentPath = string("") + categoryName + "/" + subCategoryName;
721 if (
722 subCategoryName != "TexType" &&
723 subCategoryName != "Filter" &&
724 subCategoryName != "IsProjectedTexGen" &&
725 subCategoryName != "TexGenType" &&
726 subCategoryName != "Wave X" &&
727 subCategoryName != "Wave Y" &&
728 subCategoryName != "Wave Z" &&
729 subCategoryName != "Wave W" &&
730 subCategoryName != "Shader1" &&
731 subCategoryName != "Shader2" &&
732 subCategoryName != "Shader3" &&
733 subCategoryName != "Tiling" &&
734 subCategoryName != "Rotator" &&
735 subCategoryName != "Oscillator" &&
736 subCategoryName != "Diffuse" &&
737 subCategoryName != "Specular" &&
738 subCategoryName != "Bumpmap" &&
739 subCategoryName != "Heightmap" &&
740 subCategoryName != "Environment" &&
741 subCategoryName != "Detail" &&
742 subCategoryName != "Opacity" &&
743 subCategoryName != "Decal" &&
744 subCategoryName != "SubSurface" &&
745 subCategoryName != "Custom" &&
746 subCategoryName != "[1] Custom"
749 throw std::runtime_error(errorMsgInvalidPropertyPath + " (" + currentPath + ")");
752 else if (splittedPropertyPathSubCategory.size() == 4)
754 splittedPropertyPathSubCategory.pop_back();
755 subCategoryName = splittedPropertyPathSubCategory.back();
756 splittedPropertyPathSubCategory.pop_back();
757 subSubCategoryName = splittedPropertyPathSubCategory.back();
758 currentPath = categoryName + "/" + subSubCategoryName + "/" + subCategoryName;
760 if (
761 subSubCategoryName != "Diffuse" &&
762 subSubCategoryName != "Specular" &&
763 subSubCategoryName != "Bumpmap" &&
764 subSubCategoryName != "Heightmap" &&
765 subSubCategoryName != "Environment" &&
766 subSubCategoryName != "Detail" &&
767 subSubCategoryName != "Opacity" &&
768 subSubCategoryName != "Decal" &&
769 subSubCategoryName != "SubSurface" &&
770 subSubCategoryName != "Custom" &&
771 subSubCategoryName != "[1] Custom"
774 throw std::runtime_error(errorMsgInvalidPropertyPath + " (" + currentPath + ")");
776 else if (subCategoryName != "Tiling" && subCategoryName != "Rotator" && subCategoryName != "Oscillator")
778 throw std::runtime_error(errorMsgInvalidPropertyPath + " (" + currentPath + ")");
781 else
783 currentPath = categoryName;
786 if (
787 categoryName == "Material Settings" ||
788 categoryName == "Opacity Settings" ||
789 categoryName == "Lighting Settings" ||
790 categoryName == "Advanced" ||
791 categoryName == "Texture Maps" ||
792 categoryName == "Vertex Deformation" ||
793 categoryName == "Layer Presets")
795 if (propertyName == "Opacity" || propertyName == "AlphaTest" || propertyName == "Glow Amount")
797 // int: 0 < x < 100
798 if (value.type != SPyWrappedProperty::eType_Int)
800 throw std::runtime_error(errorMsgInvalidDataType);
803 if (value.property.intValue < 0 || value.property.intValue > 100)
805 throw std::runtime_error(errorMsgInvalidValue);
807 return true;
809 else if (propertyName == "Glossiness")
811 // int: 0 < x < 255
812 if (value.type != SPyWrappedProperty::eType_Int)
814 throw std::runtime_error(errorMsgInvalidDataType);
817 if (value.property.intValue < iMinColorValue || value.property.intValue > iMaxColorValue)
819 throw std::runtime_error(errorMsgInvalidValue);
821 return true;
823 else if (propertyName == "Specular Level" || propertyName == "Heat Amount")
825 // float: 0.0 < x < 4.0
826 if (value.type != SPyWrappedProperty::eType_Float)
828 throw std::runtime_error(errorMsgInvalidDataType);
831 if (value.property.floatValue < 0.0f || value.property.floatValue > 4.0f)
833 throw std::runtime_error(errorMsgInvalidValue);
835 return true;
837 else if (propertyName == "Fur Amount" || propertyName == "Cloak Amount")
839 // float: 0.0 < x < 1.0
840 if (value.type != SPyWrappedProperty::eType_Float)
842 throw std::runtime_error(errorMsgInvalidDataType);
845 if (value.property.floatValue < 0.0f || value.property.floatValue > 1.0f)
847 throw std::runtime_error(errorMsgInvalidValue);
849 return true;
851 else if (
852 propertyName == "TileU" ||
853 propertyName == "TileV" ||
854 propertyName == "OffsetU" ||
855 propertyName == "OffsetV" ||
856 propertyName == "RotateU" ||
857 propertyName == "RotateV" ||
858 propertyName == "RotateW" ||
859 propertyName == "Rate" ||
860 propertyName == "Phase" ||
861 propertyName == "Amplitude" ||
862 propertyName == "CenterU" ||
863 propertyName == "CenterV" ||
864 propertyName == "RateU" ||
865 propertyName == "RateV" ||
866 propertyName == "PhaseU" ||
867 propertyName == "PhaseV" ||
868 propertyName == "AmplitudeU" ||
869 propertyName == "AmplitudeV" ||
870 propertyName == "Wave Length X" ||
871 propertyName == "Wave Length Y" ||
872 propertyName == "Wave Length Z" ||
873 propertyName == "Wave Length W" ||
874 propertyName == "Level" ||
875 propertyName == "Amplitude" ||
876 propertyName == "Phase" ||
877 propertyName == "Frequency")
879 // float: 0.0 < x < 100.0
880 if (value.type != SPyWrappedProperty::eType_Float)
882 throw std::runtime_error(errorMsgInvalidDataType);
885 if (value.property.floatValue < 0.0f || value.property.floatValue > 100.0f)
887 throw std::runtime_error(errorMsgInvalidValue);
889 return true;
891 else if (propertyName == "Diffuse Color" || propertyName == "Specular Color" || propertyName == "Emissive Color")
893 // intVector(RGB): 0 < x < 255
894 if (value.type != SPyWrappedProperty::eType_Color)
896 throw std::runtime_error(errorMsgInvalidDataType);
899 if (value.property.colorValue.r < iMinColorValue || value.property.colorValue.r > iMaxColorValue)
901 throw std::runtime_error(errorMsgInvalidValue + " (red)");
903 else if (value.property.colorValue.g < iMinColorValue || value.property.colorValue.g > iMaxColorValue)
905 throw std::runtime_error(errorMsgInvalidValue + " (green)");
907 else if (value.property.colorValue.b < iMinColorValue || value.property.colorValue.b > iMaxColorValue)
909 throw std::runtime_error(errorMsgInvalidValue + " (blue)");
911 return true;
913 else if (
914 propertyName == "Template Material" ||
915 propertyName == "Link to Material" ||
916 propertyName == "Surface Type" ||
917 propertyName == "Diffuse" ||
918 propertyName == "Specular" ||
919 propertyName == "Bumpmap" ||
920 propertyName == "Heightmap" ||
921 propertyName == "Environment" ||
922 propertyName == "Detail" ||
923 propertyName == "Opacity" ||
924 propertyName == "Decal" ||
925 propertyName == "SubSurface" ||
926 propertyName == "Custom" ||
927 propertyName == "[1] Custom" ||
928 propertyName == "TexType" ||
929 propertyName == "Filter" ||
930 propertyName == "TexGenType" ||
931 propertyName == "Type" ||
932 propertyName == "TypeU" ||
933 propertyName == "TypeV")
935 // string
936 if (value.type != SPyWrappedProperty::eType_String)
938 throw std::runtime_error(errorMsgInvalidDataType);
940 return true;
942 else if (
943 propertyName == "Additive" ||
944 propertyName == "Allow layer activation" ||
945 propertyName == "2 Sided" ||
946 propertyName == "No Shadow" ||
947 propertyName == "Use Scattering" ||
948 propertyName == "Hide After Breaking" ||
949 propertyName == "Traceable Texture" ||
950 propertyName == "Propagate Material Settings" ||
951 propertyName == "Propagate Opacity Settings" ||
952 propertyName == "Propagate Lighting Settings" ||
953 propertyName == "Propagate Advanced Settings" ||
954 propertyName == "Propagate Texture Maps" ||
955 propertyName == "Propagate Shader Params" ||
956 propertyName == "Propagate Shader Generation" ||
957 propertyName == "Propagate Vertex Deformation" ||
958 propertyName == "Propagate Layer Presets" ||
959 propertyName == "IsProjectedTexGen" ||
960 propertyName == "IsTileU" ||
961 propertyName == "IsTileV" ||
962 propertyName == "No Draw")
964 // bool
965 if (value.type != SPyWrappedProperty::eType_Bool)
967 throw std::runtime_error(errorMsgInvalidDataType);
969 return true;
971 else if (propertyName == "Shader" || propertyName == "Shader1" || propertyName == "Shader2" || propertyName == "Shader3")
973 // string && valid shader
974 if (value.type != SPyWrappedProperty::eType_String)
976 throw std::runtime_error(errorMsgInvalidDataType);
979 const auto& shaderList = GetIEditorImpl()->GetMaterialManager()->GetShaderList();
980 if (std::find(shaderList.begin(), shaderList.end(), value.stringValue) != shaderList.end())
981 return true;
983 else if (propertyName == "Noise Scale")
985 // FloatVec: undefined < x < undefined
986 if (value.type != SPyWrappedProperty::eType_Vec3)
988 throw std::runtime_error(errorMsgInvalidDataType);
990 return true;
993 else if (categoryName == "Shader Params")
995 DynArray<SShaderParam>& shaderParams = pMaterial->GetShaderResources().m_ShaderParams;
996 for (int i = 0; i < shaderParams.size(); i++)
998 if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script))
1000 if (shaderParams[i].m_Type == eType_FLOAT)
1002 // float: valid range (from script)
1003 if (value.type != SPyWrappedProperty::eType_Float)
1005 throw std::runtime_error(errorMsgInvalidDataType);
1007 std::map<string, float> range = ParseValidRangeFromPublicParamsScript(shaderParams[i].m_Script);
1008 if (value.property.floatValue < range["UIMin"] || value.property.floatValue > range["UIMax"])
1010 string errorMsg;
1011 errorMsg.Format("Invalid value for shader param \"%s\" (min: %f, max: %f)", propertyName, range["UIMin"], range["UIMax"]);
1012 throw std::runtime_error(errorMsg);
1014 return true;
1016 else if (shaderParams[i].m_Type == eType_FCOLOR)
1018 // intVector(RGB): 0 < x < 255
1019 if (value.type != SPyWrappedProperty::eType_Color)
1021 throw std::runtime_error(errorMsgInvalidDataType);
1024 if (value.property.colorValue.r < iMinColorValue || value.property.colorValue.r > iMaxColorValue)
1026 throw std::runtime_error(errorMsgInvalidValue + " (red)");
1028 else if (value.property.colorValue.g < iMinColorValue || value.property.colorValue.g > iMaxColorValue)
1030 throw std::runtime_error(errorMsgInvalidValue + " (green)");
1032 else if (value.property.colorValue.b < iMinColorValue || value.property.colorValue.b > iMaxColorValue)
1034 throw std::runtime_error(errorMsgInvalidValue + " (blue)");
1036 return true;
1041 else if (categoryName == "Shader Generation Params")
1043 for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++)
1045 if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName())
1047 if (value.type != SPyWrappedProperty::eType_Bool)
1049 throw std::runtime_error(errorMsgInvalidDataType);
1051 return true;
1055 else
1057 throw std::runtime_error(errorMsgInvalidPropertyPath + " (" + currentPath + ")");
1059 return false;
1062 //////////////////////////////////////////////////////////////////////////
1064 SPyWrappedProperty PyGetProperty(const char* pPathAndMaterialName, const char* pPathAndPropertyName)
1066 CMaterial* pMaterial = TryLoadingMaterial(pPathAndMaterialName);
1067 std::deque<string> splittedPropertyPath = PreparePropertyPath(pPathAndPropertyName);
1068 std::deque<string> splittedPropertyPathCategory = splittedPropertyPath;
1069 string categoryName = splittedPropertyPath.front();
1070 string subCategoryName = "None";
1071 string subSubCategoryName = "None";
1072 string propertyName = splittedPropertyPath.back();
1073 string errorMsgInvalidPropertyPath = "Invalid property path.";
1074 SPyWrappedProperty value;
1076 if (splittedPropertyPathCategory.size() == 3)
1078 splittedPropertyPathCategory.pop_back();
1079 subCategoryName = splittedPropertyPathCategory.back();
1081 else if (splittedPropertyPathCategory.size() == 4)
1083 splittedPropertyPathCategory.pop_back();
1084 subCategoryName = splittedPropertyPathCategory.back();
1085 splittedPropertyPathCategory.pop_back();
1086 subSubCategoryName = splittedPropertyPathCategory.back();
1089 // ########## Material Settings ##########
1090 if (categoryName == "Material Settings")
1092 if (propertyName == "Template Material")
1094 value.type = SPyWrappedProperty::eType_String;
1095 value.stringValue = pMaterial->GetMatTemplate();
1097 else if (propertyName == "Shader")
1099 value.type = SPyWrappedProperty::eType_String;
1100 value.stringValue = pMaterial->GetShaderName();
1102 else if (propertyName == "Surface Type")
1104 value.type = SPyWrappedProperty::eType_String;
1105 value.stringValue = pMaterial->GetSurfaceTypeName();
1106 if (value.stringValue.Find("mat_") == 0)
1108 value.stringValue.Delete(0, 4);
1111 else
1113 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid material setting.");
1116 // ########## Opacity Settings ##########
1117 else if (categoryName == "Opacity Settings")
1119 if (propertyName == "Opacity")
1121 value.type = SPyWrappedProperty::eType_Int;
1122 value.property.floatValue = pMaterial->GetShaderResources().m_LMaterial.m_Opacity;
1123 value.property.intValue = value.property.floatValue * 100.0f;
1125 else if (propertyName == "AlphaTest")
1127 value.type = SPyWrappedProperty::eType_Int;
1128 value.property.floatValue = pMaterial->GetShaderResources().m_AlphaRef;
1129 value.property.intValue = value.property.floatValue * 100.0f;
1131 else if (propertyName == "Additive")
1133 value.type = SPyWrappedProperty::eType_Bool;
1134 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_ADDITIVE;
1136 else
1138 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid opacity setting.");
1141 // ########## Lighting Settings ##########
1142 else if (categoryName == "Lighting Settings")
1144 if (propertyName == "Diffuse Color")
1146 value.type = SPyWrappedProperty::eType_Color;
1147 COLORREF col = CMFCUtils::ColorLinearToGamma(ColorF(
1148 pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.r,
1149 pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.g,
1150 pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.b));
1151 value.property.colorValue.r = (int)GetRValue(col);
1152 value.property.colorValue.g = (int)GetGValue(col);
1153 value.property.colorValue.b = (int)GetBValue(col);
1155 else if (propertyName == "Specular Color")
1157 value.type = SPyWrappedProperty::eType_Color;
1158 COLORREF col = CMFCUtils::ColorLinearToGamma(ColorF(
1159 pMaterial->GetShaderResources().m_LMaterial.m_Specular.r / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a,
1160 pMaterial->GetShaderResources().m_LMaterial.m_Specular.g / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a,
1161 pMaterial->GetShaderResources().m_LMaterial.m_Specular.b / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a));
1162 value.property.colorValue.r = (int)GetRValue(col);
1163 value.property.colorValue.g = (int)GetGValue(col);
1164 value.property.colorValue.b = (int)GetBValue(col);
1166 else if (propertyName == "Glossiness")
1168 value.type = SPyWrappedProperty::eType_Int;
1169 value.property.floatValue = pMaterial->GetShaderResources().m_LMaterial.m_Smoothness;
1170 value.property.intValue = (int)value.property.floatValue;
1172 else if (propertyName == "Specular Level")
1174 value.type = SPyWrappedProperty::eType_Float;
1175 value.property.floatValue = pMaterial->GetShaderResources().m_LMaterial.m_Specular.a;
1177 else if (propertyName == "Emissive Color")
1179 value.type = SPyWrappedProperty::eType_Color;
1180 COLORREF col = CMFCUtils::ColorLinearToGamma(ColorF(
1181 pMaterial->GetShaderResources().m_LMaterial.m_Emittance.r,
1182 pMaterial->GetShaderResources().m_LMaterial.m_Emittance.g,
1183 pMaterial->GetShaderResources().m_LMaterial.m_Emittance.b));
1184 value.property.colorValue.r = (int)GetRValue(col);
1185 value.property.colorValue.g = (int)GetGValue(col);
1186 value.property.colorValue.b = (int)GetBValue(col);
1188 else if (propertyName == "Emissive Intensity")
1190 value.type = SPyWrappedProperty::eType_Float;
1191 value.property.floatValue = pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a;
1193 else
1195 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid lighting setting.");
1198 // ########## Advanced ##########
1199 else if (categoryName == "Advanced")
1201 if (propertyName == "Allow layer activation")
1203 value.type = SPyWrappedProperty::eType_Bool;
1204 value.property.boolValue = pMaterial->LayerActivationAllowed();
1206 else if (propertyName == "2 Sided")
1208 value.type = SPyWrappedProperty::eType_Bool;
1209 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_2SIDED;
1211 else if (propertyName == "No Shadow")
1213 value.type = SPyWrappedProperty::eType_Bool;
1214 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_NOSHADOW;
1216 else if (propertyName == "Use Scattering")
1218 value.type = SPyWrappedProperty::eType_Bool;
1219 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_SCATTER;
1221 else if (propertyName == "Hide After Breaking")
1223 value.type = SPyWrappedProperty::eType_Bool;
1224 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_HIDEONBREAK;
1226 else if (propertyName == "Traceable Texture")
1228 value.type = SPyWrappedProperty::eType_Bool;
1229 value.property.boolValue = pMaterial->GetFlags() & MTL_FLAG_TRACEABLE_TEXTURE;
1231 else if (propertyName == "Fur Amount")
1233 value.type = SPyWrappedProperty::eType_Float;
1234 value.property.floatValue = (float)pMaterial->GetShaderResources().m_FurAmount / 255.0f;
1236 else if (propertyName == "Voxel Coverage")
1238 value.type = SPyWrappedProperty::eType_Float;
1239 value.property.floatValue = (float)pMaterial->GetShaderResources().m_VoxelCoverage / 255.0f;
1241 else if (propertyName == "Heat Amount")
1243 value.type = SPyWrappedProperty::eType_Float;
1244 value.property.floatValue = ((float)pMaterial->GetShaderResources().m_HeatAmount / 255.0f) * 4.0f;
1246 else if (propertyName == "Cloak Amount")
1248 value.type = SPyWrappedProperty::eType_Float;
1249 value.property.floatValue = (float)pMaterial->GetShaderResources().m_CloakAmount / 255.0f;
1251 else if (propertyName == "Link to Material")
1253 value.type = SPyWrappedProperty::eType_String;
1254 value.stringValue = pMaterial->GetMatInfo()->GetMaterialLinkName();
1256 else if (propertyName == "Propagate Material Settings")
1258 value.type = SPyWrappedProperty::eType_Bool;
1259 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_MATERIAL_SETTINGS;
1261 else if (propertyName == "Propagate Opacity Settings")
1263 value.type = SPyWrappedProperty::eType_Bool;
1264 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_OPACITY;
1266 else if (propertyName == "Propagate Lighting Settings")
1268 value.type = SPyWrappedProperty::eType_Bool;
1269 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_LIGHTING;
1271 else if (propertyName == "Propagate Advanced Settings")
1273 value.type = SPyWrappedProperty::eType_Bool;
1274 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_ADVANCED;
1276 else if (propertyName == "Propagate Texture Maps")
1278 value.type = SPyWrappedProperty::eType_Bool;
1279 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_TEXTURES;
1281 else if (propertyName == "Propagate Shader Params")
1283 value.type = SPyWrappedProperty::eType_Bool;
1284 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_SHADER_PARAMS;
1286 else if (propertyName == "Propagate Shader Generation")
1288 value.type = SPyWrappedProperty::eType_Bool;
1289 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_SHADER_GEN;
1291 else if (propertyName == "Propagate Vertex Deformation")
1293 value.type = SPyWrappedProperty::eType_Bool;
1294 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_VERTEX_DEF;
1296 else if (propertyName == "Propagate Layer Presets")
1298 value.type = SPyWrappedProperty::eType_Bool;
1299 value.property.boolValue = pMaterial->GetPropagationFlags() & MTL_PROPAGATE_LAYER_PRESETS;
1301 else
1303 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid advanced setting.");
1306 // ########## Texture Maps ##########
1307 else if (categoryName == "Texture Maps")
1309 // ########## Texture Maps / [name] ##########
1310 if (splittedPropertyPath.size() == 2)
1312 value.type = SPyWrappedProperty::eType_String;
1313 value.stringValue = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(propertyName)].m_Name.c_str();
1315 // ########## Texture Maps / [TexType | Filter | IsProjectedTexGen | TexGenType ] ##########
1316 else if (splittedPropertyPath.size() == 3)
1318 SEfResTexture& currentResTexture = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(subCategoryName)];
1320 if (propertyName == "TexType")
1322 value.type = SPyWrappedProperty::eType_String;
1323 value.stringValue = TryConvertingETEX_TypeToCString(currentResTexture.m_Sampler.m_eTexType);
1325 else if (propertyName == "Filter")
1327 value.type = SPyWrappedProperty::eType_String;
1328 value.stringValue = TryConvertingTexFilterToCString(currentResTexture.m_Filter);
1330 else if (propertyName == "IsProjectedTexGen")
1332 value.type = SPyWrappedProperty::eType_Bool;
1333 value.property.boolValue = currentResTexture.AddModificator()->m_bTexGenProjected;
1335 else if (propertyName == "TexGenType")
1337 value.type = SPyWrappedProperty::eType_String;
1338 value.stringValue = TryConvertingETexGenTypeToCString(currentResTexture.AddModificator()->m_eTGType);
1340 else
1342 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1345 // ########## Texture Maps / [Tiling | Rotator | Oscillator] ##########
1346 else if (splittedPropertyPath.size() == 4)
1348 SEfResTexture& currentResTexture = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(subSubCategoryName)];
1350 if (subCategoryName == "Tiling")
1352 if (propertyName == "IsTileU")
1354 value.type = SPyWrappedProperty::eType_Bool;
1355 value.property.boolValue = currentResTexture.m_bUTile;
1357 else if (propertyName == "IsTileV")
1359 value.type = SPyWrappedProperty::eType_Bool;
1360 value.property.boolValue = currentResTexture.m_bVTile;
1362 else if (propertyName == "TileU")
1364 value.type = SPyWrappedProperty::eType_Float;
1365 value.property.floatValue = currentResTexture.AddModificator()->m_Tiling[0];
1367 else if (propertyName == "TileV")
1369 value.type = SPyWrappedProperty::eType_Float;
1370 value.property.floatValue = currentResTexture.AddModificator()->m_Tiling[1];
1372 else if (propertyName == "OffsetU")
1374 value.type = SPyWrappedProperty::eType_Float;
1375 value.property.floatValue = currentResTexture.AddModificator()->m_Offs[0];
1377 else if (propertyName == "OffsetV")
1379 value.type = SPyWrappedProperty::eType_Float;
1380 value.property.floatValue = currentResTexture.AddModificator()->m_Offs[1];
1382 else if (propertyName == "RotateU")
1384 value.type = SPyWrappedProperty::eType_Float;
1385 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_Rot[0]);
1387 else if (propertyName == "RotateV")
1389 value.type = SPyWrappedProperty::eType_Float;
1390 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_Rot[1]);
1392 else if (propertyName == "RotateW")
1394 value.type = SPyWrappedProperty::eType_Float;
1395 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_Rot[2]);
1397 else
1399 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1402 else if (subCategoryName == "Rotator")
1404 if (propertyName == "Type")
1406 value.type = SPyWrappedProperty::eType_String;
1407 value.stringValue = TryConvertingETexModRotateTypeToCString(currentResTexture.AddModificator()->m_eRotType);
1409 else if (propertyName == "Rate")
1411 value.type = SPyWrappedProperty::eType_Float;
1412 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_RotOscRate[2]);
1414 else if (propertyName == "Phase")
1416 value.type = SPyWrappedProperty::eType_Float;
1417 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_RotOscPhase[2]);
1419 else if (propertyName == "Amplitude")
1421 value.type = SPyWrappedProperty::eType_Float;
1422 value.property.floatValue = Word2Degr(currentResTexture.AddModificator()->m_RotOscAmplitude[2]);
1424 else if (propertyName == "CenterU")
1426 value.type = SPyWrappedProperty::eType_Float;
1427 value.property.floatValue = currentResTexture.AddModificator()->m_RotOscCenter[0];
1429 else if (propertyName == "CenterV")
1431 value.type = SPyWrappedProperty::eType_Float;
1432 value.property.floatValue = currentResTexture.AddModificator()->m_RotOscCenter[1];
1434 else
1436 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1439 else if (subCategoryName == "Oscillator")
1441 if (propertyName == "TypeU")
1443 value.type = SPyWrappedProperty::eType_String;
1444 value.stringValue = TryConvertingETexModMoveTypeToCString(currentResTexture.AddModificator()->m_eMoveType[0]);
1446 else if (propertyName == "TypeV")
1448 value.type = SPyWrappedProperty::eType_String;
1449 value.stringValue = TryConvertingETexModMoveTypeToCString(currentResTexture.AddModificator()->m_eMoveType[1]);
1451 else if (propertyName == "RateU")
1453 value.type = SPyWrappedProperty::eType_Float;
1454 value.property.floatValue = currentResTexture.AddModificator()->m_OscRate[0];
1456 else if (propertyName == "RateV")
1458 value.type = SPyWrappedProperty::eType_Float;
1459 value.property.floatValue = currentResTexture.AddModificator()->m_OscRate[1];
1461 else if (propertyName == "PhaseU")
1463 value.type = SPyWrappedProperty::eType_Float;
1464 value.property.floatValue = currentResTexture.AddModificator()->m_OscPhase[0];
1466 else if (propertyName == "PhaseV")
1468 value.type = SPyWrappedProperty::eType_Float;
1469 value.property.floatValue = currentResTexture.AddModificator()->m_OscPhase[1];
1471 else if (propertyName == "AmplitudeU")
1473 value.type = SPyWrappedProperty::eType_Float;
1474 value.property.floatValue = currentResTexture.AddModificator()->m_OscAmplitude[0];
1476 else if (propertyName == "AmplitudeV")
1478 value.type = SPyWrappedProperty::eType_Float;
1479 value.property.floatValue = currentResTexture.AddModificator()->m_OscAmplitude[1];
1481 else
1483 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1486 else
1488 throw std::runtime_error(string("\"") + subCategoryName + "\" is an invalid sub category.");
1491 else
1493 throw std::runtime_error(errorMsgInvalidPropertyPath);
1496 // ########## Shader Params ##########
1497 else if (categoryName == "Shader Params")
1499 DynArray<SShaderParam>& shaderParams = pMaterial->GetShaderResources().m_ShaderParams;
1500 bool isPropertyFound(false);
1502 for (int i = 0; i < shaderParams.size(); i++)
1504 if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script))
1506 if (shaderParams[i].m_Type == eType_FLOAT)
1508 value.type = SPyWrappedProperty::eType_Float;
1509 value.property.floatValue = shaderParams[i].m_Value.m_Float;
1510 isPropertyFound = true;
1511 break;
1513 else if (shaderParams[i].m_Type == eType_FCOLOR)
1515 value.type = SPyWrappedProperty::eType_Color;
1516 COLORREF col = CMFCUtils::ColorLinearToGamma(ColorF(
1517 shaderParams[i].m_Value.m_Vector[0],
1518 shaderParams[i].m_Value.m_Vector[1],
1519 shaderParams[i].m_Value.m_Vector[2]));
1520 value.property.colorValue.r = (int)GetRValue(col);
1521 value.property.colorValue.g = (int)GetGValue(col);
1522 value.property.colorValue.b = (int)GetBValue(col);
1523 isPropertyFound = true;
1524 break;
1529 if (!isPropertyFound)
1531 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid shader param.");
1534 // ########## Shader Generation Params ##########
1535 else if (categoryName == "Shader Generation Params")
1537 value.type = SPyWrappedProperty::eType_Bool;
1538 bool isPropertyFound(false);
1539 for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++)
1541 if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName())
1543 isPropertyFound = true;
1544 pMaterial->GetShaderGenParamsVars()->GetVariable(i)->Get(value.property.boolValue);
1545 break;
1549 if (!isPropertyFound)
1551 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid shader generation param.");
1554 // ########## Vertex Deformation ##########
1555 else if (categoryName == "Vertex Deformation")
1557 // ########## Vertex Deformation / [ Type | Wave Length X | Wave Length Y | Wave Length Z | Wave Length W | Noise Scale ] ##########
1558 if (splittedPropertyPath.size() == 2)
1560 if (propertyName == "Type")
1562 value.type = SPyWrappedProperty::eType_String;
1563 value.stringValue = TryConvertingEDeformTypeToCString(pMaterial->GetShaderResources().m_DeformInfo.m_eType);
1565 else if (propertyName == "Wave Length X")
1567 value.type = SPyWrappedProperty::eType_Float;
1568 value.property.floatValue = pMaterial->GetShaderResources().m_DeformInfo.m_fDividerX;
1570 else if (propertyName == "Wave Length Y")
1572 value.type = SPyWrappedProperty::eType_Float;
1573 value.property.floatValue = pMaterial->GetShaderResources().m_DeformInfo.m_fDividerY;
1575 else if (propertyName == "Wave Length Z")
1577 value.type = SPyWrappedProperty::eType_Float;
1578 value.property.floatValue = pMaterial->GetShaderResources().m_DeformInfo.m_fDividerZ;
1580 else if (propertyName == "Wave Length W")
1582 value.type = SPyWrappedProperty::eType_Float;
1583 value.property.floatValue = pMaterial->GetShaderResources().m_DeformInfo.m_fDividerW;
1585 else if (propertyName == "Noise Scale")
1587 value.type = SPyWrappedProperty::eType_Vec3;
1588 value.property.vecValue.x = pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[0];
1589 value.property.vecValue.y = pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[1];
1590 value.property.vecValue.z = pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[2];
1592 else
1594 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1597 // ########## Vertex Deformation / [ Wave X | Wave Y | Wave Z | Wave W ] ##########
1598 else if (splittedPropertyPath.size() == 3)
1600 if (subCategoryName == "Wave X" || subCategoryName == "Wave Y" || subCategoryName == "Wave Z" || subCategoryName == "Wave W")
1602 SWaveForm2 currentWaveForm;
1603 if (subCategoryName == "Wave X")
1605 currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveX;
1607 else if (subCategoryName == "Wave Y")
1609 currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveY;
1611 else if (subCategoryName == "Wave Z")
1613 currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveZ;
1615 else if (subCategoryName == "Wave W")
1617 currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveW;
1620 if (propertyName == "Type")
1622 value.type = SPyWrappedProperty::eType_String;
1623 value.stringValue = TryConvertingEWaveFormToCString(currentWaveForm.m_eWFType);
1625 else if (propertyName == "Level")
1627 value.type = SPyWrappedProperty::eType_Float;
1628 value.property.floatValue = currentWaveForm.m_Level;
1630 else if (propertyName == "Amplitude")
1632 value.type = SPyWrappedProperty::eType_Float;
1633 value.property.floatValue = currentWaveForm.m_Amp;
1635 else if (propertyName == "Phase")
1637 value.type = SPyWrappedProperty::eType_Float;
1638 value.property.floatValue = currentWaveForm.m_Phase;
1640 else if (propertyName == "Frequency")
1642 value.type = SPyWrappedProperty::eType_Float;
1643 value.property.floatValue = currentWaveForm.m_Freq;
1645 else
1647 throw std::runtime_error(string("\"") + propertyName + "\" is an invalid property.");
1650 else
1652 throw std::runtime_error(string("\"") + categoryName + "\" is an invalid category.");
1655 else
1657 throw std::runtime_error(errorMsgInvalidPropertyPath);
1660 // ########## Layer Presets ##########
1661 else if (categoryName == "Layer Presets")
1663 // names are "Shader1", "Shader2" and "Shader3", bacause all have the name "Shader" in material editor
1664 if (splittedPropertyPath.size() == 2)
1666 value.type = SPyWrappedProperty::eType_String;
1668 int shaderNumber = -1;
1669 if (propertyName == "Shader1")
1671 shaderNumber = 0;
1673 else if (propertyName == "Shader2")
1675 shaderNumber = 1;
1677 else if (propertyName == "Shader3")
1679 shaderNumber = 2;
1681 else
1683 throw std::runtime_error("Invalid shader.");
1686 value.stringValue = pMaterial->GetMtlLayerResources()[shaderNumber].m_shaderName;
1688 else if (splittedPropertyPath.size() == 3)
1690 if (propertyName == "No Draw")
1692 value.type = SPyWrappedProperty::eType_Bool;
1694 int shaderNumber = -1;
1695 if (subCategoryName == "Shader1")
1697 shaderNumber = 0;
1699 else if (subCategoryName == "Shader2")
1701 shaderNumber = 1;
1703 else if (subCategoryName == "Shader3")
1705 shaderNumber = 2;
1707 else
1709 throw std::runtime_error("Invalid shader.");
1711 value.property.boolValue = pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW;
1714 else
1716 throw std::runtime_error(errorMsgInvalidPropertyPath);
1719 else
1721 throw std::runtime_error(errorMsgInvalidPropertyPath);
1724 return value;
1727 void PySetProperty(const char* pPathAndMaterialName, const char* pPathAndPropertyName, const SPyWrappedProperty& value)
1729 CMaterial* pMaterial = TryLoadingMaterial(pPathAndMaterialName);
1730 std::deque<string> splittedPropertyPath = PreparePropertyPath(pPathAndPropertyName);
1731 std::deque<string> splittedPropertyPathCategory = splittedPropertyPath;
1732 string categoryName = splittedPropertyPath.front();
1733 string subCategoryName = "None";
1734 string subSubCategoryName = "None";
1735 string propertyName = splittedPropertyPath.back();
1736 string errorMsgInvalidPropertyPath = "Invalid property path.";
1738 if (!ValidateProperty(pMaterial, splittedPropertyPath, value))
1740 throw std::runtime_error("Invalid property.");
1743 string undoMsg = "Set Material Property";
1744 CUndo undo(undoMsg);
1745 pMaterial->RecordUndo(undoMsg, true);
1747 if (splittedPropertyPathCategory.size() == 3)
1749 splittedPropertyPathCategory.pop_back();
1750 subCategoryName = splittedPropertyPathCategory.back();
1752 else if (splittedPropertyPathCategory.size() == 4)
1754 splittedPropertyPathCategory.pop_back();
1755 subCategoryName = splittedPropertyPathCategory.back();
1756 splittedPropertyPathCategory.pop_back();
1757 subSubCategoryName = splittedPropertyPathCategory.back();
1760 // ########## Material Settings ##########
1761 if (categoryName == "Material Settings")
1763 if (propertyName == "Template Material")
1765 pMaterial->SetMatTemplate(value.stringValue);
1767 else if (propertyName == "Shader")
1769 pMaterial->SetShaderName(value.stringValue);
1771 else if (propertyName == "Surface Type")
1773 bool isSurfaceExist(false);
1774 string realSurfacename = "";
1775 ISurfaceTypeEnumerator* pSurfaceTypeEnum = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator();
1776 if (pSurfaceTypeEnum)
1778 for (ISurfaceType* pSurfaceType = pSurfaceTypeEnum->GetFirst(); pSurfaceType; pSurfaceType = pSurfaceTypeEnum->GetNext())
1780 string surfaceName = pSurfaceType->GetName();
1781 realSurfacename = surfaceName;
1782 if (surfaceName.Left(4) == "mat_")
1784 surfaceName.Delete(0, 4);
1786 if (surfaceName == value.stringValue)
1788 isSurfaceExist = true;
1789 pMaterial->SetSurfaceTypeName(realSurfacename);
1793 if (!isSurfaceExist)
1795 throw std::runtime_error("Invalid surface type name.");
1798 else
1800 throw std::runtime_error("Surface Type Enumerator corrupted.");
1804 // ########## Opacity Settings ##########
1805 else if (categoryName == "Opacity Settings")
1807 if (propertyName == "Opacity")
1809 pMaterial->GetShaderResources().m_LMaterial.m_Opacity = static_cast<float>(value.property.intValue) / 100.0f;
1811 else if (propertyName == "AlphaTest")
1813 pMaterial->GetShaderResources().m_AlphaRef = static_cast<float>(value.property.intValue) / 100.0f;
1815 else if (propertyName == "Additive")
1817 SetMaterialFlag(pMaterial, MTL_FLAG_ADDITIVE, value.property.boolValue);
1820 // ########## Lighting Settings ##########
1821 else if (categoryName == "Lighting Settings")
1823 if (propertyName == "Diffuse Color")
1825 ColorB color(value.property.colorValue.r, value.property.colorValue.g, value.property.colorValue.b);
1826 pMaterial->GetShaderResources().m_LMaterial.m_Diffuse = CMFCUtils::ColorGammaToLinear(RGB(color.r, color.g, color.b));
1828 else if (propertyName == "Specular Color")
1830 ColorB color(value.property.colorValue.r, value.property.colorValue.g, value.property.colorValue.b);
1831 ColorF colorFloat = CMFCUtils::ColorGammaToLinear(RGB(color.r, color.g, color.b));
1832 colorFloat.a = pMaterial->GetShaderResources().m_LMaterial.m_Specular.a;
1833 colorFloat.r *= colorFloat.a;
1834 colorFloat.g *= colorFloat.a;
1835 colorFloat.b *= colorFloat.a;
1836 pMaterial->GetShaderResources().m_LMaterial.m_Specular = colorFloat;
1838 else if (propertyName == "Glossiness")
1840 pMaterial->GetShaderResources().m_LMaterial.m_Smoothness = static_cast<float>(value.property.intValue);
1842 else if (propertyName == "Specular Level")
1844 float tempFloat = pMaterial->GetShaderResources().m_LMaterial.m_Specular.a;
1845 float tempFloat2 = value.property.floatValue;
1847 ColorF colorFloat = pMaterial->GetShaderResources().m_LMaterial.m_Specular;
1848 colorFloat.a = value.property.floatValue;
1849 colorFloat.r *= colorFloat.a;
1850 colorFloat.g *= colorFloat.a;
1851 colorFloat.b *= colorFloat.a;
1852 colorFloat.a = 1.0f;
1853 pMaterial->GetShaderResources().m_LMaterial.m_Specular = colorFloat;
1856 else if (propertyName == "Emissive Color")
1858 ColorB color(value.property.colorValue.r, value.property.colorValue.g, value.property.colorValue.b);
1859 float emissiveIntensity = pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a;
1860 pMaterial->GetShaderResources().m_LMaterial.m_Emittance = CMFCUtils::ColorGammaToLinear(RGB(color.r, color.g, color.b));
1861 pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a = emissiveIntensity;
1863 else if (propertyName == "Emissive Intensity")
1865 pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a = value.property.floatValue;
1868 // ########## Advanced ##########
1869 else if (categoryName == "Advanced")
1871 if (propertyName == "Allow layer activation")
1873 pMaterial->SetLayerActivation(value.property.boolValue);
1875 else if (propertyName == "2 Sided")
1877 SetMaterialFlag(pMaterial, MTL_FLAG_2SIDED, value.property.boolValue);
1879 else if (propertyName == "No Shadow")
1881 SetMaterialFlag(pMaterial, MTL_FLAG_NOSHADOW, value.property.boolValue);
1883 else if (propertyName == "Use Scattering")
1885 SetMaterialFlag(pMaterial, MTL_FLAG_SCATTER, value.property.boolValue);
1887 else if (propertyName == "Hide After Breaking")
1889 SetMaterialFlag(pMaterial, MTL_FLAG_HIDEONBREAK, value.property.boolValue);
1891 else if (propertyName == "Traceable Texture")
1893 SetMaterialFlag(pMaterial, MTL_FLAG_TRACEABLE_TEXTURE, value.property.boolValue);
1895 else if (propertyName == "Fur Amount")
1897 pMaterial->GetShaderResources().m_FurAmount = static_cast<uint8>(value.property.floatValue * 255.0f);
1899 else if (propertyName == "Voxel Coverage")
1901 pMaterial->GetShaderResources().m_VoxelCoverage = static_cast<uint8>(value.property.floatValue * 255.0f);
1903 else if (propertyName == "Heat Amount")
1905 pMaterial->GetShaderResources().m_HeatAmount = static_cast<uint8>((value.property.floatValue / 4.0f) * 255.0f);
1907 else if (propertyName == "Cloak Amount")
1909 pMaterial->GetShaderResources().m_CloakAmount = static_cast<uint8>((value.property.floatValue * 255.0f));
1911 else if (propertyName == "Link to Material")
1913 pMaterial->GetMatInfo()->SetMaterialLinkName(value.stringValue);
1915 else if (propertyName == "Propagate Material Settings")
1917 SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, value.property.boolValue);
1919 else if (propertyName == "Propagate Opacity Settings")
1921 SetPropagationFlag(pMaterial, MTL_PROPAGATE_OPACITY, value.property.boolValue);
1923 else if (propertyName == "Propagate Lighting Settings")
1925 SetPropagationFlag(pMaterial, MTL_PROPAGATE_LIGHTING, value.property.boolValue);
1927 else if (propertyName == "Propagate Advanced Settings")
1929 SetPropagationFlag(pMaterial, MTL_PROPAGATE_ADVANCED, value.property.boolValue);
1931 else if (propertyName == "Propagate Texture Maps")
1933 SetPropagationFlag(pMaterial, MTL_PROPAGATE_TEXTURES, value.property.boolValue);
1935 else if (propertyName == "Propagate Shader Params")
1937 if (value.property.boolValue == true)
1939 SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, true);
1941 SetPropagationFlag(pMaterial, MTL_PROPAGATE_SHADER_PARAMS, value.property.boolValue);
1943 else if (propertyName == "Propagate Shader Generation")
1945 if (value.property.boolValue == true)
1947 SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, true);
1949 SetPropagationFlag(pMaterial, MTL_PROPAGATE_SHADER_GEN, value.property.boolValue);
1951 else if (propertyName == "Propagate Vertex Deformation")
1953 SetPropagationFlag(pMaterial, MTL_PROPAGATE_VERTEX_DEF, value.property.boolValue);
1955 else if (propertyName == "Propagate Layer Presets")
1957 SetPropagationFlag(pMaterial, MTL_PROPAGATE_LAYER_PRESETS, value.property.boolValue);
1960 // ########## Texture Maps ##########
1961 else if (categoryName == "Texture Maps")
1963 // ########## Texture Maps / [name] ##########
1964 if (splittedPropertyPath.size() == 2)
1966 SEfResTexture& currentResTexture = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(propertyName)];
1967 currentResTexture.m_Name = value.stringValue;
1969 // ########## Texture Maps / [TexType | Filter | IsProjectedTexGen | TexGenType ] ##########
1970 else if (splittedPropertyPath.size() == 3)
1972 SEfResTexture& currentResTexture = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(subCategoryName)];
1974 if (propertyName == "TexType")
1976 currentResTexture.m_Sampler.m_eTexType = TryConvertingCStringToETEX_Type(value.stringValue);
1978 else if (propertyName == "Filter")
1980 currentResTexture.m_Filter = TryConvertingCStringToTexFilter(value.stringValue);
1982 else if (propertyName == "IsProjectedTexGen")
1984 currentResTexture.AddModificator()->m_bTexGenProjected = value.property.boolValue;
1986 else if (propertyName == "TexGenType")
1988 currentResTexture.AddModificator()->m_eTGType = TryConvertingCStringToETexGenType(value.stringValue);
1991 // ########## Texture Maps / [Tiling | Rotator | Oscillator] ##########
1992 else if (splittedPropertyPath.size() == 4)
1994 SEfResTexture& currentResTexture = pMaterial->GetShaderResources().m_Textures[TryConvertingCStringToEEfResTextures(subSubCategoryName)];
1996 if (subCategoryName == "Tiling")
1998 if (propertyName == "IsTileU")
2000 currentResTexture.m_bUTile = value.property.boolValue;
2002 else if (propertyName == "IsTileV")
2004 currentResTexture.m_bVTile = value.property.boolValue;
2006 else if (propertyName == "TileU")
2008 currentResTexture.AddModificator()->m_Tiling[0] = value.property.floatValue;
2010 else if (propertyName == "TileV")
2012 currentResTexture.AddModificator()->m_Tiling[1] = value.property.floatValue;
2014 else if (propertyName == "OffsetU")
2016 currentResTexture.AddModificator()->m_Offs[0] = value.property.floatValue;
2018 else if (propertyName == "OffsetV")
2020 currentResTexture.AddModificator()->m_Offs[1] = value.property.floatValue;
2022 else if (propertyName == "RotateU")
2024 currentResTexture.AddModificator()->m_Rot[0] = Degr2Word(value.property.floatValue);
2026 else if (propertyName == "RotateV")
2028 currentResTexture.AddModificator()->m_Rot[1] = Degr2Word(value.property.floatValue);
2030 else if (propertyName == "RotateW")
2032 currentResTexture.AddModificator()->m_Rot[2] = Degr2Word(value.property.floatValue);
2035 else if (subCategoryName == "Rotator")
2037 if (propertyName == "Type")
2039 currentResTexture.AddModificator()->m_eRotType = TryConvertingCStringToETexModRotateType(value.stringValue);
2041 else if (propertyName == "Rate")
2043 currentResTexture.AddModificator()->m_RotOscRate[2] = Degr2Word(value.property.floatValue);
2045 else if (propertyName == "Phase")
2047 currentResTexture.AddModificator()->m_RotOscPhase[2] = Degr2Word(value.property.floatValue);
2049 else if (propertyName == "Amplitude")
2051 currentResTexture.AddModificator()->m_RotOscAmplitude[2] = Degr2Word(value.property.floatValue);
2053 else if (propertyName == "CenterU")
2055 currentResTexture.AddModificator()->m_RotOscCenter[0] = value.property.floatValue;
2057 else if (propertyName == "CenterV")
2059 currentResTexture.AddModificator()->m_RotOscCenter[1] = value.property.floatValue;
2062 else if (subCategoryName == "Oscillator")
2064 if (propertyName == "TypeU")
2066 currentResTexture.AddModificator()->m_eMoveType[0] = TryConvertingCStringToETexModMoveType(value.stringValue);
2068 else if (propertyName == "TypeV")
2070 currentResTexture.AddModificator()->m_eMoveType[1] = TryConvertingCStringToETexModMoveType(value.stringValue);
2072 else if (propertyName == "RateU")
2074 currentResTexture.AddModificator()->m_OscRate[0] = value.property.floatValue;
2076 else if (propertyName == "RateV")
2078 currentResTexture.AddModificator()->m_OscRate[1] = value.property.floatValue;
2080 else if (propertyName == "PhaseU")
2082 currentResTexture.AddModificator()->m_OscPhase[0] = value.property.floatValue;
2084 else if (propertyName == "PhaseV")
2086 currentResTexture.AddModificator()->m_OscPhase[1] = value.property.floatValue;
2088 else if (propertyName == "AmplitudeU")
2090 currentResTexture.AddModificator()->m_OscAmplitude[0] = value.property.floatValue;
2092 else if (propertyName == "AmplitudeV")
2094 currentResTexture.AddModificator()->m_OscAmplitude[1] = value.property.floatValue;
2099 // ########## Shader Params ##########
2100 else if (categoryName == "Shader Params")
2102 DynArray<SShaderParam>& shaderParams = pMaterial->GetShaderResources().m_ShaderParams;
2104 for (int i = 0; i < shaderParams.size(); i++)
2106 if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script))
2108 if (shaderParams[i].m_Type == eType_FLOAT)
2110 shaderParams[i].m_Value.m_Float = value.property.floatValue;
2111 break;
2113 else if (shaderParams[i].m_Type == eType_FCOLOR)
2115 ColorF colorLinear = CMFCUtils::ColorGammaToLinear(
2116 RGB(
2117 (uint8)value.property.colorValue.r,
2118 (uint8)value.property.colorValue.g,
2119 (uint8)value.property.colorValue.b
2122 shaderParams[i].m_Value.m_Vector[0] = colorLinear.r;
2123 shaderParams[i].m_Value.m_Vector[1] = colorLinear.g;
2124 shaderParams[i].m_Value.m_Vector[2] = colorLinear.b;
2125 break;
2127 else
2129 throw std::runtime_error("Invalid data type (Shader Params)");
2134 // ########## Shader Generation Params ##########
2135 else if (categoryName == "Shader Generation Params")
2137 for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++)
2139 if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName())
2141 CVarBlock* shaderGenBlock = pMaterial->GetShaderGenParamsVars();
2142 shaderGenBlock->GetVariable(i)->Set(value.property.boolValue);
2143 pMaterial->SetShaderGenParamsVars(shaderGenBlock);
2144 break;
2148 // ########## Vertex Deformation ##########
2149 else if (categoryName == "Vertex Deformation")
2151 // ########## Vertex Deformation / [ Type | Wave Length X | Wave Length Y | Wave Length Z | Wave Length W | Noise Scale ] ##########
2152 if (splittedPropertyPath.size() == 2)
2154 if (propertyName == "Type")
2156 pMaterial->GetShaderResources().m_DeformInfo.m_eType = TryConvertingCStringToEDeformType(value.stringValue);
2158 else if (propertyName == "Wave Length X")
2160 pMaterial->GetShaderResources().m_DeformInfo.m_fDividerX = value.property.floatValue;
2162 else if (propertyName == "Wave Length Y")
2164 pMaterial->GetShaderResources().m_DeformInfo.m_fDividerY = value.property.floatValue;
2166 else if (propertyName == "Wave Length Z")
2168 pMaterial->GetShaderResources().m_DeformInfo.m_fDividerZ = value.property.floatValue;
2170 else if (propertyName == "Wave Length W")
2172 pMaterial->GetShaderResources().m_DeformInfo.m_fDividerW = value.property.floatValue;
2174 else if (propertyName == "Noise Scale")
2176 pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[0] = value.property.vecValue.x;
2177 pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[1] = value.property.vecValue.y;
2178 pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[2] = value.property.vecValue.z;
2181 // ########## Vertex Deformation / [ Wave X | Wave Y | Wave Z | Wave W ] ##########
2182 else if (splittedPropertyPath.size() == 3)
2184 if (subCategoryName == "Wave X")
2186 SWaveForm2& currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveX;
2188 if (propertyName == "Type")
2190 currentWaveForm.m_eWFType = TryConvertingCStringToEWaveForm(value.stringValue);
2192 else if (propertyName == "Level")
2194 currentWaveForm.m_Level = value.property.floatValue;
2196 else if (propertyName == "Amplitude")
2198 currentWaveForm.m_Amp = value.property.floatValue;
2200 else if (propertyName == "Phase")
2202 currentWaveForm.m_Phase = value.property.floatValue;
2204 else if (propertyName == "Frequency")
2206 currentWaveForm.m_Freq = value.property.floatValue;
2209 else if (subCategoryName == "Wave Y")
2211 SWaveForm2& currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveY;
2213 if (propertyName == "Type")
2215 currentWaveForm.m_eWFType = TryConvertingCStringToEWaveForm(value.stringValue);
2217 else if (propertyName == "Level")
2219 currentWaveForm.m_Level = value.property.floatValue;
2221 else if (propertyName == "Amplitude")
2223 currentWaveForm.m_Amp = value.property.floatValue;
2225 else if (propertyName == "Phase")
2227 currentWaveForm.m_Phase = value.property.floatValue;
2229 else if (propertyName == "Frequency")
2231 currentWaveForm.m_Freq = value.property.floatValue;
2234 else if (subCategoryName == "Wave Z")
2236 SWaveForm2& currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveZ;
2238 if (propertyName == "Type")
2240 currentWaveForm.m_eWFType = TryConvertingCStringToEWaveForm(value.stringValue);
2242 else if (propertyName == "Level")
2244 currentWaveForm.m_Level = value.property.floatValue;
2246 else if (propertyName == "Amplitude")
2248 currentWaveForm.m_Amp = value.property.floatValue;
2250 else if (propertyName == "Phase")
2252 currentWaveForm.m_Phase = value.property.floatValue;
2254 else if (propertyName == "Frequency")
2256 currentWaveForm.m_Freq = value.property.floatValue;
2259 else if (subCategoryName == "Wave W")
2261 SWaveForm2& currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveW;
2263 if (propertyName == "Type")
2265 currentWaveForm.m_eWFType = TryConvertingCStringToEWaveForm(value.stringValue);
2267 else if (propertyName == "Level")
2269 currentWaveForm.m_Level = value.property.floatValue;
2271 else if (propertyName == "Amplitude")
2273 currentWaveForm.m_Amp = value.property.floatValue;
2275 else if (propertyName == "Phase")
2277 currentWaveForm.m_Phase = value.property.floatValue;
2279 else if (propertyName == "Frequency")
2281 currentWaveForm.m_Freq = value.property.floatValue;
2286 // ########## Layer Presets ##########
2287 else if (categoryName == "Layer Presets")
2289 // names are "Shader1", "Shader2" and "Shader3", bacause all have the name "Shader" in material editor
2290 if (splittedPropertyPath.size() == 2)
2292 int shaderNumber = -1;
2293 if (propertyName == "Shader1")
2295 shaderNumber = 0;
2297 else if (propertyName == "Shader2")
2299 shaderNumber = 1;
2301 else if (propertyName == "Shader3")
2303 shaderNumber = 2;
2306 pMaterial->GetMtlLayerResources()[shaderNumber].m_shaderName = value.stringValue;
2308 else if (splittedPropertyPath.size() == 3)
2310 if (propertyName == "No Draw")
2312 int shaderNumber = -1;
2313 if (subCategoryName == "Shader1")
2315 shaderNumber = 0;
2317 else if (subCategoryName == "Shader2")
2319 shaderNumber = 1;
2321 else if (subCategoryName == "Shader3")
2323 shaderNumber = 2;
2326 if (pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW && value.property.boolValue == false)
2328 pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags = pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags - MTL_LAYER_USAGE_NODRAW;
2330 else if (!(pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW) && value.property.boolValue == true)
2332 pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags = pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags | MTL_LAYER_USAGE_NODRAW;
2338 pMaterial->Update();
2339 pMaterial->Save();
2340 GetIEditorImpl()->GetMaterialManager()->OnUpdateProperties(pMaterial);
2344 DECLARE_PYTHON_MODULE(material);
2346 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialCreate, material, create,
2347 "Creates a material.",
2348 "material.create()");
2349 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialCreateMulti, material, create_multi,
2350 "Creates a multi-material.",
2351 "material.create_multi()");
2352 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialConvertToMulti, material, convert_to_multi,
2353 "Converts the selected material to a multi-material.",
2354 "material.convert_to_multi()");
2355 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialDuplicateCurrent, material, duplicate_current,
2356 "Duplicates the current material.",
2357 "material.duplicate_current()");
2358 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialMergeSelection, material, merge_selection,
2359 "Merges the selected materials.",
2360 "material.merge_selection()");
2361 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialDeleteCurrent, material, delete_current,
2362 "Deletes the current material.",
2363 "material.delete_current()");
2364 REGISTER_PYTHON_COMMAND(PyCreateTerrainLayer, material, create_terrain_layer, "");
2366 REGISTER_EDITOR_AND_SCRIPT_COMMAND(PyMaterialAssignCurrentToSelection, material, assign_current_to_selection,
2367 CCommandDescription("Assigns the current material to the selection."))
2368 REGISTER_EDITOR_UI_COMMAND_DESC(material, assign_current_to_selection, "Assign Current", "", "icons:MaterialEditor/Material_Editor_Assign_To_Object.ico", false)
2369 REGISTER_COMMAND_REMAPPING(ui_action, actionMaterial_Assign_Current, material, assign_current_to_selection)
2371 REGISTER_EDITOR_AND_SCRIPT_COMMAND(PyMaterialResetSelection, material, reset_selection,
2372 CCommandDescription("Resets the materials of the selection."))
2373 REGISTER_EDITOR_UI_COMMAND_DESC(material, reset_selection, "Reset to Default", "", "icons:MaterialEditor/Material_Editor_Reset_Material.ico", false)
2374 REGISTER_COMMAND_REMAPPING(ui_action, actionMaterial_Reset_to_Default, material, reset_selection)
2376 REGISTER_EDITOR_AND_SCRIPT_COMMAND(PyMaterialSetCurrentFromObject, material, set_current_from_object,
2377 CCommandDescription("Sets the current material to the material of a selected object."))
2378 REGISTER_EDITOR_UI_COMMAND_DESC(material, set_current_from_object, "Get from Selected", "", "icons:MaterialEditor/Material_Editor_Pick_From_Object.ico", false)
2379 REGISTER_COMMAND_REMAPPING(ui_action, actionMaterial_Get_from_Selected, material, set_current_from_object)
2381 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyMaterialSelectObjectsWithCurrent, material, select_objects_with_current,
2382 "Selects the objects which have the current material.",
2383 "material.select_objects_with_current()");
2384 REGISTER_PYTHON_COMMAND_WITH_EXAMPLE(PyGetSubMaterial, material, get_submaterial,
2385 "Gets sub materials of an material.",
2386 "material.get_submaterial()");
2387 REGISTER_ONLY_PYTHON_COMMAND_WITH_EXAMPLE(PyGetProperty, material, get_property,
2388 "Gets a property of a material.",
2389 "material.get_property(str materialPath/materialName, str propertyPath/propertyName)");
2390 REGISTER_ONLY_PYTHON_COMMAND_WITH_EXAMPLE(PySetProperty, material, set_property,
2391 "Sets a property of a material.",
2392 "material.set_property(str materialPath/materialName, str propertyPath/propertyName, [ str | (int, int, int) | (float, float, float) | int | float | bool ] value)");