color_picker.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  1. /*************************************************************************/
  2. /* color_picker.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 "color_picker.h"
  31. #include "core/input/input.h"
  32. #include "core/os/keyboard.h"
  33. #include "core/os/os.h"
  34. #ifdef TOOLS_ENABLED
  35. #include "editor/editor_settings.h"
  36. #endif
  37. #include "scene/main/window.h"
  38. List<Color> ColorPicker::preset_cache;
  39. void ColorPicker::_notification(int p_what) {
  40. switch (p_what) {
  41. case NOTIFICATION_ENTER_TREE: {
  42. _update_color();
  43. #ifdef TOOLS_ENABLED
  44. if (Engine::get_singleton()->is_editor_hint()) {
  45. if (preset_cache.is_empty()) {
  46. PackedColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PackedColorArray());
  47. for (int i = 0; i < saved_presets.size(); i++) {
  48. preset_cache.push_back(saved_presets[i]);
  49. }
  50. }
  51. for (int i = 0; i < preset_cache.size(); i++) {
  52. presets.push_back(preset_cache[i]);
  53. }
  54. }
  55. #endif
  56. [[fallthrough]];
  57. }
  58. case NOTIFICATION_THEME_CHANGED: {
  59. btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
  60. btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
  61. uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
  62. w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0));
  63. wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
  64. wheel_margin->add_theme_constant_override("margin_bottom", 8 * get_theme_default_base_scale());
  65. for (int i = 0; i < 4; i++) {
  66. labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
  67. set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin")));
  68. }
  69. if (Engine::get_singleton()->is_editor_hint()) {
  70. // Adjust for the width of the "Script" icon.
  71. text_type->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0));
  72. }
  73. _update_presets();
  74. _update_controls();
  75. } break;
  76. case NOTIFICATION_VISIBILITY_CHANGED: {
  77. Popup *p = Object::cast_to<Popup>(get_parent());
  78. if (p) {
  79. p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant(SNAME("margin")) * 2, get_combined_minimum_size().height + get_theme_constant(SNAME("margin")) * 2));
  80. }
  81. } break;
  82. case NOTIFICATION_WM_CLOSE_REQUEST: {
  83. if (screen != nullptr && screen->is_visible()) {
  84. screen->hide();
  85. }
  86. } break;
  87. }
  88. }
  89. Ref<Shader> ColorPicker::wheel_shader;
  90. Ref<Shader> ColorPicker::circle_shader;
  91. void ColorPicker::init_shaders() {
  92. wheel_shader.instantiate();
  93. wheel_shader->set_code(R"(
  94. // ColorPicker wheel shader.
  95. shader_type canvas_item;
  96. void fragment() {
  97. float x = UV.x - 0.5;
  98. float y = UV.y - 0.5;
  99. float a = atan(y, x);
  100. x += 0.001;
  101. y += 0.001;
  102. float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
  103. x -= 0.002;
  104. float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
  105. y -= 0.002;
  106. float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
  107. x += 0.002;
  108. float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);
  109. COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);
  110. }
  111. )");
  112. circle_shader.instantiate();
  113. circle_shader->set_code(R"(
  114. // ColorPicker circle shader.
  115. shader_type canvas_item;
  116. uniform float v = 1.0;
  117. void fragment() {
  118. float x = UV.x - 0.5;
  119. float y = UV.y - 0.5;
  120. float a = atan(y, x);
  121. x += 0.001;
  122. y += 0.001;
  123. float b = float(sqrt(x * x + y * y) < 0.5);
  124. x -= 0.002;
  125. float b2 = float(sqrt(x * x + y * y) < 0.5);
  126. y -= 0.002;
  127. float b3 = float(sqrt(x * x + y * y) < 0.5);
  128. x += 0.002;
  129. float b4 = float(sqrt(x * x + y * y) < 0.5);
  130. COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);
  131. })");
  132. }
  133. void ColorPicker::finish_shaders() {
  134. wheel_shader.unref();
  135. circle_shader.unref();
  136. }
  137. void ColorPicker::set_focus_on_line_edit() {
  138. c_text->call_deferred(SNAME("grab_focus"));
  139. }
  140. void ColorPicker::_update_controls() {
  141. const char *rgb[3] = { "R", "G", "B" };
  142. const char *hsv[3] = { "H", "S", "V" };
  143. if (hsv_mode_enabled) {
  144. for (int i = 0; i < 3; i++) {
  145. labels[i]->set_text(hsv[i]);
  146. }
  147. } else {
  148. for (int i = 0; i < 3; i++) {
  149. labels[i]->set_text(rgb[i]);
  150. }
  151. }
  152. if (hsv_mode_enabled) {
  153. set_raw_mode(false);
  154. btn_raw->set_disabled(true);
  155. } else if (raw_mode_enabled) {
  156. set_hsv_mode(false);
  157. btn_hsv->set_disabled(true);
  158. } else {
  159. btn_raw->set_disabled(false);
  160. btn_hsv->set_disabled(false);
  161. }
  162. if (raw_mode_enabled) {
  163. for (int i = 0; i < 3; i++) {
  164. scroll[i]->remove_theme_icon_override("grabber");
  165. scroll[i]->remove_theme_icon_override("grabber_highlight");
  166. scroll[i]->remove_theme_style_override("slider");
  167. scroll[i]->remove_theme_style_override("grabber_area");
  168. scroll[i]->remove_theme_style_override("grabber_area_highlight");
  169. }
  170. } else {
  171. Ref<StyleBoxEmpty> style_box_empty(memnew(StyleBoxEmpty));
  172. Ref<Texture2D> bar_arrow = get_theme_icon(SNAME("bar_arrow"));
  173. for (int i = 0; i < 4; i++) {
  174. scroll[i]->add_theme_icon_override("grabber", bar_arrow);
  175. scroll[i]->add_theme_icon_override("grabber_highlight", bar_arrow);
  176. scroll[i]->add_theme_style_override("slider", style_box_empty);
  177. scroll[i]->add_theme_style_override("grabber_area", style_box_empty);
  178. scroll[i]->add_theme_style_override("grabber_area_highlight", style_box_empty);
  179. }
  180. }
  181. if (edit_alpha) {
  182. values[3]->show();
  183. scroll[3]->show();
  184. labels[3]->show();
  185. } else {
  186. values[3]->hide();
  187. scroll[3]->hide();
  188. labels[3]->hide();
  189. }
  190. switch (picker_type) {
  191. case SHAPE_HSV_RECTANGLE:
  192. wheel_edit->hide();
  193. w_edit->show();
  194. uv_edit->show();
  195. break;
  196. case SHAPE_HSV_WHEEL:
  197. wheel_edit->show();
  198. w_edit->hide();
  199. uv_edit->hide();
  200. wheel->set_material(wheel_mat);
  201. break;
  202. case SHAPE_VHS_CIRCLE:
  203. wheel_edit->show();
  204. w_edit->show();
  205. uv_edit->hide();
  206. wheel->set_material(circle_mat);
  207. break;
  208. default: {
  209. }
  210. }
  211. }
  212. void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) {
  213. color = p_color;
  214. if (color != last_hsv) {
  215. h = color.get_h();
  216. s = color.get_s();
  217. v = color.get_v();
  218. last_hsv = color;
  219. }
  220. if (!is_inside_tree()) {
  221. return;
  222. }
  223. _update_color(p_update_sliders);
  224. }
  225. void ColorPicker::set_pick_color(const Color &p_color) {
  226. _set_pick_color(p_color, true); //because setters can't have more arguments
  227. }
  228. void ColorPicker::set_old_color(const Color &p_color) {
  229. old_color = p_color;
  230. }
  231. void ColorPicker::set_display_old_color(bool p_enabled) {
  232. display_old_color = p_enabled;
  233. }
  234. bool ColorPicker::is_displaying_old_color() const {
  235. return display_old_color;
  236. }
  237. void ColorPicker::set_edit_alpha(bool p_show) {
  238. edit_alpha = p_show;
  239. _update_controls();
  240. if (!is_inside_tree()) {
  241. return;
  242. }
  243. _update_color();
  244. sample->update();
  245. }
  246. bool ColorPicker::is_editing_alpha() const {
  247. return edit_alpha;
  248. }
  249. void ColorPicker::_value_changed(double) {
  250. if (updating) {
  251. return;
  252. }
  253. if (hsv_mode_enabled) {
  254. h = scroll[0]->get_value() / 360.0;
  255. s = scroll[1]->get_value() / 100.0;
  256. v = scroll[2]->get_value() / 100.0;
  257. color.set_hsv(h, s, v, scroll[3]->get_value() / 255.0);
  258. last_hsv = color;
  259. } else {
  260. for (int i = 0; i < 4; i++) {
  261. color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
  262. }
  263. }
  264. _set_pick_color(color, false);
  265. emit_signal(SNAME("color_changed"), color);
  266. }
  267. void ColorPicker::_html_submitted(const String &p_html) {
  268. if (updating || text_is_constructor || !c_text->is_visible()) {
  269. return;
  270. }
  271. float last_alpha = color.a;
  272. color = Color::html(p_html);
  273. if (!is_editing_alpha()) {
  274. color.a = last_alpha;
  275. }
  276. if (!is_inside_tree()) {
  277. return;
  278. }
  279. set_pick_color(color);
  280. emit_signal(SNAME("color_changed"), color);
  281. }
  282. void ColorPicker::_update_color(bool p_update_sliders) {
  283. updating = true;
  284. if (p_update_sliders) {
  285. if (hsv_mode_enabled) {
  286. for (int i = 0; i < 4; i++) {
  287. scroll[i]->set_step(1.0);
  288. }
  289. scroll[0]->set_max(359);
  290. scroll[0]->set_value(h * 360.0);
  291. scroll[1]->set_max(100);
  292. scroll[1]->set_value(s * 100.0);
  293. scroll[2]->set_max(100);
  294. scroll[2]->set_value(v * 100.0);
  295. scroll[3]->set_max(255);
  296. scroll[3]->set_value(color.components[3] * 255.0);
  297. } else {
  298. for (int i = 0; i < 4; i++) {
  299. if (raw_mode_enabled) {
  300. scroll[i]->set_step(0.01);
  301. scroll[i]->set_max(100);
  302. if (i == 3) {
  303. scroll[i]->set_max(1);
  304. }
  305. scroll[i]->set_value(color.components[i]);
  306. } else {
  307. scroll[i]->set_step(1);
  308. const float byte_value = color.components[i] * 255.0;
  309. scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
  310. scroll[i]->set_value(byte_value);
  311. }
  312. }
  313. }
  314. }
  315. _update_text_value();
  316. sample->update();
  317. uv_edit->update();
  318. w_edit->update();
  319. for (int i = 0; i < 4; i++) {
  320. scroll[i]->update();
  321. }
  322. wheel->update();
  323. wheel_uv->update();
  324. updating = false;
  325. }
  326. void ColorPicker::_update_presets() {
  327. int preset_size = _get_preset_size();
  328. // Only update the preset button size if it has changed.
  329. if (preset_size != prev_preset_size) {
  330. prev_preset_size = preset_size;
  331. btn_add_preset->set_custom_minimum_size(Size2(preset_size, preset_size));
  332. for (int i = 1; i < preset_container->get_child_count(); i++) {
  333. ColorPresetButton *cpb = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
  334. cpb->set_custom_minimum_size(Size2(preset_size, preset_size));
  335. }
  336. }
  337. // Only load preset buttons when the only child is the add-preset button.
  338. if (preset_container->get_child_count() == 1) {
  339. for (int i = 0; i < preset_cache.size(); i++) {
  340. _add_preset_button(preset_size, preset_cache[i]);
  341. }
  342. _notification(NOTIFICATION_VISIBILITY_CHANGED);
  343. }
  344. }
  345. void ColorPicker::_text_type_toggled() {
  346. text_is_constructor = !text_is_constructor;
  347. if (text_is_constructor) {
  348. text_type->set_text("");
  349. text_type->set_icon(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")));
  350. c_text->set_editable(false);
  351. } else {
  352. text_type->set_text("#");
  353. text_type->set_icon(nullptr);
  354. c_text->set_editable(true);
  355. }
  356. _update_color();
  357. }
  358. Color ColorPicker::get_pick_color() const {
  359. return color;
  360. }
  361. void ColorPicker::set_picker_shape(PickerShapeType p_picker_type) {
  362. ERR_FAIL_INDEX(p_picker_type, SHAPE_MAX);
  363. picker_type = p_picker_type;
  364. _update_controls();
  365. _update_color();
  366. }
  367. ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const {
  368. return picker_type;
  369. }
  370. inline int ColorPicker::_get_preset_size() {
  371. return (int(get_minimum_size().width) - (preset_container->get_theme_constant(SNAME("hseparation")) * (preset_column_count - 1))) / preset_column_count;
  372. }
  373. void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
  374. ColorPresetButton *btn_preset = memnew(ColorPresetButton(p_color));
  375. btn_preset->set_preset_color(p_color);
  376. btn_preset->set_custom_minimum_size(Size2(p_size, p_size));
  377. btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input), varray(p_color));
  378. btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
  379. preset_container->add_child(btn_preset);
  380. }
  381. void ColorPicker::add_preset(const Color &p_color) {
  382. if (presets.find(p_color)) {
  383. presets.move_to_back(presets.find(p_color));
  384. // Find button to move to the end.
  385. for (int i = 1; i < preset_container->get_child_count(); i++) {
  386. ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
  387. if (current_btn && p_color == current_btn->get_preset_color()) {
  388. preset_container->move_child(current_btn, preset_container->get_child_count() - 1);
  389. break;
  390. }
  391. }
  392. } else {
  393. presets.push_back(p_color);
  394. preset_cache.push_back(p_color);
  395. _add_preset_button(_get_preset_size(), p_color);
  396. }
  397. #ifdef TOOLS_ENABLED
  398. if (Engine::get_singleton()->is_editor_hint()) {
  399. PackedColorArray arr_to_save = get_presets();
  400. EditorSettings::get_singleton()->set_project_metadata("color_picker", "presets", arr_to_save);
  401. }
  402. #endif
  403. }
  404. void ColorPicker::erase_preset(const Color &p_color) {
  405. if (presets.find(p_color)) {
  406. presets.erase(presets.find(p_color));
  407. preset_cache.erase(preset_cache.find(p_color));
  408. // Find preset button to remove.
  409. for (int i = 1; i < preset_container->get_child_count(); i++) {
  410. ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
  411. if (current_btn && p_color == current_btn->get_preset_color()) {
  412. current_btn->queue_delete();
  413. break;
  414. }
  415. }
  416. #ifdef TOOLS_ENABLED
  417. if (Engine::get_singleton()->is_editor_hint()) {
  418. PackedColorArray arr_to_save = get_presets();
  419. EditorSettings::get_singleton()->set_project_metadata("color_picker", "presets", arr_to_save);
  420. }
  421. #endif
  422. }
  423. }
  424. PackedColorArray ColorPicker::get_presets() const {
  425. PackedColorArray arr;
  426. arr.resize(presets.size());
  427. for (int i = 0; i < presets.size(); i++) {
  428. arr.set(i, presets[i]);
  429. }
  430. return arr;
  431. }
  432. void ColorPicker::set_hsv_mode(bool p_enabled) {
  433. if (hsv_mode_enabled == p_enabled || raw_mode_enabled) {
  434. return;
  435. }
  436. hsv_mode_enabled = p_enabled;
  437. if (btn_hsv->is_pressed() != p_enabled) {
  438. btn_hsv->set_pressed(p_enabled);
  439. }
  440. if (!is_inside_tree()) {
  441. return;
  442. }
  443. _update_controls();
  444. _update_color();
  445. }
  446. bool ColorPicker::is_hsv_mode() const {
  447. return hsv_mode_enabled;
  448. }
  449. void ColorPicker::set_raw_mode(bool p_enabled) {
  450. if (raw_mode_enabled == p_enabled || hsv_mode_enabled) {
  451. return;
  452. }
  453. raw_mode_enabled = p_enabled;
  454. if (btn_raw->is_pressed() != p_enabled) {
  455. btn_raw->set_pressed(p_enabled);
  456. }
  457. if (!is_inside_tree()) {
  458. return;
  459. }
  460. _update_controls();
  461. _update_color();
  462. }
  463. bool ColorPicker::is_raw_mode() const {
  464. return raw_mode_enabled;
  465. }
  466. void ColorPicker::set_deferred_mode(bool p_enabled) {
  467. deferred_mode_enabled = p_enabled;
  468. }
  469. bool ColorPicker::is_deferred_mode() const {
  470. return deferred_mode_enabled;
  471. }
  472. void ColorPicker::_update_text_value() {
  473. bool visible = true;
  474. if (text_is_constructor) {
  475. String t = "Color(" + String::num(color.r) + ", " + String::num(color.g) + ", " + String::num(color.b);
  476. if (edit_alpha && color.a < 1) {
  477. t += ", " + String::num(color.a) + ")";
  478. } else {
  479. t += ")";
  480. }
  481. c_text->set_text(t);
  482. }
  483. if (color.r > 1 || color.g > 1 || color.b > 1 || color.r < 0 || color.g < 0 || color.b < 0) {
  484. visible = false;
  485. } else if (!text_is_constructor) {
  486. c_text->set_text(color.to_html(edit_alpha && color.a < 1));
  487. }
  488. text_type->set_visible(visible);
  489. c_text->set_visible(visible);
  490. }
  491. void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) {
  492. const Ref<InputEventMouseButton> mb = p_event;
  493. if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
  494. const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
  495. if (rect_old.has_point(mb->get_position())) {
  496. // Revert to the old color when left-clicking the old color sample.
  497. color = old_color;
  498. _update_color();
  499. emit_signal(SNAME("color_changed"), color);
  500. }
  501. }
  502. }
  503. void ColorPicker::_sample_draw() {
  504. // Covers the right half of the sample if the old color is being displayed,
  505. // or the whole sample if it's not being displayed.
  506. Rect2 rect_new;
  507. if (display_old_color) {
  508. rect_new = Rect2(Point2(sample->get_size().width * 0.5, 0), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
  509. // Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton).
  510. const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
  511. if (display_old_color && old_color.a < 1.0) {
  512. sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
  513. }
  514. sample->draw_rect(rect_old, old_color);
  515. if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) {
  516. // Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview.
  517. sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2());
  518. }
  519. } else {
  520. rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95));
  521. }
  522. if (color.a < 1.0) {
  523. sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_new, true);
  524. }
  525. sample->draw_rect(rect_new, color);
  526. if (color.r > 1 || color.g > 1 || color.b > 1) {
  527. // Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview.
  528. sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2(uv_edit->get_size().width * 0.5, 0));
  529. }
  530. }
  531. void ColorPicker::_hsv_draw(int p_which, Control *c) {
  532. if (!c) {
  533. return;
  534. }
  535. if (p_which == 0) {
  536. Vector<Point2> points;
  537. Vector<Color> colors;
  538. Vector<Color> colors2;
  539. Color col = color;
  540. Vector2 center = c->get_size() / 2.0;
  541. switch (picker_type) {
  542. case SHAPE_HSV_WHEEL: {
  543. points.resize(4);
  544. colors.resize(4);
  545. colors2.resize(4);
  546. real_t ring_radius_x = Math_SQRT12 * c->get_size().width * 0.42;
  547. real_t ring_radius_y = Math_SQRT12 * c->get_size().height * 0.42;
  548. points.set(0, center - Vector2(ring_radius_x, ring_radius_y));
  549. points.set(1, center + Vector2(ring_radius_x, -ring_radius_y));
  550. points.set(2, center + Vector2(ring_radius_x, ring_radius_y));
  551. points.set(3, center + Vector2(-ring_radius_x, ring_radius_y));
  552. colors.set(0, Color(1, 1, 1, 1));
  553. colors.set(1, Color(1, 1, 1, 1));
  554. colors.set(2, Color(0, 0, 0, 1));
  555. colors.set(3, Color(0, 0, 0, 1));
  556. c->draw_polygon(points, colors);
  557. col.set_hsv(h, 1, 1);
  558. col.a = 0;
  559. colors2.set(0, col);
  560. col.a = 1;
  561. colors2.set(1, col);
  562. col.set_hsv(h, 1, 0);
  563. colors2.set(2, col);
  564. col.a = 0;
  565. colors2.set(3, col);
  566. c->draw_polygon(points, colors2);
  567. break;
  568. }
  569. case SHAPE_HSV_RECTANGLE: {
  570. points.resize(4);
  571. colors.resize(4);
  572. colors2.resize(4);
  573. points.set(0, Vector2());
  574. points.set(1, Vector2(c->get_size().x, 0));
  575. points.set(2, c->get_size());
  576. points.set(3, Vector2(0, c->get_size().y));
  577. colors.set(0, Color(1, 1, 1, 1));
  578. colors.set(1, Color(1, 1, 1, 1));
  579. colors.set(2, Color(0, 0, 0, 1));
  580. colors.set(3, Color(0, 0, 0, 1));
  581. c->draw_polygon(points, colors);
  582. col = color;
  583. col.set_hsv(h, 1, 1);
  584. col.a = 0;
  585. colors2.set(0, col);
  586. col.a = 1;
  587. colors2.set(1, col);
  588. col.set_hsv(h, 1, 0);
  589. colors2.set(2, col);
  590. col.a = 0;
  591. colors2.set(3, col);
  592. c->draw_polygon(points, colors2);
  593. break;
  594. }
  595. default: {
  596. }
  597. }
  598. Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
  599. int x;
  600. int y;
  601. if (picker_type == SHAPE_VHS_CIRCLE) {
  602. x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2);
  603. y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2);
  604. } else {
  605. real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0;
  606. real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0;
  607. Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2);
  608. x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (cursor->get_width() / 2);
  609. y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (cursor->get_height() / 2);
  610. }
  611. c->draw_texture(cursor, Point2(x, y));
  612. col.set_hsv(h, 1, 1);
  613. if (picker_type == SHAPE_HSV_WHEEL) {
  614. points.resize(4);
  615. double h1 = h - (0.5 / 360);
  616. double h2 = h + (0.5 / 360);
  617. points.set(0, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU)), center.y + (center.y * Math::sin(h1 * Math_TAU))));
  618. points.set(1, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h1 * Math_TAU) * 0.84)));
  619. points.set(2, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU)), center.y + (center.y * Math::sin(h2 * Math_TAU))));
  620. points.set(3, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h2 * Math_TAU) * 0.84)));
  621. c->draw_multiline(points, col.inverted());
  622. }
  623. } else if (p_which == 1) {
  624. if (picker_type == SHAPE_HSV_RECTANGLE) {
  625. Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
  626. c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
  627. int y = c->get_size().y - c->get_size().y * (1.0 - h);
  628. Color col;
  629. col.set_hsv(h, 1, 1);
  630. c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
  631. } else if (picker_type == SHAPE_VHS_CIRCLE) {
  632. Vector<Point2> points;
  633. Vector<Color> colors;
  634. Color col;
  635. col.set_hsv(h, s, 1);
  636. points.resize(4);
  637. colors.resize(4);
  638. points.set(0, Vector2());
  639. points.set(1, Vector2(c->get_size().x, 0));
  640. points.set(2, c->get_size());
  641. points.set(3, Vector2(0, c->get_size().y));
  642. colors.set(0, col);
  643. colors.set(1, col);
  644. colors.set(2, Color(0, 0, 0));
  645. colors.set(3, Color(0, 0, 0));
  646. c->draw_polygon(points, colors);
  647. int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1);
  648. col.set_hsv(h, 1, v);
  649. c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
  650. }
  651. } else if (p_which == 2) {
  652. c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1));
  653. if (picker_type == SHAPE_VHS_CIRCLE) {
  654. circle_mat->set_shader_param("v", v);
  655. }
  656. }
  657. }
  658. void ColorPicker::_slider_draw(int p_which) {
  659. Vector<Vector2> pos;
  660. pos.resize(4);
  661. Vector<Color> col;
  662. col.resize(4);
  663. Size2 size = scroll[p_which]->get_size();
  664. Color left_color;
  665. Color right_color;
  666. const real_t margin = 4 * get_theme_default_base_scale();
  667. if (p_which == 3) {
  668. scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
  669. left_color = color;
  670. left_color.a = 0;
  671. right_color = color;
  672. right_color.a = 1;
  673. } else {
  674. if (raw_mode_enabled) {
  675. return;
  676. }
  677. if (hsv_mode_enabled) {
  678. if (p_which == 0) {
  679. Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
  680. scroll[p_which]->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
  681. scroll[p_which]->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(scroll[p_which]->get_size().x, margin)), false, Color(1, 1, 1), true);
  682. return;
  683. }
  684. Color s_col;
  685. Color v_col;
  686. s_col.set_hsv(h, 0, v);
  687. left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
  688. s_col.set_hsv(h, 1, v);
  689. v_col.set_hsv(h, s, 1);
  690. right_color = (p_which == 1) ? s_col : v_col;
  691. } else {
  692. left_color = Color(
  693. p_which == 0 ? 0 : color.r,
  694. p_which == 1 ? 0 : color.g,
  695. p_which == 2 ? 0 : color.b);
  696. right_color = Color(
  697. p_which == 0 ? 1 : color.r,
  698. p_which == 1 ? 1 : color.g,
  699. p_which == 2 ? 1 : color.b);
  700. }
  701. }
  702. col.set(0, left_color);
  703. col.set(1, right_color);
  704. col.set(2, right_color);
  705. col.set(3, left_color);
  706. pos.set(0, Vector2(0, margin));
  707. pos.set(1, Vector2(size.x, margin));
  708. pos.set(2, Vector2(size.x, margin * 2));
  709. pos.set(3, Vector2(0, margin * 2));
  710. scroll[p_which]->draw_polygon(pos, col);
  711. }
  712. void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
  713. Ref<InputEventMouseButton> bev = p_event;
  714. if (bev.is_valid()) {
  715. if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
  716. Vector2 center = c->get_size() / 2.0;
  717. if (picker_type == SHAPE_VHS_CIRCLE) {
  718. real_t dist = center.distance_to(bev->get_position());
  719. if (dist <= center.x) {
  720. real_t rad = bev->get_position().angle_to_point(center);
  721. h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
  722. s = CLAMP(dist / center.x, 0, 1);
  723. } else {
  724. return;
  725. }
  726. } else {
  727. real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0;
  728. real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0;
  729. Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2);
  730. if (bev->get_position().x < corner_x || bev->get_position().x > c->get_size().x - corner_x ||
  731. bev->get_position().y < corner_y || bev->get_position().y > c->get_size().y - corner_y) {
  732. {
  733. real_t dist = center.distance_to(bev->get_position());
  734. if (dist >= center.x * 0.84 && dist <= center.x) {
  735. real_t rad = bev->get_position().angle_to_point(center);
  736. h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
  737. spinning = true;
  738. } else {
  739. return;
  740. }
  741. }
  742. }
  743. if (!spinning) {
  744. real_t x = CLAMP(bev->get_position().x, corner_x, c->get_size().x - corner_x);
  745. real_t y = CLAMP(bev->get_position().y, corner_x, c->get_size().y - corner_y);
  746. s = (x - c->get_position().x - corner_x) / real_size.x;
  747. v = 1.0 - (y - c->get_position().y - corner_y) / real_size.y;
  748. }
  749. }
  750. changing_color = true;
  751. color.set_hsv(h, s, v, color.a);
  752. last_hsv = color;
  753. set_pick_color(color);
  754. _update_color();
  755. if (!deferred_mode_enabled) {
  756. emit_signal(SNAME("color_changed"), color);
  757. }
  758. } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
  759. emit_signal(SNAME("color_changed"), color);
  760. changing_color = false;
  761. spinning = false;
  762. } else {
  763. changing_color = false;
  764. spinning = false;
  765. }
  766. }
  767. Ref<InputEventMouseMotion> mev = p_event;
  768. if (mev.is_valid()) {
  769. if (!changing_color) {
  770. return;
  771. }
  772. Vector2 center = c->get_size() / 2.0;
  773. if (picker_type == SHAPE_VHS_CIRCLE) {
  774. real_t dist = center.distance_to(mev->get_position());
  775. real_t rad = mev->get_position().angle_to_point(center);
  776. h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
  777. s = CLAMP(dist / center.x, 0, 1);
  778. } else {
  779. if (spinning) {
  780. real_t rad = mev->get_position().angle_to_point(center);
  781. h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
  782. } else {
  783. real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0;
  784. real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0;
  785. Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2);
  786. real_t x = CLAMP(mev->get_position().x, corner_x, c->get_size().x - corner_x);
  787. real_t y = CLAMP(mev->get_position().y, corner_x, c->get_size().y - corner_y);
  788. s = (x - corner_x) / real_size.x;
  789. v = 1.0 - (y - corner_y) / real_size.y;
  790. }
  791. }
  792. color.set_hsv(h, s, v, color.a);
  793. last_hsv = color;
  794. set_pick_color(color);
  795. _update_color();
  796. if (!deferred_mode_enabled) {
  797. emit_signal(SNAME("color_changed"), color);
  798. }
  799. }
  800. }
  801. void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
  802. Ref<InputEventMouseButton> bev = p_event;
  803. if (bev.is_valid()) {
  804. if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
  805. changing_color = true;
  806. float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height);
  807. if (picker_type == SHAPE_VHS_CIRCLE) {
  808. v = 1.0 - (y / w_edit->get_size().height);
  809. } else {
  810. h = y / w_edit->get_size().height;
  811. }
  812. } else {
  813. changing_color = false;
  814. }
  815. color.set_hsv(h, s, v, color.a);
  816. last_hsv = color;
  817. set_pick_color(color);
  818. _update_color();
  819. if (!deferred_mode_enabled) {
  820. emit_signal(SNAME("color_changed"), color);
  821. } else if (!bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
  822. emit_signal(SNAME("color_changed"), color);
  823. }
  824. }
  825. Ref<InputEventMouseMotion> mev = p_event;
  826. if (mev.is_valid()) {
  827. if (!changing_color) {
  828. return;
  829. }
  830. float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height);
  831. if (picker_type == SHAPE_VHS_CIRCLE) {
  832. v = 1.0 - (y / w_edit->get_size().height);
  833. } else {
  834. h = y / w_edit->get_size().height;
  835. }
  836. color.set_hsv(h, s, v, color.a);
  837. last_hsv = color;
  838. set_pick_color(color);
  839. _update_color();
  840. if (!deferred_mode_enabled) {
  841. emit_signal(SNAME("color_changed"), color);
  842. }
  843. }
  844. }
  845. void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_color) {
  846. Ref<InputEventMouseButton> bev = p_event;
  847. if (bev.is_valid()) {
  848. if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
  849. set_pick_color(p_color);
  850. _update_color();
  851. emit_signal(SNAME("color_changed"), p_color);
  852. } else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) {
  853. erase_preset(p_color);
  854. emit_signal(SNAME("preset_removed"), p_color);
  855. }
  856. }
  857. }
  858. void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
  859. if (!is_inside_tree()) {
  860. return;
  861. }
  862. Ref<InputEventMouseButton> bev = p_event;
  863. if (bev.is_valid() && bev->get_button_index() == MOUSE_BUTTON_LEFT && !bev->is_pressed()) {
  864. emit_signal(SNAME("color_changed"), color);
  865. screen->hide();
  866. }
  867. Ref<InputEventMouseMotion> mev = p_event;
  868. if (mev.is_valid()) {
  869. Viewport *r = get_tree()->get_root();
  870. if (!r->get_visible_rect().has_point(mev->get_global_position())) {
  871. return;
  872. }
  873. Ref<Image> img = r->get_texture()->get_image();
  874. if (img.is_valid() && !img->is_empty()) {
  875. Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position();
  876. Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y);
  877. set_pick_color(c);
  878. }
  879. }
  880. }
  881. void ColorPicker::_add_preset_pressed() {
  882. add_preset(color);
  883. emit_signal(SNAME("preset_added"), color);
  884. }
  885. void ColorPicker::_screen_pick_pressed() {
  886. if (!is_inside_tree()) {
  887. return;
  888. }
  889. Viewport *r = get_tree()->get_root();
  890. if (!screen) {
  891. screen = memnew(Control);
  892. r->add_child(screen);
  893. screen->set_as_top_level(true);
  894. screen->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
  895. screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
  896. screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input));
  897. // It immediately toggles off in the first press otherwise.
  898. screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed"), varray(false));
  899. }
  900. screen->raise();
  901. #ifndef _MSC_VER
  902. #warning show modal no longer works, needs to be converted to a popup
  903. #endif
  904. //screen->show_modal();
  905. }
  906. void ColorPicker::_focus_enter() {
  907. bool has_ctext_focus = c_text->has_focus();
  908. if (has_ctext_focus) {
  909. c_text->select_all();
  910. } else {
  911. c_text->select(0, 0);
  912. }
  913. for (int i = 0; i < 4; i++) {
  914. if (values[i]->get_line_edit()->has_focus() && !has_ctext_focus) {
  915. values[i]->get_line_edit()->select_all();
  916. } else {
  917. values[i]->get_line_edit()->select(0, 0);
  918. }
  919. }
  920. }
  921. void ColorPicker::_focus_exit() {
  922. for (int i = 0; i < 4; i++) {
  923. if (!values[i]->get_line_edit()->get_menu()->is_visible()) {
  924. values[i]->get_line_edit()->select(0, 0);
  925. }
  926. }
  927. c_text->select(0, 0);
  928. }
  929. void ColorPicker::_html_focus_exit() {
  930. if (c_text->is_menu_visible()) {
  931. return;
  932. }
  933. _html_submitted(c_text->get_text());
  934. _focus_exit();
  935. }
  936. void ColorPicker::set_presets_enabled(bool p_enabled) {
  937. presets_enabled = p_enabled;
  938. if (!p_enabled) {
  939. btn_add_preset->set_disabled(true);
  940. btn_add_preset->set_focus_mode(FOCUS_NONE);
  941. } else {
  942. btn_add_preset->set_disabled(false);
  943. btn_add_preset->set_focus_mode(FOCUS_ALL);
  944. }
  945. }
  946. bool ColorPicker::are_presets_enabled() const {
  947. return presets_enabled;
  948. }
  949. void ColorPicker::set_presets_visible(bool p_visible) {
  950. presets_visible = p_visible;
  951. preset_separator->set_visible(p_visible);
  952. preset_container->set_visible(p_visible);
  953. }
  954. bool ColorPicker::are_presets_visible() const {
  955. return presets_visible;
  956. }
  957. void ColorPicker::_bind_methods() {
  958. ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color);
  959. ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color);
  960. ClassDB::bind_method(D_METHOD("set_hsv_mode", "enabled"), &ColorPicker::set_hsv_mode);
  961. ClassDB::bind_method(D_METHOD("is_hsv_mode"), &ColorPicker::is_hsv_mode);
  962. ClassDB::bind_method(D_METHOD("set_raw_mode", "enabled"), &ColorPicker::set_raw_mode);
  963. ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode);
  964. ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode);
  965. ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode);
  966. ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha);
  967. ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha);
  968. ClassDB::bind_method(D_METHOD("set_presets_enabled", "enabled"), &ColorPicker::set_presets_enabled);
  969. ClassDB::bind_method(D_METHOD("are_presets_enabled"), &ColorPicker::are_presets_enabled);
  970. ClassDB::bind_method(D_METHOD("set_presets_visible", "visible"), &ColorPicker::set_presets_visible);
  971. ClassDB::bind_method(D_METHOD("are_presets_visible"), &ColorPicker::are_presets_visible);
  972. ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset);
  973. ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset);
  974. ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets);
  975. ClassDB::bind_method(D_METHOD("set_picker_shape", "picker"), &ColorPicker::set_picker_shape);
  976. ClassDB::bind_method(D_METHOD("get_picker_shape"), &ColorPicker::get_picker_shape);
  977. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
  978. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
  979. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hsv_mode"), "set_hsv_mode", "is_hsv_mode");
  980. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode");
  981. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
  982. ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle"), "set_picker_shape", "get_picker_shape");
  983. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
  984. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible");
  985. ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
  986. ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color")));
  987. ADD_SIGNAL(MethodInfo("preset_removed", PropertyInfo(Variant::COLOR, "color")));
  988. BIND_ENUM_CONSTANT(SHAPE_HSV_RECTANGLE);
  989. BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL);
  990. BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
  991. }
  992. ColorPicker::ColorPicker() :
  993. BoxContainer(true) {
  994. HBoxContainer *hb_edit = memnew(HBoxContainer);
  995. add_child(hb_edit, false, INTERNAL_MODE_FRONT);
  996. hb_edit->set_v_size_flags(SIZE_EXPAND_FILL);
  997. hb_edit->add_child(uv_edit);
  998. uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(uv_edit));
  999. uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
  1000. uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
  1001. uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
  1002. uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));
  1003. HBoxContainer *hb_smpl = memnew(HBoxContainer);
  1004. add_child(hb_smpl, false, INTERNAL_MODE_FRONT);
  1005. hb_smpl->add_child(sample);
  1006. sample->set_h_size_flags(SIZE_EXPAND_FILL);
  1007. sample->connect("gui_input", callable_mp(this, &ColorPicker::_sample_input));
  1008. sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw));
  1009. btn_pick->set_flat(true);
  1010. hb_smpl->add_child(btn_pick);
  1011. btn_pick->set_toggle_mode(true);
  1012. btn_pick->set_tooltip(RTR("Pick a color from the editor window."));
  1013. btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed));
  1014. VBoxContainer *vbl = memnew(VBoxContainer);
  1015. add_child(vbl, false, INTERNAL_MODE_FRONT);
  1016. add_child(memnew(HSeparator), false, INTERNAL_MODE_FRONT);
  1017. VBoxContainer *vbr = memnew(VBoxContainer);
  1018. add_child(vbr, false, INTERNAL_MODE_FRONT);
  1019. vbr->set_h_size_flags(SIZE_EXPAND_FILL);
  1020. for (int i = 0; i < 4; i++) {
  1021. HBoxContainer *hbc = memnew(HBoxContainer);
  1022. labels[i] = memnew(Label());
  1023. labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
  1024. labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
  1025. hbc->add_child(labels[i]);
  1026. scroll[i] = memnew(HSlider);
  1027. scroll[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
  1028. scroll[i]->set_focus_mode(FOCUS_NONE);
  1029. hbc->add_child(scroll[i]);
  1030. values[i] = memnew(SpinBox);
  1031. scroll[i]->share(values[i]);
  1032. hbc->add_child(values[i]);
  1033. values[i]->get_line_edit()->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
  1034. values[i]->get_line_edit()->connect("focus_exited", callable_mp(this, &ColorPicker::_focus_exit));
  1035. scroll[i]->set_min(0);
  1036. scroll[i]->set_page(0);
  1037. scroll[i]->set_h_size_flags(SIZE_EXPAND_FILL);
  1038. scroll[i]->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed));
  1039. scroll[i]->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(i));
  1040. vbr->add_child(hbc);
  1041. }
  1042. labels[3]->set_text("A");
  1043. HBoxContainer *hhb = memnew(HBoxContainer);
  1044. vbr->add_child(hhb);
  1045. hhb->add_child(btn_hsv);
  1046. btn_hsv->set_text(RTR("HSV"));
  1047. btn_hsv->connect("toggled", callable_mp(this, &ColorPicker::set_hsv_mode));
  1048. hhb->add_child(btn_raw);
  1049. btn_raw->set_text(RTR("Raw"));
  1050. btn_raw->connect("toggled", callable_mp(this, &ColorPicker::set_raw_mode));
  1051. hhb->add_child(text_type);
  1052. text_type->set_text("#");
  1053. text_type->set_tooltip(TTR("Switch between hexadecimal and code values."));
  1054. if (Engine::get_singleton()->is_editor_hint()) {
  1055. text_type->connect("pressed", callable_mp(this, &ColorPicker::_text_type_toggled));
  1056. } else {
  1057. text_type->set_flat(true);
  1058. text_type->set_mouse_filter(MOUSE_FILTER_IGNORE);
  1059. }
  1060. hhb->add_child(c_text);
  1061. c_text->set_h_size_flags(SIZE_EXPAND_FILL);
  1062. c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
  1063. c_text->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
  1064. c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit));
  1065. wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL);
  1066. wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL);
  1067. hb_edit->add_child(wheel_edit);
  1068. wheel_mat.instantiate();
  1069. wheel_mat->set_shader(wheel_shader);
  1070. circle_mat.instantiate();
  1071. circle_mat->set_shader(circle_shader);
  1072. wheel_margin->add_theme_constant_override("margin_bottom", 8);
  1073. wheel_edit->add_child(wheel_margin);
  1074. wheel_margin->add_child(wheel);
  1075. wheel->set_mouse_filter(MOUSE_FILTER_PASS);
  1076. wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(2, wheel));
  1077. wheel_margin->add_child(wheel_uv);
  1078. wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(wheel_uv));
  1079. wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv));
  1080. hb_edit->add_child(w_edit);
  1081. w_edit->set_h_size_flags(SIZE_FILL);
  1082. w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
  1083. w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input));
  1084. w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(1, w_edit));
  1085. picker_type = SHAPE_HSV_RECTANGLE;
  1086. _update_controls();
  1087. updating = false;
  1088. set_pick_color(Color(1, 1, 1));
  1089. add_child(preset_separator, false, INTERNAL_MODE_FRONT);
  1090. preset_container->set_h_size_flags(SIZE_EXPAND_FILL);
  1091. preset_container->set_columns(preset_column_count);
  1092. add_child(preset_container, false, INTERNAL_MODE_FRONT);
  1093. btn_add_preset->set_icon_align(Button::ALIGN_CENTER);
  1094. btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
  1095. btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
  1096. preset_container->add_child(btn_add_preset);
  1097. }
  1098. /////////////////
  1099. void ColorPickerButton::_about_to_popup() {
  1100. set_pressed(true);
  1101. if (picker) {
  1102. picker->set_old_color(color);
  1103. }
  1104. }
  1105. void ColorPickerButton::_color_changed(const Color &p_color) {
  1106. color = p_color;
  1107. update();
  1108. emit_signal(SNAME("color_changed"), color);
  1109. }
  1110. void ColorPickerButton::_modal_closed() {
  1111. emit_signal(SNAME("popup_closed"));
  1112. set_pressed(false);
  1113. }
  1114. void ColorPickerButton::pressed() {
  1115. _update_picker();
  1116. Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
  1117. popup->set_as_minsize();
  1118. picker->_update_presets();
  1119. Rect2i usable_rect = popup->get_usable_parent_rect();
  1120. //let's try different positions to see which one we can use
  1121. Rect2i cp_rect(Point2i(), popup->get_size());
  1122. for (int i = 0; i < 4; i++) {
  1123. if (i > 1) {
  1124. cp_rect.position.y = get_screen_position().y - cp_rect.size.y;
  1125. } else {
  1126. cp_rect.position.y = get_screen_position().y + size.height;
  1127. }
  1128. if (i & 1) {
  1129. cp_rect.position.x = get_screen_position().x;
  1130. } else {
  1131. cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - size.x));
  1132. }
  1133. if (usable_rect.encloses(cp_rect)) {
  1134. break;
  1135. }
  1136. }
  1137. popup->set_position(cp_rect.position);
  1138. popup->popup();
  1139. picker->set_focus_on_line_edit();
  1140. }
  1141. void ColorPickerButton::_notification(int p_what) {
  1142. switch (p_what) {
  1143. case NOTIFICATION_DRAW: {
  1144. const Ref<StyleBox> normal = get_theme_stylebox(SNAME("normal"));
  1145. const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
  1146. draw_texture_rect(Control::get_theme_icon(SNAME("bg"), SNAME("ColorPickerButton")), r, true);
  1147. draw_rect(r, color);
  1148. if (color.r > 1 || color.g > 1 || color.b > 1) {
  1149. // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
  1150. draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), normal->get_offset());
  1151. }
  1152. } break;
  1153. case NOTIFICATION_WM_CLOSE_REQUEST: {
  1154. if (popup) {
  1155. popup->hide();
  1156. }
  1157. } break;
  1158. }
  1159. if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
  1160. if (popup && !is_visible_in_tree()) {
  1161. popup->hide();
  1162. }
  1163. }
  1164. }
  1165. void ColorPickerButton::set_pick_color(const Color &p_color) {
  1166. color = p_color;
  1167. if (picker) {
  1168. picker->set_pick_color(p_color);
  1169. }
  1170. update();
  1171. }
  1172. Color ColorPickerButton::get_pick_color() const {
  1173. return color;
  1174. }
  1175. void ColorPickerButton::set_edit_alpha(bool p_show) {
  1176. edit_alpha = p_show;
  1177. if (picker) {
  1178. picker->set_edit_alpha(p_show);
  1179. }
  1180. }
  1181. bool ColorPickerButton::is_editing_alpha() const {
  1182. return edit_alpha;
  1183. }
  1184. ColorPicker *ColorPickerButton::get_picker() {
  1185. _update_picker();
  1186. return picker;
  1187. }
  1188. PopupPanel *ColorPickerButton::get_popup() {
  1189. _update_picker();
  1190. return popup;
  1191. }
  1192. void ColorPickerButton::_update_picker() {
  1193. if (!picker) {
  1194. popup = memnew(PopupPanel);
  1195. popup->set_wrap_controls(true);
  1196. picker = memnew(ColorPicker);
  1197. picker->set_anchors_and_offsets_preset(PRESET_WIDE);
  1198. popup->add_child(picker);
  1199. add_child(popup, false, INTERNAL_MODE_FRONT);
  1200. picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
  1201. popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup));
  1202. popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed));
  1203. picker->set_pick_color(color);
  1204. picker->set_edit_alpha(edit_alpha);
  1205. picker->set_display_old_color(true);
  1206. emit_signal(SNAME("picker_created"));
  1207. }
  1208. }
  1209. void ColorPickerButton::_bind_methods() {
  1210. ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPickerButton::set_pick_color);
  1211. ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPickerButton::get_pick_color);
  1212. ClassDB::bind_method(D_METHOD("get_picker"), &ColorPickerButton::get_picker);
  1213. ClassDB::bind_method(D_METHOD("get_popup"), &ColorPickerButton::get_popup);
  1214. ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha);
  1215. ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha);
  1216. ClassDB::bind_method(D_METHOD("_about_to_popup"), &ColorPickerButton::_about_to_popup);
  1217. ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
  1218. ADD_SIGNAL(MethodInfo("popup_closed"));
  1219. ADD_SIGNAL(MethodInfo("picker_created"));
  1220. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
  1221. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
  1222. }
  1223. ColorPickerButton::ColorPickerButton() {
  1224. set_toggle_mode(true);
  1225. }
  1226. /////////////////
  1227. void ColorPresetButton::_notification(int p_what) {
  1228. switch (p_what) {
  1229. case NOTIFICATION_DRAW: {
  1230. const Rect2 r = Rect2(Point2(0, 0), get_size());
  1231. Ref<StyleBox> sb_raw = get_theme_stylebox(SNAME("preset_fg"), SNAME("ColorPresetButton"))->duplicate();
  1232. Ref<StyleBoxFlat> sb_flat = sb_raw;
  1233. Ref<StyleBoxTexture> sb_texture = sb_raw;
  1234. if (sb_flat.is_valid()) {
  1235. if (preset_color.a < 1) {
  1236. // Draw a background pattern when the color is transparent.
  1237. sb_flat->set_bg_color(Color(1, 1, 1));
  1238. sb_flat->draw(get_canvas_item(), r);
  1239. Rect2 bg_texture_rect = r.grow_side(SIDE_LEFT, -sb_flat->get_margin(SIDE_LEFT));
  1240. bg_texture_rect = bg_texture_rect.grow_side(SIDE_RIGHT, -sb_flat->get_margin(SIDE_RIGHT));
  1241. bg_texture_rect = bg_texture_rect.grow_side(SIDE_TOP, -sb_flat->get_margin(SIDE_TOP));
  1242. bg_texture_rect = bg_texture_rect.grow_side(SIDE_BOTTOM, -sb_flat->get_margin(SIDE_BOTTOM));
  1243. draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), bg_texture_rect, true);
  1244. sb_flat->set_bg_color(preset_color);
  1245. }
  1246. sb_flat->set_bg_color(preset_color);
  1247. sb_flat->draw(get_canvas_item(), r);
  1248. } else if (sb_texture.is_valid()) {
  1249. if (preset_color.a < 1) {
  1250. // Draw a background pattern when the color is transparent.
  1251. bool use_tile_texture = (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE) || (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE_FIT);
  1252. draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), r, use_tile_texture);
  1253. }
  1254. sb_texture->set_modulate(preset_color);
  1255. sb_texture->draw(get_canvas_item(), r);
  1256. } else {
  1257. WARN_PRINT("Unsupported StyleBox used for ColorPresetButton. Use StyleBoxFlat or StyleBoxTexture instead.");
  1258. }
  1259. if (preset_color.r > 1 || preset_color.g > 1 || preset_color.b > 1) {
  1260. // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
  1261. draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPresetButton")), Vector2(0, 0));
  1262. }
  1263. } break;
  1264. }
  1265. }
  1266. void ColorPresetButton::set_preset_color(const Color &p_color) {
  1267. preset_color = p_color;
  1268. }
  1269. Color ColorPresetButton::get_preset_color() const {
  1270. return preset_color;
  1271. }
  1272. ColorPresetButton::ColorPresetButton(Color p_color) {
  1273. preset_color = p_color;
  1274. }
  1275. ColorPresetButton::~ColorPresetButton() {
  1276. }