diff --git a/druid/base/drag.lua b/druid/base/drag.lua index 15d6a13..ddbb5ba 100644 --- a/druid/base/drag.lua +++ b/druid/base/drag.lua @@ -63,6 +63,7 @@ local function start_touch(self, touch) self.x = touch.x self.y = touch.y + self._scene_scale = helper.get_scene_scale(self.node) self.on_touch_start:trigger(self:get_context()) end @@ -155,11 +156,11 @@ end -- or create your own style -- @table style -- @tfield[opt=10] number DRAG_DEADZONE Distance in pixels to start dragging --- @tfield[opt=false] boolean IS_USE_SCREEN_KOEF If screen aspect ration affects on drag values +-- @tfield[opt=false] boolean NO_USE_SCREEN_KOEF If screen aspect ration affects on drag values function Drag.on_style_change(self, style) self.style = {} self.style.DRAG_DEADZONE = style.DRAG_DEADZONE or 10 - self.style.IS_USE_SCREEN_KOEF = style.IS_USE_SCREEN_KOEF or false + self.style.NO_USE_SCREEN_KOEF = style.NO_USE_SCREEN_KOEF or false end @@ -183,6 +184,8 @@ function Drag.init(self, node, on_drag_callback) self.can_x = true self.can_y = true + self._scene_scale = helper.get_scene_scale(self.node) + self.click_zone = nil self.on_touch_start = Event() self.on_touch_end = Event() @@ -208,6 +211,7 @@ function Drag.on_window_resized(self) local x_koef, y_koef = helper.get_screen_aspect_koef() self._x_koef = x_koef self._y_koef = y_koef + self._scene_scale = helper.get_scene_scale(self.node) end @@ -231,7 +235,6 @@ function Drag.on_input(self, action_id, action) if self.click_zone then is_pick = is_pick and gui.pick_node(self.click_zone, action.x, action.y) end - if not is_pick and not self.is_drag then end_touch(self) return false @@ -281,15 +284,15 @@ function Drag.on_input(self, action_id, action) if self.is_drag then local x_koef, y_koef = self._x_koef, self._y_koef - if not self.style.IS_USE_SCREEN_KOEF then + if self.style.NO_USE_SCREEN_KOEF then x_koef, y_koef = 1, 1 end self.on_drag:trigger(self:get_context(), - self.dx * x_koef, - self.dy * y_koef, - (self.x - self.touch_start_pos.x) * x_koef, - (self.y - self.touch_start_pos.y) * y_koef) + self.dx * x_koef / self._scene_scale.x, + self.dy * y_koef / self._scene_scale.y, + (self.x - self.touch_start_pos.x) * x_koef / self._scene_scale.x, + (self.y - self.touch_start_pos.y) * y_koef / self._scene_scale.y) end return self.is_drag diff --git a/druid/extended/layout.lua b/druid/extended/layout.lua index 0c544f5..6e8db43 100644 --- a/druid/extended/layout.lua +++ b/druid/extended/layout.lua @@ -36,10 +36,13 @@ function Layout.init(self, node, mode, on_size_changed_callback) self._min_size = nil self._max_size = nil + self._current_size = vmath.vector3(0) self._inited = false - + self._max_gui_upscale = nil self._fit_node = nil + self._anchors = {} + self.mode = mode or const.LAYOUT_MODE.FIT self.on_size_changed = Event(on_size_changed_callback) @@ -66,6 +69,13 @@ function Layout.on_window_resized(self) local x_koef, y_koef = helper.get_screen_aspect_koef() + local revert_scale = 1 + if self._max_gui_upscale then + revert_scale = self._max_gui_upscale / helper.get_gui_scale() + revert_scale = math.min(revert_scale, 1) + end + gui.set_scale(self.node, vmath.vector3(revert_scale)) + if self._fit_node then self.fit_size = gui.get_size(self._fit_node) self.fit_size.x = self.fit_size.x / x_koef @@ -77,11 +87,17 @@ function Layout.on_window_resized(self) local new_size = vmath.vector3(self.origin_size) - if self.mode == const.LAYOUT_MODE.STRETCH_X or self.mode == const.LAYOUT_MODE.STRETCH then - new_size.x = new_size.x * x_koef + if self.mode == const.LAYOUT_MODE.STRETCH then + new_size.x = new_size.x * x_koef / revert_scale + new_size.y = new_size.y * y_koef / revert_scale end - if self.mode == const.LAYOUT_MODE.STRETCH_Y or self.mode == const.LAYOUT_MODE.STRETCH then - new_size.y = new_size.y * y_koef + + if self.mode == const.LAYOUT_MODE.STRETCH_X then + new_size.x = new_size.x * x_koef / revert_scale + end + + if self.mode == const.LAYOUT_MODE.STRETCH_Y then + new_size.y = new_size.y * y_koef / revert_scale end -- Fit to the stretched container (node size or other defined) @@ -100,6 +116,7 @@ function Layout.on_window_resized(self) new_size.x = math.min(new_size.x, self._max_size.x) new_size.y = math.min(new_size.y, self._max_size.y) end + self._current_size = new_size gui.set_size(self.node, new_size) self.position.x = self.origin_position.x + self.origin_position.x * (x_koef - 1) @@ -152,6 +169,16 @@ function Layout.set_origin_size(self, new_origin_size) end +--- Set max gui upscale for FIT adjust mode (or side). It happens on bigger render gui screen +-- @tparam Layout self @{Layout} +-- @tparam number max_gui_upscale +-- @treturn Layout @{Layout} +function Layout.set_max_gui_upscale(self, max_gui_upscale) + self._max_gui_upscale = max_gui_upscale + self:on_window_resized() +end + + --- Set size for layout node to fit inside it -- @tparam Layout self @{Layout} -- @tparam vector3 target_size diff --git a/druid/extended/slider.lua b/druid/extended/slider.lua index 4a8c90c..4f48e8d 100644 --- a/druid/extended/slider.lua +++ b/druid/extended/slider.lua @@ -64,7 +64,7 @@ function Slider.init(self, node, end_pos, callback) self.start_pos = gui.get_position(self.node) self.pos = gui.get_position(self.node) - self.target_pos = self.pos + self.target_pos = vmath.vector3(self.pos) self.end_pos = end_pos self.dist = self.end_pos - self.start_pos @@ -72,6 +72,7 @@ function Slider.init(self, node, end_pos, callback) self.value = 0 self.on_change_value = Event(callback) + self:on_window_resized() assert(self.dist.x == 0 or self.dist.y == 0, "Slider for now can be only vertical or horizontal") end @@ -82,6 +83,14 @@ function Slider.on_layout_change(self) end +function Slider.on_window_resized(self) + local x_koef, y_koef = helper.get_screen_aspect_koef() + self._x_koef = x_koef + self._y_koef = y_koef + self._scene_scale = helper.get_scene_scale(self.node) +end + + function Slider.on_input(self, action_id, action) if action_id ~= const.ACTION_TOUCH then return false @@ -90,15 +99,17 @@ function Slider.on_input(self, action_id, action) if gui.pick_node(self.node, action.x, action.y) then if action.pressed then self.pos = gui.get_position(self.node) + self._scene_scale = helper.get_scene_scale(self.node) self.is_drag = true end end if not self.is_drag and self._input_node and gui.pick_node(self._input_node, action.x, action.y) then if action.pressed and gui.screen_to_local then + self._scene_scale = helper.get_scene_scale(self.node) self.pos = gui.screen_to_local(self.node, vmath.vector3(action.screen_x, action.screen_y, 0)) - self.pos.x = helper.clamp(self.pos.x, self.start_pos.x, self.end_pos.x) - self.pos.y = helper.clamp(self.pos.y, self.start_pos.y, self.end_pos.y) + self.pos.x = helper.clamp(self.pos.x / self._scene_scale.x, self.start_pos.x, self.end_pos.x) + self.pos.y = helper.clamp(self.pos.y / self._scene_scale.y, self.start_pos.y, self.end_pos.y) gui.set_position(self.node, self.pos) self.is_drag = true @@ -107,8 +118,8 @@ function Slider.on_input(self, action_id, action) if self.is_drag and not action.pressed then -- move - self.pos.x = self.pos.x + action.dx - self.pos.y = self.pos.y + action.dy + self.pos.x = self.pos.x + action.dx * self._x_koef / self._scene_scale.x + self.pos.y = self.pos.y + action.dy * self._y_koef / self._scene_scale.y local prev_x = self.target_pos.x local prev_y = self.target_pos.y diff --git a/druid/helper.lua b/druid/helper.lua index 7663fb4..c87f7da 100644 --- a/druid/helper.lua +++ b/druid/helper.lua @@ -107,6 +107,13 @@ function M.get_screen_aspect_koef() end +function M.get_gui_scale() + local window_x, window_y = window.get_size() + return math.min(window_x / gui.get_width(), + window_y / gui.get_height()) +end + + function M.step(current, target, step) if current < target then return math.min(current + step, target) @@ -181,7 +188,6 @@ function M.get_text_metrics_from_node(text_node) end - --- Check if node is enabled in gui hierarchy. -- Return false, if node or any his parent is disabled -- @function helper.is_enabled @@ -199,6 +205,23 @@ function M.is_enabled(node) end +--- Check if node is enabled in gui hierarchy. +-- Return false, if node or any his parent is disabled +-- @function helper.is_enabled +-- @tparam node node Gui node +-- @treturn bool Is enabled in hierarchy +function M.get_scene_scale(node) + local scale = gui.get_scale(node) + local parent = gui.get_parent(node) + while parent do + scale = vmath.mul_per_elem(scale, gui.get_scale(parent)) + parent = gui.get_parent(parent) + end + + return scale +end + + --- Return closest non inverted clipping parent node for node -- @function helper.get_closest_stencil_node -- @tparam node node Gui node diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua index 6cdd878..0991ba4 100644 --- a/druid/styles/default/style.lua +++ b/druid/styles/default/style.lua @@ -56,7 +56,7 @@ M["button"] = { M["drag"] = { DRAG_DEADZONE = 10, -- Size in pixels of drag deadzone - IS_USE_SCREEN_KOEF = true, + NO_USE_SCREEN_KOEF = false, } diff --git a/test/tests/test_button.lua b/test/tests/test_button.lua index 41a7737..2b7c23f 100644 --- a/test/tests/test_button.lua +++ b/test/tests/test_button.lua @@ -239,5 +239,28 @@ return function() druid:on_input(mock_input.click_released(25, 25)) assert(on_click_mock.calls == 1) end) + + it("Should work with set_enabled", function() + local button = mock_gui.add_box("button", 0, 0, 100, 50) + local button_params = {} + local on_click, on_click_mock = test_helper.get_function() + local instance = druid:new_button(button, on_click, button_params) + + instance:set_enabled(false) + local is_clicked_pressed = druid:on_input(mock_input.click_pressed(10, 10)) + local is_clicked_released = druid:on_input(mock_input.click_released(10, 10)) + assert(is_clicked_pressed == false) + assert(is_clicked_released == false) + assert(on_click_mock.calls == 0) + assert(instance:is_enabled() == false) + + instance:set_enabled(true) + local is_clicked_pressed2 = druid:on_input(mock_input.click_pressed(10, 10)) + assert(is_clicked_pressed2 == true) + local is_clicked_released2 = druid:on_input(mock_input.click_released(10, 10)) + assert(is_clicked_released2 == true) + assert(on_click_mock.calls == 1) + assert(instance:is_enabled() == true) + end) end) end