mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-14 09:35:30 +01:00
Instrument editor now uses TGUI (#81923)
## About The Pull Request Instruments now use TGUI as their editor which is pretty cool. It's mostly a 1:1 remake of the HTML UI except I did make a change to make the playback options a little more compact, leaving some more space for the editor before you have to scroll, and some other minor things that were made to make the UI hopefully nicer to look at and mess with. When there's a song to play - While playing, Repeat section can't be edited  Help section and UI when there's no song put in  ## Why It's Good For The Game It is yet another step in finishing up https://hackmd.io/XLt5MoRvRxuhFbwtk4VAUA?view Instruments especially were in a poor spot because they didn't respect things like ``IN_USE`` to not refresh if it's not the "UI" you are on, and such. ## Changelog 🆑 refactor: Instruments now use TGUI. /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -34,20 +34,7 @@
|
||||
user.visible_message(span_suicide("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!"))
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/instrument/attack_self(mob/user)
|
||||
if(!ISADVANCEDTOOLUSER(user))
|
||||
to_chat(user, span_warning("You don't have the dexterity to do this!"))
|
||||
return TRUE
|
||||
interact(user)
|
||||
|
||||
/obj/item/instrument/interact(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/instrument/ui_interact(mob/living/user)
|
||||
if(!isliving(user) || user.stat != CONSCIOUS || (HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) && !ispAI(user)))
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
/obj/item/instrument/ui_interact(mob/user, datum/tgui/ui)
|
||||
song.ui_interact(user)
|
||||
|
||||
/obj/item/instrument/violin
|
||||
@@ -130,9 +117,9 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/spooky)
|
||||
|
||||
/obj/item/instrument/trumpet/spectral/attack(mob/living/carbon/C, mob/user)
|
||||
playsound (src, 'sound/runtime/instruments/trombone/En4.mid', 100,1,-1)
|
||||
..()
|
||||
/obj/item/instrument/trumpet/spectral/attack(mob/living/target_mob, mob/living/user, params)
|
||||
playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1)
|
||||
return ..()
|
||||
|
||||
/obj/item/instrument/saxophone
|
||||
name = "saxophone"
|
||||
@@ -154,9 +141,9 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/spooky)
|
||||
|
||||
/obj/item/instrument/saxophone/spectral/attack(mob/living/carbon/C, mob/user)
|
||||
playsound (src, 'sound/runtime/instruments/saxophone/En4.mid', 100,1,-1)
|
||||
..()
|
||||
/obj/item/instrument/saxophone/spectral/attack(mob/living/target_mob, mob/living/user, params)
|
||||
playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1)
|
||||
return ..()
|
||||
|
||||
/obj/item/instrument/trombone
|
||||
name = "trombone"
|
||||
@@ -178,9 +165,9 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/spooky)
|
||||
|
||||
/obj/item/instrument/trombone/spectral/attack(mob/living/carbon/C, mob/user)
|
||||
playsound (src, 'sound/runtime/instruments/trombone/Cn4.mid', 100,1,-1)
|
||||
..()
|
||||
/obj/item/instrument/trombone/spectral/attack(mob/living/target_mob, mob/living/user, params)
|
||||
playsound(src, 'sound/runtime/instruments/trombone/Cn4.mid', 1000, 1, -1)
|
||||
return ..()
|
||||
|
||||
/obj/item/instrument/recorder
|
||||
name = "recorder"
|
||||
@@ -201,19 +188,24 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
actions_types = list(/datum/action/item_action/instrument)
|
||||
|
||||
/obj/item/instrument/harmonica/equipped(mob/user, slot, initial = FALSE)
|
||||
. = ..()
|
||||
if(!(slot & slot_flags))
|
||||
return
|
||||
RegisterSignal(user, COMSIG_MOB_SAY, PROC_REF(handle_speech))
|
||||
|
||||
/obj/item/instrument/harmonica/dropped(mob/user, silent = FALSE)
|
||||
. = ..()
|
||||
UnregisterSignal(user, COMSIG_MOB_SAY)
|
||||
|
||||
/obj/item/instrument/harmonica/proc/handle_speech(datum/source, list/speech_args)
|
||||
SIGNAL_HANDLER
|
||||
if(song.playing && ismob(loc))
|
||||
to_chat(loc, span_warning("You stop playing the harmonica to talk..."))
|
||||
song.playing = FALSE
|
||||
|
||||
/obj/item/instrument/harmonica/equipped(mob/M, slot)
|
||||
. = ..()
|
||||
RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech))
|
||||
|
||||
/obj/item/instrument/harmonica/dropped(mob/M)
|
||||
. = ..()
|
||||
UnregisterSignal(M, COMSIG_MOB_SAY)
|
||||
if(!song.playing)
|
||||
return
|
||||
if(!ismob(loc))
|
||||
CRASH("[src] was still registered to listen in on [source] but was not found to be on their mob.")
|
||||
to_chat(loc, span_warning("You stop playing the harmonica to talk..."))
|
||||
song.playing = FALSE
|
||||
|
||||
/datum/action/item_action/instrument
|
||||
name = "Use Instrument"
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
stopped_playing.set_output(COMPONENT_SIGNAL)
|
||||
|
||||
/obj/item/circuit_component/synth/proc/import_song()
|
||||
synth.song.ParseSong(song.value)
|
||||
synth.song.ParseSong(new_song = song.value)
|
||||
|
||||
/obj/item/circuit_component/synth/proc/set_repetitions()
|
||||
synth.song.set_repeats(repetitions.value)
|
||||
@@ -169,7 +169,9 @@
|
||||
synth.song.note_shift = clamp(note_shift.value, synth.song.note_shift_min, synth.song.note_shift_max)
|
||||
|
||||
/obj/item/circuit_component/synth/proc/set_sustain_mode()
|
||||
synth.song.sustain_mode = SSinstruments.note_sustain_modes[sustain_mode.value]
|
||||
if(!(sustain_mode.value in SSinstruments.note_sustain_modes))
|
||||
return
|
||||
synth.song.sustain_mode = sustain_mode.value
|
||||
|
||||
/obj/item/circuit_component/synth/proc/set_sustain_value()
|
||||
switch(synth.song.sustain_mode)
|
||||
|
||||
@@ -23,11 +23,6 @@
|
||||
/// Are we currently playing?
|
||||
var/playing = FALSE
|
||||
|
||||
/// Are we currently editing?
|
||||
var/editing = TRUE
|
||||
/// Is the help screen open?
|
||||
var/help = FALSE
|
||||
|
||||
/// Repeats left
|
||||
var/repeat = 0
|
||||
/// Maximum times we can repeat
|
||||
@@ -107,7 +102,6 @@
|
||||
var/note_shift = 0
|
||||
var/note_shift_min = -100
|
||||
var/note_shift_max = 100
|
||||
var/can_noteshift = TRUE
|
||||
/// The kind of sustain we're using
|
||||
var/sustain_mode = SUSTAIN_LINEAR
|
||||
/// When a note is considered dead if it is below this in volume
|
||||
@@ -129,7 +123,7 @@
|
||||
tempo = sanitize_tempo(tempo, TRUE)
|
||||
src.parent = parent
|
||||
if(instrument_ids)
|
||||
allowed_instrument_ids = islist(instrument_ids)? instrument_ids : list(instrument_ids)
|
||||
allowed_instrument_ids = islist(instrument_ids) ? instrument_ids : list(instrument_ids)
|
||||
if(length(allowed_instrument_ids))
|
||||
set_instrument(allowed_instrument_ids[1])
|
||||
hearing_mobs = list()
|
||||
@@ -217,8 +211,6 @@
|
||||
delay_by = 0
|
||||
current_chord = 1
|
||||
music_player = user
|
||||
if(ismob(music_player))
|
||||
updateDialog(music_player)
|
||||
START_PROCESSING(SSinstruments, src)
|
||||
|
||||
/**
|
||||
@@ -328,12 +320,6 @@
|
||||
/datum/song/proc/set_bpm(bpm)
|
||||
tempo = sanitize_tempo(600 / bpm)
|
||||
|
||||
/**
|
||||
* Updates the window for our users. Override down the line.
|
||||
*/
|
||||
/datum/song/proc/updateDialog(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/datum/song/process(wait)
|
||||
if(!playing)
|
||||
return PROCESS_KILL
|
||||
@@ -359,7 +345,6 @@
|
||||
/datum/song/proc/set_volume(volume)
|
||||
src.volume = clamp(round(volume, 1), max(0, min_volume), min(100, max_volume))
|
||||
update_sustain()
|
||||
updateDialog()
|
||||
|
||||
/**
|
||||
* Setter for setting how low the volume has to get before a note is considered "dead" and dropped
|
||||
@@ -367,7 +352,6 @@
|
||||
/datum/song/proc/set_dropoff_volume(volume)
|
||||
sustain_dropoff_volume = clamp(round(volume, 0.01), INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100)
|
||||
update_sustain()
|
||||
updateDialog()
|
||||
|
||||
/**
|
||||
* Setter for setting exponential falloff factor.
|
||||
@@ -375,7 +359,6 @@
|
||||
/datum/song/proc/set_exponential_drop_rate(drop)
|
||||
sustain_exponential_dropoff = clamp(round(drop, 0.00001), INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX)
|
||||
update_sustain()
|
||||
updateDialog()
|
||||
|
||||
/**
|
||||
* Setter for setting linear falloff duration.
|
||||
@@ -383,7 +366,6 @@
|
||||
/datum/song/proc/set_linear_falloff_duration(duration)
|
||||
sustain_linear_duration = clamp(round(duration * 10, world.tick_lag), world.tick_lag, INSTRUMENT_MAX_TOTAL_SUSTAIN)
|
||||
update_sustain()
|
||||
updateDialog()
|
||||
|
||||
/datum/song/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
@@ -401,9 +383,6 @@
|
||||
// subtype for handheld instruments, like violin
|
||||
/datum/song/handheld
|
||||
|
||||
/datum/song/handheld/updateDialog(mob/user)
|
||||
parent.ui_interact(user || usr)
|
||||
|
||||
/datum/song/handheld/should_stop_playing(atom/player)
|
||||
. = ..()
|
||||
if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS)
|
||||
@@ -414,9 +393,6 @@
|
||||
// subtype for stationary structures, like pianos
|
||||
/datum/song/stationary
|
||||
|
||||
/datum/song/stationary/updateDialog(mob/user)
|
||||
parent.ui_interact(user || usr)
|
||||
|
||||
/datum/song/stationary/should_stop_playing(atom/player)
|
||||
. = ..()
|
||||
if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS)
|
||||
|
||||
@@ -1,96 +1,189 @@
|
||||
/**
|
||||
* Returns the HTML for the status UI for this song datum.
|
||||
*/
|
||||
/datum/song/proc/instrument_status_ui()
|
||||
. = list()
|
||||
. += "<div class='statusDisplay'>"
|
||||
. += "<b><a href='?src=[REF(src)];switchinstrument=1'>Current instrument</a>:</b> "
|
||||
if(!using_instrument)
|
||||
. += "[span_danger("No instrument loaded!")]<br>"
|
||||
else
|
||||
. += "[using_instrument.name]<br>"
|
||||
. += "Playback Settings:<br>"
|
||||
if(can_noteshift)
|
||||
. += "<a href='?src=[REF(src)];setnoteshift=1'>Note Shift/Note Transpose</a>: [note_shift] keys / [round(note_shift / 12, 0.01)] octaves<br>"
|
||||
var/smt
|
||||
var/modetext = ""
|
||||
/datum/song/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, "InstrumentEditor", parent.name)
|
||||
ui.open()
|
||||
|
||||
/datum/song/ui_host(mob/user)
|
||||
return parent
|
||||
|
||||
/datum/song/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["using_instrument"] = using_instrument?.name || "No instrument loaded!"
|
||||
data["note_shift"] = note_shift
|
||||
data["octaves"] = round(note_shift / 12, 0.01)
|
||||
data["sustain_mode"] = sustain_mode
|
||||
switch(sustain_mode)
|
||||
if(SUSTAIN_LINEAR)
|
||||
smt = "Linear"
|
||||
modetext = "<a href='?src=[REF(src)];setlinearfalloff=1'>Linear Sustain Duration</a>: [sustain_linear_duration / 10] seconds<br>"
|
||||
data["sustain_mode_button"] = "Linear Sustain Duration (in seconds)"
|
||||
data["sustain_mode_duration"] = sustain_linear_duration / 10
|
||||
data["sustain_mode_min"] = INSTRUMENT_MIN_TOTAL_SUSTAIN
|
||||
data["sustain_mode_max"] = INSTRUMENT_MAX_TOTAL_SUSTAIN
|
||||
if(SUSTAIN_EXPONENTIAL)
|
||||
smt = "Exponential"
|
||||
modetext = "<a href='?src=[REF(src)];setexpfalloff=1'>Exponential Falloff Factor</a>: [sustain_exponential_dropoff]% per decisecond<br>"
|
||||
. += "<a href='?src=[REF(src)];setsustainmode=1'>Sustain Mode</a>: [smt]<br>"
|
||||
. += modetext
|
||||
. += using_instrument?.ready()? "Status: <span class='good'>Ready</span><br>" : "Status: <span class='bad'>!Instrument Definition Error!</span><br>"
|
||||
. += "Instrument Type: [legacy? "Legacy" : "Synthesized"]<br>"
|
||||
. += "<a href='?src=[REF(src)];setvolume=1'>Volume</a>: [volume]<br>"
|
||||
. += "<a href='?src=[REF(src)];setdropoffvolume=1'>Volume Dropoff Threshold</a>: [sustain_dropoff_volume]<br>"
|
||||
. += "<a href='?src=[REF(src)];togglesustainhold=1'>Sustain indefinitely last held note</a>: [full_sustain_held_note? "Enabled" : "Disabled"].<br>"
|
||||
. += "</div>"
|
||||
data["sustain_mode_button"] = "Exponential Falloff Factor (% per decisecond)"
|
||||
data["sustain_mode_duration"] = sustain_exponential_dropoff
|
||||
data["sustain_mode_min"] = INSTRUMENT_EXP_FALLOFF_MIN
|
||||
data["sustain_mode_max"] = INSTRUMENT_EXP_FALLOFF_MAX
|
||||
data["instrument_ready"] = using_instrument?.ready()
|
||||
data["volume"] = volume
|
||||
data["volume_dropoff_threshold"] = sustain_dropoff_volume
|
||||
data["sustain_indefinitely"] = full_sustain_held_note
|
||||
data["playing"] = playing
|
||||
data["repeat"] = repeat
|
||||
data["bpm"] = round(60 SECONDS / tempo)
|
||||
data["lines"] = list()
|
||||
var/linecount
|
||||
for(var/line in lines)
|
||||
linecount++
|
||||
data["lines"] += list(list(
|
||||
"line_count" = linecount,
|
||||
"line_text" = line,
|
||||
))
|
||||
return data
|
||||
|
||||
/datum/song/ui_interact(mob/user)
|
||||
var/list/dat = list()
|
||||
/datum/song/ui_static_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["can_switch_instrument"] = (length(allowed_instrument_ids) > 1)
|
||||
data["possible_instruments"] = list()
|
||||
for(var/instrument in allowed_instrument_ids)
|
||||
UNTYPED_LIST_ADD(data["possible_instruments"], list("name" = SSinstruments.instrument_data[instrument], "id" = instrument))
|
||||
data["sustain_modes"] = SSinstruments.note_sustain_modes
|
||||
data["max_repeats"] = max_repeats
|
||||
data["min_volume"] = min_volume
|
||||
data["max_volume"] = max_volume
|
||||
data["note_shift_min"] = note_shift_min
|
||||
data["note_shift_max"] = note_shift_max
|
||||
data["max_line_chars"] = MUSIC_MAXLINECHARS
|
||||
data["max_lines"] = MUSIC_MAXLINES
|
||||
return data
|
||||
|
||||
dat += instrument_status_ui()
|
||||
/datum/song/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/mob/user = ui.user
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
|
||||
if(lines.len > 0)
|
||||
dat += "<H3>Playback</H3>"
|
||||
if(!playing)
|
||||
dat += "<A href='?src=[REF(src)];play=1'>Play</A> <span class='linkOn'>Stop</span><BR><BR>"
|
||||
dat += "Repeat Song: "
|
||||
dat += repeat > 0 ? "<A href='?src=[REF(src)];repeat=-10'>-</A><A href='?src=[REF(src)];repeat=-1'>-</A>" : "<span class='linkOff'>-</SPAN><SPAN CLASS='linkOff'>-</span>"
|
||||
dat += " [repeat] times "
|
||||
dat += repeat < max_repeats ? "<A href='?src=[REF(src)];repeat=1'>+</A><A href='?src=[REF(src)];repeat=10'>+</A>" : "<span class='linkOff'>+</SPAN><SPAN CLASS='linkOff'>+</span>"
|
||||
dat += "<BR>"
|
||||
else
|
||||
dat += "<span class='linkOn'>Play</span> <A href='?src=[REF(src)];stop=1'>Stop</A><BR>"
|
||||
dat += "Repeats left: <B>[repeat]</B><BR>"
|
||||
if(!editing)
|
||||
dat += "<BR><B><A href='?src=[REF(src)];edit=2'>Show Editor</A></B><BR>"
|
||||
else
|
||||
dat += "<H3>Editing</H3>"
|
||||
dat += "<B><A href='?src=[REF(src)];edit=1'>Hide Editor</A></B>"
|
||||
dat += " <A href='?src=[REF(src)];newsong=1'>Start a New Song</A>"
|
||||
dat += " <A href='?src=[REF(src)];import=1'>Import a Song</A><BR><BR>"
|
||||
var/bpm = round(600 / tempo)
|
||||
dat += "Tempo: <A href='?src=[REF(src)];tempo=[world.tick_lag]'>-</A> [bpm] BPM <A href='?src=[REF(src)];tempo=-[world.tick_lag]'>+</A><BR><BR>"
|
||||
var/linecount = 0
|
||||
for(var/line in lines)
|
||||
linecount += 1
|
||||
dat += "Line [linecount]: <A href='?src=[REF(src)];modifyline=[linecount]'>Edit</A> <A href='?src=[REF(src)];deleteline=[linecount]'>X</A> [line]<BR>"
|
||||
dat += "<A href='?src=[REF(src)];newline=1'>Add Line</A><BR><BR>"
|
||||
if(help)
|
||||
dat += "<B><A href='?src=[REF(src)];help=1'>Hide Help</A></B><BR>"
|
||||
dat += {"
|
||||
Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).<br>
|
||||
Every note in a chord will play together, with chord timed by the tempo.<br>
|
||||
<br>
|
||||
Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.<br>
|
||||
By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.<br>
|
||||
Example: <i>C,D,E,F,G,A,B</i> will play a C major scale.<br>
|
||||
After a note has an accidental placed, it will be remembered: <i>C,C4,C,C3</i> is <i>C3,C4,C4,C3</i><br>
|
||||
Chords can be played simply by seperating each note with a hyphon: <i>A-C#,Cn-E,E-G#,Gn-B</i><br>
|
||||
A pause may be denoted by an empty chord: <i>C,E,,C,G</i><br>
|
||||
To make a chord be a different time, end it with /x, where the chord length will be length<br>
|
||||
defined by tempo / x: <i>C,G/2,E/4</i><br>
|
||||
Combined, an example is: <i>E-E4/4,F#/2,G#/8,B/8,E3-E4/4</i>
|
||||
<br>
|
||||
Lines may be up to [MUSIC_MAXLINECHARS] characters.<br>
|
||||
A song may only contain up to [MUSIC_MAXLINES] lines.<br>
|
||||
"}
|
||||
else
|
||||
dat += "<B><A href='?src=[REF(src)];help=2'>Show Help</A></B><BR>"
|
||||
switch(action)
|
||||
//SETTINGS
|
||||
if("play_music")
|
||||
if(!playing)
|
||||
INVOKE_ASYNC(src, PROC_REF(start_playing), user)
|
||||
else
|
||||
stop_playing()
|
||||
return TRUE
|
||||
if("change_instrument")
|
||||
var/new_instrument = params["new_instrument"]
|
||||
//only one instrument, so no need to bother changing it.
|
||||
if(!length(allowed_instrument_ids))
|
||||
return FALSE
|
||||
if(!(new_instrument in allowed_instrument_ids))
|
||||
return FALSE
|
||||
set_instrument(new_instrument)
|
||||
return TRUE
|
||||
if("tempo")
|
||||
var/move_direction = params["tempo_change"]
|
||||
var/tempo_diff
|
||||
if(move_direction == "increase_speed")
|
||||
tempo_diff = world.tick_lag
|
||||
else
|
||||
tempo_diff = -world.tick_lag
|
||||
tempo = sanitize_tempo(tempo + tempo_diff)
|
||||
return TRUE
|
||||
|
||||
var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500)
|
||||
popup.set_content(dat.Join(""))
|
||||
popup.open()
|
||||
//SONG MAKING
|
||||
if("import_song")
|
||||
var/song_text = ""
|
||||
do
|
||||
song_text = tgui_input_text(user, "Please paste the entire song, formatted:", name, max_length = (MUSIC_MAXLINES * MUSIC_MAXLINECHARS))
|
||||
if(!in_range(parent, user))
|
||||
return
|
||||
if(length_char(song_text) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
var/should_continue = tgui_alert(user, "Your message is too long! Would you like to continue editing it?", "Warning", list("Yes", "No"))
|
||||
if(should_continue != "Yes")
|
||||
break
|
||||
while(length_char(song_text) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
ParseSong(user, song_text)
|
||||
return TRUE
|
||||
if("start_new_song")
|
||||
name = ""
|
||||
lines = new()
|
||||
tempo = sanitize_tempo(5) // default 120 BPM
|
||||
return TRUE
|
||||
if("add_new_line")
|
||||
var/newline = tgui_input_text(user, "Enter your line", parent.name)
|
||||
if(!newline || !in_range(parent, user))
|
||||
return
|
||||
if(lines.len > MUSIC_MAXLINES)
|
||||
return
|
||||
if(length(newline) > MUSIC_MAXLINECHARS)
|
||||
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
|
||||
lines.Add(newline)
|
||||
if("delete_line")
|
||||
var/line_to_delete = params["line_deleted"]
|
||||
if(line_to_delete > lines.len || line_to_delete < 1)
|
||||
return FALSE
|
||||
lines.Cut(line_to_delete, line_to_delete + 1)
|
||||
return TRUE
|
||||
if("modify_line")
|
||||
var/line_to_edit = params["line_editing"]
|
||||
if(line_to_edit > lines.len || line_to_edit < 1)
|
||||
return FALSE
|
||||
var/new_line_text = tgui_input_text(user, "Enter your line ", parent.name, lines[line_to_edit], MUSIC_MAXLINECHARS)
|
||||
if(isnull(new_line_text) || !in_range(parent, user))
|
||||
return FALSE
|
||||
lines[line_to_edit] = new_line_text
|
||||
return TRUE
|
||||
|
||||
//MODE STUFF
|
||||
if("set_sustain_mode")
|
||||
var/new_mode = params["new_mode"]
|
||||
if(isnull(new_mode) || !(new_mode in SSinstruments.note_sustain_modes))
|
||||
return FALSE
|
||||
sustain_mode = new_mode
|
||||
return TRUE
|
||||
if("set_note_shift")
|
||||
var/amount = params["amount"]
|
||||
if(!isnum(amount))
|
||||
return FALSE
|
||||
note_shift = clamp(amount, note_shift_min, note_shift_max)
|
||||
return TRUE
|
||||
if("set_volume")
|
||||
var/new_volume = params["amount"]
|
||||
if(!isnum(new_volume))
|
||||
return FALSE
|
||||
set_volume(new_volume)
|
||||
return TRUE
|
||||
if("set_dropoff_volume")
|
||||
var/dropoff_threshold = params["amount"]
|
||||
if(!isnum(dropoff_threshold))
|
||||
return FALSE
|
||||
set_dropoff_volume(dropoff_threshold)
|
||||
return TRUE
|
||||
if("toggle_sustain_hold_indefinitely")
|
||||
full_sustain_held_note = !full_sustain_held_note
|
||||
return TRUE
|
||||
if("set_repeat_amount")
|
||||
if(playing)
|
||||
return
|
||||
var/repeat_amount = params["amount"]
|
||||
if(!isnum(repeat_amount))
|
||||
return FALSE
|
||||
set_repeats(repeat_amount)
|
||||
return TRUE
|
||||
if("edit_sustain_mode")
|
||||
var/sustain_amount = params["amount"]
|
||||
if(isnull(sustain_amount) || !isnum(sustain_amount))
|
||||
return
|
||||
switch(sustain_mode)
|
||||
if(SUSTAIN_LINEAR)
|
||||
set_linear_falloff_duration(sustain_amount)
|
||||
if(SUSTAIN_EXPONENTIAL)
|
||||
set_exponential_drop_rate(sustain_amount)
|
||||
|
||||
/**
|
||||
* Parses a song the user has input into lines and stores them.
|
||||
*/
|
||||
/datum/song/proc/ParseSong(new_song)
|
||||
/datum/song/proc/ParseSong(mob/user, new_song)
|
||||
set waitfor = FALSE
|
||||
//split into lines
|
||||
lines = islist(new_song) ? new_song : splittext(new_song, "\n")
|
||||
@@ -103,142 +196,14 @@
|
||||
else
|
||||
tempo = sanitize_tempo(5) // default 120 BPM
|
||||
if(lines.len > MUSIC_MAXLINES)
|
||||
to_chat(usr, "Too many lines!")
|
||||
if(user)
|
||||
to_chat(user, "Too many lines!")
|
||||
lines.Cut(MUSIC_MAXLINES + 1)
|
||||
var/linenum = 1
|
||||
for(var/l in lines)
|
||||
if(length_char(l) > MUSIC_MAXLINECHARS)
|
||||
to_chat(usr, "Line [linenum] too long!")
|
||||
if(user)
|
||||
to_chat(user, "Line [linenum] too long!")
|
||||
lines.Remove(l)
|
||||
else
|
||||
linenum++
|
||||
updateDialog(usr) // make sure updates when complete
|
||||
|
||||
/datum/song/Topic(href, href_list)
|
||||
if(!usr.can_perform_action(parent, ALLOW_RESTING))
|
||||
usr << browse(null, "window=instrument")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
parent.add_fingerprint(usr)
|
||||
|
||||
if(href_list["newsong"])
|
||||
lines = new()
|
||||
tempo = sanitize_tempo(5) // default 120 BPM
|
||||
name = ""
|
||||
|
||||
else if(href_list["import"])
|
||||
var/t = ""
|
||||
do
|
||||
t = html_encode(input(usr, "Please paste the entire song, formatted:", name, t) as message)
|
||||
if(!in_range(parent, usr))
|
||||
return
|
||||
|
||||
if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
var/cont = tgui_alert(usr, "Your message is too long! Would you like to continue editing it?", "Warning", list("Yes", "No"))
|
||||
if(cont != "Yes")
|
||||
break
|
||||
while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
ParseSong(t)
|
||||
|
||||
else if(href_list["help"])
|
||||
help = text2num(href_list["help"]) - 1
|
||||
|
||||
else if(href_list["edit"])
|
||||
editing = text2num(href_list["edit"]) - 1
|
||||
|
||||
if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops.
|
||||
set_repeats(repeat + text2num(href_list["repeat"]))
|
||||
|
||||
else if(href_list["tempo"])
|
||||
tempo = sanitize_tempo(tempo + text2num(href_list["tempo"]))
|
||||
|
||||
else if(href_list["play"])
|
||||
INVOKE_ASYNC(src, PROC_REF(start_playing), usr)
|
||||
|
||||
else if(href_list["newline"])
|
||||
var/newline = tgui_input_text(usr, "Enter your line ", parent.name)
|
||||
if(!newline || !in_range(parent, usr))
|
||||
return
|
||||
if(lines.len > MUSIC_MAXLINES)
|
||||
return
|
||||
if(length(newline) > MUSIC_MAXLINECHARS)
|
||||
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
|
||||
lines.Add(newline)
|
||||
|
||||
else if(href_list["deleteline"])
|
||||
var/num = round(text2num(href_list["deleteline"]))
|
||||
if(num > lines.len || num < 1)
|
||||
return
|
||||
lines.Cut(num, num+1)
|
||||
|
||||
else if(href_list["modifyline"])
|
||||
var/num = round(text2num(href_list["modifyline"]),1)
|
||||
var/content = tgui_input_text(usr, "Enter your line ", parent.name, lines[num], MUSIC_MAXLINECHARS)
|
||||
if(!content || !in_range(parent, usr))
|
||||
return
|
||||
if(num > lines.len || num < 1)
|
||||
return
|
||||
lines[num] = content
|
||||
|
||||
else if(href_list["stop"])
|
||||
stop_playing()
|
||||
|
||||
else if(href_list["setlinearfalloff"])
|
||||
var/amount = tgui_input_number(usr, "Set linear sustain duration in seconds", "Linear Sustain Duration", 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN, 0.1, round_value = FALSE)
|
||||
if(!isnull(amount))
|
||||
set_linear_falloff_duration(amount)
|
||||
|
||||
else if(href_list["setexpfalloff"])
|
||||
var/amount = tgui_input_number(usr, "Set exponential sustain factor", "Exponential sustain factor", INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX, INSTRUMENT_EXP_FALLOFF_MIN, round_value = FALSE)
|
||||
if(!isnull(amount))
|
||||
set_exponential_drop_rate(amount)
|
||||
|
||||
else if(href_list["setvolume"])
|
||||
var/amount = tgui_input_number(usr, "Set volume", "Volume", 1, 75, 1)
|
||||
if(!isnull(amount))
|
||||
set_volume(amount)
|
||||
|
||||
else if(href_list["setdropoffvolume"])
|
||||
var/amount = tgui_input_number(usr, "Set dropoff threshold", "Dropoff Volume", max_value = 100)
|
||||
if(!isnull(amount))
|
||||
set_dropoff_volume(amount)
|
||||
|
||||
else if(href_list["switchinstrument"])
|
||||
if(!length(allowed_instrument_ids))
|
||||
return
|
||||
else if(length(allowed_instrument_ids) == 1)
|
||||
set_instrument(allowed_instrument_ids[1])
|
||||
return
|
||||
var/list/categories = list()
|
||||
for(var/i in allowed_instrument_ids)
|
||||
var/datum/instrument/I = SSinstruments.get_instrument(i)
|
||||
if(I)
|
||||
LAZYSET(categories[I.category || "ERROR CATEGORY"], I.name, I.id)
|
||||
var/cat = tgui_input_list(usr, "Select Category", "Instrument Category", categories)
|
||||
if(isnull(cat))
|
||||
return
|
||||
var/list/instruments = categories[cat]
|
||||
var/choice = tgui_input_list(usr, "Select Instrument", "Instrument Selection", instruments)
|
||||
if(isnull(choice))
|
||||
return
|
||||
if(isnull(instruments[choice]))
|
||||
return
|
||||
choice = instruments[choice] //get id
|
||||
if(choice)
|
||||
set_instrument(choice)
|
||||
|
||||
else if(href_list["setnoteshift"])
|
||||
var/amount = input(usr, "Set note shift", "Note Shift") as null|num
|
||||
if(!isnull(amount))
|
||||
note_shift = clamp(amount, note_shift_min, note_shift_max)
|
||||
|
||||
else if(href_list["setsustainmode"])
|
||||
var/choice = tgui_input_list(usr, "Choose a sustain mode", "Sustain Mode", SSinstruments.note_sustain_modes)
|
||||
if(choice)
|
||||
sustain_mode = SSinstruments.note_sustain_modes[choice]
|
||||
|
||||
else if(href_list["togglesustainhold"])
|
||||
full_sustain_held_note = !full_sustain_held_note
|
||||
|
||||
updateDialog(usr)
|
||||
|
||||
@@ -43,8 +43,7 @@
|
||||
* Does a hearing check if enough time has passed.
|
||||
*/
|
||||
/datum/song/proc/playkey_synth(key, atom/player)
|
||||
if(can_noteshift)
|
||||
key = clamp(key + note_shift, key_min, key_max)
|
||||
key = clamp(key + note_shift, key_min, key_max)
|
||||
if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck)
|
||||
do_hearcheck()
|
||||
var/datum/instrument_key/K = using_instrument.samples[num2text(key)] //See how fucking easy it is to make a number text? You don't need a complicated 9 line proc!
|
||||
|
||||
Reference in New Issue
Block a user