Skip to content

Commit

Permalink
Add color support to Midi Fighter Twister controller presets
Browse files Browse the repository at this point in the history
  • Loading branch information
helgoboss committed Feb 13, 2024
1 parent 614de4f commit 5e2a388
Show file tree
Hide file tree
Showing 6 changed files with 528 additions and 5 deletions.
2 changes: 1 addition & 1 deletion main/lib/helgoboss-learn
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
--!strict

local realearn = require("realearn")
local commons = require("djtechtools/midi-fighter-twister-lib/preset-commons")
local commons = require("djtechtools/midi-fighter-twister-lib/preset-common")

return commons.create_compartment {
create_push_target = function (col, row)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
--!strict

local midi_script = require("midi_script_source_runtime")

local module = {}

local color_palette: { midi_script.RgbColor } = {
{ r = 0, g = 0, b = 0 },
{ r = 0, g = 0, b = 255 },
{ r = 0, g = 21, b = 255 },
{ r = 0, g = 34, b = 255 },
{ r = 0, g = 46, b = 255 },
{ r = 0, g = 59, b = 255 },
{ r = 0, g = 68, b = 255 },
{ r = 0, g = 80, b = 255 },
{ r = 0, g = 93, b = 255 },
{ r = 0, g = 106, b = 255 },
{ r = 0, g = 119, b = 255 },
{ r = 0, g = 127, b = 255 },
{ r = 0, g = 140, b = 255 },
{ r = 0, g = 153, b = 255 },
{ r = 0, g = 165, b = 255 },
{ r = 0, g = 178, b = 255 },
{ r = 0, g = 191, b = 255 },
{ r = 0, g = 199, b = 255 },
{ r = 0, g = 212, b = 255 },
{ r = 0, g = 225, b = 255 },
{ r = 0, g = 238, b = 255 },
{ r = 0, g = 250, b = 255 },
{ r = 0, g = 255, b = 250 },
{ r = 0, g = 255, b = 237 },
{ r = 0, g = 255, b = 225 },
{ r = 0, g = 255, b = 212 },
{ r = 0, g = 255, b = 199 },
{ r = 0, g = 255, b = 191 },
{ r = 0, g = 255, b = 178 },
{ r = 0, g = 255, b = 165 },
{ r = 0, g = 255, b = 153 },
{ r = 0, g = 255, b = 140 },
{ r = 0, g = 255, b = 127 },
{ r = 0, g = 255, b = 119 },
{ r = 0, g = 255, b = 106 },
{ r = 0, g = 255, b = 93 },
{ r = 0, g = 255, b = 80 },
{ r = 0, g = 255, b = 67 },
{ r = 0, g = 255, b = 59 },
{ r = 0, g = 255, b = 46 },
{ r = 0, g = 255, b = 33 },
{ r = 0, g = 255, b = 21 },
{ r = 0, g = 255, b = 8 },
{ r = 0, g = 255, b = 0 },
{ r = 12, g = 255, b = 0 },
{ r = 25, g = 255, b = 0 },
{ r = 38, g = 255, b = 0 },
{ r = 51, g = 255, b = 0 },
{ r = 63, g = 255, b = 0 },
{ r = 72, g = 255, b = 0 },
{ r = 84, g = 255, b = 0 },
{ r = 97, g = 255, b = 0 },
{ r = 110, g = 255, b = 0 },
{ r = 123, g = 255, b = 0 },
{ r = 131, g = 255, b = 0 },
{ r = 144, g = 255, b = 0 },
{ r = 157, g = 255, b = 0 },
{ r = 170, g = 255, b = 0 },
{ r = 182, g = 255, b = 0 },
{ r = 191, g = 255, b = 0 },
{ r = 203, g = 255, b = 0 },
{ r = 216, g = 255, b = 0 },
{ r = 229, g = 255, b = 0 },
{ r = 242, g = 255, b = 0 },
{ r = 255, g = 255, b = 0 },
{ r = 255, g = 246, b = 0 },
{ r = 255, g = 233, b = 0 },
{ r = 255, g = 220, b = 0 },
{ r = 255, g = 208, b = 0 },
{ r = 255, g = 195, b = 0 },
{ r = 255, g = 187, b = 0 },
{ r = 255, g = 174, b = 0 },
{ r = 255, g = 161, b = 0 },
{ r = 255, g = 148, b = 0 },
{ r = 255, g = 135, b = 0 },
{ r = 255, g = 127, b = 0 },
{ r = 255, g = 114, b = 0 },
{ r = 255, g = 102, b = 0 },
{ r = 255, g = 89, b = 0 },
{ r = 255, g = 76, b = 0 },
{ r = 255, g = 63, b = 0 },
{ r = 255, g = 55, b = 0 },
{ r = 255, g = 42, b = 0 },
{ r = 255, g = 29, b = 0 },
{ r = 255, g = 16, b = 0 },
{ r = 255, g = 4, b = 0 },
{ r = 255, g = 0, b = 4 },
{ r = 255, g = 0, b = 16 },
{ r = 255, g = 0, b = 29 },
{ r = 255, g = 0, b = 42 },
{ r = 255, g = 0, b = 55 },
{ r = 255, g = 0, b = 63 },
{ r = 255, g = 0, b = 76 },
{ r = 255, g = 0, b = 89 },
{ r = 255, g = 0, b = 102 },
{ r = 255, g = 0, b = 114 },
{ r = 255, g = 0, b = 127 },
{ r = 255, g = 0, b = 135 },
{ r = 255, g = 0, b = 148 },
{ r = 255, g = 0, b = 161 },
{ r = 255, g = 0, b = 174 },
{ r = 255, g = 0, b = 186 },
{ r = 255, g = 0, b = 195 },
{ r = 255, g = 0, b = 208 },
{ r = 255, g = 0, b = 221 },
{ r = 255, g = 0, b = 233 },
{ r = 255, g = 0, b = 246 },
{ r = 255, g = 0, b = 255 },
{ r = 242, g = 0, b = 255 },
{ r = 229, g = 0, b = 255 },
{ r = 216, g = 0, b = 255 },
{ r = 204, g = 0, b = 255 },
{ r = 191, g = 0, b = 255 },
{ r = 182, g = 0, b = 255 },
{ r = 169, g = 0, b = 255 },
{ r = 157, g = 0, b = 255 },
{ r = 144, g = 0, b = 255 },
{ r = 131, g = 0, b = 255 },
{ r = 123, g = 0, b = 255 },
{ r = 110, g = 0, b = 255 },
{ r = 97, g = 0, b = 255 },
{ r = 85, g = 0, b = 255 },
{ r = 72, g = 0, b = 255 },
{ r = 63, g = 0, b = 255 },
{ r = 50, g = 0, b = 255 },
{ r = 38, g = 0, b = 255 },
{ r = 25, g = 0, b = 255 },
{ r = 240, g = 240, b = 225 },
}

type FeedbackEntry = {
behavior: number,
color: number?,
}
local dark = 30
local medium = 40
local bright = 47
local pulsing = 12
local blinking = 8
local red_color = 83
local default_color = 21
local feedback_table: { [string]: FeedbackEntry? } = {
empty = {
behavior = bright,
color = 0,
},
armed = {
behavior = dark,
color = red_color,
},
stopped = {
behavior = dark,
},
scheduled_for_play_start = {
behavior = medium,
},
playing = {
behavior = pulsing,
},
paused = {
behavior = dark,
},
scheduled_for_play_stop = {
behavior = blinking,
},
scheduled_for_record_start = {
behavior = medium,
color = red_color,
},
recording = {
behavior = pulsing,
color = red_color,
},
scheduled_for_record_stop = {
behavior = blinking,
color = red_color,
},
}

--- Returns the 0-based index within the given palette array.
local function find_closest_color_in_palette(color: midi_script.RgbColor, palette: { midi_script.RgbColor }): number
local ifurthest = 0
local furthest = 3 * math.pow(255, 2) + 1
for i, c in palette do
if color.r == c.r and color.g == c.g and color.b == c.b then
return i - 1
end
local distance = math.pow((color.r - c.r), 2) + math.pow((color.g - c.g), 2) + math.pow((color.b - c.b), 2)
if distance < furthest then
furthest = distance
ifurthest = i - 1
end
end
return ifurthest
end

local function create_output(pad_index: number, color_index: number, behavior: number): midi_script.Output
return {
address = pad_index,
messages = {
{ 0xB1, pad_index, color_index },
{ 0xB2, pad_index, behavior },
},
}
end

function module.pad_script(
pad_index: number,
y: midi_script.InputValue,
context: midi_script.Context
): midi_script.Output
local off_color = 0x00
local off_output = create_output(pad_index, off_color, bright)
-- Handle "off" feedback
if y == nil then
return off_output
end
-- Handle numeric feedback
if type(y) == "number" then
-- Translate number to solid feedback color.
local color = math.floor(y * 127)
return create_output(pad_index, color, bright)
end
-- Handle text feedback
if type(y) == "string" then
-- This can be used as a grid controller for controlling a clip matrix, so we should be able to
-- handle text feedback that conforms to Playtime's clip state convention.
local entry = feedback_table[y]
if entry == nil then
-- Unknown texts switch the LED off
return off_output
end
local explicit_color = entry.color
if explicit_color ~= nil then
-- Switch LED to explicit color
return create_output(pad_index, explicit_color, entry.behavior)
end
-- No explicit color means we should use the event color (which is set in the "Glue" section)
local event_color = context.feedback_event.color
if event_color == nil then
-- Event has default color / no specific color
return create_output(pad_index, default_color, entry.behavior)
end
-- Find color available on the controller that's closest to the desired RGB color
local closest_color = find_closest_color_in_palette(event_color, color_palette)
return create_output(pad_index, closest_color, entry.behavior)
end
-- Complex feedback is highly individual. It doesn't make sense to handle this in a general-purpose controller preset.
return {
address = pad_index,
messages = {},
}
end

return module
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
--!strict

local preset_runtime = require("preset_runtime")
local realearn = require("realearn")

local module = {}
Expand All @@ -9,11 +10,18 @@ export type MidiFighterTwisterPresetConfig = {
create_push_target: (col: number, row: number) -> realearn.Target,
}

local common_lua = preset_runtime.include_str("djtechtools/midi-fighter-twister-lib/compartment-common.luau")

local function build_pad_script(pad_index: number): string
return `return require("compartment").pad_script({pad_index}, y, context)`
end

function module.create_compartment(config: MidiFighterTwisterPresetConfig): realearn.Compartment
-- Preparation
local function pad(col: number, row: number, cc_number: number): realearn.Mapping
local function pad_control(col: number, row: number, cc_number: number): realearn.Mapping
return realearn.Mapping {
id = `col{col + 1}/row{row + 1}/pad`,
feedback_enabled = false,
source = realearn.Source.MidiControlChangeValue {
channel = 1,
controller_number = cc_number,
Expand All @@ -23,6 +31,18 @@ function module.create_compartment(config: MidiFighterTwisterPresetConfig): real
}
end

local function pad_feedback(col: number, row: number, cc_number: number): realearn.Mapping
return realearn.Mapping {
id = `col{col + 1}/row{row + 1}/pad/feedback`,
control_enabled = false,
source = realearn.Source.MidiScript {
script_kind = "Lua",
script = build_pad_script(cc_number),
},
target = config.create_push_target(col, row)
}
end

local function knob(col: number, row: number, cc_number: number): realearn.Mapping
return realearn.Mapping {
id = `col{col + 1}/row{row + 1}/knob`,
Expand Down Expand Up @@ -67,7 +87,8 @@ function module.create_compartment(config: MidiFighterTwisterPresetConfig): real
for col = 0, column_count - 1 do
for row = 0, row_count - 1 do
local cc_number = row * row_count + col
table.insert(mappings, pad(col, row, cc_number))
table.insert(mappings, pad_control(col, row, cc_number))
table.insert(mappings, pad_feedback(col, row, cc_number))
table.insert(mappings, knob(col, row, cc_number))
end
end
Expand Down Expand Up @@ -562,6 +583,7 @@ function module.create_compartment(config: MidiFighterTwisterPresetConfig): real
-- Result
return realearn.Compartment {
mappings = mappings,
common_lua = common_lua,
custom_data = {
companion = companion_data,
numbered = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
--!strict

local realearn = require("realearn")
local commons = require("djtechtools/midi-fighter-twister-lib/preset-commons")
local commons = require("djtechtools/midi-fighter-twister-lib/preset-common")

return commons.create_compartment {
create_push_target = function (col, row)
Expand Down
Loading

0 comments on commit 5e2a388

Please sign in to comment.