2
0

Gui.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. Progress UpdateProgress;
  5. Thread UpdateThread;
  6. Image WhiteImage;
  7. ImagePtr GlowBorder;
  8. Panel WindowNoShadow, ActiveWindowNoShadow;
  9. GuiSkin DarkSkin, LightSkin, TransparentSkin, HalfTransparentSkin, LitSkin, RedSkin, NoComboBoxImage, NoShadowSkin;
  10. /******************************************************************************/
  11. bool BigVisible ( ) {return MtrlEdit.bigVisible() || WaterMtrlEdit.bigVisible() || Theater.visible();}
  12. void HideBig ( ) {MtrlEdit.hideBig(); WaterMtrlEdit.hideBig(); Theater.hideDo();}
  13. void HideProjsAct(GuiObj &go) {go.hide(); Projs.proj_list.kbSet();} // hide and set keyboard focus to the Projects list
  14. void HideProjAct (GuiObj &go) {go.hide(); Proj .list .kbSet();} // hide and set keyboard focus to the Project view
  15. void HideEditAct (GuiObj &go) {go.hide(); Mode . kbSet();} // hide and set keyboard focus to the Edit view
  16. /******************************************************************************/
  17. RenameElmClass RenameElm;
  18. /******************************************************************************/
  19. ReplaceNameClass ReplaceName;
  20. /******************************************************************************/
  21. RenameSlotClass RenameSlot;
  22. /******************************************************************************/
  23. RenameBoneClass RenameBone;
  24. /******************************************************************************/
  25. RenameEventClass RenameEvent;
  26. /******************************************************************************/
  27. NewWorldClass NewWorld;
  28. /******************************************************************************/
  29. cchar8 *ModeText[]=
  30. {
  31. "Object",
  32. "Anim",
  33. "World",
  34. "GuiSkin",
  35. "Gui",
  36. "Code",
  37. "Texture Downsize",
  38. };
  39. ModeTabs Mode;
  40. /******************************************************************************/
  41. ReloadElmClass ReloadElm;
  42. /******************************************************************************/
  43. ImportCodeClass ImportCode;
  44. /******************************************************************************/
  45. SetMtrlColorClass SetMtrlColor;
  46. /******************************************************************************/
  47. MulSoundVolumeClass MulSoundVolume;
  48. /******************************************************************************/
  49. EraseRemovedElms EraseRemoved;
  50. /******************************************************************************/
  51. ProjectLocked ProjectLock;
  52. /******************************************************************************/
  53. ElmProperties ElmProps;
  54. /******************************************************************************/
  55. void Highlight(C Rect &rect, flt alpha, C Color &color, flt e) // Color(100, 240, 255, 0)
  56. {
  57. if(GlowBorder && alpha>0)
  58. {
  59. MIN(e, rect.size().min());
  60. Rect r=rect; r&=Rect(-D.w(), -D.h(), D.w(), D.h()); r.extend(-e/2);
  61. GlowBorder->drawBorder(Color(0, 0, 0, Mid(Round(alpha*255), 0, 255)), Color(color.r, color.g, color.b, 0), r, -e);
  62. }
  63. }
  64. /******************************************************************************/
  65. Color MaterialColor(C MaterialPtr &mtrl)
  66. {
  67. return mtrl ? mtrl->color.xyz : WHITE;
  68. }
  69. ImagePtr MaterialImage(C MaterialPtr &mtrl)
  70. {
  71. return mtrl ? (mtrl->base_0 && mtrl->base_0->is()) ? mtrl->base_0 : &WhiteImage : ImagePtr();
  72. }
  73. Color MaterialColor(C WaterMtrlPtr &mtrl)
  74. {
  75. return mtrl ? mtrl->color : WHITE;
  76. }
  77. ImagePtr MaterialImage(C WaterMtrlPtr &mtrl)
  78. {
  79. return mtrl ? (mtrl->colorMap() && mtrl->colorMap()->is()) ? mtrl->colorMap() : &WhiteImage : ImagePtr();
  80. }
  81. /******************************************************************************/
  82. void MakeRed(Color &col)
  83. {
  84. col.r=AvgI(col.r, 255);
  85. col.g=AvgI(col.g, 0);
  86. col.b=AvgI(col.b, 0);
  87. }
  88. void MakeLit(Color &col)
  89. {
  90. col.r=AvgI(col.r, 0);
  91. col.g=AvgI(col.g, 128);
  92. col.b=AvgI(col.b, 255);
  93. }
  94. void MakeTransparent(Color &col)
  95. {
  96. col.a/=2;
  97. }
  98. void MakeTransparent(GuiSkin::Button &button)
  99. {
  100. MakeTransparent(button.pushed_color);
  101. MakeTransparent(button.normal_color);
  102. MakeTransparent(button.disabled_color);
  103. MakeTransparent(button.pushed_disabled_color);
  104. }
  105. void MakeTransparent(GuiSkin::ButtonImage &button)
  106. {
  107. MakeTransparent(SCAST(GuiSkin::Button, button));
  108. MakeTransparent(button.image_color);
  109. }
  110. void SetGuiSkin(UID id)
  111. {
  112. if(!id.valid())id=Gui.default_skin;
  113. CACHE_MODE mode=GuiSkins.mode(CACHE_NULL);
  114. if(!Gui.skin.get(id))Gui.skin=Gui.default_skin;
  115. GuiSkins.mode(mode);
  116. REPAO(TextBlack ::texts ).skinChanged();
  117. REPAO(TextWhite ::texts ).skinChanged();
  118. REPAO(ImageSkin ::images ).skinChanged();
  119. REPAO(ViewportSkin::viewports).skinChanged();
  120. Proj .refresh();
  121. Projs .refresh();
  122. CodeEdit .skinChanged();
  123. EnumEdit .skinChanged();
  124. ImageAtlasEdit.skinChanged();
  125. ObjEdit .skinChanged();
  126. WorldEdit .skinChanged();
  127. Paks.remove("Gui/white.pak"); // always remove in case 'add' adds multiple times
  128. Paks.remove("Gui/neon.pak" );
  129. Color color=Gui.backgroundColor();
  130. if(color.b>color.r*1.2f)Paks.addTry("Gui/neon.pak" );else
  131. if(color.lum()<64 )Paks.addTry("Gui/white.pak");
  132. Pak pak; if(pak.load("Gui/white.pak"))REPA(pak)if(ImagePtr image=ImagePtr().find(pak.fullName(i)))image->load(pak.fullName(i)); // reload images listed in the pak
  133. if(Gui.skin)
  134. {
  135. DarkSkin=TransparentSkin=*Gui.skin;
  136. if(Gui.backgroundColor().lum()>64) // light
  137. {
  138. DarkSkin.region.normal_color=ColorBrightness(DarkSkin.region.normal_color, 0.5f);
  139. }
  140. }
  141. TransparentSkin.region.normal_color=ColorAlpha(TransparentSkin.region.normal_color, 0.35f);
  142. if(Gui.skin)
  143. {
  144. EmptyGuiSkin.font=Gui.skin->font;
  145. EmptyGuiSkin.text_style=Gui.skin->text_style;
  146. EmptyGuiSkin.button.text_size=Gui.skin->button.text_size;
  147. EmptyGuiSkin.button.text_style=Gui.skin->text_style;
  148. EmptyGuiSkin.list.cursor_color=EmptyGuiSkin.list.highlight_color=EmptyGuiSkin.list.selection_color=TRANSPARENT;
  149. }
  150. {
  151. if(Gui.skin)NoComboBoxImage=*Gui.skin;
  152. NoComboBoxImage.combobox.image=null;
  153. }
  154. {
  155. if(Gui.skin)NoShadowSkin=*Gui.skin;
  156. if(NoShadowSkin.window.normal_no_bar){ WindowNoShadow=*NoShadowSkin.window.normal_no_bar; WindowNoShadow.shadow_opacity=0; WindowNoShadow.border_color=Gui.borderColor(); NoShadowSkin.window.normal_no_bar=& WindowNoShadow;}
  157. if(NoShadowSkin.window.active_no_bar){ActiveWindowNoShadow=*NoShadowSkin.window.active_no_bar; ActiveWindowNoShadow.shadow_opacity=0; ActiveWindowNoShadow.border_color=Gui.borderColor(); NoShadowSkin.window.active_no_bar=&ActiveWindowNoShadow;}
  158. }
  159. {
  160. LightSkin=NoShadowSkin;
  161. LightSkin.region.normal=LightSkin.window.active_no_bar;
  162. LightSkin.region.normal_color=ColorBrightness(LightSkin.window.active_color, 0.92f);
  163. LightSkin.region.normal_color.a=255;
  164. }
  165. {
  166. if(Gui.skin)HalfTransparentSkin=*Gui.skin;
  167. MakeTransparent(HalfTransparentSkin.button);
  168. MakeTransparent(HalfTransparentSkin.slidebar.left);
  169. MakeTransparent(HalfTransparentSkin.slidebar.right);
  170. MakeTransparent(HalfTransparentSkin.slidebar.center);
  171. MakeTransparent(HalfTransparentSkin.slidebar.background_color);
  172. MakeTransparent(HalfTransparentSkin.checkbox. normal_color);
  173. MakeTransparent(HalfTransparentSkin.checkbox.disabled_color);
  174. MakeTransparent(HalfTransparentSkin.combobox);
  175. MakeTransparent(HalfTransparentSkin.textline. normal_panel_color);
  176. MakeTransparent(HalfTransparentSkin.textline. normal_text_color );
  177. MakeTransparent(HalfTransparentSkin.textline.disabled_panel_color);
  178. MakeTransparent(HalfTransparentSkin.textline.disabled_text_color );
  179. }
  180. {
  181. if(Gui.skin)RedSkin=*Gui.skin;
  182. MakeRed(RedSkin.button.pushed_color);
  183. MakeRed(RedSkin.button.normal_color);
  184. MakeRed(RedSkin.button.disabled_color);
  185. MakeRed(RedSkin.button.pushed_disabled_color);
  186. MakeRed(RedSkin.checkbox. normal_color);
  187. MakeRed(RedSkin.checkbox.disabled_color);
  188. MakeRed(RedSkin.combobox.pushed_color);
  189. MakeRed(RedSkin.combobox.normal_color);
  190. MakeRed(RedSkin.combobox.disabled_color);
  191. MakeRed(RedSkin.combobox.pushed_disabled_color);
  192. MakeRed(RedSkin.combobox.image_color);
  193. MakeRed(RedSkin.textline. normal_panel_color);
  194. MakeRed(RedSkin.textline. normal_text_color );
  195. MakeRed(RedSkin.textline.disabled_panel_color);
  196. MakeRed(RedSkin.textline.disabled_text_color );
  197. }
  198. {
  199. if(Gui.skin)LitSkin=*Gui.skin;
  200. MakeLit(LitSkin.button.pushed_color);
  201. MakeLit(LitSkin.button.normal_color);
  202. MakeLit(LitSkin.button.disabled_color);
  203. MakeLit(LitSkin.button.pushed_disabled_color);
  204. MakeLit(LitSkin.checkbox. normal_color);
  205. MakeLit(LitSkin.checkbox.disabled_color);
  206. MakeLit(LitSkin.combobox.pushed_color);
  207. MakeLit(LitSkin.combobox.normal_color);
  208. MakeLit(LitSkin.combobox.disabled_color);
  209. MakeLit(LitSkin.combobox.pushed_disabled_color);
  210. MakeLit(LitSkin.combobox.image_color);
  211. MakeLit(LitSkin.textline. normal_panel_color);
  212. MakeLit(LitSkin.textline. normal_text_color );
  213. MakeLit(LitSkin.textline.disabled_panel_color);
  214. MakeLit(LitSkin.textline.disabled_text_color );
  215. }
  216. }
  217. void InitGui()
  218. {
  219. WhiteImage.create(1, 1, 1, IMAGE_L8, IMAGE_2D, 1);
  220. if(WhiteImage.lock(LOCK_WRITE))
  221. {
  222. WhiteImage.color(0, 0, WHITE);
  223. WhiteImage.unlock();
  224. }
  225. GlowBorder="Gui/Misc/glow border.img";
  226. UID skin_id(3070792110, 1173521724, 2244074370, 3689187718); // this is "Dark Grey"
  227. if(C TextNode *video=Settings.findNode("Video"))if(C TextNode *p=video->findNode("GuiSkin"))skin_id=VidOpt.skinID(p->asText());
  228. SetGuiSkin(skin_id);
  229. }
  230. void ShutGui()
  231. {
  232. }
  233. /******************************************************************************/
  234. OP_HM_MODE OpHm =OP_HM_NONE;
  235. OP_OBJ_MODE OpObj=OP_OBJ_NONE;
  236. void SetHmOp(OP_HM_MODE op)
  237. {
  238. if(OpHm!=op)
  239. {
  240. OpHm=op;
  241. WorldEdit.hm_add_rem.set(op==OP_HM_ADD_REM, QUIET);
  242. if(op!=OP_HM_HEIGHT)HeightBrush.mode.set(-1, QUIET);
  243. if(op!=OP_HM_COLOR ) ColorBrush. set(-1, QUIET);
  244. MtrlBrush.scale.set(op==OP_HM_MTRL_SCALE, QUIET);
  245. MtrlBrush.hole .set(op==OP_HM_MTRL_HOLE , QUIET);
  246. MtrlBrush.max1 .set(op==OP_HM_MTRL_MAX_1, QUIET);
  247. MtrlBrush.max2 .set(op==OP_HM_MTRL_MAX_2, QUIET);
  248. if(op!=OP_HM_MTRL)MtrlBrush.set(-1, QUIET);
  249. }
  250. }
  251. void SetObjOp(OP_OBJ_MODE op)
  252. {
  253. if(OpObj!=op)
  254. {
  255. OpObj=op;
  256. MtrlEdit.set_mtrl.set(op==OP_OBJ_SET_MTRL, QUIET);
  257. if(op!=OP_OBJ_SET_GROUP)REPAO(ObjEdit.group.set_groups).set(false, QUIET);
  258. if(op!=OP_OBJ_NONE &&
  259. (ObjEdit.mode()==ObjView::SLOTS
  260. || ObjEdit.mode()==ObjView::RAGDOLL
  261. || ObjEdit.mode()==ObjView::PHYS
  262. || ObjEdit.mode()==ObjView::BONES
  263. || ObjEdit.mode()==ObjView::SKIN
  264. || ObjEdit.mode()==ObjView::REMOVE))ObjEdit.mode.set(-1);
  265. }
  266. }
  267. void Drag(Memc<UID> &elms, GuiObj *obj, C Vec2 &screen_pos)
  268. {
  269. Proj.drag(elms, obj, screen_pos);
  270. MtrlEdit.drag(elms, obj, screen_pos);
  271. WaterMtrlEdit.drag(elms, obj, screen_pos);
  272. ObjEdit.drag(elms, obj, screen_pos);
  273. WorldEdit.drag(elms, obj, screen_pos);
  274. ImportTerrain.drag(elms, obj, screen_pos);
  275. ObjClassEdit.drag(elms, obj, screen_pos);
  276. TextStyleEdit.drag(elms, obj, screen_pos);
  277. PanelEdit.drag(elms, obj, screen_pos);
  278. CodeEdit.drag(elms, obj, screen_pos);
  279. AppPropsEdit.drag(elms, obj, screen_pos);
  280. ImageEdit.drag(elms, obj, screen_pos);
  281. ImageAtlasEdit.drag(elms, obj, screen_pos);
  282. AnimEdit.drag(elms, obj, screen_pos);
  283. GuiEdit.drag(elms, obj, screen_pos);
  284. ObjPaint.drag(elms, obj, screen_pos);
  285. MSM.drag(elms, obj, screen_pos);
  286. CreateMtrls.drag(elms, obj, screen_pos);
  287. ConvertToAtlas.drag(elms, obj, screen_pos);
  288. ConvertToDeAtlas.drag(elms, obj, screen_pos);
  289. if(obj && obj->type()==GO_TEXTLINE && elms.elms())REPA(PropEx::props) // first check if this is a PropEx
  290. {
  291. PropEx &prop=PropEx::props[i]; if(&prop.textline==obj)
  292. {
  293. // find compatible element
  294. if(prop.elm_type)REPA(elms)if(Elm *elm=Proj.findElm(elms[i]))if(prop.compatible(elm->type))
  295. {
  296. prop.set(elm->id.asHex()) // first set using HEX to make sure it detects correct Elm in case of multiple elements with same path
  297. .set(Proj.elmFullName(elm), QUIET) // then set textline to be as path and not HEX
  298. .textline.selectAll();
  299. return;
  300. }
  301. Gui.msgBox("Incompatible Element", prop.elm_type ? S+"This property accepts only "+ElmTypeName[prop.elm_type]+" elements." : S+"This property doesn't accepts elements");
  302. return;
  303. }
  304. }
  305. }
  306. /******************************************************************************/
  307. /******************************************************************************/
  308. ObjPtrs<TextWhite> TextWhite::texts;
  309. ObjPtrs<TextBlack> TextBlack::texts;
  310. ObjPtrs<ViewportSkin> ViewportSkin::viewports;
  311. ObjPtrs<ImageSkin> ImageSkin::images;
  312. ObjPtrs<PropEx> PropEx::props;
  313. /******************************************************************************/
  314. void TextWhite::skinChanged() {resetColors(false);}
  315. TextWhite& TextWhite::reset() {::EE::TextStyle::reset(false); return T;}
  316. TextWhite& TextWhite::operator= (C TextStyle &ts) {SCAST(TextStyle, T)=ts; return T;}
  317. TextWhite::TextWhite() {texts.include(T);}
  318. TextWhite::~TextWhite() {texts.exclude(T);}
  319. void TextBlack::skinChanged() {resetColors(true);}
  320. TextBlack& TextBlack::reset() {::EE::TextStyle::reset(true); return T;}
  321. TextBlack& TextBlack::operator= (C TextStyle &ts) {SCAST(TextStyle, T)=ts; return T;}
  322. TextBlack::TextBlack() {texts.include(T);}
  323. TextBlack::~TextBlack() {texts.exclude(T);}
  324. void ViewportSkin::skinChanged() {rect_color=Gui.borderColor();}
  325. ViewportSkin::ViewportSkin() {viewports.include(T);}
  326. ViewportSkin::~ViewportSkin() {viewports.exclude(T);}
  327. void ImageSkin::skinChanged() {rect_color=Gui.borderColor();}
  328. ImageSkin::ImageSkin() {images.include(T);}
  329. ImageSkin::~ImageSkin() {images.exclude(T);}
  330. GuiObj* TextNoTest::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return null;}
  331. void PropEx::Clear(PropEx &prop) {prop.clear();}
  332. bool PropEx::compatible(ELM_TYPE elm_type)C {return ElmCompatible(elm_type, T.elm_type);}
  333. void PropEx::setDesc( ) {Str d=_desc; if(elm_type)d.line()+=S+"Drag and drop "+ElmTypeName[elm_type]+" element here\nCtrl+LeftClick to open it"; ::EE::Property::desc(d);}
  334. PropEx& PropEx::desc(C Str &desc ) {_desc=desc; setDesc(); return T;}
  335. PropEx& PropEx::setEnum( ) {::EE::Property::setEnum( ); return T;}
  336. PropEx& PropEx::setEnum(cchar8 *data[], int elms) {::EE::Property::setEnum(data, elms); return T;}
  337. PropEx& PropEx::setEnum(cchar *data[], int elms) {::EE::Property::setEnum(data, elms); return T;}
  338. PropEx& PropEx::elmType(ELM_TYPE elm_type ) {T.elm_type=elm_type; setDesc(); if(elm_type)button.create("C").func(Clear, T).desc(S+"Clear this "+((elm_type==ELM_ANY) ? "element" : ElmTypeName[elm_type])); return T;}
  339. void PropEx::clear( ) {::EE::Property::set(S);}
  340. PropEx& PropEx::create(C Str &name, C MemberDesc &md) {::EE::Property::create(name, md ); return T;}
  341. void PropEx::dragStart(bool elm_types[ELM_NUM_ANY]) {textline.enabled(elm_types[elm_type]);}
  342. void PropEx::dragEnd( ) {textline.enabled(true );}
  343. PropEx::PropEx() : elm_type(ELM_NONE) {props.include(T);}
  344. PropEx::~PropEx() {props.exclude(T);}
  345. Rect PropWin::create(C Str &name, C Vec2 &lu, C Vec2 &text_scale, flt property_height, flt value_width)
  346. {
  347. ts.reset().size=text_scale; ts.align.set(1, 0);
  348. Gui+=::EE::Window::create(name).hide();
  349. Rect rect =AddProperties(props, T, lu, property_height, value_width, &ts);
  350. flt right=Max(rect.max.x, defaultBarFullWidth()+button[2].rect().w()); // here 'button[2]' is hidden so add it manually
  351. Vec2 padd =defaultInnerPaddingSize()+0.02f; T.rect(Rect_RD(D.w(), -D.h(), right+padd.x, -rect.min.y+padd.y));
  352. return rect;
  353. }
  354. PropEx & PropWin::add(C Str &name, C MemberDesc &md) {return props.New().create(name, md);}
  355. PropWin& PropWin::toGui( ) {REPAO(props). toGui ( ); return T;}
  356. PropWin& PropWin::toGui(cptr data) {REPAO(props). toGui (data); return T;}
  357. PropWin& PropWin::autoData( ptr data) {REPAO(props).autoData(data); return T;}
  358. ptr PropWin::autoData()C {FREPA(props)if(ptr data=props[i].autoData())return data; return null;}
  359. PropWin& PropWin::changed(void (*changed)(C Property &prop), void (*pre_changed)(C Property &prop)) {REPAO(props).changed(changed, pre_changed); return T;}
  360. PropWin& PropWin::hide(){::EE::Window::hide(); REPAO(props).close(); return T;}
  361. void RenameElmClass::create()
  362. {
  363. Gui+=::EE::Window::create(Rect_C(0, 0, 1, 0.14f), "Rename Element").level(1).hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  364. T +=textline.create(Rect (0, -clientHeight(), clientWidth(), 0).extend(-0.01f));
  365. }
  366. void RenameElmClass::activate(C UID &elm_id, C Str &name)
  367. {
  368. T.elm_id=elm_id;
  369. textline.set(name).selectAll().activate();
  370. ::EE::GuiObj::activate();
  371. }
  372. void RenameElmClass::activate(C UID &elm_id) {activate(Proj.findElm(elm_id));}
  373. void RenameElmClass::activate( Elm *elm ) {if(elm)activate(elm->id, elm->name);}
  374. void RenameElmClass::update(C GuiPC &gpc)
  375. {
  376. ::EE::ClosableWindow::update(gpc);
  377. if(Gui.window()==this)
  378. {
  379. if(Kb.k(KB_ENTER)){Proj.renameElm(elm_id, textline()); hide(); Kb.eatKey(); Proj.list.activate();} // set keyboard focus to the Project view
  380. }
  381. }
  382. void ReplaceNameClass::create()
  383. {
  384. flt y=-0.05f;
  385. Gui+=::EE::Window::create(Rect_C(0, 0, 1, 0.23f), "Replace Name Part").level(1).hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  386. T+=t_from .create(Vec2(0.1f, y), "From"); T+=from.create(Rect(0.2f, y-0.03f, clientWidth()-0.01f, y+0.03f)); y-=0.07f;
  387. T+=t_to .create(Vec2(0.1f, y), "To" ); T+=to .create(Rect(0.2f, y-0.03f, clientWidth()-0.01f, y+0.03f)); y-=0.07f;
  388. }
  389. void ReplaceNameClass::activate(C MemPtr<UID> &elm_ids)
  390. {
  391. T.elm_ids=elm_ids;
  392. if(elm_ids.elms()){from.selectAll().activate(); ::EE::GuiObj::activate();}else button[2].push();
  393. }
  394. void ReplaceNameClass::update(C GuiPC &gpc)
  395. {
  396. ::EE::ClosableWindow::update(gpc);
  397. if(Gui.window()==this)
  398. {
  399. if(Kb.k(KB_ENTER)){Proj.replaceName(elm_ids, from(), to()); hide(); Kb.eatKey(); Proj.list.activate();} // set keyboard focus to the Project view
  400. }
  401. }
  402. void RenameSlotClass::create()
  403. {
  404. Gui+=::EE::Window::create(Rect_C(0, 0, 1, 0.14f), "Rename Slot").hide(); button[2].show();
  405. T +=textline.create(Rect (0, -clientHeight(), clientWidth(), 0).extend(-0.01f));
  406. }
  407. void RenameSlotClass::activate(int slot)
  408. {
  409. if(ObjEdit.mesh_skel && InRange(slot, ObjEdit.mesh_skel->slots))
  410. {
  411. slot_name =ObjEdit.mesh_skel->slots[slot].name;
  412. slot_index=0; for(int i=0; i<slot; i++)if(slot_name==ObjEdit.mesh_skel->slots[i].name)slot_index++;
  413. textline.set(slot_name).selectAll().activate();
  414. ::EE::GuiObj::activate();
  415. }
  416. }
  417. void RenameSlotClass::update(C GuiPC &gpc)
  418. {
  419. ::EE::ClosableWindow::update(gpc);
  420. if(Gui.window()==this)
  421. {
  422. if(Kb.k(KB_ENTER)){ObjEdit.renameSlot(slot_index, slot_name, textline()); hide(); Kb.eatKey();}
  423. }
  424. }
  425. void RenameBoneClass::create()
  426. {
  427. Gui+=::EE::Window::create(Rect_C(0, 0, 1, 0.14f), "Rename Bone").hide(); button[2].show();
  428. T +=textline.create(Rect (0, -clientHeight(), clientWidth(), 0).extend(-0.01f));
  429. }
  430. void RenameBoneClass::activate(int bone)
  431. {
  432. if(ObjEdit.mesh_skel && InRange(bone, ObjEdit.mesh_skel->bones))
  433. {
  434. bone_name=ObjEdit.mesh_skel->bones[bone].name;
  435. textline.set(bone_name).selectAll().activate();
  436. ::EE::GuiObj::activate();
  437. }
  438. }
  439. void RenameBoneClass::update(C GuiPC &gpc)
  440. {
  441. ::EE::ClosableWindow::update(gpc);
  442. if(Gui.window()==this)
  443. {
  444. if(Kb.k(KB_ENTER)){Kb.eatKey(); if(ObjEdit.renameBone(bone_name, textline()))hide();}
  445. }
  446. }
  447. void RenameEventClass::Hide(RenameEventClass &re) {re.hide(); AnimEdit.focus();}
  448. void RenameEventClass::create()
  449. {
  450. Gui+=::EE::Window::create(Rect_C(0, 0, 1, 0.14f), "Rename Event").hide(); button[2].show().func(Hide, T);
  451. T +=textline.create(Rect (0, -clientHeight(), clientWidth(), 0).extend(-0.01f));
  452. }
  453. void RenameEventClass::activate(int event)
  454. {
  455. if(AnimEdit.anim && InRange(event, AnimEdit.anim->events))
  456. {
  457. event_name =AnimEdit.anim->events[event].name;
  458. event_index=0; for(int i=0; i<event; i++)if(event_name==AnimEdit.anim->events[i].name)event_index++;
  459. textline.set(event_name).selectAll().activate();
  460. ::EE::GuiObj::activate();
  461. }
  462. }
  463. void RenameEventClass::update(C GuiPC &gpc)
  464. {
  465. ::EE::ClosableWindow::update(gpc);
  466. if(Gui.window()==this)
  467. {
  468. if(Kb.k(KB_ENTER)){AnimEdit.renameEvent(event_index, event_name, textline()); Kb.eatKey(); Hide(T);}
  469. }
  470. }
  471. void NewWorldClass::OK(NewWorldClass &nw) {Proj.newWorld(nw.name(), nw.areaSize(), nw.heightmapRes(), nw.parent_id, true); HideProjAct(nw);}
  472. int NewWorldClass::areaSize() {return TextInt( area_size.text());}
  473. int NewWorldClass::heightmapRes() {return TextInt(heightmap_res .text());}
  474. void NewWorldClass::create()
  475. {
  476. static cchar8 *area_siz[]=
  477. {
  478. "32",
  479. "64 (default)",
  480. "128",
  481. // don't allow more because there will be conflict of lods with Macro textures from the shaders (which fade out at a specified distance)
  482. };
  483. static cchar8 *hm_res[]=
  484. {
  485. "32",
  486. "64 (default)",
  487. "128",
  488. }; //ASSERT(MIN_HM_RES==33 && MAX_HM_RES==129);
  489. ts.reset().align.set(1, 0);
  490. Gui+=::EE::Window::create(Rect_C(0, 0, 1.0f, 0.7f), MLTC(u"New World", PL, u"Nowy Świat", DE, u"Neue Welt", RU, u"Новый мир", PO, u"Novo Mundo")).hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  491. T+=tname.create(Vec2(0.05f, -0.1f), "Name:", &ts);
  492. T+= name.create(Rect_L(clientWidth()/2+0.05f, -0.1f, 0.35f, 0.06f));
  493. T+=tarea_size.create(Vec2(0.05f, -0.2f), MLTC(u"Area Size (meters):", PL, u"Rozmiar Obszaru (metry):", DE, u"Gebiets Größe (Meter):", RU, u"Размер области (в метрах):", PO, u"Área (metros):"), &ts);
  494. T+= area_size.create(Rect_L(clientWidth()/2+0.05f, -0.2f, 0.35f, 0.06f), area_siz, Elms(area_siz)).set(1).desc(MLTC(u"Lower Area Size is for Games which target Lower View Range with More Details.\nHigher Area Size is for Games which target Higher View Range with Less Details.", DE, u"Kleinere Gebietsgröße ist für Spiele mit geringerer Sichtweite und höherem Detail.\nGrößere Gebietsgrößen ist für Spiele die höhere Sichtweite mit weniger Detail wollen.", RU, u"Области с более низким размером. Для игр, где видимость меньше и большое количество деталей.\nОбласти с более высоким размером. Для игр, где видимость больше и меньше количество деталей.", PO, u"Áreas pequenas é para Jogos que tęm um menor alcance de visăo mas mais Detalhado.\nÁreas grandes é para Jogos que tęm maior alcance da visăo mas menos Detalhado."));
  495. T+=theightmap_res.create(Vec2(0.05f, -0.3f), MLTC(u"Heightmap Resolution:", PL, u"Rozdzielczość Heightmapy:", DE, u"Heightmap Auflösung:", RU, u"Разрешение карты высот:", PO, u"Resoluçăo do Heightmap:"), &ts);
  496. T+= heightmap_res.create(Rect_L(clientWidth()/2+0.05f, -0.3f, 0.35f, 0.06f), hm_res, Elms(hm_res)).set(1);
  497. T+=tdensity.create(Vec2(0.05f, -0.4f), MLTC(u"Heightmap Density:", PL, u"Gęstość Heightmapy:", DE, u"Heightmap Dichte:", RU, u"Плотность карты высот:", PO, u"Densidade do Heightmap:"), &ts);
  498. T+= density.create(Vec2(clientWidth()/2+0.05f, -0.4f), S, &ts);
  499. T+= ok.create(Rect_C(clientWidth()*3/8, -0.55f, 0.2f, 0.06f), MLTC(u"OK" )).func(OK , T);
  500. T+=cancel.create(Rect_C(clientWidth()*5/8, -0.55f, 0.2f, 0.06f), MLTC(u"Cancel", PL, u"Anuluj", DE, u"Abbrechen", RU, u"Отмена", PO, u"Cancelar")).func(HideProjAct, SCAST(GuiObj, T));
  501. }
  502. void NewWorldClass::display()
  503. {
  504. if(Proj.testElmsNum())
  505. {
  506. Proj.setMenuListSel();
  507. parent_id=(Proj.menu_list_sel.elms() ? Proj.menu_list_sel[0] : UIDZero);
  508. name.set(Proj.newElmName(ELM_WORLD, parent_id));
  509. ::EE::GuiObj::activate();
  510. }
  511. }
  512. void NewWorldClass::update(C GuiPC &gpc)
  513. {
  514. ::EE::ClosableWindow::update(gpc);
  515. if(visible() && gpc.visible)
  516. {
  517. density.set(S+TextReal(flt(heightmapRes())/areaSize(), -3)+MLTC(u" per meter", PL, u" na metr", DE, u" pro Meter", RU, u" за метр", PO, u" por metro"));
  518. if(Gui.window()==this && Kb.k(KB_ENTER))ok.push();
  519. }
  520. }
  521. void ModeTabs::TabEx::update(C GuiPC &gpc)
  522. {
  523. GuiSkinPtr temp; if(Mode.Gui_skin){Swap(temp, Gui.skin); Gui.skin=Mode.Gui_skin;} // restore Editor's Gui.skin before updating this Tab
  524. ::EE::Button::update(gpc);
  525. if(temp)Swap(Gui.skin, temp);
  526. }
  527. void ModeTabs::TabEx::draw(C GuiPC &gpc)
  528. {
  529. if(gpc.visible && visible())
  530. {
  531. GuiSkinPtr temp; if(Mode.Gui_skin){Swap(temp, Gui.skin); Gui.skin=Mode.Gui_skin;} // restore Editor's Gui.skin before drawing this Tab
  532. ::EE::Button::draw(gpc);
  533. if(temp)Swap(Gui.skin, temp);
  534. }
  535. }
  536. ModeTabs::ModeTabs() {Zero(available); replaceClass<TabEx>();}
  537. void ModeTabs::CloseActive(ModeTabs &mt ) {mt.closeActive(true);}
  538. void ModeTabs::closeActive(bool all) {closeTab(T(), all);}
  539. void ModeTabs::Changed(ModeTabs &mt) {mt.changed();}
  540. void ModeTabs::changed()
  541. {
  542. Misc.updateMove();
  543. ObjEdit.selectedChanged();
  544. AnimEdit.selectedChanged();
  545. WorldEdit.selectedChanged();
  546. GuiSkinEdit.selectedChanged();
  547. GuiEdit.selectedChanged();
  548. CodeEdit.selectedChanged();
  549. TexDownsize.selectedChanged();
  550. if(InRange(T(), MODE_NUM))
  551. {
  552. order.exclude(MODE(T()), true);
  553. order.include(MODE(T()));
  554. }
  555. setCloseVisibility(); // because close should always be visible for MODE_TEX_DOWN
  556. SetTitle();
  557. SetKbExclusive();
  558. if(T()==MODE_CODE)CodeEdit.resize();
  559. }
  560. Elm* ModeTabs::elm(int i)
  561. {
  562. switch(i)
  563. {
  564. case MODE_OBJ : return ObjEdit.obj_elm;
  565. case MODE_ANIM : return AnimEdit.elm;
  566. case MODE_WORLD : return WorldEdit.elm;
  567. case MODE_GUI_SKIN: return GuiSkinEdit.elm;
  568. case MODE_GUI : return GuiEdit.elm;
  569. }
  570. return null;
  571. }
  572. void ModeTabs::closeTab(int i, bool all)
  573. {
  574. switch(i)
  575. {
  576. case MODE_OBJ : ObjEdit.set(null); break;
  577. case MODE_ANIM : AnimEdit.set(null); break;
  578. case MODE_WORLD : WorldEdit.set(null); break;
  579. case MODE_GUI_SKIN: GuiSkinEdit.set(null); break;
  580. case MODE_GUI : GuiEdit.set(null); break;
  581. case MODE_CODE : if(all)CodeEdit.closeAll();else CodeEdit.close(); break;
  582. case MODE_TEX_DOWN: TexDownsize.close(); break;
  583. }
  584. }
  585. void ModeTabs::kbSet()
  586. {
  587. switch(T())
  588. {
  589. case MODE_OBJ : ObjEdit.kbSet(); break;
  590. case MODE_ANIM : AnimEdit.kbSet(); break;
  591. case MODE_WORLD : WorldEdit.kbSet(); break;
  592. case MODE_GUI_SKIN: GuiSkinEdit.kbSet(); break;
  593. case MODE_GUI : GuiEdit.kbSet(); break;
  594. case MODE_CODE : CodeEdit.kbSet(); break;
  595. case MODE_TEX_DOWN: TexDownsize.kbSet(); break;
  596. default : Proj.list.kbSet(); break;
  597. }
  598. }
  599. void ModeTabs::kbToggle()
  600. {
  601. if(Proj.list.contains(Gui.kb()) || !Proj.list.visibleFull())kbSet();else Proj.list.kbSet();
  602. }
  603. void ModeTabs::activateLast()
  604. {
  605. REPA(order)if(available[order[i]]){set(order[i]); return;} valid(false).set(-1).valid(true); kbSet();
  606. }
  607. void ModeTabs::create()
  608. {
  609. Gui+=::EE::Tabs::create(ModeText, Elms(ModeText)).func(Changed, T).valid(true).hide();
  610. Gui+=close.create().func(CloseActive, T).desc("Keyboard Shortcut: Alt+F3"); close.image="Gui/close.img"; close.skin=&EmptyGuiSkin;
  611. tab(MODE_OBJ )+= ObjEdit.create();
  612. tab(MODE_ANIM )+= AnimEdit.create();
  613. tab(MODE_WORLD )+= WorldEdit.create();
  614. tab(MODE_TEX_DOWN)+=TexDownsize.create();
  615. GuiSkinEdit.create(tab(MODE_GUI_SKIN));
  616. GuiEdit.create(tab(MODE_GUI ));
  617. CodeEdit.create(tab(MODE_CODE ));
  618. setTabs();
  619. changed(); // call to setup initial settings
  620. }
  621. void ModeTabs::setCloseVisibility()
  622. {
  623. close.visible(StateActive==&StateProject && (visibleTabs() || Mode()==MODE_TEX_DOWN));
  624. }
  625. void ModeTabs::setTabs()
  626. {
  627. flt x=rect().min.x; if(Misc.visible() && Misc.pos==VecI2(0, 1)){x+=rect().h()*0.1f; if(Misc.move_misc.visible())x+=Misc.move_misc.rect().w();}
  628. bool visible=visibleTabs();
  629. int v=0; FREPA(T)if(tab(i).visible(visible && available[i]).visible()){tab(i).pos(Vec2(x, rect().max.y)); v++; tab(i).desc(S+"Keyboard Shortcut: "+Kb.ctrlCmdName()+"+F"+v); x+=tab(i).rect().w();}
  630. setCloseVisibility();
  631. }
  632. Tabs& ModeTabs::rect(C Rect &rect){::EE::Tabs::rect(rect); setTabs(); return T;}
  633. C Rect& ModeTabs::rect()C {return ::EE::Tabs::rect();}
  634. void ModeTabs::resize()
  635. {
  636. flt l=-D.w(), r=D.w();
  637. if( Misc.visible() && Misc.pos==VecI2(0, 1))MAX(l, Misc.rect().max.x);else
  638. if( Proj.visible() )MAX(l, Proj.rect().max.x);
  639. if(Misc.move_misc.visible() && Misc.pos==VecI2(1, 1))MIN(r, Misc.move_misc.rect().min.x);else
  640. if( Misc.visible() && Misc.pos==VecI2(1, 1))MIN(r, Misc.rect().min.x);
  641. if( MtrlEdit.visible() )MIN(r, MtrlEdit.rect().min.x);
  642. if( WaterMtrlEdit.visible() )MIN(r, WaterMtrlEdit.rect().min.x);
  643. flt h=0.06f;
  644. rect(Rect_LU(l, D.h() , 0.17f*MODE_NUM, h )); // Tabs.rect to set rects of every single Tab
  645. GuiObj::rect(Rect (l, D.h()-h, r, D.h())); // GuiObj.rect to set rect of Tabs
  646. close.rect(Rect_RU(r, D.h(), rect().h(), rect().h()));
  647. if(InRange(MODE_TEX_DOWN, tabs()))tab(MODE_TEX_DOWN).resize(Vec2(0.2f, 0)); // make this tab wider
  648. }
  649. bool ModeTabs::tabAvailable(MODE mode )C {return available[mode];}
  650. void ModeTabs::tabAvailable(MODE mode, bool on)
  651. {
  652. if(available[mode]!=on)
  653. {
  654. available[mode]=on; setTabs(); CodeEdit.resize();
  655. if(!on && T()==mode)activateLast();
  656. }
  657. }
  658. bool ModeTabs::visibleTabs() {int v=0; REPA(T)v+=available[i]; return v>(ModeTabsAlwaysVisible ? 0 : 1);}
  659. Tab* ModeTabs::visibleTab(int t) {if(InRange(t, T))FREPA(T)if(tab(i).visible())if(!t--)return &tab(i); return null;}
  660. GuiObj& ModeTabs::show(){setCloseVisibility(); return ::EE::GuiObj::show();}
  661. GuiObj& ModeTabs::hide(){close.hide (); return ::EE::GuiObj::hide();}
  662. void ModeTabs::update(C GuiPC &gpc)
  663. {
  664. ::EE::Tabs::update(gpc);
  665. if(visible() && gpc.visible && Ms.bp(2))REPA(T)if(Gui.ms()==&tab(i)) // close Tab on middle mouse
  666. {
  667. closeTab(i, true);
  668. break;
  669. }
  670. }
  671. void ModeTabs::draw(C GuiPC &gpc)
  672. {
  673. if(gpc.visible && visible())
  674. {
  675. if(visibleTabs()){D.clip(gpc.clip); (rect()+gpc.offset).draw(BackgroundColorLight());}
  676. bool gui=(T()==MODE_GUI);
  677. if(gui){Gui_skin=Gui.skin; if(GuiSkinPtr app_skin=Proj.appGuiSkin())Swap(app_skin, Gui.skin);}
  678. ::EE::Tabs::draw(gpc);
  679. if(gui){Swap(Gui.skin, Gui_skin); Gui_skin.clear();}
  680. }
  681. }
  682. void ReloadElmClass::Select(C Str &name, ReloadElmClass &re) {re.path.set(name);}
  683. void ReloadElmClass::Select(ReloadElmClass &re) {SetPath(re.win_io.activate(), re.path(), true);}
  684. void ReloadElmClass::Reload(ReloadElmClass &re) {re.reload();}
  685. void ReloadElmClass::reload()
  686. {
  687. if(path.visible() && elms.elms()==1) // single element
  688. if(Elm *elm=Proj.findElm(elms[0]))
  689. {
  690. // adjust its source path according to textline
  691. Mems<Edit::FileParams> files=Edit::FileParams::Decode(path());
  692. if(files.elms())
  693. {
  694. if(elm->type==ELM_ANIM)
  695. {
  696. if(set_start_frame())files[0].getParam("start_frame").value=start_frame();
  697. if(set_end_frame ())files[0].getParam( "end_frame").value= end_frame();
  698. if(set_speed ())files[0].getParam("speed" ).value=speed ();
  699. if(set_optimize ())files[0].getParam("optimize" ).value=optimize ();
  700. if(mirror ())files[0].getParam("mirror" ); // uses TextBool1 so no need to specify =1
  701. }
  702. if(elm->type==ELM_ANIM || elm->type==ELM_MTRL)
  703. {
  704. files[0].getParam("name").value=name();
  705. }
  706. }
  707. elm->setSrcFile(Edit::FileParams::Encode(files));
  708. Server.setElmShort(elm->id);
  709. }
  710. Proj.elmReload(elms); // reload all elements
  711. hide();
  712. }
  713. void ReloadElmClass::activate(Memc<UID> &elms) // multiple elements
  714. {
  715. win_io.hide(); T-=text; T-=path; T-=path_sel; T-=yes; T-=t_name; T-=name; T-=set_start_frame; T-=set_end_frame; T-=set_speed; T-=set_optimize; T-=mirror; T-=start_frame; T-=end_frame; T-=speed; T-=optimize;
  716. rect(Rect_C(0, 0, 1, 0.36f)); T+=text_all; T+=yes_all;
  717. Swap(elms, T.elms);
  718. ::EE::GuiObj::activate();
  719. }
  720. void ReloadElmClass::activate(C UID &elm_id) // single element
  721. {
  722. elms.clear().add(elm_id);
  723. T-=text_all; T-=yes_all;
  724. rect(Rect_C(0, 0, 1.4f, 0.544f)); T+=text; T+=yes; T+=path; T+=path_sel; T+=yes; T-=t_name; T-=name; T-=set_start_frame; T-=set_end_frame; T-=set_speed; T-=set_optimize; T-=mirror; T-=start_frame; T-=end_frame; T-=speed; T-=optimize;
  725. path.clear();
  726. if(Elm *elm=Proj.findElm(elm_id))if(elm->type!=ELM_FOLDER && elm->type!=ELM_LIB && elm->type!=ELM_APP)
  727. {
  728. Mems<Edit::FileParams> files=Edit::FileParams::Decode(elm->srcFile());
  729. // check for which params we provide a dedicated gui, remove them from the param list because they're set in the gui, parameters without dedicated gui, keep in the name
  730. switch(elm->type)
  731. {
  732. case ELM_ANIM:
  733. {
  734. T+=t_name; T+=name.desc("This is the Animation name inside the source file.\nIf source file has multiple Animations, then one will be selected that has this name.");
  735. T+=set_start_frame; T+=set_end_frame; T+=set_speed; T+=set_optimize; T+=mirror; T+=start_frame; T+=end_frame; T+=speed; T+=optimize;
  736. if(files.elms())
  737. {
  738. C TextParam *start_frame=files[0].findParam("start_frame"); set_start_frame.set(start_frame!=null); T.start_frame.set(start_frame ? start_frame->value : S ); files[0].params.removeData(start_frame);
  739. C TextParam * end_frame=files[0].findParam( "end_frame"); set_end_frame .set( end_frame!=null); T. end_frame.set( end_frame ? end_frame->value : S ); files[0].params.removeData( end_frame);
  740. C TextParam *speed =files[0].findParam("speed" ); set_speed .set(speed !=null); T.speed .set(speed ? speed ->value : S+"1"); files[0].params.removeData(speed );
  741. C TextParam *optimize =files[0].findParam("optimize" ); set_optimize .set(optimize !=null); T.optimize .set(optimize ? optimize ->value : S+"1"); files[0].params.removeData(optimize );
  742. C TextParam *name =files[0].findParam("name" ); T.name .set(name ? name ->value : S ); files[0].params.removeData(name );
  743. C TextParam *mirror =files[0].findParam("mirror" ); T.mirror .set(mirror ? mirror->asBool1() : false); files[0].params.removeData(mirror );
  744. }
  745. }break;
  746. case ELM_MTRL:
  747. {
  748. T+=t_name; T+=name.desc("This is the Material name inside the source file.\nIf source file has multiple Materials, then one will be selected that has this name.");
  749. if(files.elms())
  750. {
  751. C TextParam *name=files[0].findParam("name"); T.name.set(name ? name->value : S); files[0].params.removeData(name);
  752. }
  753. }break;
  754. }
  755. path.set(Edit::FileParams::Encode(files));
  756. ::EE::GuiObj::activate();
  757. }
  758. }
  759. ReloadElmClass& ReloadElmClass::hide()
  760. {
  761. win_io.hide();
  762. ::EE::Window::hide();
  763. return T;
  764. }
  765. void ReloadElmClass::ToggleStart(ReloadElmClass &re) {re.start_frame.visible(re.set_start_frame());}
  766. void ReloadElmClass::ToggleEnd(ReloadElmClass &re) {re. end_frame.visible(re.set_end_frame ());}
  767. void ReloadElmClass::ToggleSpeed(ReloadElmClass &re) {re.speed .visible(re.set_speed ());}
  768. void ReloadElmClass::ToggleOptimize(ReloadElmClass &re) {re.optimize .visible(re.set_optimize ());}
  769. void ReloadElmClass::create()
  770. {
  771. cchar8 *speed_t="Set custom speed factor, default=1", *optimize_t="Set custom keyframe optimization (reduction) factor, default=1\nIf not specified, then optimization of 1 is applied.\nValue of 0 completely disables keyframe reduction.";
  772. Gui+=::EE::Window::create("Reload Elements").hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  773. text_all .create(Vec2 (0.5f , -0.09f), "Are you sure you wish to reload all selected\nelements from their original files?");
  774. text .create(Vec2 (0.7f , -0.09f), "Are you sure you wish to reload selected\nelement from its original file?");
  775. path .create(Rect_C(0.675f, -0.20f, 1.3f , 0.055f));
  776. path_sel .create(Rect_LU(path.rect().ru(), path.rect().h()), "...").func(Select, T).focusable(false);
  777. t_name .create(Vec2(0.08f, -0.264f), "Name");
  778. name .create(Rect_L(t_name.rect().right()+Vec2(0.055f, 0), 0.3f, 0.0475f));
  779. set_start_frame.create(Rect_L(0.50f, -0.264f, 0.27f, 0.0475f), "Set Start Frame").func(ToggleStart , T) ; set_start_frame.mode=BUTTON_TOGGLE; start_frame.create(Rect_LU(set_start_frame.rect().ru(), 0.15f, set_start_frame.rect().h())).hide();
  780. set_end_frame .create(Rect_L(0.98f, -0.264f, 0.25f, 0.0475f), "Set End Frame" ).func(ToggleEnd , T) ; set_end_frame .mode=BUTTON_TOGGLE; end_frame.create(Rect_LU(set_end_frame .rect().ru(), 0.15f, set_end_frame .rect().h())).hide();
  781. set_speed .create(Rect_L(0.50f, -0.328f, 0.27f, 0.0475f), "Set Speed" ).func(ToggleSpeed , T).desc( speed_t); set_speed .mode=BUTTON_TOGGLE; speed.create(Rect_LU(set_speed .rect().ru(), 0.15f, set_speed .rect().h())).hide().desc( speed_t);
  782. set_optimize .create(Rect_L(0.98f, -0.328f, 0.25f, 0.0475f), "Set Optimize" ).func(ToggleOptimize, T).desc(optimize_t); set_optimize .mode=BUTTON_TOGGLE; optimize.create(Rect_LU(set_optimize .rect().ru(), 0.15f, set_optimize .rect().h())).hide().desc(optimize_t);
  783. mirror .create(Rect_L(path.rect().min.x, -0.328f, 0.23f, 0.0475f), "Mirror"); mirror .mode=BUTTON_TOGGLE;
  784. yes_all .create(Rect_C(0.5f , -0.22f , 0.29f, 0.07f), "Yes").func(Reload, T).focusable(false);
  785. yes .create(Rect_C(0.7f , -0.408f, 0.29f, 0.07f), "Yes").func(Reload, T).focusable(false);
  786. win_io.create(S, S, S, Select, Select, T);
  787. }
  788. void ReloadElmClass::update(C GuiPC &gpc)
  789. {
  790. ::EE::ClosableWindow::update(gpc);
  791. if(Gui.window()==this)
  792. {
  793. if(Kb.k(KB_ENTER))yes.push();
  794. }
  795. }
  796. ::ImportCodeClass::Update& ImportCodeClass::Update::set(C UID &id) {T.id=id; return T;}
  797. Str ImportCodeClass::Update::AsText(C Update &code) {return Proj.elmFullName(code.id);}
  798. void ImportCodeClass::No(ImportCodeClass &is) { is.del();}
  799. void ImportCodeClass::Yes(ImportCodeClass &is) {is.apply(); is.del();}
  800. Rect ImportCodeClass::sizeLimit()C {Rect size=::EE::Window::sizeLimit(); size.min.set(0.9f, 0.5f); return size;}
  801. C Rect& ImportCodeClass::rect()C {return ::EE::Window::rect();}
  802. ImportCodeClass& ImportCodeClass::rect(C Rect &rect)
  803. {
  804. ::EE::Window::rect(rect);
  805. text .rect(Vec2(clientWidth()/2, -0.10f));
  806. region.rect(Rect_LU(0, -0.14f, clientWidth(), clientHeight()-0.205f).extend(-0.05f));
  807. yes .rect(Rect_C(clientWidth()*0.3f, -clientHeight()+0.06f, 0.25f, 0.06f));
  808. no .rect(Rect_C(clientWidth()*0.7f, -clientHeight()+0.06f, 0.25f, 0.06f));
  809. return T;
  810. }
  811. bool ImportCodeClass::apply()
  812. {
  813. bool ok=true;
  814. REPA(updates)
  815. {
  816. Update &update=updates[i];
  817. if(Elm *elm=Proj.findElm(update.id, ELM_CODE))
  818. if(elm->finalExists())
  819. ok&=Proj.codeSet(elm->id, update.data);
  820. }
  821. updates.clear();
  822. return ok;
  823. }
  824. void ImportCodeClass::import()
  825. {
  826. if(updates.elms())
  827. {
  828. Gui+=::EE::Window::create("Code Import"); button[2].func(No, T).show(); flag|=WIN_RESIZABLE;
  829. T +=text .create("Are you sure you wish to import codes\nfrom Code Synchronization folder?\nFollowing files will be modified:");
  830. T +=region.create();
  831. T +=yes .create("OK" ).func(Yes, T);
  832. T +=no .create("Cancel").func(No , T);
  833. ListColumn lc[]=
  834. {
  835. ListColumn(Update::AsText, LCW_DATA, "File"),
  836. };
  837. region+=list.create(lc, Elms(lc), true); list.sort_column[0]=0; list.setData(updates);
  838. rect(Rect_C(0, 0, 1.0f, 1.0f));
  839. activate();
  840. }else
  841. {
  842. Gui.msgBox(S, "Importing Codes completed.\nNo files were modified.");
  843. del();
  844. }
  845. }
  846. void SetMtrlColorClass::OK(SetMtrlColorClass &smc)
  847. {
  848. Proj.mtrlRGB(smc.elms, smc.rgb, smc.mul);
  849. smc.hide();
  850. }
  851. void SetMtrlColorClass::create()
  852. {
  853. add("Red" , MEMBER(SetMtrlColorClass, rgb.x)).range(0, 4);
  854. add("Green", MEMBER(SetMtrlColorClass, rgb.y)).range(0, 4);
  855. add("Blue" , MEMBER(SetMtrlColorClass, rgb.z)).range(0, 4);
  856. autoData(this);
  857. Rect r=::PropWin::create(S, Vec2(0.02f, -0.02f), 0.04f, 0.045f, 0.2f); button[2].func(HideProjAct, SCAST(GuiObj, T)).show(); hide();
  858. T+=ok.create(Rect_U(clientWidth()/2, r.min.y-0.03f, 0.25f, 0.053f), "OK").func(OK, T);
  859. rect(Rect_C(0, size()+Vec2(0, 0.09f)));
  860. }
  861. void SetMtrlColorClass::display(C MemPtr<UID> &elms, bool mul)
  862. {
  863. T.mul=mul;
  864. T.elms=elms;
  865. setTitle(mul ? "Multiply Material Color" : "Set Material Color");
  866. activate();
  867. }
  868. void SetMtrlColorClass::update(C GuiPC &gpc)
  869. {
  870. ::EE::ClosableWindow::update(gpc);
  871. if(Gui.window()==this && Kb.k(KB_ENTER))
  872. {
  873. Kb.eatKey();
  874. OK(T);
  875. }
  876. }
  877. void MulSoundVolumeClass::OK(MulSoundVolumeClass &smc)
  878. {
  879. Proj.mulSoundVolume(smc.elms, smc.volume);
  880. smc.hide();
  881. }
  882. void MulSoundVolumeClass::create()
  883. {
  884. add("Volume", MEMBER(MulSoundVolumeClass, volume)).range(0, 10);
  885. autoData(this);
  886. Rect r=::PropWin::create("Multiply Sound Volume", Vec2(0.02f, -0.02f), 0.04f, 0.045f, 0.2f); button[2].func(HideProjAct, SCAST(GuiObj, T)).show(); hide();
  887. T+=ok.create(Rect_U(clientWidth()/2, r.min.y-0.03f, 0.25f, 0.053f), "OK").func(OK, T);
  888. rect(Rect_C(0, size()+Vec2(0, 0.09f)));
  889. }
  890. void MulSoundVolumeClass::display(C MemPtr<UID> &elms)
  891. {
  892. T.elms=elms;
  893. activate();
  894. }
  895. void MulSoundVolumeClass::update(C GuiPC &gpc)
  896. {
  897. ::EE::ClosableWindow::update(gpc);
  898. if(Gui.window()==this && Kb.k(KB_ENTER))
  899. {
  900. Kb.eatKey();
  901. OK(T);
  902. }
  903. }
  904. void EraseRemovedElms::OK(EraseRemovedElms &ere) {ere.hide(); Proj.eraseRemoved();}
  905. void EraseRemovedElms::Elm::create(C ::Elm &src)
  906. {
  907. name=Proj.elmFullName(&src);
  908. id =src.id;
  909. }
  910. void EraseRemovedElms::create()
  911. {
  912. Gui+=::EE::Window::create(Rect_C(0, 0, 1.44f, 1.5f), "Erase Removed Elements").hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  913. T +=text .create(Rect_C(clientWidth()/2 , -0.15f, clientWidth()-0.05f, 0.1f), "Are you sure you wish to erase all removed elements from the project?\nWarning: This operation cannot be undone!\n\nThis will remove files only from the local computer - when connected to server it will redownload the elements."); text.auto_line=AUTO_LINE_SPACE_SPLIT;
  914. T +=ok .create(Rect_C(clientWidth()*1/3, -0.34f, 0.29f, 0.07f), "OK" ).func(OK , T ).focusable(false);
  915. T +=cancel.create(Rect_C(clientWidth()*2/3, -0.34f, 0.29f, 0.07f), "Cancel").func(HideProjAct, SCAST(GuiObj, T)).focusable(false);
  916. T +=region.create(Rect (0, -clientHeight(), clientWidth(), ok.rect().min.y-0.01f).extend(-0.03f));
  917. ListColumn lc[]=
  918. {
  919. ListColumn(MEMBER(Elm, name), LCW_MAX_DATA_PARENT, "Name"),
  920. };
  921. region+=list.create(lc, Elms(lc), true).elmHeight(0.038f).textSize(0, 1); list.cur_mode=LCM_ALWAYS;
  922. }
  923. EraseRemovedElms& EraseRemovedElms::show()
  924. {
  925. if(hidden())
  926. {
  927. Memc<UID> remove; Proj.floodRemoved(remove, Proj.root);
  928. data.clear();
  929. FREPA(remove)if(::Elm *elm=Proj.findElm(remove[i]))if(ElmVisible(elm->type))data.New().create(*elm);
  930. list.setData(data);
  931. ::EE::Window::show();
  932. }
  933. return T;
  934. }
  935. EraseRemovedElms& EraseRemovedElms::hide()
  936. {
  937. list.clear();
  938. data.clear();
  939. ::EE::Window::hide(); return T;
  940. }
  941. void EraseRemovedElms::update(C GuiPC &gpc)
  942. {
  943. ::EE::ClosableWindow::update(gpc);
  944. if(Ms.bd(0) && Gui.ms()==&list)if(Elm *elm=list())Proj.elmToggle(elm->id);
  945. }
  946. void ProjectLocked::OK(ProjectLocked &pl)
  947. {
  948. pl.del();
  949. if(Projects::Elm *proj=Projs.findProj(pl.proj_id))Projs.open(*proj, true);
  950. }
  951. void ProjectLocked::create(C UID &proj_id)
  952. {
  953. T.proj_id=proj_id;
  954. Gui+=::EE::Window::create(Rect_C(0, 0, 1.59f, 0.38f), "Project Already Opened"); button[2].show();
  955. T +=text .create(Rect_C(clientWidth()/2 , -0.10f, clientWidth()-0.08f, 0.1f), "This project appears to be already opened in another instance of the Editor.\nOpening the same project in multiple instances of the Editor may corrupt its data.\nWould you like to open it anyway?"); text.auto_line=AUTO_LINE_SPACE_SPLIT;
  956. T +=ok .create(Rect_C(clientWidth()*1/3, -0.25f, 0.29f, 0.07f), "OK" ).func(OK , T ).focusable(false);
  957. T +=cancel.create(Rect_C(clientWidth()*2/3, -0.25f, 0.29f, 0.07f), "Cancel").func(Hide, SCAST(GuiObj, T)).focusable(false);
  958. }
  959. void ElmProperties::CopyID(ElmProperties &ep) {ClipSet(ep.id ());}
  960. void ElmProperties::CopyFile(ElmProperties &ep) {ClipSet(ep.file());}
  961. void ElmProperties::Explore(ElmProperties &ep) {if(Elm *elm=Proj.findElm(ep.elm_id))Proj.explore(*elm);}
  962. void ElmProperties::create()
  963. {
  964. Gui+=::EE::Window::create(Rect_C(0, 0, 1.3f, 0.47f)).hide(); button[2].func(HideProjAct, SCAST(GuiObj, T)).show();
  965. ts.reset().size=0.046f; ts.align.set(1, 0); ts_small=ts; ts_small.size=0.04f; ts_small.align.set(1, -1);
  966. T+=t_id .create(Vec2(0.02f, -0.05f), "ID:" , &ts); T+=id .create(Vec2(0.23f, -0.03f), S, &ts_small); T+=b_id .create(Rect_R(clientWidth()-0.02f, -0.05f, 0.15f, 0.05f), "Copy").func(CopyID , T).desc(S+"Element ID can be accessed in additional ways:\n- Drag and drop the element to the codes to insert its ID at that location\n- "+Kb.ctrlCmdName()+"+RightClick the element to copy its ID to current location in codes\n- "+Kb.ctrlCmdName()+"+MiddleClick the element to copy its ID to system clipboard");
  967. T+=t_file .create(Vec2(0.02f, -0.12f), "File ID:" , &ts); T+=file .create(Vec2(0.23f, -0.10f), S, &ts_small); T+=b_file.create(Rect_R(clientWidth()-0.02f, -0.12f, 0.15f, 0.05f), "Copy").func(CopyFile, T);
  968. T+=t_size .create(Vec2(0.02f, -0.19f), "Size:" , &ts); T+=size .create(Vec2(0.23f, -0.17f), S, &ts_small);
  969. T+=t_class.create(Vec2(0.02f, -0.26f), "C++ Class:", &ts); T+=Class.create(Vec2(0.23f, -0.24f), S, &ts_small);
  970. T+=t_src .create(Vec2(0.02f, -0.33f), "Source:" , &ts); T+=b_src.create(Rect_R(clientWidth()-0.02f, -0.33f, 0.15f, 0.05f), "Explore").func(Explore, T).desc("Open folder containing the source file"); T+=src.create(Rect(0.23f, -0.38f, b_src.rect().min.x-0.02f, -0.31f), S, &ts_small); src.auto_line=AUTO_LINE_SPACE_SPLIT;
  971. }
  972. void ElmProperties::activate(Elm &elm)
  973. {
  974. if(elm.type==ELM_APP)AppPropsEdit.set(&elm);else
  975. if(!ElmPublish(elm.type))Gui.msgBox(S, "This type of element doesn't have any properties.");else
  976. {
  977. setTitle(S+"Element Properties - "+Proj.elmFullName(&elm)).activate();
  978. elm_id=elm.id;
  979. id .set(elm.id.asCString());
  980. file .set(EncodeFileName(elm.id));
  981. size .clear(); if(FExist(Proj.gamePath(elm.id)))size.set(FileSize(FSize(Proj.gamePath(elm.id))));
  982. Class.set(ElmTypeClass[elm.type]);
  983. Mems<Edit::FileParams> files=Edit::FileParams::Decode(elm.srcFile());
  984. Str src_text; FREPA(files)src_text.line()+=files[i].name; // ignore parameters
  985. src .set(src_text);
  986. b_src.visible(src().is());
  987. }
  988. }
  989. RenameElmClass::RenameElmClass() : elm_id(UIDZero) {}
  990. RenameSlotClass::RenameSlotClass() : slot_index(-1) {}
  991. RenameEventClass::RenameEventClass() : event_index(-1) {}
  992. NewWorldClass::NewWorldClass() : parent_id(UIDZero) {}
  993. ImportCodeClass::Update::Update() : id(UIDZero) {}
  994. SetMtrlColorClass::SetMtrlColorClass() : rgb(1) {}
  995. MulSoundVolumeClass::MulSoundVolumeClass() : volume(1) {}
  996. EraseRemovedElms::Elm::Elm() : id(UIDZero) {}
  997. ProjectLocked::ProjectLocked() : proj_id(UIDZero) {}
  998. ElmProperties::ElmProperties() : elm_id(UIDZero) {}
  999. /******************************************************************************/