144 lines
3.6 KiB
Go
144 lines
3.6 KiB
Go
package sounds
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/inkyblackness/imgui-go/v3"
|
|
|
|
"github.com/inkyblackness/hacked/editor/external"
|
|
"github.com/inkyblackness/hacked/ss1/content/audio"
|
|
"github.com/inkyblackness/hacked/ss1/edit/undoable"
|
|
"github.com/inkyblackness/hacked/ss1/world/ids"
|
|
"github.com/inkyblackness/hacked/ui/gui"
|
|
)
|
|
|
|
// View provides edit controls for sound effects.
|
|
type View struct {
|
|
soundEffectService undoable.SoundEffectService
|
|
|
|
modalStateMachine gui.ModalStateMachine
|
|
guiScale float32
|
|
|
|
model viewModel
|
|
}
|
|
|
|
// NewSoundEffectsView returns a new instance.
|
|
func NewSoundEffectsView(soundEffectService undoable.SoundEffectService,
|
|
modalStateMachine gui.ModalStateMachine,
|
|
guiScale float32) *View {
|
|
view := &View{
|
|
soundEffectService: soundEffectService,
|
|
|
|
modalStateMachine: modalStateMachine,
|
|
guiScale: guiScale,
|
|
|
|
model: freshViewModel(),
|
|
}
|
|
return view
|
|
}
|
|
|
|
// WindowOpen returns the flag address, to be used with the main menu.
|
|
func (view *View) WindowOpen() *bool {
|
|
return &view.model.windowOpen
|
|
}
|
|
|
|
// Render renders the view.
|
|
func (view *View) Render() {
|
|
if view.model.restoreFocus {
|
|
imgui.SetNextWindowFocus()
|
|
view.model.restoreFocus = false
|
|
view.model.windowOpen = true
|
|
}
|
|
if view.model.windowOpen {
|
|
imgui.SetNextWindowSizeV(imgui.Vec2{X: 400 * view.guiScale, Y: 300 * view.guiScale}, imgui.ConditionFirstUseEver)
|
|
if imgui.BeginV("Sound Effects", view.WindowOpen(), imgui.WindowFlagsNoCollapse) {
|
|
view.renderContent()
|
|
}
|
|
imgui.End()
|
|
}
|
|
}
|
|
|
|
func (view *View) renderContent() {
|
|
info, _ := ids.Info(view.model.currentKey.ID)
|
|
|
|
imgui.BeginChildV("SoundEffects", imgui.Vec2{X: -1, Y: -60 * view.guiScale}, true, 0)
|
|
for i := 0; i < info.MaxCount; i++ {
|
|
effects := ids.SoundEffectsForAudio(i)
|
|
text := fmt.Sprintf("%3d", i)
|
|
if len(effects) > 0 {
|
|
text += " - "
|
|
for effectIndex, effect := range effects {
|
|
if effectIndex > 0 {
|
|
text += ", "
|
|
}
|
|
text += effect.Name
|
|
}
|
|
} else {
|
|
text += " (unidentified)"
|
|
}
|
|
if imgui.SelectableV(text, view.model.currentKey.Index == i, 0, imgui.Vec2{}) {
|
|
view.model.currentKey.Index = i
|
|
}
|
|
}
|
|
imgui.EndChild()
|
|
|
|
imgui.PushItemWidth(-100 * view.guiScale)
|
|
sound := view.currentSound()
|
|
if !sound.Empty() {
|
|
imgui.LabelText("Audio", fmt.Sprintf("%.2f sec", sound.Duration()))
|
|
if imgui.Button("Export") {
|
|
view.requestExportAudio(sound)
|
|
}
|
|
imgui.SameLine()
|
|
} else {
|
|
imgui.LabelText("Audio", "(no sound)")
|
|
}
|
|
if imgui.Button("Import") {
|
|
view.requestImportAudio()
|
|
}
|
|
imgui.PopItemWidth()
|
|
imgui.SameLine()
|
|
if imgui.Button("Clear") {
|
|
view.clearAudio()
|
|
}
|
|
if view.soundEffectService.Modified(view.model.currentKey) {
|
|
imgui.SameLine()
|
|
if imgui.Button("Remove") {
|
|
view.removeAudio()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (view *View) clearAudio() {
|
|
view.soundEffectService.RequestClear(view.model.currentKey, view.restoreFunc())
|
|
}
|
|
|
|
func (view *View) removeAudio() {
|
|
view.soundEffectService.RequestRemove(view.model.currentKey, view.restoreFunc())
|
|
}
|
|
|
|
func (view *View) currentSound() (sound audio.L8) {
|
|
return view.soundEffectService.Audio(view.model.currentKey)
|
|
}
|
|
|
|
func (view *View) requestExportAudio(sound audio.L8) {
|
|
filename := fmt.Sprintf("sfx_%03d.wav", view.model.currentKey.Index)
|
|
|
|
external.ExportAudio(view.modalStateMachine, filename, sound)
|
|
}
|
|
|
|
func (view *View) requestImportAudio() {
|
|
external.ImportAudio(view.modalStateMachine, func(sound audio.L8) {
|
|
view.soundEffectService.RequestSetAudio(view.model.currentKey, sound, view.restoreFunc())
|
|
})
|
|
}
|
|
|
|
func (view *View) restoreFunc() func() {
|
|
oldKey := view.model.currentKey
|
|
|
|
return func() {
|
|
view.model.restoreFocus = true
|
|
view.model.currentKey = oldKey
|
|
}
|
|
}
|