[email protected] 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. MaterialRegion MtrlEdit;
  5. /******************************************************************************/
  6. MaterialTech mtrl_techs[]=
  7. {
  8. {"Default" , u"Standard rendering of solid (opaque) materials."},
  9. {"Alpha Test" , u"Indicates that textures alpha channel will be used as models transparency.\nThis is slightly slower than Default as alpha testing may disable some hardware-level optimizations."},
  10. {"Fur" , u"Mesh will be rendered with fur effect, the mesh will be wrapped with additional fur imitating textures.\nDetail Scale specifies fur intensity, Detail Power specifies fur length.\nSupported only in Deferred Renderer!"},
  11. {"Grass" , u"Mesh vertexes will bend on the wind like grass,\nbending intensity is determined by mesh vertex source Y position,\nwhich should be in the range from 0 to 1."},
  12. {"Leaf" , u"Mesh vertexes will bend on the wind like tree leafs,\nto use this technique mesh must also contain leaf attachment positions,\nwhich can be generated in the Model Editor tool through menu options."},
  13. {"Blend" , u"Mesh will be smoothly blended on the screen using alpha values,\nmesh will not be affected by lighting or shadowing."},
  14. {"Blend Light" , u"Works like Blend technique except that mesh will be affected by lighting or shadowing,\nhowever only the most significant directional light will be used (all other lights are ignored)\nDue to additional lighting calculations this is slower than Blend technique."},
  15. {"Blend Light Grass" , u"Combination of Blend Light and Grass techniques."},
  16. {"Blend Light Leaf" , u"Combination of Blend Light and Leaf techniques."},
  17. {"Test Blend Light" , u"Works like Blend Light technique with additional Alpha-Testing and Depth-Writing which enables correct Depth-Sorting."},
  18. {"Test Blend Light Grass", u"Works like Blend Light Grass technique with additional Alpha-Testing and Depth-Writing which enables correct Depth-Sorting."},
  19. {"Test Blend Light Leaf" , u"Works like Blend Light Leaf technique with additional Alpha-Testing and Depth-Writing which enables correct Depth-Sorting."},
  20. };
  21. /******************************************************************************/
  22. /******************************************************************************/
  23. cchar8 *MaterialRegion::auto_reload_name="Reload on Change";
  24. cchar8 *MaterialRegion::DownsizeTexMobileText[]=
  25. {
  26. "Full",
  27. "Half",
  28. "Quarter",
  29. };
  30. cchar8 *MaterialRegion::TexQualityiOSText[]=
  31. {
  32. "2-bit Low (default)",
  33. "4-bit High",
  34. };
  35. const flt MaterialRegion::BumpScale=0.10f;
  36. /******************************************************************************/
  37. void MaterialRegion::Change::create(ptr user)
  38. {
  39. data=MtrlEdit.edit;
  40. MtrlEdit.undoVis();
  41. }
  42. void MaterialRegion::Change::apply(ptr user)
  43. {
  44. uint changed=MtrlEdit.edit.undo(data);
  45. MtrlEdit.setChanged();
  46. MtrlEdit.toGui();
  47. D.setShader(MtrlEdit.game());
  48. MtrlEdit.undoVis();
  49. if(changed&(EditMaterial::CHANGED_BASE|EditMaterial::CHANGED_REFL|EditMaterial::CHANGED_DET|EditMaterial::CHANGED_MACRO|EditMaterial::CHANGED_LIGHT))Proj.mtrlTexChanged();
  50. }
  51. void MaterialRegion::Texture::Load(C Str &name, Texture &texture) {texture.setFile(name);}
  52. void MaterialRegion::Texture::Remove( Texture &texture) {texture.setFile(S);}
  53. ImagePtr MaterialRegion::Texture::getImage()
  54. {
  55. if(mr)
  56. {
  57. EditMaterial &em =mr->getEditMtrl ();
  58. C ImagePtr &base_0 =mr->getBase0 (),
  59. &base_1 =mr->getBase1 (),
  60. &macro =mr->getMacro (),
  61. &detail =mr->getDetail (),
  62. &reflection=mr->getReflection(),
  63. &light =mr->getLight ();
  64. switch(type)
  65. {
  66. case TEX_COLOR : if(em. color_map.is() )return base_0; break;
  67. case TEX_ALPHA : if(em. color_map.is() || em.alpha_map.is() )return base_1 ? base_1 : base_0; break;
  68. case TEX_BUMP : if( em.hasBumpMap() )if(base_1)return base_0; break;
  69. case TEX_NORMAL : if(em. normal_map.is() || em.hasBumpMap() )return base_1; break;
  70. case TEX_SPEC : if(em. specular_map.is() )return base_1; break;
  71. case TEX_GLOW : if(em. glow_map.is() && em.tech==MTECH_DEFAULT)return base_1; break;
  72. case TEX_LIGHT : if(em. light_map.is() )return light ; break;
  73. case TEX_MACRO : if(em. macro_map.is() )return macro ; break;
  74. case TEX_DET_COL : if(em. detail_color .is() )return detail; break;
  75. case TEX_DET_BUMP: if(em. detail_bump .is() )return detail; break;
  76. case TEX_DET_NRM : if(em. detail_normal.is() || em.detail_bump.is() )return detail; break;
  77. case TEX_RFL_L : if(em.reflection_map.is() )return reflection; break;
  78. case TEX_RFL_F : if(em.reflection_map.is() )return reflection; break;
  79. case TEX_RFL_R : if(em.reflection_map.is() )return reflection; break;
  80. case TEX_RFL_B : if(em.reflection_map.is() )return reflection; break;
  81. case TEX_RFL_D : if(em.reflection_map.is() )return reflection; break;
  82. case TEX_RFL_U : if(em.reflection_map.is() )return reflection; break;
  83. case TEX_RFL_ALL : if(em.reflection_map.is() )return reflection; break;
  84. }
  85. }
  86. return null;
  87. }
  88. void MaterialRegion::Texture::setDesc()
  89. {
  90. Mems<Edit::FileParams> files=Edit::FileParams::Decode(file); UID image_id; REPA(files)if(DecodeFileName(files[i].name, image_id))files[i].name=Proj.elmFullName(image_id);
  91. Str desc=Replace(text, '\n', ' '); if(C ImagePtr &image=getImage())desc+=S+", "+image->w()+'x'+image->h();
  92. if(type==TEX_MACRO )desc.line()+="Can be set for heightmap materials to decrease repetitiveness of textures.\nBecomes visible at distance of around 100 meters.";
  93. if(type==TEX_LIGHT )desc.line()+="Model must have 2nd set of texture coordinates (VTX_TEX1) in order for lightmap to take effect";
  94. if(type==TEX_RFL_ALL)desc.line()+="Drag and drop an image here to set it for all faces";
  95. FREPA(files){desc+='\n'; desc+=files[i].encode();}
  96. T.desc(desc);
  97. }
  98. void MaterialRegion::Texture::setFile(Str file)
  99. {
  100. // convert multiple lines into separate file params and handle <..> commands
  101. Mems<Edit::FileParams> fps=Edit::FileParams::Decode(file); REPA(fps)
  102. {
  103. Edit::FileParams &fp=fps[i];
  104. if(Contains(fp.name, '<'))fp.name=GetBaseNoExt(fp.name); // we want to support things like "<bump>" but when entering that into 'WindowIO', it may append the path, so when this command is detected, remove the path (and possible extension too)
  105. }
  106. file=Edit::FileParams::Encode(fps);
  107. T.file=file; setDesc();
  108. if(mr)
  109. {
  110. mr->undos.set(null, true);
  111. EditMaterial &mtrl=mr->getEditMtrl();
  112. uint base_tex=mtrl.baseTex(); // get current state of textures before making any change
  113. if(type>=TEX_RFL_L && type<=TEX_RFL_U)file=SetCubeFile(md_file.asText(&mtrl), type-TEX_RFL_L, file);
  114. md_time.as<TimeStamp>(&mtrl).now();
  115. md_file.fromText (&mtrl, file);
  116. if(!file.is()) // if removing texture
  117. {
  118. Str name, name2; switch(type)
  119. {
  120. case TEX_COLOR: name="<color>"; break;
  121. case TEX_SPEC : name="<spec>" ; name2="<specular>"; break;
  122. case TEX_BUMP : name="<bump>" ; break;
  123. }
  124. if(name.is())REPA(mr->texs)
  125. {
  126. Texture &tex=mr->texs[i]; if(tex.type>=TEX_COLOR && tex.type<=TEX_GLOW) // iterate all base textures
  127. {
  128. Mems<Edit::FileParams> fps=Edit::FileParams::Decode(tex.md_file.asText(&mtrl)); // get file name of that texture
  129. if(fps.elms()==1 && (fps[0].name==name || name2.is() && fps[0].name==name2)) // if that file is made from removed one
  130. {
  131. tex.md_time.as<TimeStamp>(&mtrl).now();
  132. tex.md_file.fromText (&mtrl, S); // remove too
  133. tex.toGui();
  134. }
  135. }
  136. }
  137. }
  138. // rebuild methods already call 'setChanged'
  139. if(type>=TEX_COLOR && type<=TEX_GLOW )mr->rebuildBase (base_tex);else
  140. if(type>=TEX_DET_COL && type<=TEX_DET_NRM)mr->rebuildDetail ();else
  141. if(type>=TEX_RFL_L && type<=TEX_RFL_ALL)mr->rebuildReflection();else
  142. if(type==TEX_MACRO )mr->rebuildMacro ();else
  143. if(type==TEX_LIGHT )mr->rebuildLight ();else
  144. mr->setChanged ();
  145. // if adjusting reflection texture, then adjust parameters of all other relfection slots, because they are connected
  146. if(type>=TEX_RFL_L && type<=TEX_RFL_ALL)REPA(mr->texs)if(mr->texs[i].type>=TEX_RFL_L && mr->texs[i].type<=TEX_RFL_ALL)mr->texs[i].toGui();
  147. }
  148. }
  149. void MaterialRegion::Texture::toGui()
  150. {
  151. if(mr)
  152. {
  153. file=md_file.asText(&mr->getEditMtrl()); if(type>=TEX_RFL_L && type<=TEX_RFL_U)file=GetCubeFile(file, type-TEX_RFL_L);
  154. setDesc();
  155. }
  156. }
  157. ::MaterialRegion::Texture& MaterialRegion::Texture::create(TEX_TYPE type, C MemberDesc &md_file, C MemberDesc &md_time, Rect rect, C Str &text, MaterialRegion &mr)
  158. {
  159. T.mr=&mr;
  160. T.type=type;
  161. T.md_file=md_file;
  162. T.md_time=md_time;
  163. ::EE::GuiCustom::create().rect(rect.extend(-0.003f)); T.text=text;
  164. win_io.create().ext(SUPPORTED_IMAGE_EXT, Replace(text, '\n', ' ')).io(Load, Load, T);
  165. remove.create(Rect_RU(rect.ru(), 0.035f, 0.035f)).func(Remove, T); remove.image="Gui/close.img";
  166. return T;
  167. }
  168. void MaterialRegion::Texture::update(C GuiPC &gpc)
  169. {
  170. if(visible() && gpc.visible)
  171. {
  172. ::EE::GuiObj::update(gpc);
  173. rect_color=((Gui.msLit()==this && Gui.skin) ? Gui.skin->keyboard_highlight_color : Gui.borderColor());
  174. REPA(MT)if(MT.bp(i) && MT.guiObj(i)==this)
  175. {
  176. UID id;
  177. if(file.is() && !DecodeFileName(file, id)) // texture path
  178. {
  179. if(Kb.ctrl()) // Ctrl+Click -> explore file path
  180. {
  181. Mems<Edit::FileParams> fps=Edit::FileParams::Decode(file); if(fps.elms()>=1)Explore(FFirstUp(fps[0].name));
  182. goto skip;
  183. }else
  184. {
  185. SetPath(win_io, file);
  186. }
  187. }else
  188. if(mr)
  189. {
  190. Mems<Edit::FileParams> fps=Edit::FileParams::Decode(mr->getEditMtrl().color_map);
  191. Str mtrl_path=Proj.elmSrcFileFirst(mr->elm); if(FileInfoSystem(mtrl_path).type==FSTD_FILE)mtrl_path=GetPath(mtrl_path);
  192. Str color_path; if(fps.elms())color_path=FFirstUp(GetPath(fps[0].name));
  193. SetPath(win_io, (mtrl_path.length()>color_path.length()) ? mtrl_path : color_path);
  194. }
  195. win_io.activate();
  196. skip:;
  197. }
  198. }
  199. remove.visible((Gui.ms()==this || Gui.ms()==&remove) && file.is());
  200. }
  201. bool MaterialRegion::Texture::draw(C Rect &rect)
  202. {
  203. bool tex=false;
  204. if(mr)
  205. {
  206. EditMaterial &em =mr->getEditMtrl ();
  207. C ImagePtr &base_0 =mr->getBase0 (),
  208. &base_1 =mr->getBase1 (),
  209. &macro =mr->getMacro (),
  210. &detail =mr->getDetail (),
  211. &reflection=mr->getReflection(),
  212. &light =mr->getLight ();
  213. ALPHA_MODE alpha=D.alpha(ALPHA_NONE);
  214. switch(type) // #MaterialTextureChannelOrder
  215. {
  216. case TEX_COLOR : if(em. color_map.is() )if(base_0 ){ base_0->drawFit(rect); tex=true;} break;
  217. case TEX_ALPHA : if(em. color_map.is() || em.alpha_map.is() )if(base_0 || base_1){VI.shader(ShaderFiles("Main")->get(base_1 ? "DrawTexW" : "DrawTexW" )); if(base_1)base_1->drawFit(rect);else base_0->drawFit(rect); tex=true;} break;
  218. case TEX_BUMP : if( em.hasBumpMap() )if(base_0 && base_1){VI.shader(ShaderFiles("Main")->get( "DrawTexW" )); base_0->drawFit(rect); tex=true;} break;
  219. case TEX_NORMAL : if(em. normal_map.is() || em.hasBumpMap() )if( base_1){VI.shader(ShaderFiles("Main")->get( "DrawTexNrm")); base_1->drawFit(rect); tex=true;} break;
  220. case TEX_SPEC : if(em. specular_map.is() )if( base_1){VI.shader(ShaderFiles("Main")->get( "DrawTexZ" )); base_1->drawFit(rect); tex=true;} break;
  221. case TEX_GLOW : if(em. glow_map.is() && em.tech==MTECH_DEFAULT)if( base_1){VI.shader(ShaderFiles("Main")->get( "DrawTexW" )); base_1->drawFit(rect); tex=true;} break;
  222. case TEX_LIGHT : if(em. light_map.is() )if( light){ light ->drawFit(rect); tex=true;} break;
  223. case TEX_MACRO : if(em. macro_map.is() )if( macro){ macro ->drawFit(rect); tex=true;} break;
  224. case TEX_DET_COL : if(em. detail_color .is() )if( detail){VI.shader(ShaderFiles("Main")->get( "DrawTexZ" )); detail->drawFit(rect); tex=true;} break;
  225. case TEX_DET_BUMP: if(em. detail_bump .is() )if( detail){ if(Image *bump=mr->getDetailBump(em.detail_bump))bump->drawFit(rect); tex=true;} break; //{VI.shader(ShaderFiles("Main")->get( "DrawTexW" )); detail->drawFit(rect); tex=true;} break; // Detail Bump may not be available due to BC1 compression or RemoveMtrlDetailBump
  226. case TEX_DET_NRM : if(em. detail_normal.is() || em.detail_bump.is() )if( detail){VI.shader(ShaderFiles("Main")->get( "DrawTexNrm")); detail->drawFit(rect); tex=true;} break;
  227. case TEX_RFL_L : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_LEFT ); tex=true;} break;
  228. case TEX_RFL_F : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_FORWARD); tex=true;} break;
  229. case TEX_RFL_R : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_RIGHT ); tex=true;} break;
  230. case TEX_RFL_B : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_BACK ); tex=true;} break;
  231. case TEX_RFL_D : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_DOWN ); tex=true;} break;
  232. case TEX_RFL_U : if(em.reflection_map.is() )if( reflection){reflection->drawCubeFace(WHITE, TRANSPARENT, rect, DIR_UP ); tex=true;} break;
  233. case TEX_RFL_ALL : if(em.reflection_map.is() )if( reflection)
  234. {
  235. Image &i=*reflection; flt x[5]={rect.min.x, rect.lerpX(1.0f/4), rect.lerpX(2.0f/4), rect.lerpX(3.0f/4), rect.max.x},
  236. y[4]={rect.min.y, rect.lerpY(1.0f/3), rect.lerpY(2.0f/3), rect.max.y};
  237. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[0], y[1], x[1], y[2]), DIR_LEFT );
  238. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[1], y[1], x[2], y[2]), DIR_FORWARD);
  239. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[2], y[1], x[3], y[2]), DIR_RIGHT );
  240. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[3], y[1], x[4], y[2]), DIR_BACK );
  241. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[1], y[0], x[2], y[1]), DIR_DOWN );
  242. i.drawCubeFace(WHITE, TRANSPARENT, Rect(x[1], y[2], x[2], y[3]), DIR_UP );
  243. tex=true;
  244. }break;
  245. }
  246. D.alpha(alpha);
  247. }
  248. return tex;
  249. }
  250. void MaterialRegion::Texture::draw(C GuiPC &gpc)
  251. {
  252. if(visible() && gpc.visible)
  253. {
  254. D.clip(gpc.clip);
  255. Rect r=rect()+gpc.offset;
  256. TextStyleParams ts; if(draw(r))ts.reset(false).size=0.040f;else ts.reset(true).size=0.036f;
  257. D.text(ts, r, text);
  258. // if mouse cursor is over reload button, and source file is not found, then draw exclamation as a warning
  259. if((Gui.ms()==&mr->reload_base_textures || Gui.ms()==&mr->texture_options)
  260. && Proj.invalidTexSrc(file))
  261. Proj.exclamation->drawFit(Rect_C(r.center(), 0.08f, 0.08f));
  262. r.draw(rect_color, false);
  263. }
  264. }
  265. void MaterialRegion::undoVis() {SetUndo(undos, undo, redo);}
  266. Vec MaterialRegion::previewLight()C {return Matrix3().setRotateXY(light_angle.y-ActiveCam.pitch, light_angle.x-ActiveCam.yaw).z;}
  267. void MaterialRegion::Render() {MtrlEdit.render();}
  268. void MaterialRegion::render()
  269. {
  270. switch(Renderer())
  271. {
  272. case RM_PREPARE:
  273. {
  274. if(InRange(preview_mode(), preview_mesh))
  275. {
  276. Matrix m; m.setScale((game && game->technique==MTECH_FUR) ? 0.75f : 1.0f);
  277. preview_mesh[preview_mode()].draw(m);
  278. }
  279. LightDir(previewLight(), 1-D.ambientColor()).add(false);
  280. }break;
  281. }
  282. }
  283. void MaterialRegion::DrawPreview(Viewport &viewport) {((MaterialRegion*)viewport.user)->drawPreview();}
  284. void MaterialRegion::drawPreview()
  285. {
  286. preview_cam.set();
  287. REPAO(preview_mesh).material(game).setShader();
  288. CurrentEnvironment().set();
  289. MOTION_MODE motion =D. motionMode(); D. motionMode( MOTION_NONE);
  290. AMBIENT_MODE ambient =D. ambientMode(); D. ambientMode(AMBIENT_FLAT);
  291. DOF_MODE dof =D. dofMode(); D. dofMode( DOF_NONE);
  292. bool eye_adapt=D.eyeAdaptation(); D.eyeAdaptation( false);
  293. bool astros =AstrosDraw ; AstrosDraw =false;
  294. bool ocean =Water.draw ; Water.draw =false;
  295. Renderer(Render);
  296. D. dofMode(dof );
  297. D. motionMode(motion );
  298. D. ambientMode(ambient );
  299. D.eyeAdaptation(eye_adapt);
  300. AstrosDraw =astros;
  301. Water.draw =ocean;
  302. }
  303. void MaterialRegion::PreChanged(C Property &prop) {cptr change_type=&prop; if(change_type==MtrlEdit.green || change_type==MtrlEdit.blue)change_type=MtrlEdit.red; MtrlEdit.undos.set(change_type);}
  304. void MaterialRegion::Changed(C Property &prop) {MtrlEdit.setChanged();}
  305. Str MaterialRegion::Tech(C MaterialRegion &mr ) {return mr.edit.tech;}
  306. void MaterialRegion::Tech( MaterialRegion &mr, C Str &t) {mr.edit.tech=MATERIAL_TECHNIQUE(TextInt(t)); mr.edit.tech_time.now(); mr.setChanged(); D.setShader(mr.game());}
  307. Str MaterialRegion::DownsizeTexMobile(C MaterialRegion &mr ) {return mr.edit.downsize_tex_mobile;}
  308. void MaterialRegion::DownsizeTexMobile( MaterialRegion &mr, C Str &t) {mr.edit.downsize_tex_mobile=TextInt(t); mr.edit.downsize_tex_mobile_time.getUTC();}
  309. Str MaterialRegion::TexQualityiOS(C MaterialRegion &mr ) {return mr.edit.high_quality_ios;}
  310. void MaterialRegion::TexQualityiOS( MaterialRegion &mr, C Str &t) {mr.edit.high_quality_ios=TextBool(t); mr.edit.high_quality_ios_time.getUTC();}
  311. void MaterialRegion::RGB(MaterialRegion &mr)
  312. {
  313. mr.undos.set("brightness");
  314. Vec2 d=0; int on=0, pd=0; REPA(MT)if(MT.b(i) && MT.guiObj(i)==&mr.brightness){d+=MT.ad(i); if(!MT.touch(i))Ms.freeze(); if(MT.bp(i))pd++;else on++;}
  315. Vec &rgb=mr.edit.color.xyz; if(pd && !on){mr.mouse_edit_value=rgb; mr.mouse_edit_delta=0;} mr.mouse_edit_delta+=d.sum()*0.75f;
  316. flt max=mr.mouse_edit_value.max(), lum=max+mr.mouse_edit_delta; if(lum<0){mr.mouse_edit_delta-=lum; lum=0;}
  317. Vec v =mr.mouse_edit_value; if(max)v/=max;else v=1; v*=lum;
  318. if(mr.red ){mr.red ->set(v.x, QUIET); rgb.x=mr.red ->asFlt();}
  319. if(mr.green){mr.green->set(v.y, QUIET); rgb.y=mr.green->asFlt();}
  320. if(mr.blue ){mr.blue ->set(v.z, QUIET); rgb.z=mr.blue ->asFlt();}
  321. mr.edit.color_time.getUTC(); mr.setChanged();
  322. }
  323. Str MaterialRegion::Red(C MaterialRegion &mr ) {return mr.edit.color.x;}
  324. void MaterialRegion::Red( MaterialRegion &mr, C Str &t) {mr.edit.color.x=TextFlt(t); mr.edit.color_time.getUTC();}
  325. Str MaterialRegion::Green(C MaterialRegion &mr ) {return mr.edit.color.y;}
  326. void MaterialRegion::Green( MaterialRegion &mr, C Str &t) {mr.edit.color.y=TextFlt(t); mr.edit.color_time.getUTC();}
  327. Str MaterialRegion::Blue(C MaterialRegion &mr ) {return mr.edit.color.z;}
  328. void MaterialRegion::Blue( MaterialRegion &mr, C Str &t) {mr.edit.color.z=TextFlt(t); mr.edit.color_time.getUTC();}
  329. Str MaterialRegion::Alpha(C MaterialRegion &mr ) {return mr.edit.color.w;}
  330. void MaterialRegion::Alpha( MaterialRegion &mr, C Str &t) {mr.edit.color.w=TextFlt(t); mr.edit.color_time.getUTC();}
  331. Str MaterialRegion::Bump(C MaterialRegion &mr ) {return mr.edit.bump/BumpScale;}
  332. void MaterialRegion::Bump( MaterialRegion &mr, C Str &t) {mr.edit.bump=TextFlt(t)*BumpScale; mr.edit.rough_bump_time.getUTC(); mr.setChanged(); D.setShader(mr.game());}
  333. Str MaterialRegion::NrmScale(C MaterialRegion &mr ) {return mr.edit.rough;}
  334. void MaterialRegion::NrmScale( MaterialRegion &mr, C Str &t) {mr.edit.rough=TextFlt(t); mr.edit.rough_bump_time.getUTC();}
  335. Str MaterialRegion::FNY(C MaterialRegion &mr ) {return mr.edit.flip_normal_y;}
  336. void MaterialRegion::FNY( MaterialRegion &mr, C Str &t) {uint base_tex=mr.edit.baseTex(); mr.edit.flip_normal_y=TextBool(t); mr.edit.flip_normal_y_time.getUTC(); mr.rebuildBase(base_tex, true, false);}
  337. Str MaterialRegion::Spec(C MaterialRegion &mr ) {return mr.edit.specular;}
  338. void MaterialRegion::Spec( MaterialRegion &mr, C Str &t) {mr.edit.specular=TextFlt(t); mr.edit.spec_time.getUTC();}
  339. Str MaterialRegion::Glow(C MaterialRegion &mr ) {return mr.edit.glow;}
  340. void MaterialRegion::Glow( MaterialRegion &mr, C Str &t) {mr.edit.glow=TextFlt(t); mr.edit.glow_time.getUTC();}
  341. Str MaterialRegion::DetScale(C MaterialRegion &mr ) {return mr.edit.det_scale;}
  342. void MaterialRegion::DetScale( MaterialRegion &mr, C Str &t) {mr.edit.det_scale=TextFlt(t); mr.edit.detail_time.getUTC();}
  343. Str MaterialRegion::DetPower(C MaterialRegion &mr ) {return mr.edit.det_power;}
  344. void MaterialRegion::DetPower( MaterialRegion &mr, C Str &t) {mr.edit.det_power=TextFlt(t); mr.edit.detail_time.getUTC();}
  345. Str MaterialRegion::Reflect(C MaterialRegion &mr ) {return mr.edit.reflection;}
  346. void MaterialRegion::Reflect( MaterialRegion &mr, C Str &t) {mr.edit.reflection=TextFlt(t); mr.edit.reflection_time.getUTC();}
  347. Str MaterialRegion::Cull(C MaterialRegion &mr ) {return mr.edit.cull;}
  348. void MaterialRegion::Cull( MaterialRegion &mr, C Str &t) {mr.edit.cull=TextBool(t); mr.edit.cull_time.now();}
  349. Str MaterialRegion::SSS(C MaterialRegion &mr ) {return mr.edit.sss;}
  350. void MaterialRegion::SSS( MaterialRegion &mr, C Str &t) {mr.edit.sss=TextFlt(t); mr.edit.sss_time.getUTC();}
  351. Str MaterialRegion::AmbR(C MaterialRegion &mr ) {return mr.edit.ambient.x;}
  352. void MaterialRegion::AmbR( MaterialRegion &mr, C Str &t) {mr.edit.ambient.x=TextFlt(t); mr.edit.ambient_time.getUTC(); mr.setChanged(); D.setShader(mr.game());}
  353. Str MaterialRegion::AmbG(C MaterialRegion &mr ) {return mr.edit.ambient.y;}
  354. void MaterialRegion::AmbG( MaterialRegion &mr, C Str &t) {mr.edit.ambient.y=TextFlt(t); mr.edit.ambient_time.getUTC(); mr.setChanged(); D.setShader(mr.game());}
  355. Str MaterialRegion::AmbB(C MaterialRegion &mr ) {return mr.edit.ambient.z;}
  356. void MaterialRegion::AmbB( MaterialRegion &mr, C Str &t) {mr.edit.ambient.z=TextFlt(t); mr.edit.ambient_time.getUTC(); mr.setChanged(); D.setShader(mr.game());}
  357. Str MaterialRegion::TexScale(C MaterialRegion &mr ) {return mr.edit.tex_scale;}
  358. void MaterialRegion::TexScale( MaterialRegion &mr, C Str &t) {mr.edit.tex_scale=TextFlt(t); mr.edit.tex_scale_time.getUTC();}
  359. void MaterialRegion::Undo(MaterialRegion &editor) {editor.undos.undo();}
  360. void MaterialRegion::Redo(MaterialRegion &editor) {editor.undos.redo();}
  361. void MaterialRegion::Locate(MaterialRegion &editor) {Proj.elmLocate(editor.elm_id);}
  362. void MaterialRegion::Hide(MaterialRegion &editor) {editor.set(null);}
  363. void MaterialRegion::SetMtrl(MaterialRegion &editor) {SetObjOp(editor.set_mtrl() ? OP_OBJ_SET_MTRL : OP_OBJ_NONE);}
  364. void MaterialRegion::AutoReload(MaterialRegion &editor) {editor.auto_reload=editor.texture_options.menu(auto_reload_name);}
  365. void MaterialRegion::ReloadBaseTextures(MaterialRegion &editor) {editor.undos.set("rebuildBase"); editor.rebuildBase(editor.getEditMtrl().baseTex(), false, false, true);}
  366. void MaterialRegion::ResizeBase128(MaterialRegion &editor) {editor.resizeBase(128);}
  367. void MaterialRegion::ResizeBase256(MaterialRegion &editor) {editor.resizeBase(256);}
  368. void MaterialRegion::ResizeBase512(MaterialRegion &editor) {editor.resizeBase(512);}
  369. void MaterialRegion::ResizeBase1024(MaterialRegion &editor) {editor.resizeBase(1024);}
  370. void MaterialRegion::ResizeBase2048(MaterialRegion &editor) {editor.resizeBase(2048);}
  371. void MaterialRegion::ResizeBase4096(MaterialRegion &editor) {editor.resizeBase(4096);}
  372. void MaterialRegion::ResizeBase128x64(MaterialRegion &editor) {editor.resizeBase(VecI2(128, 64));}
  373. void MaterialRegion::ResizeBase256x128(MaterialRegion &editor) {editor.resizeBase(VecI2(256, 128));}
  374. void MaterialRegion::ResizeBase512x256(MaterialRegion &editor) {editor.resizeBase(VecI2(512, 256));}
  375. void MaterialRegion::ResizeBase1024x512(MaterialRegion &editor) {editor.resizeBase(VecI2(1024, 512));}
  376. void MaterialRegion::ResizeBase2048x1024(MaterialRegion &editor) {editor.resizeBase(VecI2(2048, 1024));}
  377. void MaterialRegion::ResizeBase64x128(MaterialRegion &editor) {editor.resizeBase(VecI2(64, 128));}
  378. void MaterialRegion::ResizeBase128x256(MaterialRegion &editor) {editor.resizeBase(VecI2(128, 256));}
  379. void MaterialRegion::ResizeBase256x512(MaterialRegion &editor) {editor.resizeBase(VecI2(256, 512));}
  380. void MaterialRegion::ResizeBase512x1024(MaterialRegion &editor) {editor.resizeBase(VecI2(512, 1024));}
  381. void MaterialRegion::ResizeBase1024x2048(MaterialRegion &editor) {editor.resizeBase(VecI2(1024, 2048));}
  382. void MaterialRegion::ResizeBaseQuarter(MaterialRegion &editor) {editor.resizeBase(-2, true);}
  383. void MaterialRegion::ResizeBaseHalf(MaterialRegion &editor) {editor.resizeBase(-1, true);}
  384. void MaterialRegion::ResizeBaseOriginal(MaterialRegion &editor) {editor.resizeBase( 0, true);}
  385. void MaterialRegion::ResizeBaseDouble(MaterialRegion &editor) {editor.resizeBase( 1, true);}
  386. void MaterialRegion::ResizeBase0_128(MaterialRegion &editor) {editor.resizeBase0(128);}
  387. void MaterialRegion::ResizeBase0_256(MaterialRegion &editor) {editor.resizeBase0(256);}
  388. void MaterialRegion::ResizeBase0_512(MaterialRegion &editor) {editor.resizeBase0(512);}
  389. void MaterialRegion::ResizeBase0_1024(MaterialRegion &editor) {editor.resizeBase0(1024);}
  390. void MaterialRegion::ResizeBase0_2048(MaterialRegion &editor) {editor.resizeBase0(2048);}
  391. void MaterialRegion::ResizeBase0_4096(MaterialRegion &editor) {editor.resizeBase0(4096);}
  392. void MaterialRegion::ResizeBase0_128x64(MaterialRegion &editor) {editor.resizeBase0(VecI2(128, 64));}
  393. void MaterialRegion::ResizeBase0_256x128(MaterialRegion &editor) {editor.resizeBase0(VecI2(256, 128));}
  394. void MaterialRegion::ResizeBase0_512x256(MaterialRegion &editor) {editor.resizeBase0(VecI2(512, 256));}
  395. void MaterialRegion::ResizeBase0_1024x512(MaterialRegion &editor) {editor.resizeBase0(VecI2(1024, 512));}
  396. void MaterialRegion::ResizeBase0_2048x1024(MaterialRegion &editor) {editor.resizeBase0(VecI2(2048, 1024));}
  397. void MaterialRegion::ResizeBase0_64x128(MaterialRegion &editor) {editor.resizeBase0(VecI2(64, 128));}
  398. void MaterialRegion::ResizeBase0_128x256(MaterialRegion &editor) {editor.resizeBase0(VecI2(128, 256));}
  399. void MaterialRegion::ResizeBase0_256x512(MaterialRegion &editor) {editor.resizeBase0(VecI2(256, 512));}
  400. void MaterialRegion::ResizeBase0_512x1024(MaterialRegion &editor) {editor.resizeBase0(VecI2(512, 1024));}
  401. void MaterialRegion::ResizeBase0_1024x2048(MaterialRegion &editor) {editor.resizeBase0(VecI2(1024, 2048));}
  402. void MaterialRegion::ResizeBase0_Quarter(MaterialRegion &editor) {editor.resizeBase0(-2, true);}
  403. void MaterialRegion::ResizeBase0_Half(MaterialRegion &editor) {editor.resizeBase0(-1, true);}
  404. void MaterialRegion::ResizeBase0_Original(MaterialRegion &editor) {editor.resizeBase0( 0, true);}
  405. void MaterialRegion::ResizeBase0_Double(MaterialRegion &editor) {editor.resizeBase0( 1, true);}
  406. void MaterialRegion::ResizeBase1_128(MaterialRegion &editor) {editor.resizeBase1(128);}
  407. void MaterialRegion::ResizeBase1_256(MaterialRegion &editor) {editor.resizeBase1(256);}
  408. void MaterialRegion::ResizeBase1_512(MaterialRegion &editor) {editor.resizeBase1(512);}
  409. void MaterialRegion::ResizeBase1_1024(MaterialRegion &editor) {editor.resizeBase1(1024);}
  410. void MaterialRegion::ResizeBase1_2048(MaterialRegion &editor) {editor.resizeBase1(2048);}
  411. void MaterialRegion::ResizeBase1_4096(MaterialRegion &editor) {editor.resizeBase1(4096);}
  412. void MaterialRegion::ResizeBase1_128x64(MaterialRegion &editor) {editor.resizeBase1(VecI2(128, 64));}
  413. void MaterialRegion::ResizeBase1_256x128(MaterialRegion &editor) {editor.resizeBase1(VecI2(256, 128));}
  414. void MaterialRegion::ResizeBase1_512x256(MaterialRegion &editor) {editor.resizeBase1(VecI2(512, 256));}
  415. void MaterialRegion::ResizeBase1_1024x512(MaterialRegion &editor) {editor.resizeBase1(VecI2(1024, 512));}
  416. void MaterialRegion::ResizeBase1_2048x1024(MaterialRegion &editor) {editor.resizeBase1(VecI2(2048, 1024));}
  417. void MaterialRegion::ResizeBase1_64x128(MaterialRegion &editor) {editor.resizeBase1(VecI2(64, 128));}
  418. void MaterialRegion::ResizeBase1_128x256(MaterialRegion &editor) {editor.resizeBase1(VecI2(128, 256));}
  419. void MaterialRegion::ResizeBase1_256x512(MaterialRegion &editor) {editor.resizeBase1(VecI2(256, 512));}
  420. void MaterialRegion::ResizeBase1_512x1024(MaterialRegion &editor) {editor.resizeBase1(VecI2(512, 1024));}
  421. void MaterialRegion::ResizeBase1_1024x2048(MaterialRegion &editor) {editor.resizeBase1(VecI2(1024, 2048));}
  422. void MaterialRegion::ResizeBase1_Quarter(MaterialRegion &editor) {editor.resizeBase1(-2, true);}
  423. void MaterialRegion::ResizeBase1_Half(MaterialRegion &editor) {editor.resizeBase1(-1, true);}
  424. void MaterialRegion::ResizeBase1_Original(MaterialRegion &editor) {editor.resizeBase1( 0, true);}
  425. void MaterialRegion::ResizeBase1_Double(MaterialRegion &editor) {editor.resizeBase1( 1, true);}
  426. void MaterialRegion::BumpFromCol(MaterialRegion &editor) {editor.bumpFromCol(-1);}
  427. void MaterialRegion::BumpFromCol2(MaterialRegion &editor) {editor.bumpFromCol( 2);}
  428. void MaterialRegion::BumpFromCol3(MaterialRegion &editor) {editor.bumpFromCol( 3);}
  429. void MaterialRegion::BumpFromCol4(MaterialRegion &editor) {editor.bumpFromCol( 4);}
  430. void MaterialRegion::BumpFromCol5(MaterialRegion &editor) {editor.bumpFromCol( 5);}
  431. void MaterialRegion::BumpFromCol6(MaterialRegion &editor) {editor.bumpFromCol( 6);}
  432. void MaterialRegion::BumpFromCol8(MaterialRegion &editor) {editor.bumpFromCol( 8);}
  433. void MaterialRegion::BumpFromCol12(MaterialRegion &editor) {editor.bumpFromCol(12);}
  434. void MaterialRegion::BumpFromCol16(MaterialRegion &editor) {editor.bumpFromCol(16);}
  435. void MaterialRegion::BumpFromCol24(MaterialRegion &editor) {editor.bumpFromCol(24);}
  436. void MaterialRegion::BumpFromCol32(MaterialRegion &editor) {editor.bumpFromCol(32);}
  437. void MaterialRegion::MulTexCol(MaterialRegion &editor) {Proj.mtrlMulTexCol (editor.elm_id);}
  438. void MaterialRegion::MulTexRough(MaterialRegion &editor) {Proj.mtrlMulTexRough(editor.elm_id);}
  439. bool MaterialRegion::bigVisible()C {return visible() && big();}
  440. void MaterialRegion::setRGB(C Vec &rgb) {if(edit.color.xyz !=rgb){undos.set("rgb1" ); edit.color.xyz =rgb; edit. color_time.getUTC(); setChanged(); toGui();}}
  441. void MaterialRegion::resetAlpha( ) { undos.set("alpha"); edit.resetAlpha() ; setChanged(); toGui(); }
  442. void MaterialRegion::cull(bool on ) {if(edit.cull !=on ){undos.set("cull" ); edit.cull =on ; edit. cull_time.getUTC(); setChanged(); toGui();}}
  443. void MaterialRegion::flipNrmY(bool on ) {if(edit.flip_normal_y !=on ){undos.set("fny" ); edit.flip_normal_y =on ; edit. flip_normal_y_time.getUTC(); rebuildBase(edit.baseTex(), true, false);}}
  444. void MaterialRegion::downsizeTexMobile(byte ds ) {if(edit.downsize_tex_mobile!=ds ){undos.set("dtm" ); edit.downsize_tex_mobile=ds ; edit.downsize_tex_mobile_time.getUTC(); setChanged(); toGui();}}
  445. void MaterialRegion::texQualityiOS(bool q ) {if(edit.high_quality_ios !=q ){undos.set("tq" ); edit.high_quality_ios =q ; edit. high_quality_ios_time.getUTC(); setChanged(); toGui();}}
  446. void MaterialRegion::resizeBase(C VecI2 &size, bool relative)
  447. {
  448. undos.set("resizeBase");
  449. TimeStamp time; time.getUTC();
  450. VecI2 sizes[2]={size, size};
  451. if(relative && size.any()) // if we want to have relative size and not original, then first revert to original size
  452. if(Proj.forceImageSize(edit. color_map, 0, relative, edit. color_map_time, time) // !! use '|' because all need to be processed !!
  453. | Proj.forceImageSize(edit. alpha_map, 0, relative, edit. alpha_map_time, time)
  454. | Proj.forceImageSize(edit. bump_map, 0, relative, edit. bump_map_time, time)
  455. | Proj.forceImageSize(edit. normal_map, 0, relative, edit. normal_map_time, time)
  456. | Proj.forceImageSize(edit.specular_map, 0, relative, edit.specular_map_time, time)
  457. | Proj.forceImageSize(edit. glow_map, 0, relative, edit. glow_map_time, time))
  458. {
  459. MtrlImages mi; mi.fromMaterial(edit, Proj, false); mi.baseTextureSizes(&sizes[0], &sizes[1]); // calculate actual sizes
  460. REP(2)
  461. {
  462. sizes[i].set(Max(1, Shl(sizes[i].x, size.x)), Max(1, Shl(sizes[i].y, size.y)));
  463. sizes[i].set(NearestPow2(sizes[i].x), NearestPow2(sizes[i].y)); // textures are gonna be resized to pow2 anyway, so force pow2 size, to avoid double resize
  464. }
  465. if(sizes[0]!=sizes[1])edit.separateBaseTexs(Proj, time);
  466. relative=false; // we now have the sizes known, so disable relative mode
  467. }
  468. if(Proj.forceImageSize(edit. color_map, sizes[0], relative, edit. color_map_time, time) // !! use '|' because all need to be processed !!
  469. | Proj.forceImageSize(edit. alpha_map, edit.hasBase1Tex() ? sizes[1] : sizes[0], relative, edit. alpha_map_time, time) // #MaterialTextureChannelOrder
  470. | Proj.forceImageSize(edit. bump_map, sizes[0], relative, edit. bump_map_time, time)
  471. | Proj.forceImageSize(edit. normal_map, sizes[1] , relative, edit. normal_map_time, time)
  472. | Proj.forceImageSize(edit.specular_map, sizes[1] , relative, edit.specular_map_time, time)
  473. | Proj.forceImageSize(edit. glow_map, sizes[1] , relative, edit. glow_map_time, time))
  474. {
  475. edit.cleanupMaps();
  476. rebuildBase(edit.baseTex());
  477. }
  478. }
  479. void MaterialRegion::resizeBase0(C VecI2 &size, bool relative)
  480. {
  481. undos.set("resizeBase");
  482. TimeStamp time; time.getUTC();
  483. VecI2 size0=size;
  484. if(relative ? true : (game && game->base_1 && game->base_1->size()!=size))edit.separateBaseTexs(Proj, time); // separate before reverting
  485. if(relative && size.any()) // if we want to have relative size and not original, then first revert to original size
  486. if( Proj.forceImageSize(edit.color_map, 0, relative, edit.color_map_time, time) // !! use '|' because all need to be processed !!
  487. | Proj.forceImageSize(edit. bump_map, 0, relative, edit. bump_map_time, time)
  488. | (!edit.hasBase1Tex() && Proj.forceImageSize(edit.alpha_map, 0, relative, edit.alpha_map_time, time))) // resize alpha only if it's going to be placed in Base0 tex, #MaterialTextureChannelOrder
  489. {
  490. MtrlImages mi; mi.fromMaterial(edit, Proj, false); mi.baseTextureSizes(&size0, null); // calculate actual sizes
  491. size0.set(Max(1, Shl(size0.x, size.x)), Max(1, Shl(size0.y, size.y)));
  492. size0.set(NearestPow2(size0.x), NearestPow2(size0.y)); // textures are gonna be resized to pow2 anyway, so force pow2 size, to avoid double resize
  493. relative=false; // we now have the sizes known, so disable relative mode
  494. }
  495. if( Proj.forceImageSize(edit.color_map, size0, relative, edit.color_map_time, time) // !! use '|' because all need to be processed !!
  496. | Proj.forceImageSize(edit. bump_map, size0, relative, edit. bump_map_time, time)
  497. | (!edit.hasBase1Tex() && Proj.forceImageSize(edit.alpha_map, size0, relative, edit.alpha_map_time, time)) // resize alpha only if it's going to be placed in Base0 tex, #MaterialTextureChannelOrder
  498. )
  499. {
  500. edit.cleanupMaps();
  501. rebuildBase(edit.baseTex());
  502. }
  503. }
  504. void MaterialRegion::resizeBase1(C VecI2 &size, bool relative)
  505. {
  506. undos.set("resizeBase");
  507. TimeStamp time; time.getUTC();
  508. VecI2 size1=size;
  509. if(relative ? true : (game && game->base_0 && game->base_0->size()!=size))edit.separateBaseTexs(Proj, time); // separate before reverting
  510. if(relative && size.any()) // if we want to have relative size and not original, then first revert to original size
  511. if( Proj.forceImageSize(edit. normal_map, 0, relative, edit. normal_map_time, time) // !! use '|' because all need to be processed !!
  512. | Proj.forceImageSize(edit.specular_map, 0, relative, edit.specular_map_time, time)
  513. | Proj.forceImageSize(edit. glow_map, 0, relative, edit. glow_map_time, time)
  514. | (edit.hasBase1Tex() && Proj.forceImageSize(edit. alpha_map, 0, relative, edit. alpha_map_time, time))) // resize alpha only if it's going to be placed in Base1 tex, #MaterialTextureChannelOrder
  515. {
  516. MtrlImages mi; mi.fromMaterial(edit, Proj, false); mi.baseTextureSizes(null, &size1); // calculate actual sizes
  517. size1.set(Max(1, Shl(size1.x, size.x)), Max(1, Shl(size1.y, size.y)));
  518. size1.set(NearestPow2(size1.x), NearestPow2(size1.y)); // textures are gonna be resized to pow2 anyway, so force pow2 size, to avoid double resize
  519. relative=false; // we now have the sizes known, so disable relative mode
  520. }
  521. if( Proj.forceImageSize(edit. normal_map, size1, relative, edit. normal_map_time, time) // !! use '|' because all need to be processed !!
  522. | Proj.forceImageSize(edit.specular_map, size1, relative, edit.specular_map_time, time)
  523. | Proj.forceImageSize(edit. glow_map, size1, relative, edit. glow_map_time, time)
  524. | (edit.hasBase1Tex() && Proj.forceImageSize(edit. alpha_map, size1, relative, edit. alpha_map_time, time)) // resize alpha only if it's going to be placed in Base1 tex, #MaterialTextureChannelOrder
  525. )
  526. {
  527. edit.cleanupMaps();
  528. rebuildBase(edit.baseTex());
  529. }
  530. }
  531. void MaterialRegion::bumpFromCol(int blur)
  532. {
  533. undos.set("bumpFromCol");
  534. uint base_tex=edit.baseTex(); // get current state of textures before making any change
  535. edit.bump_map=BumpFromColTransform(edit.color_map, blur); edit.bump_map_time.now();
  536. rebuildBase(base_tex);
  537. }
  538. EditMaterial& MaterialRegion::getEditMtrl() {return edit;}
  539. C ImagePtr & MaterialRegion::getBase0() {return game->base_0;}
  540. C ImagePtr & MaterialRegion::getBase1() {return game->base_1;}
  541. C ImagePtr & MaterialRegion::getDetail() {return game->detail_map;}
  542. C ImagePtr & MaterialRegion::getReflection() {return game->reflection_map;}
  543. C ImagePtr & MaterialRegion::getMacro() {return game->macro_map;}
  544. C ImagePtr & MaterialRegion::getLight() {return game->light_map;}
  545. void MaterialRegion::setBottom(C Rect &prop_rect)
  546. {
  547. reload_base_textures.rect(Rect_LU(0.10f, prop_rect.min.y-0.02f, 0.42f, 0.053f));
  548. texture_options.rect(Rect_LU(reload_base_textures.rect().ru(), reload_base_textures.rect().h()));
  549. }
  550. void MaterialRegion::create()
  551. {
  552. Gui+=::EE::Region::create(Rect_LU(0, 0, 0.73f, 1)).skin(&LightSkin, false).hide();
  553. flt w=rect().w()-slidebarSize(), e=0.01f, we=w-e*2, p=0.007f, h=0.05f, prop_height=0.044f;
  554. T+=big .create(Rect_LU(e, 0, h*1.6f, h), "<<").focusable(false); big.mode=BUTTON_TOGGLE;
  555. T+=set_mtrl .create(Rect_LU(big.rect().max.x+p, big.rect().max.y, h, h)).func(SetMtrl, T).focusable(false).desc("Enable this and click on the screen to set material at that location"); set_mtrl.mode=BUTTON_TOGGLE; set_mtrl.image="Gui/Misc/set.img";
  556. T+=undo .create(Rect_LU(set_mtrl.rect().ru()+Vec2(p, 0), 0.05f, 0.05f )).func(Undo, T).focusable(false).desc("Undo"); undo.image="Gui/Misc/undo.img";
  557. T+=redo .create(Rect_LU(undo.rect().ru() , 0.05f, 0.05f )).func(Redo, T).focusable(false).desc("Redo"); redo.image="Gui/Misc/redo.img";
  558. T+=locate .create(Rect_L (redo.rect().right() +Vec2(p, 0), 0.11f, 0.043f), "Locate").func(Locate, T).focusable(false).desc("Locate this element in the Project");
  559. T+=close .create(Rect_RU(w-e, 0, h, h)).func(Hide, T); close.image="Gui/close.img"; close.skin=&EmptyGuiSkin;
  560. T+=preview_mode.create(Rect (locate.rect().max.x+p, redo.rect().min.y, close.rect().min.x-p, close.rect().max.y), 0, (cchar**)null, Elms(preview_mesh)).valid(true).set(0);
  561. T+=preview .create(Rect_LU(big.rect().ld()-Vec2(0, 0.007f), we, we), DrawPreview); preview.fov=PreviewFOV; preview.user=this;
  562. Gui+=preview_big .create(DrawPreview).hide(); preview_big.fov=preview.fov; preview_big.user=preview.user;
  563. T+=sub .create(Rect_LU(0, 0, rect().w(), 1)).skin(&EmptyGuiSkin, false); sub.kb_lit=false;
  564. preview_mode.tab(0).setImage("Gui/Misc/circle.img");
  565. preview_mode.tab(1).setImage("Gui/Misc/box.img");
  566. preview_mode.tab(2).setImage("Gui/Misc/tube.img");
  567. preview_mode.tab(3).setImage("Gui/Misc/grid_small.img");
  568. Property &tech=props.New().create("Technique", MemberDesc(DATA_INT).setFunc(Tech, Tech)).setEnum();
  569. ListColumn tech_lc[]=
  570. {
  571. ListColumn(MEMBER(MaterialTech, name), LCW_DATA, "name"),
  572. };
  573. tech.combobox.setColumns(tech_lc, Elms(tech_lc)).setData(mtrl_techs, Elms(mtrl_techs)); tech.combobox.menu.list.setElmDesc(MEMBER(MaterialTech, desc));
  574. /*Property &max_tex_size=props.New().create("Max Image Size", MemberDesc(DATA_INT).setFunc(MaxTexSize, MaxTexSize)).setEnum();
  575. ListColumn mts_lc[]=
  576. {
  577. ListColumn(MEMBER(.MaxTexSize, name), LCW_DATA, "name"),
  578. };
  579. max_tex_size.combobox.setColumns(mts_lc, Elms(mts_lc)).setData(max_tex_sizes, Elms(max_tex_sizes)); max_tex_size.combobox.menu.list.setElmDesc(MEMBER(.MaxTexSize, desc)); */
  580. red=&props.New().create("Red" , MemberDesc(DATA_REAL).setFunc(Red , Red )).range(0, 4).mouseEditSpeed(0.4f);
  581. green=&props.New().create("Green", MemberDesc(DATA_REAL).setFunc(Green, Green)).range(0, 4).mouseEditSpeed(0.4f);
  582. blue=&props.New().create("Blue" , MemberDesc(DATA_REAL).setFunc(Blue , Blue )).range(0, 4).mouseEditSpeed(0.4f);
  583. alpha=&props.New().create("Alpha", MemberDesc(DATA_REAL).setFunc(Alpha, Alpha)).range(0, 1);
  584. //props.New();
  585. props.New().create("Bump" , MemberDesc(DATA_REAL).setFunc(Bump , Bump )).range(0, 1);
  586. props.New().create("Normal" , MemberDesc(DATA_REAL).setFunc(NrmScale, NrmScale)).range(0, 2);
  587. props.New().create("Flip Normal Y" , MemberDesc(DATA_BOOL).setFunc(FNY , FNY ));
  588. //props.New();
  589. props.New().create("Specular" , MemberDesc(DATA_REAL).setFunc(Spec, Spec)).range(0, 3);
  590. props.New().create("Glow" , MemberDesc(DATA_REAL).setFunc(Glow, Glow)).range(0, 1);
  591. props.New().create("Subsurf Scatter", MemberDesc(DATA_REAL).setFunc(SSS , SSS )).range(0, 1);
  592. props.New().create("Detail Scale" , MemberDesc(DATA_REAL).setFunc(DetScale, DetScale)).range(0.01f, 1024).mouseEditMode(PROP_MOUSE_EDIT_SCALAR);
  593. props.New().create("Detail Power" , MemberDesc(DATA_REAL).setFunc(DetPower, DetPower)).range(0, 1);
  594. props.New();
  595. props.New();
  596. props.New().create("Reflection", MemberDesc(DATA_REAL).setFunc(Reflect, Reflect)).range(0, 2);
  597. props.New();
  598. props.New();
  599. props.New();
  600. props.New();
  601. props.New().create("Cull" , MemberDesc(DATA_BOOL).setFunc(Cull , Cull ));
  602. props.New().create("Ambient Red" , MemberDesc(DATA_REAL).setFunc(AmbR , AmbR )).range(0, 1);
  603. props.New().create("Ambient Green" , MemberDesc(DATA_REAL).setFunc(AmbG , AmbG )).range(0, 1);
  604. props.New().create("Ambient Blue" , MemberDesc(DATA_REAL).setFunc(AmbB , AmbB )).range(0, 1);
  605. props.New().create("UV Scale" , MemberDesc(DATA_REAL).setFunc(TexScale, TexScale)).range(0.01f, 1024).mouseEditMode(PROP_MOUSE_EDIT_SCALAR);
  606. Property &mts=props.New().create("Mobile Tex Size", MemberDesc(DATA_INT ).setFunc(DownsizeTexMobile, DownsizeTexMobile)).setEnum(DownsizeTexMobileText, Elms(DownsizeTexMobileText)).desc("If Downsize Textures when making Applications for Mobile platforms");
  607. Property &tqi=props.New().create("iOS Tex Quality", MemberDesc(DATA_BOOL).setFunc(TexQualityiOS , TexQualityiOS )).setEnum( TexQualityiOSText, Elms( TexQualityiOSText)).desc("Select Texture Quality for iOS platform.\n4-bit per pixel PVRTC format offers higher quality, however it makes the texture use 2x more memory than 2-bit PVRTC.");
  608. ts.reset().size=0.038f; ts.align.set(1, 0);
  609. Rect prop_rect=AddProperties(props, sub, 0, prop_height, 0.145f, &ts); REPAO(props).autoData(this).changed(Changed, PreChanged);
  610. sub+=brightness.create(Rect_RU(red->textline.rect().left(), red->button.rect().w(), prop_height*2)).func(RGB, T).focusable(false).subType(BUTTON_TYPE_PROPERTY_VALUE); brightness.mode=BUTTON_CONTINUOUS;
  611. tech.combobox.resize(Vec2(0.27f, 0)); // increase size
  612. mts .combobox.resize(Vec2(0.15f, 0)); // increase size
  613. tqi .combobox.resize(Vec2(0.15f, 0)); // increase size
  614. flt tex_size=prop_height*3; int i=-1;
  615. sub+=texs.New().create(TEX_COLOR , MEMBER(EditMaterial, color_map), MEMBER(EditMaterial, color_map_time), Rect_LU(prop_rect.ru()+Vec2(e , i*prop_height), tex_size, tex_size), "Color" , T);
  616. sub+=texs.New().create(TEX_ALPHA , MEMBER(EditMaterial, alpha_map), MEMBER(EditMaterial, alpha_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Alpha" , T); i-=3;
  617. sub+=texs.New().create(TEX_BUMP , MEMBER(EditMaterial, bump_map), MEMBER(EditMaterial, bump_map_time), Rect_LU(prop_rect.ru()+Vec2(e , i*prop_height), tex_size, tex_size), "Bump" , T);
  618. sub+=texs.New().create(TEX_NORMAL , MEMBER(EditMaterial, normal_map), MEMBER(EditMaterial, normal_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Normal" , T); i-=3;
  619. sub+=texs.New().create(TEX_SPEC , MEMBER(EditMaterial, specular_map), MEMBER(EditMaterial, specular_map_time), Rect_LU(prop_rect.ru()+Vec2(e , i*prop_height), tex_size, tex_size), "Spec" , T);
  620. sub+=texs.New().create(TEX_GLOW , MEMBER(EditMaterial, glow_map), MEMBER(EditMaterial, glow_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Glow" , T); i-=3;
  621. sub+=texs.New().create(TEX_MACRO , MEMBER(EditMaterial, macro_map), MEMBER(EditMaterial, macro_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Macro" , T);
  622. sub+=texs.New().create(TEX_DET_COL , MEMBER(EditMaterial, detail_color), MEMBER(EditMaterial, detail_map_time), Rect_LU(prop_rect.ru()+Vec2(e , i*prop_height), tex_size, tex_size), "Detail\nColor" , T); i-=3;
  623. sub+=texs.New().create(TEX_DET_BUMP, MEMBER(EditMaterial, detail_bump), MEMBER(EditMaterial, detail_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*0, i*prop_height), tex_size, tex_size), "Detail\nBump" , T);
  624. sub+=texs.New().create(TEX_DET_NRM , MEMBER(EditMaterial, detail_normal), MEMBER(EditMaterial, detail_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Detail\nNormal", T); i-=3;
  625. sub+=texs.New().create(TEX_RFL_ALL , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e-tex_size*3, i*prop_height), tex_size, tex_size), "Reflect\nAll" , T);
  626. sub+=texs.New().create(TEX_RFL_L , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e-tex_size*2, i*prop_height), tex_size, tex_size), "Reflect\nLeft" , T);
  627. sub+=texs.New().create(TEX_RFL_F , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e-tex_size*1, i*prop_height), tex_size, tex_size), "Reflect\nFront", T);
  628. sub+=texs.New().create(TEX_RFL_R , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*0, i*prop_height), tex_size, tex_size), "Reflect\nRight", T);
  629. sub+=texs.New().create(TEX_RFL_B , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Reflect\nBack" , T); i-=3;
  630. sub+=texs.New().create(TEX_RFL_D , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*0, i*prop_height), tex_size, tex_size), "Reflect\nDown" , T);
  631. sub+=texs.New().create(TEX_RFL_U , MEMBER(EditMaterial, reflection_map), MEMBER(EditMaterial, reflection_map_time), Rect_LU(prop_rect.ru()+Vec2(e+tex_size*1, i*prop_height), tex_size, tex_size), "Reflect\nUp" , T); i-=3;
  632. sub+=texs.New().create(TEX_LIGHT , MEMBER(EditMaterial, light_map), MEMBER(EditMaterial, light_map_time), Rect_LU(prop_rect.ru()+Vec2(e , i*prop_height), tex_size, tex_size), "Light" , T);
  633. REPA(texs)sub+=texs[i].remove;
  634. sub+=reload_base_textures.create("Reload Base Textures").func(ReloadBaseTextures, T).desc("Reload base textures, such as Color, Alpha, Bump, Normal, Specular and Glow, from their original source files.");
  635. Node<MenuElm> n;
  636. n.New().create(auto_reload_name, AutoReload, T).flag(MENU_TOGGLABLE).setOn(auto_reload).desc("If this is enabled then base textures will be instantly reloaded when changing them.\nIf you only want to change the source file paths, without actually reloading the textures, then you can disable this option first.");
  637. {
  638. Node<MenuElm> &resize=(n+="Resize Base Textures"); resize.desc("This allows to resize the base textures, such as Color, Alpha, Bump, Normal, Specular and Glow to a custom size.");
  639. resize.New().create( "128x128" , ResizeBase128 , T);
  640. resize.New().create( "256x256" , ResizeBase256 , T);
  641. resize.New().create( "512x512" , ResizeBase512 , T);
  642. resize.New().create("1024x1024", ResizeBase1024, T);
  643. resize.New().create("2048x2048", ResizeBase2048, T);
  644. resize.New().create("4096x4096", ResizeBase4096, T);
  645. Node<MenuElm> &other=(resize+="Other");
  646. other.New().create("128x64" , ResizeBase128x64, T);
  647. other.New().create("256x128" , ResizeBase256x128, T);
  648. other.New().create("512x256" , ResizeBase512x256, T);
  649. other.New().create("1024x512" , ResizeBase1024x512, T);
  650. other.New().create("2048x1024", ResizeBase2048x1024, T);
  651. other++;
  652. other.New().create("64x128" , ResizeBase64x128, T);
  653. other.New().create("128x256" , ResizeBase128x256, T);
  654. other.New().create("256x512" , ResizeBase256x512, T);
  655. other.New().create("512x1024" , ResizeBase512x1024, T);
  656. other.New().create("1024x2048", ResizeBase1024x2048, T);
  657. resize++;
  658. resize.New().create("Quarter" , ResizeBaseQuarter , T);
  659. resize.New().create("Half" , ResizeBaseHalf , T);
  660. resize.New().create("Original", ResizeBaseOriginal, T);
  661. resize.New().create("Double" , ResizeBaseDouble , T);
  662. }
  663. {
  664. Node<MenuElm> &resize=(n+="Resize Base 0 Textures"); resize.desc("This allows to resize the base 0 textures, such as Color and Alpha to a custom size.");
  665. resize.New().create( "128x128" , ResizeBase0_128 , T);
  666. resize.New().create( "256x256" , ResizeBase0_256 , T);
  667. resize.New().create( "512x512" , ResizeBase0_512 , T);
  668. resize.New().create("1024x1024", ResizeBase0_1024, T);
  669. resize.New().create("2048x2048", ResizeBase0_2048, T);
  670. resize.New().create("4096x4096", ResizeBase0_4096, T);
  671. Node<MenuElm> &other=(resize+="Other");
  672. other.New().create("128x64" , ResizeBase0_128x64, T);
  673. other.New().create("256x128" , ResizeBase0_256x128, T);
  674. other.New().create("512x256" , ResizeBase0_512x256, T);
  675. other.New().create("1024x512" , ResizeBase0_1024x512, T);
  676. other.New().create("2048x1024", ResizeBase0_2048x1024, T);
  677. other++;
  678. other.New().create("64x128" , ResizeBase0_64x128, T);
  679. other.New().create("128x256" , ResizeBase0_128x256, T);
  680. other.New().create("256x512" , ResizeBase0_256x512, T);
  681. other.New().create("512x1024" , ResizeBase0_512x1024, T);
  682. other.New().create("1024x2048", ResizeBase0_1024x2048, T);
  683. resize++;
  684. resize.New().create("Quarter" , ResizeBase0_Quarter , T);
  685. resize.New().create("Half" , ResizeBase0_Half , T);
  686. resize.New().create("Original", ResizeBase0_Original, T);
  687. resize.New().create("Double" , ResizeBase0_Double , T);
  688. }
  689. {
  690. Node<MenuElm> &resize=(n+="Resize Base 1 Textures"); resize.desc("This allows to resize the base 1 textures, such as Alpha, Normal, Specular and Glow to a custom size.");
  691. resize.New().create( "128x128" , ResizeBase1_128 , T);
  692. resize.New().create( "256x256" , ResizeBase1_256 , T);
  693. resize.New().create( "512x512" , ResizeBase1_512 , T);
  694. resize.New().create("1024x1024", ResizeBase1_1024, T);
  695. resize.New().create("2048x2048", ResizeBase1_2048, T);
  696. resize.New().create("4096x4096", ResizeBase1_4096, T);
  697. Node<MenuElm> &other=(resize+="Other");
  698. other.New().create("128x64" , ResizeBase1_128x64, T);
  699. other.New().create("256x128" , ResizeBase1_256x128, T);
  700. other.New().create("512x256" , ResizeBase1_512x256, T);
  701. other.New().create("1024x512" , ResizeBase1_1024x512, T);
  702. other.New().create("2048x1024", ResizeBase1_2048x1024, T);
  703. other++;
  704. other.New().create("64x128" , ResizeBase1_64x128, T);
  705. other.New().create("128x256" , ResizeBase1_128x256, T);
  706. other.New().create("256x512" , ResizeBase1_256x512, T);
  707. other.New().create("512x1024" , ResizeBase1_512x1024, T);
  708. other.New().create("1024x2048", ResizeBase1_1024x2048, T);
  709. resize++;
  710. resize.New().create("Quarter" , ResizeBase1_Quarter , T);
  711. resize.New().create("Half" , ResizeBase1_Half , T);
  712. resize.New().create("Original", ResizeBase1_Original, T);
  713. resize.New().create("Double" , ResizeBase1_Double , T);
  714. }
  715. {
  716. Node<MenuElm> &bump=(n+="Set Bump from Color");
  717. //bump.New().create("Blur Auto", BumpFromCol , T);
  718. bump.New().create("Blur 2" , BumpFromCol2 , T);
  719. bump.New().create("Blur 3" , BumpFromCol3 , T);
  720. bump.New().create("Blur 4" , BumpFromCol4 , T);
  721. bump.New().create("Blur 5" , BumpFromCol5 , T);
  722. bump.New().create("Blur 6" , BumpFromCol6 , T);
  723. bump.New().create("Blur 8" , BumpFromCol8 , T);
  724. bump.New().create("Blur 12" , BumpFromCol12, T);
  725. bump.New().create("Blur 16" , BumpFromCol16, T);
  726. bump.New().create("Blur 24" , BumpFromCol24, T);
  727. bump.New().create("Blur 32" , BumpFromCol32, T);
  728. }
  729. {
  730. Node<MenuElm> &extra=(n+="Extra");
  731. extra.New().create("Multiply Color Texture by Color" , MulTexCol , T);
  732. extra.New().create("Multiply Normal Texture by Roughness", MulTexRough, T);
  733. }
  734. sub+=texture_options.create().setData(n); texture_options.flag|=COMBOBOX_CONST_TEXT;
  735. setBottom(prop_rect);
  736. preview_mesh[0].create(1).parts[0].base.create(Ball(0.42f ), VTX_NRM|VTX_TAN|VTX_TEX0, 16);
  737. preview_mesh[1].create(1).parts[0].base.create(Box (0.42f/SQRT3), VTX_NRM|VTX_TAN|VTX_TEX0 );
  738. preview_mesh[2].create(1).parts[0].base.create(Tube(0.12f, 0.75f), VTX_NRM|VTX_TAN|VTX_TEX0, 16);
  739. preview_mesh[3].create(1).parts[0].base.createPlane(2, 2 , VTX_NRM|VTX_TAN|VTX_TEX0 ).transform(Matrix().setRotateX(PI_2).move(-0.5f, 0, -0.5f).scale(16)).texScale(16);
  740. REPAO(preview_mesh).setRender().setBox();
  741. preview_cam.setFromAt(Vec(0, 0, -1), VecZero);
  742. }
  743. Image* MaterialRegion::getDetailBump(C Str &file)
  744. {
  745. if(!EqualPath(file, detail_bump_file))
  746. {
  747. detail_bump_file=file;
  748. Image temp; Proj.loadImage(temp, detail_bump_file);
  749. temp.copyTry(detail_bump, Min(temp.w(), 128), Min(temp.h(), 128), 1, -1, IMAGE_2D, 1, FILTER_LINEAR); // we only need a preview, so make it small, no mip maps, and fast filtering
  750. }
  751. return detail_bump.is() ? &detail_bump : null;
  752. }
  753. void MaterialRegion::resize()
  754. {
  755. rect(Rect_RU(D.w(), D.h(), rect().w(), D.h()*2));
  756. sub.rect(Rect(0.01f, -rect().h(), rect().w(), preview.rect().min.y-0.01f));
  757. sub.virtualSize(&(sub.childrenSize()+Vec2(0, 0.02f))); // add a bit of padding
  758. if(!sub.slidebar[1].visible())move(Vec2(slidebarSize(), 0));
  759. preview_big.rect(EditRect(false));
  760. }
  761. void MaterialRegion::toGui()
  762. {
  763. REPAO(props).toGui();
  764. REPAO(texs ).toGui();
  765. }
  766. void MaterialRegion::flush(C UID &elm_id) {if(T.elm_id==elm_id)flush();}
  767. void MaterialRegion::flush()
  768. {
  769. if(elm && game && changed)
  770. {
  771. if(ElmMaterial *data=elm->mtrlData()){data->newVer(); data->from(edit);} // modify just before saving/sending in case we've received data from server after edit
  772. Save( edit, Proj.editPath(elm_id)); edit.copyTo(*game, Proj);
  773. Save(*game, Proj.gamePath(elm_id)); Proj.savedGame(*elm);
  774. Proj.mtrlSetAutoTanBin(elm->id);
  775. Server.setElmLong(elm->id);
  776. if(saved.downsize_tex_mobile!=edit.downsize_tex_mobile)Proj.mtrlDownsizeTexMobile(elm_id, edit.downsize_tex_mobile); // upon flushing set all materials with same textures to the same 'downsize_tex_mobile'
  777. if(saved.high_quality_ios !=edit.high_quality_ios )Proj.mtrlTexQualityiOS (elm_id, edit.high_quality_ios ); // upon flushing set all materials with same textures to the same 'high_quality_ios'
  778. saved=edit;
  779. }
  780. changed=false;
  781. }
  782. void MaterialRegion::setChanged()
  783. {
  784. if(elm && game)
  785. {
  786. changed=true;
  787. if(ElmMaterial *data=elm->mtrlData()){data->newVer(); data->from(edit);}
  788. edit.copyTo(*game, Proj);
  789. }
  790. }
  791. void MaterialRegion::set(Elm *elm)
  792. {
  793. if(elm && elm->type!=ELM_MTRL)elm=null;
  794. if(T.elm!=elm)
  795. {
  796. flush();
  797. undos.del(); undoVis();
  798. if(elm)game= Proj.gamePath( elm->id) ;else game=&temp;
  799. if(elm)edit.load(Proj.editPath(*elm ));else edit.reset(); saved=edit;
  800. T.elm =elm;
  801. T.elm_id=(elm ? elm->id : UIDZero);
  802. toGui();
  803. Proj.refresh(false, false);
  804. if(!elm)
  805. {
  806. MaterialRegion &other=((this==&MtrlEdit) ? WaterMtrlEdit : MtrlEdit);
  807. hide(); if(other.elm)other.show();
  808. }
  809. }
  810. }
  811. void MaterialRegion::activate(Elm *elm)
  812. {
  813. set(elm); if(T.elm)
  814. {
  815. MaterialRegion &other=((this==&MtrlEdit) ? WaterMtrlEdit : MtrlEdit);
  816. show(); other.hide();
  817. }
  818. }
  819. void MaterialRegion::toggle(Elm *elm)
  820. {
  821. if(elm==T.elm && visible())elm=null; activate(elm);
  822. }
  823. void MaterialRegion::hideBig() {if(bigVisible())big.push();}
  824. MaterialRegion& MaterialRegion::show(){if(hidden ()){::EE::GuiObj::show(); resize(); CodeEdit.resize();} return T;}
  825. MaterialRegion& MaterialRegion::hide(){if(visible()){::EE::GuiObj::hide(); preview_big.hide(); REPAO(props).close(); resize(); CodeEdit.resize();} return T;}
  826. void MaterialRegion::set(C MaterialPtr &mtrl) {activate(Proj.findElm(mtrl.id()));}
  827. void MaterialRegion::set(Memt<MaterialPtr> mtrls)
  828. {
  829. REPD(i, mtrls.elms())
  830. {
  831. if(!mtrls[i])mtrls.remove(i, true); // remove if null
  832. else REPD(j, i)if(mtrls[i]==mtrls[j]){mtrls.remove(i, true); break;} // remove duplicates
  833. }
  834. FREPA(mtrls)if(mtrls[i]==game){set(mtrls[(i+1)%mtrls.elms()]); return;} // activate next
  835. if(mtrls.elms())set(mtrls[0]); // activate first
  836. }
  837. void MaterialRegion::drag(Memc<UID> &elms, GuiObj *focus_obj, C Vec2 &screen_pos)
  838. {
  839. if(contains(focus_obj))
  840. {
  841. FREPA(elms)if(Elm *elm=Proj.findElm(elms[i]))if(elm->type==elm_type)
  842. {
  843. activate(elm);
  844. break;
  845. }else
  846. if(elm->type==ELM_IMAGE)
  847. {
  848. REPA(texs)if(texs[i].contains(focus_obj))
  849. {
  850. texs[i].setFile(EncodeFileName(elm->id));
  851. break;
  852. }
  853. break;
  854. }
  855. elms.clear(); // processed
  856. }
  857. }
  858. int MaterialRegion::Compare(C ImageSource &a, C ImageSource &b) {return ::Compare(a.order, b.order);}
  859. void MaterialRegion::drop(Memc<Str> &names, GuiObj *focus_obj, C Vec2 &screen_pos)
  860. {
  861. if(contains(focus_obj))REPA(texs)if(texs[i].contains(focus_obj))
  862. {
  863. Memc<ImageSource> images; FREPA(names)if(ExtType(GetExt(names[i]))==EXT_IMAGE)images.New().name=CodeEdit.importPaths(names[i]);
  864. if(images.elms()>1)REPA(images) // detect if there are any special maps
  865. {
  866. ImageSource &image=images[i];
  867. Str base=GetBaseNoExt(image.name);
  868. if(Contains(base, "ao", false, true) || Contains(base, "AO", true) || Contains(base, "occlusion")){image.order=1; image.params.New().set("mode", "mul" );}else // AO
  869. if(Contains(base, "illumination") || Contains(base, "glow") || Contains(base, "emissive") ){image.order=2; image.params.New().set("mode", "blend");} // glow
  870. }
  871. images.sort(Compare); // sort by order
  872. texs[i].setFile(Edit::FileParams::Encode(SCAST(Memc<Edit::FileParams>, images)));
  873. break;
  874. }
  875. }
  876. void MaterialRegion::rebuildBase(uint old_base_tex, bool changed_flip_normal_y, bool adjust_params, bool always)
  877. {
  878. if(elm && game)
  879. {
  880. bool want_tan_bin=game->wantTanBin();
  881. uint new_base_tex;
  882. if(auto_reload || always)
  883. {
  884. new_base_tex=Proj.mtrlCreateBaseTextures(edit, changed_flip_normal_y); // set precise
  885. Time.skipUpdate(); // compressing textures can be slow
  886. }else
  887. {
  888. new_base_tex=edit.baseTex(); // set approximate
  889. }
  890. setChanged();
  891. Proj.mtrlTexChanged();
  892. if(adjust_params)AdjustMaterialParams(edit, *game, old_base_tex, new_base_tex);
  893. D.setShader(game());
  894. toGui();
  895. if(want_tan_bin!=game->wantTanBin())Proj.mtrlSetAutoTanBin(elm->id);
  896. }
  897. }
  898. void MaterialRegion::rebuildReflection()
  899. {
  900. if(elm && game)
  901. {
  902. Proj.mtrlCreateReflectionTexture(edit);
  903. setChanged();
  904. Proj.mtrlTexChanged();
  905. Time.skipUpdate(); // compressing textures can be slow
  906. D.setShader(game());
  907. toGui();
  908. }
  909. }
  910. void MaterialRegion::rebuildDetail()
  911. {
  912. if(elm && game)
  913. {
  914. bool want_tan_bin=game->wantTanBin();
  915. Proj.mtrlCreateDetailTexture(edit);
  916. setChanged();
  917. Proj.mtrlTexChanged();
  918. Time.skipUpdate(); // compressing textures can be slow
  919. D.setShader(game());
  920. toGui();
  921. if(want_tan_bin!=game->wantTanBin())Proj.mtrlSetAutoTanBin(elm->id);
  922. }
  923. }
  924. void MaterialRegion::rebuildMacro()
  925. {
  926. if(elm && game)
  927. {
  928. Proj.mtrlCreateMacroTexture(edit);
  929. setChanged();
  930. Proj.mtrlTexChanged();
  931. Time.skipUpdate(); // compressing textures can be slow
  932. D.setShader(game());
  933. toGui();
  934. }
  935. }
  936. void MaterialRegion::rebuildLight()
  937. {
  938. if(elm && game)
  939. {
  940. Proj.mtrlCreateLightTexture(edit);
  941. setChanged();
  942. Proj.mtrlTexChanged();
  943. Time.skipUpdate(); // compressing textures can be slow
  944. D.setShader(game());
  945. toGui();
  946. }
  947. }
  948. void MaterialRegion::elmChanged(C UID &mtrl_id)
  949. {
  950. if(elm && elm->id==mtrl_id)
  951. {
  952. undos.set(null, true);
  953. EditMaterial temp; if(temp.load(Proj.editPath(*elm)))if(edit.sync(temp)){edit.copyTo(*game, Proj); toGui();}
  954. }
  955. }
  956. void MaterialRegion::erasing(C UID &elm_id) {if(elm && elm->id==elm_id)set(null);}
  957. bool MaterialRegion::winIOContains(GuiObj *go)C {REPA(texs)if(texs[i].win_io.contains(go))return true; return false;}
  958. void MaterialRegion::update(C GuiPC &gpc)
  959. {
  960. ::EE::Region::update(gpc);
  961. preview_big.visible(bigVisible());
  962. if(Gui.ms()==&preview || Gui.ms()==&preview_big)
  963. {
  964. bool rot_cam=(Ms.b(0) || Ms.b(4)), rot_light=Ms.b(1);
  965. preview_cam.transformByMouse(min_zoom, max_zoom, (rot_cam ? CAMH_ROT : 0)|CAMH_ZOOM);
  966. if(rot_light)light_angle+=Ms.d()*Vec2(-1, 1);
  967. if(rot_cam || rot_light)Ms.freeze();
  968. if(Ms.bd(0))big.push();
  969. }
  970. if(Ms.bp(2))
  971. {
  972. if(contains(Gui.ms()))set(null);else
  973. if(Gui.ms()==&preview_big)big.push();
  974. }
  975. REPA(Touches)if(Touches[i].guiObj()==&preview || Touches[i].guiObj()==&preview_big)if(Touches[i].on()){preview_cam.yaw-=Touches[i].ad().x*2.0f; preview_cam.pitch+=Touches[i].ad().y*2.0f; preview_cam.setSpherical();}
  976. if(visible() && Kb.k.k && (contains(Gui.kb()) || contains(Gui.ms()) || preview_big.contains(Gui.ms()) || winIOContains(Gui.ms())))
  977. {
  978. KbSc prev(KB_PGUP, KBSC_CTRL_CMD|KBSC_REPEAT),
  979. next(KB_PGDN, KBSC_CTRL_CMD|KBSC_REPEAT);
  980. if(prev.pd()){prev.eat(); Proj.elmNext(elm_id, -1);}else
  981. if(next.pd()){next.eat(); Proj.elmNext(elm_id );}
  982. }
  983. }
  984. MaterialRegion::MaterialRegion() : elm_type(ELM_MTRL), auto_reload(true), min_zoom(0.48f), max_zoom(3), mouse_edit_delta(0), mouse_edit_value(0), light_angle(PI_4), red(null), green(null), blue(null), alpha(null), game(&temp), elm_id(UIDZero), elm(null), changed(false), undos(true) {}
  985. MaterialRegion::Texture::Texture() : mr(null) {}
  986. MaterialRegion::ImageSource::ImageSource() : order(0) {}
  987. /******************************************************************************/