EditorMaterial.as 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. // Urho3D material editor
  2. Window@ materialWindow;
  3. Material@ editMaterial;
  4. XMLFile@ oldMaterialState;
  5. bool inMaterialRefresh = true;
  6. View3D@ materialPreview;
  7. Scene@ previewScene;
  8. Node@ previewCameraNode;
  9. Node@ previewLightNode;
  10. Light@ previewLight;
  11. Node@ previewModelNode;
  12. StaticModel@ previewModel;
  13. void CreateMaterialEditor()
  14. {
  15. if (materialWindow !is null)
  16. return;
  17. materialWindow = LoadEditorUI("UI/EditorMaterialWindow.xml");
  18. ui.root.AddChild(materialWindow);
  19. materialWindow.opacity = uiMaxOpacity;
  20. InitMaterialPreview();
  21. InitModelPreviewList();
  22. RefreshMaterialEditor();
  23. int height = Min(ui.root.height - 60, 600);
  24. materialWindow.SetSize(400, height);
  25. CenterDialog(materialWindow);
  26. HideMaterialEditor();
  27. SubscribeToEvent(materialWindow.GetChild("NewButton", true), "Released", "NewMaterial");
  28. SubscribeToEvent(materialWindow.GetChild("RevertButton", true), "Released", "RevertMaterial");
  29. SubscribeToEvent(materialWindow.GetChild("SaveButton", true), "Released", "SaveMaterial");
  30. SubscribeToEvent(materialWindow.GetChild("SaveAsButton", true), "Released", "SaveMaterialAs");
  31. SubscribeToEvent(materialWindow.GetChild("CloseButton", true), "Released", "HideMaterialEditor");
  32. SubscribeToEvent(materialWindow.GetChild("NewParameterDropDown", true), "ItemSelected", "CreateShaderParameter");
  33. SubscribeToEvent(materialWindow.GetChild("DeleteParameterButton", true), "Released", "DeleteShaderParameter");
  34. SubscribeToEvent(materialWindow.GetChild("NewTechniqueButton", true), "Released", "NewTechnique");
  35. SubscribeToEvent(materialWindow.GetChild("DeleteTechniqueButton", true), "Released", "DeleteTechnique");
  36. SubscribeToEvent(materialWindow.GetChild("SortTechniquesButton", true), "Released", "SortTechniques");
  37. SubscribeToEvent(materialWindow.GetChild("ConstantBiasEdit", true), "TextChanged", "EditConstantBias");
  38. SubscribeToEvent(materialWindow.GetChild("ConstantBiasEdit", true), "TextFinished", "EditConstantBias");
  39. SubscribeToEvent(materialWindow.GetChild("SlopeBiasEdit", true), "TextChanged", "EditSlopeBias");
  40. SubscribeToEvent(materialWindow.GetChild("SlopeBiasEdit", true), "TextFinished", "EditSlopeBias");
  41. SubscribeToEvent(materialWindow.GetChild("CullModeEdit", true), "ItemSelected", "EditCullMode");
  42. SubscribeToEvent(materialWindow.GetChild("ShadowCullModeEdit", true), "ItemSelected", "EditShadowCullMode");
  43. SubscribeToEvent(materialWindow.GetChild("FillModeEdit", true), "ItemSelected", "EditFillMode");
  44. }
  45. bool ShowMaterialEditor()
  46. {
  47. RefreshMaterialEditor();
  48. materialWindow.visible = true;
  49. materialWindow.BringToFront();
  50. return true;
  51. }
  52. void HideMaterialEditor()
  53. {
  54. materialWindow.visible = false;
  55. }
  56. void InitMaterialPreview()
  57. {
  58. previewScene = Scene("PreviewScene");
  59. previewScene.CreateComponent("Octree");
  60. Node@ zoneNode = previewScene.CreateChild("Zone");
  61. Zone@ zone = zoneNode.CreateComponent("Zone");
  62. zone.boundingBox = BoundingBox(-1000, 1000);
  63. zone.ambientColor = Color(0.15, 0.15, 0.15);
  64. zone.fogColor = Color(0, 0, 0);
  65. zone.fogStart = 10.0;
  66. zone.fogEnd = 100.0;
  67. previewCameraNode = previewScene.CreateChild("PreviewCamera");
  68. previewCameraNode.position = Vector3(0, 0, -1.5);
  69. Camera@ camera = previewCameraNode.CreateComponent("Camera");
  70. camera.nearClip = 0.1f;
  71. camera.farClip = 100.0f;
  72. previewLightNode = previewScene.CreateChild("PreviewLight");
  73. previewLightNode.direction = Vector3(0.5, -0.5, 0.5);
  74. previewLight = previewLightNode.CreateComponent("Light");
  75. previewLight.lightType = LIGHT_DIRECTIONAL;
  76. previewLight.specularIntensity = 0.5;
  77. previewModelNode = previewScene.CreateChild("PreviewModel");
  78. previewModelNode.rotation = Quaternion(0, 0, 0);
  79. previewModel = previewModelNode.CreateComponent("StaticModel");
  80. previewModel.model = cache.GetResource("Model", "Models/Sphere.mdl");
  81. materialPreview = materialWindow.GetChild("MaterialPreview", true);
  82. materialPreview.SetFixedHeight(100);
  83. materialPreview.SetView(previewScene, camera);
  84. materialPreview.viewport.renderPath = renderPath;
  85. materialPreview.autoUpdate = false;
  86. SubscribeToEvent(materialPreview, "DragMove", "RotateMaterialPreview");
  87. }
  88. void InitModelPreviewList()
  89. {
  90. DropDownList@ modelPreview = materialWindow.GetChild("ModelPreview", true);
  91. SubscribeToEvent(materialWindow.GetChild("ModelPreview", true), "ItemSelected", "EditModelPreviewChange");
  92. }
  93. void EditMaterial(Material@ mat)
  94. {
  95. if (editMaterial !is null)
  96. UnsubscribeFromEvent(editMaterial, "ReloadFinished");
  97. editMaterial = mat;
  98. if (editMaterial !is null)
  99. SubscribeToEvent(editMaterial, "ReloadFinished", "RefreshMaterialEditor");
  100. ShowMaterialEditor();
  101. }
  102. void RefreshMaterialEditor()
  103. {
  104. RefreshMaterialPreview();
  105. RefreshMaterialName();
  106. RefreshMaterialTechniques();
  107. RefreshMaterialTextures();
  108. RefreshMaterialShaderParameters();
  109. RefreshMaterialMiscParameters();
  110. }
  111. void RefreshMaterialPreview()
  112. {
  113. previewModel.material = editMaterial;
  114. materialPreview.QueueUpdate();
  115. }
  116. void RefreshMaterialName()
  117. {
  118. UIElement@ container = materialWindow.GetChild("NameContainer", true);
  119. container.RemoveAllChildren();
  120. LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
  121. if (editMaterial !is null)
  122. nameEdit.text = editMaterial.name;
  123. SubscribeToEvent(nameEdit, "TextFinished", "EditMaterialName");
  124. Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "smallButtonPick");
  125. SubscribeToEvent(pickButton, "Released", "PickEditMaterial");
  126. }
  127. void RefreshMaterialTechniques(bool fullUpdate = true)
  128. {
  129. ListView@ list = materialWindow.GetChild("TechniqueList", true);
  130. if (editMaterial is null)
  131. return;
  132. if (fullUpdate == true)
  133. {
  134. list.RemoveAllItems();
  135. for (uint i = 0; i < editMaterial.numTechniques; ++i)
  136. {
  137. TechniqueEntry entry = editMaterial.techniqueEntries[i];
  138. UIElement@ container = UIElement();
  139. container.SetLayout(LM_HORIZONTAL, 4);
  140. container.SetFixedHeight(ATTR_HEIGHT);
  141. list.AddItem(container);
  142. LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, i, 0);
  143. nameEdit.name = "TechniqueNameEdit" + String(i);
  144. Button@ pickButton = CreateResourcePickerButton(container, null, i, 0, "smallButtonPick");
  145. SubscribeToEvent(pickButton, "Released", "PickMaterialTechnique");
  146. Button@ openButton = CreateResourcePickerButton(container, null, i, 0, "smallButtonOpen");
  147. SubscribeToEvent(openButton, "Released", "OpenResource");
  148. if (entry.technique !is null)
  149. nameEdit.text = entry.technique.name;
  150. SubscribeToEvent(nameEdit, "TextFinished", "EditMaterialTechnique");
  151. UIElement@ container2 = UIElement();
  152. container2.SetLayout(LM_HORIZONTAL, 4);
  153. container2.SetFixedHeight(ATTR_HEIGHT);
  154. list.AddItem(container2);
  155. Text@ text = container2.CreateChild("Text");
  156. text.style = "EditorAttributeText";
  157. text.text = "Quality";
  158. LineEdit@ attrEdit = CreateAttributeLineEdit(container2, null, i, 0);
  159. attrEdit.text = String(entry.qualityLevel);
  160. SubscribeToEvent(attrEdit, "TextChanged", "EditTechniqueQuality");
  161. SubscribeToEvent(attrEdit, "TextFinished", "EditTechniqueQuality");
  162. text = container2.CreateChild("Text");
  163. text.style = "EditorAttributeText";
  164. text.text = "LOD Distance";
  165. attrEdit = CreateAttributeLineEdit(container2, null, i, 0);
  166. attrEdit.text = String(entry.lodDistance);
  167. SubscribeToEvent(attrEdit, "TextChanged", "EditTechniqueLodDistance");
  168. SubscribeToEvent(attrEdit, "TextFinished", "EditTechniqueLodDistance");
  169. }
  170. }
  171. else
  172. {
  173. for (uint i = 0; i < editMaterial.numTechniques; ++i)
  174. {
  175. TechniqueEntry entry = editMaterial.techniqueEntries[i];
  176. LineEdit@ nameEdit = materialWindow.GetChild("TechniqueNameEdit" + String(i), true);
  177. if (nameEdit is null)
  178. continue;
  179. nameEdit.text = entry.technique !is null ? entry.technique.name : "";
  180. }
  181. }
  182. }
  183. void RefreshMaterialTextures(bool fullUpdate = true)
  184. {
  185. if (fullUpdate)
  186. {
  187. ListView@ list = materialWindow.GetChild("TextureList", true);
  188. list.RemoveAllItems();
  189. for (uint i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
  190. {
  191. String tuName = GetTextureUnitName(TextureUnit(i));
  192. tuName[0] = ToUpper(tuName[0]);
  193. UIElement@ parent = CreateAttributeEditorParentWithSeparatedLabel(list, "Unit " + i + " " + tuName, i, 0, false);
  194. UIElement@ container = UIElement();
  195. container.SetLayout(LM_HORIZONTAL, 4, IntRect(10, 0, 4, 0));
  196. container.SetFixedHeight(ATTR_HEIGHT);
  197. parent.AddChild(container);
  198. LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, i, 0);
  199. nameEdit.name = "TextureNameEdit" + String(i);
  200. Button@ pickButton = CreateResourcePickerButton(container, null, i, 0, "smallButtonPick");
  201. SubscribeToEvent(pickButton, "Released", "PickMaterialTexture");
  202. Button@ openButton = CreateResourcePickerButton(container, null, i, 0, "smallButtonOpen");
  203. SubscribeToEvent(openButton, "Released", "OpenResource");
  204. if (editMaterial !is null)
  205. {
  206. Texture@ texture = editMaterial.textures[i];
  207. if (texture !is null)
  208. nameEdit.text = texture.name;
  209. }
  210. SubscribeToEvent(nameEdit, "TextFinished", "EditMaterialTexture");
  211. }
  212. }
  213. else
  214. {
  215. for (uint i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
  216. {
  217. LineEdit@ nameEdit = materialWindow.GetChild("TextureNameEdit" + String(i), true);
  218. if (nameEdit is null)
  219. continue;
  220. String textureName;
  221. if (editMaterial !is null)
  222. {
  223. Texture@ texture = editMaterial.textures[i];
  224. if (texture !is null)
  225. textureName = texture.name;
  226. }
  227. nameEdit.text = textureName;
  228. }
  229. }
  230. }
  231. void RefreshMaterialShaderParameters()
  232. {
  233. ListView@ list = materialWindow.GetChild("ShaderParameterList", true);
  234. list.RemoveAllItems();
  235. if (editMaterial is null)
  236. return;
  237. Array<String>@ parameterNames = editMaterial.shaderParameterNames;
  238. for (uint i = 0; i < parameterNames.length; ++i)
  239. {
  240. VariantType type = editMaterial.shaderParameters[parameterNames[i]].type;
  241. Variant value = editMaterial.shaderParameters[parameterNames[i]];
  242. UIElement@ parent = CreateAttributeEditorParent(list, parameterNames[i], 0, 0);
  243. uint numCoords = type - VAR_FLOAT + 1;
  244. Array<String> coordValues = value.ToString().Split(' ');
  245. for (uint j = 0; j < numCoords; ++j)
  246. {
  247. LineEdit@ attrEdit = CreateAttributeLineEdit(parent, null, 0, 0);
  248. attrEdit.vars["Coordinate"] = j;
  249. attrEdit.vars["Name"] = parameterNames[i];
  250. attrEdit.text = coordValues[j];
  251. CreateDragSlider(attrEdit);
  252. SubscribeToEvent(attrEdit, "TextChanged", "EditShaderParameter");
  253. SubscribeToEvent(attrEdit, "TextFinished", "EditShaderParameter");
  254. }
  255. }
  256. }
  257. void RefreshMaterialMiscParameters()
  258. {
  259. if (editMaterial is null)
  260. return;
  261. BiasParameters bias = editMaterial.depthBias;
  262. inMaterialRefresh = true;
  263. LineEdit@ attrEdit = materialWindow.GetChild("ConstantBiasEdit", true);
  264. attrEdit.text = String(bias.constantBias);
  265. attrEdit = materialWindow.GetChild("SlopeBiasEdit", true);
  266. attrEdit.text = String(bias.slopeScaledBias);
  267. DropDownList@ attrList = materialWindow.GetChild("CullModeEdit", true);
  268. attrList.selection = editMaterial.cullMode;
  269. attrList = materialWindow.GetChild("ShadowCullModeEdit", true);
  270. attrList.selection = editMaterial.shadowCullMode;
  271. attrList = materialWindow.GetChild("FillModeEdit", true);
  272. attrList.selection = editMaterial.fillMode;
  273. inMaterialRefresh = false;
  274. }
  275. void RotateMaterialPreview(StringHash eventType, VariantMap& eventData)
  276. {
  277. int elemX = eventData["ElementX"].GetInt();
  278. int elemY = eventData["ElementY"].GetInt();
  279. if (materialPreview.height > 0 && materialPreview.width > 0)
  280. {
  281. float yaw = ((materialPreview.height / 2) - elemY) * (90.0 / materialPreview.height);
  282. float pitch = ((materialPreview.width / 2) - elemX) * (90.0 / materialPreview.width);
  283. previewModelNode.rotation = previewModelNode.rotation.Slerp(Quaternion(yaw, pitch, 0), 0.1);
  284. materialPreview.QueueUpdate();
  285. }
  286. }
  287. void EditMaterialName(StringHash eventType, VariantMap& eventData)
  288. {
  289. LineEdit@ nameEdit = eventData["Element"].GetPtr();
  290. String newMaterialName = nameEdit.text.Trimmed();
  291. if (!newMaterialName.empty)
  292. {
  293. Material@ newMaterial = cache.GetResource("Material", newMaterialName);
  294. if (newMaterial !is null)
  295. EditMaterial(newMaterial);
  296. }
  297. }
  298. void PickEditMaterial()
  299. {
  300. @resourcePicker = GetResourcePicker(StringHash("Material"));
  301. if (resourcePicker is null)
  302. return;
  303. String lastPath = resourcePicker.lastPath;
  304. if (lastPath.empty)
  305. lastPath = sceneResourcePath;
  306. CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
  307. SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditMaterialDone");
  308. }
  309. void PickEditMaterialDone(StringHash eventType, VariantMap& eventData)
  310. {
  311. StoreResourcePickerPath();
  312. CloseFileSelector();
  313. if (!eventData["OK"].GetBool())
  314. {
  315. @resourcePicker = null;
  316. return;
  317. }
  318. String resourceName = eventData["FileName"].GetString();
  319. Resource@ res = GetPickedResource(resourceName);
  320. if (res !is null)
  321. EditMaterial(cast<Material>(res));
  322. @resourcePicker = null;
  323. }
  324. void NewMaterial()
  325. {
  326. EditMaterial(Material());
  327. }
  328. void RevertMaterial()
  329. {
  330. if (editMaterial is null)
  331. return;
  332. BeginMaterialEdit();
  333. cache.ReloadResource(editMaterial);
  334. EndMaterialEdit();
  335. RefreshMaterialEditor();
  336. }
  337. void SaveMaterial()
  338. {
  339. if (editMaterial is null || editMaterial.name.empty)
  340. return;
  341. String fullName = cache.GetResourceFileName(editMaterial.name);
  342. if (fullName.empty)
  343. return;
  344. MakeBackup(fullName);
  345. File saveFile(fullName, FILE_WRITE);
  346. bool success = editMaterial.Save(saveFile);
  347. RemoveBackup(success, fullName);
  348. }
  349. void SaveMaterialAs()
  350. {
  351. if (editMaterial is null)
  352. return;
  353. @resourcePicker = GetResourcePicker(StringHash("Material"));
  354. if (resourcePicker is null)
  355. return;
  356. String lastPath = resourcePicker.lastPath;
  357. if (lastPath.empty)
  358. lastPath = sceneResourcePath;
  359. CreateFileSelector("Save material as", "Save", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
  360. SubscribeToEvent(uiFileSelector, "FileSelected", "SaveMaterialAsDone");
  361. }
  362. void SaveMaterialAsDone(StringHash eventType, VariantMap& eventData)
  363. {
  364. StoreResourcePickerPath();
  365. CloseFileSelector();
  366. @resourcePicker = null;
  367. if (editMaterial is null)
  368. return;
  369. if (!eventData["OK"].GetBool())
  370. {
  371. @resourcePicker = null;
  372. return;
  373. }
  374. String fullName = eventData["FileName"].GetString();
  375. // Add default extension for saving if not specified
  376. String filter = eventData["Filter"].GetString();
  377. if (GetExtension(fullName).empty && filter != "*.*")
  378. fullName = fullName + filter.Substring(1);
  379. MakeBackup(fullName);
  380. File saveFile(fullName, FILE_WRITE);
  381. if (editMaterial.Save(saveFile))
  382. {
  383. saveFile.Close();
  384. RemoveBackup(true, fullName);
  385. // Load the new resource to update the name in the editor
  386. Material@ newMat = cache.GetResource("Material", GetResourceNameFromFullName(fullName));
  387. if (newMat !is null)
  388. EditMaterial(newMat);
  389. }
  390. }
  391. void EditModelPreviewChange(StringHash eventType, VariantMap& eventData)
  392. {
  393. if (materialPreview is null)
  394. return;
  395. previewModelNode.scale = Vector3(1.0, 1.0, 1.0);
  396. DropDownList@ element = eventData["Element"].GetPtr();
  397. switch (element.selection)
  398. {
  399. case 0:
  400. previewModel.model = cache.GetResource("Model", "Models/Box.mdl");
  401. break;
  402. case 1:
  403. previewModel.model = cache.GetResource("Model", "Models/Sphere.mdl");
  404. break;
  405. case 2:
  406. previewModel.model = cache.GetResource("Model", "Models/Plane.mdl");
  407. break;
  408. case 3:
  409. previewModel.model = cache.GetResource("Model", "Models/Cylinder.mdl");
  410. previewModelNode.scale = Vector3(0.8, 0.8, 0.8);
  411. break;
  412. case 4:
  413. previewModel.model = cache.GetResource("Model", "Models/Cone.mdl");
  414. break;
  415. case 5:
  416. previewModel.model = cache.GetResource("Model", "Models/TeaPot.mdl");
  417. break;
  418. }
  419. materialPreview.QueueUpdate();
  420. }
  421. void EditShaderParameter(StringHash eventType, VariantMap& eventData)
  422. {
  423. if (editMaterial is null)
  424. return;
  425. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  426. uint coordinate = attrEdit.vars["Coordinate"].GetUInt();
  427. String name = attrEdit.vars["Name"].GetString();
  428. Variant oldValue = editMaterial.shaderParameters[name];
  429. Array<String> coordValues = oldValue.ToString().Split(' ');
  430. coordValues[coordinate] = String(attrEdit.text.ToFloat());
  431. String valueString;
  432. for (uint i = 0; i < coordValues.length; ++i)
  433. {
  434. valueString += coordValues[i];
  435. valueString += " ";
  436. }
  437. Variant newValue;
  438. newValue.FromString(oldValue.type, valueString);
  439. BeginMaterialEdit();
  440. editMaterial.shaderParameters[name] = newValue;
  441. EndMaterialEdit();
  442. }
  443. void CreateShaderParameter(StringHash eventType, VariantMap& eventData)
  444. {
  445. if (editMaterial is null)
  446. return;
  447. LineEdit@ nameEdit = materialWindow.GetChild("ParameterNameEdit", true);
  448. String newName = nameEdit.text.Trimmed();
  449. if (newName.empty)
  450. return;
  451. DropDownList@ dropDown = eventData["Element"].GetPtr();
  452. Variant newValue;
  453. switch (dropDown.selection)
  454. {
  455. case 0:
  456. newValue = float(0);
  457. break;
  458. case 1:
  459. newValue = Vector2(0, 0);
  460. break;
  461. case 2:
  462. newValue = Vector3(0, 0, 0);
  463. break;
  464. case 3:
  465. newValue = Vector4(0, 0, 0, 0);
  466. break;
  467. }
  468. BeginMaterialEdit();
  469. editMaterial.shaderParameters[newName] = newValue;
  470. EndMaterialEdit();
  471. RefreshMaterialShaderParameters();
  472. }
  473. void DeleteShaderParameter()
  474. {
  475. if (editMaterial is null)
  476. return;
  477. LineEdit@ nameEdit = materialWindow.GetChild("ParameterNameEdit", true);
  478. String name = nameEdit.text.Trimmed();
  479. if (name.empty)
  480. return;
  481. BeginMaterialEdit();
  482. editMaterial.RemoveShaderParameter(name);
  483. EndMaterialEdit();
  484. RefreshMaterialShaderParameters();
  485. }
  486. void PickMaterialTexture(StringHash eventType, VariantMap& eventData)
  487. {
  488. if (editMaterial is null)
  489. return;
  490. UIElement@ button = eventData["Element"].GetPtr();
  491. resourcePickIndex = button.vars["Index"].GetUInt();
  492. @resourcePicker = GetResourcePicker(StringHash("Texture2D"));
  493. if (resourcePicker is null)
  494. return;
  495. String lastPath = resourcePicker.lastPath;
  496. if (lastPath.empty)
  497. lastPath = sceneResourcePath;
  498. CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
  499. SubscribeToEvent(uiFileSelector, "FileSelected", "PickMaterialTextureDone");
  500. }
  501. void PickMaterialTextureDone(StringHash eventType, VariantMap& eventData)
  502. {
  503. StoreResourcePickerPath();
  504. CloseFileSelector();
  505. if (!eventData["OK"].GetBool())
  506. {
  507. @resourcePicker = null;
  508. return;
  509. }
  510. String resourceName = eventData["FileName"].GetString();
  511. Resource@ res = GetPickedResource(resourceName);
  512. if (res !is null && editMaterial !is null)
  513. {
  514. BeginMaterialEdit();
  515. editMaterial.textures[resourcePickIndex] = res;
  516. EndMaterialEdit();
  517. RefreshMaterialTextures(false);
  518. }
  519. @resourcePicker = null;
  520. }
  521. void EditMaterialTexture(StringHash eventType, VariantMap& eventData)
  522. {
  523. if (editMaterial is null)
  524. return;
  525. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  526. String textureName = attrEdit.text.Trimmed();
  527. uint index = attrEdit.vars["Index"].GetUInt();
  528. BeginMaterialEdit();
  529. if (!textureName.empty)
  530. {
  531. Texture@ texture = cache.GetResource(GetExtension(textureName) == ".xml" ? "TextureCube" : "Texture2D", textureName);
  532. editMaterial.textures[index] = texture;
  533. }
  534. else
  535. editMaterial.textures[index] = null;
  536. EndMaterialEdit();
  537. }
  538. void NewTechnique()
  539. {
  540. if (editMaterial is null)
  541. return;
  542. BeginMaterialEdit();
  543. editMaterial.numTechniques = editMaterial.numTechniques + 1;
  544. EndMaterialEdit();
  545. RefreshMaterialTechniques();
  546. }
  547. void DeleteTechnique()
  548. {
  549. if (editMaterial is null || editMaterial.numTechniques < 2)
  550. return;
  551. BeginMaterialEdit();
  552. editMaterial.numTechniques = editMaterial.numTechniques - 1;
  553. EndMaterialEdit();
  554. RefreshMaterialTechniques();
  555. }
  556. void PickMaterialTechnique(StringHash eventType, VariantMap& eventData)
  557. {
  558. if (editMaterial is null)
  559. return;
  560. UIElement@ button = eventData["Element"].GetPtr();
  561. resourcePickIndex = button.vars["Index"].GetUInt();
  562. @resourcePicker = GetResourcePicker(StringHash("Technique"));
  563. if (resourcePicker is null)
  564. return;
  565. String lastPath = resourcePicker.lastPath;
  566. if (lastPath.empty)
  567. lastPath = sceneResourcePath;
  568. CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
  569. SubscribeToEvent(uiFileSelector, "FileSelected", "PickMaterialTechniqueDone");
  570. }
  571. void PickMaterialTechniqueDone(StringHash eventType, VariantMap& eventData)
  572. {
  573. StoreResourcePickerPath();
  574. CloseFileSelector();
  575. if (!eventData["OK"].GetBool())
  576. {
  577. @resourcePicker = null;
  578. return;
  579. }
  580. String resourceName = eventData["FileName"].GetString();
  581. Resource@ res = GetPickedResource(resourceName);
  582. if (res !is null && editMaterial !is null)
  583. {
  584. BeginMaterialEdit();
  585. TechniqueEntry entry = editMaterial.techniqueEntries[resourcePickIndex];
  586. editMaterial.SetTechnique(resourcePickIndex, res, entry.qualityLevel, entry.lodDistance);
  587. EndMaterialEdit();
  588. RefreshMaterialTechniques(false);
  589. }
  590. @resourcePicker = null;
  591. }
  592. void EditMaterialTechnique(StringHash eventType, VariantMap& eventData)
  593. {
  594. if (editMaterial is null)
  595. return;
  596. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  597. String techniqueName = attrEdit.text.Trimmed();
  598. uint index = attrEdit.vars["Index"].GetUInt();
  599. BeginMaterialEdit();
  600. Technique@ newTech;
  601. if (!techniqueName.empty)
  602. newTech = cache.GetResource("Technique", techniqueName);
  603. TechniqueEntry entry = editMaterial.techniqueEntries[index];
  604. editMaterial.SetTechnique(index, newTech, entry.qualityLevel, entry.lodDistance);
  605. EndMaterialEdit();
  606. }
  607. void EditTechniqueQuality(StringHash eventType, VariantMap& eventData)
  608. {
  609. if (editMaterial is null)
  610. return;
  611. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  612. uint newQualityLevel = attrEdit.text.ToUInt();
  613. uint index = attrEdit.vars["Index"].GetUInt();
  614. BeginMaterialEdit();
  615. TechniqueEntry entry = editMaterial.techniqueEntries[index];
  616. editMaterial.SetTechnique(index, entry.technique, newQualityLevel, entry.lodDistance);
  617. EndMaterialEdit();
  618. }
  619. void EditTechniqueLodDistance(StringHash eventType, VariantMap& eventData)
  620. {
  621. if (editMaterial is null)
  622. return;
  623. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  624. float newLodDistance = attrEdit.text.ToFloat();
  625. uint index = attrEdit.vars["Index"].GetUInt();
  626. BeginMaterialEdit();
  627. TechniqueEntry entry = editMaterial.techniqueEntries[index];
  628. editMaterial.SetTechnique(index, entry.technique, entry.qualityLevel, newLodDistance);
  629. EndMaterialEdit();
  630. }
  631. void SortTechniques()
  632. {
  633. if (editMaterial is null)
  634. return;
  635. BeginMaterialEdit();
  636. editMaterial.SortTechniques();
  637. EndMaterialEdit();
  638. RefreshMaterialTechniques();
  639. }
  640. void EditConstantBias(StringHash eventType, VariantMap& eventData)
  641. {
  642. if (editMaterial is null || inMaterialRefresh)
  643. return;
  644. BeginMaterialEdit();
  645. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  646. BiasParameters bias = editMaterial.depthBias;
  647. bias.constantBias = attrEdit.text.ToFloat();
  648. editMaterial.depthBias = bias;
  649. EndMaterialEdit();
  650. }
  651. void EditSlopeBias(StringHash eventType, VariantMap& eventData)
  652. {
  653. if (editMaterial is null || inMaterialRefresh)
  654. return;
  655. BeginMaterialEdit();
  656. LineEdit@ attrEdit = eventData["Element"].GetPtr();
  657. BiasParameters bias = editMaterial.depthBias;
  658. bias.slopeScaledBias = attrEdit.text.ToFloat();
  659. editMaterial.depthBias = bias;
  660. EndMaterialEdit();
  661. }
  662. void EditCullMode(StringHash eventType, VariantMap& eventData)
  663. {
  664. if (editMaterial is null || inMaterialRefresh)
  665. return;
  666. BeginMaterialEdit();
  667. DropDownList@ attrEdit = eventData["Element"].GetPtr();
  668. editMaterial.cullMode = CullMode(attrEdit.selection);
  669. EndMaterialEdit();
  670. }
  671. void EditShadowCullMode(StringHash eventType, VariantMap& eventData)
  672. {
  673. if (editMaterial is null || inMaterialRefresh)
  674. return;
  675. BeginMaterialEdit();
  676. DropDownList@ attrEdit = eventData["Element"].GetPtr();
  677. editMaterial.shadowCullMode = CullMode(attrEdit.selection);
  678. EndMaterialEdit();
  679. }
  680. void EditFillMode(StringHash eventType, VariantMap& eventData)
  681. {
  682. if (editMaterial is null || inMaterialRefresh)
  683. return;
  684. BeginMaterialEdit();
  685. DropDownList@ attrEdit = eventData["Element"].GetPtr();
  686. editMaterial.fillMode = FillMode(attrEdit.selection);
  687. EndMaterialEdit();
  688. }
  689. void BeginMaterialEdit()
  690. {
  691. if (editMaterial is null)
  692. return;
  693. oldMaterialState = XMLFile();
  694. XMLElement materialElem = oldMaterialState.CreateRoot("material");
  695. editMaterial.Save(materialElem);
  696. }
  697. void EndMaterialEdit()
  698. {
  699. if (editMaterial is null)
  700. return;
  701. if (!dragEditAttribute)
  702. {
  703. EditMaterialAction@ action = EditMaterialAction();
  704. action.Define(editMaterial, oldMaterialState);
  705. SaveEditAction(action);
  706. }
  707. materialPreview.QueueUpdate();
  708. }