property_editor.cpp 54 KB

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