Divergent/mods/Hideout Furniture/gamedata/scripts/ui_furniture_piano.script

1152 lines
29 KiB
Plaintext
Raw Blame History

gc = game.translate_string
local sound_object_by_path = {}
--' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
function get_safe_sound_object(path)
if sound_object_by_path[path] == nil then
local snd_obj = sound_object(path)
sound_object_by_path[path] = {snd_obj}
return snd_obj
end
for i, snd_obj in ipairs(sound_object_by_path[path]) do
if not snd_obj:playing() then
return snd_obj
end
end
local snd_obj = sound_object(path)
table.insert(sound_object_by_path, snd_obj)
return snd_obj
end
function stop_all_sound_object()
for k,v in pairs(sound_object_by_path) do
if v then
for i, snd_obj in pairs(v) do
snd_obj:stop()
end
end
end
sound_object_by_path = {}
end
local playing_piano_id = nil
local notes = {
"C1",
"C#1",
"D1",
"D#1",
"E1",
"F1",
"F#1",
"G1",
"G#1",
"A1",
"A#1",
"B1",
"C2",
"C#2",
"D2",
"D#2",
"E2",
"F2",
"F#2",
"G2",
"G#2",
"A2",
"A#2",
"B2",
"C3",
"C#3",
"D3",
"D#3",
"E3",
"F3",
"F#3",
"G3",
"G#3",
"A3",
"A#3",
"B3",
"C4",
"C#4",
"D4",
"D#4",
"E4",
"F4",
"F#4",
"G4",
"G#4",
"A4",
"A#4",
"B4",
"C5",
"C#5",
"D5",
"D#5",
"E5",
"F5",
"F#5",
"G5",
"G#5",
"A5",
"A#5",
"B5",
"C6",
"C#6",
"D6",
"D#6",
"E6",
"F6",
"F#6",
"G6",
"G#6",
"A6",
"A#6",
"B6",
"C7",
"C#7",
"D7",
"D#7",
"E7",
"F7",
"F#7",
"G7",
"G#7",
"A7",
"A#7",
"B7",
"C8",
}
local note2i = {}
local whitenote2i = {}
local sharpnote2i = {}
local i = 1
local note_i = 1
local sharp_i = 1
for k,v in pairs(notes) do
if string.find(v, "#") then
sharpnote2i[v] = sharp_i
sharp_i = sharp_i + 1
else
whitenote2i[v] = note_i
note_i = note_i + 1
end
note2i[v]=i
i = i + 1
end
-- local ini_instruments = ini_file_ex("plugins\\playable_piano\\instruments\\instrument_piano.ltx")
local ini_instruments = ini_file_ex("plugins\\playable_piano\\instruments\\instruments.ltx")
local instruments = {}
local note2snd = {}
-- for i, note_str in ipairs(notes) do
-- note2snd[note_str] = ini_instruments:r_string_ex("instrument_piano", note_str)
-- end
for i, section in pairs(ini_instruments:get_sections()) do
instruments[i] = {}
instruments[i]["name"] = ini_instruments:r_string_ex(section, "name")
for _, note_str in ipairs(notes) do
instruments[i][note_str] = ini_instruments:r_string_ex(section, note_str)
end
end
note2snd = instruments[1]
local dik2note = {
[DIK_keys.DIK_1] = "C2",
[DIK_keys.DIK_2] = "D2",
[DIK_keys.DIK_3] = "E2",
[DIK_keys.DIK_4] = "F2",
[DIK_keys.DIK_5] = "G2",
[DIK_keys.DIK_6] = "A2",
[DIK_keys.DIK_7] = "B2",
[DIK_keys.DIK_8] = "C3",
[DIK_keys.DIK_9] = "D3",
[DIK_keys.DIK_0] = "E3",
[DIK_keys.DIK_Q] = "F3",
[DIK_keys.DIK_W] = "G3",
[DIK_keys.DIK_E] = "A3",
[DIK_keys.DIK_R] = "B3",
[DIK_keys.DIK_T] = "C4",
[DIK_keys.DIK_Y] = "D4",
[DIK_keys.DIK_U] = "E4",
[DIK_keys.DIK_I] = "F4",
[DIK_keys.DIK_O] = "G4",
[DIK_keys.DIK_P] = "A4",
[DIK_keys.DIK_A] = "B4",
[DIK_keys.DIK_S] = "C5",
[DIK_keys.DIK_D] = "D5",
[DIK_keys.DIK_F] = "E5",
[DIK_keys.DIK_G] = "F5",
[DIK_keys.DIK_H] = "G5",
[DIK_keys.DIK_J] = "A5",
[DIK_keys.DIK_K] = "B5",
[DIK_keys.DIK_L] = "C6",
[DIK_keys.DIK_Z] = "D6",
[DIK_keys.DIK_X] = "E6",
[DIK_keys.DIK_C] = "F6",
[DIK_keys.DIK_V] = "G6",
[DIK_keys.DIK_B] = "A6",
[DIK_keys.DIK_N] = "B6",
[DIK_keys.DIK_M] = "C7",
}
local mod_dik2note = {
[DIK_keys.DIK_1] = "C#2",
[DIK_keys.DIK_2] = "D#2",
[DIK_keys.DIK_4] = "F#2",
[DIK_keys.DIK_5] = "G#2",
[DIK_keys.DIK_6] = "A#2",
[DIK_keys.DIK_8] = "C#3",
[DIK_keys.DIK_9] = "D#3",
[DIK_keys.DIK_Q] = "F#3",
[DIK_keys.DIK_W] = "G#3",
[DIK_keys.DIK_E] = "A#3",
[DIK_keys.DIK_T] = "C#4",
[DIK_keys.DIK_Y] = "D#4",
[DIK_keys.DIK_I] = "F#4",
[DIK_keys.DIK_O] = "G#4",
[DIK_keys.DIK_P] = "A#4",
[DIK_keys.DIK_S] = "C#5",
[DIK_keys.DIK_D] = "D#5",
[DIK_keys.DIK_G] = "F#5",
[DIK_keys.DIK_H] = "G#5",
[DIK_keys.DIK_J] = "A#5",
[DIK_keys.DIK_L] = "C#6",
[DIK_keys.DIK_Z] = "D#6",
[DIK_keys.DIK_C] = "F#6",
[DIK_keys.DIK_V] = "G#6",
[DIK_keys.DIK_B] = "A#6",
}
local mod_dik = DIK_keys.DIK_LSHIFT
local mod_held = false
local autokey2note = {
-- White keys
["1"] = "C2",
["2"] = "D2",
["3"] = "E2",
["4"] = "F2",
["5"] = "G2",
["6"] = "A2",
["7"] = "B2",
["8"] = "C3",
["9"] = "D3",
["0"] = "E3",
["q"] = "F3",
["w"] = "G3",
["e"] = "A3",
["r"] = "B3",
["t"] = "C4",
["y"] = "D4",
["u"] = "E4",
["i"] = "F4",
["o"] = "G4",
["p"] = "A4",
["a"] = "B4",
["s"] = "C5",
["d"] = "D5",
["f"] = "E5",
["g"] = "F5",
["h"] = "G5",
["j"] = "A5",
["k"] = "B5",
["l"] = "C6",
["z"] = "D6",
["x"] = "E6",
["c"] = "F6",
["v"] = "G6",
["b"] = "A6",
["n"] = "B6",
["m"] = "C7",
-- Black keys
["!"] = "C#2",
["@"] = "D#2",
["$"] = "F#2",
["%"] = "G#2",
["^"] = "A#2",
["*"] = "C#3",
["("] = "D#3",
["Q"] = "F#3",
["W"] = "G#3",
["E"] = "A#3",
["T"] = "C#4",
["Y"] = "D#4",
["I"] = "F#4",
["O"] = "G#4",
["P"] = "A#4",
["S"] = "C#5",
["D"] = "D#5",
["G"] = "F#5",
["H"] = "G#5",
["J"] = "A#5",
["L"] = "C#6",
["Z"] = "D#6",
["C"] = "F#6",
["V"] = "G#6",
["B"] = "A#6",
}
local bpm = 100
local transpose = 0
local volume = 1.0
local sheets = {}
local sheets_index = 1
local delay = {
WHOLENOTE = 1,
HALFNOTE = 2,
QUARTERNOTE = 4,
EIGHTHNOTE = 8
}
local function wait2secs(note)
if note == nil then
return nil
end
-- Converts note to seconds according to type of note (see enum notes) and current bpm
local spb = 60/bpm
return spb / note
end
function getSheetsWithTags(tags, tag2sheets)
local matching_sheets = {}
local tag_indexes = {}
for _, val in pairs(tags) do
-- Contains current index for access at a particular tag
tag_indexes[val] = 1
end
local selected_tag = tags[1]
local keep_looping = true
while keep_looping do
local selected_sheet = tag2sheets[selected_tag][tag_indexes[selected_tag]]
-- print(selected_sheet)
if selected_sheet == nil then
keep_looping = false
end
if keep_looping then
local next_tag = selected_tag
local is_matching = true
for _, tag in pairs(tags) do
-- Ignore comparison with the selected tag
if tag ~= selected_tag then
-- Check if tag has the same sheet as the selected one
local sheet = tag2sheets[tag][tag_indexes[tag]]
-- print("COMPARING:" .. selected_sheet .. "v" .. sheet)
if sheet ~= selected_sheet then
-- No match, pick tag with lowest sheet
is_matching = false
if sheet < selected_sheet then next_tag = tag end
end
end
end
-- found sheet with the same tags
if is_matching then
table.insert(matching_sheets, selected_sheet)
end
-- continue incrementing selected tag index
selected_tag = next_tag
tag_indexes[selected_tag] = tag_indexes[selected_tag] + 1
end
end
return matching_sheets
end
function getTags()
local ini_tags = ini_file_ex("plugins\\playable_piano\\tags\\categories.ltx")
local tags_info = {}
for _, section in pairs(ini_tags:get_sections()) do
local priority = ini_tags:r_float_ex(section, "priority")
table.insert(tags_info, {
["priority"] = priority,
["tag"] = section
})
end
table.sort(tags_info, function(a,b) return a["priority"] < b["priority"] end)
local tags = {}
local tag2sheets = {}
for i,v in ipairs(tags_info) do
table.insert(tags, v["tag"])
tag2sheets[v["tag"]] = {}
end
return tags, tag2sheets
end
local ini_sheets = ini_file_ex("plugins\\playable_piano\\sheets\\sheets.ltx")
-- local tags = getTags()
-- local tag2sheets = {}
local tags, tag2sheets = getTags()
local i = 1
for _, section in pairs(ini_sheets:get_sections()) do
local bpm = ini_sheets:r_float_ex(section, "bpm")
local title = ""
local sheet_path = ini_sheets:r_string_ex(section, "sheet")
local transpose = ini_sheets:r_float_ex(section, "transpose") or 0
local tags_str = ini_sheets:r_string_ex(section, "tags") or ""
-- Build inverted index of tags to list of sheets
local tags_list = str_explode(tags_str,",")
for j=1,#tags_list do
local tag = tags_list[j]
if tag2sheets[tag] == nil then
table.insert(tags, tag)
tag2sheets[tag] = {}
end
table.insert(tag2sheets[tag], i)
end
local file_reader = getFS():r_open("$game_config$", sheet_path)
local file_data = ""
local prev_char = nil
local simult_flag = false
local simult_notes = {}
local music_chart = {}
local read_modes = {
title=0,
subtitle=1,
sheet=2
}
local mode = read_modes.title
while not file_reader:r_eof() do
local raw_data = file_reader:r_u8()
local data = string.char(raw_data)
-- -- printf("CHAR: " .. data .. "|CODE: " .. raw_data)
if mode == read_modes.title then
if data == "\n" then
-- Transition to reading subtitles
title = file_data
file_data = ""
mode = read_modes.subtitle
else
file_data = file_data .. data
end
elseif mode == read_modes.subtitle then
if data == "\n" then
-- Transition to reading sheet
file_data = ""
mode = read_modes.sheet
end
-- Ignore subtitle text for now
-- -- printf("TITLE: " .. title)
elseif mode == read_modes.sheet then
if autokey2note[data] then
if simult_flag then
-- Collect notes together
table.insert(simult_notes, autokey2note[data])
else
-- Add quarternote pause for consecutive notes (jjjj)
if autokey2note[prev_char] or prev_char == "]" then
table.insert(music_chart, {
type = "wait", -- "note", "wait"
wait = delay.QUARTERNOTE
})
end
-- Play note (j)
table.insert(music_chart, {
type = "note", -- "note", "wait"
note = autokey2note[data]
})
end
elseif data == " " then
if simult_flag then
-- Add eighthnote pause for spaces in brackets ([j j j j])
if #simult_notes ~= 0 then
table.insert(music_chart, {
type = "notes",
notes = simult_notes
})
simult_notes = {}
end
table.insert(music_chart, {
type = "wait",
wait = delay.EIGHTHNOTE
})
else
-- Add halfnote pause for spaces (j j j j)
table.insert(music_chart, {
type = "wait",
wait = delay.HALFNOTE
})
end
elseif data == "|" then
-- Add wholenote pause for pipes (j|j|j|j)
table.insert(music_chart, {
type = "wait",
wait = delay.WHOLENOTE
})
-- -- ASCII code for carriage return (NOTE: newlines are done with codes 13, 10 in sequence)
elseif raw_data == 10 then
if prev_char == "\n" then
-- Add total of 2 whole note pause for 2 new lines (previous \n already added halfnote)
table.insert(music_chart, {
type = "wait",
wait = delay.HALFNOTE
})
table.insert(music_chart, {
type = "wait",
wait = delay.WHOLENOTE
})
else
-- Add halfnote pause for newlines
table.insert(music_chart, {
type = "wait",
wait = delay.HALFNOTE
})
end
elseif data == "[" then
if prev_char ~= " " and prev_char ~= "|" and prev_char ~= "\n" then
table.insert(music_chart, {
type = "wait", -- "note", "wait"
wait = delay.QUARTERNOTE
})
end
simult_flag = true
elseif data == "]" then
table.insert(music_chart, {
type = "notes",
notes = simult_notes
})
simult_flag = false
simult_notes = {}
end
-- if data == "\n" then
if raw_data == 10 then
file_data = file_data .. " \\n"
prev_char = data
elseif raw_data == 13 then
-- ignore carriage returns
else
file_data = file_data .. data
prev_char = data
end
end
end
table.insert(sheets, {
title = title,
bpm = bpm,
chart = music_chart,
transpose = transpose,
score = file_data,
})
i = i + 1
end
-- Functions for autoplaying music
function PlaySound(note)
-- Transpose note
local i = note2i[note]
i = i + transpose
local new_note = notes[i]
-- Play note
local snd = get_safe_sound_object(note2snd[new_note])
local obj = playing_piano_id and level.object_by_id(playing_piano_id) or db.actor
if snd then
snd:play_at_pos(obj, obj:position(), sound_object.s3d)
snd.volume = volume
else
-- printf("could not play sound")
end
end
local music_index = nil
local prev_part = nil
function UpdateChartMetadata()
bpm = sheets[sheets_index].bpm
transpose = sheets[sheets_index].transpose
-- printf("BPM: " .. bpm)
-- printf("Score: " .. sheets[sheets_index].score)
if GUI then
GUI.tempo_trackbar:SetFValue((bpm - 40) / 200)
GUI.tempo_value:SetText(bpm)
GUI.transpose_trackbar:SetFValue((12+transpose) / 24)
GUI.transpose_value:SetText(transpose)
GUI.volume_trackbar:SetFValue((volume) / 2)
GUI.volume_value:SetText(volume)
end
end
function IterateOverChart()
-- printf("IterateOverChart")
local music_chart = sheets[sheets_index].chart
if music_index == nil then
music_index = 1
end
local part = music_chart[music_index]
-- Animate key release
if prev_part and GUI then
local time_eighthnote = (60/bpm) / 8
if prev_part.notes then
for i, note in ipairs(prev_part.notes) do
local isSharp = false
if sharpnote2i[note] then
isSharp = true
end
local wait = part and wait2secs(part.wait) or time_eighthnote
wait = wait - (time_eighthnote / 2)
CreateTimeEvent("PlayablePiano","ReleaseKey-" .. note, wait, GUI.AnimateKeyRelease, GUI, note, isSharp)
end
end
if prev_part.note then
local isSharp = false
if sharpnote2i[prev_part.note] then
isSharp = true
end
local wait = part and wait2secs(part.wait) or time_eighthnote
wait = wait - (time_eighthnote / 2)
CreateTimeEvent("PlayablePiano","ReleaseKey-" .. prev_part.note, wait, GUI.AnimateKeyRelease, GUI, prev_part.note, isSharp)
end
end
if part == nil then
music_index = nil
prev_part = nil
-- printf("No more part")
return true
end
if part.type == "note" then
PlaySound(part.note)
if GUI then
local isSharp = false
if sharpnote2i[part.note] then
isSharp = true
end
GUI:AnimateKeyPress(part.note, isSharp)
end
-- printf("Play note: " .. part.note)
elseif part.type == "wait" then
-- printf("Wait for: " .. wait2secs(part.wait))
ResetTimeEvent("PlayablePiano","IterateChart",wait2secs(part.wait))
elseif part.type == "notes" then
-- printf("Play multiple notes")
for i, note in ipairs(part.notes) do
-- printf("Play note(multiple): " .. note)
PlaySound(note)
if GUI then
local isSharp = false
if sharpnote2i[note] then
isSharp = true
end
GUI:AnimateKeyPress(note, isSharp)
end
end
end
music_index = music_index + 1
prev_part = part
return false
end
-- UI for Piano Object
GUI = nil -- instance, don't touch
class "UIFurniturePiano" (CUIScriptWnd)
function UIFurniturePiano:__init() super()
self:InitControls()
self:InitCallbacks()
end
function UIFurniturePiano:__finalize()
GUI = nil
end
function UIFurniturePiano:InitControls()
self:SetWndRect(Frect():set(0,0,1024,768))
self.wide = (device().width/device().height) > (1024/768 + 0.01)
self:SetAutoDelete(true)
local xml = CScriptXmlInit()
-- xml:ParseFile("ui_sleep_dialog.xml")
xml:ParseFile("ui_furniture_piano_dialog.xml")
-- controls
self.autoplay_btn = xml:InitCheck("autoplay_btn", self)
self.autoplay_btn_text = xml:InitTextWnd("autoplay_btn:txt", self.autoplay_btn)
self.autoplay_btn_text:SetText(gc("st_autoplay"))
self:Register(self.autoplay_btn, "toggle_autoplay")
-- button toggle
self.piano_config_btn = xml:InitCheck("piano_config_btn", self)
self.piano_config_btn_text = xml:InitTextWnd("piano_config_btn:txt", self.piano_config_btn)
self.piano_config_btn_text:SetText(gc("st_configure"))
self:Register(self.piano_config_btn, "toggle_piano_config")
-- Config Background
self.piano_config_bg = xml:InitFrame("piano_config_bg", self)
self.piano_config_bg:Show(false)
self.piano_config_scroll = xml:InitScrollView("piano_config_scroll", self.piano_config_bg)
-- Tempo
self.tempo_container = xml:InitStatic("trackbar_container", self.piano_config_scroll)
self.tempo_caption = xml:InitTextWnd("trackbar_container:caption", self.tempo_container)
self.tempo_caption:SetText(gc("st_tempo"))
self.tempo_trackbar = xml:InitTrackBar("trackbar_container:trackbar", self.tempo_container)
self.tempo_value = xml:InitTextWnd("trackbar_container:value", self.tempo_container)
self.tempo_trackbar:SetStep(1/200)
self:Register(self.tempo_trackbar, "tempo")
-- Transpose
self.transpose_container = xml:InitStatic("trackbar_container", self.piano_config_scroll)
self.transpose_caption = xml:InitTextWnd("trackbar_container:caption", self.transpose_container)
self.transpose_caption:SetText(gc("st_transpose"))
self.transpose_trackbar = xml:InitTrackBar("trackbar_container:trackbar", self.transpose_container)
self.transpose_value = xml:InitTextWnd("trackbar_container:value", self.transpose_container)
self.transpose_trackbar:SetStep(1/24) -- Range: -12 to +12
self:Register(self.transpose_trackbar, "transpose")
-- Volume
self.volume_container = xml:InitStatic("trackbar_container", self.piano_config_scroll)
self.volume_caption = xml:InitTextWnd("trackbar_container:caption", self.volume_container)
self.volume_caption:SetText(gc("st_volume"))
self.volume_trackbar = xml:InitTrackBar("trackbar_container:trackbar", self.volume_container)
self.volume_value = xml:InitTextWnd("trackbar_container:value", self.volume_container)
self.volume_trackbar:SetStep(1/20) -- Range: 0.0 to 2.0
self.volume_trackbar:SetFValue(volume/2)
self:Register(self.volume_trackbar, "volume")
-- Instrument Select
self.instrument_container = xml:InitStatic("select_container", self.piano_config_scroll)
self.instrument_caption = xml:InitTextWnd("select_container:caption", self.instrument_container)
self.instrument_caption:SetText(gc("st_instrument"))
self.instrument_select = xml:InitComboBox("select_container:select", self.instrument_container)
self:Register(self.instrument_select, "instrument")
local i = 1
for instrument, notes2str in pairs(instruments) do
self.instrument_select:AddItem(notes2str["name"], i)
i = i+1
end
self.instrument_select:SetText(gc(instruments[1].name))
-- Sheet
self.sheet_bg = xml:InitFrame("sheet_bg", self)
-- Sheet Select
self.sheet_select = xml:InitComboBox("sheet_select", self)
self:Register(self.sheet_select, "sheet_select")
self.filtered_sheets = {}
for i=1,#sheets do
self.sheet_select:AddItem(sheets[i].title, i)
self.filtered_sheets[i] = i
end
self.sheet_select:SetText(sheets[1].title)
-- Tag Select
-- button toggle
self.tag_select_btn = xml:InitCheck("tag_select_btn", self)
self.tag_select_btn_text = xml:InitTextWnd("tag_select_btn:txt", self.tag_select_btn)
self.tag_select_btn_text:SetText(gc("st_filter_by_tag"))
self:Register(self.tag_select_btn, "toggle_tags")
self.tag_select_bg = xml:InitFrame("tag_select_bg", self)
self.tag_select_bg:Show(false)
self.tag_select_scroll = xml:InitScrollView("tag_select_scroll", self.tag_select_bg)
self.tag_checkboxes = {}
for i=1,#tags do
local tag_wnd = xml:InitStatic("tag_select", self.tag_select_scroll)
local tag_cap = xml:InitTextWnd("tag_select:cap_tag", tag_wnd)
tag_cap:SetText(gc(tags[i]))
local tag_check = xml:InitCheck("tag_select:check_tag", tag_wnd)
tag_check:SetCheck(false)
self:Register(tag_check, "tag_checkbox")
table.insert(self.tag_checkboxes, {
container = tag_wnd,
caption = tag_cap,
check = tag_check,
tag_name = tags[i]
})
end
self.score_scroll = xml:InitScrollView("score_scroll", self.sheet_bg)
self.title = xml:InitTextWnd("title", self.score_scroll)
self.title:SetText(sheets[sheets_index].title)
self.title:SetAutoDelete(false)
-- self.score_scroll:AddWindow(self.title, true)
self.score = xml:InitTextWnd("score", self.score_scroll)
self.score:SetText(sheets[sheets_index].score)
self.score:AdjustHeightToText()
self.score:SetAutoDelete(false)
-- self.score_scroll:AddWindow(self.score, true)
self.piano_bg = xml:InitStatic("piano_bg", self)
self.white_keys = {}
for i = 1, 36, 1 do
table.insert(self.white_keys, xml:InitStatic("white_key", self))
local new_pos = self.white_keys[i]:GetWndPos()
new_pos.x = new_pos.x + (self.white_keys[i]:GetWidth() * (i-1))
self.white_keys[i]:SetWndPos(new_pos)
end
local skip_key = {[3] = true,
[7] = true,
[10] = true,
[14] = true,
[17] = true,
[21] = true,
[24] = true,
[28] = true,
[31] = true,
}
self.black_keys = {}
local count = 1
for i = 1, 34, 1 do
if skip_key[i] ~= true then
table.insert(self.black_keys, xml:InitStatic("black_key", self))
local new_pos = self.black_keys[count]:GetWndPos()
new_pos.x = new_pos.x + (self.white_keys[1]:GetWidth() * (i-1))
self.black_keys[count]:SetWndPos(new_pos)
count = count + 1
end
end
self.btn_pickup = xml:Init3tButton("btn_pickup", self)
self:Register(self.btn_pickup, "btn_pickup")
self.btn_close = xml:Init3tButton("btn_close", self)
self:Register(self.btn_close, "btn_close")
end
function UIFurniturePiano:Pickup()
local obj = get_object_by_id(self.obj_id)
if obj:binded_object().is_world_obj then
actor_menu.set_msg(1, game.translate_string("st_reject_pickup_world_obj"),3)
self:Close()
return
end
local item_section = ini_sys:r_string_ex(obj:section(), "item_section") or "device_gas_lamp"
alife_create_item(item_section, db.actor)
-- local item = alife():create(item_section, db.actor:position(), 1, db.actor:game_vertex_id(), db.actor:id())
-- get_object_by_id(item.id):set_condition(obj:binded_object().fuel)
alife_release(obj)
self:Close()
end
function UIFurniturePiano:UpdateTempo()
local tempo = self.tempo_trackbar:GetFValue()
-- printf("Tempo (Float): " .. tempo)
-- printf("Tempo (BPM): " .. 40+(tempo*200))
bpm = round(40+(tempo*200))
self.tempo_value:SetText(bpm)
end
function UIFurniturePiano:UpdateTranspose()
local transpose_tb = self.transpose_trackbar:GetFValue()
-- printf("transpose (Float): " .. transpose_tb)
-- printf("transpose (BPM): " .. -12+(transpose_tb*24))
transpose = round(-12+(transpose_tb*24))
self.transpose_value:SetText(transpose)
end
function UIFurniturePiano:UpdateVolume()
local volume_tb = self.volume_trackbar:GetFValue()
-- printf("volume (Float): " .. volume_tb)
-- printf("volume (BPM): " .. (round(volume_tb*2*10))/10)
volume = (round(volume_tb*2*10))/10
self.volume_value:SetText(volume)
end
function UIFurniturePiano:OnInstrumentSelect()
-- printf("OnInstrumentSelect()")
local instrument_id = self.instrument_select:CurrentID()
local note_sounds = instruments[instrument_id]
note2snd = note_sounds
-- printf("OnInstrumentSelect() - COMPLETE")
end
function UIFurniturePiano:OnSheetSelect()
local channel_id = self.sheet_select:CurrentID()
sheets_index = self.filtered_sheets[channel_id]
UpdateChartMetadata()
RemoveTimeEvent("PlayablePiano","IterateChart")
music_index = 1
self.autoplay_btn:SetCheck(false)
self.title:SetText(sheets[sheets_index].title)
self.score:SetText(sheets[sheets_index].score)
self.score:AdjustHeightToText()
-- self.score:SetWndSize(vector2():set(self.score:GetWidth(), self.score:GetHeight()))
self.score_scroll:Clear()
self.score_scroll:AddWindow(self.title, true)
self.title:SetAutoDelete(false)
self.score_scroll:AddWindow(self.score, true)
self.score:SetAutoDelete(false)
end
function UIFurniturePiano:OnTagSelect()
local tags = {}
for i=1,#self.tag_checkboxes do
local is_checked = self.tag_checkboxes[i].check:GetCheck()
if is_checked then
table.insert(tags, self.tag_checkboxes[i].tag_name)
-- printf("CHECKBOX TICKED (" .. self.tag_checkboxes[i].caption:GetText() .. "): " .. i)
end
end
if next(tags) then
self.filtered_sheets = getSheetsWithTags(tags, tag2sheets)
self.sheet_select:ClearList()
for i, sheet in ipairs(self.filtered_sheets) do
self.sheet_select:AddItem(sheets[sheet].title, i)
end
else
self.filtered_sheets[i] = {}
self.sheet_select:ClearList()
for i, sheet in ipairs(sheets) do
self.sheet_select:AddItem(sheets[i].title, i)
self.filtered_sheets[i] = i
end
end
end
function UIFurniturePiano:ToggleAutoplay()
local autoplay = self.autoplay_btn:GetCheck()
if autoplay then
CreateTimeEvent("PlayablePiano","IterateChart", 0, IterateOverChart)
else
RemoveTimeEvent("PlayablePiano","IterateChart")
end
end
function UIFurniturePiano:TogglePianoConfig()
self.piano_config_bg:Show(self.piano_config_btn:GetCheck())
end
function UIFurniturePiano:ToggleTags()
self.tag_select_bg:Show(self.tag_select_btn:GetCheck())
end
function UIFurniturePiano:InitCallbacks()
-- piano controls
self:AddCallback("tempo", ui_events.BUTTON_CLICKED, self.UpdateTempo, self)
self:AddCallback("transpose", ui_events.BUTTON_CLICKED, self.UpdateTranspose, self)
self:AddCallback("volume", ui_events.BUTTON_CLICKED, self.UpdateVolume, self)
self:AddCallback("instrument", ui_events.LIST_ITEM_SELECT, self.OnInstrumentSelect, self)
self:AddCallback("toggle_autoplay", ui_events.BUTTON_CLICKED, self.ToggleAutoplay, self)
self:AddCallback("toggle_piano_config", ui_events.BUTTON_CLICKED, self.TogglePianoConfig, self)
self:AddCallback("toggle_tags", ui_events.BUTTON_CLICKED, self.ToggleTags, self)
-- sheet controls
self:AddCallback("sheet_select", ui_events.LIST_ITEM_SELECT, self.OnSheetSelect, self)
self:AddCallback("tag_checkbox", ui_events.BUTTON_CLICKED, self.OnTagSelect, self)
self:AddCallback("btn_pickup", ui_events.BUTTON_CLICKED, self.Pickup, self)
self:AddCallback("btn_close", ui_events.BUTTON_CLICKED, self.Close, self)
end
function UIFurniturePiano:Initialize()
end
function UIFurniturePiano:TestAndShow(obj_id)
-- printf("awf")
playing_piano_id = obj_id
self.obj_id = obj_id
self:Initialize()
self:ShowDialog(true)
Register_UI("UIFurniturePiano","ui_piano_dialog")
end
function UIFurniturePiano:Update()
CUIScriptWnd.Update(self)
-- self.title:SetText(sheets[sheets_index].title)
-- self.score:SetText(sheets[sheets_index].score)
end
function UIFurniturePiano:OnTrackButton()
end
function UIFurniturePiano:AnimateKeyPress(note, isSharp)
local note_static = nil
if isSharp then
local index = sharpnote2i[note] - 5
-- printf("Index: " .. index)
note_static = self.black_keys[index]
if not note_static then
-- printf("Could not find image static for note.")
return
end
note_static:InitTexture("ui_inGame2_piano_blackkey_on")
else
local index = whitenote2i[note] - 7
-- printf("Index: " .. index)
note_static = self.white_keys[index]
if not note_static then
-- printf("Could not find image static for note.")
return
end
note_static:InitTexture("ui_inGame2_piano_whitekey_on")
end
end
function UIFurniturePiano:AnimateKeyRelease(note, isSharp)
local note_static = nil
if isSharp then
local index = sharpnote2i[note] - 5
-- printf("Index: " .. index)
note_static = self.black_keys[index]
if not note_static then
-- printf("Could not find image static for note.")
return true
end
note_static:InitTexture("ui_inGame2_piano_blackkey_off")
else
local index = whitenote2i[note] - 7
-- printf("Index: " .. index)
note_static = self.white_keys[index]
if not note_static then
-- printf("Could not find image static for note.")
return true
end
note_static:InitTexture("ui_inGame2_piano_whitekey_off")
end
return true
end
function UIFurniturePiano:OnKeyboard(dik, keyboard_action)
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
if (res == false) then
local bind = dik_to_bind(dik)
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
if dik == mod_dik then
mod_held = true
end
if dik == DIK_keys.DIK_ESCAPE then
self:Close()
end
-- -- Hotkey for changing sheets
-- if dik == DIK_keys.DIK_RIGHT then
-- if sheets_index < #sheets then
-- sheets_index = sheets_index + 1
-- end
-- UpdateChartMetadata()
-- -- printf("Selected: " .. sheets[sheets_index].title)
-- end
-- if dik == DIK_keys.DIK_LEFT then
-- if sheets_index > 1 then
-- sheets_index = sheets_index - 1
-- end
-- UpdateChartMetadata()
-- -- printf("Selected: " .. sheets[sheets_index].title)
-- end
-- -- Hotkey for transpose
-- if dik == DIK_keys.DIK_UP then
-- if transpose < 12 then transpose = transpose + 1 end
-- -- printf("Transpose: " .. transpose)
-- end
-- if dik == DIK_keys.DIK_DOWN then
-- if transpose > 1 then transpose = transpose - 1 end
-- -- printf("Transpose: " .. transpose)
-- end
-- Hotkey for autoplay
-- if dik == DIK_keys.DIK_HOME then
-- -- printf("Pressed HOME key")
-- CreateTimeEvent("PlayablePiano","IterateChart", 0, IterateOverChart)
-- end
if (not mod_held) and dik2note[dik] then
local note = dik2note[dik]
PlaySound(note)
self:AnimateKeyPress(note, false)
elseif mod_held and mod_dik2note[dik] then
local note = mod_dik2note[dik]
PlaySound(note)
self:AnimateKeyPress(note, true)
end
elseif keyboard_action == ui_events.WINDOW_KEY_RELEASED then
if dik == mod_dik then
mod_held = false
end
if (not mod_held) and dik2note[dik] then
local note = dik2note[dik]
self:AnimateKeyRelease(note, false)
elseif mod_held and mod_dik2note[dik] then
local note = mod_dik2note[dik]
self:AnimateKeyRelease(note, true)
end
end
end
return res
end
function UIFurniturePiano:Close()
if (self:IsShown()) then
self:HideDialog()
end
Unregister_UI("UIFurniturePiano")
end
-------
function start_dialog(obj_id)
-- printf("awf")
if (GUI == nil) then
GUI = UIFurniturePiano()
end
GUI:TestAndShow(obj_id)
UpdateChartMetadata()
--return GUI
end