property_editor.cpp 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910
  1. /**************************************************************************/
  2. /* property_editor.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "property_editor.h"
  31. #include "core/class_db.h"
  32. #include "core/io/image_loader.h"
  33. #include "core/io/marshalls.h"
  34. #include "core/io/resource_loader.h"
  35. #include "core/math/expression.h"
  36. #include "core/os/input.h"
  37. #include "core/os/keyboard.h"
  38. #include "core/pair.h"
  39. #include "core/print_string.h"
  40. #include "core/project_settings.h"
  41. #include "editor/array_property_edit.h"
  42. #include "editor/create_dialog.h"
  43. #include "editor/dictionary_property_edit.h"
  44. #include "editor/editor_export.h"
  45. #include "editor/editor_file_system.h"
  46. #include "editor/editor_help.h"
  47. #include "editor/editor_node.h"
  48. #include "editor/editor_scale.h"
  49. #include "editor/editor_settings.h"
  50. #include "editor/filesystem_dock.h"
  51. #include "editor/multi_node_edit.h"
  52. #include "editor/property_selector.h"
  53. #include "scene/gui/label.h"
  54. #include "scene/main/viewport.h"
  55. #include "scene/resources/font.h"
  56. #include "scene/resources/packed_scene.h"
  57. #include "scene/scene_string_names.h"
  58. void EditorResourceConversionPlugin::_bind_methods() {
  59. MethodInfo mi;
  60. mi.name = "_convert";
  61. mi.return_val.type = Variant::OBJECT;
  62. mi.return_val.class_name = "Resource";
  63. mi.return_val.hint = PROPERTY_HINT_RESOURCE_TYPE;
  64. mi.return_val.hint_string = "Resource";
  65. mi.arguments.push_back(mi.return_val);
  66. mi.arguments[0].name = "resource";
  67. BIND_VMETHOD(mi)
  68. mi.name = "_handles";
  69. mi.return_val = PropertyInfo(Variant::BOOL, "");
  70. BIND_VMETHOD(MethodInfo(Variant::STRING, "_converts_to"));
  71. }
  72. String EditorResourceConversionPlugin::converts_to() const {
  73. if (get_script_instance()) {
  74. return get_script_instance()->call("_converts_to");
  75. }
  76. return "";
  77. }
  78. bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const {
  79. if (get_script_instance()) {
  80. return get_script_instance()->call("_handles", p_resource);
  81. }
  82. return false;
  83. }
  84. Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const {
  85. if (get_script_instance()) {
  86. return get_script_instance()->call("_convert", p_resource);
  87. }
  88. return Ref<Resource>();
  89. }
  90. void CustomPropertyEditor::_notification(int p_what) {
  91. if (p_what == NOTIFICATION_DRAW) {
  92. RID ci = get_canvas_item();
  93. get_stylebox("panel", "PopupMenu")->draw(ci, Rect2(Point2(), get_size()));
  94. }
  95. if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
  96. hide();
  97. }
  98. }
  99. void CustomPropertyEditor::_menu_option(int p_which) {
  100. switch (type) {
  101. case Variant::INT: {
  102. if (hint == PROPERTY_HINT_FLAGS) {
  103. int idx = menu->get_item_index(p_which);
  104. uint32_t item_value = menu->get_item_metadata(idx);
  105. uint32_t value = v;
  106. // If the item wasn't previously checked it means it was pressed,
  107. // otherwise it was unpressed.
  108. if (!menu->is_item_checked(idx)) {
  109. v = value | item_value;
  110. } else {
  111. v = value & ~item_value;
  112. }
  113. emit_signal("variant_changed");
  114. } else if (hint == PROPERTY_HINT_ENUM) {
  115. v = menu->get_item_metadata(p_which);
  116. emit_signal("variant_changed");
  117. }
  118. } break;
  119. case Variant::STRING: {
  120. if (hint == PROPERTY_HINT_ENUM) {
  121. v = hint_text.get_slice(",", p_which);
  122. emit_signal("variant_changed");
  123. }
  124. } break;
  125. case Variant::OBJECT: {
  126. switch (p_which) {
  127. case OBJ_MENU_LOAD: {
  128. file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  129. String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
  130. List<String> extensions;
  131. for (int i = 0; i < type.get_slice_count(","); i++) {
  132. ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions);
  133. }
  134. Set<String> valid_extensions;
  135. for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
  136. valid_extensions.insert(E->get());
  137. }
  138. file->clear_filters();
  139. for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) {
  140. file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
  141. }
  142. file->popup_centered_ratio();
  143. } break;
  144. case OBJ_MENU_EDIT: {
  145. RefPtr RefPtr = v;
  146. if (!RefPtr.is_null()) {
  147. emit_signal("resource_edit_request");
  148. hide();
  149. }
  150. } break;
  151. case OBJ_MENU_CLEAR: {
  152. v = Variant();
  153. emit_signal("variant_changed");
  154. hide();
  155. } break;
  156. case OBJ_MENU_MAKE_UNIQUE: {
  157. RefPtr RefPtr = v;
  158. Ref<Resource> res_orig = RefPtr;
  159. if (res_orig.is_null()) {
  160. return;
  161. }
  162. List<PropertyInfo> property_list;
  163. res_orig->get_property_list(&property_list);
  164. List<Pair<String, Variant>> propvalues;
  165. for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
  166. Pair<String, Variant> p;
  167. PropertyInfo &pi = E->get();
  168. if (pi.usage & PROPERTY_USAGE_STORAGE) {
  169. p.first = pi.name;
  170. p.second = res_orig->get(pi.name);
  171. }
  172. propvalues.push_back(p);
  173. }
  174. String orig_type = res_orig->get_class();
  175. Object *inst = ClassDB::instance(orig_type);
  176. Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst));
  177. ERR_FAIL_COND(res.is_null());
  178. for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
  179. Pair<String, Variant> &p = E->get();
  180. res->set(p.first, p.second);
  181. }
  182. v = res.get_ref_ptr();
  183. emit_signal("variant_changed");
  184. hide();
  185. } break;
  186. case OBJ_MENU_COPY: {
  187. EditorSettings::get_singleton()->set_resource_clipboard(v);
  188. } break;
  189. case OBJ_MENU_PASTE: {
  190. v = EditorSettings::get_singleton()->get_resource_clipboard();
  191. emit_signal("variant_changed");
  192. } break;
  193. case OBJ_MENU_NEW_SCRIPT: {
  194. if (Object::cast_to<Node>(owner)) {
  195. EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), false);
  196. }
  197. } break;
  198. case OBJ_MENU_EXTEND_SCRIPT: {
  199. if (Object::cast_to<Node>(owner)) {
  200. EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), true);
  201. }
  202. } break;
  203. case OBJ_MENU_SHOW_IN_FILE_SYSTEM: {
  204. RES r = v;
  205. FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock();
  206. file_system_dock->navigate_to_path(r->get_path());
  207. // Ensure that the FileSystem dock is visible.
  208. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
  209. tab_container->set_current_tab(file_system_dock->get_position_in_parent());
  210. } break;
  211. default: {
  212. if (p_which >= CONVERT_BASE_ID) {
  213. int to_type = p_which - CONVERT_BASE_ID;
  214. Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(RES(v));
  215. ERR_FAIL_INDEX(to_type, conversions.size());
  216. Ref<Resource> new_res = conversions[to_type]->convert(v);
  217. v = new_res;
  218. emit_signal("variant_changed");
  219. break;
  220. }
  221. ERR_FAIL_COND(inheritors_array.empty());
  222. String intype = inheritors_array[p_which - TYPE_BASE_ID];
  223. if (intype == "ViewportTexture") {
  224. scene_tree->set_title(TTR("Pick a Viewport"));
  225. scene_tree->popup_centered_ratio();
  226. picking_viewport = true;
  227. return;
  228. }
  229. Variant obj = ClassDB::instance(intype);
  230. if (!obj) {
  231. if (ScriptServer::is_global_class(intype)) {
  232. obj = EditorNode::get_editor_data().script_class_instance(intype);
  233. } else {
  234. obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
  235. }
  236. }
  237. ERR_BREAK(!obj);
  238. Resource *res = Object::cast_to<Resource>(obj);
  239. ERR_BREAK(!res);
  240. if (owner && hint == PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Script") {
  241. //make visual script the right type
  242. res->call("set_instance_base_type", owner->get_class());
  243. }
  244. v = obj;
  245. emit_signal("variant_changed");
  246. } break;
  247. }
  248. } break;
  249. default: {
  250. }
  251. }
  252. }
  253. void CustomPropertyEditor::hide_menu() {
  254. menu->hide();
  255. }
  256. Variant CustomPropertyEditor::get_variant() const {
  257. return v;
  258. }
  259. String CustomPropertyEditor::get_name() const {
  260. return name;
  261. }
  262. bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text) {
  263. owner = p_owner;
  264. updating = true;
  265. name = p_name;
  266. v = p_variant;
  267. field_names.clear();
  268. hint = p_hint;
  269. hint_text = p_hint_text;
  270. type_button->hide();
  271. if (color_picker) {
  272. color_picker->hide();
  273. }
  274. texture_preview->hide();
  275. inheritors_array.clear();
  276. text_edit->hide();
  277. easing_draw->hide();
  278. spinbox->hide();
  279. slider->hide();
  280. menu->clear();
  281. menu->set_size(Size2(1, 1) * EDSCALE);
  282. for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
  283. value_editor[i]->hide();
  284. value_label[i]->hide();
  285. if (i < 4) {
  286. scroll[i]->hide();
  287. }
  288. }
  289. for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
  290. action_buttons[i]->hide();
  291. }
  292. checks20gc->hide();
  293. for (int i = 0; i < 20; i++) {
  294. checks20[i]->hide();
  295. }
  296. type = (p_variant.get_type() != Variant::NIL && p_variant.get_type() != Variant::_RID && p_type != Variant::OBJECT) ? p_variant.get_type() : p_type;
  297. switch (type) {
  298. case Variant::BOOL: {
  299. checks20gc->show();
  300. CheckBox *c = checks20[0];
  301. c->set_text("True");
  302. checks20gc->set_position(Vector2(4, 4) * EDSCALE);
  303. c->set_pressed(v);
  304. c->show();
  305. checks20gc->set_size(checks20gc->get_minimum_size());
  306. set_size(checks20gc->get_position() + checks20gc->get_size() + c->get_size() + Vector2(4, 4) * EDSCALE);
  307. } break;
  308. case Variant::INT:
  309. case Variant::REAL: {
  310. if (hint == PROPERTY_HINT_RANGE) {
  311. int c = hint_text.get_slice_count(",");
  312. float min = 0, max = 100, step = type == Variant::REAL ? .01 : 1;
  313. if (c >= 1) {
  314. if (!hint_text.get_slice(",", 0).empty()) {
  315. min = hint_text.get_slice(",", 0).to_double();
  316. }
  317. }
  318. if (c >= 2) {
  319. if (!hint_text.get_slice(",", 1).empty()) {
  320. max = hint_text.get_slice(",", 1).to_double();
  321. }
  322. }
  323. if (c >= 3) {
  324. if (!hint_text.get_slice(",", 2).empty()) {
  325. step = hint_text.get_slice(",", 2).to_double();
  326. }
  327. }
  328. if (c >= 4 && hint_text.get_slice(",", 3) == "slider") {
  329. slider->set_min(min);
  330. slider->set_max(max);
  331. slider->set_step(step);
  332. slider->set_value(v);
  333. slider->show();
  334. set_size(Size2(110, 30) * EDSCALE);
  335. } else {
  336. spinbox->set_min(min);
  337. spinbox->set_max(max);
  338. spinbox->set_step(step);
  339. spinbox->set_value(v);
  340. spinbox->show();
  341. set_size(Size2(70, 35) * EDSCALE);
  342. }
  343. } else if (hint == PROPERTY_HINT_ENUM) {
  344. Vector<String> options = hint_text.split(",");
  345. int current_val = 0;
  346. for (int i = 0; i < options.size(); i++) {
  347. Vector<String> text_split = options[i].split(":");
  348. if (text_split.size() != 1) {
  349. current_val = text_split[1].to_int();
  350. }
  351. menu->add_item(text_split[0]);
  352. menu->set_item_metadata(i, current_val);
  353. current_val += 1;
  354. }
  355. menu->set_position(get_position());
  356. menu->popup();
  357. hide();
  358. updating = false;
  359. return false;
  360. } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
  361. String basename;
  362. switch (hint) {
  363. case PROPERTY_HINT_LAYERS_2D_RENDER:
  364. basename = "layer_names/2d_render";
  365. break;
  366. case PROPERTY_HINT_LAYERS_2D_PHYSICS:
  367. basename = "layer_names/2d_physics";
  368. break;
  369. case PROPERTY_HINT_LAYERS_2D_NAVIGATION:
  370. basename = "layer_names/2d_navigation";
  371. break;
  372. case PROPERTY_HINT_LAYERS_3D_RENDER:
  373. basename = "layer_names/3d_render";
  374. break;
  375. case PROPERTY_HINT_LAYERS_3D_PHYSICS:
  376. basename = "layer_names/3d_physics";
  377. break;
  378. case PROPERTY_HINT_LAYERS_3D_NAVIGATION:
  379. basename = "layer_names/3d_navigation";
  380. break;
  381. }
  382. checks20gc->show();
  383. uint32_t flgs = v;
  384. for (int i = 0; i < 2; i++) {
  385. Point2 ofs(4, 4);
  386. ofs.y += 22 * i;
  387. for (int j = 0; j < 10; j++) {
  388. int idx = i * 10 + j;
  389. CheckBox *c = checks20[idx];
  390. c->set_text(ProjectSettings::get_singleton()->get(basename + "/layer_" + itos(idx + 1)));
  391. c->set_pressed(flgs & (1 << (i * 10 + j)));
  392. c->show();
  393. }
  394. }
  395. show();
  396. checks20gc->set_position(Vector2(4, 4) * EDSCALE);
  397. checks20gc->set_size(checks20gc->get_minimum_size());
  398. set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size());
  399. } else if (hint == PROPERTY_HINT_EXP_EASING) {
  400. easing_draw->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5 * EDSCALE);
  401. easing_draw->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -5 * EDSCALE);
  402. easing_draw->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 5 * EDSCALE);
  403. easing_draw->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -30 * EDSCALE);
  404. type_button->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 3 * EDSCALE);
  405. type_button->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -3 * EDSCALE);
  406. type_button->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -25 * EDSCALE);
  407. type_button->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -7 * EDSCALE);
  408. type_button->set_text(TTR("Preset..."));
  409. type_button->get_popup()->clear();
  410. type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR);
  411. type_button->get_popup()->add_item(TTR("Ease In"), EASING_EASE_IN);
  412. type_button->get_popup()->add_item(TTR("Ease Out"), EASING_EASE_OUT);
  413. if (hint_text != "attenuation") {
  414. type_button->get_popup()->add_item(TTR("Zero"), EASING_ZERO);
  415. type_button->get_popup()->add_item(TTR("Easing In-Out"), EASING_IN_OUT);
  416. type_button->get_popup()->add_item(TTR("Easing Out-In"), EASING_OUT_IN);
  417. }
  418. type_button->show();
  419. easing_draw->show();
  420. set_size(Size2(200, 150) * EDSCALE);
  421. } else if (hint == PROPERTY_HINT_FLAGS) {
  422. Vector<String> flags = hint_text.split(",");
  423. uint32_t value = v;
  424. for (int i = 0; i < flags.size(); i++) {
  425. uint32_t current_val;
  426. Vector<String> text_split = flags[i].split(":");
  427. if (text_split.size() != 1) {
  428. current_val = text_split[1].to_int();
  429. } else {
  430. current_val = 1 << i;
  431. }
  432. menu->add_check_item(text_split[0], current_val);
  433. menu->set_item_metadata(i, current_val);
  434. if ((value & current_val) == current_val) {
  435. menu->set_item_checked(menu->get_item_index(current_val), true);
  436. }
  437. }
  438. menu->set_position(get_position());
  439. menu->popup();
  440. hide();
  441. updating = false;
  442. return false;
  443. } else {
  444. List<String> names;
  445. names.push_back("value:");
  446. config_value_editors(1, 1, 50, names);
  447. value_editor[0]->set_text(String::num(v));
  448. }
  449. } break;
  450. case Variant::STRING: {
  451. if (hint == PROPERTY_HINT_LOCALE_ID) {
  452. List<String> names;
  453. names.push_back(TTR("Locale..."));
  454. names.push_back(TTR("Clear"));
  455. config_action_buttons(names);
  456. } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) {
  457. List<String> names;
  458. names.push_back(TTR("File..."));
  459. names.push_back(TTR("Clear"));
  460. config_action_buttons(names);
  461. } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) {
  462. List<String> names;
  463. names.push_back(TTR("Dir..."));
  464. names.push_back(TTR("Clear"));
  465. config_action_buttons(names);
  466. } else if (hint == PROPERTY_HINT_ENUM) {
  467. Vector<String> options = hint_text.split(",");
  468. for (int i = 0; i < options.size(); i++) {
  469. menu->add_item(options[i], i);
  470. }
  471. menu->set_position(get_position());
  472. menu->popup();
  473. hide();
  474. updating = false;
  475. return false;
  476. } else if (hint == PROPERTY_HINT_MULTILINE_TEXT) {
  477. text_edit->show();
  478. text_edit->set_text(v);
  479. text_edit->deselect();
  480. int button_margin = get_constant("button_margin", "Dialogs");
  481. int margin = get_constant("margin", "Dialogs");
  482. action_buttons[0]->set_anchor(MARGIN_LEFT, ANCHOR_END);
  483. action_buttons[0]->set_anchor(MARGIN_TOP, ANCHOR_END);
  484. action_buttons[0]->set_anchor(MARGIN_RIGHT, ANCHOR_END);
  485. action_buttons[0]->set_anchor(MARGIN_BOTTOM, ANCHOR_END);
  486. action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE));
  487. action_buttons[0]->set_end(Point2(-margin, -margin));
  488. action_buttons[0]->set_text(TTR("Close"));
  489. action_buttons[0]->show();
  490. } else if (hint == PROPERTY_HINT_TYPE_STRING) {
  491. if (!create_dialog) {
  492. create_dialog = memnew(CreateDialog);
  493. create_dialog->connect("create", this, "_create_dialog_callback");
  494. add_child(create_dialog);
  495. }
  496. if (hint_text != String()) {
  497. create_dialog->set_base_type(hint_text);
  498. } else {
  499. create_dialog->set_base_type("Object");
  500. }
  501. create_dialog->popup_create(false);
  502. hide();
  503. updating = false;
  504. return false;
  505. } else if (hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) {
  506. #define MAKE_PROPSELECT \
  507. if (!property_select) { \
  508. property_select = memnew(PropertySelector); \
  509. property_select->connect("selected", this, "_create_selected_property"); \
  510. add_child(property_select); \
  511. } \
  512. hide();
  513. MAKE_PROPSELECT;
  514. Variant::Type type = Variant::NIL;
  515. for (int i = 0; i < Variant::VARIANT_MAX; i++) {
  516. if (hint_text == Variant::get_type_name(Variant::Type(i))) {
  517. type = Variant::Type(i);
  518. }
  519. }
  520. if (type != Variant::NIL) {
  521. property_select->select_method_from_basic_type(type, v);
  522. }
  523. updating = false;
  524. return false;
  525. } else if (hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE) {
  526. MAKE_PROPSELECT
  527. property_select->select_method_from_base_type(hint_text, v);
  528. updating = false;
  529. return false;
  530. } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) {
  531. MAKE_PROPSELECT
  532. Object *instance = ObjectDB::get_instance(hint_text.to_int64());
  533. if (instance) {
  534. property_select->select_method_from_instance(instance, v);
  535. }
  536. updating = false;
  537. return false;
  538. } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) {
  539. MAKE_PROPSELECT
  540. Object *obj = ObjectDB::get_instance(hint_text.to_int64());
  541. if (Object::cast_to<Script>(obj)) {
  542. property_select->select_method_from_script(Object::cast_to<Script>(obj), v);
  543. }
  544. updating = false;
  545. return false;
  546. } else if (hint == PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) {
  547. MAKE_PROPSELECT
  548. Variant::Type type = Variant::NIL;
  549. String tname = hint_text;
  550. if (tname.find(".") != -1) {
  551. tname = tname.get_slice(".", 0);
  552. }
  553. for (int i = 0; i < Variant::VARIANT_MAX; i++) {
  554. if (tname == Variant::get_type_name(Variant::Type(i))) {
  555. type = Variant::Type(Variant::Type(i));
  556. }
  557. }
  558. if (type != Variant::NIL) {
  559. property_select->select_property_from_basic_type(type, v);
  560. }
  561. updating = false;
  562. return false;
  563. } else if (hint == PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) {
  564. MAKE_PROPSELECT
  565. property_select->select_property_from_base_type(hint_text, v);
  566. updating = false;
  567. return false;
  568. } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) {
  569. MAKE_PROPSELECT
  570. Object *instance = ObjectDB::get_instance(hint_text.to_int64());
  571. if (instance) {
  572. property_select->select_property_from_instance(instance, v);
  573. }
  574. updating = false;
  575. return false;
  576. } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) {
  577. MAKE_PROPSELECT
  578. Object *obj = ObjectDB::get_instance(hint_text.to_int64());
  579. if (Object::cast_to<Script>(obj)) {
  580. property_select->select_property_from_script(Object::cast_to<Script>(obj), v);
  581. }
  582. updating = false;
  583. return false;
  584. } else {
  585. List<String> names;
  586. names.push_back("string:");
  587. config_value_editors(1, 1, 50, names);
  588. value_editor[0]->set_text(v);
  589. }
  590. } break;
  591. case Variant::VECTOR2: {
  592. field_names.push_back("x");
  593. field_names.push_back("y");
  594. config_value_editors(2, 2, 10, field_names);
  595. Vector2 vec = v;
  596. value_editor[0]->set_text(String::num(vec.x));
  597. value_editor[1]->set_text(String::num(vec.y));
  598. } break;
  599. case Variant::RECT2: {
  600. field_names.push_back("x");
  601. field_names.push_back("y");
  602. field_names.push_back("w");
  603. field_names.push_back("h");
  604. config_value_editors(4, 4, 10, field_names);
  605. Rect2 r = v;
  606. value_editor[0]->set_text(String::num(r.position.x));
  607. value_editor[1]->set_text(String::num(r.position.y));
  608. value_editor[2]->set_text(String::num(r.size.x));
  609. value_editor[3]->set_text(String::num(r.size.y));
  610. } break;
  611. case Variant::VECTOR3: {
  612. field_names.push_back("x");
  613. field_names.push_back("y");
  614. field_names.push_back("z");
  615. config_value_editors(3, 3, 10, field_names);
  616. Vector3 vec = v;
  617. value_editor[0]->set_text(String::num(vec.x));
  618. value_editor[1]->set_text(String::num(vec.y));
  619. value_editor[2]->set_text(String::num(vec.z));
  620. } break;
  621. case Variant::PLANE: {
  622. field_names.push_back("x");
  623. field_names.push_back("y");
  624. field_names.push_back("z");
  625. field_names.push_back("d");
  626. config_value_editors(4, 4, 10, field_names);
  627. Plane plane = v;
  628. value_editor[0]->set_text(String::num(plane.normal.x));
  629. value_editor[1]->set_text(String::num(plane.normal.y));
  630. value_editor[2]->set_text(String::num(plane.normal.z));
  631. value_editor[3]->set_text(String::num(plane.d));
  632. } break;
  633. case Variant::QUAT: {
  634. field_names.push_back("x");
  635. field_names.push_back("y");
  636. field_names.push_back("z");
  637. field_names.push_back("w");
  638. config_value_editors(4, 4, 10, field_names);
  639. Quat q = v;
  640. value_editor[0]->set_text(String::num(q.x));
  641. value_editor[1]->set_text(String::num(q.y));
  642. value_editor[2]->set_text(String::num(q.z));
  643. value_editor[3]->set_text(String::num(q.w));
  644. } break;
  645. case Variant::AABB: {
  646. field_names.push_back("px");
  647. field_names.push_back("py");
  648. field_names.push_back("pz");
  649. field_names.push_back("sx");
  650. field_names.push_back("sy");
  651. field_names.push_back("sz");
  652. config_value_editors(6, 3, 16, field_names);
  653. AABB aabb = v;
  654. value_editor[0]->set_text(String::num(aabb.position.x));
  655. value_editor[1]->set_text(String::num(aabb.position.y));
  656. value_editor[2]->set_text(String::num(aabb.position.z));
  657. value_editor[3]->set_text(String::num(aabb.size.x));
  658. value_editor[4]->set_text(String::num(aabb.size.y));
  659. value_editor[5]->set_text(String::num(aabb.size.z));
  660. } break;
  661. case Variant::TRANSFORM2D: {
  662. field_names.push_back("xx");
  663. field_names.push_back("xy");
  664. field_names.push_back("yx");
  665. field_names.push_back("yy");
  666. field_names.push_back("ox");
  667. field_names.push_back("oy");
  668. config_value_editors(6, 2, 16, field_names);
  669. Transform2D basis = v;
  670. for (int i = 0; i < 6; i++) {
  671. value_editor[i]->set_text(String::num(basis.elements[i / 2][i % 2]));
  672. }
  673. } break;
  674. case Variant::BASIS: {
  675. field_names.push_back("xx");
  676. field_names.push_back("xy");
  677. field_names.push_back("xz");
  678. field_names.push_back("yx");
  679. field_names.push_back("yy");
  680. field_names.push_back("yz");
  681. field_names.push_back("zx");
  682. field_names.push_back("zy");
  683. field_names.push_back("zz");
  684. config_value_editors(9, 3, 16, field_names);
  685. Basis basis = v;
  686. for (int i = 0; i < 9; i++) {
  687. value_editor[i]->set_text(String::num(basis.elements[i / 3][i % 3]));
  688. }
  689. } break;
  690. case Variant::TRANSFORM: {
  691. field_names.push_back("xx");
  692. field_names.push_back("xy");
  693. field_names.push_back("xz");
  694. field_names.push_back("xo");
  695. field_names.push_back("yx");
  696. field_names.push_back("yy");
  697. field_names.push_back("yz");
  698. field_names.push_back("yo");
  699. field_names.push_back("zx");
  700. field_names.push_back("zy");
  701. field_names.push_back("zz");
  702. field_names.push_back("zo");
  703. config_value_editors(12, 4, 16, field_names);
  704. Transform tr = v;
  705. for (int i = 0; i < 9; i++) {
  706. value_editor[(i / 3) * 4 + i % 3]->set_text(String::num(tr.basis.elements[i / 3][i % 3]));
  707. }
  708. value_editor[3]->set_text(String::num(tr.origin.x));
  709. value_editor[7]->set_text(String::num(tr.origin.y));
  710. value_editor[11]->set_text(String::num(tr.origin.z));
  711. } break;
  712. case Variant::COLOR: {
  713. if (!color_picker) {
  714. //late init for performance
  715. color_picker = memnew(ColorPicker);
  716. color_picker->set_deferred_mode(true);
  717. add_child(color_picker);
  718. color_picker->hide();
  719. color_picker->connect("color_changed", this, "_color_changed");
  720. // get default color picker mode from editor settings
  721. int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
  722. if (default_color_mode == 1) {
  723. color_picker->set_hsv_mode(true);
  724. } else if (default_color_mode == 2) {
  725. color_picker->set_raw_mode(true);
  726. }
  727. }
  728. color_picker->show();
  729. color_picker->set_edit_alpha(hint != PROPERTY_HINT_COLOR_NO_ALPHA);
  730. color_picker->set_pick_color(v);
  731. color_picker->set_focus_on_line_edit();
  732. } break;
  733. case Variant::NODE_PATH: {
  734. List<String> names;
  735. names.push_back(TTR("Assign"));
  736. names.push_back(TTR("Clear"));
  737. if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) {
  738. names.push_back(TTR("Select Node"));
  739. }
  740. config_action_buttons(names);
  741. } break;
  742. case Variant::OBJECT: {
  743. if (hint != PROPERTY_HINT_RESOURCE_TYPE) {
  744. break;
  745. }
  746. if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) {
  747. menu->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
  748. menu->add_separator();
  749. } else if (hint_text != "") {
  750. int idx = 0;
  751. Vector<EditorData::CustomType> custom_resources;
  752. if (EditorNode::get_editor_data().get_custom_types().has("Resource")) {
  753. custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"];
  754. }
  755. for (int i = 0; i < hint_text.get_slice_count(","); i++) {
  756. String base = hint_text.get_slice(",", i);
  757. Set<String> valid_inheritors;
  758. valid_inheritors.insert(base);
  759. List<StringName> inheritors;
  760. ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors);
  761. for (int j = 0; j < custom_resources.size(); j++) {
  762. inheritors.push_back(custom_resources[j].name);
  763. }
  764. List<StringName>::Element *E = inheritors.front();
  765. while (E) {
  766. valid_inheritors.insert(E->get());
  767. E = E->next();
  768. }
  769. for (Set<String>::Element *j = valid_inheritors.front(); j; j = j->next()) {
  770. const String &t = j->get();
  771. bool is_custom_resource = false;
  772. Ref<Texture> icon;
  773. if (!custom_resources.empty()) {
  774. for (int k = 0; k < custom_resources.size(); k++) {
  775. if (custom_resources[k].name == t) {
  776. is_custom_resource = true;
  777. if (custom_resources[k].icon.is_valid()) {
  778. icon = custom_resources[k].icon;
  779. }
  780. break;
  781. }
  782. }
  783. }
  784. if (!is_custom_resource && !ClassDB::can_instance(t)) {
  785. continue;
  786. }
  787. inheritors_array.push_back(t);
  788. int id = TYPE_BASE_ID + idx;
  789. if (!icon.is_valid() && has_icon(t, "EditorIcons")) {
  790. icon = get_icon(t, "EditorIcons");
  791. }
  792. if (icon.is_valid()) {
  793. menu->add_icon_item(icon, vformat(TTR("New %s"), t), id);
  794. } else {
  795. menu->add_item(vformat(TTR("New %s"), t), id);
  796. }
  797. idx++;
  798. }
  799. }
  800. if (menu->get_item_count()) {
  801. menu->add_separator();
  802. }
  803. }
  804. menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD);
  805. if (!RES(v).is_null()) {
  806. menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
  807. menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
  808. menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
  809. RES r = v;
  810. if (r.is_valid() && r->get_path().is_resource_file()) {
  811. menu->add_separator();
  812. menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM);
  813. }
  814. }
  815. RES cb = EditorSettings::get_singleton()->get_resource_clipboard();
  816. bool paste_valid = false;
  817. if (cb.is_valid()) {
  818. if (hint_text == "") {
  819. paste_valid = true;
  820. } else {
  821. for (int i = 0; i < hint_text.get_slice_count(","); i++) {
  822. if (ClassDB::is_parent_class(cb->get_class(), hint_text.get_slice(",", i))) {
  823. paste_valid = true;
  824. break;
  825. }
  826. }
  827. }
  828. }
  829. if (!RES(v).is_null() || paste_valid) {
  830. menu->add_separator();
  831. if (!RES(v).is_null()) {
  832. menu->add_item(TTR("Copy"), OBJ_MENU_COPY);
  833. }
  834. if (paste_valid) {
  835. menu->add_item(TTR("Paste"), OBJ_MENU_PASTE);
  836. }
  837. }
  838. if (!RES(v).is_null()) {
  839. Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(RES(v));
  840. if (conversions.size()) {
  841. menu->add_separator();
  842. }
  843. for (int i = 0; i < conversions.size(); i++) {
  844. String what = conversions[i]->converts_to();
  845. Ref<Texture> icon;
  846. if (has_icon(what, "EditorIcons")) {
  847. icon = get_icon(what, "EditorIcons");
  848. } else {
  849. icon = get_icon(what, "Resource");
  850. }
  851. menu->add_icon_item(icon, vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
  852. }
  853. }
  854. menu->set_position(get_position());
  855. menu->popup();
  856. hide();
  857. updating = false;
  858. return false;
  859. } break;
  860. case Variant::DICTIONARY: {
  861. } break;
  862. case Variant::POOL_BYTE_ARRAY: {
  863. } break;
  864. case Variant::POOL_INT_ARRAY: {
  865. } break;
  866. case Variant::POOL_REAL_ARRAY: {
  867. } break;
  868. case Variant::POOL_STRING_ARRAY: {
  869. } break;
  870. case Variant::POOL_VECTOR3_ARRAY: {
  871. } break;
  872. case Variant::POOL_COLOR_ARRAY: {
  873. } break;
  874. default: {
  875. }
  876. }
  877. updating = false;
  878. return true;
  879. }
  880. void CustomPropertyEditor::_file_selected(String p_file) {
  881. switch (type) {
  882. case Variant::STRING: {
  883. if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_DIR) {
  884. v = ProjectSettings::get_singleton()->localize_path(p_file);
  885. emit_signal("variant_changed");
  886. hide();
  887. }
  888. if (hint == PROPERTY_HINT_GLOBAL_FILE || hint == PROPERTY_HINT_GLOBAL_DIR) {
  889. v = p_file;
  890. emit_signal("variant_changed");
  891. hide();
  892. }
  893. } break;
  894. case Variant::OBJECT: {
  895. String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
  896. RES res = ResourceLoader::load(p_file, type);
  897. if (res.is_null()) {
  898. error->set_text(TTR("Error loading file: Not a resource!"));
  899. error->popup_centered_minsize();
  900. break;
  901. }
  902. v = res.get_ref_ptr();
  903. emit_signal("variant_changed");
  904. hide();
  905. } break;
  906. default: {
  907. }
  908. }
  909. }
  910. void CustomPropertyEditor::_locale_selected(String p_locale) {
  911. if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) {
  912. v = p_locale;
  913. emit_signal("variant_changed");
  914. hide();
  915. }
  916. }
  917. void CustomPropertyEditor::_type_create_selected(int p_idx) {
  918. if (type == Variant::INT || type == Variant::REAL) {
  919. float newval = 0;
  920. switch (p_idx) {
  921. case EASING_LINEAR: {
  922. newval = 1;
  923. } break;
  924. case EASING_EASE_IN: {
  925. newval = 2.0;
  926. } break;
  927. case EASING_EASE_OUT: {
  928. newval = 0.5;
  929. } break;
  930. case EASING_ZERO: {
  931. newval = 0;
  932. } break;
  933. case EASING_IN_OUT: {
  934. newval = -0.5;
  935. } break;
  936. case EASING_OUT_IN: {
  937. newval = -2.0;
  938. } break;
  939. }
  940. v = newval;
  941. emit_signal("variant_changed");
  942. easing_draw->update();
  943. } else if (type == Variant::OBJECT) {
  944. ERR_FAIL_INDEX(p_idx, inheritors_array.size());
  945. String intype = inheritors_array[p_idx];
  946. Variant obj = ClassDB::instance(intype);
  947. if (!obj) {
  948. if (ScriptServer::is_global_class(intype)) {
  949. obj = EditorNode::get_editor_data().script_class_instance(intype);
  950. } else {
  951. obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
  952. }
  953. }
  954. ERR_FAIL_COND(!obj);
  955. ERR_FAIL_COND(!Object::cast_to<Resource>(obj));
  956. v = obj;
  957. emit_signal("variant_changed");
  958. hide();
  959. }
  960. }
  961. void CustomPropertyEditor::_color_changed(const Color &p_color) {
  962. v = p_color;
  963. emit_signal("variant_changed");
  964. }
  965. void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
  966. if (picking_viewport) {
  967. Node *to_node = get_node(p_path);
  968. if (!Object::cast_to<Viewport>(to_node)) {
  969. EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!"));
  970. return;
  971. }
  972. Ref<ViewportTexture> vt;
  973. vt.instance();
  974. vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
  975. vt->setup_local_to_scene();
  976. v = vt;
  977. emit_signal("variant_changed");
  978. return;
  979. }
  980. if (hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && hint_text != String()) {
  981. Node *node = get_node(hint_text);
  982. if (node) {
  983. Node *tonode = node->get_node(p_path);
  984. if (tonode) {
  985. p_path = node->get_path_to(tonode);
  986. }
  987. }
  988. } else if (owner) {
  989. Node *node = nullptr;
  990. if (owner->is_class("Node")) {
  991. node = Object::cast_to<Node>(owner);
  992. } else if (owner->is_class("ArrayPropertyEdit")) {
  993. node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node();
  994. } else if (owner->is_class("DictionaryPropertyEdit")) {
  995. node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node();
  996. }
  997. if (!node) {
  998. v = p_path;
  999. emit_signal("variant_changed");
  1000. call_deferred("hide"); //to not mess with dialogs
  1001. return;
  1002. }
  1003. Node *tonode = node->get_node(p_path);
  1004. if (tonode) {
  1005. p_path = node->get_path_to(tonode);
  1006. }
  1007. }
  1008. v = p_path;
  1009. emit_signal("variant_changed");
  1010. call_deferred("hide"); //to not mess with dialogs
  1011. }
  1012. void CustomPropertyEditor::_action_pressed(int p_which) {
  1013. if (updating) {
  1014. return;
  1015. }
  1016. switch (type) {
  1017. case Variant::BOOL: {
  1018. v = checks20[0]->is_pressed();
  1019. emit_signal("variant_changed");
  1020. } break;
  1021. case Variant::INT: {
  1022. if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
  1023. uint32_t f = v;
  1024. if (checks20[p_which]->is_pressed()) {
  1025. f |= (1 << p_which);
  1026. } else {
  1027. f &= ~(1 << p_which);
  1028. }
  1029. v = f;
  1030. emit_signal("variant_changed");
  1031. }
  1032. } break;
  1033. case Variant::STRING: {
  1034. if (hint == PROPERTY_HINT_MULTILINE_TEXT) {
  1035. hide();
  1036. } else if (hint == PROPERTY_HINT_LOCALE_ID) {
  1037. locale->popup_locale_dialog();
  1038. } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) {
  1039. if (p_which == 0) {
  1040. if (hint == PROPERTY_HINT_FILE) {
  1041. file->set_access(EditorFileDialog::ACCESS_RESOURCES);
  1042. } else {
  1043. file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
  1044. }
  1045. file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1046. file->clear_filters();
  1047. file->clear_filters();
  1048. if (hint_text != "") {
  1049. Vector<String> extensions = hint_text.split(",");
  1050. for (int i = 0; i < extensions.size(); i++) {
  1051. String filter = extensions[i];
  1052. if (filter.begins_with(".")) {
  1053. filter = "*" + extensions[i];
  1054. } else if (!filter.begins_with("*")) {
  1055. filter = "*." + extensions[i];
  1056. }
  1057. file->add_filter(filter + " ; " + extensions[i].to_upper());
  1058. }
  1059. }
  1060. file->popup_centered_ratio();
  1061. } else {
  1062. v = "";
  1063. emit_signal("variant_changed");
  1064. hide();
  1065. }
  1066. } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) {
  1067. if (p_which == 0) {
  1068. if (hint == PROPERTY_HINT_DIR) {
  1069. file->set_access(EditorFileDialog::ACCESS_RESOURCES);
  1070. } else {
  1071. file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
  1072. }
  1073. file->set_mode(EditorFileDialog::MODE_OPEN_DIR);
  1074. file->clear_filters();
  1075. file->popup_centered_ratio();
  1076. } else {
  1077. v = "";
  1078. emit_signal("variant_changed");
  1079. hide();
  1080. }
  1081. }
  1082. } break;
  1083. case Variant::NODE_PATH: {
  1084. if (p_which == 0) {
  1085. picking_viewport = false;
  1086. scene_tree->set_title(TTR("Pick a Node"));
  1087. scene_tree->popup_centered_ratio();
  1088. } else if (p_which == 1) {
  1089. v = NodePath();
  1090. emit_signal("variant_changed");
  1091. hide();
  1092. } else if (p_which == 2) {
  1093. if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) {
  1094. Node *target_node = Object::cast_to<Node>(owner)->get_node(v);
  1095. EditorNode::get_singleton()->get_editor_selection()->clear();
  1096. EditorNode::get_singleton()->get_scene_tree_dock()->set_selected(target_node);
  1097. }
  1098. hide();
  1099. }
  1100. } break;
  1101. case Variant::OBJECT: {
  1102. if (p_which == 0) {
  1103. ERR_FAIL_COND(inheritors_array.empty());
  1104. String intype = inheritors_array[0];
  1105. if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
  1106. Variant obj = ClassDB::instance(intype);
  1107. if (!obj) {
  1108. if (ScriptServer::is_global_class(intype)) {
  1109. obj = EditorNode::get_editor_data().script_class_instance(intype);
  1110. } else {
  1111. obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
  1112. }
  1113. }
  1114. ERR_BREAK(!obj);
  1115. ERR_BREAK(!Object::cast_to<Resource>(obj));
  1116. v = obj;
  1117. emit_signal("variant_changed");
  1118. hide();
  1119. }
  1120. } else if (p_which == 1) {
  1121. file->set_access(EditorFileDialog::ACCESS_RESOURCES);
  1122. file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1123. List<String> extensions;
  1124. String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
  1125. ResourceLoader::get_recognized_extensions_for_type(type, &extensions);
  1126. file->clear_filters();
  1127. for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
  1128. file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
  1129. }
  1130. file->popup_centered_ratio();
  1131. } else if (p_which == 2) {
  1132. RefPtr RefPtr = v;
  1133. if (!RefPtr.is_null()) {
  1134. emit_signal("resource_edit_request");
  1135. hide();
  1136. }
  1137. } else if (p_which == 3) {
  1138. v = Variant();
  1139. emit_signal("variant_changed");
  1140. hide();
  1141. } else if (p_which == 4) {
  1142. RefPtr RefPtr = v;
  1143. Ref<Resource> res_orig = RefPtr;
  1144. if (res_orig.is_null()) {
  1145. return;
  1146. }
  1147. List<PropertyInfo> property_list;
  1148. res_orig->get_property_list(&property_list);
  1149. List<Pair<String, Variant>> propvalues;
  1150. for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
  1151. Pair<String, Variant> p;
  1152. PropertyInfo &pi = E->get();
  1153. if (pi.usage & PROPERTY_USAGE_STORAGE) {
  1154. p.first = pi.name;
  1155. p.second = res_orig->get(pi.name);
  1156. }
  1157. propvalues.push_back(p);
  1158. }
  1159. Ref<Resource> res = Ref<Resource>(ClassDB::instance(res_orig->get_class()));
  1160. ERR_FAIL_COND(res.is_null());
  1161. for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
  1162. Pair<String, Variant> &p = E->get();
  1163. res->set(p.first, p.second);
  1164. }
  1165. v = res.get_ref_ptr();
  1166. emit_signal("variant_changed");
  1167. hide();
  1168. }
  1169. } break;
  1170. default: {
  1171. };
  1172. }
  1173. }
  1174. void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) {
  1175. Ref<InputEventMouseMotion> mm = p_ev;
  1176. if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
  1177. float rel = mm->get_relative().x;
  1178. if (rel == 0) {
  1179. return;
  1180. }
  1181. bool flip = hint_text == "attenuation";
  1182. if (flip) {
  1183. rel = -rel;
  1184. }
  1185. float val = v;
  1186. if (val == 0) {
  1187. return;
  1188. }
  1189. bool sg = val < 0;
  1190. val = Math::absf(val);
  1191. val = Math::log(val) / Math::log((float)2.0);
  1192. //logspace
  1193. val += rel * 0.05;
  1194. val = Math::pow(2.0f, val);
  1195. if (sg) {
  1196. val = -val;
  1197. }
  1198. v = val;
  1199. easing_draw->update();
  1200. emit_signal("variant_changed");
  1201. }
  1202. }
  1203. void CustomPropertyEditor::_draw_easing() {
  1204. RID ci = easing_draw->get_canvas_item();
  1205. Size2 s = easing_draw->get_size();
  1206. Rect2 r(Point2(), s);
  1207. r = r.grow(3);
  1208. get_stylebox("normal", "LineEdit")->draw(ci, r);
  1209. int points = 48;
  1210. float prev = 1.0;
  1211. float exp = v;
  1212. bool flip = hint_text == "attenuation";
  1213. Ref<Font> f = get_font("font", "Label");
  1214. Color color = get_color("font_color", "Label");
  1215. for (int i = 1; i <= points; i++) {
  1216. float ifl = i / float(points);
  1217. float iflp = (i - 1) / float(points);
  1218. float h = 1.0 - Math::ease(ifl, exp);
  1219. if (flip) {
  1220. ifl = 1.0 - ifl;
  1221. iflp = 1.0 - iflp;
  1222. }
  1223. VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color);
  1224. prev = h;
  1225. }
  1226. f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), color);
  1227. }
  1228. void CustomPropertyEditor::_text_edit_changed() {
  1229. v = text_edit->get_text();
  1230. emit_signal("variant_changed");
  1231. }
  1232. void CustomPropertyEditor::_create_dialog_callback() {
  1233. v = create_dialog->get_selected_type();
  1234. emit_signal("variant_changed");
  1235. }
  1236. void CustomPropertyEditor::_create_selected_property(const String &p_prop) {
  1237. v = p_prop;
  1238. emit_signal("variant_changed");
  1239. }
  1240. void CustomPropertyEditor::_modified(String p_string) {
  1241. if (updating) {
  1242. return;
  1243. }
  1244. updating = true;
  1245. switch (type) {
  1246. case Variant::INT: {
  1247. String text = value_editor[0]->get_text();
  1248. Ref<Expression> expr;
  1249. expr.instance();
  1250. Error err = expr->parse(text);
  1251. if (err != OK) {
  1252. v = value_editor[0]->get_text().to_int();
  1253. return;
  1254. } else {
  1255. v = expr->execute(Array(), nullptr, false);
  1256. }
  1257. emit_signal("variant_changed");
  1258. } break;
  1259. case Variant::REAL: {
  1260. if (hint != PROPERTY_HINT_EXP_EASING) {
  1261. String text = value_editor[0]->get_text();
  1262. v = _parse_real_expression(text);
  1263. emit_signal("variant_changed");
  1264. }
  1265. } break;
  1266. case Variant::STRING: {
  1267. v = value_editor[0]->get_text();
  1268. emit_signal("variant_changed");
  1269. } break;
  1270. case Variant::VECTOR2: {
  1271. Vector2 vec;
  1272. vec.x = _parse_real_expression(value_editor[0]->get_text());
  1273. vec.y = _parse_real_expression(value_editor[1]->get_text());
  1274. v = vec;
  1275. _emit_changed_whole_or_field();
  1276. } break;
  1277. case Variant::RECT2: {
  1278. Rect2 r2;
  1279. r2.position.x = _parse_real_expression(value_editor[0]->get_text());
  1280. r2.position.y = _parse_real_expression(value_editor[1]->get_text());
  1281. r2.size.x = _parse_real_expression(value_editor[2]->get_text());
  1282. r2.size.y = _parse_real_expression(value_editor[3]->get_text());
  1283. v = r2;
  1284. _emit_changed_whole_or_field();
  1285. } break;
  1286. case Variant::VECTOR3: {
  1287. Vector3 vec;
  1288. vec.x = _parse_real_expression(value_editor[0]->get_text());
  1289. vec.y = _parse_real_expression(value_editor[1]->get_text());
  1290. vec.z = _parse_real_expression(value_editor[2]->get_text());
  1291. v = vec;
  1292. _emit_changed_whole_or_field();
  1293. } break;
  1294. case Variant::PLANE: {
  1295. Plane pl;
  1296. pl.normal.x = _parse_real_expression(value_editor[0]->get_text());
  1297. pl.normal.y = _parse_real_expression(value_editor[1]->get_text());
  1298. pl.normal.z = _parse_real_expression(value_editor[2]->get_text());
  1299. pl.d = _parse_real_expression(value_editor[3]->get_text());
  1300. v = pl;
  1301. _emit_changed_whole_or_field();
  1302. } break;
  1303. case Variant::QUAT: {
  1304. Quat q;
  1305. q.x = _parse_real_expression(value_editor[0]->get_text());
  1306. q.y = _parse_real_expression(value_editor[1]->get_text());
  1307. q.z = _parse_real_expression(value_editor[2]->get_text());
  1308. q.w = _parse_real_expression(value_editor[3]->get_text());
  1309. v = q;
  1310. _emit_changed_whole_or_field();
  1311. } break;
  1312. case Variant::AABB: {
  1313. Vector3 pos;
  1314. Vector3 size;
  1315. pos.x = _parse_real_expression(value_editor[0]->get_text());
  1316. pos.y = _parse_real_expression(value_editor[1]->get_text());
  1317. pos.z = _parse_real_expression(value_editor[2]->get_text());
  1318. size.x = _parse_real_expression(value_editor[3]->get_text());
  1319. size.y = _parse_real_expression(value_editor[4]->get_text());
  1320. size.z = _parse_real_expression(value_editor[5]->get_text());
  1321. v = AABB(pos, size);
  1322. _emit_changed_whole_or_field();
  1323. } break;
  1324. case Variant::TRANSFORM2D: {
  1325. Transform2D m;
  1326. for (int i = 0; i < 6; i++) {
  1327. m.elements[i / 2][i % 2] = _parse_real_expression(value_editor[i]->get_text());
  1328. }
  1329. v = m;
  1330. _emit_changed_whole_or_field();
  1331. } break;
  1332. case Variant::BASIS: {
  1333. Basis m;
  1334. for (int i = 0; i < 9; i++) {
  1335. m.elements[i / 3][i % 3] = _parse_real_expression(value_editor[i]->get_text());
  1336. }
  1337. v = m;
  1338. _emit_changed_whole_or_field();
  1339. } break;
  1340. case Variant::TRANSFORM: {
  1341. Basis basis;
  1342. for (int i = 0; i < 9; i++) {
  1343. basis.elements[i / 3][i % 3] = _parse_real_expression(value_editor[(i / 3) * 4 + i % 3]->get_text());
  1344. }
  1345. Vector3 origin;
  1346. origin.x = _parse_real_expression(value_editor[3]->get_text());
  1347. origin.y = _parse_real_expression(value_editor[7]->get_text());
  1348. origin.z = _parse_real_expression(value_editor[11]->get_text());
  1349. v = Transform(basis, origin);
  1350. _emit_changed_whole_or_field();
  1351. } break;
  1352. case Variant::COLOR: {
  1353. } break;
  1354. case Variant::NODE_PATH: {
  1355. v = NodePath(value_editor[0]->get_text());
  1356. emit_signal("variant_changed");
  1357. } break;
  1358. case Variant::DICTIONARY: {
  1359. } break;
  1360. case Variant::POOL_BYTE_ARRAY: {
  1361. } break;
  1362. case Variant::POOL_INT_ARRAY: {
  1363. } break;
  1364. case Variant::POOL_REAL_ARRAY: {
  1365. } break;
  1366. case Variant::POOL_STRING_ARRAY: {
  1367. } break;
  1368. case Variant::POOL_VECTOR3_ARRAY: {
  1369. } break;
  1370. case Variant::POOL_COLOR_ARRAY: {
  1371. } break;
  1372. default: {
  1373. }
  1374. }
  1375. updating = false;
  1376. }
  1377. real_t CustomPropertyEditor::_parse_real_expression(String text) {
  1378. Ref<Expression> expr;
  1379. expr.instance();
  1380. Error err = expr->parse(text);
  1381. real_t out;
  1382. if (err != OK) {
  1383. out = value_editor[0]->get_text().to_double();
  1384. } else {
  1385. out = expr->execute(Array(), nullptr, false);
  1386. }
  1387. return out;
  1388. }
  1389. void CustomPropertyEditor::_emit_changed_whole_or_field() {
  1390. if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
  1391. emit_signal("variant_changed");
  1392. } else {
  1393. emit_signal("variant_field_changed", field_names[focused_value_editor]);
  1394. }
  1395. }
  1396. void CustomPropertyEditor::_range_modified(double p_value) {
  1397. v = p_value;
  1398. emit_signal("variant_changed");
  1399. }
  1400. void CustomPropertyEditor::_focus_enter() {
  1401. switch (type) {
  1402. case Variant::REAL:
  1403. case Variant::STRING:
  1404. case Variant::VECTOR2:
  1405. case Variant::RECT2:
  1406. case Variant::VECTOR3:
  1407. case Variant::PLANE:
  1408. case Variant::QUAT:
  1409. case Variant::AABB:
  1410. case Variant::TRANSFORM2D:
  1411. case Variant::BASIS:
  1412. case Variant::TRANSFORM: {
  1413. for (int i = 0; i < MAX_VALUE_EDITORS; ++i) {
  1414. if (value_editor[i]->has_focus()) {
  1415. focused_value_editor = i;
  1416. value_editor[i]->select_all();
  1417. break;
  1418. }
  1419. }
  1420. } break;
  1421. default: {
  1422. }
  1423. }
  1424. }
  1425. void CustomPropertyEditor::_focus_exit() {
  1426. switch (type) {
  1427. case Variant::REAL:
  1428. case Variant::STRING:
  1429. case Variant::VECTOR2:
  1430. case Variant::RECT2:
  1431. case Variant::VECTOR3:
  1432. case Variant::PLANE:
  1433. case Variant::QUAT:
  1434. case Variant::AABB:
  1435. case Variant::TRANSFORM2D:
  1436. case Variant::BASIS:
  1437. case Variant::TRANSFORM: {
  1438. for (int i = 0; i < MAX_VALUE_EDITORS; ++i) {
  1439. value_editor[i]->select(0, 0);
  1440. }
  1441. } break;
  1442. default: {
  1443. }
  1444. }
  1445. }
  1446. void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
  1447. Ref<StyleBox> sb = get_stylebox("panel");
  1448. int margin_top = sb->get_margin(MARGIN_TOP);
  1449. int margin_left = sb->get_margin(MARGIN_LEFT);
  1450. int margin_bottom = sb->get_margin(MARGIN_BOTTOM);
  1451. int margin_right = sb->get_margin(MARGIN_RIGHT);
  1452. int max_width = 0;
  1453. int height = 0;
  1454. for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
  1455. if (i < p_strings.size()) {
  1456. action_buttons[i]->show();
  1457. action_buttons[i]->set_text(p_strings[i]);
  1458. Size2 btn_m_size = action_buttons[i]->get_minimum_size();
  1459. if (btn_m_size.width > max_width) {
  1460. max_width = btn_m_size.width;
  1461. }
  1462. } else {
  1463. action_buttons[i]->hide();
  1464. }
  1465. }
  1466. for (int i = 0; i < p_strings.size(); i++) {
  1467. Size2 btn_m_size = action_buttons[i]->get_size();
  1468. action_buttons[i]->set_position(Point2(0, height) + Point2(margin_left, margin_top));
  1469. action_buttons[i]->set_size(Size2(max_width, btn_m_size.height));
  1470. height += btn_m_size.height;
  1471. }
  1472. set_size(Size2(max_width, height) + Size2(margin_left + margin_right, margin_top + margin_bottom));
  1473. }
  1474. void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) {
  1475. int cell_width = 95;
  1476. int cell_height = 25;
  1477. int cell_margin = 5;
  1478. int hor_spacing = 5; // Spacing between labels and their values
  1479. int rows = ((p_amount - 1) / p_columns) + 1;
  1480. set_size(Size2(cell_margin + p_label_w + (cell_width + cell_margin + p_label_w) * p_columns, cell_margin + (cell_height + cell_margin) * rows) * EDSCALE);
  1481. for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
  1482. int c = i % p_columns;
  1483. int r = i / p_columns;
  1484. if (i < p_amount) {
  1485. value_editor[i]->show();
  1486. value_label[i]->show();
  1487. value_label[i]->set_text(i < p_strings.size() ? p_strings[i] : String(""));
  1488. value_editor[i]->set_position(Point2(cell_margin + p_label_w + hor_spacing + (cell_width + cell_margin + p_label_w + hor_spacing) * c, cell_margin + (cell_height + cell_margin) * r) * EDSCALE);
  1489. value_editor[i]->set_size(Size2(cell_width, cell_height));
  1490. value_label[i]->set_position(Point2(cell_margin + (cell_width + cell_margin + p_label_w + hor_spacing) * c, cell_margin + (cell_height + cell_margin) * r) * EDSCALE);
  1491. value_editor[i]->set_editable(!read_only);
  1492. } else {
  1493. value_editor[i]->hide();
  1494. value_label[i]->hide();
  1495. }
  1496. }
  1497. }
  1498. void CustomPropertyEditor::_bind_methods() {
  1499. ClassDB::bind_method("_focus_enter", &CustomPropertyEditor::_focus_enter);
  1500. ClassDB::bind_method("_focus_exit", &CustomPropertyEditor::_focus_exit);
  1501. ClassDB::bind_method("_modified", &CustomPropertyEditor::_modified);
  1502. ClassDB::bind_method("_range_modified", &CustomPropertyEditor::_range_modified);
  1503. ClassDB::bind_method("_action_pressed", &CustomPropertyEditor::_action_pressed);
  1504. ClassDB::bind_method("_file_selected", &CustomPropertyEditor::_file_selected);
  1505. ClassDB::bind_method("_locale_selected", &CustomPropertyEditor::_locale_selected);
  1506. ClassDB::bind_method("_type_create_selected", &CustomPropertyEditor::_type_create_selected);
  1507. ClassDB::bind_method("_node_path_selected", &CustomPropertyEditor::_node_path_selected);
  1508. ClassDB::bind_method("_color_changed", &CustomPropertyEditor::_color_changed);
  1509. ClassDB::bind_method("_draw_easing", &CustomPropertyEditor::_draw_easing);
  1510. ClassDB::bind_method("_drag_easing", &CustomPropertyEditor::_drag_easing);
  1511. ClassDB::bind_method("_text_edit_changed", &CustomPropertyEditor::_text_edit_changed);
  1512. ClassDB::bind_method("_menu_option", &CustomPropertyEditor::_menu_option);
  1513. ClassDB::bind_method("_create_dialog_callback", &CustomPropertyEditor::_create_dialog_callback);
  1514. ClassDB::bind_method("_create_selected_property", &CustomPropertyEditor::_create_selected_property);
  1515. ADD_SIGNAL(MethodInfo("variant_changed"));
  1516. ADD_SIGNAL(MethodInfo("variant_field_changed", PropertyInfo(Variant::STRING, "field")));
  1517. ADD_SIGNAL(MethodInfo("resource_edit_request"));
  1518. }
  1519. CustomPropertyEditor::CustomPropertyEditor() {
  1520. read_only = false;
  1521. updating = false;
  1522. for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
  1523. value_editor[i] = memnew(LineEdit);
  1524. add_child(value_editor[i]);
  1525. value_label[i] = memnew(Label);
  1526. add_child(value_label[i]);
  1527. value_editor[i]->hide();
  1528. value_label[i]->hide();
  1529. value_editor[i]->connect("text_entered", this, "_modified");
  1530. value_editor[i]->connect("focus_entered", this, "_focus_enter");
  1531. value_editor[i]->connect("focus_exited", this, "_focus_exit");
  1532. }
  1533. focused_value_editor = -1;
  1534. for (int i = 0; i < 4; i++) {
  1535. scroll[i] = memnew(HScrollBar);
  1536. scroll[i]->hide();
  1537. scroll[i]->set_min(0);
  1538. scroll[i]->set_max(1.0);
  1539. scroll[i]->set_step(0.01);
  1540. add_child(scroll[i]);
  1541. }
  1542. checks20gc = memnew(GridContainer);
  1543. add_child(checks20gc);
  1544. checks20gc->set_columns(11);
  1545. for (int i = 0; i < 20; i++) {
  1546. if (i == 5 || i == 15) {
  1547. Control *space = memnew(Control);
  1548. space->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
  1549. checks20gc->add_child(space);
  1550. }
  1551. checks20[i] = memnew(CheckBox);
  1552. checks20[i]->set_toggle_mode(true);
  1553. checks20[i]->set_focus_mode(FOCUS_NONE);
  1554. checks20gc->add_child(checks20[i]);
  1555. checks20[i]->hide();
  1556. checks20[i]->connect("pressed", this, "_action_pressed", make_binds(i));
  1557. checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1 << i));
  1558. }
  1559. text_edit = memnew(TextEdit);
  1560. add_child(text_edit);
  1561. text_edit->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
  1562. text_edit->set_margin(MARGIN_BOTTOM, -30);
  1563. text_edit->hide();
  1564. text_edit->connect("text_changed", this, "_text_edit_changed");
  1565. for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
  1566. action_buttons[i] = memnew(Button);
  1567. action_buttons[i]->hide();
  1568. add_child(action_buttons[i]);
  1569. Vector<Variant> binds;
  1570. binds.push_back(i);
  1571. action_buttons[i]->connect("pressed", this, "_action_pressed", binds);
  1572. action_buttons[i]->set_flat(true);
  1573. }
  1574. color_picker = nullptr;
  1575. set_as_toplevel(true);
  1576. file = memnew(EditorFileDialog);
  1577. add_child(file);
  1578. file->hide();
  1579. file->connect("file_selected", this, "_file_selected");
  1580. file->connect("dir_selected", this, "_file_selected");
  1581. locale = memnew(EditorLocaleDialog);
  1582. add_child(locale);
  1583. locale->hide();
  1584. locale->connect("locale_selected", this, "_locale_selected");
  1585. error = memnew(ConfirmationDialog);
  1586. error->set_title(TTR("Error!"));
  1587. add_child(error);
  1588. scene_tree = memnew(SceneTreeDialog);
  1589. add_child(scene_tree);
  1590. scene_tree->connect("selected", this, "_node_path_selected");
  1591. scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
  1592. texture_preview = memnew(TextureRect);
  1593. add_child(texture_preview);
  1594. texture_preview->hide();
  1595. easing_draw = memnew(Control);
  1596. add_child(easing_draw);
  1597. easing_draw->hide();
  1598. easing_draw->connect("draw", this, "_draw_easing");
  1599. easing_draw->connect("gui_input", this, "_drag_easing");
  1600. easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE);
  1601. type_button = memnew(MenuButton);
  1602. add_child(type_button);
  1603. type_button->hide();
  1604. type_button->get_popup()->connect("id_pressed", this, "_type_create_selected");
  1605. menu = memnew(PopupMenu);
  1606. menu->set_pass_on_modal_close_click(false);
  1607. add_child(menu);
  1608. menu->connect("id_pressed", this, "_menu_option");
  1609. evaluator = nullptr;
  1610. spinbox = memnew(SpinBox);
  1611. add_child(spinbox);
  1612. spinbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
  1613. spinbox->connect("value_changed", this, "_range_modified");
  1614. slider = memnew(HSlider);
  1615. add_child(slider);
  1616. slider->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
  1617. slider->connect("value_changed", this, "_range_modified");
  1618. create_dialog = nullptr;
  1619. property_select = nullptr;
  1620. }