[email protected] 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. IconSettsEditor IconSettsEdit;
  5. /******************************************************************************/
  6. IconEditor IconEdit;
  7. /******************************************************************************/
  8. /******************************************************************************/
  9. cchar8 *IconSettsEditor::IconSizes[]=
  10. {
  11. "32",
  12. "64",
  13. "128",
  14. "192",
  15. "256",
  16. "320",
  17. "384",
  18. "512",
  19. };
  20. /******************************************************************************/
  21. void IconSettsEditor::Change::create(ptr user)
  22. {
  23. data=IconSettsEdit.edit;
  24. IconSettsEdit.undoVis();
  25. }
  26. void IconSettsEditor::Change::apply(ptr user)
  27. {
  28. IconSettsEdit.edit.undo(data);
  29. IconSettsEdit.setChanged();
  30. IconSettsEdit.toGui();
  31. IconSettsEdit.undoVis();
  32. }
  33. void IconSettsEditor::undoVis() {SetUndo(undos, undo, redo);}
  34. ElmIconSetts* IconSettsEditor::data()C {return elm ? elm->iconSettsData() : null;}
  35. void IconSettsEditor::PreChanged(C Property &prop) {IconSettsEdit.undos.set(&prop);}
  36. void IconSettsEditor::Changed(C Property &prop) {IconSettsEdit.setChanged();}
  37. void IconSettsEditor::Width( IconSettsEditor &ie, C Str &t) {int i=TextInt(t); ie.edit.width=(InRange(i, IconSizes) ? TextInt(IconSizes[i]) : 128); ie.edit.width_time.getUTC();}
  38. Str IconSettsEditor::Width(C IconSettsEditor &ie ) {int nearest=-1, dist; REPA(IconSizes){int d=Abs(ie.edit.width-TextInt(IconSizes[i])); if(nearest<0 || d<dist){nearest=i; dist=d;}} return nearest;}
  39. void IconSettsEditor::Height( IconSettsEditor &ie, C Str &t) {int i=TextInt(t); ie.edit.height=(InRange(i, IconSizes) ? TextInt(IconSizes[i]) : 128); ie.edit.height_time.getUTC();}
  40. Str IconSettsEditor::Height(C IconSettsEditor &ie ) {int nearest=-1, dist; REPA(IconSizes){int d=Abs(ie.edit.height-TextInt(IconSizes[i])); if(nearest<0 || d<dist){nearest=i; dist=d;}} return nearest;}
  41. void IconSettsEditor::Type( IconSettsEditor &ie, C Str &t) {int i=TextInt(t); if(InRange(i, ElmImage::NUM))ie.edit.type=ElmImage::TYPE(i); ie.edit.type_time.getUTC();}
  42. Str IconSettsEditor::Type(C IconSettsEditor &ie ) {return ie.edit.type;}
  43. void IconSettsEditor::MipMaps( IconSettsEditor &ie, C Str &t) {ie.edit.mip_maps=TextBool(t); ie.edit.mip_maps_time.getUTC();}
  44. Str IconSettsEditor::MipMaps(C IconSettsEditor &ie ) {return ie.edit.mip_maps;}
  45. void IconSettsEditor::AutoCenter( IconSettsEditor &ie, C Str &t) {ie.edit.auto_center=TextBool(t); ie.edit.auto_center_time.getUTC();}
  46. Str IconSettsEditor::AutoCenter(C IconSettsEditor &ie ) {return ie.edit.auto_center;}
  47. void IconSettsEditor::Scale( IconSettsEditor &ie, C Str &t) {ie.edit.scale=TextFlt(t); ie.edit.scale_time.getUTC();}
  48. Str IconSettsEditor::Scale(C IconSettsEditor &ie ) {return ie.edit.scale;}
  49. void IconSettsEditor::CamYaw( IconSettsEditor &ie, C Str &t) {ie.edit.cam_angle.x=DegToRad(TextFlt(t)); ie.edit.cam_angle_time.getUTC();}
  50. Str IconSettsEditor::CamYaw(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.cam_angle.x);}
  51. void IconSettsEditor::CamPitch( IconSettsEditor &ie, C Str &t) {ie.edit.cam_angle.y=DegToRad(TextFlt(t)); ie.edit.cam_angle_time.getUTC();}
  52. Str IconSettsEditor::CamPitch(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.cam_angle.y);}
  53. void IconSettsEditor::CamRoll( IconSettsEditor &ie, C Str &t) {ie.edit.cam_angle.z=DegToRad(TextFlt(t)); ie.edit.cam_angle_time.getUTC();}
  54. Str IconSettsEditor::CamRoll(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.cam_angle.z);}
  55. void IconSettsEditor::CamFocusX( IconSettsEditor &ie, C Str &t) {ie.edit.cam_focus.x=TextFlt(t); ie.edit.cam_focus_time.getUTC();}
  56. Str IconSettsEditor::CamFocusX(C IconSettsEditor &ie ) {return ie.edit.cam_focus.x;}
  57. void IconSettsEditor::CamFocusY( IconSettsEditor &ie, C Str &t) {ie.edit.cam_focus.y=TextFlt(t); ie.edit.cam_focus_time.getUTC();}
  58. Str IconSettsEditor::CamFocusY(C IconSettsEditor &ie ) {return ie.edit.cam_focus.y;}
  59. void IconSettsEditor::CamFocusZ( IconSettsEditor &ie, C Str &t) {ie.edit.cam_focus.z=TextFlt(t); ie.edit.cam_focus_time.getUTC();}
  60. Str IconSettsEditor::CamFocusZ(C IconSettsEditor &ie ) {return ie.edit.cam_focus.z;}
  61. void IconSettsEditor::BloomOriginal( IconSettsEditor &ie, C Str &t) {ie.edit.bloom_original=TextFlt(t); ie.edit.bloom_original_time.getUTC();}
  62. Str IconSettsEditor::BloomOriginal(C IconSettsEditor &ie ) {return ie.edit.bloom_original;}
  63. void IconSettsEditor::BloomScale( IconSettsEditor &ie, C Str &t) {ie.edit.bloom_scale=TextFlt(t); ie.edit.bloom_scale_time.getUTC();}
  64. Str IconSettsEditor::BloomScale(C IconSettsEditor &ie ) {return ie.edit.bloom_scale;}
  65. void IconSettsEditor::BloomCut( IconSettsEditor &ie, C Str &t) {ie.edit.bloom_cut=TextFlt(t); ie.edit.bloom_cut_time.getUTC();}
  66. Str IconSettsEditor::BloomCut(C IconSettsEditor &ie ) {return ie.edit.bloom_cut;}
  67. void IconSettsEditor::Light0Shadow( IconSettsEditor &ie, C Str &t) {ie.edit.light0_shadow=TextBool(t); ie.edit.light0_shadow_time.getUTC();}
  68. Str IconSettsEditor::Light0Shadow(C IconSettsEditor &ie ) {return ie.edit.light0_shadow;}
  69. void IconSettsEditor::Light1Shadow( IconSettsEditor &ie, C Str &t) {ie.edit.light1_shadow=TextBool(t); ie.edit.light1_shadow_time.getUTC();}
  70. Str IconSettsEditor::Light1Shadow(C IconSettsEditor &ie ) {return ie.edit.light1_shadow;}
  71. void IconSettsEditor::AmbientCol( IconSettsEditor &ie, C Str &t) {ie.edit.ambient_col=TextVec(t); ie.edit.ambient_col_time.getUTC();}
  72. Str IconSettsEditor::AmbientCol(C IconSettsEditor &ie ) {return ie.edit.ambient_col;}
  73. void IconSettsEditor::AmbientOccl( IconSettsEditor &ie, C Str &t) {ie.edit.ambient_occl=TextFlt(t); ie.edit.ambient_occl_time.getUTC();}
  74. Str IconSettsEditor::AmbientOccl(C IconSettsEditor &ie ) {return ie.edit.ambient_occl;}
  75. void IconSettsEditor::AmbientRange( IconSettsEditor &ie, C Str &t) {ie.edit.ambient_range=TextFlt(t); ie.edit.ambient_range_time.getUTC();}
  76. Str IconSettsEditor::AmbientRange(C IconSettsEditor &ie ) {return ie.edit.ambient_range;}
  77. void IconSettsEditor::Light0Col( IconSettsEditor &ie, C Str &t) {ie.edit.light0_col=TextVec(t); ie.edit.light0_col_time.getUTC();}
  78. Str IconSettsEditor::Light0Col(C IconSettsEditor &ie ) {return ie.edit.light0_col;}
  79. void IconSettsEditor::Light0Yaw( IconSettsEditor &ie, C Str &t) {ie.edit.light0_angle.x=DegToRad(TextFlt(t)); ie.edit.light0_angle_time.getUTC();}
  80. Str IconSettsEditor::Light0Yaw(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.light0_angle.x);}
  81. void IconSettsEditor::Light0Pitch( IconSettsEditor &ie, C Str &t) {ie.edit.light0_angle.y=DegToRad(TextFlt(t)); ie.edit.light0_angle_time.getUTC();}
  82. Str IconSettsEditor::Light0Pitch(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.light0_angle.y);}
  83. void IconSettsEditor::Light1Col( IconSettsEditor &ie, C Str &t) {ie.edit.light1_col=TextVec(t); ie.edit.light1_col_time.getUTC();}
  84. Str IconSettsEditor::Light1Col(C IconSettsEditor &ie ) {return ie.edit.light1_col;}
  85. void IconSettsEditor::Light1Yaw( IconSettsEditor &ie, C Str &t) {ie.edit.light1_angle.x=DegToRad(TextFlt(t)); ie.edit.light1_angle_time.getUTC();}
  86. Str IconSettsEditor::Light1Yaw(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.light1_angle.x);}
  87. void IconSettsEditor::Light1Pitch( IconSettsEditor &ie, C Str &t) {ie.edit.light1_angle.y=DegToRad(TextFlt(t)); ie.edit.light1_angle_time.getUTC();}
  88. Str IconSettsEditor::Light1Pitch(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.light1_angle.y);}
  89. void IconSettsEditor::Fov( IconSettsEditor &ie, C Str &t) {ie.edit.fov=DegToRad(TextFlt(t)); ie.edit.fov_time.getUTC();}
  90. Str IconSettsEditor::Fov(C IconSettsEditor &ie ) {return RadToDeg(ie.edit.fov);}
  91. void IconSettsEditor::Undo(IconSettsEditor &editor) {editor.undos.undo();}
  92. void IconSettsEditor::Redo(IconSettsEditor &editor) {editor.undos.redo();}
  93. void IconSettsEditor::Locate(IconSettsEditor &editor) {Proj.elmLocate(editor.elm_id);}
  94. void IconSettsEditor::create()
  95. {
  96. ListColumn lct[]=
  97. {
  98. ListColumn(MEMBER(NameDesc, name), LCW_MAX_DATA_PARENT, "Name"),
  99. };
  100. add("Width" , MemberDesc( ).setFunc(Width , Width )).setEnum(IconSizes, Elms(IconSizes));
  101. add("Height" , MemberDesc( ).setFunc(Height , Height )).setEnum(IconSizes, Elms(IconSizes));
  102. add("Type" , MemberDesc( ).setFunc(Type , Type )).setEnum().combobox.setColumns(lct, Elms(lct)).setData(ElmImage::ImageTypes, ElmImage::ImageTypesElms).menu.list.setElmDesc(MEMBER(NameDesc, desc));
  103. add("Mip Maps" , MemberDesc(DATA_BOOL).setFunc(MipMaps , MipMaps ));
  104. add();
  105. add("Auto Center" , MemberDesc(DATA_BOOL).setFunc(AutoCenter , AutoCenter ));
  106. add("Scale" , MemberDesc(DATA_REAL).setFunc(Scale , Scale )).min(0.001f).mouseEditMode(PROP_MOUSE_EDIT_SCALAR);
  107. add();
  108. add("Camera Yaw" , MemberDesc(DATA_INT).setFunc(CamYaw , CamYaw ));
  109. add("Camera Pitch" , MemberDesc(DATA_INT).setFunc(CamPitch , CamPitch ));
  110. add("Camera Roll" , MemberDesc(DATA_INT).setFunc(CamRoll , CamRoll ));
  111. add();
  112. add("Camera Focus X", MemberDesc(DATA_REAL).setFunc(CamFocusX , CamFocusX ));
  113. add("Camera Focus Y", MemberDesc(DATA_REAL).setFunc(CamFocusY , CamFocusY ));
  114. add("Camera Focus Z", MemberDesc(DATA_REAL).setFunc(CamFocusZ , CamFocusZ ));
  115. add();
  116. add("Bloom Original", MemberDesc(DATA_REAL).setFunc(BloomOriginal, BloomOriginal)).range(0, 2);
  117. add("Bloom Scale" , MemberDesc(DATA_REAL).setFunc(BloomScale , BloomScale )).range(0, 2);
  118. add("Bloom Cut" , MemberDesc(DATA_REAL).setFunc(BloomCut , BloomCut )).range(0, 1);
  119. add();
  120. add("Ambient" , MemberDesc(DATA_VEC ).setFunc(AmbientCol , AmbientCol )).setColor();
  121. add("Ambient Occlusion", MemberDesc(DATA_REAL).setFunc(AmbientOccl , AmbientOccl )).range(0, 2);
  122. add("Ambient Range" , MemberDesc(DATA_REAL).setFunc(AmbientRange , AmbientRange )).range(0, 1).mouseEditSpeed(0.01f);
  123. add();
  124. add("Light 1" , MemberDesc(DATA_VEC ).setFunc(Light0Col , Light0Col )).setColor();
  125. add("Light 1 Yaw" , MemberDesc(DATA_INT ).setFunc(Light0Yaw , Light0Yaw ));
  126. add("Light 1 Pitch" , MemberDesc(DATA_INT ).setFunc(Light0Pitch , Light0Pitch ));
  127. add("Light 1 Shadows" , MemberDesc(DATA_BOOL).setFunc(Light0Shadow, Light0Shadow));
  128. add();
  129. add("Light 2" , MemberDesc(DATA_VEC ).setFunc(Light1Col , Light1Col )).setColor();
  130. add("Light 2 Yaw" , MemberDesc(DATA_INT ).setFunc(Light1Yaw , Light1Yaw ));
  131. add("Light 2 Pitch" , MemberDesc(DATA_INT ).setFunc(Light1Pitch , Light1Pitch ));
  132. add("Light 2 Shadows" , MemberDesc(DATA_BOOL).setFunc(Light1Shadow, Light1Shadow));
  133. add();
  134. add("Field of View" , MemberDesc(DATA_REAL).setFunc(Fov, Fov)).range(1, 120).mouseEditMode(PROP_MOUSE_EDIT_SCALAR);
  135. autoData(this);
  136. ::PropWin::create("Icon Settings Editor", Vec2(0.02f, -0.07f), 0.036f, 0.043f, 0.28f); ::PropWin::changed(Changed, PreChanged); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  137. T+=undo .create(Rect_LU(0.02f, -0.01f , 0.05f, 0.05f)).func(Undo, T).focusable(false).desc("Undo"); undo.image="Gui/Misc/undo.img";
  138. 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";
  139. T+=locate.create(Rect_LU(redo.rect().ru()+Vec2(0.01f, 0), 0.14f, 0.05f), "Locate").func(Locate, T).focusable(false).desc("Locate this element in the Project");
  140. move(Vec2(D.w(), 0)-rect().right());
  141. }
  142. IconSettsEditor& IconSettsEditor::hide(){set(null); ::PropWin::hide(); return T;}
  143. void IconSettsEditor::flush()
  144. {
  145. if(elm && changed)
  146. {
  147. if(ElmIconSetts *data=T.data())
  148. {
  149. data->newVer(); // modify just before saving/sending in case we've received data from server after edit
  150. data->from(edit);
  151. }
  152. Save(edit, Proj.basePath(*elm));
  153. Server.setElmLong(elm->id);
  154. }
  155. changed=false;
  156. }
  157. void IconSettsEditor::setChanged()
  158. {
  159. if(elm)
  160. {
  161. changed=true;
  162. if(ElmIconSetts *data=T.data())
  163. {
  164. data->newVer();
  165. data->from(edit); // call this here too, because data can be used for icon creation which can be called before flushing
  166. }
  167. if(ElmIcon *icon=IconEdit.data())if(icon->icon_settings_id==elm_id)IconEdit.settings=edit;
  168. }
  169. }
  170. void IconSettsEditor::set(Elm *elm)
  171. {
  172. if(elm && elm->type!=ELM_ICON_SETTS)elm=null;
  173. if(T.elm!=elm)
  174. {
  175. flush();
  176. undos.del(); undoVis();
  177. T.elm =elm;
  178. T.elm_id=(elm ? elm->id : UIDZero);
  179. if(elm)edit.load(Proj.basePath(*elm));else edit.reset();
  180. toGui();
  181. Proj.refresh(false, false);
  182. visible(T.elm!=null).moveToTop();
  183. }
  184. }
  185. void IconSettsEditor::activate(Elm *elm) {set(elm); if(T.elm)::EE::GuiObj::activate();}
  186. void IconSettsEditor::toggle(Elm *elm) {if(elm==T.elm)elm=null; set(elm);}
  187. void IconSettsEditor::erasing(C UID &elm_id) {if(elm && elm->id==elm_id)set(null);}
  188. void IconSettsEditor::elmChanged(C UID &elm_id)
  189. {
  190. if(elm && elm->id==elm_id)
  191. {
  192. undos.set(null, true);
  193. IconSettings temp; if(temp.load(Proj.basePath(*elm)))if(edit.sync(temp))toGui();
  194. }
  195. }
  196. void IconEditor::Change::create(ptr user)
  197. {
  198. if(ElmIcon *data=IconEdit.data())T.data=*data;
  199. IconEdit.undoVis();
  200. }
  201. void IconEditor::Change::apply(ptr user)
  202. {
  203. if(ElmIcon *data=IconEdit.data())
  204. {
  205. data->undo(T.data);
  206. IconEdit.setChanged();
  207. IconEdit.reloadSettings();
  208. IconEdit.toGui();
  209. IconEdit.undoVis();
  210. }
  211. }
  212. void IconEditor::Render() {IconEdit.render();}
  213. void IconEditor::render()
  214. {
  215. switch(Renderer())
  216. {
  217. case RM_PREPARE:
  218. {
  219. if(obj && obj->mesh())
  220. {
  221. SetVariation(mesh_variation); obj->mesh()->draw(skel);
  222. SetVariation();
  223. }
  224. LightDir(Matrix3().setRotateXY(settings.light0_angle.y, settings.light0_angle.x+PI).z, settings.light0_col).add(settings.light0_shadow);
  225. LightDir(Matrix3().setRotateXY(settings.light1_angle.y, settings.light1_angle.x+PI).z, settings.light1_col).add(settings.light1_shadow);
  226. }break;
  227. case RM_SHADOW:
  228. {
  229. if(obj && obj->mesh())
  230. {
  231. SetVariation(mesh_variation); obj->mesh()->drawShadow(skel);
  232. SetVariation();
  233. }
  234. }break;
  235. }
  236. }
  237. Matrix IconEditor::matrix() {return Matrix().setScale(settings.scale);}
  238. Box IconEditor::box() {return (obj && obj->mesh()) ? obj->mesh()->ext : 0;}
  239. flt IconEditor::GetDist(C Box &box) // avoid changing this func as it will break old icon settings
  240. {
  241. return Max(box.w()/(2*Tan(D.viewFovX()/2)), box.h()/(2*Tan(D.viewFovY()/2))) + box.d()/2;
  242. }
  243. flt IconEditor::getDist() // !! assumes that viewport and obj are already set !!
  244. {
  245. if(!settings.auto_center)return 1; // we need constant camera distance when auto centering is disabled
  246. return GetDist(box());
  247. }
  248. void IconEditor::Draw(Viewport &viewport) {IconEdit.draw();}
  249. void IconEditor::draw(bool final)
  250. {
  251. MOTION_MODE motion =D.motionMode (); D. motionMode (MOTION_NONE);
  252. AMBIENT_MODE ambient =D.ambientMode (); D.ambientMode (AMBIENT_ULTRA);
  253. BUMP_MODE bump =D.bumpMode (); if(final && bump<BUMP_PARALLAX)D.bumpMode(BUMP_PARALLAX);
  254. EDGE_SOFTEN_MODE edge =D.edgeSoften (); D.edgeSoften (EDGE_SOFTEN_SMAA);
  255. SHADOW_MODE shadow =D.shadowMode (); D.shadowMode (SHADOW_MAP);
  256. Vec ambient_col =D.ambientColor (); D.ambientColor (settings.ambient_col);
  257. flt ambient_contr=D.ambientContrast(); D.ambientContrast(settings.ambient_occl);
  258. Vec2 ambient_range=D.ambientRange (); D.ambientRange (settings.ambient_range);
  259. int ambient_res =D.ambientRes (); D.ambientRes (0);
  260. flt lod_fac =D.lodFactor (); D.lodFactor (0);
  261. DOF_MODE dof =D.dofMode (); D.dofMode (DOF_NONE);
  262. bool bloom_max =D.bloomMaximum ();
  263. bool bloom_half =D.bloomHalf (), shadow_jitter=D.shadowJitter();
  264. byte bloom_blurs =D.bloomBlurs (), shadow_soft =D.shadowSoft (), shd_map_num=D.shadowMapNum();
  265. bool eye_adapt =D.eyeAdaptation (); D.eyeAdaptation(false);
  266. bool astros =AstrosDraw ; AstrosDraw =false;
  267. bool ocean =Water.draw ; Water.draw =false;
  268. flt view_from=D.viewFrom(), view_range=D.viewRange(), view_fov=D.viewFov();
  269. VecI2 view_size;
  270. Sky.clear();
  271. D.bloomOriginal(settings.bloom_original).bloomScale(settings.bloom_scale).bloomCut(settings.bloom_cut);
  272. D.bloomBlurs(0).bloomHalf(true).bloomMaximum(false);
  273. D.shadowSoft(1).shadowJitter(true).shadowMapNum(6);
  274. // set object first
  275. setObj();
  276. // set variation, skeleton & anim
  277. mesh_variation=0;
  278. ElmIcon *data=T.data();
  279. Skeleton *skel=null; if(T.obj)if(C MeshPtr &mesh=T.obj->mesh())
  280. {
  281. skel=mesh->skeleton();
  282. if(data)mesh_variation=((data->variation_id==ElmIcon::InheritVariation) ? obj->meshVariationIndex() : mesh->variationFind(data->variation_id));
  283. }
  284. if(T.skel.skeleton()!=skel || !T.skel.scale() || skel && skel->bones.elms()!=T.skel.bones.elms()){T.skel.create(skel); T.skel_anim.del();}
  285. ::Animation *anim=null; if(data)if(data->anim_id.valid())anim=Animations(Proj.gamePath(data->anim_id));
  286. if(skel_anim.animation()!=anim)
  287. if(skel && anim)skel_anim.create(*skel, *anim);else skel_anim.del();
  288. flt time=(data ? data->anim_pos : 0);
  289. T.skel.clear().animate(skel_anim, time).animateRoot(anim, time).updateMatrix(matrix()).updateVelocities(false, false); T.skel.updateVelocities(false, false); // 'updateVelocities' twice to remove motion blur
  290. // set viewport
  291. VecI2 size(settings.width, settings.height);
  292. Rect rect=D.viewRect();
  293. Vec2 rect_size=rect.size();
  294. if(final)
  295. {
  296. D.viewForceSquarePixel(true);
  297. view_size=size; VecI2 screen_size(D.resW(), D.resH());
  298. if(view_size.x>screen_size.x)view_size=Round(view_size*(flt(screen_size.x)/view_size.x)); // fit X
  299. if(view_size.y>screen_size.y)view_size=Round(view_size*(flt(screen_size.y)/view_size.y)); // fit Y
  300. REP(8) // super sample
  301. {
  302. VecI2 super_size=view_size*2;
  303. if( super_size.x<=screen_size.x && super_size.y<=screen_size.y)view_size=super_size;else break;
  304. }
  305. D.viewRect(&RectI(VecI2(0), view_size));
  306. }else
  307. if(no_scale)
  308. {
  309. Vec2 view_size=D.pixelToScreenSize(size);
  310. if(view_size.x>rect_size.x)view_size*=rect_size.x/view_size.x; // fit X
  311. if(view_size.y>rect_size.y)view_size*=rect_size.y/view_size.y; // fit Y
  312. D.viewRect(Rect_C(rect.center(), view_size));
  313. }else
  314. {
  315. Vec2 view_size=size*rect_size.y/size.y; // scale to fit Y
  316. if(view_size.x>rect_size.x)view_size*=rect_size.x/view_size.x; // fit X
  317. D.viewRect(Rect_C(rect.center(), view_size));
  318. }
  319. D.viewFov (settings.fov); // set fov first
  320. D.viewRange(Max(0.1f, getDist()*5)); // 5 is needed because of 64x320 icons with low FOV
  321. D.viewFrom (D.viewRange()*0.01f);
  322. // now after obj and viewport
  323. Cam.at=settings.cam_focus;
  324. if(settings.auto_center)Cam.at+=(box()*matrix()).center();
  325. Cam.setSpherical(Cam.at, settings.cam_angle.x+PI, settings.cam_angle.y, settings.cam_angle.z, getDist()).set();
  326. if(!final)Renderer(IconEditor::Render);else
  327. if(data)
  328. {
  329. Image col, soft;
  330. D.edgeSoften(EDGE_SOFTEN_NONE); Renderer(IconEditor::Render); Renderer.capture(col , -1, -1, IMAGE_R8G8B8A8, IMAGE_SOFT, 1, true );
  331. D.edgeSoften(EDGE_SOFTEN_SMAA); Renderer(IconEditor::Render); Renderer.capture(soft, -1, -1, IMAGE_R8G8B8A8, IMAGE_SOFT, 1, false); // skip alpha for 'soft' to improve performance
  332. col .crop(col , 0, 0, view_size.x, view_size.y);
  333. soft.crop(soft, 0, 0, view_size.x, view_size.y);
  334. // copy alpha from 'col' to 'soft
  335. REPD(y, col.h())
  336. REPD(x, col.w())
  337. {
  338. Color c=soft.color(x, y); c.a=col.color(x, y).a; soft.color(x, y, c);
  339. }
  340. // !! following code assumes that background is black !!
  341. // setup anti-aliasing according to soft (soft will be darker on edges because it will be softened with black background)
  342. REPD(y, col.h())
  343. REPD(x, col.w())
  344. {
  345. Color c=col.color(x, y), s=soft.color(x, y);
  346. if(s.a) // fully opaque
  347. {
  348. if(c.r!=s.r || c.g!=s.g || c.b!=s.b) // if different (was affected by softening)
  349. {
  350. for(int sy=y-1; sy<=y+1; sy++)if(InRange(sy, col.h()))
  351. for(int sx=x-1; sx<=x+1; sx++)if(InRange(sx, col.w()))if(sx || sy)if(!soft.color(sx, sy).a) // if at least one neighbor is transparent (so we won't adjust opacity of softened pixels which are "inside" the object)
  352. {
  353. int c_lum=c.r+c.g+c.b, s_lum=s.r+s.g+s.b;
  354. if( c_lum)
  355. {
  356. c.a=Min(DivRound(c.a*s_lum, c_lum), 255);
  357. col.color(x, y, c);
  358. }
  359. goto found_transparent;
  360. }
  361. col.color(x, y, s); // copy color from soft (because this is softened surrounded by object)
  362. found_transparent:;
  363. }
  364. }else // transparent
  365. {
  366. int c_lum=c.lum(), // generated from bloom blur or blend material
  367. s_lum=s.lum(); // generated from softening
  368. if( s_lum>c_lum+3) // softening
  369. {
  370. // find max luminance of nearby opaque colors
  371. c_lum=0;
  372. for(int sy=y-1; sy<=y+1; sy++)if(InRange(sy, col.h()))
  373. for(int sx=x-1; sx<=x+1; sx++)if(InRange(sx, col.w()))if(sx || sy)
  374. {
  375. Color n=soft.color(sx, sy); if(n.a) // fully opaque neighbor
  376. {
  377. MAX(c_lum, n.lum());
  378. }
  379. }
  380. if(c_lum)
  381. {
  382. s=ColorBrightness(s, Min(8, flt(c_lum)/s_lum));
  383. s.a=Min(DivRound(255*s_lum, c_lum), 255);
  384. col.color(x, y, s);
  385. }
  386. }else
  387. if(c_lum) // bloom blur / blend material
  388. {
  389. c.a=c_lum;
  390. MAX(c_lum, 32); // limit brightness adjustment because without this, artifacts could occur (especially visible when drawing stretched and with compression enabled)
  391. c=ColorBrightness(c, 255.0f/c_lum); // increase brightness
  392. col.color(x, y, c);
  393. }
  394. }
  395. }
  396. col.resize(settings.width, settings.height, FILTER_BEST, true, true);
  397. data->hasAlpha(HasAlpha(col)).hasColor(HasColor(col));
  398. EditToGameImage(col, col, false, false, settings.type, IMAGE_2D, settings.mip_maps ? 0 : 1, data->hasColor(), data->hasAlpha(), false);
  399. setChanged(true);
  400. Save(col, Proj.gamePath(*elm)); Proj.savedGame(*elm);
  401. }
  402. D.viewForceSquarePixel(false).viewFrom(view_from).viewRange(view_range).viewFov(view_fov);
  403. D. bloomBlurs(bloom_blurs).bloomHalf(bloom_half).bloomMaximum(bloom_max);
  404. D. shadowMode(shadow ).shadowSoft(shadow_soft).shadowJitter(shadow_jitter).shadowMapNum(shd_map_num);
  405. D. lodFactor(lod_fac);
  406. D. dofMode(dof );
  407. D. edgeSoften(edge );
  408. D. bumpMode(bump );
  409. D. ambientMode(ambient).ambientColor(ambient_col).ambientContrast(ambient_contr).ambientRange(ambient_range).ambientRes(ambient_res);
  410. D. motionMode(motion );
  411. D.eyeAdaptation(eye_adapt);
  412. AstrosDraw =astros;
  413. Water.draw =ocean;
  414. }
  415. void IconEditor::makeIcon()
  416. {
  417. if(make_do)
  418. {
  419. make_do=false;
  420. if(elm){draw(true); D.viewRect(null);}
  421. }
  422. }
  423. void IconEditor::undoVis() {SetUndo(undos, undo, redo);}
  424. ElmIcon* IconEditor::data()C {return elm ? elm->iconData() : null;}
  425. void IconEditor::PreChanged(C Property &prop) {IconEdit.undos.set(&prop);}
  426. void IconEditor::Changed(C Property &prop) {IconEdit.setChanged();}
  427. void IconEditor::Object( IconEditor &ie, C Str &text) {if(ElmIcon *data=ie.data()){data->obj_id=Proj.findElmID(text, ELM_OBJ); data->obj_time.getUTC();}}
  428. Str IconEditor::Object(C IconEditor &ie ) {if(ElmIcon *data=ie.data())return Proj.elmFullName(data->obj_id); return S;}
  429. void IconEditor::Variation( IconEditor &ie, C Str &text) {if(ElmIcon *data=ie.data())if(ie.var){data->variation_id=(InRange(ie.var->combobox(), ie.mesh_variations) ? ie.mesh_variations[ie.var->combobox()].id : ElmIcon::InheritVariation); data->variation_time.getUTC();}}
  430. Str IconEditor::Variation(C IconEditor &ie ) {if(ElmIcon *data=ie.data())REPA(ie.mesh_variations)if(data->variation_id==ie.mesh_variations[i].id)return i; return S;}
  431. void IconEditor::Settings( IconEditor &ie, C Str &text) {if(ElmIcon *data=ie.data()){data->icon_settings_id=Proj.findElmID(text, ELM_ICON_SETTS); data->icon_settings_time.getUTC(); ie.reloadSettings();}}
  432. Str IconEditor::Settings(C IconEditor &ie ) {if(ElmIcon *data=ie.data())return Proj.elmFullName(data->icon_settings_id); return S;}
  433. void IconEditor::Animation( IconEditor &ie, C Str &text) {if(ElmIcon *data=ie.data()){data->anim_id=Proj.findElmID(text, ELM_ANIM); data->anim_id_time.getUTC();}}
  434. Str IconEditor::Animation(C IconEditor &ie ) {if(ElmIcon *data=ie.data())return Proj.elmFullName(data->anim_id); return S;}
  435. void IconEditor::AnimPos( IconEditor &ie, C Str &text) {if(ElmIcon *data=ie.data()){data->anim_pos=TextFlt(text); data->anim_pos_time.getUTC();}}
  436. Str IconEditor::AnimPos(C IconEditor &ie ) {if(ElmIcon *data=ie.data())return data->anim_pos; return S;}
  437. void IconEditor::Make(IconEditor &editor) {editor.make_do=true;}
  438. void IconEditor::Undo(IconEditor &editor) {editor.undos.undo();}
  439. void IconEditor::Redo(IconEditor &editor) {editor.undos.redo();}
  440. void IconEditor::Locate(IconEditor &editor) {Proj.elmLocate(editor.elm_id);}
  441. void IconEditor::setObj()
  442. {
  443. ElmIcon *data=T.data();
  444. UID obj_id=UIDZero; if(data)obj_id=data->obj_id; obj=Proj.gamePath(obj_id);
  445. }
  446. void IconEditor::meshVariationChanged()
  447. {
  448. if(var)
  449. {
  450. setObj();
  451. mesh_variations.setNum(2);
  452. mesh_variations[0].set("Inherit", ElmIcon::InheritVariation);
  453. mesh_variations[1].set("Default", 0);
  454. if(obj)if(C MeshPtr &mesh=obj->mesh())for(int i=1; i<mesh->variations(); i++)mesh_variations.New().set(mesh->variationName(i), mesh->variationID(i));
  455. var->combobox.setData(mesh_variations, null, true);
  456. }
  457. }
  458. void IconEditor::create()
  459. {
  460. add("Object" , MemberDesc(DATA_STR ).setFunc(Object , Object )).elmType(ELM_OBJ);
  461. var=&add("Variation" , MemberDesc( ).setFunc(Variation, Variation)).setEnum();
  462. add("Icon Settings" , MemberDesc(DATA_STR ).setFunc(Settings , Settings )).elmType(ELM_ICON_SETTS);
  463. add("Animation" , MemberDesc(DATA_STR ).setFunc(Animation, Animation)).elmType(ELM_ANIM);
  464. add("Animation Time", MemberDesc(DATA_REAL).setFunc(AnimPos , AnimPos ));
  465. add();
  466. add("Display:");
  467. nos=&add("No Scale", MemberDesc(MEMBER(IconEditor, no_scale)));
  468. autoData(this);
  469. flt h=0.043f;
  470. Rect r=::PropWin::create("Icon Editor", Vec2(0.02f, -0.07f), 0.036f, h, PropElmNameWidth); ::PropWin::changed(Changed, PreChanged); nos->changed(null, null);
  471. T+=undo .create(Rect_LU(0.02f, -0.01f , 0.05f, 0.05f)).func(Undo, T).focusable(false).desc("Undo"); undo.image="Gui/Misc/undo.img";
  472. 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";
  473. T+=locate.create(Rect_LU(redo.rect().ru()+Vec2(0.01f, 0), 0.14f, 0.05f), "Locate").func(Locate, T).focusable(false).desc("Locate this element in the Project");
  474. prop_max_x=r.max.x; button[1].show(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show(); flag|=WIN_RESIZABLE;
  475. T+=make.create(Rect_U(r.down()-Vec2(0, 0.04f), 0.3f, 0.055f), "Create").func(Make, T).desc("Create and save icon using current settings");
  476. T+=viewport.create(Draw);
  477. rect(Rect_C(0, 0, Min(1.7f, D.w()*2), Min(1.12f, D.h()*2)));
  478. ListColumn lc[]=
  479. {
  480. ListColumn(MEMBER(ParamEditor::MeshVariation, name), LCW_MAX_DATA_PARENT, "Name"),
  481. };
  482. var->combobox.setColumns(lc, Elms(lc), true);
  483. }
  484. void IconEditor::toGui() {meshVariationChanged(); ::PropWin::toGui();}
  485. IconEditor& IconEditor::hide( ) {set(null); ::PropWin::hide(); return T;}
  486. Rect IconEditor::sizeLimit( )C {Rect r=::EE::Window::sizeLimit(); r.min.set(0.75f, 0.45f); return r;}
  487. IconEditor& IconEditor::rect(C Rect &rect)
  488. {
  489. ::EE::Window::rect(rect);
  490. viewport.rect(Rect(prop_max_x, -clientHeight(), clientWidth(), 0).extend(-0.02f));
  491. return T;
  492. }
  493. void IconEditor::flush()
  494. {
  495. if(elm && changed)
  496. {
  497. if(ElmIcon *data=T.data())data->newVer(); // modify just before saving/sending in case we've received data from server after edit
  498. if(changed_file)Server.setElmLong(elm->id);else Server.setElmShort(elm->id);
  499. }
  500. changed=changed_file=false;
  501. }
  502. void IconEditor::setChanged(bool file)
  503. {
  504. if(elm)
  505. {
  506. changed=true;
  507. if(ElmIcon *data=T.data())
  508. {
  509. data->newVer();
  510. if(file){data->file_time.getUTC(); changed_file=true;}
  511. }
  512. }
  513. }
  514. void IconEditor::reloadSettings()
  515. {
  516. UID settings_id=UIDZero; if(ElmIcon *data=T.data())settings_id=data->icon_settings_id;
  517. if(!settings_id.valid())settings.reset();else
  518. if(IconSettsEdit.elm_id==settings_id)settings=IconSettsEdit.edit;else
  519. settings.load(Proj.editPath(settings_id));
  520. }
  521. void IconEditor::set(Elm *elm)
  522. {
  523. if(elm && elm->type!=ELM_ICON)elm=null;
  524. if(T.elm!=elm)
  525. {
  526. flush();
  527. undos.del(); undoVis();
  528. T.elm =elm;
  529. T.elm_id=(elm ? elm->id : UIDZero);
  530. reloadSettings();
  531. toGui();
  532. Proj.refresh(false, false);
  533. visible(T.elm!=null).moveToTop();
  534. }
  535. }
  536. void IconEditor::activate(Elm *elm) {set(elm); if(T.elm)::EE::GuiObj::activate();}
  537. void IconEditor::toggle(Elm *elm) {if(elm==T.elm)elm=null; set(elm);}
  538. void IconEditor::elmChanged(C UID &elm_id)
  539. {
  540. if(elm)
  541. {
  542. if(elm->id==elm_id){undos.set(null, true); reloadSettings(); toGui();}
  543. if(ElmIcon *data=T.data())
  544. {
  545. if(data->icon_settings_id==elm_id)reloadSettings();
  546. if(data-> anim_id==elm_id)skel_anim.del();
  547. }
  548. }
  549. }
  550. void IconEditor::erasing(C UID &elm_id) {if(elm && elm->id==elm_id)set(null);}
  551. IconSettsEditor::IconSettsEditor() : elm_id(UIDZero), elm(null), changed(false), undos(true) {}
  552. IconEditor::IconEditor() : make_do(false), elm_id(UIDZero), elm(null), changed(false), changed_file(false), no_scale(false), prop_max_x(0), var(null), nos(null), mesh_variation(0), undos(true) {}
  553. /******************************************************************************/