color_picker.cpp 50 KB

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