Commit 395734d4f0a5a45070456273341063c5c4fd3d95
1 parent
6fcb9bf8
Added .. mouse gestures. Yes right! Find them in the keybinder menu. You can now…
… bind mouse gestures to any bindable actions! Module makers can use gestures easily with the engine.ui.Gesture class git-svn-id: http://svn.net-core.org/repos/t-engine4@3381 51575b47-30f0-44d4-a5cc-537603b46e54
Showing
7 changed files
with
390 additions
and
75 deletions
... | ... | @@ -83,17 +83,23 @@ function _M:saveRemap(file) |
83 | 83 | end |
84 | 84 | |
85 | 85 | local f = fs.open(file, "w") |
86 | + | |
87 | + local k1, k2, k3 | |
86 | 88 | |
87 | 89 | for virtual, keys in pairs(_M.binds_remap) do |
88 | - if keys[1] and not keys[2] then | |
89 | - f:write(("%s = {%q,nil}\n"):format(virtual, keys[1])) | |
90 | - elseif not keys[1] and keys[2] then | |
91 | - f:write(("%s = {nil,%q}\n"):format(virtual, keys[2])) | |
92 | - elseif keys[1] and keys[2] then | |
93 | - f:write(("%s = {%q,%q}\n"):format(virtual, keys[1], keys[2])) | |
94 | - elseif not keys[1] and not keys[2] then | |
95 | - f:write(("%s = {nil,nil}\n"):format(virtual)) | |
90 | + k1 = "nil" | |
91 | + k2 = "nil" | |
92 | + k3 = "nil" | |
93 | + if keys[1] then | |
94 | + k1 = ("%q"):format(keys[1]) | |
96 | 95 | end |
96 | + if keys[2] then | |
97 | + k2 = ("%q"):format(keys[2]) | |
98 | + end | |
99 | + if keys[3] then | |
100 | + k3 = ("%q"):format(keys[3]) | |
101 | + end | |
102 | + f:write(("%s = {%s,%s,%s}\n"):format(virtual, k1, k2, k3)) | |
97 | 103 | end |
98 | 104 | |
99 | 105 | f:close() |
... | ... | @@ -138,6 +144,10 @@ function _M:makeKeyString(sym, ctrl, shift, alt, meta, unicode) |
138 | 144 | return ("sym:%s:%s:%s:%s:%s"):format(tostring(sym), tostring(ctrl), tostring(shift), tostring(alt), tostring(meta)), unicode and "uni:"..unicode |
139 | 145 | end |
140 | 146 | |
147 | +function _M:makeGestureString(gesture) | |
148 | + return ("gest:%s"):format(tostring(gesture)) | |
149 | +end | |
150 | + | |
141 | 151 | function _M:makeMouseString(button, ctrl, shift, alt, meta) |
142 | 152 | return ("mouse:%s:%s:%s:%s:%s"):format(tostring(button), tostring(ctrl), tostring(shift), tostring(alt), tostring(meta)) |
143 | 153 | end |
... | ... | @@ -181,6 +191,10 @@ function _M:formatKeyString(ks) |
181 | 191 | if meta then sym = "[meta]+"..sym end |
182 | 192 | |
183 | 193 | return sym |
194 | + elseif ks:find("^gest:") then | |
195 | + local i, j, sym = ks:find("^gest:([a-zA-Z0-9]+)$") | |
196 | + if not i then return "--" end | |
197 | + return sym | |
184 | 198 | end |
185 | 199 | end |
186 | 200 | ... | ... |
... | ... | @@ -50,12 +50,12 @@ function _M:generateList(actions) |
50 | 50 | resume = { "Resume", function() game:unregisterDialog(self) end }, |
51 | 51 | keybinds = { "Key Bindings", function() |
52 | 52 | game:unregisterDialog(self) |
53 | - local menu = require("engine.dialogs.KeyBinder").new(game.normal_key) | |
53 | + local menu = require("engine.dialogs.KeyBinder").new(game.normal_key, nil, game.gestures) | |
54 | 54 | game:registerDialog(menu) |
55 | 55 | end }, |
56 | 56 | keybinds_all = { "Key Bindings", function() |
57 | 57 | game:unregisterDialog(self) |
58 | - local menu = require("engine.dialogs.KeyBinder").new(game.normal_key, true) | |
58 | + local menu = require("engine.dialogs.KeyBinder").new(game.normal_key, true, game.gestures) | |
59 | 59 | game:registerDialog(menu) |
60 | 60 | end }, |
61 | 61 | video = { "Video Options", function() | ... | ... |
... | ... | @@ -25,11 +25,12 @@ local Textbox = require "engine.ui.Textbox" |
25 | 25 | |
26 | 26 | module(..., package.seeall, class.inherit(Dialog)) |
27 | 27 | |
28 | -function _M:init(title, text, min, max, action, cancel) | |
28 | +function _M:init(title, text, min, max, action, cancel, absolute) | |
29 | 29 | self.action = action |
30 | 30 | self.cancel = cancel |
31 | 31 | self.min = min or 2 |
32 | 32 | self.max = max or 25 |
33 | + self.absolute = absolute | |
33 | 34 | |
34 | 35 | Dialog.init(self, title, 320, 110) |
35 | 36 | |
... | ... | @@ -53,11 +54,11 @@ end |
53 | 54 | |
54 | 55 | function _M:okclick() |
55 | 56 | self.name = self.c_box.text |
56 | - if self.name:len() >= self.min then | |
57 | + if self.name:len() >= self.min and self.name:len() <= self.max then | |
57 | 58 | game:unregisterDialog(self) |
58 | 59 | self.action(self.name) |
59 | 60 | else |
60 | - Dialog:simplePopup("Error", "Must be between 2 and 25 characters.") | |
61 | + Dialog:simplePopup("Error", ("Must be between %i and %i characters."):format(self.min, self.max)) | |
61 | 62 | end |
62 | 63 | end |
63 | 64 | ... | ... |
... | ... | @@ -23,21 +23,36 @@ local TreeList = require "engine.ui.TreeList" |
23 | 23 | local Textzone = require "engine.ui.Textzone" |
24 | 24 | local Separator = require "engine.ui.Separator" |
25 | 25 | local KeyBind = require "engine.KeyBind" |
26 | +local Gestures = require "engine.ui.Gestures" | |
27 | +local GetText = require "engine.dialogs.GetText" | |
26 | 28 | |
27 | 29 | module(..., package.seeall, class.inherit(Dialog)) |
28 | 30 | |
29 | -function _M:init(key_source, force_all) | |
30 | - Dialog.init(self, "Key bindings", 800, game.h) | |
31 | +function _M:init(key_source, force_all, gesture_source) | |
32 | + Dialog.init(self, "Key bindings", 800, game.h * 0.9) | |
33 | + self.gesture = gesture_source | |
34 | + self.key_source = key_source | |
31 | 35 | |
32 | 36 | self:generateList(key_source, force_all) |
33 | 37 | |
34 | - self.c_tree = TreeList.new{width=self.iw, height=self.ih, sel_by_col=true, scrollbar=true, columns={ | |
35 | - {width=40, display_prop="name"}, | |
36 | - {width=30, display_prop="b1"}, | |
37 | - {width=30, display_prop="b2"}, | |
38 | - }, tree=self.tree, | |
39 | - fct=function(item, sel, v) self:use(item, sel, v) end, | |
40 | - } | |
38 | + if self.gesture then | |
39 | + self.c_tree = TreeList.new{width=self.iw, height=self.ih, sel_by_col=true, scrollbar=true, columns={ | |
40 | + {width=40, display_prop="name"}, | |
41 | + {width=20, display_prop="b1"}, | |
42 | + {width=20, display_prop="b2"}, | |
43 | + {width=20, display_prop="g"}, | |
44 | + }, tree=self.tree, | |
45 | + fct=function(item, sel, v) self:use(item, sel, v) end, | |
46 | + } | |
47 | + else | |
48 | + self.c_tree = TreeList.new{width=self.iw, height=self.ih, sel_by_col=true, scrollbar=true, columns={ | |
49 | + {width=40, display_prop="name"}, | |
50 | + {width=30, display_prop="b1"}, | |
51 | + {width=30, display_prop="b2"}, | |
52 | + }, tree=self.tree, | |
53 | + fct=function(item, sel, v) self:use(item, sel, v) end, | |
54 | + } | |
55 | + end | |
41 | 56 | |
42 | 57 | self:loadUI{ |
43 | 58 | {left=0, top=0, ui=self.c_tree}, |
... | ... | @@ -56,63 +71,118 @@ end |
56 | 71 | function _M:use(item) |
57 | 72 | local t = item |
58 | 73 | local curcol = self.c_tree.cur_col - 1 |
59 | - if not item or item.nodes or curcol < 1 or curcol > 2 then return end | |
74 | + if not item or item.nodes or curcol < 1 or curcol > 3 then return end | |
60 | 75 | |
61 | 76 | -- |
62 | 77 | -- Make a dialog to ask for the key |
63 | 78 | -- |
64 | - local title = "Press a key (or escape) for: "..tostring(t.name) | |
65 | - local font = self.font | |
66 | - local w, h = font:size(title) | |
67 | - local d = engine.Dialog.new(title, w + 8, h + 25, nil, nil, nil, font) | |
68 | - d:keyCommands{__DEFAULT=function(sym, ctrl, shift, alt, meta, unicode) | |
69 | - -- Modifier keys are not treated | |
70 | - if not t.single_key and (sym == KeyBind._LCTRL or sym == KeyBind._RCTRL or | |
71 | - sym == KeyBind._LSHIFT or sym == KeyBind._RSHIFT or | |
72 | - sym == KeyBind._LALT or sym == KeyBind._RALT or | |
73 | - sym == KeyBind._LMETA or sym == KeyBind._RMETA) then | |
74 | - return | |
75 | - end | |
76 | - | |
77 | - if sym == KeyBind._BACKSPACE then | |
78 | - KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
79 | - KeyBind.binds_remap[t.type][curcol] = nil | |
80 | - elseif sym ~= KeyBind._ESCAPE then | |
81 | - local ks = KeyBind:makeKeyString(sym, ctrl, shift, alt, meta, unicode) | |
82 | - print("Binding", t.name, "to", ks, "::", curcol) | |
83 | - | |
84 | - KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
85 | - KeyBind.binds_remap[t.type][curcol] = ks | |
86 | - end | |
87 | - self.c_tree:drawItem(item) | |
88 | - game:unregisterDialog(d) | |
89 | - end} | |
90 | - | |
91 | - d:mouseZones{ norestrict=true, | |
92 | - { x=0, y=0, w=game.w, h=game.h, fct=function(button, x, y, xrel, yrel, tx, ty) | |
93 | - if xrel or yrel then return end | |
94 | - if button == "left" then return end | |
95 | - | |
96 | - local ks = KeyBind:makeMouseString( | |
97 | - button, | |
98 | - core.key.modState("ctrl") and true or false, | |
99 | - core.key.modState("shift") and true or false, | |
100 | - core.key.modState("alt") and true or false, | |
101 | - core.key.modState("meta") and true or false | |
102 | - ) | |
103 | - print("Binding", t.name, "to", ks) | |
104 | - | |
105 | - KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
106 | - KeyBind.binds_remap[t.type][curcol] = ks | |
79 | + if curcol == 1 or curcol == 2 then | |
80 | + local title = "Press a key (or escape) for: "..tostring(t.name) | |
81 | + local font = self.font | |
82 | + local w, h = font:size(title) | |
83 | + local d = engine.Dialog.new(title, w + 8, h + 25, nil, nil, nil, font) | |
84 | + d:keyCommands{__DEFAULT=function(sym, ctrl, shift, alt, meta, unicode) | |
85 | + -- Modifier keys are not treated | |
86 | + if not t.single_key and (sym == KeyBind._LCTRL or sym == KeyBind._RCTRL or | |
87 | + sym == KeyBind._LSHIFT or sym == KeyBind._RSHIFT or | |
88 | + sym == KeyBind._LALT or sym == KeyBind._RALT or | |
89 | + sym == KeyBind._LMETA or sym == KeyBind._RMETA) then | |
90 | + return | |
91 | + end | |
92 | + | |
93 | + if sym == KeyBind._BACKSPACE then | |
94 | + KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
95 | + KeyBind.binds_remap[t.type][curcol] = nil | |
96 | + elseif sym ~= KeyBind._ESCAPE then | |
97 | + local ks = KeyBind:makeKeyString(sym, ctrl, shift, alt, meta, unicode) | |
98 | + print("Binding", t.name, "to", ks, "::", curcol) | |
99 | + | |
100 | + KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
101 | + KeyBind.binds_remap[t.type][curcol] = ks | |
102 | + end | |
107 | 103 | self.c_tree:drawItem(item) |
108 | 104 | game:unregisterDialog(d) |
109 | - end }, | |
110 | - } | |
105 | + end} | |
106 | + | |
107 | + d:mouseZones{ norestrict=true, | |
108 | + { x=0, y=0, w=game.w, h=game.h, fct=function(button, x, y, xrel, yrel, tx, ty) | |
109 | + if xrel or yrel then return end | |
110 | + if button == "left" then return end | |
111 | + | |
112 | + local ks = KeyBind:makeMouseString( | |
113 | + button, | |
114 | + core.key.modState("ctrl") and true or false, | |
115 | + core.key.modState("shift") and true or false, | |
116 | + core.key.modState("alt") and true or false, | |
117 | + core.key.modState("meta") and true or false | |
118 | + ) | |
119 | + print("Binding", t.name, "to", ks) | |
120 | + | |
121 | + KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
122 | + KeyBind.binds_remap[t.type][curcol] = ks | |
123 | + self.c_tree:drawItem(item) | |
124 | + game:unregisterDialog(d) | |
125 | + end }, | |
126 | + } | |
111 | 127 | |
112 | - d.drawDialog = function(self, s) | |
113 | - s:drawColorStringBlendedCentered(self.font, curcol == 1 and "Bind key" or "Bind alternate key", 2, 2, self.iw - 2, self.ih - 2) | |
128 | + d.drawDialog = function(self, s) | |
129 | + s:drawColorStringBlendedCentered(self.font, curcol == 1 and "Bind key" or "Bind alternate key", 2, 2, self.iw - 2, self.ih - 2) | |
130 | + end | |
131 | + game:registerDialog(d) | |
132 | + elseif curcol == 3 then | |
133 | + local title = "Make gesture (using right mouse button) or type it (or escape) for: "..tostring(t.name) | |
134 | + local font = self.font | |
135 | + local w, h = font:size(title) | |
136 | + local d = GetText.new(title, "Gesture", 0, 5, | |
137 | + function(gesture) | |
138 | + if item.g and item.g ~= "--" then | |
139 | + self.gesture:removeGesture(item.g) | |
140 | + end | |
141 | + KeyBind.binds_remap[t.type] = KeyBind.binds_remap[t.type] or t.k.default | |
142 | + if gesture == "" then | |
143 | + KeyBind.binds_remap[t.type][curcol] = nil | |
144 | + else | |
145 | + KeyBind.binds_remap[t.type][curcol] = KeyBind:makeGestureString(gesture) | |
146 | + end | |
147 | + self.gesture:addGesture(gesture, function() self.key_source:triggerVirtual(t.type) end, t.sortname) | |
148 | + self.c_tree:drawItem(item) | |
149 | + end, | |
150 | + function() | |
151 | + | |
152 | + end, | |
153 | + true) | |
154 | + | |
155 | + d.c_box.filter = function(c) | |
156 | + c=string.upper(c) | |
157 | + local text = table.concat(d.c_box.tmp) | |
158 | + if (c =="U" or c=="D" or c=="L" or c=="R") and c:byte(1)~=text:byte(d.c_box.cursor-1) and c:byte(1)~=text:byte(d.c_box.cursor) then | |
159 | + return c | |
160 | + else | |
161 | + return nil | |
162 | + end | |
163 | + end | |
164 | + d.mouse:registerZone(0, 0, game.w, game.h, function(button, mx, my, xrel, yrel, bx, by, event) | |
165 | + if button == "right" then | |
166 | + if event == "motion" then | |
167 | + self.gesture:changeMouseButton(true) | |
168 | + self.gesture:mouseMove(mx, my) | |
169 | + local text = table.concat(d.c_box.tmp) | |
170 | + if #text < 5 and self.gesture.lastgesture~="" and self.gesture.lastgesture:byte(1)~=text:byte(d.c_box.cursor-1) and self.gesture.lastgesture:byte(1) ~= text:byte(d.c_box.cursor) then | |
171 | + table.insert(d.c_box.tmp, d.c_box.cursor, self.gesture.lastgesture) | |
172 | + d.c_box.cursor = d.c_box.cursor + 1 | |
173 | + d.c_box:updateText() | |
174 | + end | |
175 | + elseif event == "button" then | |
176 | + self.gesture:changeMouseButton(false) | |
177 | + self.gesture:reset() | |
178 | + end | |
179 | + end | |
180 | + | |
181 | + d:mouseEvent(button, mx, my, xrel, yrel, bx - d.display_x, by - d.display_y, event) | |
182 | + end) | |
183 | + | |
184 | + game:registerDialog(d) | |
114 | 185 | end |
115 | - game:registerDialog(d) | |
116 | 186 | end |
117 | 187 | |
118 | 188 | function _M:generateList(key_source, force_all) |
... | ... | @@ -143,8 +213,10 @@ function _M:generateList(key_source, force_all) |
143 | 213 | single_key = k.single_key, |
144 | 214 | bind1 = function(item) return KeyBind:getBindTable(k)[1] end, |
145 | 215 | bind2 = function(item) return KeyBind:getBindTable(k)[2] end, |
216 | + bind3 = function(item) return KeyBind:getBindTable(k)[3] end, | |
146 | 217 | b1 = function(item) return KeyBind:formatKeyString(util.getval(item.bind1, item)) end, |
147 | 218 | b2 = function(item) return KeyBind:formatKeyString(util.getval(item.bind2, item)) end, |
219 | + g = function(item) return KeyBind:formatKeyString(util.getval(item.bind3, item)) end, | |
148 | 220 | } |
149 | 221 | groups[k.group] = groups[k.group] or {} |
150 | 222 | table.insert(groups[k.group], item) |
... | ... | @@ -154,7 +226,7 @@ function _M:generateList(key_source, force_all) |
154 | 226 | tree[#tree+1] = { |
155 | 227 | name = tstring{{"font","bold"}, {"color","GOLD"}, group:capitalize(), {"font","normal"}}, |
156 | 228 | sortname = group:capitalize(), |
157 | - b1 = "", b2 = "", | |
229 | + b1 = "", b2 = "", g = "", | |
158 | 230 | shown = true, |
159 | 231 | nodes = data, |
160 | 232 | } | ... | ... |
... | ... | @@ -169,6 +169,9 @@ function _M:resize(w, h, nogen) |
169 | 169 | self.ix, self.iy = 5, 8 + 3 + self.font_bold_h |
170 | 170 | self.iw, self.ih = w - 2 * 5, h - 8 - 8 - 3 - self.font_bold_h |
171 | 171 | |
172 | +-- self.display_x = util.bound(self.display_x, 0, game.w - (self.w+self.frame.ox2)) | |
173 | +-- self.display_y = util.bound(self.display_y, 0, game.h - (self.h+self.frame.oy2)) | |
174 | + | |
172 | 175 | if not nogen then self:generate() end |
173 | 176 | end |
174 | 177 | |
... | ... | @@ -423,8 +426,6 @@ end |
423 | 426 | |
424 | 427 | function _M:toScreen(x, y, nb_keyframes) |
425 | 428 | if self.__hidden then return end |
426 | - x = util.bound(x, 0, game.w - (self.w+self.frame.ox2)) | |
427 | - y = util.bound(y, 0, game.h - (self.h+self.frame.oy2)) | |
428 | 429 | |
429 | 430 | local zoom = 1 |
430 | 431 | if self.__showup then | ... | ... |
game/engines/default/engine/ui/Gestures.lua
0 → 100644
1 | +-- TE4 - T-Engine 4 | |
2 | +-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini | |
3 | +-- | |
4 | +-- This program is free software: you can redistribute it and/or modify | |
5 | +-- it under the terms of the GNU General Public License as published by | |
6 | +-- the Free Software Foundation, either version 3 of the License, or | |
7 | +-- (at your option) any later version. | |
8 | +-- | |
9 | +-- This program is distributed in the hope that it will be useful, | |
10 | +-- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | +-- GNU General Public License for more details. | |
13 | +-- | |
14 | +-- You should have received a copy of the GNU General Public License | |
15 | +-- along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | +-- | |
17 | +-- Nicolas Casalini "DarkGod" | |
18 | +-- darkgod@te4.org | |
19 | + | |
20 | +require "engine.class" | |
21 | +local KeyBind = require "engine.KeyBind" | |
22 | + | |
23 | +module(..., package.seeall, class.make) | |
24 | + | |
25 | +function _M:init(text, key_source, force_all) | |
26 | + assert(key_source, "no key source") | |
27 | + self.text = text or "Gesture: " | |
28 | + self.gesture = "" | |
29 | + self.gestures = {} | |
30 | + self.font = core.display.newFont("/data/font/Vera.ttf", 12) | |
31 | + | |
32 | + local gesttext = self.text.."WWWWW" | |
33 | + self.fontmax_w, self.font_h = self.font:size(gesttext) | |
34 | + | |
35 | + self.surface = core.display.newSurface(self.fontmax_w, self.font_h) | |
36 | + self.surface:drawColorStringBlended(self.font, self.text, 0, 0, 255, 255, 255, true) | |
37 | + self.texture, self.texture_w, self.texture_h = self.surface:glTexture() | |
38 | + self.timeout = 1.7 | |
39 | + self.lastupdate = os.time() | |
40 | + self.gesturing = false | |
41 | + self.mousebuttondown = false | |
42 | + self.distance = 0 | |
43 | + self.lastgesture = "" | |
44 | + self.lastgesturename = "" | |
45 | + | |
46 | + self:loadGestures(key_source, force_all) | |
47 | +end | |
48 | + | |
49 | +function _M:loadGestures(key_source, force_all) | |
50 | + local l = {} | |
51 | + | |
52 | + for virtual, t in pairs(KeyBind.binds_def) do | |
53 | + if (force_all or key_source.virtuals[virtual]) and t.group ~= "debug" then | |
54 | + l[#l+1] = t | |
55 | + end | |
56 | + end | |
57 | + table.sort(l, function(a,b) | |
58 | + if a.group ~= b.group then | |
59 | + return a.group < b.group | |
60 | + else | |
61 | + return a.order < b.order | |
62 | + end | |
63 | + end) | |
64 | + | |
65 | + -- Makes up the list | |
66 | + local tree = {} | |
67 | + local groups = {} | |
68 | + for _, k in ipairs(l) do | |
69 | + local bind3 = KeyBind:getBindTable(k)[3] | |
70 | + local gesture = KeyBind:formatKeyString(util.getval(bind3)) | |
71 | + if k.name ~= "" and k.name~= "--" then | |
72 | + self:addGesture(gesture, function() key_source:triggerVirtual(k.type) end, k.name) | |
73 | + end | |
74 | + end | |
75 | +end | |
76 | + | |
77 | +function _M:mouseMove(mx, my) | |
78 | + if #self.gesture >= 5 then return end | |
79 | + if self.omx and self.omy then | |
80 | + self.distance = self.distance + (self.omy - my)^2 + (self.omx - mx)^2 | |
81 | + if math.abs(self.omx - mx) > math.abs(self.omy - my) and self.distance > 100 then | |
82 | + if self.omx > mx then | |
83 | + if self.lastgesture~="L" then | |
84 | + self.gesture = self.gesture.."L" | |
85 | + self.lastgesture = "L" | |
86 | + end | |
87 | + else | |
88 | + if self.lastgesture~="R" then | |
89 | + self.gesture = self.gesture.."R" | |
90 | + self.lastgesture = "R" | |
91 | + end | |
92 | + end | |
93 | + self.gesturing = true | |
94 | + self.lastupdate = os.time() | |
95 | + self.distance = 0 | |
96 | + end | |
97 | + if math.abs(self.omx - mx) < math.abs(self.omy - my) and self.distance > 100 then | |
98 | + if self.omy > my then | |
99 | + if self.lastgesture~="U" then | |
100 | + self.gesture = self.gesture.."U" | |
101 | + self.lastgesture = "U" | |
102 | + end | |
103 | + else | |
104 | + if self.lastgesture~="D" then | |
105 | + self.gesture = self.gesture.."D" | |
106 | + self.lastgesture = "D" | |
107 | + end | |
108 | + end | |
109 | + self.gesturing = true | |
110 | + self.lastupdate = os.time() | |
111 | + self.distance = 0 | |
112 | + end | |
113 | + end | |
114 | + | |
115 | + self.omx = mx | |
116 | + self.omy = my | |
117 | +end | |
118 | + | |
119 | +function _M:isGesturing() | |
120 | + return self.gesturing | |
121 | +end | |
122 | + | |
123 | +function _M:isMouseButtonDown() | |
124 | + return self.mousebuttondown | |
125 | +end | |
126 | + | |
127 | +function _M:changeMouseButton(isDown) | |
128 | + self.mousebuttondown = isDown | |
129 | +end | |
130 | + | |
131 | +function _M:useGesture() | |
132 | + if self.gestures[self.gesture] then | |
133 | + self.gestures[self.gesture].func() | |
134 | + end | |
135 | +end | |
136 | + | |
137 | +function _M:reset() | |
138 | + self.gesturing = false | |
139 | + self.omx = nil | |
140 | + self.omy = nil | |
141 | + self.gesture = "" | |
142 | + self.lastgesture = "" | |
143 | + self.distance = 0 | |
144 | +end | |
145 | + | |
146 | +function _M:addGesture(gesture, func, name) | |
147 | + self.gestures[gesture] = {} | |
148 | + self.gestures[gesture].func = func | |
149 | + self.gestures[gesture].name = name | |
150 | +end | |
151 | + | |
152 | +function _M:removeGesture(gesture) | |
153 | + if not self.gestures[gesture] then return end | |
154 | + self.gestures[gesture] = nil | |
155 | +end | |
156 | + | |
157 | +function _M:empty() | |
158 | + self.gestures = {} | |
159 | + self:reset() | |
160 | +end | |
161 | + | |
162 | +function _M:setTimeout(timeout) | |
163 | + self.timeout = timeout | |
164 | +end | |
165 | + | |
166 | +function _M:getLastGesture() | |
167 | + return self.gesture | |
168 | +end | |
169 | + | |
170 | +function _M:update() | |
171 | + local gesttxt = "" | |
172 | + | |
173 | + if self.gesturing == true then | |
174 | + gesttxt = self.text | |
175 | + if os.difftime(os.time(), self.lastupdate) >= self.timeout then | |
176 | + self:reset() | |
177 | + end | |
178 | + end | |
179 | + | |
180 | + gesttxt = gesttxt..self.gesture | |
181 | + | |
182 | + self.surface:erase(0,0,0,1) | |
183 | + self.surface:drawColorStringBlended(self.font, gesttxt, 0, 0, 255, 255, 255, true) | |
184 | + self.surface:updateTexture(self.texture) | |
185 | +end | |
186 | + | |
187 | +function _M:display(display_x, display_y) | |
188 | + self.texture:toScreenFull(display_x, display_y, self.fontmax_w, self.font_h, self.texture_w, self.texture_h) | |
189 | + | |
190 | + if self.gestures[self.gesture] then | |
191 | + if self.gestures[self.gesture].name == self.lastgesturename and self.gesturenametexure then | |
192 | + self.gesturenametexure:toScreenFull(display_x + self.fontmax_w, display_y, self.gesturenamefont_w , self.font_h, self.gesturenametexure_w, self.gesturenametexure_h) | |
193 | + else | |
194 | + self.gesturenamefont_w, _ = self.font:size(self.gestures[self.gesture].name) | |
195 | + local s = core.display.newSurface(self.gesturenamefont_w, self.font_h) | |
196 | + s:drawColorStringBlended(self.font, self.gestures[self.gesture].name, 0, 0, 255, 255, 255, true) | |
197 | + self.gesturenametexure, self.gesturenametexure_w, self.gesturenametexure_h = s:glTexture() | |
198 | + self.gesturenametexure:toScreenFull(display_x, display_y, self.fontmax_w, self.font_h, self.texture_w, self.texture_h) | |
199 | + end | |
200 | + self.lastgesturename = self.gestures[self.gesture].name | |
201 | + end | |
202 | +end | ... | ... |
... | ... | @@ -54,6 +54,7 @@ local DebugConsole = require "engine.DebugConsole" |
54 | 54 | local FlyingText = require "engine.FlyingText" |
55 | 55 | local Tooltip = require "engine.Tooltip" |
56 | 56 | local Calendar = require "engine.Calendar" |
57 | +local Gestures = require "engine.ui.Gestures" | |
57 | 58 | |
58 | 59 | local Dialog = require "engine.ui.Dialog" |
59 | 60 | local MapMenu = require "mod.dialogs.MapMenu" |
... | ... | @@ -854,6 +855,10 @@ function _M:display(nb_keyframes) |
854 | 855 | self.minimap_bg:toScreen(0, 35, 200, 200) |
855 | 856 | self.minimap_scroll_x, self.minimap_scroll_y = util.bound(self.player.x - 25, 0, map.w - 50), util.bound(self.player.y - 25, 0, map.h - 50) |
856 | 857 | map:minimapDisplay(0, 35, self.minimap_scroll_x, self.minimap_scroll_y, 50, 50, 1) |
858 | + | |
859 | + -- Mouse gestures | |
860 | + self.gestures:update() | |
861 | + self.gestures:display(map.display_x, map.display_y + map.viewport.height - self.gestures.font_h - 5) | |
857 | 862 | end |
858 | 863 | |
859 | 864 | -- We display the player's interface |
... | ... | @@ -907,6 +912,9 @@ function _M:setupCommands() |
907 | 912 | -- Activate profiler keybinds |
908 | 913 | self.key:setupProfiler() |
909 | 914 | |
915 | + -- Activate mouse gestures | |
916 | + self.gestures = Gestures.new("Gesture: ", self.key, true) | |
917 | + | |
910 | 918 | -- Helper function to not allow some actions on the wilderness map |
911 | 919 | local not_wild = function(f) return function() if self.zone and not self.zone.wilderness then f() else self.logPlayer(self.player, "You cannot do that on the world map.") end end end |
912 | 920 | |
... | ... | @@ -1183,7 +1191,24 @@ function _M:setupMouse(reset) |
1183 | 1191 | if self:targetMouse(button, mx, my, xrel, yrel, event) then return end |
1184 | 1192 | |
1185 | 1193 | -- Handle Use menu |
1186 | - if button == "right" and not xrel and not yrel and event == "button" then self:mouseRightClick(mx, my) return end | |
1194 | + if button == "right" then | |
1195 | + if event == "motion" then | |
1196 | + self.gestures:changeMouseButton(true) | |
1197 | + self.gestures:mouseMove(mx, my) | |
1198 | + elseif event == "button" then | |
1199 | + if not self.gestures:isGesturing() then | |
1200 | + if not xrel and not yrel then | |
1201 | + -- Handle Use menu | |
1202 | + self:mouseRightClick(mx, my) | |
1203 | + return | |
1204 | + end | |
1205 | + else | |
1206 | + self.gestures:changeMouseButton(false) | |
1207 | + self.gestures:useGesture() | |
1208 | + self.gestures:reset() | |
1209 | + end | |
1210 | + end | |
1211 | + end | |
1187 | 1212 | |
1188 | 1213 | -- Default left button action |
1189 | 1214 | if button == "left" and not xrel and not yrel and event == "button" and self.zone and not self.zone.wilderness then if self:mouseLeftClick(mx, my) then return end end | ... | ... |
-
Please register or login to post a comment