diff --git a/.defignore b/.defignore new file mode 100644 index 0000000..3e22129 --- /dev/null +++ b/.defignore @@ -0,0 +1 @@ +/dist \ No newline at end of file diff --git a/druid/druid.atlas b/druid/druid.atlas new file mode 100644 index 0000000..ce36b4e --- /dev/null +++ b/druid/druid.atlas @@ -0,0 +1,22 @@ +images { + image: "/druid/images/empty.png" +} +images { + image: "/druid/images/panels/rect_round2_width1.png" +} +images { + image: "/druid/images/panels/ui_circle_8.png" +} +images { + image: "/druid/images/panels/ui_circle_16.png" +} +images { + image: "/druid/images/panels/ui_circle_32.png" +} +images { + image: "/druid/images/panels/ui_circle_64.png" +} +images { + image: "/druid/images/pixel.png" +} +extrude_borders: 2 diff --git a/druid/fonts/Roboto-Bold.ttf b/druid/fonts/Roboto-Bold.ttf new file mode 100644 index 0000000..e64db79 Binary files /dev/null and b/druid/fonts/Roboto-Bold.ttf differ diff --git a/druid/fonts/Roboto-Regular.ttf b/druid/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..2d116d9 Binary files /dev/null and b/druid/fonts/Roboto-Regular.ttf differ diff --git a/druid/fonts/text_bold.font b/druid/fonts/text_bold.font new file mode 100644 index 0000000..82420e1 --- /dev/null +++ b/druid/fonts/text_bold.font @@ -0,0 +1,10 @@ +font: "/druid/fonts/Roboto-Bold.ttf" +material: "/builtins/fonts/font-df.material" +size: 40 +outline_alpha: 1.0 +outline_width: 2.0 +shadow_alpha: 1.0 +shadow_blur: 2 +output_format: TYPE_DISTANCE_FIELD +render_mode: MODE_MULTI_LAYER +characters: " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\302\241\302\277\303\200\303\202\303\206\303\207\303\210\303\211\303\212\303\213\303\216\303\217\303\224\303\231\303\233\303\234\303\240\303\241\303\242\303\243\303\244\303\246\303\247\303\250\303\251\303\252\303\253\303\255\303\256\303\257\303\261\303\263\303\264\303\271\303\273\303\274\303\277\305\222\305\223\305\270\320\201\320\220\320\221\320\222\320\223\320\224\320\225\320\226\320\227\320\230\320\231\320\232\320\233\320\234\320\235\320\236\320\237\320\240\320\241\320\242\320\243\320\244\320\245\320\246\320\247\320\250\320\251\320\252\320\253\320\254\320\255\320\256\320\257\320\260\320\261\320\262\320\263\320\264\320\265\320\266\320\267\320\270\320\271\320\272\320\273\320\274\320\275\320\276\320\277\321\200\321\201\321\202\321\203\321\204\321\205\321\206\321\207\321\210\321\211\321\212\321\213\321\214\321\215\321\216\321\217\321\221\343\200\202\343\201\202\343\201\213\343\201\214\343\201\215\343\201\223\343\201\227\343\201\231\343\201\233\343\201\237\343\201\244\343\201\247\343\201\250\343\201\252\343\201\253\343\201\256\343\201\257\343\201\276\343\202\212\343\202\213\343\202\222\343\202\223\343\202\241\343\202\242\343\202\243\343\202\244\343\202\246\343\202\255\343\202\257\343\202\260\343\202\262\343\202\263\343\202\267\343\202\270\343\202\271\343\202\273\343\202\277\343\203\203\343\203\206\343\203\207\343\203\210\343\203\211\343\203\213\343\203\215\343\203\221\343\203\224\343\203\225\343\203\226\343\203\227\343\203\231\343\203\234\343\203\235\343\203\240\343\203\241\343\203\242\343\203\243\343\203\245\343\203\247\343\203\251\343\203\252\343\203\253\343\203\254\343\203\255\343\203\263\343\203\274\344\270\200\344\270\207\344\270\252\344\270\255\344\271\260\344\272\213\344\273\230\344\273\243\344\273\266\344\275\240\344\275\277\344\276\213\344\277\241\345\205\203\345\205\245\345\205\267\345\206\205\345\207\272\345\207\273\345\210\206\345\210\227\345\211\252\345\212\233\345\212\237\345\212\250\345\215\225\345\217\226\345\217\243\345\220\210\345\231\250\345\235\227\345\236\202\345\237\272\345\240\261\345\255\230\345\261\236\345\270\246\345\271\263\346\200\247\346\201\257\346\203\205\346\211\213\346\212\236\346\213\251\346\214\201\346\214\211\346\215\256\346\225\260\346\226\207\346\227\245\346\230\257\346\234\200\346\234\211\346\234\254\346\236\220\346\237\204\346\237\245\346\243\222\346\250\241\346\251\237\346\255\244\346\260\264\346\261\275\346\262\241\346\265\213\346\266\210\346\267\267\347\202\271\347\224\250\347\224\273\347\231\276\347\232\204\347\233\264\347\234\213\347\240\201\347\241\256\347\242\272\347\244\272\347\252\227\347\256\200\347\273\204\347\276\216\350\203\275\350\241\250\350\243\201\350\250\200\350\252\215\350\252\236\350\256\244\350\257\225\350\257\255\350\263\274\350\264\255\350\273\212\350\275\246\350\276\223\350\277\231\351\200\211\351\201\270\351\222\256\351\253\230\352\260\200\352\260\204\352\262\214\352\262\240\352\263\240\352\265\254\352\265\255\352\270\260\352\271\214\353\212\224\353\212\245\353\213\210\353\213\244\353\213\250\353\213\254\353\213\271\353\214\200\353\215\260\353\220\234\353\223\210\353\223\234\353\224\251\353\236\214\353\237\254\353\240\214\353\240\245\353\241\234\353\241\235\353\245\274\353\246\254\353\246\255\353\247\214\353\247\244\353\251\224\353\252\250\353\252\251\353\260\261\353\262\204\353\262\244\353\263\264\353\263\270\353\270\224\354\202\254\354\204\234\354\204\240\354\204\261\354\205\230\354\206\214\354\206\215\354\210\230\354\212\244\354\212\265\354\213\234\354\213\240\354\225\240\354\226\264\354\226\270\354\227\206\354\227\220\354\230\210\354\232\224\354\232\251\354\235\200\354\235\204\354\235\230\354\235\264\354\235\270\354\235\274\354\236\204\354\236\205\354\236\210\354\240\225\354\247\200\354\247\201\354\247\234\354\260\250\354\260\275\354\265\234\354\266\234\354\267\250\354\275\224\355\201\264\355\203\235\355\204\260\355\205\214\355\212\270\355\212\274\355\214\214\355\214\250\355\214\254\355\217\211\355\217\254\355\224\204\355\225\221\355\225\230\355\225\234\355\225\250\355\231\225\357\274\201\357\274\237" diff --git a/druid/fonts/text_regular.font b/druid/fonts/text_regular.font new file mode 100644 index 0000000..b872982 --- /dev/null +++ b/druid/fonts/text_regular.font @@ -0,0 +1,8 @@ +font: "/druid/fonts/Roboto-Regular.ttf" +material: "/builtins/fonts/font-df.material" +size: 40 +outline_alpha: 1.0 +outline_width: 2.0 +output_format: TYPE_DISTANCE_FIELD +render_mode: MODE_MULTI_LAYER +characters: " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\302\241\302\277\303\200\303\202\303\206\303\207\303\210\303\211\303\212\303\213\303\216\303\217\303\224\303\231\303\233\303\234\303\240\303\241\303\242\303\243\303\244\303\246\303\247\303\250\303\251\303\252\303\253\303\255\303\256\303\257\303\261\303\263\303\264\303\271\303\273\303\274\303\277\305\222\305\223\305\270\320\201\320\220\320\221\320\222\320\223\320\224\320\225\320\226\320\227\320\230\320\231\320\232\320\233\320\234\320\235\320\236\320\237\320\240\320\241\320\242\320\243\320\244\320\245\320\246\320\247\320\250\320\251\320\252\320\253\320\254\320\255\320\256\320\257\320\260\320\261\320\262\320\263\320\264\320\265\320\266\320\267\320\270\320\271\320\272\320\273\320\274\320\275\320\276\320\277\321\200\321\201\321\202\321\203\321\204\321\205\321\206\321\207\321\210\321\211\321\212\321\213\321\214\321\215\321\216\321\217\321\221\343\200\202\343\201\202\343\201\213\343\201\214\343\201\215\343\201\223\343\201\227\343\201\231\343\201\233\343\201\237\343\201\244\343\201\247\343\201\250\343\201\252\343\201\253\343\201\256\343\201\257\343\201\276\343\202\212\343\202\213\343\202\222\343\202\223\343\202\241\343\202\242\343\202\243\343\202\244\343\202\246\343\202\255\343\202\257\343\202\260\343\202\262\343\202\263\343\202\267\343\202\270\343\202\271\343\202\273\343\202\277\343\203\203\343\203\206\343\203\207\343\203\210\343\203\211\343\203\213\343\203\215\343\203\221\343\203\224\343\203\225\343\203\226\343\203\227\343\203\231\343\203\234\343\203\235\343\203\240\343\203\241\343\203\242\343\203\243\343\203\245\343\203\247\343\203\251\343\203\252\343\203\253\343\203\254\343\203\255\343\203\263\343\203\274\344\270\200\344\270\207\344\270\252\344\270\255\344\271\260\344\272\213\344\273\230\344\273\243\344\273\266\344\275\240\344\275\277\344\276\213\344\277\241\345\205\203\345\205\245\345\205\267\345\206\205\345\207\272\345\207\273\345\210\206\345\210\227\345\211\252\345\212\233\345\212\237\345\212\250\345\215\225\345\217\226\345\217\243\345\220\210\345\231\250\345\235\227\345\236\202\345\237\272\345\240\261\345\255\230\345\261\236\345\270\246\345\271\263\346\200\247\346\201\257\346\203\205\346\211\213\346\212\236\346\213\251\346\214\201\346\214\211\346\215\256\346\225\260\346\226\207\346\227\245\346\230\257\346\234\200\346\234\211\346\234\254\346\236\220\346\237\204\346\237\245\346\243\222\346\250\241\346\251\237\346\255\244\346\260\264\346\261\275\346\262\241\346\265\213\346\266\210\346\267\267\347\202\271\347\224\250\347\224\273\347\231\276\347\232\204\347\233\264\347\234\213\347\240\201\347\241\256\347\242\272\347\244\272\347\252\227\347\256\200\347\273\204\347\276\216\350\203\275\350\241\250\350\243\201\350\250\200\350\252\215\350\252\236\350\256\244\350\257\225\350\257\255\350\263\274\350\264\255\350\273\212\350\275\246\350\276\223\350\277\231\351\200\211\351\201\270\351\222\256\351\253\230\352\260\200\352\260\204\352\262\214\352\262\240\352\263\240\352\265\254\352\265\255\352\270\260\352\271\214\353\212\224\353\212\245\353\213\210\353\213\244\353\213\250\353\213\254\353\213\271\353\214\200\353\215\260\353\220\234\353\223\210\353\223\234\353\224\251\353\236\214\353\237\254\353\240\214\353\240\245\353\241\234\353\241\235\353\245\274\353\246\254\353\246\255\353\247\214\353\247\244\353\251\224\353\252\250\353\252\251\353\260\261\353\262\204\353\262\244\353\263\264\353\263\270\353\270\224\354\202\254\354\204\234\354\204\240\354\204\261\354\205\230\354\206\214\354\206\215\354\210\230\354\212\244\354\212\265\354\213\234\354\213\240\354\225\240\354\226\264\354\226\270\354\227\206\354\227\220\354\230\210\354\232\224\354\232\251\354\235\200\354\235\204\354\235\230\354\235\264\354\235\270\354\235\274\354\236\204\354\236\205\354\236\210\354\240\225\354\247\200\354\247\201\354\247\234\354\260\250\354\260\275\354\265\234\354\266\234\354\267\250\354\275\224\355\201\264\355\203\235\355\204\260\355\205\214\355\212\270\355\212\274\355\214\214\355\214\250\355\214\254\355\217\211\355\217\254\355\224\204\355\225\221\355\225\230\355\225\234\355\225\250\355\231\225\357\274\201\357\274\237" diff --git a/druid/images/empty.png b/druid/images/empty.png new file mode 100755 index 0000000..36b4ff1 Binary files /dev/null and b/druid/images/empty.png differ diff --git a/druid/images/panels/rect_round2_width1.png b/druid/images/panels/rect_round2_width1.png new file mode 100644 index 0000000..bbde0a6 Binary files /dev/null and b/druid/images/panels/rect_round2_width1.png differ diff --git a/druid/images/panels/ui_circle_16.png b/druid/images/panels/ui_circle_16.png new file mode 100644 index 0000000..559c77c Binary files /dev/null and b/druid/images/panels/ui_circle_16.png differ diff --git a/druid/images/panels/ui_circle_32.png b/druid/images/panels/ui_circle_32.png new file mode 100644 index 0000000..82932ca Binary files /dev/null and b/druid/images/panels/ui_circle_32.png differ diff --git a/druid/images/panels/ui_circle_64.png b/druid/images/panels/ui_circle_64.png new file mode 100644 index 0000000..c74547d Binary files /dev/null and b/druid/images/panels/ui_circle_64.png differ diff --git a/druid/images/panels/ui_circle_8.png b/druid/images/panels/ui_circle_8.png new file mode 100644 index 0000000..0d49e70 Binary files /dev/null and b/druid/images/panels/ui_circle_8.png differ diff --git a/druid/images/pixel.png b/druid/images/pixel.png new file mode 100755 index 0000000..9619df8 Binary files /dev/null and b/druid/images/pixel.png differ diff --git a/example/examples/basic/checkbox/checkbox.gui b/example/examples/basic/checkbox/checkbox.gui new file mode 100644 index 0000000..287fcdb --- /dev/null +++ b/example/examples/basic/checkbox/checkbox.gui @@ -0,0 +1,77 @@ +fonts { + name: "text_bold" + font: "/example/assets/fonts/text_bold.font" +} +textures { + name: "druid" + texture: "/example/assets/druid.atlas" +} +nodes { + size { + x: 70.0 + y: 70.0 + } + type: TYPE_BOX + id: "root" + inherit_alpha: true + size_mode: SIZE_MODE_AUTO + visible: false +} +nodes { + size { + x: 40.0 + y: 40.0 + } + color { + x: 0.463 + y: 0.475 + z: 0.49 + } + type: TYPE_BOX + texture: "druid/rect_round2_width1" + id: "button" + parent: "root" + inherit_alpha: true + slice9 { + x: 4.0 + y: 4.0 + z: 4.0 + w: 4.0 + } +} +nodes { + color { + x: 0.722 + y: 0.741 + z: 0.761 + } + type: TYPE_BOX + texture: "druid/icon_check" + id: "icon" + parent: "button" + inherit_alpha: true + size_mode: SIZE_MODE_AUTO +} +nodes { + position { + y: -20.0 + } + size { + x: 40.0 + y: 4.0 + } + color { + x: 0.894 + y: 0.506 + z: 0.333 + } + type: TYPE_BOX + texture: "druid/pixel" + id: "selected" + pivot: PIVOT_S + adjust_mode: ADJUST_MODE_STRETCH + parent: "button" + inherit_alpha: true +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT diff --git a/example/examples/basic/checkbox/checkbox.lua b/example/examples/basic/checkbox/checkbox.lua new file mode 100644 index 0000000..32bee28 --- /dev/null +++ b/example/examples/basic/checkbox/checkbox.lua @@ -0,0 +1,50 @@ +local component = require("druid.component") +local event = require("druid.event") + +---@class checkbox: druid.base_component +---@field druid druid_instance +---@field button druid.button +local M = component.create("checkbox") + + +---@param template string +---@param nodes table +function M:init(template, nodes) + self.druid = self:get_druid(template, nodes) + + self.button = self.druid:new_button("root", self.on_checkbox_click) -- Button to handle checkbox + self.icon = self:get_node("icon") -- Checkbox icon to hide/show + self.selected = self:get_node("selected") -- Selected effect to show when checkbox is changed + gui.set_alpha(self.selected, 0) + + self:set_state(false) + + self.on_state_changed = event.create() +end + + +function M:on_checkbox_click() + self:set_state(not self.is_enabled) + self.on_state_changed:trigger(self.is_enabled) +end + + +function M:set_state(is_enabled) + if self.is_enabled == is_enabled then + return + end + + self.is_enabled = is_enabled + gui.set_enabled(self.icon, self.is_enabled) + + gui.set_alpha(self.selected, 1) + gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16) +end + + +function M:get_state() + return self.is_enabled +end + + +return M diff --git a/example/examples/basic/checkbox_group/checkbox_group.gui b/example/examples/basic/checkbox_group/checkbox_group.gui new file mode 100644 index 0000000..275a269 --- /dev/null +++ b/example/examples/basic/checkbox_group/checkbox_group.gui @@ -0,0 +1,120 @@ +fonts { + name: "text_bold" + font: "/example/assets/fonts/text_bold.font" +} +textures { + name: "druid" + texture: "/example/assets/druid.atlas" +} +nodes { + size { + x: 200.0 + y: 100.0 + } + type: TYPE_BOX + id: "root" + inherit_alpha: true + size_mode: SIZE_MODE_AUTO + visible: false +} +nodes { + position { + x: -100.0 + } + type: TYPE_TEMPLATE + id: "checkbox_1" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_1/root" + parent: "checkbox_1" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_1/button" + parent: "checkbox_1/root" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_1/icon" + parent: "checkbox_1/button" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_1/selected" + parent: "checkbox_1/button" + template_node_child: true +} +nodes { + type: TYPE_TEMPLATE + id: "checkbox_2" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_2/root" + parent: "checkbox_2" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_2/button" + parent: "checkbox_2/root" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_2/icon" + parent: "checkbox_2/button" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_2/selected" + parent: "checkbox_2/button" + template_node_child: true +} +nodes { + position { + x: 100.0 + } + type: TYPE_TEMPLATE + id: "checkbox_3" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_3/root" + parent: "checkbox_3" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_3/button" + parent: "checkbox_3/root" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_3/icon" + parent: "checkbox_3/button" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "checkbox_3/selected" + parent: "checkbox_3/button" + template_node_child: true +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT diff --git a/example/examples/basic/checkbox_group/checkbox_group.lua b/example/examples/basic/checkbox_group/checkbox_group.lua new file mode 100644 index 0000000..cff045f --- /dev/null +++ b/example/examples/basic/checkbox_group/checkbox_group.lua @@ -0,0 +1,39 @@ +local event = require("druid.event") +local component = require("druid.component") + +-- Require checkbox component from checkbox example +local checkbox = require("example.examples.basic.checkbox.checkbox") + +---@class checkbox_group: druid.base_component +---@field druid druid_instance +---@field button druid.button +local M = component.create("checkbox_group") + + +---@param template string +---@param nodes table +function M:init(template, nodes) + self.druid = self:get_druid(template, nodes) + + self.checkbox_1 = self.druid:new(checkbox, "checkbox_1") + self.checkbox_2 = self.druid:new(checkbox, "checkbox_2") + self.checkbox_3 = self.druid:new(checkbox, "checkbox_3") + + self.checkbox_1.on_state_changed:subscribe(self.on_checkbox_click, self) + self.checkbox_2.on_state_changed:subscribe(self.on_checkbox_click, self) + self.checkbox_3.on_state_changed:subscribe(self.on_checkbox_click, self) + + self.on_state_changed = event.create() +end + + +function M:on_checkbox_click() + print("Checkbox 1: ", self.checkbox_1:get_state()) + print("Checkbox 2: ", self.checkbox_2:get_state()) + print("Checkbox 3: ", self.checkbox_3:get_state()) + + self.on_state_changed:trigger(self.checkbox_1:get_state(), self.checkbox_2:get_state(), self.checkbox_3:get_state()) +end + + +return M diff --git a/example/examples/basic/radio_group/radio_group.gui b/example/examples/basic/radio_group/radio_group.gui new file mode 100644 index 0000000..f4b822a --- /dev/null +++ b/example/examples/basic/radio_group/radio_group.gui @@ -0,0 +1,195 @@ +fonts { + name: "text_bold" + font: "/example/assets/fonts/text_bold.font" +} +textures { + name: "druid" + texture: "/example/assets/druid.atlas" +} +nodes { + size { + x: 200.0 + y: 100.0 + } + type: TYPE_BOX + id: "root" + inherit_alpha: true + size_mode: SIZE_MODE_AUTO + visible: false +} +nodes { + position { + x: -100.0 + } + type: TYPE_TEMPLATE + id: "checkbox_1" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_1/root" + parent: "checkbox_1" + template_node_child: true +} +nodes { + color { + x: 0.31 + y: 0.318 + z: 0.322 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "checkbox_1/button" + parent: "checkbox_1/root" + slice9 { + x: 8.0 + y: 8.0 + z: 8.0 + w: 8.0 + } + overridden_fields: 5 + overridden_fields: 9 + overridden_fields: 22 + template_node_child: true +} +nodes { + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_1/icon" + parent: "checkbox_1/button" + overridden_fields: 9 + template_node_child: true +} +nodes { + position { + y: -8.0 + } + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_1/selected" + parent: "checkbox_1/button" + overridden_fields: 1 + overridden_fields: 9 + overridden_fields: 38 + template_node_child: true + size_mode: SIZE_MODE_AUTO +} +nodes { + type: TYPE_TEMPLATE + id: "checkbox_2" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_2/root" + parent: "checkbox_2" + template_node_child: true +} +nodes { + color { + x: 0.31 + y: 0.318 + z: 0.322 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "checkbox_2/button" + parent: "checkbox_2/root" + slice9 { + x: 8.0 + y: 8.0 + z: 8.0 + w: 8.0 + } + overridden_fields: 5 + overridden_fields: 9 + overridden_fields: 22 + template_node_child: true +} +nodes { + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_2/icon" + parent: "checkbox_2/button" + overridden_fields: 9 + template_node_child: true +} +nodes { + position { + y: -8.0 + } + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_2/selected" + parent: "checkbox_2/button" + overridden_fields: 1 + overridden_fields: 9 + overridden_fields: 38 + template_node_child: true + size_mode: SIZE_MODE_AUTO +} +nodes { + position { + x: 100.0 + } + type: TYPE_TEMPLATE + id: "checkbox_3" + parent: "root" + inherit_alpha: true + template: "/example/examples/basic/checkbox/checkbox.gui" +} +nodes { + type: TYPE_BOX + id: "checkbox_3/root" + parent: "checkbox_3" + template_node_child: true +} +nodes { + color { + x: 0.31 + y: 0.318 + z: 0.322 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "checkbox_3/button" + parent: "checkbox_3/root" + slice9 { + x: 8.0 + y: 8.0 + z: 8.0 + w: 8.0 + } + overridden_fields: 5 + overridden_fields: 9 + overridden_fields: 22 + template_node_child: true +} +nodes { + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_3/icon" + parent: "checkbox_3/button" + overridden_fields: 9 + template_node_child: true +} +nodes { + position { + y: -8.0 + } + type: TYPE_BOX + texture: "druid/ui_circle_16" + id: "checkbox_3/selected" + parent: "checkbox_3/button" + overridden_fields: 1 + overridden_fields: 9 + overridden_fields: 38 + template_node_child: true + size_mode: SIZE_MODE_AUTO +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT diff --git a/example/examples/basic/radio_group/radio_group.lua b/example/examples/basic/radio_group/radio_group.lua new file mode 100644 index 0000000..1b74273 --- /dev/null +++ b/example/examples/basic/radio_group/radio_group.lua @@ -0,0 +1,55 @@ +local component = require("druid.component") +local event = require("druid.event") + +-- Require checkbox component from checkbox example +local checkbox = require("example.examples.basic.checkbox.checkbox") + +---@class radio_group: druid.base_component +---@field druid druid_instance +---@field button druid.button +local M = component.create("radio_group") + + +---@param template string +---@param nodes table +function M:init(template, nodes) + self.druid = self:get_druid(template, nodes) + + self.state = {} + self.checkboxes = { + self.druid:new(checkbox, "checkbox_1"), + self.druid:new(checkbox, "checkbox_2"), + self.druid:new(checkbox, "checkbox_3") + } + + for i = 1, #self.checkboxes do + self.checkboxes[i].on_state_changed:subscribe(self.on_checkbox_click, self) + self.state[i] = false + end + + self.checkboxes[1]:set_state(true) + self.state[1] = true + + self.on_state_changed = event.create() +end + + +function M:on_checkbox_click() + local new_clicked = nil + for index = 1, #self.checkboxes do + if self.checkboxes[index]:get_state() ~= self.state[index] then + new_clicked = index + break + end + end + + for index = 1, #self.state do + self.checkboxes[index]:set_state(index == new_clicked) + self.state[index] = index == new_clicked + end + + self.on_state_changed:trigger(new_clicked) +end + + +return M diff --git a/example/examples/widgets/examples_list.lua b/example/examples/widgets/examples_list.lua new file mode 100644 index 0000000..6209cdd --- /dev/null +++ b/example/examples/widgets/examples_list.lua @@ -0,0 +1,59 @@ +local M = {} + +function M.get_examples() + ---@type druid.example.data[] + return { + { + name_id = "ui_example_widget_hover_hint", + information_text_id = "ui_example_widget_hover_hint_description", + template = "hover_hint_example", + root = "hover_hint_example/root", + code_url = "example/examples/widgets/hover_hint/hover_hint_example.lua", + component_class = require("example.examples.widgets.hover_hint.hover_hint_example"), + }, + { + name_id = "ui_example_widget_property_button", + information_text_id = "ui_example_widget_property_button_description", + template = "property_button", + root = "property_button/root", + code_url = "example/components/properties_panel/properties/property_button.lua", + component_class = require("example.components.properties_panel.properties.property_button"), + on_create = function(instance, output_list) + ---@cast instance property_button + instance.button.on_click:subscribe(function() + output_list:add_log_text("Button clicked") + end) + end, + }, + { + name_id = "ui_example_widget_property_slider", + information_text_id = "ui_example_widget_property_slider_description", + template = "property_slider", + root = "property_slider/root", + code_url = "example/components/properties_panel/properties/property_slider.lua", + component_class = require("example.components.properties_panel.properties.property_slider"), + on_create = function(instance, output_list) + ---@cast instance property_slider + instance.slider.on_change_value:subscribe(function(_, value) + output_list:add_log_text("Slider value: " .. value) + end) + end, + }, + { + name_id = "ui_example_widget_property_checkbox", + information_text_id = "ui_example_widget_property_checkbox_description", + template = "property_checkbox", + root = "property_checkbox/root", + code_url = "example/components/properties_panel/properties/property_checkbox.lua", + component_class = require("example.components.properties_panel.properties.property_checkbox"), + on_create = function(instance, output_list) + ---@cast instance property_checkbox + instance.button.on_click:subscribe(function() + output_list:add_log_text("Checkbox clicked") + end) + end, + }, + } +end + +return M \ No newline at end of file diff --git a/example/examples/widgets/hover_hint/hover_hint.gui b/example/examples/widgets/hover_hint/hover_hint.gui new file mode 100644 index 0000000..9c8190c --- /dev/null +++ b/example/examples/widgets/hover_hint/hover_hint.gui @@ -0,0 +1,76 @@ +fonts { + name: "text_regular" + font: "/example/assets/fonts/text_regular.font" +} +textures { + name: "druid" + texture: "/example/assets/druid.atlas" +} +nodes { + size { + x: 200.0 + y: 90.0 + } + type: TYPE_BOX + id: "root" + inherit_alpha: true + visible: false +} +nodes { + size { + x: 250.0 + y: 90.0 + } + color { + x: 0.129 + y: 0.141 + z: 0.157 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "panel_hint" + parent: "root" + inherit_alpha: true + slice9 { + x: 16.0 + y: 16.0 + z: 16.0 + w: 16.0 + } +} +nodes { + scale { + x: 0.65 + y: 0.65 + } + size { + x: 350.0 + y: 150.0 + } + color { + x: 0.463 + y: 0.475 + z: 0.49 + } + type: TYPE_TEXT + text: "Show hint on hover" + font: "text_regular" + id: "text_hint" + outline { + x: 1.0 + y: 1.0 + z: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + } + line_break: true + parent: "panel_hint" + inherit_alpha: true + outline_alpha: 0.0 + shadow_alpha: 0.0 +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT diff --git a/example/examples/widgets/hover_hint/hover_hint.lua b/example/examples/widgets/hover_hint/hover_hint.lua new file mode 100644 index 0000000..1578106 --- /dev/null +++ b/example/examples/widgets/hover_hint/hover_hint.lua @@ -0,0 +1,139 @@ +local helper = require("druid.helper") +local druid_const = require("druid.const") +local component = require("druid.component") + +---@class hover_hint: druid.base_component +---@field druid druid_instance +---@field root node +---@field panel_hint node +---@field text_hint druid.text +---@field hovers druid.hover[] +---@field is_shown boolean +---@field private _hint_text string +---@field private _hover_timer_id hash +local M = component.create("hover_hint") + +local TIMER_DELAY = 0.5 +local MIN_PANEL_WIDTH = 100 +local MIN_PANEL_HEIGHT = 50 +local PANEL_MARGIN = 40 +local HINT_OFFSET = 20 + +---@param template string +function M:init(template, nodes) + self.druid = self:get_druid(template, nodes) + + self.root = self:get_node("root") + self.panel_hint = self:get_node("panel_hint") + self.text_hint = self.druid:new_text("text_hint") + + self.hovers = {} + self._timer_id = nil + self.is_shown = false + + gui.set_enabled(self.root, false) +end + + +---@param node node|string +---@param hint_text string +---@param pivot_point constant +---@param content_pivot constant +function M:add_hover_hint(node, hint_text, pivot_point, content_pivot) + local hover = self.druid:new_hover(node, nil, function(_, is_hover) + self:hide_hint() + + if is_hover then + self._timer_id = timer.delay(TIMER_DELAY, false, function() + self._timer_id = nil + self:show_hint(node, hint_text, pivot_point, content_pivot) + end) + end + end) + + table.insert(self.hovers, hover) +end + + +function M:hide_hint() + if self._timer_id then + timer.cancel(self._timer_id) + self._timer_id = nil + end + + if self.is_shown then + self.is_shown = false + gui.animate(self.root, "color.w", 0, gui.EASING_OUTSINE, 0.2, 0, function() + gui.set_enabled(self.root, false) + end) + end +end + + +---@param hint_text string +---@param pivot_point constant +---@param content_pivot constant +function M:show_hint(node, hint_text, pivot_point, content_pivot) + self:refresh_content(node, hint_text, pivot_point, content_pivot) + + self.is_shown = true + + do -- Animate appear + gui.set_enabled(self.root, true) + gui.set_alpha(self.root, 0) + gui.animate(self.root, "color.w", 1, gui.EASING_OUTSINE, 0.2) + end +end + + +---@private +function M:refresh_content(node, hint_text, pivot_point, content_pivot) + self.text_hint:set_to(hint_text) + local text_width, text_height = self.text_hint:get_text_size() + + local panel_width = math.max(text_width, MIN_PANEL_WIDTH) + PANEL_MARGIN + local panel_height = math.max(text_height, MIN_PANEL_HEIGHT) + PANEL_MARGIN + + gui.set(self.root, "size.x", panel_width) + gui.set(self.root, "size.y", panel_height) + gui.set(self.panel_hint, "size.x", panel_width) + gui.set(self.panel_hint, "size.y", panel_height) + + self:refresh_position(node, pivot_point, content_pivot) +end + + +---@private +---@param node node +---@param pivot_point constant +---@param content_pivot constant +function M:refresh_position(node, pivot_point, content_pivot) + local screen_position = gui.get_screen_position(node) + local node_size = gui.get_size(node) + node_size.x = node_size.x + HINT_OFFSET * 2 + node_size.y = node_size.y + HINT_OFFSET * 2 + + -- Offset for trigger node + local offset = -vmath.mul_per_elem(node_size, druid_const.PIVOTS[gui.get_pivot(node)]) + + -- Offset from center to pivot pointi + offset = offset + vmath.mul_per_elem(node_size, druid_const.PIVOTS[pivot_point]) + + -- Offset for hint component + local hint_size = gui.get_size(self.root) + offset = offset - vmath.mul_per_elem(hint_size, druid_const.PIVOTS[content_pivot]) + + -- Position + local world_scale = helper.get_scene_scale(self.root) + local local_pos = gui.screen_to_local(self.root, screen_position) / world_scale.x + gui.set_position(self.root, local_pos) + + local position = gui.get_position(self.root) + if offset then + position = position + offset + end + gui.set_position(self.root, position) +end + + +return M diff --git a/example/examples/widgets/hover_hint/hover_hint_example.gui b/example/examples/widgets/hover_hint/hover_hint_example.gui new file mode 100644 index 0000000..8bb74a9 --- /dev/null +++ b/example/examples/widgets/hover_hint/hover_hint_example.gui @@ -0,0 +1,155 @@ +textures { + name: "druid" + texture: "/example/assets/druid.atlas" +} +nodes { + size { + x: 1000.0 + y: 1000.0 + } + color { + x: 0.173 + y: 0.184 + z: 0.204 + } + type: TYPE_BOX + texture: "druid/ui_circle_64" + id: "root" + inherit_alpha: true + slice9 { + x: 32.0 + y: 32.0 + z: 32.0 + w: 32.0 + } +} +nodes { + position { + y: 270.0 + } + type: TYPE_TEMPLATE + id: "hover_hint" + parent: "root" + inherit_alpha: true + template: "/example/examples/widgets/hover_hint/hover_hint.gui" +} +nodes { + type: TYPE_BOX + id: "hover_hint/root" + parent: "hover_hint" + template_node_child: true +} +nodes { + type: TYPE_BOX + id: "hover_hint/panel_hint" + parent: "hover_hint/root" + template_node_child: true +} +nodes { + type: TYPE_TEXT + id: "hover_hint/text_hint" + parent: "hover_hint/panel_hint" + template_node_child: true +} +nodes { + position { + y: 100.0 + } + size { + x: 140.0 + y: 140.0 + } + color { + x: 0.902 + y: 0.875 + z: 0.624 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "node_yellow" + parent: "root" + inherit_alpha: true + slice9 { + x: 16.0 + y: 16.0 + z: 16.0 + w: 16.0 + } +} +nodes { + position { + x: 200.0 + } + size { + x: 140.0 + y: 140.0 + } + color { + x: 0.957 + y: 0.608 + z: 0.608 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "node_red" + parent: "root" + inherit_alpha: true + slice9 { + x: 16.0 + y: 16.0 + z: 16.0 + w: 16.0 + } +} +nodes { + position { + x: -200.0 + } + size { + x: 140.0 + y: 140.0 + } + color { + x: 0.631 + y: 0.843 + z: 0.961 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "node_blue" + parent: "root" + inherit_alpha: true + slice9 { + x: 16.0 + y: 16.0 + z: 16.0 + w: 16.0 + } +} +nodes { + position { + y: -100.0 + } + size { + x: 140.0 + y: 140.0 + } + color { + x: 0.557 + y: 0.835 + z: 0.62 + } + type: TYPE_BOX + texture: "druid/ui_circle_32" + id: "node_green" + parent: "root" + inherit_alpha: true + slice9 { + x: 16.0 + y: 16.0 + z: 16.0 + w: 16.0 + } +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT diff --git a/example/examples/widgets/hover_hint/hover_hint_example.lua b/example/examples/widgets/hover_hint/hover_hint_example.lua new file mode 100644 index 0000000..53633c1 --- /dev/null +++ b/example/examples/widgets/hover_hint/hover_hint_example.lua @@ -0,0 +1,23 @@ +local hover_hint = require("example.examples.widgets.hover_hint.hover_hint") + +local component = require("druid.component") + +---@class hover_hint_example: druid.component +---@field druid druid_instance +local M = component.create("hover_hint_example") + + +---@param template string +---@param nodes table +function M:init(template, nodes) + self.druid = self:get_druid(template, nodes) + self.hover_hint = self.druid:new(hover_hint, "hover_hint") + + self.hover_hint:add_hover_hint(self:get_node("node_yellow"), "Yellow box", gui.PIVOT_N, gui.PIVOT_S) + self.hover_hint:add_hover_hint(self:get_node("node_green"), "Green box", gui.PIVOT_S, gui.PIVOT_N) + self.hover_hint:add_hover_hint(self:get_node("node_red"), "Red box", gui.PIVOT_E, gui.PIVOT_W) + self.hover_hint:add_hover_hint(self:get_node("node_blue"), "And this is definitely a blue box", gui.PIVOT_W, gui.PIVOT_E) +end + + +return M