summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/icons/CollapseTree.svg1
-rw-r--r--editor/icons/ExpandTree.svg1
-rw-r--r--editor/icons/FontSize.svg2
-rw-r--r--editor/icons/ThemeDeselectAll.svg1
-rw-r--r--editor/icons/ThemeRemoveAllItems.svg2
-rw-r--r--editor/icons/ThemeRemoveCustomItems.svg2
-rw-r--r--editor/icons/ThemeSelectAll.svg1
-rw-r--r--editor/icons/ThemeSelectFull.svg1
-rw-r--r--editor/plugins/theme_editor_plugin.cpp1698
-rw-r--r--editor/plugins/theme_editor_plugin.h172
10 files changed, 1452 insertions, 429 deletions
diff --git a/editor/icons/CollapseTree.svg b/editor/icons/CollapseTree.svg
new file mode 100644
index 0000000000..ece9071e03
--- /dev/null
+++ b/editor/icons/CollapseTree.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 9.669-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m8 6.355-3.536-2.583h2.536v-2.537h2v2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>
diff --git a/editor/icons/ExpandTree.svg b/editor/icons/ExpandTree.svg
new file mode 100644
index 0000000000..abdc1f9458
--- /dev/null
+++ b/editor/icons/ExpandTree.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 16-3.536-2.597h2.536v-2.523h2v2.523h2.536z"/><path d="m8 0-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>
diff --git a/editor/icons/FontSize.svg b/editor/icons/FontSize.svg
index e608d89b6a..3e148009ce 100644
--- a/editor/icons/FontSize.svg
+++ b/editor/icons/FontSize.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="SmallerT"><rect x="1.047" y="7.127" width="6.025" height="1.2" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="3.452" y="7.127" width="1.214" height="6.508" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="2.238" y="13.171" width="3.643" height="0.465" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,7.127l0,2.4l-0.43,0l-0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.071,7.127l0,2.4l-0.43,0l0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,8.327l0,1.2c0,-0.658 0.389,-1.2 0.861,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.78,8.327c0.473,0 0.861,0.542 0.861,1.2l0,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M2.238,13.171c0.666,-0 1.214,-0.42 1.214,-0.93l0,0.93l-1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.88,13.171c-0.666,-0 -1.214,-0.42 -1.214,-0.93l0,0.93l1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g id="BiggerT"><rect x="4.563" y="2.873" width="10.773" height="1.539" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="9.18" y="2.873" width="1.539" height="10.773" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="7.641" y="12.877" width="4.617" height="0.769" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,2.873l0,3.078l-0.769,0l-0,-3.078l0.769,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M15.336,2.873l-0,3.078l-0.77,0l0,-3.078l0.77,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,4.412l0,1.539c0,-0.844 0.695,-1.539 1.539,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M13.027,4.412c0.844,0 1.539,0.695 1.539,1.539l0,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.641,12.877c0.844,-0 1.539,-0.695 1.539,-1.539l-0,1.539l-1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M12.258,12.877c-0.845,-0 -1.539,-0.695 -1.539,-1.539l-0,1.539l1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m1.047 7.127h6.025v1.2h-6.025z"/><path d="m3.452 7.127h1.214v6.508h-1.214z"/><path d="m2.238 13.171h3.643v.465h-3.643z"/><path d="m1.477 7.127v2.4h-.43v-2.4z"/><path d="m7.071 7.127v2.4h-.43v-2.4z"/><path d="m1.477 8.327v1.2c0-.658.389-1.2.861-1.2z"/><path d="m5.78 8.327c.473 0 .861.542.861 1.2v-1.2z"/><path d="m2.238 13.171c.666 0 1.214-.42 1.214-.93v.93z"/><path d="m5.88 13.171c-.666 0-1.214-.42-1.214-.93v.93z"/><path d="m4.563 2.873h10.773v1.539h-10.773z"/><path d="m9.18 2.873h1.539v10.773h-1.539z"/><path d="m7.641 12.877h4.617v.769h-4.617z"/><path d="m5.332 2.873v3.078h-.769v-3.078z"/><path d="m15.336 2.873v3.078h-.77v-3.078z"/><path d="m5.332 4.412v1.539c0-.844.695-1.539 1.539-1.539z"/><path d="m13.027 4.412c.844 0 1.539.695 1.539 1.539v-1.539z"/><path d="m7.641 12.877c.844 0 1.539-.695 1.539-1.539v1.539z"/><path d="m12.258 12.877c-.845 0-1.539-.695-1.539-1.539v1.539z"/></g></svg>
diff --git a/editor/icons/ThemeDeselectAll.svg b/editor/icons/ThemeDeselectAll.svg
new file mode 100644
index 0000000000..d43ca85163
--- /dev/null
+++ b/editor/icons/ThemeDeselectAll.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5.952 6.976h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z"/><path d="m5.952 1.956h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/><path d="m5.952 11.996h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/></g></svg>
diff --git a/editor/icons/ThemeRemoveAllItems.svg b/editor/icons/ThemeRemoveAllItems.svg
index 47ed624d04..652274a0e7 100644
--- a/editor/icons/ThemeRemoveAllItems.svg
+++ b/editor/icons/ThemeRemoveAllItems.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M8,1.745c-0.595,0 -1.084,0.489 -1.084,1.084l0,3.699l-3.851,-1.927c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.076,0.151 -0.115,0.317 -0.115,0.485c0,0.41 0.233,0.786 0.599,0.97l3.481,1.74l-3.481,1.74c-0.366,0.184 -0.599,0.56 -0.599,0.97c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l3.851,-1.927l0,3.111c0,0.594 0.489,1.084 1.084,1.084c0.595,-0 1.084,-0.49 1.084,-1.084l-0,-3.111l3.851,1.927c0.151,0.075 0.317,0.114 0.485,0.114c0.41,0 0.786,-0.232 0.969,-0.599c0.076,-0.151 0.115,-0.317 0.115,-0.485c-0,-0.41 -0.233,-0.786 -0.599,-0.97l-3.481,-1.74l3.481,-1.74c0.366,-0.184 0.599,-0.56 0.599,-0.97c-0,-0.168 -0.039,-0.334 -0.115,-0.485c-0.182,-0.364 -0.554,-0.596 -0.961,-0.599c-0.171,-0.001 -0.34,0.038 -0.493,0.114l-3.851,1.927l-0,-3.699c-0,-0.595 -0.489,-1.084 -1.084,-1.084Z" style="fill:#a5efac;"/><path d="M8,1.745c-0,0 -0,1.783 -0,1.783l-1.084,0l0,-0.699c0,-0.595 0.489,-1.084 1.084,-1.084Z" style="fill:#ff7070;fill-rule:nonzero;"/><path d="M1.528,5.312l2.957,-0l-1.42,-0.711c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.036,0.072 -0.064,0.148 -0.083,0.226Zm5.388,-1.784l1.084,0l-0,1.784l-1.084,-0l0,-1.784Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M6.916,5.312l1.084,-0l-0,1.783l-4.796,0l-1.109,-0.554c-0.366,-0.184 -0.599,-0.56 -0.599,-0.97c0,-0.088 0.011,-0.175 0.032,-0.259l2.957,-0l2.431,1.216l0,-1.216Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M3.204,7.095l4.796,0l-0,1.783l-3.619,0l1.195,-0.597l-2.372,-1.186Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.381,8.878l3.619,0l-0,1.784l-1.084,-0l0,-0.628l-1.255,0.628l-4.114,-0c0.088,-0.274 0.283,-0.508 0.548,-0.641l2.286,-1.143Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M6.916,12.445l1.084,0l-0,1.784l-0,-0c-0.595,-0.001 -1.084,-0.49 -1.084,-1.084l0,-0.7Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M6.916,10.662l1.084,-0l-0,1.783l-1.084,0l0,-1.783Zm-1.255,-0l-4.114,-0c-0.033,0.105 -0.051,0.216 -0.051,0.329c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l2.596,-1.299Z" style="fill:#9f70ff;fill-rule:nonzero;"/></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#a5efac"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff7070"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffeb70"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#9dff70"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#70ffb9"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#70deff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff70ac"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#9f70ff"/></g></svg>
diff --git a/editor/icons/ThemeRemoveCustomItems.svg b/editor/icons/ThemeRemoveCustomItems.svg
index bb8a8bd026..839f584fce 100644
--- a/editor/icons/ThemeRemoveCustomItems.svg
+++ b/editor/icons/ThemeRemoveCustomItems.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M11.299,3c0.772,0.513 1.42,1.199 1.888,2l-2.553,0c-0.706,-0.621 -1.629,-1 -2.634,-1c-1.005,0 -1.928,0.379 -2.634,1l-2.553,0c0.468,-0.801 1.116,-1.487 1.888,-2l6.598,-0Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M5.366,5c-0.593,0.522 -1.033,1.216 -1.238,2l-2.043,0c0.122,-0.717 0.373,-1.392 0.728,-2l2.553,-0Zm7.821,-0c0.355,0.608 0.606,1.283 0.728,2l-2.043,0c-0.205,-0.784 -0.645,-1.478 -1.238,-2l2.553,-0Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M13.915,7c0.056,0.326 0.085,0.66 0.085,1c-0,0.34 -0.029,0.674 -0.085,1l-2.043,0c0.083,-0.32 0.128,-0.655 0.128,-1c0,-0.345 -0.045,-0.68 -0.128,-1l2.043,-0Zm-9.787,0c-0.083,0.32 -0.128,0.655 -0.128,1c0,0.345 0.045,0.68 0.128,1l-2.043,-0c-0.056,-0.326 -0.085,-0.66 -0.085,-1c0,-0.34 0.029,-0.674 0.085,-1l2.043,0Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.128,9c0.205,0.784 0.645,1.478 1.238,2l-2.553,0c-0.355,-0.608 -0.606,-1.283 -0.728,-2l2.043,0Zm9.787,0c-0.122,0.717 -0.373,1.392 -0.728,2l-2.553,0c0.593,-0.522 1.033,-1.216 1.238,-2l2.043,0Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M11.299,13l-6.598,0c0.949,0.631 2.084,1 3.299,1c1.215,0 2.35,-0.369 3.299,-1Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M13.187,11c-0.468,0.801 -1.116,1.487 -1.888,2l-6.598,0c-0.772,-0.513 -1.42,-1.199 -1.888,-2l2.553,0c0.706,0.621 1.629,1 2.634,1c1.005,0 1.928,-0.379 2.634,-1l2.553,0Z" style="fill:#9f70ff;fill-rule:nonzero;"/><path d="M4.701,3l6.598,0c-0.949,-0.631 -2.084,-1 -3.299,-1c-1.215,0 -2.35,0.369 -3.299,1Z" style="fill:#ff7070;fill-rule:nonzero;"/></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffeb70"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#9dff70"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#70ffb9"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#70deff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff70ac"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#9f70ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff7070"/></g></svg>
diff --git a/editor/icons/ThemeSelectAll.svg b/editor/icons/ThemeSelectAll.svg
new file mode 100644
index 0000000000..59d9fb3387
--- /dev/null
+++ b/editor/icons/ThemeSelectAll.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m5.952 6.976h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m5.952 1.956h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.952 11.996h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/ThemeSelectFull.svg b/editor/icons/ThemeSelectFull.svg
new file mode 100644
index 0000000000..0fabb9961a
--- /dev/null
+++ b/editor/icons/ThemeSelectFull.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m11 6.976h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m11 1.956h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m11 11.996h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.995 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 5.995h4.01v4.01h-4.01zm.968.968h2.074v2.074h-2.074z" fill="#e0e0e0"/><path d="m5.995.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995.974h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/><path d="m5.995 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 11.015h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/></svg>
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index c765aa0319..36c1bf3a09 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -34,12 +34,1187 @@
#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor/editor_scale.h"
+#include "editor/progress_dialog.h"
#include "scene/gui/progress_bar.h"
+void ThemeItemImportTree::_update_items_tree() {
+ import_items_tree->clear();
+ TreeItem *root = import_items_tree->create_item();
+
+ if (base_theme.is_null()) {
+ return;
+ }
+
+ String filter_text = import_items_filter->get_text();
+
+ List<StringName> types;
+ List<StringName> names;
+ List<StringName> filtered_names;
+ base_theme->get_type_list(&types);
+ types.sort_custom<StringName::AlphCompare>();
+
+ int color_amount = 0;
+ int constant_amount = 0;
+ int font_amount = 0;
+ int font_size_amount = 0;
+ int icon_amount = 0;
+ int stylebox_amount = 0;
+
+ tree_color_items.clear();
+ tree_constant_items.clear();
+ tree_font_items.clear();
+ tree_font_size_items.clear();
+ tree_icon_items.clear();
+ tree_stylebox_items.clear();
+
+ for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ String type_name = (String)E->get();
+
+ TreeItem *type_node = import_items_tree->create_item(root);
+ type_node->set_meta("_can_be_imported", false);
+ type_node->set_collapsed(true);
+ type_node->set_text(0, type_name);
+ type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ type_node->set_checked(IMPORT_ITEM, false);
+ type_node->set_editable(IMPORT_ITEM, true);
+ type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ type_node->set_checked(IMPORT_ITEM_DATA, false);
+ type_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1);
+ bool has_filtered_items = false;
+ bool any_checked = false;
+ bool any_checked_with_data = false;
+
+ for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
+ Theme::DataType dt = (Theme::DataType)i;
+
+ names.clear();
+ filtered_names.clear();
+ base_theme->get_theme_item_list(dt, E->get(), &names);
+
+ bool data_type_has_filtered_items = false;
+
+ for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
+ String item_name = (String)F->get();
+ bool is_item_matching_filter = (item_name.findn(filter_text) > -1);
+ if (!filter_text.is_empty() && !is_matching_filter && !is_item_matching_filter) {
+ continue;
+ }
+
+ // Only mark this if actual items match the filter and not just the type group.
+ if (!filter_text.is_empty() && is_item_matching_filter) {
+ has_filtered_items = true;
+ data_type_has_filtered_items = true;
+ }
+ filtered_names.push_back(F->get());
+ }
+
+ if (filtered_names.size() == 0) {
+ continue;
+ }
+
+ TreeItem *data_type_node = import_items_tree->create_item(type_node);
+ data_type_node->set_meta("_can_be_imported", false);
+ data_type_node->set_metadata(0, i);
+ data_type_node->set_collapsed(!data_type_has_filtered_items);
+ data_type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ data_type_node->set_checked(IMPORT_ITEM, false);
+ data_type_node->set_editable(IMPORT_ITEM, true);
+ data_type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ data_type_node->set_checked(IMPORT_ITEM_DATA, false);
+ data_type_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ List<TreeItem *> *item_list;
+
+ switch (dt) {
+ case Theme::DATA_TYPE_COLOR:
+ data_type_node->set_icon(0, get_theme_icon("Color", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Colors"));
+
+ item_list = &tree_color_items;
+ color_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ data_type_node->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Constants"));
+
+ item_list = &tree_constant_items;
+ constant_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ data_type_node->set_icon(0, get_theme_icon("Font", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Fonts"));
+
+ item_list = &tree_font_items;
+ font_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ data_type_node->set_icon(0, get_theme_icon("FontSize", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Font Sizes"));
+
+ item_list = &tree_font_size_items;
+ font_size_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ data_type_node->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Icons"));
+
+ item_list = &tree_icon_items;
+ icon_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ data_type_node->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Styleboxes"));
+
+ item_list = &tree_stylebox_items;
+ stylebox_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ bool data_type_any_checked = false;
+ bool data_type_any_checked_with_data = false;
+
+ filtered_names.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *F = filtered_names.front(); F; F = F->next()) {
+ TreeItem *item_node = import_items_tree->create_item(data_type_node);
+ item_node->set_meta("_can_be_imported", true);
+ item_node->set_text(0, F->get());
+ item_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ item_node->set_checked(IMPORT_ITEM, false);
+ item_node->set_editable(IMPORT_ITEM, true);
+ item_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ item_node->set_checked(IMPORT_ITEM_DATA, false);
+ item_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ _restore_selected_item(item_node);
+ if (item_node->is_checked(IMPORT_ITEM)) {
+ data_type_any_checked = true;
+ any_checked = true;
+ }
+ if (item_node->is_checked(IMPORT_ITEM_DATA)) {
+ data_type_any_checked_with_data = true;
+ any_checked_with_data = true;
+ }
+
+ item_list->push_back(item_node);
+ }
+
+ data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked);
+ data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data);
+ }
+
+ // Remove the item if it doesn't match the filter in any way.
+ if (!is_matching_filter && !has_filtered_items) {
+ root->remove_child(type_node);
+ memdelete(type_node);
+ continue;
+ }
+
+ // Show one level inside of a type group if there are matches in items.
+ if (!filter_text.is_empty() && has_filtered_items) {
+ type_node->set_collapsed(false);
+ }
+
+ type_node->set_checked(IMPORT_ITEM, any_checked);
+ type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
+ }
+
+ if (color_amount > 0) {
+ Array arr;
+ arr.push_back(color_amount);
+ select_colors_label->set_text(TTRN("One color", "{num} colors", color_amount).format(arr, "{num}"));
+ select_all_colors_button->set_visible(true);
+ select_full_colors_button->set_visible(true);
+ deselect_all_colors_button->set_visible(true);
+ } else {
+ select_colors_label->set_text(TTR("No colors found."));
+ select_all_colors_button->set_visible(false);
+ select_full_colors_button->set_visible(false);
+ deselect_all_colors_button->set_visible(false);
+ }
+
+ if (constant_amount > 0) {
+ Array arr;
+ arr.push_back(constant_amount);
+ select_constants_label->set_text(TTRN("One constant", "{num} constants", constant_amount).format(arr, "{num}"));
+ select_all_constants_button->set_visible(true);
+ select_full_constants_button->set_visible(true);
+ deselect_all_constants_button->set_visible(true);
+ } else {
+ select_constants_label->set_text(TTR("No constants found."));
+ select_all_constants_button->set_visible(false);
+ select_full_constants_button->set_visible(false);
+ deselect_all_constants_button->set_visible(false);
+ }
+
+ if (font_amount > 0) {
+ Array arr;
+ arr.push_back(font_amount);
+ select_fonts_label->set_text(TTRN("One font", "{num} fonts", font_amount).format(arr, "{num}"));
+ select_all_fonts_button->set_visible(true);
+ select_full_fonts_button->set_visible(true);
+ deselect_all_fonts_button->set_visible(true);
+ } else {
+ select_fonts_label->set_text(TTR("No fonts found."));
+ select_all_fonts_button->set_visible(false);
+ select_full_fonts_button->set_visible(false);
+ deselect_all_fonts_button->set_visible(false);
+ }
+
+ if (font_size_amount > 0) {
+ Array arr;
+ arr.push_back(font_size_amount);
+ select_font_sizes_label->set_text(TTRN("One font size", "{num} font sizes", font_size_amount).format(arr, "{num}"));
+ select_all_font_sizes_button->set_visible(true);
+ select_full_font_sizes_button->set_visible(true);
+ deselect_all_font_sizes_button->set_visible(true);
+ } else {
+ select_font_sizes_label->set_text(TTR("No font sizes found."));
+ select_all_font_sizes_button->set_visible(false);
+ select_full_font_sizes_button->set_visible(false);
+ deselect_all_font_sizes_button->set_visible(false);
+ }
+
+ if (icon_amount > 0) {
+ Array arr;
+ arr.push_back(icon_amount);
+ select_icons_label->set_text(TTRN("One icon", "{num} icons", icon_amount).format(arr, "{num}"));
+ select_all_icons_button->set_visible(true);
+ select_full_icons_button->set_visible(true);
+ deselect_all_icons_button->set_visible(true);
+ select_icons_warning_hb->set_visible(true);
+ } else {
+ select_icons_label->set_text(TTR("No icons found."));
+ select_all_icons_button->set_visible(false);
+ select_full_icons_button->set_visible(false);
+ deselect_all_icons_button->set_visible(false);
+ select_icons_warning_hb->set_visible(false);
+ }
+
+ if (stylebox_amount > 0) {
+ Array arr;
+ arr.push_back(stylebox_amount);
+ select_styleboxes_label->set_text(TTRN("One stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}"));
+ select_all_styleboxes_button->set_visible(true);
+ select_full_styleboxes_button->set_visible(true);
+ deselect_all_styleboxes_button->set_visible(true);
+ } else {
+ select_styleboxes_label->set_text(TTR("No styleboxes found."));
+ select_all_styleboxes_button->set_visible(false);
+ select_full_styleboxes_button->set_visible(false);
+ deselect_all_styleboxes_button->set_visible(false);
+ }
+}
+
+void ThemeItemImportTree::_toggle_type_items(bool p_collapse) {
+ TreeItem *root = import_items_tree->get_root();
+ if (!root) {
+ return;
+ }
+
+ TreeItem *type_node = root->get_children();
+ while (type_node) {
+ type_node->set_collapsed(p_collapse);
+ type_node = type_node->get_next();
+ }
+}
+
+void ThemeItemImportTree::_filter_text_changed(const String &p_value) {
+ _update_items_tree();
+}
+
+void ThemeItemImportTree::_store_selected_item(TreeItem *p_tree_item) {
+ if (!p_tree_item->get_meta("_can_be_imported")) {
+ return;
+ }
+
+ TreeItem *data_type_node = p_tree_item->get_parent();
+ if (!data_type_node || data_type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ TreeItem *type_node = data_type_node->get_parent();
+ if (!type_node || type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ ThemeItem ti;
+ ti.item_name = p_tree_item->get_text(0);
+ ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0);
+ ti.type_name = type_node->get_text(0);
+
+ bool import = p_tree_item->is_checked(IMPORT_ITEM);
+ bool with_data = p_tree_item->is_checked(IMPORT_ITEM_DATA);
+
+ if (import && with_data) {
+ selected_items[ti] = SELECT_IMPORT_FULL;
+ } else if (import) {
+ selected_items[ti] = SELECT_IMPORT_DEFINITION;
+ } else {
+ selected_items.erase(ti);
+ }
+
+ _update_total_selected(ti.data_type);
+}
+
+void ThemeItemImportTree::_restore_selected_item(TreeItem *p_tree_item) {
+ if (!p_tree_item->get_meta("_can_be_imported")) {
+ return;
+ }
+
+ TreeItem *data_type_node = p_tree_item->get_parent();
+ if (!data_type_node || data_type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ TreeItem *type_node = data_type_node->get_parent();
+ if (!type_node || type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ ThemeItem ti;
+ ti.item_name = p_tree_item->get_text(0);
+ ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0);
+ ti.type_name = type_node->get_text(0);
+
+ if (!selected_items.has(ti)) {
+ p_tree_item->set_checked(IMPORT_ITEM, false);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, false);
+ return;
+ }
+
+ if (selected_items[ti] == SELECT_IMPORT_FULL) {
+ p_tree_item->set_checked(IMPORT_ITEM, true);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, true);
+ } else if (selected_items[ti] == SELECT_IMPORT_DEFINITION) {
+ p_tree_item->set_checked(IMPORT_ITEM, true);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, false);
+ }
+}
+
+void ThemeItemImportTree::_update_total_selected(Theme::DataType p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ Label *total_selected_items_label;
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ total_selected_items_label = total_selected_colors_label;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ total_selected_items_label = total_selected_constants_label;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ total_selected_items_label = total_selected_fonts_label;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ total_selected_items_label = total_selected_font_sizes_label;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ total_selected_items_label = total_selected_icons_label;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ total_selected_items_label = total_selected_styleboxes_label;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ if (!total_selected_items_label) {
+ return;
+ }
+
+ int count = 0;
+ for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) {
+ ThemeItem ti = E->key();
+ if (ti.data_type == p_data_type) {
+ count++;
+ }
+ }
+
+ if (count == 0) {
+ total_selected_items_label->hide();
+ } else {
+ Array arr;
+ arr.push_back(count);
+ total_selected_items_label->set_text(TTRN("{num} currently selected", "{num} currently selected", count).format(arr, "{num}"));
+ total_selected_items_label->show();
+ }
+}
+
+void ThemeItemImportTree::_tree_item_edited() {
+ if (updating_tree) {
+ return;
+ }
+
+ TreeItem *edited_item = import_items_tree->get_edited();
+ if (!edited_item) {
+ return;
+ }
+
+ updating_tree = true;
+
+ int edited_column = import_items_tree->get_edited_column();
+ bool is_checked = edited_item->is_checked(edited_column);
+ if (is_checked) {
+ if (edited_column == IMPORT_ITEM_DATA) {
+ edited_item->set_checked(IMPORT_ITEM, true);
+ }
+
+ _select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA));
+ } else {
+ if (edited_column == IMPORT_ITEM) {
+ edited_item->set_checked(IMPORT_ITEM_DATA, false);
+ }
+
+ _deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM));
+ }
+
+ _update_parent_items(edited_item);
+ _store_selected_item(edited_item);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
+ TreeItem *child_item = p_root_item->get_children();
+ while (child_item) {
+ child_item->set_checked(IMPORT_ITEM, true);
+ if (p_select_with_data) {
+ child_item->set_checked(IMPORT_ITEM_DATA, true);
+ }
+ _store_selected_item(child_item);
+
+ _select_all_subitems(child_item, p_select_with_data);
+ child_item = child_item->get_next();
+ }
+}
+
+void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely) {
+ TreeItem *child_item = p_root_item->get_children();
+ while (child_item) {
+ child_item->set_checked(IMPORT_ITEM_DATA, false);
+ if (p_deselect_completely) {
+ child_item->set_checked(IMPORT_ITEM, false);
+ }
+ _store_selected_item(child_item);
+
+ _deselect_all_subitems(child_item, p_deselect_completely);
+ child_item = child_item->get_next();
+ }
+}
+
+void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) {
+ TreeItem *parent_item = p_root_item->get_parent();
+ if (!parent_item) {
+ return;
+ }
+
+ bool any_checked = false;
+ bool any_checked_with_data = false;
+
+ TreeItem *child_item = parent_item->get_children();
+ while (child_item) {
+ if (child_item->is_checked(IMPORT_ITEM)) {
+ any_checked = true;
+ }
+ if (child_item->is_checked(IMPORT_ITEM_DATA)) {
+ any_checked_with_data = true;
+ }
+
+ child_item = child_item->get_next();
+ }
+
+ parent_item->set_checked(IMPORT_ITEM, any_checked);
+ parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
+ _update_parent_items(parent_item);
+}
+
+void ThemeItemImportTree::_select_all_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _select_all_subitems(root, false);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_full_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _select_all_subitems(root, true);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_deselect_all_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _deselect_all_subitems(root, true);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, true);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, true);
+ child_item->set_checked(IMPORT_ITEM_DATA, true);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, false);
+ child_item->set_checked(IMPORT_ITEM_DATA, false);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_import_selected() {
+ if (selected_items.size() == 0) {
+ EditorNode::get_singleton()->show_accept(TTR("Nothing was selected for the import."), TTR("OK"));
+ return;
+ }
+
+ ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size());
+
+ int idx = 0;
+ for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) {
+ // Arbitrary number of items to skip from reporting.
+ // Reduces the number of UI updates that this causes when copying large themes.
+ if (idx % 10 == 0) {
+ Array arr;
+ arr.push_back(idx + 1);
+ arr.push_back(selected_items.size());
+ ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Importing items {n}/{n}").format(arr, "{n}"), idx);
+ }
+
+ ItemCheckedState cs = E->get();
+ ThemeItem ti = E->key();
+
+ if (cs == SELECT_IMPORT_DEFINITION || cs == SELECT_IMPORT_FULL) {
+ Variant item_value = Variant();
+
+ if (cs == SELECT_IMPORT_FULL) {
+ item_value = base_theme->get_theme_item(ti.data_type, ti.item_name, ti.type_name);
+ } else {
+ switch (ti.data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_value = Color();
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_value = 0;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_value = Ref<Font>();
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_value = -1;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_value = Ref<Texture2D>();
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_value = Ref<StyleBox>();
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+ }
+
+ edited_theme->set_theme_item(ti.data_type, ti.item_name, ti.type_name, item_value);
+ }
+
+ idx++;
+ }
+
+ ProgressDialog::get_singleton()->end_task("import_theme_items");
+ emit_signal("items_imported");
+}
+
+void ThemeItemImportTree::set_edited_theme(const Ref<Theme> &p_theme) {
+ edited_theme = p_theme;
+}
+
+void ThemeItemImportTree::set_base_theme(const Ref<Theme> &p_theme) {
+ base_theme = p_theme;
+}
+
+void ThemeItemImportTree::reset_item_tree() {
+ import_items_filter->clear();
+ selected_items.clear();
+
+ total_selected_colors_label->hide();
+ total_selected_constants_label->hide();
+ total_selected_fonts_label->hide();
+ total_selected_font_sizes_label->hide();
+ total_selected_icons_label->hide();
+ total_selected_styleboxes_label->hide();
+
+ _update_items_tree();
+}
+
+bool ThemeItemImportTree::has_selected_items() const {
+ return (selected_items.size() > 0);
+}
+
+void ThemeItemImportTree::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ select_icons_warning_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons"));
+ select_icons_warning->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+
+ // Bottom panel buttons.
+ import_collapse_types_button->set_icon(get_theme_icon("CollapseTree", "EditorIcons"));
+ import_expand_types_button->set_icon(get_theme_icon("ExpandTree", "EditorIcons"));
+
+ import_select_all_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ import_select_full_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+ import_deselect_all_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+
+ // Side panel buttons.
+ select_colors_icon->set_texture(get_theme_icon("Color", "EditorIcons"));
+ deselect_all_colors_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_colors_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_colors_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_constants_icon->set_texture(get_theme_icon("MemberConstant", "EditorIcons"));
+ deselect_all_constants_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_constants_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_constants_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_fonts_icon->set_texture(get_theme_icon("Font", "EditorIcons"));
+ deselect_all_fonts_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_fonts_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_fonts_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_font_sizes_icon->set_texture(get_theme_icon("FontSize", "EditorIcons"));
+ deselect_all_font_sizes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_font_sizes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_font_sizes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_icons_icon->set_texture(get_theme_icon("ImageTexture", "EditorIcons"));
+ deselect_all_icons_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_icons_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_icons_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_styleboxes_icon->set_texture(get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ deselect_all_styleboxes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_styleboxes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_styleboxes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+ } break;
+ }
+}
+
+void ThemeItemImportTree::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("items_imported"));
+}
+
+ThemeItemImportTree::ThemeItemImportTree() {
+ HBoxContainer *import_items_filter_hb = memnew(HBoxContainer);
+ add_child(import_items_filter_hb);
+ Label *import_items_filter_label = memnew(Label);
+ import_items_filter_label->set_text(TTR("Filter:"));
+ import_items_filter_hb->add_child(import_items_filter_label);
+ import_items_filter = memnew(LineEdit);
+ import_items_filter->set_clear_button_enabled(true);
+ import_items_filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_items_filter_hb->add_child(import_items_filter);
+ import_items_filter->connect("text_changed", callable_mp(this, &ThemeItemImportTree::_filter_text_changed));
+
+ HBoxContainer *import_main_hb = memnew(HBoxContainer);
+ import_main_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(import_main_hb);
+
+ import_items_tree = memnew(Tree);
+ import_items_tree->set_hide_root(true);
+ import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_main_hb->add_child(import_items_tree);
+ import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited));
+
+ import_items_tree->set_columns(3);
+ import_items_tree->set_column_titles_visible(true);
+ import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import"));
+ import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data"));
+ import_items_tree->set_column_expand(0, true);
+ import_items_tree->set_column_expand(IMPORT_ITEM, false);
+ import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false);
+ import_items_tree->set_column_min_width(0, 160 * EDSCALE);
+ import_items_tree->set_column_min_width(IMPORT_ITEM, 80 * EDSCALE);
+ import_items_tree->set_column_min_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+
+ ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
+ import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
+ import_bulk_sc->set_enable_h_scroll(false);
+ import_main_hb->add_child(import_bulk_sc);
+ VBoxContainer *import_bulk_vb = memnew(VBoxContainer);
+ import_bulk_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_bulk_sc->add_child(import_bulk_vb);
+
+ Label *import_bulk_label = memnew(Label);
+ import_bulk_label->set_text(TTR("Select by data type:"));
+ import_bulk_vb->add_child(import_bulk_label);
+
+ select_colors_icon = memnew(TextureRect);
+ select_colors_label = memnew(Label);
+ deselect_all_colors_button = memnew(Button);
+ select_all_colors_button = memnew(Button);
+ select_full_colors_button = memnew(Button);
+ total_selected_colors_label = memnew(Label);
+
+ select_constants_icon = memnew(TextureRect);
+ select_constants_label = memnew(Label);
+ deselect_all_constants_button = memnew(Button);
+ select_all_constants_button = memnew(Button);
+ select_full_constants_button = memnew(Button);
+ total_selected_constants_label = memnew(Label);
+
+ select_fonts_icon = memnew(TextureRect);
+ select_fonts_label = memnew(Label);
+ deselect_all_fonts_button = memnew(Button);
+ select_all_fonts_button = memnew(Button);
+ select_full_fonts_button = memnew(Button);
+ total_selected_fonts_label = memnew(Label);
+
+ select_font_sizes_icon = memnew(TextureRect);
+ select_font_sizes_label = memnew(Label);
+ deselect_all_font_sizes_button = memnew(Button);
+ select_all_font_sizes_button = memnew(Button);
+ select_full_font_sizes_button = memnew(Button);
+ total_selected_font_sizes_label = memnew(Label);
+
+ select_icons_icon = memnew(TextureRect);
+ select_icons_label = memnew(Label);
+ deselect_all_icons_button = memnew(Button);
+ select_all_icons_button = memnew(Button);
+ select_full_icons_button = memnew(Button);
+ total_selected_icons_label = memnew(Label);
+
+ select_styleboxes_icon = memnew(TextureRect);
+ select_styleboxes_label = memnew(Label);
+ deselect_all_styleboxes_button = memnew(Button);
+ select_all_styleboxes_button = memnew(Button);
+ select_full_styleboxes_button = memnew(Button);
+ total_selected_styleboxes_label = memnew(Label);
+
+ for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
+ Theme::DataType dt = (Theme::DataType)i;
+
+ TextureRect *select_items_icon;
+ Label *select_items_label;
+ Button *deselect_all_items_button;
+ Button *select_all_items_button;
+ Button *select_full_items_button;
+ Label *total_selected_items_label;
+
+ String items_title = "";
+ String select_all_items_tooltip = "";
+ String select_full_items_tooltip = "";
+ String deselect_all_items_tooltip = "";
+
+ switch (dt) {
+ case Theme::DATA_TYPE_COLOR:
+ select_items_icon = select_colors_icon;
+ select_items_label = select_colors_label;
+ deselect_all_items_button = deselect_all_colors_button;
+ select_all_items_button = select_all_colors_button;
+ select_full_items_button = select_full_colors_button;
+ total_selected_items_label = total_selected_colors_label;
+
+ items_title = TTR("Colors");
+ select_all_items_tooltip = TTR("Select all visible color items.");
+ select_full_items_tooltip = TTR("Select all visible color items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible color items.");
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ select_items_icon = select_constants_icon;
+ select_items_label = select_constants_label;
+ deselect_all_items_button = deselect_all_constants_button;
+ select_all_items_button = select_all_constants_button;
+ select_full_items_button = select_full_constants_button;
+ total_selected_items_label = total_selected_constants_label;
+
+ items_title = TTR("Constants");
+ select_all_items_tooltip = TTR("Select all visible constant items.");
+ select_full_items_tooltip = TTR("Select all visible constant items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible constant items.");
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ select_items_icon = select_fonts_icon;
+ select_items_label = select_fonts_label;
+ deselect_all_items_button = deselect_all_fonts_button;
+ select_all_items_button = select_all_fonts_button;
+ select_full_items_button = select_full_fonts_button;
+ total_selected_items_label = total_selected_fonts_label;
+
+ items_title = TTR("Fonts");
+ select_all_items_tooltip = TTR("Select all visible font items.");
+ select_full_items_tooltip = TTR("Select all visible font items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible font items.");
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ select_items_icon = select_font_sizes_icon;
+ select_items_label = select_font_sizes_label;
+ deselect_all_items_button = deselect_all_font_sizes_button;
+ select_all_items_button = select_all_font_sizes_button;
+ select_full_items_button = select_full_font_sizes_button;
+ total_selected_items_label = total_selected_font_sizes_label;
+
+ items_title = TTR("Font sizes");
+ select_all_items_tooltip = TTR("Select all visible font size items.");
+ select_full_items_tooltip = TTR("Select all visible font size items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible font size items.");
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ select_items_icon = select_icons_icon;
+ select_items_label = select_icons_label;
+ deselect_all_items_button = deselect_all_icons_button;
+ select_all_items_button = select_all_icons_button;
+ select_full_items_button = select_full_icons_button;
+ total_selected_items_label = total_selected_icons_label;
+
+ items_title = TTR("Icons");
+ select_all_items_tooltip = TTR("Select all visible icon items.");
+ select_full_items_tooltip = TTR("Select all visible icon items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible icon items.");
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ select_items_icon = select_styleboxes_icon;
+ select_items_label = select_styleboxes_label;
+ deselect_all_items_button = deselect_all_styleboxes_button;
+ select_all_items_button = select_all_styleboxes_button;
+ select_full_items_button = select_full_styleboxes_button;
+ total_selected_items_label = total_selected_styleboxes_label;
+
+ items_title = TTR("Styleboxes");
+ select_all_items_tooltip = TTR("Select all visible stylebox items.");
+ select_full_items_tooltip = TTR("Select all visible stylebox items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible stylebox items.");
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ continue; // Can't happen, but silences warning.
+ }
+
+ if (i > 0) {
+ import_bulk_vb->add_child(memnew(HSeparator));
+ }
+
+ HBoxContainer *all_set = memnew(HBoxContainer);
+ import_bulk_vb->add_child(all_set);
+
+ HBoxContainer *label_set = memnew(HBoxContainer);
+ label_set->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ all_set->add_child(label_set);
+ select_items_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ label_set->add_child(select_items_icon);
+ select_items_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_items_label->set_clip_text(true);
+ select_items_label->set_text(items_title);
+ label_set->add_child(select_items_label);
+
+ HBoxContainer *button_set = memnew(HBoxContainer);
+ button_set->set_alignment(BoxContainer::ALIGN_END);
+ all_set->add_child(button_set);
+ select_all_items_button->set_flat(true);
+ select_all_items_button->set_tooltip(select_all_items_tooltip);
+ button_set->add_child(select_all_items_button);
+ select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed), varray(i));
+ select_full_items_button->set_flat(true);
+ select_full_items_button->set_tooltip(select_full_items_tooltip);
+ button_set->add_child(select_full_items_button);
+ select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed), varray(i));
+ deselect_all_items_button->set_flat(true);
+ deselect_all_items_button->set_tooltip(deselect_all_items_tooltip);
+ button_set->add_child(deselect_all_items_button);
+ deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed), varray(i));
+
+ total_selected_items_label->set_align(Label::ALIGN_RIGHT);
+ total_selected_items_label->hide();
+ import_bulk_vb->add_child(total_selected_items_label);
+
+ if (dt == Theme::DATA_TYPE_ICON) {
+ select_icons_warning_hb = memnew(HBoxContainer);
+ import_bulk_vb->add_child(select_icons_warning_hb);
+
+ select_icons_warning_icon = memnew(TextureRect);
+ select_icons_warning_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ select_icons_warning_hb->add_child(select_icons_warning_icon);
+
+ select_icons_warning = memnew(Label);
+ select_icons_warning->set_text(TTR("Caution: Adding icon data may considerably increase the size of your Theme resource."));
+ select_icons_warning->set_autowrap(true);
+ select_icons_warning->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_icons_warning_hb->add_child(select_icons_warning);
+ }
+ }
+
+ add_child(memnew(HSeparator));
+
+ HBoxContainer *import_buttons = memnew(HBoxContainer);
+ add_child(import_buttons);
+
+ import_collapse_types_button = memnew(Button);
+ import_collapse_types_button->set_flat(true);
+ import_collapse_types_button->set_tooltip(TTR("Collapse types."));
+ import_buttons->add_child(import_collapse_types_button);
+ import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(true));
+ import_expand_types_button = memnew(Button);
+ import_expand_types_button->set_flat(true);
+ import_expand_types_button->set_tooltip(TTR("Expand types."));
+ import_buttons->add_child(import_expand_types_button);
+ import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(false));
+
+ import_buttons->add_child(memnew(VSeparator));
+
+ import_select_all_button = memnew(Button);
+ import_select_all_button->set_flat(true);
+ import_select_all_button->set_text(TTR("Select All"));
+ import_select_all_button->set_tooltip(TTR("Select all Theme items."));
+ import_buttons->add_child(import_select_all_button);
+ import_select_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_items_pressed));
+ import_select_full_button = memnew(Button);
+ import_select_full_button->set_flat(true);
+ import_select_full_button->set_text(TTR("Select With Data"));
+ import_select_full_button->set_tooltip(TTR("Select all Theme items with item data."));
+ import_buttons->add_child(import_select_full_button);
+ import_select_full_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_items_pressed));
+ import_deselect_all_button = memnew(Button);
+ import_deselect_all_button->set_flat(true);
+ import_deselect_all_button->set_text(TTR("Deselect All"));
+ import_deselect_all_button->set_tooltip(TTR("Deselect all Theme items."));
+ import_buttons->add_child(import_deselect_all_button);
+ import_deselect_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_items_pressed));
+
+ import_buttons->add_spacer();
+
+ Button *import_add_selected_button = memnew(Button);
+ import_add_selected_button->set_text(TTR("Import Selected"));
+ import_buttons->add_child(import_add_selected_button);
+ import_add_selected_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_import_selected));
+}
+
+void ThemeItemEditorDialog::ok_pressed() {
+ if (import_default_theme_items->has_selected_items() || import_editor_theme_items->has_selected_items() || import_other_theme_items->has_selected_items()) {
+ confirm_closing_dialog->set_text(TTR("Import Items tab has some items selected. Selection will be lost upon closing this window.\nClose anyway?"));
+ confirm_closing_dialog->popup_centered(Size2i(380, 120) * EDSCALE);
+ return;
+ }
+
+ hide();
+}
+
+void ThemeItemEditorDialog::_close_dialog() {
+ hide();
+}
+
void ThemeItemEditorDialog::_dialog_about_to_show() {
ERR_FAIL_COND(edited_theme.is_null());
_update_edit_types();
+
+ import_default_theme_items->set_edited_theme(edited_theme);
+ import_default_theme_items->set_base_theme(Theme::get_default());
+ import_default_theme_items->reset_item_tree();
+
+ import_editor_theme_items->set_edited_theme(edited_theme);
+ import_editor_theme_items->set_base_theme(EditorNode::get_singleton()->get_theme_base()->get_theme());
+ import_editor_theme_items->reset_item_tree();
+
+ import_other_theme_items->set_edited_theme(edited_theme);
+ import_other_theme_items->reset_item_tree();
}
void ThemeItemEditorDialog::_update_edit_types() {
@@ -79,11 +1254,6 @@ void ThemeItemEditorDialog::_update_edit_types() {
base_theme->get_type_list(&default_types);
default_types.sort_custom<StringName::AlphCompare>();
- edit_add_class_options->clear();
- for (List<StringName>::Element *E = default_types.front(); E; E = E->next()) {
- edit_add_class_options->add_item(E->get());
- }
-
String selected_type = "";
Vector<int> selected_ids = edit_type_list->get_selected_items();
if (selected_ids.size() > 0) {
@@ -127,7 +1297,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
List<StringName> names;
- {
+ { // Colors.
names.clear();
edited_theme->get_color_list(p_item_type, &names);
@@ -148,7 +1318,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Constants.
names.clear();
edited_theme->get_constant_list(p_item_type, &names);
@@ -169,7 +1339,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Fonts.
names.clear();
edited_theme->get_font_list(p_item_type, &names);
@@ -190,7 +1360,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Font sizes.
names.clear();
edited_theme->get_font_size_list(p_item_type, &names);
@@ -211,7 +1381,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Icons.
names.clear();
edited_theme->get_icon_list(p_item_type, &names);
@@ -232,7 +1402,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Styleboxes.
names.clear();
edited_theme->get_stylebox_list(p_item_type, &names);
@@ -280,64 +1450,13 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu
_update_edit_item_tree(edited_item_type);
}
-void ThemeItemEditorDialog::_add_class_type_items() {
- int selected_idx = edit_add_class_options->get_selected();
- String type_name = edit_add_class_options->get_item_text(selected_idx);
- List<StringName> names;
-
- {
- names.clear();
- Theme::get_default()->get_icon_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_icon(E->get(), type_name, Ref<Texture2D>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_stylebox_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_stylebox(E->get(), type_name, Ref<StyleBox>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_font(E->get(), type_name, Ref<Font>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_size_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_font_size(E->get(), type_name, Theme::get_default()->get_font_size(E->get(), type_name));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_color_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_color(E->get(), type_name, Theme::get_default()->get_color(E->get(), type_name));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_constant_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_constant(E->get(), type_name, Theme::get_default()->get_constant(E->get(), type_name));
- }
- }
-
- _update_edit_types();
-}
-
-void ThemeItemEditorDialog::_add_custom_type() {
- edited_theme->add_icon_type(edit_add_custom_value->get_text());
- edited_theme->add_stylebox_type(edit_add_custom_value->get_text());
- edited_theme->add_font_type(edit_add_custom_value->get_text());
- edited_theme->add_font_size_type(edit_add_custom_value->get_text());
- edited_theme->add_color_type(edit_add_custom_value->get_text());
- edited_theme->add_constant_type(edit_add_custom_value->get_text());
+void ThemeItemEditorDialog::_add_theme_type() {
+ edited_theme->add_icon_type(edit_add_type_value->get_text());
+ edited_theme->add_stylebox_type(edit_add_type_value->get_text());
+ edited_theme->add_font_type(edit_add_type_value->get_text());
+ edited_theme->add_font_size_type(edit_add_type_value->get_text());
+ edited_theme->add_color_type(edit_add_type_value->get_text());
+ edited_theme->add_constant_type(edit_add_type_value->get_text());
_update_edit_types();
}
@@ -536,6 +1655,26 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_
}
}
+void ThemeItemEditorDialog::_open_select_another_theme() {
+ import_another_theme_dialog->popup_file_dialog();
+}
+
+void ThemeItemEditorDialog::_select_another_theme_cbk(const String &p_path) {
+ Ref<Theme> loaded_theme = ResourceLoader::load(p_path);
+ if (loaded_theme.is_null()) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, not a Theme resource."));
+ return;
+ }
+ if (loaded_theme == edited_theme) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, same as the edited Theme resource."));
+ return;
+ }
+
+ import_another_theme_value->set_text(p_path);
+ import_other_theme_items->set_base_theme(loaded_theme);
+ import_other_theme_items->reset_item_tree();
+}
+
void ThemeItemEditorDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -553,6 +1692,8 @@ void ThemeItemEditorDialog::_notification(int p_what) {
edit_items_remove_class->set_icon(get_theme_icon("Control", "EditorIcons"));
edit_items_remove_custom->set_icon(get_theme_icon("ThemeRemoveCustomItems", "EditorIcons"));
edit_items_remove_all->set_icon(get_theme_icon("ThemeRemoveAllItems", "EditorIcons"));
+
+ import_another_theme_button->set_icon(get_theme_icon("Folder", "EditorIcons"));
} break;
}
}
@@ -562,10 +1703,18 @@ void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) {
}
ThemeItemEditorDialog::ThemeItemEditorDialog() {
- set_title(TTR("Edit Theme Items"));
+ set_title(TTR("Manage Theme Items"));
+ get_ok_button()->set_text(TTR("Close"));
+ set_hide_on_ok(false); // Closing may require a confirmation in some cases.
+ TabContainer *tc = memnew(TabContainer);
+ tc->set_tab_align(TabContainer::TabAlign::ALIGN_LEFT);
+ add_child(tc);
+
+ // Edit Items tab.
HSplitContainer *edit_dialog_hs = memnew(HSplitContainer);
- add_child(edit_dialog_hs);
+ tc->add_child(edit_dialog_hs);
+ tc->set_tab_title(0, TTR("Edit Items"));
VBoxContainer *edit_dialog_side_vb = memnew(VBoxContainer);
edit_dialog_side_vb->set_custom_minimum_size(Size2(200.0, 0.0) * EDSCALE);
@@ -580,33 +1729,19 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_dialog_side_vb->add_child(edit_type_list);
edit_type_list->connect("item_selected", callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected));
- Label *edit_add_class_label = memnew(Label);
- edit_add_class_label->set_text(TTR("Add Type from Class:"));
- edit_dialog_side_vb->add_child(edit_add_class_label);
-
- HBoxContainer *edit_add_class = memnew(HBoxContainer);
- edit_dialog_side_vb->add_child(edit_add_class);
- edit_add_class_options = memnew(OptionButton);
- edit_add_class_options->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- edit_add_class->add_child(edit_add_class_options);
- Button *edit_add_class_button = memnew(Button);
- edit_add_class_button->set_text(TTR("Add"));
- edit_add_class->add_child(edit_add_class_button);
- edit_add_class_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_class_type_items));
-
- Label *edit_add_custom_label = memnew(Label);
- edit_add_custom_label->set_text(TTR("Add Custom Type:"));
- edit_dialog_side_vb->add_child(edit_add_custom_label);
-
- HBoxContainer *edit_add_custom = memnew(HBoxContainer);
- edit_dialog_side_vb->add_child(edit_add_custom);
- edit_add_custom_value = memnew(LineEdit);
- edit_add_custom_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- edit_add_custom->add_child(edit_add_custom_value);
- Button *edit_add_custom_button = memnew(Button);
- edit_add_custom_button->set_text(TTR("Add"));
- edit_add_custom->add_child(edit_add_custom_button);
- edit_add_custom_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_custom_type));
+ Label *edit_add_type_label = memnew(Label);
+ edit_add_type_label->set_text(TTR("Add Type:"));
+ edit_dialog_side_vb->add_child(edit_add_type_label);
+
+ HBoxContainer *edit_add_type_hb = memnew(HBoxContainer);
+ edit_dialog_side_vb->add_child(edit_add_type_hb);
+ edit_add_type_value = memnew(LineEdit);
+ edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ edit_add_type_hb->add_child(edit_add_type_value);
+ Button *edit_add_type_button = memnew(Button);
+ edit_add_type_button->set_text(TTR("Add"));
+ edit_add_type_hb->add_child(edit_add_type_button);
+ edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type));
VBoxContainer *edit_items_vb = memnew(VBoxContainer);
edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -616,7 +1751,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_items_vb->add_child(edit_items_toolbar);
Label *edit_items_toolbar_add_label = memnew(Label);
- edit_items_toolbar_add_label->set_text(TTR("Add:"));
+ edit_items_toolbar_add_label->set_text(TTR("Add Item:"));
edit_items_toolbar->add_child(edit_items_toolbar_add_label);
edit_items_add_color = memnew(Button);
@@ -664,7 +1799,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_items_toolbar->add_child(memnew(VSeparator));
Label *edit_items_toolbar_remove_label = memnew(Label);
- edit_items_toolbar_remove_label->set_text(TTR("Remove:"));
+ edit_items_toolbar_remove_label->set_text(TTR("Remove Items:"));
edit_items_toolbar->add_child(edit_items_toolbar_remove_label);
edit_items_remove_class = memnew(Button);
@@ -716,6 +1851,57 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_theme_item_vb->add_child(theme_item_name);
theme_item_name->connect("gui_input", callable_mp(this, &ThemeItemEditorDialog::_edit_theme_item_gui_input));
edit_theme_item_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_confirm_edit_theme_item));
+
+ // Import Items tab.
+ TabContainer *import_tc = memnew(TabContainer);
+ tc->add_child(import_tc);
+ tc->set_tab_title(1, TTR("Import Items"));
+
+ import_default_theme_items = memnew(ThemeItemImportTree);
+ import_tc->add_child(import_default_theme_items);
+ import_tc->set_tab_title(0, TTR("Default Theme"));
+ import_default_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ import_editor_theme_items = memnew(ThemeItemImportTree);
+ import_tc->add_child(import_editor_theme_items);
+ import_tc->set_tab_title(1, TTR("Editor Theme"));
+ import_editor_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ VBoxContainer *import_another_theme_vb = memnew(VBoxContainer);
+
+ HBoxContainer *import_another_file_hb = memnew(HBoxContainer);
+ import_another_theme_vb->add_child(import_another_file_hb);
+ import_another_theme_value = memnew(LineEdit);
+ import_another_theme_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_another_theme_value->set_editable(false);
+ import_another_file_hb->add_child(import_another_theme_value);
+ import_another_theme_button = memnew(Button);
+ import_another_file_hb->add_child(import_another_theme_button);
+ import_another_theme_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_select_another_theme));
+
+ import_another_theme_dialog = memnew(EditorFileDialog);
+ import_another_theme_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ import_another_theme_dialog->set_title(TTR("Select Another Theme Resource:"));
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type("Theme", &ext);
+ for (List<String>::Element *E = ext.front(); E; E = E->next()) {
+ import_another_theme_dialog->add_filter("*." + E->get() + "; Theme Resource");
+ }
+ import_another_file_hb->add_child(import_another_theme_dialog);
+ import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk));
+
+ import_other_theme_items = memnew(ThemeItemImportTree);
+ import_other_theme_items->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ import_another_theme_vb->add_child(import_other_theme_items);
+
+ import_tc->add_child(import_another_theme_vb);
+ import_tc->set_tab_title(2, TTR("Another Theme"));
+ import_other_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ confirm_closing_dialog = memnew(ConfirmationDialog);
+ confirm_closing_dialog->set_autowrap(true);
+ add_child(confirm_closing_dialog);
+ confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
void ThemeEditor::edit(const Ref<Theme> &p_theme) {
@@ -742,299 +1928,8 @@ void ThemeEditor::_refresh_interval() {
_propagate_redraw(main_container);
}
-struct _TECategory {
- template <class T>
- struct RefItem {
- Ref<T> item;
- StringName name;
- bool operator<(const RefItem<T> &p) const { return item->get_instance_id() < p.item->get_instance_id(); }
- };
-
- template <class T>
- struct Item {
- T item;
- String name;
- bool operator<(const Item<T> &p) const { return name < p.name; }
- };
-
- Set<RefItem<StyleBox>> stylebox_items;
- Set<RefItem<Font>> font_items;
- Set<Item<int>> font_size_items;
- Set<RefItem<Texture2D>> icon_items;
-
- Set<Item<Color>> color_items;
- Set<Item<int>> constant_items;
-};
-
-void ThemeEditor::_save_template_cbk(String fname) {
- String filename = file_dialog->get_current_path();
-
- Map<String, _TECategory> categories;
-
- // Fill types.
- List<StringName> type_list;
- Theme::get_default()->get_type_list(&type_list);
- for (List<StringName>::Element *E = type_list.front(); E; E = E->next()) {
- categories.insert(E->get(), _TECategory());
- }
-
- // Fill default theme.
- for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
- _TECategory &tc = E->get();
-
- List<StringName> stylebox_list;
- Theme::get_default()->get_stylebox_list(E->key(), &stylebox_list);
- for (List<StringName>::Element *F = stylebox_list.front(); F; F = F->next()) {
- _TECategory::RefItem<StyleBox> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_stylebox(F->get(), E->key());
- tc.stylebox_items.insert(it);
- }
-
- List<StringName> font_list;
- Theme::get_default()->get_font_list(E->key(), &font_list);
- for (List<StringName>::Element *F = font_list.front(); F; F = F->next()) {
- _TECategory::RefItem<Font> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_font(F->get(), E->key());
- tc.font_items.insert(it);
- }
-
- List<StringName> font_size_list;
- Theme::get_default()->get_font_size_list(E->key(), &font_list);
- for (List<StringName>::Element *F = font_size_list.front(); F; F = F->next()) {
- _TECategory::Item<int> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_font_size(F->get(), E->key());
- tc.font_size_items.insert(it);
- }
-
- List<StringName> icon_list;
- Theme::get_default()->get_icon_list(E->key(), &icon_list);
- for (List<StringName>::Element *F = icon_list.front(); F; F = F->next()) {
- _TECategory::RefItem<Texture2D> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_icon(F->get(), E->key());
- tc.icon_items.insert(it);
- }
-
- List<StringName> color_list;
- Theme::get_default()->get_color_list(E->key(), &color_list);
- for (List<StringName>::Element *F = color_list.front(); F; F = F->next()) {
- _TECategory::Item<Color> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_color(F->get(), E->key());
- tc.color_items.insert(it);
- }
-
- List<StringName> constant_list;
- Theme::get_default()->get_constant_list(E->key(), &constant_list);
- for (List<StringName>::Element *F = constant_list.front(); F; F = F->next()) {
- _TECategory::Item<int> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_constant(F->get(), E->key());
- tc.constant_items.insert(it);
- }
- }
-
- FileAccess *file = FileAccess::open(filename, FileAccess::WRITE);
-
- ERR_FAIL_COND_MSG(!file, "Can't save theme to file '" + filename + "'.");
-
- file->store_line("; ******************* ");
- file->store_line("; Template Theme File ");
- file->store_line("; ******************* ");
- file->store_line("; ");
- file->store_line("; Theme Syntax: ");
- file->store_line("; ------------- ");
- file->store_line("; ");
- file->store_line("; Must be placed in section [theme]");
- file->store_line("; ");
- file->store_line("; Type.item = [value] ");
- file->store_line("; ");
- file->store_line("; [value] examples:");
- file->store_line("; ");
- file->store_line("; Type.item = 6 ; numeric constant. ");
- file->store_line("; Type.item = #FF00FF ; HTML color (magenta).");
- file->store_line("; Type.item = #FF00FF55 ; HTML color (magenta with alpha 0x55).");
- file->store_line("; Type.item = icon(image.png) ; icon in a png file (relative to theme file).");
- file->store_line("; Type.item = font(font.xres) ; font in a resource (relative to theme file).");
- file->store_line("; Type.item = sbox(stylebox.xres) ; stylebox in a resource (relative to theme file).");
- file->store_line("; Type.item = sboxf(2,#FF00FF) ; flat stylebox with margin 2.");
- file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF) ; flat stylebox with margin 2 and border.");
- file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF,#000000) ; flat stylebox with margin 2, light & dark borders.");
- file->store_line("; Type.item = sboxt(base.png,2,2,2,2) ; textured stylebox with 3x3 stretch and stretch margins.");
- file->store_line("; -Additionally, 4 extra integers can be added to sboxf and sboxt to specify custom padding of contents:");
- file->store_line("; Type.item = sboxt(base.png,2,2,2,2,5,4,2,4) ;");
- file->store_line("; -Order for all is always left, top, right, bottom.");
- file->store_line("; ");
- file->store_line("; Special values:");
- file->store_line("; Type.item = default ; use the value in the default theme (must exist there).");
- file->store_line("; Type.item = @somebutton_color ; reference to a library value previously defined.");
- file->store_line("; ");
- file->store_line("; Library Syntax: ");
- file->store_line("; --------------- ");
- file->store_line("; ");
- file->store_line("; Must be placed in section [library], but usage is optional.");
- file->store_line("; ");
- file->store_line("; item = [value] ; same as Theme, but assign to library.");
- file->store_line("; ");
- file->store_line("; examples:");
- file->store_line("; ");
- file->store_line("; [library]");
- file->store_line("; ");
- file->store_line("; default_button_color = #FF00FF");
- file->store_line("; ");
- file->store_line("; [theme]");
- file->store_line("; ");
- file->store_line("; Button.color = @default_button_color ; used reference.");
- file->store_line("; ");
- file->store_line("; ******************* ");
- file->store_line("; ");
- file->store_line("; Template Generated Using: " + String(VERSION_FULL_BUILD));
- file->store_line("; ");
- file->store_line("; ");
- file->store_line("");
- file->store_line("[library]");
- file->store_line("");
- file->store_line("; place library stuff here");
- file->store_line("");
- file->store_line("[theme]");
- file->store_line("");
- file->store_line("");
-
- // Write default theme.
- for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
- _TECategory &tc = E->get();
-
- String underline = "; ";
- for (int i = 0; i < E->key().length(); i++) {
- underline += "*";
- }
-
- file->store_line("");
- file->store_line(underline);
- file->store_line("; " + E->key());
- file->store_line(underline);
-
- if (tc.stylebox_items.size()) {
- file->store_line("\n; StyleBox Items:\n");
- }
-
- for (Set<_TECategory::RefItem<StyleBox>>::Element *F = tc.stylebox_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.font_items.size()) {
- file->store_line("\n; Font Items:\n");
- }
-
- for (Set<_TECategory::RefItem<Font>>::Element *F = tc.font_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.font_size_items.size()) {
- file->store_line("\n; Font Size Items:\n");
- }
-
- for (Set<_TECategory::Item<int>>::Element *F = tc.font_size_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.icon_items.size()) {
- file->store_line("\n; Icon Items:\n");
- }
-
- for (Set<_TECategory::RefItem<Texture2D>>::Element *F = tc.icon_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.color_items.size()) {
- file->store_line("\n; Color Items:\n");
- }
-
- for (Set<_TECategory::Item<Color>>::Element *F = tc.color_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.constant_items.size()) {
- file->store_line("\n; Constant Items:\n");
- }
-
- for (Set<_TECategory::Item<int>>::Element *F = tc.constant_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
- }
-
- file->close();
- memdelete(file);
-}
-
-void ThemeEditor::_theme_create_menu_cbk(int p_option) {
- bool import = (p_option == POPUP_IMPORT_EDITOR_THEME);
-
- Ref<Theme> base_theme;
-
- if (p_option == POPUP_CREATE_EMPTY) {
- base_theme = Theme::get_default();
- } else {
- base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme();
- }
-
- {
- List<StringName> types;
- base_theme->get_type_list(&types);
-
- for (List<StringName>::Element *T = types.front(); T; T = T->next()) {
- StringName type = T->get();
-
- List<StringName> icons;
- base_theme->get_icon_list(type, &icons);
-
- for (List<StringName>::Element *E = icons.front(); E; E = E->next()) {
- theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture2D>());
- }
-
- List<StringName> styleboxs;
- base_theme->get_stylebox_list(type, &styleboxs);
-
- for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) {
- theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>());
- }
-
- List<StringName> fonts;
- base_theme->get_font_list(type, &fonts);
-
- for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) {
- theme->set_font(E->get(), type, Ref<Font>());
- }
-
- List<StringName> font_sizes;
- base_theme->get_font_size_list(type, &font_sizes);
-
- for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) {
- theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type));
- }
-
- List<StringName> colors;
- base_theme->get_color_list(type, &colors);
-
- for (List<StringName>::Element *E = colors.front(); E; E = E->next()) {
- theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color());
- }
-
- List<StringName> constants;
- base_theme->get_constant_list(type, &constants);
-
- for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type));
- }
- }
- }
-}
-
void ThemeEditor::_theme_edit_button_cbk() {
- theme_edit_dialog->popup_centered(Size2(800, 640) * EDSCALE);
+ theme_edit_dialog->popup_centered(Size2(850, 760) * EDSCALE);
}
void ThemeEditor::_notification(int p_what) {
@@ -1059,19 +1954,9 @@ ThemeEditor::ThemeEditor() {
top_menu->add_child(memnew(Label(TTR("Preview:"))));
top_menu->add_spacer(false);
- theme_create_menu = memnew(MenuButton);
- theme_create_menu->set_text(TTR("Create Theme..."));
- theme_create_menu->set_tooltip(TTR("Create a new Theme."));
- theme_create_menu->get_popup()->add_item(TTR("Empty Template"), POPUP_CREATE_EMPTY);
- theme_create_menu->get_popup()->add_separator();
- theme_create_menu->get_popup()->add_item(TTR("Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
- theme_create_menu->get_popup()->add_item(TTR("From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME);
- top_menu->add_child(theme_create_menu);
- theme_create_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_create_menu_cbk));
-
theme_edit_button = memnew(Button);
- theme_edit_button->set_text(TTR("Edit Theme Items"));
- theme_edit_button->set_tooltip(TTR("Customize Theme items."));
+ theme_edit_button->set_text(TTR("Manage Items"));
+ theme_edit_button->set_tooltip(TTR("Add, remove, organize and import Theme items."));
theme_edit_button->set_flat(true);
theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk));
top_menu->add_child(theme_edit_button);
@@ -1260,11 +2145,6 @@ ThemeEditor::ThemeEditor() {
theme_edit_dialog = memnew(ThemeItemEditorDialog);
theme_edit_dialog->hide();
add_child(theme_edit_dialog);
-
- file_dialog = memnew(EditorFileDialog);
- file_dialog->add_filter("*.theme ; " + TTR("Theme File"));
- add_child(file_dialog);
- file_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_save_template_cbk));
}
void ThemeEditorPlugin::edit(Object *p_node) {
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 0a840aecd7..5f4de68f45 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -41,14 +41,148 @@
#include "editor/editor_node.h"
+class ThemeItemImportTree : public VBoxContainer {
+ GDCLASS(ThemeItemImportTree, VBoxContainer);
+
+ Ref<Theme> edited_theme;
+ Ref<Theme> base_theme;
+
+ struct ThemeItem {
+ String type_name;
+ Theme::DataType data_type;
+ String item_name;
+
+ bool operator<(const ThemeItem &p_item) const {
+ if (type_name == p_item.type_name && data_type == p_item.data_type) {
+ return item_name < p_item.item_name;
+ }
+ if (type_name == p_item.type_name) {
+ return data_type < p_item.data_type;
+ }
+ return type_name < p_item.type_name;
+ }
+ };
+
+ enum ItemCheckedState {
+ SELECT_IMPORT_DEFINITION,
+ SELECT_IMPORT_FULL,
+ };
+
+ Map<ThemeItem, ItemCheckedState> selected_items;
+
+ LineEdit *import_items_filter;
+
+ Tree *import_items_tree;
+ List<TreeItem *> tree_color_items;
+ List<TreeItem *> tree_constant_items;
+ List<TreeItem *> tree_font_items;
+ List<TreeItem *> tree_font_size_items;
+ List<TreeItem *> tree_icon_items;
+ List<TreeItem *> tree_stylebox_items;
+
+ bool updating_tree = false;
+
+ enum ItemActionFlag {
+ IMPORT_ITEM = 1,
+ IMPORT_ITEM_DATA = 2,
+ };
+
+ TextureRect *select_colors_icon;
+ Label *select_colors_label;
+ Button *select_all_colors_button;
+ Button *select_full_colors_button;
+ Button *deselect_all_colors_button;
+ Label *total_selected_colors_label;
+
+ TextureRect *select_constants_icon;
+ Label *select_constants_label;
+ Button *select_all_constants_button;
+ Button *select_full_constants_button;
+ Button *deselect_all_constants_button;
+ Label *total_selected_constants_label;
+
+ TextureRect *select_fonts_icon;
+ Label *select_fonts_label;
+ Button *select_all_fonts_button;
+ Button *select_full_fonts_button;
+ Button *deselect_all_fonts_button;
+ Label *total_selected_fonts_label;
+
+ TextureRect *select_font_sizes_icon;
+ Label *select_font_sizes_label;
+ Button *select_all_font_sizes_button;
+ Button *select_full_font_sizes_button;
+ Button *deselect_all_font_sizes_button;
+ Label *total_selected_font_sizes_label;
+
+ TextureRect *select_icons_icon;
+ Label *select_icons_label;
+ Button *select_all_icons_button;
+ Button *select_full_icons_button;
+ Button *deselect_all_icons_button;
+ Label *total_selected_icons_label;
+
+ TextureRect *select_styleboxes_icon;
+ Label *select_styleboxes_label;
+ Button *select_all_styleboxes_button;
+ Button *select_full_styleboxes_button;
+ Button *deselect_all_styleboxes_button;
+ Label *total_selected_styleboxes_label;
+
+ HBoxContainer *select_icons_warning_hb;
+ TextureRect *select_icons_warning_icon;
+ Label *select_icons_warning;
+
+ Button *import_collapse_types_button;
+ Button *import_expand_types_button;
+ Button *import_select_all_button;
+ Button *import_select_full_button;
+ Button *import_deselect_all_button;
+
+ void _update_items_tree();
+ void _toggle_type_items(bool p_collapse);
+ void _filter_text_changed(const String &p_value);
+
+ void _store_selected_item(TreeItem *p_tree_item);
+ void _restore_selected_item(TreeItem *p_tree_item);
+ void _update_total_selected(Theme::DataType p_data_type);
+
+ void _tree_item_edited();
+ void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
+ void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
+ void _update_parent_items(TreeItem *p_root_item);
+
+ void _select_all_items_pressed();
+ void _select_full_items_pressed();
+ void _deselect_all_items_pressed();
+
+ void _select_all_data_type_pressed(int p_data_type);
+ void _select_full_data_type_pressed(int p_data_type);
+ void _deselect_all_data_type_pressed(int p_data_type);
+
+ void _import_selected();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_edited_theme(const Ref<Theme> &p_theme);
+ void set_base_theme(const Ref<Theme> &p_theme);
+ void reset_item_tree();
+
+ bool has_selected_items() const;
+
+ ThemeItemImportTree();
+};
+
class ThemeItemEditorDialog : public AcceptDialog {
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
Ref<Theme> edited_theme;
ItemList *edit_type_list;
- OptionButton *edit_add_class_options;
- LineEdit *edit_add_custom_value;
+ LineEdit *edit_add_type_value;
String edited_item_type;
Button *edit_items_add_color;
@@ -83,6 +217,19 @@ class ThemeItemEditorDialog : public AcceptDialog {
String edit_item_old_name;
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
+ ThemeItemImportTree *import_default_theme_items;
+ ThemeItemImportTree *import_editor_theme_items;
+ ThemeItemImportTree *import_other_theme_items;
+
+ LineEdit *import_another_theme_value;
+ Button *import_another_theme_button;
+ EditorFileDialog *import_another_theme_dialog;
+
+ ConfirmationDialog *confirm_closing_dialog;
+
+ void ok_pressed() override;
+ void _close_dialog();
+
void _dialog_about_to_show();
void _update_edit_types();
void _edited_type_selected(int p_item_idx);
@@ -90,8 +237,7 @@ class ThemeItemEditorDialog : public AcceptDialog {
void _update_edit_item_tree(String p_item_type);
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id);
- void _add_class_type_items();
- void _add_custom_type();
+ void _add_theme_type();
void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type);
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
void _remove_class_items();
@@ -103,6 +249,9 @@ class ThemeItemEditorDialog : public AcceptDialog {
void _confirm_edit_theme_item();
void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event);
+ void _open_select_another_theme();
+ void _select_another_theme_cbk(const String &p_path);
+
protected:
void _notification(int p_what);
@@ -115,29 +264,18 @@ public:
class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer);
- Panel *main_panel;
- MarginContainer *main_container;
Ref<Theme> theme;
- EditorFileDialog *file_dialog;
-
double time_left = 0;
Button *theme_edit_button;
- MenuButton *theme_create_menu;
ThemeItemEditorDialog *theme_edit_dialog;
- enum CreatePopupMode {
- POPUP_CREATE_EMPTY,
- POPUP_CREATE_EDITOR_EMPTY,
- POPUP_IMPORT_EDITOR_THEME,
- };
-
+ Panel *main_panel;
+ MarginContainer *main_container;
Tree *test_tree;
- void _save_template_cbk(String fname);
void _theme_edit_button_cbk();
- void _theme_create_menu_cbk(int p_option);
void _propagate_redraw(Control *p_at);
void _refresh_interval();