Adding modding folder with a hacked build.

This commit is contained in:
ml
2026-09-26 08:53:08 +02:00
parent cdb960dc71
commit c91080aba7
755 changed files with 50424 additions and 0 deletions
+246
View File
@@ -0,0 +1,246 @@
package project
import (
"fmt"
"github.com/inkyblackness/imgui-go/v3"
"github.com/inkyblackness/hacked/ss1/edit"
"github.com/inkyblackness/hacked/ss1/edit/undoable/cmd"
"github.com/inkyblackness/hacked/ss1/world"
"github.com/inkyblackness/hacked/ui/gui"
)
// View handles the project display.
type View struct {
service *edit.ProjectService
modalStateMachine gui.ModalStateMachine
guiScale float32
commander cmd.Registry
model viewModel
}
// NewView creates a new instance for the project display.
func NewView(service *edit.ProjectService, modalStateMachine gui.ModalStateMachine, guiScale float32, commander cmd.Registry) *View {
return &View{
service: service,
modalStateMachine: modalStateMachine,
guiScale: guiScale,
commander: commander,
model: freshViewModel(),
}
}
// WindowOpen returns the flag address, to be used with the main menu.
func (view *View) WindowOpen() *bool {
return &view.model.windowOpen
}
// Render requests to render the view.
func (view *View) Render() {
if view.model.restoreFocus {
imgui.SetNextWindowFocus()
view.model.restoreFocus = false
view.model.windowOpen = true
}
title := "Project"
saveStatus := view.service.SaveStatus()
if saveStatus.FilesModified > 0 {
title += fmt.Sprintf(" - %d file(s) pending save", saveStatus.FilesModified)
if saveStatus.SavePending && (saveStatus.SaveIn.Seconds() < 4) {
title += fmt.Sprintf(" - auto-save in %d", int(saveStatus.SaveIn.Seconds()))
}
}
if view.model.windowOpen {
imgui.SetNextWindowSizeV(imgui.Vec2{X: 400 * view.guiScale, Y: 300 * view.guiScale}, imgui.ConditionFirstUseEver)
if imgui.BeginV(title+"###Project", view.WindowOpen(), 0) {
view.renderContent()
}
imgui.End()
}
}
func (view *View) renderContent() {
imgui.Text("Mod Location")
imgui.PushStyleVarVec2(imgui.StyleVarWindowPadding, imgui.Vec2{X: 1, Y: 0})
imgui.BeginChildV("ModLocation", imgui.Vec2{X: -200*view.guiScale - 10*view.guiScale, Y: imgui.TextLineHeight() * 1.5}, true,
imgui.WindowFlagsNoScrollbar|imgui.WindowFlagsNoScrollWithMouse)
modPath := view.service.ModPath()
if len(modPath) > 0 {
imgui.Text(modPath)
} else {
imgui.PushStyleColor(imgui.StyleColorText, imgui.Vec4{X: 1.0, Y: 1.0, Z: 1.0, W: 0.5})
imgui.Text("(new mod)")
imgui.PopStyleColor()
}
imgui.EndChild()
imgui.PopStyleVar()
imgui.BeginGroup()
imgui.SameLine()
if imgui.ButtonV("Save", imgui.Vec2{X: 100 * view.guiScale, Y: 0}) {
view.StartSavingMod()
}
imgui.SameLine()
if imgui.ButtonV("Load...", imgui.Vec2{X: 100 * view.guiScale, Y: 0}) {
view.startLoadingMod()
}
imgui.EndGroup()
imgui.Text("Static World Data")
imgui.BeginChildV("ManifestEntries", imgui.Vec2{X: -100 * view.guiScale, Y: 0}, true, 0)
manifest := view.service.Mod().World()
entries := manifest.EntryCount()
for i := entries - 1; i >= 0; i-- {
entry, _ := manifest.Entry(i)
if imgui.SelectableV(entry.ID, view.model.selectedManifestEntry == i, 0, imgui.Vec2{}) {
view.model.selectedManifestEntry = i
}
}
imgui.EndChild()
imgui.SameLine()
imgui.BeginGroup()
if imgui.ButtonV("Add...", imgui.Vec2{X: -1, Y: 0}) {
view.startAddingManifestEntry()
}
if imgui.ButtonV("Up", imgui.Vec2{X: -1, Y: 0}) {
view.requestMoveManifestEntryUp()
}
if imgui.ButtonV("Down", imgui.Vec2{X: -1, Y: 0}) {
view.requestMoveManifestEntryDown()
}
if imgui.ButtonV("Remove", imgui.Vec2{X: -1, Y: 0}) {
view.requestRemoveManifestEntry()
}
imgui.EndGroup()
}
func (view *View) startLoadingMod() {
view.modalStateMachine.SetState(&loadModStartState{
machine: view.modalStateMachine,
view: view,
})
}
// StartSavingMod initiates to save the mod.
// It either opens the save-as dialog, or simply saves under the current folder.
func (view *View) StartSavingMod() {
if view.service.ModHasStorageLocation() {
err := view.service.SaveMod()
if err != nil {
view.handleSaveModFailure(err)
}
} else {
view.modalStateMachine.SetState(&saveModAsStartState{
machine: view.modalStateMachine,
view: view,
})
}
}
func (view *View) startAddingManifestEntry() {
view.modalStateMachine.SetState(&addManifestEntryStartState{
machine: view.modalStateMachine,
view: view,
})
}
func (view *View) requestMoveManifestEntryUp() {
manifest := view.service.Mod().World()
entries := manifest.EntryCount()
if (view.model.selectedManifestEntry >= 0) && (view.model.selectedManifestEntry < (entries - 1)) {
view.requestMoveManifestEntry(view.model.selectedManifestEntry+1, view.model.selectedManifestEntry)
}
}
func (view *View) requestMoveManifestEntryDown() {
if view.model.selectedManifestEntry > 0 {
view.requestMoveManifestEntry(view.model.selectedManifestEntry-1, view.model.selectedManifestEntry)
}
}
func (view *View) requestMoveManifestEntry(to, from int) {
_ = view.commander.Register(
cmd.Named("moveManifestEntry"),
cmd.Reverse(view.taskToRestoreFocus()),
cmd.Reverse(view.taskToSelectEntry(from)),
cmd.Nested(func() error { return view.service.MoveManifestEntry(to, from) }),
cmd.Forward(view.taskToSelectEntry(to)),
cmd.Forward(view.taskToRestoreFocus()),
)
}
func (view *View) tryAddManifestEntryFrom(names []string) error {
entry, err := world.NewManifestEntryFrom(names)
if err != nil {
return err
}
view.requestAddManifestEntry(entry)
return nil
}
func (view *View) requestAddManifestEntry(entry *world.ManifestEntry) {
at := view.model.selectedManifestEntry + 1
_ = view.commander.Register(
cmd.Named("addManifestEntry"),
cmd.Reverse(view.taskToRestoreFocus()),
cmd.Reverse(view.taskToSelectEntry(view.model.selectedManifestEntry)),
cmd.Nested(func() error { return view.service.AddManifestEntry(at, entry) }),
cmd.Forward(view.taskToSelectEntry(at)),
cmd.Forward(view.taskToRestoreFocus()),
)
}
func (view *View) requestRemoveManifestEntry() {
manifest := view.service.Mod().World()
at := view.model.selectedManifestEntry
if (at < 0) || (at >= manifest.EntryCount()) {
return
}
_ = view.commander.Register(
cmd.Named("removeManifestEntry"),
cmd.Reverse(view.taskToRestoreFocus()),
cmd.Reverse(view.taskToSelectEntry(view.model.selectedManifestEntry)),
cmd.Nested(func() error { return view.service.RemoveManifestEntry(at) }),
cmd.Forward(view.taskToSelectEntry(view.model.selectedManifestEntry-1)),
cmd.Forward(view.taskToRestoreFocus()),
)
}
func (view *View) tryLoadModFrom(names []string) error {
return view.service.TryLoadModFrom(names)
}
func (view *View) requestSaveMod(modPath string) {
err := view.service.SaveModUnder(modPath)
if err != nil {
view.handleSaveModFailure(err)
}
}
func (view *View) handleSaveModFailure(err error) {
view.modalStateMachine.SetState(&saveModFailedState{
machine: view.modalStateMachine,
view: view,
errorInfo: err.Error(),
})
}
func (view *View) taskToRestoreFocus() cmd.Task {
return func(modder world.Modder) error {
view.model.restoreFocus = true
return nil
}
}
func (view *View) taskToSelectEntry(index int) cmd.Task {
return func(modder world.Modder) error {
view.model.selectedManifestEntry = index
return nil
}
}