[email protected] 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. GuiView GuiEdit;
  5. /******************************************************************************/
  6. /******************************************************************************/
  7. const flt GuiView::MinSize=0.02f;
  8. Color GuiView::TextRectColor(0, 0, 0, 0);
  9. bool GuiView::IgnoreSelected=false;
  10. GuiSkinPtr GuiView::ObjEdit::Skin;
  11. GUI_OBJ_TYPE GuiView::obj_new[]=
  12. {
  13. GO_BUTTON , // Button
  14. GO_CHECKBOX, // CheckBox
  15. //GO_MENU , // Menu
  16. GO_COMBOBOX, // ComboBox
  17. GO_CUSTOM , // Custom
  18. GO_IMAGE , // Image
  19. //GO_LIST , // List
  20. //GO_MENU_BAR, // MenuBar
  21. GO_PROGRESS, // PogressBar
  22. GO_REGION , // Region
  23. GO_SLIDEBAR, // SlideBar
  24. GO_SLIDER , // Slider
  25. GO_TABS , // Tabs
  26. GO_TEXT , // Text
  27. GO_TEXTBOX , // TextBox
  28. GO_TEXTLINE, // TextLine
  29. GO_VIEWPORT, // Viewport
  30. GO_WINDOW , // Window
  31. };
  32. int GuiView::obj_new_elms=Elms(obj_new);
  33. /******************************************************************************/
  34. void GuiView::ViewportDraw(Viewport &viewport) {D.clearCol(BLACK);}
  35. GuiView::Button2::~Button2() {GuiEdit.removed(this);}
  36. GuiView::Button2::Button2() {create();}
  37. GuiObj* GuiView::Button2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  38. GuiView::CheckBox2::~CheckBox2() {GuiEdit.removed(this);}
  39. GuiView::CheckBox2::CheckBox2() {create();}
  40. GuiObj* GuiView::CheckBox2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  41. void GuiView::CheckBox2::update(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::CheckBox::update(temp);}
  42. GuiView::ComboBox2::~ComboBox2() {GuiEdit.removed(this);}
  43. GuiView::ComboBox2::ComboBox2() {create(); size(Vec2(0.3f, 0.05f));}
  44. GuiObj* GuiView::ComboBox2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::ComboBox::test(gpc, pos, mouse_wheel);}
  45. void GuiView::ComboBox2::update(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::ComboBox::update(temp);}
  46. GuiView::GuiCustom2::~GuiCustom2() {GuiEdit.removed(this);}
  47. GuiView::GuiCustom2::GuiCustom2() {create(); size(Vec2(0.3f));}
  48. GuiObj* GuiView::GuiCustom2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  49. void GuiView::GuiCustom2::draw(C GuiPC &gpc){if(gpc.visible && visible()){D.clip(gpc.clip); (rect()+gpc.offset).draw(BLACK, false);}}
  50. GuiView::Desktop2::~Desktop2() {GuiEdit.removed(this);}
  51. GuiView::Desktop2::Desktop2() {create();}
  52. GuiView::GuiImage2::~GuiImage2() {GuiEdit.removed(this);}
  53. GuiView::GuiImage2::GuiImage2() {create();}
  54. GuiObj* GuiView::GuiImage2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  55. GuiView::List2::~List2() {GuiEdit.removed(this);}
  56. GuiView::List2::List2() {create();}
  57. GuiObj* GuiView::List2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::_List::test(gpc, pos, mouse_wheel);}
  58. GuiView::Menu2::~Menu2() {GuiEdit.removed(this);}
  59. GuiView::Menu2::Menu2() {create();}
  60. GuiObj* GuiView::Menu2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Menu::test(gpc, pos, mouse_wheel);}
  61. GuiView::MenuBar2::~MenuBar2() {GuiEdit.removed(this);}
  62. GuiView::MenuBar2::MenuBar2() { }
  63. GuiObj* GuiView::MenuBar2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  64. GuiView::Progress2::~Progress2() {GuiEdit.removed(this);}
  65. GuiView::Progress2::Progress2() {create();}
  66. GuiObj* GuiView::Progress2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  67. GuiView::Region2::~Region2() {GuiEdit.removed(this);}
  68. GuiView::Region2::Region2() {create(); size(Vec2(0.3f));}
  69. GuiObj* GuiView::Region2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Region::test(gpc, pos, mouse_wheel);}
  70. GuiView::SlideBar2::~SlideBar2() {GuiEdit.removed(this);}
  71. GuiView::SlideBar2::SlideBar2() {create(); size(Vec2(0.3f, 0.05f));}
  72. GuiObj* GuiView::SlideBar2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::SlideBar::test(gpc, pos, mouse_wheel);}
  73. GuiView::Slider2::~Slider2() {GuiEdit.removed(this);}
  74. GuiView::Slider2::Slider2() {create();}
  75. GuiObj* GuiView::Slider2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Slider::test(gpc, pos, mouse_wheel);}
  76. GuiView::Tabs2::~Tabs2() {GuiEdit.removed(this);}
  77. GuiView::Tabs2::Tabs2() {cchar8 *t[]={"Tab 0", "Tab 1", "Tab 2"}; create(t, Elms(t)); size(Vec2(0.6f, 0.06f));}
  78. GuiObj* GuiView::Tabs2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Tabs::test(gpc, pos, mouse_wheel);}
  79. GuiView::Text2::~Text2() {GuiEdit.removed(this);}
  80. GuiView::Text2::Text2() {create("Text"); size(Vec2(0.04f));}
  81. GuiObj* GuiView::Text2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::GuiObj::test(gpc, pos, mouse_wheel);}
  82. void GuiView::Text2::draw(C GuiPC &gpc){::EE::Text::draw(gpc); if(gpc.visible && visible() && TextRectColor.a){D.clip(gpc.clip); (rect()+gpc.offset).draw(TextRectColor, false);}}
  83. GuiView::TextBox2::~TextBox2() {GuiEdit.removed(this);}
  84. GuiView::TextBox2::TextBox2() {create();}
  85. GuiObj* GuiView::TextBox2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::TextBox::test(gpc, pos, mouse_wheel);}
  86. void GuiView::TextBox2::update(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::TextBox::update(temp);}
  87. void GuiView::TextBox2::draw(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::TextBox::draw(temp);}
  88. GuiView::TextLine2::~TextLine2() {GuiEdit.removed(this);}
  89. GuiView::TextLine2::TextLine2() {create();}
  90. GuiObj* GuiView::TextLine2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::TextLine::test(gpc, pos, mouse_wheel);}
  91. void GuiView::TextLine2::update(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::TextLine::update(temp);}
  92. void GuiView::TextLine2::draw(C GuiPC &gpc){GuiPC temp=gpc; temp.enabled=false; ::EE::TextLine::draw(temp);}
  93. GuiView::Viewport2::~Viewport2() {GuiEdit.removed(this);}
  94. GuiView::Viewport2::Viewport2() {create();}
  95. GuiObj* GuiView::Viewport2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Viewport::test(gpc, pos, mouse_wheel);}
  96. void GuiView::Viewport2::draw(C GuiPC &gpc){draw_func=ViewportDraw; ::EE::Viewport::draw(gpc);}
  97. GuiView::Window2::~Window2() {GuiEdit.removed(this);}
  98. GuiView::Window2::Window2() {create(); size(Vec2(0.3f));}
  99. GuiObj* GuiView::Window2::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return (IgnoreSelected && GuiEdit.sel.has(this)) ? null : ::EE::Window::test(gpc, pos, mouse_wheel);}
  100. void GuiView::Window2::update(C GuiPC &gpc){uint flag=T.flag; FlagDisable(T.flag, WIN_MOVABLE|WIN_RESIZABLE); ::EE::Window::update(gpc); T.flag=flag;}
  101. Memx<GuiObj>* GuiView::Objects::container(GUI_OBJ_TYPE type)
  102. {
  103. switch(type)
  104. {
  105. default : return null;
  106. case GO_BUTTON : return &SCAST(Memx<GuiObj>, button );
  107. case GO_CHECKBOX: return &SCAST(Memx<GuiObj>, checkbox);
  108. case GO_COMBOBOX: return &SCAST(Memx<GuiObj>, combobox);
  109. case GO_CUSTOM : return &SCAST(Memx<GuiObj>, custom );
  110. case GO_DESKTOP : return &SCAST(Memx<GuiObj>, desktop );
  111. case GO_IMAGE : return &SCAST(Memx<GuiObj>, image );
  112. case GO_LIST : return &SCAST(Memx<GuiObj>, list );
  113. case GO_MENU : return &SCAST(Memx<GuiObj>, menu );
  114. case GO_MENU_BAR: return &SCAST(Memx<GuiObj>, menubar );
  115. case GO_PROGRESS: return &SCAST(Memx<GuiObj>, progress);
  116. case GO_REGION : return &SCAST(Memx<GuiObj>, region );
  117. case GO_SLIDEBAR: return &SCAST(Memx<GuiObj>, slidebar);
  118. case GO_SLIDER : return &SCAST(Memx<GuiObj>, slider );
  119. case GO_TABS : return &SCAST(Memx<GuiObj>, tabs );
  120. case GO_TEXT : return &SCAST(Memx<GuiObj>, text );
  121. case GO_TEXTBOX : return &SCAST(Memx<GuiObj>, textbox );
  122. case GO_TEXTLINE: return &SCAST(Memx<GuiObj>, textline);
  123. case GO_VIEWPORT: return &SCAST(Memx<GuiObj>, viewport);
  124. case GO_WINDOW : return &SCAST(Memx<GuiObj>, window );
  125. }
  126. }
  127. bool GuiView::Objects::containsMain(GuiObj *go) {return contains(MainObject(go));}
  128. bool GuiView::Objects::contains(GuiObj *go) // if 'go' is stored in this objects
  129. {
  130. if(go)REP(GO_NUM)if(Memx<GuiObj> *container=T.container(GUI_OBJ_TYPE(i)))if(container->contains(go))return true;
  131. return false;
  132. }
  133. void GuiView::Objects::del()
  134. {
  135. REP(GO_NUM)if(Memx<GuiObj> *memx=container(GUI_OBJ_TYPE(i)))memx->del();
  136. }
  137. void GuiView::Objects::create(C GuiObjs &objs) // create from
  138. {
  139. del();
  140. objs.copyTo(button, checkbox, combobox, custom, desktop, image, list, menu, menubar, progress, region, slidebar, slider, tabs, text, textbox, textline, viewport, window, parent);
  141. }
  142. void GuiView::Objects::copyTo(GuiObjs &objs)C
  143. {
  144. objs.create(button, checkbox, combobox, custom, desktop, image, list, menu, menubar, progress, region, slidebar, slider, tabs, text, textbox, textline, viewport, window);
  145. }
  146. GuiObj* GuiView::Objects::New(GUI_OBJ_TYPE type)
  147. {
  148. if(Memx<GuiObj> *container=T.container(type))return &container->New();
  149. return null;
  150. }
  151. void GuiView::Objects::remove(GuiObj *go)
  152. {
  153. // delete all children first, so all objects are removed from containers
  154. if(go && contains(go))
  155. {
  156. REP(go->childNum())remove(go->child(i)); // go from end
  157. if(Memx<GuiObj> *container=T.container(go->type()))container->removeData(go);
  158. }
  159. }
  160. bool GuiView::Objects::save(File &f, cchar *path)C
  161. {
  162. GuiObjs objs; copyTo(objs); return objs.save(f, path);
  163. }
  164. bool GuiView::Objects::load(File &f, cchar *path)
  165. {
  166. GuiObjs objs; if(objs.load(f, path)){create(objs); return true;}
  167. del(); return false;
  168. }
  169. bool GuiView::Objects::save(C Str &name)C
  170. {
  171. File f; if(save(f.writeMem(), GetPath(name))){f.pos(0); return SafeOverwrite(f, name);}
  172. return false;
  173. }
  174. bool GuiView::Objects::load(C Str &name)
  175. {
  176. File f; if(f.readTry(name))return load(f, GetPath(name));
  177. del(); return false;
  178. }
  179. void GuiView::PosX( GuiObj &go, C Str &t) { go.pos(Vec2(TextFlt(t), go.pos().y));}
  180. Str GuiView::PosX(C GuiObj &go ) {return go.pos().x;}
  181. void GuiView::PosY( GuiObj &go, C Str &t) { go.pos(Vec2(go.pos().x, TextFlt(t)));}
  182. Str GuiView::PosY(C GuiObj &go ) {return go.pos().y;}
  183. void GuiView::SizeX( GuiObj &go, C Str &t) { go.size(Vec2(TextFlt(t), go.size().y));}
  184. Str GuiView::SizeX(C GuiObj &go ) {return go.size().x;}
  185. void GuiView::SizeY( GuiObj &go, C Str &t) { go.size(Vec2(go.size().x, TextFlt(t)));}
  186. Str GuiView::SizeY(C GuiObj &go ) {return go.size().y;}
  187. void GuiView::Desc( GuiObj &go, C Str &t) { go.desc(Replace(t, "\\n", "\n" ));}
  188. Str GuiView::Desc(C GuiObj &go ) {return Replace(go.desc(), "\n" , "\\n") ;}
  189. void GuiView::CheckBoxOn( CheckBox &checkbox, C Str &t) { checkbox.set(TextBool(t));}
  190. Str GuiView::CheckBoxOn(C CheckBox &checkbox ) {return checkbox();}
  191. void GuiView::ProgressValue( Progress &progress, C Str &t) { progress.set(TextFlt(t));}
  192. Str GuiView::ProgressValue(C Progress &progress ) {return progress();}
  193. void GuiView::RegionSbc( Region &region , C Str &t) { region.slidebar[0].sbc=region.slidebar[1].sbc=SLIDEBAR_BACK_CLICK_MODE(TextInt(t));}
  194. Str GuiView::RegionSbc(C Region &region ) {return region.slidebar[0].sbc;}
  195. void GuiView::SlideBarLength( SlideBar &slidebar, C Str &t) { slidebar.setLengths(TextFlt(t), slidebar.lengthTotal());}
  196. Str GuiView::SlideBarLength(C SlideBar &slidebar ) {return slidebar.length();}
  197. void GuiView::SlideBarLengthTotal( SlideBar &slidebar, C Str &t) { slidebar.setLengths(slidebar.length(), TextFlt(t));}
  198. Str GuiView::SlideBarLengthTotal(C SlideBar &slidebar ) {return slidebar.lengthTotal();}
  199. void GuiView::SlideBarFrac( SlideBar &slidebar, C Str &t) { slidebar.set(TextFlt(t));}
  200. Str GuiView::SlideBarFrac(C SlideBar &slidebar ) {return slidebar();}
  201. void GuiView::SliderValue( Slider &slider, C Str &t) { slider.set(TextFlt(t));}
  202. Str GuiView::SliderValue(C Slider &slider ) {return slider();}
  203. Str GuiView::TabsValid(C Tabs &tabs ) {return tabs.valid();}
  204. void GuiView::TabsValid( Tabs &tabs, C Str &t) { tabs.valid(TextBool(t));}
  205. Str GuiView::TabsLayout(C Tabs &tabs ) {return tabs.layout();}
  206. void GuiView::TabsLayout( Tabs &tabs, C Str &t) { tabs.layout((TABS_LAYOUT)TextInt(t));}
  207. Str GuiView::TabsSpace(C Tabs &tabs ) {return tabs.space();}
  208. void GuiView::TabsSpace( Tabs &tabs, C Str &t) { tabs.rect(tabs.rect(), TextFlt(t), tabs.autoSize());}
  209. Str GuiView::TabsAutoSize(C Tabs &tabs ) {return tabs.autoSize();}
  210. void GuiView::TabsAutoSize( Tabs &tabs, C Str &t) { tabs.rect(tabs.rect(), tabs.space(), TextBool(t));}
  211. void GuiView::TextCodeFunc( Text &text, C Str &t) { text.code(Replace(t, "\\n", "\n" ));}
  212. Str GuiView::TextCodeFunc(C Text &text ) {return Replace(text.code(), "\n" , "\\n") ;}
  213. Str GuiView::TextLineText(C TextLine &textline ) {return textline();}
  214. void GuiView::TextLineText( TextLine &textline, C Str &t) { textline.set(t);}
  215. Str GuiView::TextLinePassword(C TextLine &textline ) {return textline.password();}
  216. void GuiView::TextLinePassword( TextLine &textline, C Str &t) { textline.password(TextBool(t));}
  217. Str GuiView::TextLineMaxLength(C TextLine &textline ) {return textline.maxLength();}
  218. void GuiView::TextLineMaxLength( TextLine &textline, C Str &t) { textline.maxLength(TextInt(t));}
  219. Str GuiView::TextBoxText(C TextBox &textbox ) {return textbox();}
  220. void GuiView::TextBoxText( TextBox &textbox, C Str &t) { textbox.set(t);}
  221. Str GuiView::TextBoxMaxLength(C TextBox &textbox ) {return textbox.maxLength();}
  222. void GuiView::TextBoxMaxLength( TextBox &textbox, C Str &t) { textbox.maxLength(TextInt(t));}
  223. void GuiView::WindowLevel( Window &window, C Str &t) { window.level(TextInt(t));}
  224. Str GuiView::WindowLevel(C Window &window ) {return window.level();}
  225. void GuiView::WindowMovable( Window &window, C Str &t) { FlagSet (window.flag, WIN_MOVABLE, TextBool(t));}
  226. Str GuiView::WindowMovable(C Window &window ) {return FlagTest(window.flag, WIN_MOVABLE);}
  227. void GuiView::WindowResizable( Window &window, C Str &t) { FlagSet (window.flag, WIN_RESIZABLE, TextBool(t));}
  228. Str GuiView::WindowResizable(C Window &window ) {return FlagTest(window.flag, WIN_RESIZABLE);}
  229. void GuiView::WindowBarVisible( Window &window, C Str &t) { window.barVisible(TextBool(t));}
  230. Str GuiView::WindowBarVisible(C Window &window ) {return window.barVisible();}
  231. void GuiView::ButtonImage(Button &button , C Str &t) {button .image=Proj.gamePath(Proj.findElmImageID(t));}
  232. void GuiView::ButtonSkin(Button &button , C Str &t) {button .skin =Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN));}
  233. void GuiView::CheckBoxSkin(CheckBox &checkbox, C Str &t) {checkbox.skin =Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN));}
  234. void GuiView::ComboBoxSkin(ComboBox &combobox, C Str &t) {combobox.skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  235. void GuiView::ImageImage(GuiImage &image , C Str &t) {image .image=Proj.gamePath(Proj.findElmImageID(t));}
  236. void GuiView::ProgressSkin(Progress &progress, C Str &t) {progress.skin =Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN));}
  237. void GuiView::SlideBarSkin(SlideBar &slidebar, C Str &t) {slidebar.skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  238. void GuiView::SliderSkin(Slider &slider , C Str &t) {slider .skin =Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN));}
  239. void GuiView::RegionSkin(Region &region , C Str &t) {region .skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  240. void GuiView::TabsSkin(Tabs &tabs , C Str &t) {tabs .skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  241. void GuiView::TextSkin(Text &text , C Str &t) {text .skin =Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN));}
  242. void GuiView::TextLineSkin(TextLine &textline, C Str &t) {textline.skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  243. void GuiView::TextBoxSkin(TextBox &textbox , C Str &t) {textbox .skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  244. void GuiView::WindowSkin(Window &window , C Str &t) {window .skin (Proj.gamePath(Proj.findElmID (t, ELM_GUI_SKIN)));}
  245. void GuiView::TextTextStyle(Text &text , C Str &t) {text .text_style=Proj.gamePath(Proj.findElmID(t, ELM_TEXT_STYLE));}
  246. Str GuiView::ButtonImage(C Button &button ) {return Proj.elmFullName(button .image .id());}
  247. Str GuiView::ButtonSkin(C Button &button ) {return Proj.elmFullName(button .skin .id());}
  248. Str GuiView::CheckBoxSkin(C CheckBox &checkbox) {return Proj.elmFullName(checkbox.skin .id());}
  249. Str GuiView::ComboBoxSkin(C ComboBox &combobox) {return Proj.elmFullName(combobox.skin().id());}
  250. Str GuiView::ImageImage(C GuiImage &image ) {return Proj.elmFullName(image .image .id());}
  251. Str GuiView::ProgressSkin(C Progress &progress) {return Proj.elmFullName(progress.skin .id());}
  252. Str GuiView::SlideBarSkin(C SlideBar &slidebar) {return Proj.elmFullName(slidebar.skin().id());}
  253. Str GuiView::SliderSkin(C Slider &slider ) {return Proj.elmFullName(slider .skin .id());}
  254. Str GuiView::RegionSkin(C Region &region ) {return Proj.elmFullName(region .skin().id());}
  255. Str GuiView::TabsSkin(C Tabs &tabs ) {return Proj.elmFullName(tabs .skin().id());}
  256. Str GuiView::TextSkin(C Text &text ) {return Proj.elmFullName(text .skin .id());}
  257. Str GuiView::TextLineSkin(C TextLine &textline) {return Proj.elmFullName(textline.skin().id());}
  258. Str GuiView::TextBoxSkin(C TextBox &textbox ) {return Proj.elmFullName(textbox .skin().id());}
  259. Str GuiView::WindowSkin(C Window &window ) {return Proj.elmFullName(window .skin().id());}
  260. Str GuiView::TextTextStyle(C Text &text ) {return Proj.elmFullName(text .text_style.id());}
  261. void GuiView::ObjEdit::PreChanged(C Property &prop) {Skin=Gui.skin; if(GuiSkinPtr app_skin=Proj.appGuiSkin())Gui.skin=app_skin; GuiEdit.undo.set(&prop);}
  262. void GuiView::ObjEdit::Changed(C Property &prop) {GuiEdit.setChanged(); Gui.skin=Skin; Skin=null;}
  263. Rect GuiView::ObjEdit::create(GUI_OBJ_TYPE type, int level)
  264. {
  265. if(props.elms())
  266. {
  267. props.NewAt(0).create("Pos X" , MemberDesc(DATA_REAL).setFunc( PosX, PosX)).mouseEditSpeed(0.1f);
  268. props.NewAt(1).create("Pos Y" , MemberDesc(DATA_REAL).setFunc( PosY, PosY)).mouseEditSpeed(0.1f);
  269. props.NewAt(2).create("Width" , MemberDesc(DATA_REAL).setFunc(SizeX, SizeX)).min(MinSize).mouseEditSpeed(0.1f);
  270. props.NewAt(3).create("Height", MemberDesc(DATA_REAL).setFunc(SizeY, SizeY)).min(MinSize).mouseEditSpeed(0.1f);
  271. Rect rect=::PropWin::create(S+GuiObjTypeName(type)+" Properties", Vec2(0.02f, -0.02f), 0.036f, 0.043f, PropElmNameWidth); changed(Changed, PreChanged).level(level);
  272. Mode.tab(MODE_GUI)+=T; // move to gui tab so it will be hidden in other modes
  273. button[2].func(null); // disable auto-closing
  274. return rect;
  275. }
  276. return Rect(Vec2(0));
  277. }
  278. void GuiView::ObjEdit::draw(C GuiPC &gpc)
  279. {
  280. if(gpc.visible && visible())
  281. {
  282. GuiSkinPtr temp=Gui.skin; Gui.skin=Mode.Gui_skin; // restore Editor's Gui.skin before drawing this Window
  283. ::EE::Window::draw(gpc);
  284. Gui.skin=temp;
  285. }
  286. }
  287. GuiObj* GuiView::MainObject(GuiObj *go)
  288. {
  289. if(go)
  290. {
  291. if(go->parent())switch(go->type())
  292. {
  293. case GO_BUTTON: if(go->parent()->type()==GO_SLIDEBAR)go=go->parent(); break; // one of slidebar buttons
  294. case GO_TAB : go=go->parent(); break;
  295. }
  296. if(go->parent() && go->parent()->type()==GO_REGION)
  297. {
  298. Region &region=go->parent()->asRegion();
  299. if(go==&region.slidebar[0]
  300. || go==&region.slidebar[1]
  301. || go==&region.view )go=&region;
  302. }
  303. }
  304. return go;
  305. }
  306. GuiObj* GuiView::MainParent(GuiObj *parent, bool allow_tabs)
  307. {
  308. if(!allow_tabs && parent && parent->type()==GO_TAB)if(GuiObj *tabs=parent->parent())if(tabs->type()==GO_TABS)return MainParent(tabs->parent(), allow_tabs);
  309. return (parent==&Mode.tab(MODE_GUI)) ? Gui.desktop() : parent;
  310. }
  311. GuiObj* GuiView::FirstContainer(GuiObj *go, bool allow_tabs)
  312. {
  313. for(; go; go=go->parent())switch(go->type())
  314. {
  315. case GO_MENU :
  316. case GO_DESKTOP:
  317. case GO_REGION :
  318. case GO_WINDOW : return go;
  319. case GO_TAB : return allow_tabs ? go : FirstContainer(go->parent(), allow_tabs); break;
  320. }
  321. return null;
  322. }
  323. void GuiView::Panel::AlignSel(Panel &panel) {GuiEdit.alignSel ();}
  324. void GuiView::Panel::MoveUp(Panel &panel) {GuiEdit.moveUpSel ();}
  325. void GuiView::Panel::MoveDown(Panel &panel) {GuiEdit.moveDownSel();}
  326. void GuiView::Panel::Aspect(Panel &panel) {GuiEdit.resetAspect();}
  327. void GuiView::Panel::Undo(Panel &panel) {GuiEdit.undo.undo ();}
  328. void GuiView::Panel::Redo(Panel &panel) {GuiEdit.undo.redo ();}
  329. void GuiView::Panel::Locate(Panel &panel) {Proj.elmLocate(GuiEdit.elm_id);}
  330. GUI_OBJ_TYPE GuiView::Panel::objType()C
  331. {
  332. if(InRange(obj_type(), obj_new))return obj_new[obj_type()];
  333. return GO_NONE;
  334. }
  335. void GuiView::Panel::align(Vec2 &pos, bool force)
  336. {
  337. if((grid_align() || force) && grid_size>EPS)pos.set(AlignRound(pos.x, grid_size), AlignRound(pos.y, grid_size));
  338. }
  339. void GuiView::Panel::alignTrunc(Vec2 &pos)
  340. {
  341. if(grid_align() && grid_size>EPS)pos.set(AlignTrunc(pos.x, grid_size), AlignTrunc(pos.y, grid_size));
  342. }
  343. ::GuiView::Panel& GuiView::Panel::create()
  344. {
  345. ::EE::Window::create(Rect_RU(D.w(), D.h(), 0.31f, 1.13f)).level(/*LicenseCheck.level()*/256-2).barVisible(false);
  346. flt h=0.05f, b=0.03f, p=0.01f;
  347. T+=draw_proportions.create(Rect_LU(b, -b, h, h)).focusable(false).desc("Draw screen proportions:\nPurple : X Range -1 .. 1 , Aspect Ratio 1:1\nBlue : X Range -1.25 .. 1.25, Aspect Ratio 5:4 (1280x1024)\nGreen : X Range -1.33 .. 1.33, Aspect Ratio 4:3 (1024x768)\nRed : X Range -1.60 .. 1.60, Aspect Ratio 16:10 (1680x1050)\nCyan : X Range -1.77 .. 1.77, Aspect Ratio 16:9 (1920x1080)"); draw_proportions.mode=BUTTON_TOGGLE; draw_proportions.image="Gui/Misc/grid_small.img";
  348. T+=grid_align.create(Rect_LU(draw_proportions.rect().ru(), h, h)).focusable(false).desc("Align objects to grid"); grid_align.mode=BUTTON_TOGGLE; grid_align.set(true); grid_align.image="Gui/Misc/grid.img";
  349. T+=op.create(Rect_LU(draw_proportions.rect().ld()+Vec2(0, -p), h*5, h*2), 0, (cchar**)null, OP_NUM); REPA(op)op.tab(i).size(Vec2(h, h)).pos(op.rect().lu());
  350. op.tab(OP_NEW ).setText ("+1" ).move(Vec2(h*0, 0)).desc(S+"Create new object\nSelect with LeftClick\nInsert with RightClick\n\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+Insert");
  351. op.tab(OP_COPY ).setText ("Copy" ).move(Vec2(h*0, -h)).desc(S+"Copy selected objects\nSelect with LeftClick\nCopy with RightClick\n\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+D").resize(Vec2(h, 0));
  352. op.tab(OP_DEL ).setText ("-1" ).move(Vec2(h*1, 0)).desc(S+"Delete object\nDelete with RightClick\n\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+Del");
  353. op.tab(OP_MOVE ).setImage("Gui/Misc/move.img" ).move(Vec2(h*2, 0)).desc(S+"Move object\nSelect with LeftClick\nMove with RightClick");
  354. op.tab(OP_SEPARATE).setImage("Gui/Misc/separate.img" ).move(Vec2(h*2, -h)).desc(S+"Separate group of objects\nSelect with LeftClick\nSeparate with RightClick\nShortcut: Shift + Right Mouse Button");
  355. op.tab(OP_SIZE ).setImage("Gui/Misc/scale.img" ).move(Vec2(h*3, 0)).desc(S+"Resize object\nSelect with LeftClick\nResize with RightClick\nShortcut: "+Kb.ctrlCmdName()+" + Right Mouse Button");
  356. op.tab(OP_SCALE ).setImage("Gui/Misc/scale_all.img").move(Vec2(h*3, -h)).desc(S+"Move and resize a group of objects\nSelect with LeftClick\nMove+Resize with RightClick\nShortcut: "+Kb.ctrlCmdName()+" + Shift + Right Mouse Button");
  357. op.tab(OP_PARENT ).setImage("Gui/Misc/target.img" ).move(Vec2(h*4, 0)).desc(S+"Move object and change its parent to object under mouse cursor\nSelect with LeftClick\nMove with RightClick\nShortcut: Alt + Right Mouse Button\n\nIn this mode you don't need to actually move the object to change its parent,\nyou can just select an object, move the mouse over to desired parent, and RightClick.");
  358. T+=undo .create(Rect_LU(b, op.rect().min.y-p, h, h)).func(Undo , T).focusable(false).desc(S+"Undo\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+Z" ); undo .image="Gui/Misc/undo.img";
  359. T+=redo .create(Rect_LU(undo .rect().ru(), h, h)).func(Redo , T).focusable(false).desc(S+"Redo\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+Y" ); redo .image="Gui/Misc/redo.img";
  360. T+=locate .create(Rect_LU(redo.rect().ru(), 0.15f, 0.05f), "Locate").func(Locate, T).focusable(false).desc("Locate this element in the Project");
  361. T+=align_sel.create(Rect_LU(undo .rect().ld(), h, h)).func(AlignSel, T).focusable(false).desc(S+"Align selected objects to grid\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+G" ); align_sel.text ="G";
  362. T+=aspect .create(Rect_LU(align_sel.rect().ru(), h, h)).func(Aspect , T).focusable(false).desc(S+"Reset aspect ratio of selected objects\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+R"); aspect .text ="R";
  363. T+=move_up .create(Rect_LU(aspect .rect().ru(), h, h)).func(MoveUp , T).focusable(false).desc(S+"Move selected objects up\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+PageUp" ); move_up .image="Gui/arrow_up.img";
  364. T+=move_down.create(Rect_LU(move_up .rect().ru(), h, h)).func(MoveDown, T).focusable(false).desc(S+"Move selected objects down\nKeyboard Shortcut: "+Kb.ctrlCmdName()+"+PageDown" ); move_down.image="Gui/arrow_down.img";
  365. T+=obj_type .create(Rect_LU(b, move_down.rect().min.y-p, 0.25f, 0.053f*obj_new_elms), 0, (cchar**)null, obj_new_elms).valid(true).set(0);
  366. FREPA(obj_type)obj_type.tab(i).text(GuiObjTypeName(obj_new[i]));
  367. props.New().create(S, MEMBER(Panel, grid_size)).range(0.001f, 0.1f).mouseEditSpeed(0.01f).desc("Grid size");
  368. AddProperties(props, T, grid_align.rect().ru(), h, 0.14f); REPAO(props).autoData(this);
  369. return T;
  370. }
  371. void GuiView::Change::create(ptr user)
  372. {
  373. GuiEdit.objs.copyTo(objs);
  374. GuiEdit.undoVis();
  375. }
  376. void GuiView::Change::apply(ptr user)
  377. {
  378. if(GuiEdit.elm)
  379. {
  380. GuiEdit.objs.create(objs);
  381. GuiEdit.setChanged();
  382. GuiEdit.undoVis();
  383. }
  384. }
  385. void GuiView::undoVis() {SetUndo(undo, panel.undo, panel.redo);}
  386. bool GuiView::selected()C {return Mode()==MODE_GUI;}
  387. void GuiView::selectedChanged()
  388. {
  389. panel.visible(selected()).enabled(selected());
  390. }
  391. void GuiView::flush()
  392. {
  393. if(elm && changed)
  394. {
  395. if(ElmGui *data=elm->guiData())data->newVer(); // modify just before saving/sending in case we've received data from server after edit
  396. objs.save(Proj.gamePath(*elm));
  397. Server.setElmLong(elm->id);
  398. Preview.elmChanged(elm->id);
  399. }
  400. changed=false;
  401. }
  402. void GuiView::set(Elm *elm)
  403. {
  404. if(elm && elm->type!=ELM_GUI)elm=null;
  405. if(T.elm!=elm)
  406. {
  407. flush();
  408. undo.del(); undoVis();
  409. T.elm =elm;
  410. T.elm_id=(elm ? elm->id : UIDZero);
  411. if(elm)
  412. {
  413. GuiSkinPtr temp=Gui.skin; if(GuiSkinPtr skin=Proj.appGuiSkin())Gui.skin=skin; // set app skin before loading objects because that may affect some of their properties (such as slidebar side button visibility)
  414. objs.load(Proj.gamePath(*elm));
  415. Gui.skin=temp;
  416. }else objs.del();
  417. Proj.refresh(false, false);
  418. Mode.tabAvailable(MODE_GUI, elm!=null);
  419. }
  420. }
  421. void GuiView::activate(Elm *elm) {set(elm); if(T.elm){Mode.set(MODE_GUI); HideBig();}}
  422. void GuiView::toggle(Elm *elm)
  423. {
  424. if(elm==T.elm && selected())elm=null;
  425. activate(elm);
  426. }
  427. void GuiView::erasing(C UID &elm_id) {if(elm && elm->id==elm_id)set(null);}
  428. void GuiView::DelTab(ptr user)
  429. {
  430. if(Tabs *tabs=CAST(Tabs, GuiEdit.cur()))
  431. {
  432. int i=(uintptr)user;
  433. if(InRange(i, *tabs))
  434. {
  435. GuiEdit.undo.set("delTab", true);
  436. Tab &tab=tabs->tab(i);
  437. if(GuiObj *parent=tabs->parent())REP(tab.childNum())*parent+=*tab.child(i); // move tab children to tabs parent
  438. tabs->remove(i);
  439. if(tabs->tabs())GuiEdit.createPropsTabs(tabs).toGui();else GuiEdit.objs.remove(tabs); // if there are no tabs left then remove the object
  440. GuiEdit.setChanged();
  441. }
  442. }
  443. }
  444. void GuiView::NewTab(GuiView &gv)
  445. {
  446. if(Tabs *tabs=CAST(Tabs, gv.cur()))
  447. {
  448. gv.undo.set("newTab", true);
  449. tabs->New(S);
  450. gv.createPropsTabs(tabs).toGui().setChanged();
  451. }
  452. }
  453. GuiView& GuiView::createPropsTabs(Tabs *tabs)
  454. {
  455. ObjEdit &oe=obj_edit[GO_TABS];
  456. int t =(tabs ? tabs->tabs() : 0);
  457. static cchar8 *tabs_layout[]=
  458. {
  459. "AUTO" , // 0
  460. "HORIZONTAL", // 1
  461. "VERTICAL" , // 2
  462. }; ASSERT(TABS_AUTO==0 && TABS_HORIZONTAL==1 && TABS_VERTICAL==2 && TABS_NUM==3);
  463. oe.props.clear();
  464. oe.add("Name" , MemberDesc(MEMBER(Tabs2, name)));
  465. oe.add("Desc" , MemberDesc(DATA_STR ).setFunc(Desc , Desc ));
  466. oe.add("Valid" , MemberDesc(DATA_BOOL).setFunc(TabsValid , TabsValid )).desc("If at least one tab must be selected");
  467. oe.add("Layout" , MemberDesc( ).setFunc(TabsLayout , TabsLayout )).setEnum(tabs_layout, Elms(tabs_layout));
  468. oe.add("Space" , MemberDesc(DATA_REAL).setFunc(TabsSpace , TabsSpace )).min(0).mouseEditSpeed(0.2f).desc("Space between tabs");
  469. oe.add("Auto Size" , MemberDesc(DATA_BOOL).setFunc(TabsAutoSize , TabsAutoSize )).desc("If set tab sizes according to their text length");
  470. oe.add("Skin Override", MemberDesc(DATA_STR ).setFunc(TabsSkin , TabsSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  471. if(t>= 1){Button &b=oe.add("Tab 1" , MemberDesc(DATA_STR ).setFunc(TabsTabText<0> , TabsTabText<0> )).button; b.create().func(DelTab, (Ptr) 0).desc("Remove this tab"); b.image="Gui/close.img";}
  472. if(t>= 2){Button &b=oe.add("Tab 2" , MemberDesc(DATA_STR ).setFunc(TabsTabText<1> , TabsTabText<1> )).button; b.create().func(DelTab, (Ptr) 1).desc("Remove this tab"); b.image="Gui/close.img";}
  473. if(t>= 3){Button &b=oe.add("Tab 3" , MemberDesc(DATA_STR ).setFunc(TabsTabText<2> , TabsTabText<2> )).button; b.create().func(DelTab, (Ptr) 2).desc("Remove this tab"); b.image="Gui/close.img";}
  474. if(t>= 4){Button &b=oe.add("Tab 4" , MemberDesc(DATA_STR ).setFunc(TabsTabText<3> , TabsTabText<3> )).button; b.create().func(DelTab, (Ptr) 3).desc("Remove this tab"); b.image="Gui/close.img";}
  475. if(t>= 5){Button &b=oe.add("Tab 5" , MemberDesc(DATA_STR ).setFunc(TabsTabText<4> , TabsTabText<4> )).button; b.create().func(DelTab, (Ptr) 4).desc("Remove this tab"); b.image="Gui/close.img";}
  476. if(t>= 6){Button &b=oe.add("Tab 6" , MemberDesc(DATA_STR ).setFunc(TabsTabText<5> , TabsTabText<5> )).button; b.create().func(DelTab, (Ptr) 5).desc("Remove this tab"); b.image="Gui/close.img";}
  477. if(t>= 7){Button &b=oe.add("Tab 7" , MemberDesc(DATA_STR ).setFunc(TabsTabText<6> , TabsTabText<6> )).button; b.create().func(DelTab, (Ptr) 6).desc("Remove this tab"); b.image="Gui/close.img";}
  478. if(t>= 8){Button &b=oe.add("Tab 8" , MemberDesc(DATA_STR ).setFunc(TabsTabText<7> , TabsTabText<7> )).button; b.create().func(DelTab, (Ptr) 7).desc("Remove this tab"); b.image="Gui/close.img";}
  479. if(t>= 9){Button &b=oe.add("Tab 9" , MemberDesc(DATA_STR ).setFunc(TabsTabText<8> , TabsTabText<8> )).button; b.create().func(DelTab, (Ptr) 8).desc("Remove this tab"); b.image="Gui/close.img";}
  480. if(t>=10){Button &b=oe.add("Tab 10" , MemberDesc(DATA_STR ).setFunc(TabsTabText<9> , TabsTabText<9> )).button; b.create().func(DelTab, (Ptr) 9).desc("Remove this tab"); b.image="Gui/close.img";}
  481. if(t>=11){Button &b=oe.add("Tab 11" , MemberDesc(DATA_STR ).setFunc(TabsTabText<10>, TabsTabText<10>)).button; b.create().func(DelTab, (Ptr)10).desc("Remove this tab"); b.image="Gui/close.img";}
  482. if(t>=12){Button &b=oe.add("Tab 12" , MemberDesc(DATA_STR ).setFunc(TabsTabText<11>, TabsTabText<11>)).button; b.create().func(DelTab, (Ptr)11).desc("Remove this tab"); b.image="Gui/close.img";}
  483. if(t>=13){Button &b=oe.add("Tab 13" , MemberDesc(DATA_STR ).setFunc(TabsTabText<12>, TabsTabText<12>)).button; b.create().func(DelTab, (Ptr)11).desc("Remove this tab"); b.image="Gui/close.img";}
  484. if(t>=14){Button &b=oe.add("Tab 14" , MemberDesc(DATA_STR ).setFunc(TabsTabText<13>, TabsTabText<13>)).button; b.create().func(DelTab, (Ptr)11).desc("Remove this tab"); b.image="Gui/close.img";}
  485. if(t>=15){Button &b=oe.add("Tab 15" , MemberDesc(DATA_STR ).setFunc(TabsTabText<14>, TabsTabText<14>)).button; b.create().func(DelTab, (Ptr)11).desc("Remove this tab"); b.image="Gui/close.img";}
  486. if(t>=16){Button &b=oe.add("Tab 16" , MemberDesc(DATA_STR ).setFunc(TabsTabText<15>, TabsTabText<15>)).button; b.create().func(DelTab, (Ptr)11).desc("Remove this tab"); b.image="Gui/close.img";}
  487. bool visible=(oe.is() && oe.visible());
  488. Rect r=oe.create(GO_TABS, panel.level());
  489. oe+=new_tab.create(Rect_U(oe.clientWidth()/2, -r.h()-0.03f, 0.2f, 0.05f), "New Tab").func(NewTab, T);
  490. oe.rect(Rect_RD(oe.rect().rd(), oe.rect().w(), oe.rect().h()+0.06f));
  491. oe.autoData(tabs).visible(visible); // keep visibility
  492. return T;
  493. }
  494. void GuiView::createProps()
  495. {
  496. obj_edit[GO_BUTTON].add("Name" , MemberDesc(MEMBER(Button2, name )));
  497. obj_edit[GO_BUTTON].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc) );
  498. obj_edit[GO_BUTTON].add("Text" , MemberDesc(MEMBER(Button2, text )));
  499. obj_edit[GO_BUTTON].add("Text Align" , MemberDesc(MEMBER(Button2, text_align ))).range(-1, 1);
  500. obj_edit[GO_BUTTON].add("Text Size" , MemberDesc(MEMBER(Button2, text_size ))).range(0.01f, 2.0f);
  501. obj_edit[GO_BUTTON].add("Image" , MemberDesc(MEMBER(Button2, image )).setFunc(ButtonImage, ButtonImage)).elmType(ELM_IMAGE);
  502. obj_edit[GO_BUTTON].add("Image Color" , MemberDesc(MEMBER(Button2, image_color))).setColor();
  503. obj_edit[GO_BUTTON].add("Skin Override", MemberDesc(DATA_STR).setFunc(ButtonSkin, ButtonSkin)).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  504. obj_edit[GO_CHECKBOX].add("Name" , MemberDesc(MEMBER(CheckBox2, name)));
  505. obj_edit[GO_CHECKBOX].add("Desc" , MemberDesc(DATA_STR ).setFunc(Desc, Desc));
  506. obj_edit[GO_CHECKBOX].add("On" , MemberDesc(DATA_BOOL).setFunc(CheckBoxOn, CheckBoxOn));
  507. obj_edit[GO_CHECKBOX].add("Skin Override", MemberDesc(DATA_STR ).setFunc(CheckBoxSkin, CheckBoxSkin)).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  508. obj_edit[GO_COMBOBOX].add("Name" , MemberDesc(MEMBER(ComboBox2, name)));
  509. obj_edit[GO_COMBOBOX].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  510. obj_edit[GO_COMBOBOX].add("Skin Override", MemberDesc(DATA_STR).setFunc(ComboBoxSkin, ComboBoxSkin)).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  511. obj_edit[GO_CUSTOM].add("Name", MemberDesc(MEMBER(GuiCustom2, name)));
  512. obj_edit[GO_CUSTOM].add("Desc", MemberDesc(DATA_STR).setFunc(Desc, Desc));
  513. obj_edit[GO_IMAGE].add("Name" , MemberDesc(MEMBER(GuiImage2, name )));
  514. obj_edit[GO_IMAGE].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  515. obj_edit[GO_IMAGE].add("Fit" , MemberDesc(MEMBER(GuiImage2, fit )));
  516. obj_edit[GO_IMAGE].add("Rect Color", MemberDesc(MEMBER(GuiImage2, rect_color))).setColor();
  517. obj_edit[GO_IMAGE].add("Color" , MemberDesc(MEMBER(GuiImage2, color ))).setColor();
  518. obj_edit[GO_IMAGE].add("Color Add" , MemberDesc(MEMBER(GuiImage2, color_add ))).setColor();
  519. obj_edit[GO_IMAGE].add("Image" , MemberDesc(MEMBER(GuiImage2, image )).setFunc(ImageImage, ImageImage)).elmType(ELM_IMAGE);
  520. static cchar8 *progress_text[]=
  521. {
  522. "NONE" , // 0
  523. "PERCENT", // 1
  524. "REAL" , // 2
  525. }; ASSERT(PROGRESS_NONE==0 && PROGRESS_PERCENT==1 && PROGRESS_REAL==2);
  526. obj_edit[GO_PROGRESS].add("Name" , MemberDesc(MEMBER(Progress2, name )));
  527. obj_edit[GO_PROGRESS].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  528. obj_edit[GO_PROGRESS].add("Text Mode" , MemberDesc(MEMBER(Progress2, mode ))).setEnum(progress_text, Elms(progress_text));
  529. obj_edit[GO_PROGRESS].add("Progress" , MemberDesc(DATA_REAL).setFunc(ProgressValue, ProgressValue)).range(0, 1).mouseEditSpeed(0.1f);
  530. obj_edit[GO_PROGRESS].add("Skin Override", MemberDesc(DATA_STR ).setFunc(ProgressSkin , ProgressSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  531. static cchar8 *sbc_text[]=
  532. {
  533. "OFF" , // 0
  534. "STEP" , // 1
  535. "SMOOTH" , // 2
  536. "SET_POS", // 3
  537. }; ASSERT(SBC_OFF==0 && SBC_STEP==1 && SBC_SMOOTH==2 && SBC_SET_POS==3);
  538. obj_edit[GO_REGION].add("Name" , MemberDesc(MEMBER(Region2, name)));
  539. obj_edit[GO_REGION].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  540. obj_edit[GO_REGION].add("Back Click" , MemberDesc().setFunc(RegionSbc, RegionSbc)).setEnum(sbc_text, Elms(sbc_text));
  541. obj_edit[GO_REGION].add("Skin Override", MemberDesc(DATA_STR).setFunc(RegionSkin, RegionSkin)).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  542. obj_edit[GO_SLIDEBAR].add("Name" , MemberDesc(MEMBER(SlideBar2, name )));
  543. obj_edit[GO_SLIDEBAR].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  544. obj_edit[GO_SLIDEBAR].add("Back Click" , MemberDesc(MEMBER(SlideBar2, sbc ))).setEnum(sbc_text, Elms(sbc_text));
  545. obj_edit[GO_SLIDEBAR].add("Length" , MemberDesc(DATA_REAL).setFunc(SlideBarLength , SlideBarLength )).min(0);
  546. obj_edit[GO_SLIDEBAR].add("Length Total" , MemberDesc(DATA_REAL).setFunc(SlideBarLengthTotal, SlideBarLengthTotal)).min(0);
  547. obj_edit[GO_SLIDEBAR].add("Fraction" , MemberDesc(DATA_REAL).setFunc(SlideBarFrac , SlideBarFrac )).range(0, 1).mouseEditSpeed(0.1f);
  548. obj_edit[GO_SLIDEBAR].add("Skin Override", MemberDesc(DATA_STR ).setFunc(SlideBarSkin , SlideBarSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  549. obj_edit[GO_SLIDER].add("Name" , MemberDesc(MEMBER(Slider2, name)));
  550. obj_edit[GO_SLIDER].add("Desc" , MemberDesc(DATA_STR ).setFunc(Desc, Desc));
  551. obj_edit[GO_SLIDER].add("Value" , MemberDesc(DATA_REAL).setFunc(SliderValue, SliderValue)).range(0, 1).mouseEditSpeed(0.1f);
  552. obj_edit[GO_SLIDER].add("Skin Override", MemberDesc(DATA_STR ).setFunc(SliderSkin , SliderSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  553. static cchar8 *auto_line[]=
  554. {
  555. "NONE" , // 0
  556. "SPACE" , // 1
  557. "SPACE_SPLIT", // 2
  558. "SPLIT" , // 3
  559. }; ASSERT(AUTO_LINE_NONE==0 && AUTO_LINE_SPACE==1 && AUTO_LINE_SPACE_SPLIT==2 && AUTO_LINE_SPLIT==3 && AUTO_LINE_NUM==4);
  560. obj_edit[GO_TEXT].add("Name", MemberDesc(MEMBER(Text2, name)));
  561. obj_edit[GO_TEXT].add("Desc", MemberDesc(DATA_STR).setFunc(Desc, Desc));
  562. obj_edit[GO_TEXT].add("Code", MemberDesc(DATA_STR).setFunc(TextCodeFunc, TextCodeFunc)).desc(
  563. "1. code format accepts following keywords: in following formats:\n"
  564. " col, color - RGB, RGBA, RRGGBB, RRGGBBAA (hexadecimal format)\n"
  565. " shadow - X, XX (hexadecimal format)\n"
  566. "\n"
  567. "2. codes should be surrounded by '[' ']' signs\n"
  568. "\n"
  569. "3. removing the effect of a code should be handled by '/' sign followed by code name\n"
  570. "\n"
  571. "4. sample codes:\n"
  572. " \"Text without code. [color=F00]Text with code[/color]\" - will force red color on \"Text with code\"\n"
  573. " \"[shadow=0]No Shadow[/shadow] [shadow=F]Full Shadow[/shadow]\" - will force no shadow on \"No Shadow\" and full shadow on \"Full Shadow\"");
  574. obj_edit[GO_TEXT].add("Auto Line", MemberDesc(MEMBER(Text2, auto_line))).setEnum(auto_line, Elms(auto_line)).desc(
  575. "NONE - only manual new lines '\\n' are used\n"
  576. "SPACE - new lines can be calculated on spaces, words are not split\n"
  577. "SPACE_SPLIT - new lines can be calculated on spaces, words can be split if their length exceeds available width\n"
  578. "SPLIT - new lines are not calculated on spaces, words can be split if their length exceeds available width");
  579. obj_edit[GO_TEXT].add("Text Style" , MemberDesc(DATA_STR).setFunc(TextTextStyle, TextTextStyle)).elmType(ELM_TEXT_STYLE);
  580. obj_edit[GO_TEXT].add("Skin Override", MemberDesc(DATA_STR).setFunc(TextSkin , TextSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  581. obj_edit[GO_TEXTBOX].add("Name" , MemberDesc(MEMBER(TextBox2, name )));
  582. obj_edit[GO_TEXTBOX].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc ));
  583. obj_edit[GO_TEXTBOX].add("Text" , MemberDesc(DATA_STR).setFunc(TextBoxText, TextBoxText));
  584. obj_edit[GO_TEXTBOX].add("Hint" , MemberDesc(MEMBER(TextBox2, hint )));
  585. obj_edit[GO_TEXTBOX].add("Max Length" , MemberDesc(DATA_INT ).setFunc(TextBoxMaxLength, TextBoxMaxLength)).min(-1).desc("Maximum allowed text length, -1 = no limit");
  586. obj_edit[GO_TEXTBOX].add("Skin Override", MemberDesc(DATA_STR ).setFunc(TextBoxSkin , TextBoxSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  587. obj_edit[GO_TEXTLINE].add("Name" , MemberDesc(MEMBER(TextLine2, name )));
  588. obj_edit[GO_TEXTLINE].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc ));
  589. obj_edit[GO_TEXTLINE].add("Text" , MemberDesc(DATA_STR).setFunc(TextLineText, TextLineText));
  590. obj_edit[GO_TEXTLINE].add("Hint" , MemberDesc(MEMBER(TextLine2, hint )));
  591. obj_edit[GO_TEXTLINE].add("Show Find" , MemberDesc(MEMBER(TextLine2, show_find )));
  592. obj_edit[GO_TEXTLINE].add("Password" , MemberDesc(DATA_BOOL).setFunc(TextLinePassword , TextLinePassword ));
  593. obj_edit[GO_TEXTLINE].add("Max Length" , MemberDesc(DATA_INT ).setFunc(TextLineMaxLength, TextLineMaxLength)).min(-1).desc("Maximum allowed text length, -1 = no limit");
  594. obj_edit[GO_TEXTLINE].add("Skin Override", MemberDesc(DATA_STR ).setFunc(TextLineSkin , TextLineSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  595. obj_edit[GO_VIEWPORT].add("Name" , MemberDesc(MEMBER(Viewport2, name )));
  596. obj_edit[GO_VIEWPORT].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  597. obj_edit[GO_VIEWPORT].add("Rect Color", MemberDesc(MEMBER(Viewport2, rect_color))).setColor();
  598. obj_edit[GO_WINDOW].add("Name" , MemberDesc(MEMBER(Window2, name )));
  599. obj_edit[GO_WINDOW].add("Desc" , MemberDesc(DATA_STR).setFunc(Desc, Desc));
  600. obj_edit[GO_WINDOW].add("Title" , MemberDesc(MEMBER(Window2, title )));
  601. obj_edit[GO_WINDOW].add("Level" , MemberDesc(DATA_INT ).setFunc(WindowLevel , WindowLevel )).mouseEditSpeed(4);
  602. obj_edit[GO_WINDOW].add("Movable" , MemberDesc(DATA_BOOL).setFunc(WindowMovable , WindowMovable ));
  603. obj_edit[GO_WINDOW].add("Resizable" , MemberDesc(DATA_BOOL).setFunc(WindowResizable , WindowResizable ));
  604. obj_edit[GO_WINDOW].add("Bar Visible" , MemberDesc(DATA_BOOL).setFunc(WindowBarVisible, WindowBarVisible));
  605. //obj_edit[GO_WINDOW].add("Bar Height" , MemberDesc(DATA_REAL).setFunc(WindowBarHeight , WindowBarHeight )).min(0).mouseEditSpeed(0.05);
  606. obj_edit[GO_WINDOW].add("Skin Override", MemberDesc(DATA_STR ).setFunc(WindowSkin , WindowSkin )).elmType(ELM_GUI_SKIN).desc("Override Skin, if no skin is specified then default will be used");
  607. REPAO(obj_edit).create(GUI_OBJ_TYPE(i), panel.level());
  608. createPropsTabs(null);
  609. }
  610. GuiView& GuiView::create(GuiObj &parent)
  611. {
  612. parent+=::EE::Region::create();
  613. objs.parent=&parent;
  614. Gui+=panel.create().hide().disabled(true);
  615. undoVis();
  616. createProps();
  617. removeSlideBars();
  618. return T;
  619. }
  620. void GuiView::resize() {rect(EditRect());}
  621. GuiObj* GuiView::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel){return null;}
  622. void GuiView::elmChanged(C UID &elm_id)
  623. {
  624. if(elm && elm->id==elm_id)
  625. {
  626. undo.set(null, true);
  627. objs.load(Proj.gamePath(*elm));
  628. }
  629. }
  630. void GuiView::setChanged(bool to_gui)
  631. {
  632. if(elm)
  633. {
  634. if(ElmGui *data=elm->guiData()){data->newVer(); data->file_time.getUTC();}
  635. if(to_gui)toGui();
  636. changed=true;
  637. }
  638. }
  639. GuiObj* GuiView::cur( ) {return (sel.elms()==1) ? sel[0] : null;}
  640. GuiObj* GuiView::cur(GUI_OBJ_TYPE type) {if(GuiObj *obj=cur())if(obj->type()==type)return obj; return null;}
  641. bool GuiView::selectedParents(GuiObj *obj) {for(; obj; obj=obj->parent())if(sel.has(obj))return true; return false;}
  642. bool GuiView::editable(GuiObj *obj) {return obj==Gui.desktop() || obj==this || objs.containsMain(obj);}
  643. Rect GuiView::selRect( ) {return Rect().from(sel_pos, Ms.pos());}
  644. bool GuiView::hasKbFocus( )
  645. {
  646. if(editable(Gui.kb()))return true;
  647. if(panel.contains(Gui.kb())
  648. || Gui.kb()==&Mode)if(Gui.kb()->type()!=GO_TEXTLINE && Gui.kb()->type()!=GO_TEXTBOX)return true;
  649. return false;
  650. }
  651. void GuiView::removed(GuiObj *obj)
  652. {
  653. if(obj){sel.exclude(obj, true); lit.exclude(obj, true); if(obj->contains(sel_parent))sel_parent=null;}
  654. REPA(obj_edit)if(GuiObj *data=(GuiObj*)obj_edit[i].autoData())if(obj->contains(data))obj_edit[i].autoData(null).hide();
  655. }
  656. void GuiView::sort() {sel.sort(CompareOrder);}
  657. int GuiView::CompareOrder(GuiObj*C &a, GuiObj*C &b) {return a->compareLevel(*b);}
  658. void GuiView::alignSel()
  659. {
  660. undo.set("align");
  661. if(sel.elms())
  662. {
  663. REPA(sel){GuiObj &obj=*sel[i]; Vec2 pos=obj.pos(); panel.align(pos, true); obj.pos(pos);}
  664. setChanged(true);
  665. }
  666. }
  667. void GuiView::moveUpSel() {undo.set("moveUpDown", true); if(sel.elms()){sort(); REPA(sel)sel[i]->moveUp (); for(int i=0; i<sel.elms()-1; i++)sel[i+1]->moveAbove(*sel[i]); setChanged();}}
  668. void GuiView::moveDownSel() {undo.set("moveUpDown", true); if(sel.elms()){sort(); FREPA(sel)sel[i]->moveDown(); for(int i=0; i<sel.elms()-1; i++)sel[i+1]->moveAbove(*sel[i]); setChanged();}}
  669. void GuiView::resetAspect()
  670. {
  671. undo.set("aspect");
  672. if(sel.elms())
  673. {
  674. REPA(sel)
  675. {
  676. GuiObj &obj=*sel[i]; Vec2 size=obj.size();
  677. if(obj.type()==GO_BUTTON ) if(C ImagePtr &image=obj.asButton ().image)if(image-> is())size.y=size.x/image-> aspect();
  678. if(obj.type()==GO_COMBOBOX) if(C ImagePtr &image=obj.asComboBox().image)if(image-> is())size.y=size.x/image-> aspect();
  679. if(obj.type()==GO_CHECKBOX)if(Gui.skin)if(C PanelImagePtr &image=Gui.skin->checkbox.off)if(image->image.is())size.y=size.x/image->image.aspect();
  680. if(obj.type()==GO_IMAGE ) if(C ImagePtr &image=obj.asImage ().image)if(image-> is())size.y=size.x/image-> aspect();
  681. MAX(size.x, MinSize); MAX(size.y, MinSize);
  682. obj.size(size);
  683. }
  684. setChanged();
  685. }
  686. }
  687. void GuiView::processSel()
  688. {
  689. SelectionClass::SEL_MODE mode=((Kb.ctrlCmd() && Kb.shift()) ? SelectionClass::SM_KEEP : Kb.ctrlCmd() ? SelectionClass::SM_TOGGLE : Kb.shift() ? SelectionClass::SM_INCLUDE : Kb.alt() ? SelectionClass::SM_EXCLUDE : SelectionClass::SM_SET);
  690. if(mode==SelectionClass::SM_KEEP)
  691. {
  692. REPA(sel)if(!lit.has(sel[i]))sel.remove(i);
  693. }else
  694. {
  695. if(mode==SelectionClass::SM_SET)sel.clear();
  696. REPA(lit)switch(mode)
  697. {
  698. case SelectionClass::SM_INCLUDE:
  699. case SelectionClass::SM_SET : sel.include(lit[i]); break;
  700. case SelectionClass::SM_TOGGLE : sel.toggle (lit[i]); break;
  701. case SelectionClass::SM_EXCLUDE: sel.exclude(lit[i]); break;
  702. }
  703. }
  704. sort();
  705. lit.clear();
  706. undo.forceCreateNextUndo();
  707. }
  708. GuiView& GuiView::toGui()
  709. {
  710. if(GuiObj *obj=cur())if(InRange(obj->type(), obj_edit))obj_edit[obj->type()].toGui(obj); return T;
  711. }
  712. GuiObj* GuiView::copy(GuiObj &obj, GuiObj *parent, C Vec2 *screen_pos, C Vec2 *offset)
  713. {
  714. if(parent)
  715. if(!obj.contains(parent))
  716. if(GuiObj *dest=objs.New(obj.type()))
  717. {
  718. *parent+=dest->create(obj);
  719. if(screen_pos){Vec2 screen=dest->pos(Vec2(0)).screenPos(), pos=*screen_pos-screen; panel.align(pos); dest->pos(pos);}
  720. if(offset )dest->move(*offset);
  721. // copy children
  722. if(Tabs *src_tabs=CAST(Tabs, &obj)) // 'child' will return Tab for Tabs
  723. {
  724. if(Tabs *dest_tabs=CAST(Tabs, dest))FREP(Min(src_tabs->tabs(), dest_tabs->tabs()))
  725. {
  726. Tab & src_tab= src_tabs->tab(i),
  727. &dest_tab=dest_tabs->tab(i);
  728. FREP(src_tab.childNum())copy(*src_tab.child(i), &dest_tab, null, null);
  729. }
  730. }else FREP(obj.childNum())copy(*obj.child(i), dest, null, null);
  731. return dest;
  732. }
  733. return null;
  734. }
  735. void GuiView::clean() // clean all references which point to invalid files
  736. {
  737. if(elm)
  738. {
  739. undo.set("clean");
  740. REP(GO_NUM)if(Memx<GuiObj> *container=objs.container(GUI_OBJ_TYPE(i)))REPA(*container)Clean((*container)[i]);
  741. setChanged();
  742. }
  743. }
  744. void GuiView::update(C GuiPC &gpc)
  745. {
  746. ::EE::Region::update(gpc);
  747. lit.clear();
  748. if(visible() && gpc.visible)
  749. {
  750. GuiSkinPtr temp_skin=Gui.skin; if(GuiSkinPtr skin=Proj.appGuiSkin())Gui.skin=skin; // set skin because that may affect object properties (for example slidebar button visibility, window client rectangle)
  751. // get highlighted objects (only from containers, do not include desktop)
  752. if(selecting) // highlight by selection
  753. {
  754. Rect sel_rect=selRect();
  755. REP(GO_NUM)if(Memx<GuiObj> *container=objs.container(GUI_OBJ_TYPE(i)))REPA(*container)
  756. {
  757. GuiObj &go=(*container)[i];
  758. if(MainParent(go.parent(), false)==sel_parent && go.visibleFull())
  759. if(Cuts(sel_rect, go.screenRect()))lit.include(&go);
  760. }
  761. }else // highlight by mouse
  762. if(GuiObj *obj=MainObject(Gui.msLit()))
  763. if(objs.contains(obj))
  764. if(!Ms.b(1) && !disable_selection) // don't highlight when editing or when cancelled selection
  765. lit.include(obj);
  766. // enable rectangle selection
  767. if(!selecting)
  768. {
  769. if(!disable_selection)if(GuiObj *go=MainObject(Gui.ms()))if(editable(go))
  770. if(go->type()!=GO_SLIDER && go->type()!=GO_SLIDEBAR && go->type()!=GO_CHECKBOX && go->type()!=GO_TEXTLINE && go->type()!=GO_TEXTBOX) // disallow selection when starting with these elements because they support mouse action
  771. {
  772. if(Ms.bp(0))
  773. {
  774. sel_pos =Ms.pos();
  775. sel_parent=FirstContainer(go, false);
  776. }
  777. if(Ms.selecting())selecting=true;
  778. }
  779. }
  780. // end rectangle selection
  781. if(selecting)
  782. {
  783. if(Ms.bp(1)){selecting=false; disable_selection=true;}else // cancel selection, 'disable_selection' so releasing later any button currently pressed will not force selection
  784. if(Ms.br(0))
  785. {
  786. selecting=false; disable_selection=true; processSel();
  787. }else
  788. if(!Ms.b(0))
  789. {
  790. selecting=false;
  791. }
  792. }
  793. // select objs on tap
  794. if(!disable_selection && !selecting)
  795. if(!Ms.selecting() && (Ms.br(0) || Ms.bd(0)))
  796. if(editable(Gui.ms()))
  797. {
  798. disable_selection|=Ms.bd(0); processSel();
  799. }
  800. if(!((Ms.b(0) || Ms.br(0)) && editable(Gui.ms())))disable_selection=false; // if there are no presses and releases then re-enable selection
  801. op=panel.op();
  802. if(Kb.ctrlCmd() && Kb.shift())op=OP_SCALE ;else
  803. if( Kb.shift())op=OP_SEPARATE;else
  804. if(Kb.ctrlCmd() )op=OP_SIZE ;else
  805. if(Kb.alt () )op=OP_PARENT ;
  806. // add new object
  807. if(!selecting)
  808. if(Ms.bp(1) && op==OP_NEW
  809. || Kb.kf(KB_INS) && Kb.k.ctrlCmd() && hasKbFocus())
  810. if(GuiObj *parent=FirstContainer(Gui.ms(), false))
  811. if(editable(parent))
  812. {
  813. if(parent==Gui.desktop())parent=T.parent(); // don't add to the desktop but to the Mode Gui Tab
  814. if(parent)
  815. {
  816. undo.set("new", true);
  817. if(GuiObj *obj=objs.New(panel.objType()))
  818. {
  819. sel.clear();
  820. *parent+=*obj;
  821. Vec2 pos=Ms.pos()-obj->screenPos();
  822. panel.align(pos);
  823. obj->pos(pos);
  824. sel.add(obj);
  825. disable_selection=true;
  826. setChanged();
  827. Kb.eat(KB_INS);
  828. }
  829. }
  830. }
  831. // copy selection
  832. if(!selecting && sel.elms())
  833. if(Ms.bp(1) && op==OP_COPY
  834. || Kb.kf(KB_D) && Kb.k.ctrlCmd() && hasKbFocus())
  835. if(GuiObj *parent=FirstContainer(Gui.ms(), true)) // allow tabs so we can copy a group at once to target tab
  836. if(editable(parent))
  837. {
  838. for(; selectedParents(parent); ) // don't add to selection
  839. parent=FirstContainer(parent->parent(), true); // allow tabs so we can copy a group at once to target tab
  840. if(parent==Gui.desktop())parent=T.parent(); // don't add to the desktop but to the Mode Gui Tab
  841. if(parent)
  842. {
  843. undo.set("copy", true);
  844. sort();
  845. temp.clear(); FREPA(sel)if(!selectedParents(sel[i]->parent()))temp.add(sel[i]); // add root selected objects to temp (keep order)
  846. sel .clear();
  847. for(; temp.elms(); )
  848. {
  849. GuiObj *temp_parent=temp.first()->parent();
  850. Vec2 pos =temp.first()->pos ();
  851. REPA(temp)if(temp[i]->parent()==temp_parent){Vec2 p=temp[i]->pos(); MIN(pos.x, p.x); MAX(pos.y, p.y);} // get top-left corner
  852. for(int i=0; i<temp.elms(); )if(temp[i]->parent()==temp_parent) // keep order
  853. {
  854. if(GuiObj *obj=copy(*temp[i], parent, &Ms.pos(), &(temp[i]->pos()-pos)))sel.add(obj);
  855. temp.remove(i, true); // keep order
  856. }else i++;
  857. }
  858. setChanged();
  859. Kb.eat(KB_D);
  860. }
  861. }
  862. // delete
  863. if(!selecting && Ms.bp(1) && op==OP_DEL) // remove highlighted on RMB
  864. {
  865. undo.set("del", true);
  866. objs.remove(MainObject(Gui.ms()));
  867. disable_selection=true;
  868. setChanged();
  869. }
  870. if(hasKbFocus() && Kb.kf(KB_DEL) && Kb.k.ctrlCmd() && sel.elms()) // remove selected on Ctrl+Del
  871. {
  872. undo.set("del", true);
  873. temp=sel; REPA(temp)objs.remove(temp[i]); // copy to 'temp' container because removing changes 'sel'
  874. Kb.eatKey();
  875. setChanged();
  876. }
  877. // undo
  878. if(hasKbFocus() && Kb.k.ctrlCmd() && Kb.k(KB_Z)){undo.undo(); Kb.eatKey();}
  879. if(hasKbFocus() && Kb.k.ctrlCmd() && Kb.k(KB_Y)){undo.redo(); Kb.eatKey();}
  880. // edit
  881. if(sel.elms())
  882. {
  883. int op=T.op;
  884. if(op< 0)op=OP_MOVE;
  885. if(op==OP_NEW)op=OP_SIZE;
  886. if(editable(Gui.ms()) && Ms.b(1) && op==OP_MOVE) // move objects
  887. {
  888. undo.set("move");
  889. helper+=Ms.dc(); Vec2 d=helper; panel.alignTrunc(d); helper-=d;
  890. REPA(sel)if(!selectedParents(sel[i]->parent()))sel[i]->move(d);
  891. setChanged(true);
  892. }else
  893. if(editable(Gui.ms()) && Ms.b(1) && op==OP_SIZE) // resize objects
  894. {
  895. helper.x+=Ms.dc().x; helper.y-=Ms.dc().y; Vec2 d=helper; panel.alignTrunc(d); helper-=d;
  896. cchar8 *type="size"; if(undo.lastChangeType()==type || d.any()) // this is to prevent creating a dummy Undo level right away after creating new gui objects
  897. {
  898. undo.set(type);
  899. REPA(sel)
  900. {
  901. GuiObj &go=*sel[i]; Vec2 size=go.size()+d; MAX(size.x, MinSize); MAX(size.y, MinSize); go.size(size);
  902. }
  903. setChanged(true);
  904. }
  905. }else
  906. if(editable(Gui.ms()) && Ms.b(1) && op==OP_SEPARATE) // separate objects
  907. {
  908. undo.set("move");
  909. helper.x+=Ms.dc().x; helper.y-=Ms.dc().y; Vec2 d=helper; panel.alignTrunc(d); helper-=d;
  910. for(temp=sel; temp.elms(); )
  911. {
  912. GuiObj *parent=temp.first()->parent(); // get parent of first object
  913. Rect rect =temp.first()->rect (); // get rect of first object
  914. REPA(temp)if(temp[i]->parent()==parent)rect|=temp[i]->rect(); // get rect covering all objects for this parent
  915. Vec2 scale=1; if(rect.size().all()){scale=(rect.size()+d)/rect.size(); MAX(scale.x, 0); MAX(scale.y, 0);}
  916. REPA(temp)if(temp[i]->parent()==parent) // go from back because we're removing elements
  917. {
  918. GuiObj &obj=*temp[i]; temp.remove(i); // this object was processed so remove it
  919. obj.pos((obj.pos()-rect.lu())*scale+rect.lu());
  920. }
  921. }
  922. setChanged(true);
  923. }else
  924. if(editable(Gui.ms()) && Ms.b(1) && op==OP_SCALE) // scale objects
  925. {
  926. undo.set("scale");
  927. helper.x+=Ms.dc().x; helper.y-=Ms.dc().y; Vec2 d=helper; panel.alignTrunc(d); helper-=d;
  928. for(temp=sel; temp.elms(); )
  929. {
  930. GuiObj *parent=temp.first()->parent(); // get parent of first object
  931. Rect rect =temp.first()->rect (); // get rect of first object
  932. REPA(temp)if(temp[i]->parent()==parent)rect|=temp[i]->rect(); // get rect covering all objects for this parent
  933. Vec2 scale=1; if(rect.size().all()){scale=(rect.size()+d)/rect.size(); MAX(scale.x, 0); MAX(scale.y, 0);}
  934. REPA(temp)if(temp[i]->parent()==parent) // go from back because we're removing elements
  935. {
  936. GuiObj &obj=*temp[i]; temp.remove(i); // this object was processed so remove it
  937. Vec2 size=obj.size()*scale; MAX(size.x, MinSize); MAX(size.y, MinSize);
  938. obj.pos((obj.pos()-rect.lu())*scale+rect.lu()).size(size);
  939. }
  940. }
  941. setChanged(true);
  942. }else
  943. if(editable(Gui.ms()) && Ms.b(1) && op==OP_PARENT) // parent objects
  944. {
  945. undo.set("move");
  946. IgnoreSelected=true ; GuiObj *target=Gui.objAtPos(Ms.pos()); // don't put objects into selected ones
  947. IgnoreSelected=false;
  948. target=MainParent(FirstContainer(target, true), true); if(!editable(target))target=null; if(target==Gui.desktop())target=T.parent(); // don't add to the desktop but to the Mode Gui Tab
  949. lit.clear(); if(target)lit.add(MainParent(target, true)); // highlight target for silky smooth user experience
  950. helper+=Ms.dc(); Vec2 d=helper; panel.alignTrunc(d); helper-=d;
  951. sort();
  952. FREPA(sel)if(!selectedParents(sel[i]->parent())) // keep order
  953. {
  954. sel[i]->move(d);
  955. if(target && sel[i]->parent()!=target && !sel[i]->contains(target)) // move to new parent
  956. {
  957. Vec2 pos=sel[i]->screenPos();
  958. *target+=*sel[i];
  959. sel[i]->move(pos-sel[i]->screenPos());
  960. }
  961. }
  962. setChanged(true);
  963. }else helper.zero();
  964. // keyboard edit
  965. if(hasKbFocus() && Kb.k.k)
  966. {
  967. if(Kb.k.ctrlCmd())
  968. {
  969. if(Kb.k (KB_PGUP)){moveUpSel (); Kb.eatKey();}else
  970. if(Kb.k (KB_PGDN)){moveDownSel(); Kb.eatKey();}else
  971. if(Kb.kf(KB_R )){resetAspect(); Kb.eatKey();}else
  972. if(Kb.kf(KB_G )){alignSel (); Kb.eatKey();}
  973. }
  974. Vec2 d=D.pixelToScreenSize(); if(panel.grid_align())d=panel.grid_size;
  975. Vec2 m(0, 0);
  976. if(Kb.k(KB_LEFT ))m.x-=d.x;else
  977. if(Kb.k(KB_RIGHT))m.x+=d.x;else
  978. if(Kb.k(KB_DOWN ))m.y-=d.y;else
  979. if(Kb.k(KB_UP ))m.y+=d.y;
  980. if(op==OP_SIZE)
  981. {
  982. if(m.any())
  983. {
  984. undo.set("size");
  985. REPA(sel)
  986. {
  987. GuiObj &obj=*sel[i]; Vec2 size=obj.size(); MAX(size.x+=m.x, MinSize); MAX(size.y-=m.y, MinSize);
  988. obj.size(size);
  989. }
  990. setChanged(true);
  991. }
  992. }else
  993. {
  994. if(m.any())
  995. {
  996. undo.set("move");
  997. REPAO(sel)->move(m);
  998. setChanged(true);
  999. }
  1000. }
  1001. }
  1002. }
  1003. // update gui
  1004. GuiObj *cur=T.cur();
  1005. if(last!=cur)
  1006. {
  1007. last=cur;
  1008. if(cur && cur->type()==GO_TABS)createPropsTabs(&cur->asTabs());
  1009. REPAO(obj_edit).autoData((cur && cur->type()==i) ? cur : null).visible(cur && cur->type()==i);
  1010. }
  1011. Gui.skin=temp_skin;
  1012. }
  1013. }
  1014. void GuiView::Highlight(GuiObj &go, C Color &color, flt a)
  1015. {
  1016. Rect r=go.screenRect(); if(&go==Gui.desktop())r&=EditRect();
  1017. r.drawShaded(ColorAlpha(color, 0), ColorAlpha(color, a), 0.013f);
  1018. }
  1019. void GuiView::drawPreview(GuiObj &obj, C GuiPC &gpc, GuiObj &parent)
  1020. {
  1021. parent+=obj;
  1022. Vec2 screen=obj.screenPos(), pos=Ms.pos()-screen; panel.align(pos); obj.pos(pos);
  1023. parent-=obj;
  1024. obj.move(screen);
  1025. obj.draw(gpc);
  1026. }
  1027. void GuiView::draw(C GuiPC &gpc)
  1028. {
  1029. }
  1030. void GuiView::drawPre()
  1031. {
  1032. if(GuiSkinPtr temp=Proj.appGuiSkin())D.clear(temp->background_color);else D.clear(BackgroundColor());
  1033. }
  1034. void GuiView::draw()
  1035. {
  1036. if(selected())
  1037. {
  1038. // highlight objects
  1039. REPA(lit)Highlight(*lit[i], Color(128, 255, 255), (op==OP_PARENT || op==OP_COPY || op==OP_NEW) ? 1 : 0.6f);
  1040. REPA(sel)Highlight(*sel[i], Color(255, 255, 0), 0.6f);
  1041. // draw preview of object "to-be created"
  1042. GuiPC gpc; gpc.clip=gpc.client_rect=Gui.desktop()->rect(); gpc.visible=gpc.enabled=true; gpc.offset.zero();
  1043. if(op==OP_NEW && !Ms.b(1))if(GuiObj *parent=FirstContainer(Gui.ms(), false))if(editable(parent))
  1044. {
  1045. GuiSkinPtr temp=Gui.skin; if(GuiSkinPtr skin=Proj.appGuiSkin())Gui.skin=skin; // set current skin so object is previewed with correct skin
  1046. switch(panel.objType())
  1047. {
  1048. case GO_BUTTON : {Button2 obj; drawPreview(obj, gpc, *parent);} break;
  1049. case GO_CHECKBOX: {CheckBox2 obj; drawPreview(obj, gpc, *parent);} break;
  1050. case GO_COMBOBOX: {ComboBox2 obj; drawPreview(obj, gpc, *parent);} break;
  1051. case GO_CUSTOM : {GuiCustom2 obj; drawPreview(obj, gpc, *parent);} break;
  1052. //case GO_DESKTOP : {Desktop2 obj;} break;
  1053. case GO_IMAGE : {GuiImage2 obj; drawPreview(obj, gpc, *parent);} break;
  1054. case GO_LIST : {List2 obj; drawPreview(obj, gpc, *parent);} break;
  1055. case GO_MENU : {Menu2 obj; drawPreview(obj, gpc, *parent);} break;
  1056. case GO_MENU_BAR: {MenuBar2 obj; drawPreview(obj, gpc, *parent);} break;
  1057. case GO_PROGRESS: {Progress2 obj; drawPreview(obj, gpc, *parent);} break;
  1058. case GO_REGION : {Region2 obj; drawPreview(obj, gpc, *parent);} break;
  1059. case GO_SLIDEBAR: {SlideBar2 obj; drawPreview(obj, gpc, *parent);} break;
  1060. case GO_SLIDER : {Slider2 obj; drawPreview(obj, gpc, *parent);} break;
  1061. case GO_TABS : {Tabs2 obj; drawPreview(obj, gpc, *parent);} break;
  1062. case GO_TEXT : {Text2 obj; drawPreview(obj, gpc, *parent);} break;
  1063. case GO_TEXTBOX : {TextBox2 obj; drawPreview(obj, gpc, *parent);} break;
  1064. case GO_TEXTLINE: {TextLine2 obj; drawPreview(obj, gpc, *parent);} break;
  1065. case GO_VIEWPORT: {Viewport2 obj; drawPreview(obj, gpc, *parent);} break;
  1066. case GO_WINDOW : {Window2 obj; drawPreview(obj, gpc, *parent);} break;
  1067. }
  1068. Gui.skin=temp;
  1069. D.clip();
  1070. }
  1071. // draw screen proportions
  1072. if(panel.draw_proportions())
  1073. {
  1074. flt y=1,
  1075. a=16.0f/ 9; Rect(-a, -y, a, y).draw(CYAN , false);
  1076. a=16.0f/10; Rect(-a, -y, a, y).draw(RED , false);
  1077. a= 4.0f/ 3; Rect(-a, -y, a, y).draw(GREEN , false);
  1078. a= 5.0f/ 4; Rect(-a, -y, a, y).draw(BLUE , false);
  1079. a= 1.0f/ 1; Rect(-a, -y, a, y).draw(PURPLE, false);
  1080. D.lineY(PURPLE, 0, -1, 1);
  1081. D.lineX(PURPLE, 0, -1, 1);
  1082. }
  1083. // draw selection rectangle
  1084. if(selecting)
  1085. {
  1086. Rect r=selRect();
  1087. r.draw(ColorAlpha(ColorBrightness(LitColor, 0.25f), 0.1f), true );
  1088. r.draw(ColorAlpha(ColorBrightness(LitColor, 0.80f), 0.6f), false);
  1089. }
  1090. }
  1091. }
  1092. void GuiView::drag(Memc<UID> &elms, GuiObj* &obj, C Vec2 &screen_pos)
  1093. {
  1094. if(elms.elms())
  1095. {
  1096. // check for drop onto gui object
  1097. if(GuiObj *main=MainObject(obj))
  1098. if(objs.contains(main))
  1099. {
  1100. Memx<PropEx> &props=obj_edit[main->type()].props; // list of all properties for that kind of object
  1101. FREPA(props) // order important (set first property of elm type in case there are many)
  1102. {
  1103. PropEx &prop=props[i];
  1104. if(prop.elm_type) // if this property supports drag drop
  1105. REPA(elms)if(Elm *elm=Proj.findElm(elms[i]))if(prop.compatible(elm->type)) // if dropping element of type that matches property type
  1106. {
  1107. undo.set(null, true);
  1108. ptr auto_data=prop.autoData(); // remember old auto data
  1109. prop.autoData(main).set(elm->id.asHex()); // set auto data to target object, then set value to element ID
  1110. prop.autoData(auto_data); // restore old auto data
  1111. toGui(); // refresh gui because we've set ID in hex format (to replace with elm path)
  1112. obj=null; // clear in case got deleted
  1113. return;
  1114. }
  1115. }
  1116. }
  1117. }
  1118. }
  1119. GuiView::GuiView() : changed(false), selecting(false), disable_selection(false), sel_pos(0), helper(0), elm_id(UIDZero), elm(null), op(-1), sel_parent(null), last(null), undo(true) {}
  1120. GuiView::Objects::Objects() : parent(null) {}
  1121. GuiView::Panel::Panel() : grid_size(0.010f) {}
  1122. /******************************************************************************/