mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
linn/linndrum.cpp: Made knobs controllable by pointing device. (#13433)
This commit is contained in:
parent
5360641faf
commit
e6c3d78568
@ -224,7 +224,7 @@ copyright-holders:m1macrophage
|
||||
<simplecounter maxstate="100" digits="1"><color red="1.0" green="0.5" blue="0.2"/></simplecounter>
|
||||
</element>
|
||||
<group name="knob">
|
||||
<element ref="knob_outer"><bounds x="0" y="0" width="68" height="68"/></element>
|
||||
<element ref="knob_outer" id="knob_~knob_input~"><bounds x="0" y="0" width="68" height="68"/></element>
|
||||
<element ref="knob_inner"><bounds x="9" y="9" width="50" height="50"/></element>
|
||||
<element ref="knob_value_background" clickthrough="no">
|
||||
<bounds x="17" y="22" width="34" height="24"/>
|
||||
@ -596,6 +596,15 @@ copyright-holders:m1macrophage
|
||||
function()
|
||||
local view = file.views["Default Layout"]
|
||||
install_slider_callbacks(view)
|
||||
|
||||
local sweep_scale = 1.2
|
||||
add_simplecounter_knob(view, "knob_pot_tempo", "pot_tempo", sweep_scale)
|
||||
add_simplecounter_knob(view, "knob_pot_volume", "pot_volume", sweep_scale)
|
||||
for i = 1, 7 do
|
||||
local knob_input = "pot_tuning_" .. i
|
||||
add_simplecounter_knob(view, "knob_" .. knob_input, knob_input, sweep_scale)
|
||||
end
|
||||
|
||||
for i = 1, 16 do
|
||||
local pan_input = "pot_pan_" .. i
|
||||
add_vertical_slider(view, "slider_" .. pan_input, "slider_knob_" .. pan_input, pan_input)
|
||||
@ -605,47 +614,57 @@ copyright-holders:m1macrophage
|
||||
end)
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- Slider library starts.
|
||||
-- Slider and knob library starts.
|
||||
-- Can be copied as-is to other layouts.
|
||||
-----------------------------------------------------------------------
|
||||
local sliders = {} -- Stores slider information.
|
||||
local widgets = {} -- Stores slider and knob information.
|
||||
local pointers = {} -- Tracks pointer state.
|
||||
|
||||
-- The knob's Y position must be animated using <animate inputtag="{port_name}">.
|
||||
-- The click area's vertical size must exactly span the range of the
|
||||
-- knob's movement.
|
||||
function add_vertical_slider(view, clickarea_id, knob_id, port_name)
|
||||
local slider = {}
|
||||
table.insert(widgets, {
|
||||
clickarea = get_layout_item(view, clickarea_id),
|
||||
slider_knob = get_layout_item(view, knob_id),
|
||||
field = get_port_field(port_name),
|
||||
is_knob = false })
|
||||
end
|
||||
|
||||
slider.clickarea = view.items[clickarea_id]
|
||||
if slider.clickarea == nil then
|
||||
emu.print_error("Slider element: '" .. clickarea_id .. "' not found.")
|
||||
return
|
||||
end
|
||||
|
||||
slider.knob = view.items[knob_id]
|
||||
if slider.knob == nil then
|
||||
emu.print_error("Slider knob element: '" .. knob_id .. "' not found.")
|
||||
return
|
||||
-- A sweep between 0 and 100 requires moving the pointer by
|
||||
-- `scale * clickarea.height` pixes.
|
||||
function add_simplecounter_knob(view, clickarea_id, port_name, scale)
|
||||
table.insert(widgets, {
|
||||
clickarea = get_layout_item(view, clickarea_id),
|
||||
field = get_port_field(port_name),
|
||||
is_knob = true,
|
||||
scale = scale })
|
||||
end
|
||||
|
||||
function get_layout_item(view, item_id)
|
||||
local item = view.items[item_id]
|
||||
if item == nil then
|
||||
emu.print_error("Layout element: '" .. item_id .. "' not found.")
|
||||
end
|
||||
return item
|
||||
end
|
||||
|
||||
function get_port_field(port_name)
|
||||
local port = file.device:ioport(port_name)
|
||||
if port == nil then
|
||||
emu.print_error("Port: '" .. port_name .. "' not found.")
|
||||
return
|
||||
return nil
|
||||
end
|
||||
|
||||
slider.field = nil
|
||||
local field = nil
|
||||
for k, val in pairs(port.fields) do
|
||||
slider.field = val
|
||||
field = val
|
||||
break
|
||||
end
|
||||
if slider.field == nil then
|
||||
if field == nil then
|
||||
emu.print_error("Port: '" .. port_name .."' does not seem to be an IPT_ADJUSTER.")
|
||||
return
|
||||
return nil
|
||||
end
|
||||
|
||||
table.insert(sliders, slider)
|
||||
return field
|
||||
end
|
||||
|
||||
local function pointer_updated(type, id, dev, x, y, btn, dn, up, cnt)
|
||||
@ -655,56 +674,64 @@ copyright-holders:m1macrophage
|
||||
return
|
||||
end
|
||||
|
||||
-- If a button was just pressed, find the affected slider, if any.
|
||||
-- If a button was just pressed, find the affected widget, if any.
|
||||
if dn & 1 ~= 0 then
|
||||
for i = 1, #sliders do
|
||||
if sliders[i].knob.bounds:includes(x, y) then
|
||||
for i = 1, #widgets do
|
||||
local found, relative
|
||||
if widgets[i].slider_knob and widgets[i].slider_knob.bounds:includes(x, y) then
|
||||
found = true
|
||||
relative = true
|
||||
elseif widgets[i].clickarea.bounds:includes(x, y) then
|
||||
found = true
|
||||
relative = false
|
||||
end
|
||||
if found then
|
||||
pointers[id] = {
|
||||
selected_slider = i,
|
||||
relative = true,
|
||||
selected_widget = i,
|
||||
relative = relative,
|
||||
start_y = y,
|
||||
start_value = sliders[i].field.user_value }
|
||||
break
|
||||
elseif sliders[i].clickarea.bounds:includes(x, y) then
|
||||
pointers[id] = {
|
||||
selected_slider = i,
|
||||
relative = false }
|
||||
start_value = widgets[i].field.user_value }
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If there is no slider selected by the current pointer, we are done.
|
||||
-- If there is no widget selected by the current pointer, we are done.
|
||||
if pointers[id] == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- A slider is selected. Update state and, indirectly, slider knob position,
|
||||
-- based on the pointer's Y position. It is assumed the attached IO field is
|
||||
-- an IPT_ADJUSTER with a range of 0-100 (the default).
|
||||
-- A widget is selected. Update its state based on the pointer's Y
|
||||
-- position. It is assumed the attached IO field is an
|
||||
-- IPT_ADJUSTER with a range of 0-100 (the default).
|
||||
|
||||
local pointer = pointers[id]
|
||||
local slider = sliders[pointer.selected_slider]
|
||||
local widget = widgets[pointer.selected_widget]
|
||||
|
||||
local knob_half_height = slider.knob.bounds.height / 2
|
||||
local min_y = slider.clickarea.bounds.y0 + knob_half_height
|
||||
local max_y = slider.clickarea.bounds.y1 - knob_half_height
|
||||
|
||||
local new_value = 0
|
||||
if pointer.relative then
|
||||
-- User clicked on the knob. The new value will depend on how much the
|
||||
-- knob was dragged.
|
||||
new_value = pointer.start_value - 100 * (y - pointer.start_y) / (max_y - min_y)
|
||||
local new_value
|
||||
if widget.is_knob then
|
||||
local step_y = 100.0 / (widget.scale * widget.clickarea.bounds.height)
|
||||
new_value = pointer.start_value + (pointer.start_y - y) * step_y
|
||||
else
|
||||
-- User clicked elsewhere on the slider. The new value will depend on
|
||||
-- the absolute position of the click.
|
||||
new_value = 100 - 100 * (y - min_y) / (max_y - min_y)
|
||||
local knob_half_height = widget.slider_knob.bounds.height / 2
|
||||
local min_y = widget.clickarea.bounds.y0 + knob_half_height
|
||||
local max_y = widget.clickarea.bounds.y1 - knob_half_height
|
||||
|
||||
if pointer.relative then
|
||||
-- User clicked on the knob. The new value will depend on how
|
||||
-- much the knob was dragged.
|
||||
new_value = pointer.start_value - 100 * (y - pointer.start_y) / (max_y - min_y)
|
||||
else
|
||||
-- User clicked elsewhere on the slider. The new value will depend on
|
||||
-- the absolute position of the click.
|
||||
new_value = 100 - 100 * (y - min_y) / (max_y - min_y)
|
||||
end
|
||||
end
|
||||
|
||||
new_value = math.floor(new_value + 0.5)
|
||||
if new_value < 0 then new_value = 0 end
|
||||
if new_value > 100 then new_value = 100 end
|
||||
slider.field.user_value = new_value
|
||||
widget.field.user_value = new_value
|
||||
end
|
||||
|
||||
local function pointer_left(type, id, dev, x, y, up, cnt)
|
||||
@ -726,7 +753,7 @@ copyright-holders:m1macrophage
|
||||
view:set_forget_pointers_callback(forget_pointers)
|
||||
end
|
||||
-----------------------------------------------------------------------
|
||||
-- Slider library ends.
|
||||
-- Slider and knob library ends.
|
||||
-----------------------------------------------------------------------
|
||||
]]></script>
|
||||
</mamelayout>
|
||||
|
@ -33,12 +33,9 @@ PCBoards:
|
||||
|
||||
Usage:
|
||||
|
||||
The driver includes a (mostly) interactive layout, including buttons, LEDs and
|
||||
sliders. The only non-interactive widgets right now are the knobs (such as
|
||||
tuning and volume). Those will display their current value, but they can only
|
||||
be modified by the Slider Control menu.
|
||||
The driver includes an interactive layout.
|
||||
|
||||
Since there is no audio, the driver logs triggers and other info. To see these
|
||||
Since there is no audio, the driver logs triggers and other info. To see those,
|
||||
run the driver with `-log`:
|
||||
./mame -window linndrum -log
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user