mirror of
https://github.com/libretro/ludo.git
synced 2026-11-07 04:05:58 -10:00
Remove some non-sense (#417)
* Remove some non-sense * audio * video * Fix comments * More fixes * Lint * Add new non-sense
This commit is contained in:
1 parent
d201e5321d
commit
b83eff4369
34 files changed
+373
-485
No files matched your search
+30
-30
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
const bufSize = 1024 * 8
|
||||
|
||||
var audio struct {
|
||||
var (
|
||||
source al.Source
|
||||
buffers []al.Buffer
|
||||
rate int32
|
||||
@@ -24,14 +24,14 @@ var audio struct {
|
||||
tmpBuf [bufSize]byte
|
||||
tmpBufPtr int32
|
||||
resPtr int32
|
||||
}
|
||||
)
|
||||
|
||||
// Effects are sound effects
|
||||
var Effects map[string]*Effect
|
||||
|
||||
// SetVolume sets the audio volume
|
||||
func SetVolume(vol float32) {
|
||||
audio.source.SetGain(vol)
|
||||
source.SetGain(vol)
|
||||
}
|
||||
|
||||
// Init initializes the audio device
|
||||
@@ -54,19 +54,19 @@ func Init() {
|
||||
|
||||
// Reconfigure initializes the audio package. It sets the number of buffers, the
|
||||
// volume and the source for the games.
|
||||
func Reconfigure(rate int32) {
|
||||
audio.rate = rate
|
||||
audio.numBuffers = 4
|
||||
func Reconfigure(r int32) {
|
||||
rate = r
|
||||
numBuffers = 4
|
||||
|
||||
log.Printf("[OpenAL]: Using %v buffers of %v bytes.\n", audio.numBuffers, bufSize)
|
||||
log.Printf("[OpenAL]: Using %v buffers of %v bytes.\n", numBuffers, bufSize)
|
||||
|
||||
audio.source = al.GenSources(1)[0]
|
||||
audio.buffers = al.GenBuffers(int(audio.numBuffers))
|
||||
audio.resPtr = audio.numBuffers
|
||||
audio.tmpBufPtr = 0
|
||||
audio.tmpBuf = [bufSize]byte{}
|
||||
source = al.GenSources(1)[0]
|
||||
buffers = al.GenBuffers(int(numBuffers))
|
||||
resPtr = numBuffers
|
||||
tmpBufPtr = 0
|
||||
tmpBuf = [bufSize]byte{}
|
||||
|
||||
audio.source.SetGain(settings.Current.AudioVolume)
|
||||
source.SetGain(settings.Current.AudioVolume)
|
||||
}
|
||||
|
||||
func min(a, b int32) int32 {
|
||||
@@ -77,19 +77,19 @@ func min(a, b int32) int32 {
|
||||
}
|
||||
|
||||
func alUnqueueBuffers() bool {
|
||||
val := audio.source.BuffersProcessed()
|
||||
val := source.BuffersProcessed()
|
||||
|
||||
if val <= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
audio.source.UnqueueBuffers(audio.buffers[audio.resPtr:val]...)
|
||||
audio.resPtr += val
|
||||
source.UnqueueBuffers(buffers[resPtr:val]...)
|
||||
resPtr += val
|
||||
return true
|
||||
}
|
||||
|
||||
func alGetBuffer() al.Buffer {
|
||||
if audio.resPtr == 0 {
|
||||
if resPtr == 0 {
|
||||
for {
|
||||
if alUnqueueBuffers() {
|
||||
break
|
||||
@@ -98,21 +98,21 @@ func alGetBuffer() al.Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
audio.resPtr--
|
||||
return audio.buffers[audio.resPtr]
|
||||
resPtr--
|
||||
return buffers[resPtr]
|
||||
}
|
||||
|
||||
func fillInternalBuf(buf []byte) int32 {
|
||||
readSize := min(bufSize-audio.tmpBufPtr, int32(len(buf)))
|
||||
copy(audio.tmpBuf[audio.tmpBufPtr:], buf[:readSize])
|
||||
audio.tmpBufPtr += readSize
|
||||
readSize := min(bufSize-tmpBufPtr, int32(len(buf)))
|
||||
copy(tmpBuf[tmpBufPtr:], buf[:readSize])
|
||||
tmpBufPtr += readSize
|
||||
return readSize
|
||||
}
|
||||
|
||||
func write(buf []byte, size int32) int32 {
|
||||
written := int32(0)
|
||||
|
||||
if state.Global.FastForward {
|
||||
if state.FastForward {
|
||||
return size
|
||||
}
|
||||
|
||||
@@ -123,18 +123,18 @@ func write(buf []byte, size int32) int32 {
|
||||
written += rc
|
||||
size -= rc
|
||||
|
||||
if audio.tmpBufPtr != bufSize {
|
||||
if tmpBufPtr != bufSize {
|
||||
break
|
||||
}
|
||||
|
||||
buffer := alGetBuffer()
|
||||
|
||||
buffer.BufferData(al.FormatStereo16, audio.tmpBuf[:], audio.rate)
|
||||
audio.tmpBufPtr = 0
|
||||
audio.source.QueueBuffers(buffer)
|
||||
buffer.BufferData(al.FormatStereo16, tmpBuf[:], rate)
|
||||
tmpBufPtr = 0
|
||||
source.QueueBuffers(buffer)
|
||||
|
||||
if audio.source.State() != al.Playing {
|
||||
al.PlaySources(audio.source)
|
||||
if source.State() != al.Playing {
|
||||
al.PlaySources(source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func write(buf []byte, size int32) int32 {
|
||||
// It is passed as a callback to the libretro implementation.
|
||||
func Sample(left int16, right int16) {
|
||||
// simulate the kind of raw byte array that would be provided from C via SampleBatch.
|
||||
// (effectively typecasting int16 array to byte array)
|
||||
// (effectively typecasting int16 array to byte array)
|
||||
buf := []int16{left, right}
|
||||
pi := (*[4]byte)(unsafe.Pointer(&buf[0]))
|
||||
write((*pi)[:], 4)
|
||||
|
||||
+36
-56
@@ -11,7 +11,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/libretro/ludo/audio"
|
||||
"github.com/libretro/ludo/input"
|
||||
@@ -32,17 +31,6 @@ var Options *options.Options
|
||||
// Call Init before calling other functions of this package.
|
||||
func Init(v *video.Video) {
|
||||
vid = v
|
||||
ticker := time.NewTicker(time.Second * 10)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
state.Global.Lock()
|
||||
canSave := state.Global.CoreRunning && !state.Global.MenuActive
|
||||
state.Global.Unlock()
|
||||
if canSave {
|
||||
savefiles.SaveSRAM()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Load loads a libretro core
|
||||
@@ -52,28 +40,26 @@ func Load(sofile string) error {
|
||||
Unload()
|
||||
|
||||
// This must be set before the environment callback is called
|
||||
state.Global.CorePath = sofile
|
||||
state.CorePath = sofile
|
||||
|
||||
var err error
|
||||
state.Global.Core, err = libretro.Load(sofile)
|
||||
state.Core, err = libretro.Load(sofile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
state.Global.Core.SetEnvironment(environment)
|
||||
state.Global.Core.Init()
|
||||
state.Global.Core.SetVideoRefresh(vid.Refresh)
|
||||
state.Global.Core.SetInputPoll(input.Poll)
|
||||
state.Global.Core.SetInputState(input.State)
|
||||
state.Global.Core.SetAudioSample(audio.Sample)
|
||||
state.Global.Core.SetAudioSampleBatch(audio.SampleBatch)
|
||||
state.Core.SetEnvironment(environment)
|
||||
state.Core.Init()
|
||||
state.Core.SetVideoRefresh(vid.Refresh)
|
||||
state.Core.SetInputPoll(input.Poll)
|
||||
state.Core.SetInputState(input.State)
|
||||
state.Core.SetAudioSample(audio.Sample)
|
||||
state.Core.SetAudioSampleBatch(audio.SampleBatch)
|
||||
|
||||
// Append the library name to the window title.
|
||||
si := state.Global.Core.GetSystemInfo()
|
||||
si := state.Core.GetSystemInfo()
|
||||
if len(si.LibraryName) > 0 {
|
||||
if vid.Window != nil {
|
||||
vid.Window.SetTitle("Ludo - " + si.LibraryName)
|
||||
}
|
||||
if state.Global.Verbose {
|
||||
vid.SetTitle("Ludo - " + si.LibraryName)
|
||||
if state.Verbose {
|
||||
log.Println("[Core]: Name:", si.LibraryName)
|
||||
log.Println("[Core]: Version:", si.LibraryVersion)
|
||||
log.Println("[Core]: Valid extensions:", si.ValidExtensions)
|
||||
@@ -143,11 +129,11 @@ func LoadGame(gamePath string) error {
|
||||
|
||||
// If we're loading a new game on the same core, save the RAM of the previous
|
||||
// game before closing it.
|
||||
if state.Global.GamePath != gamePath {
|
||||
if state.GamePath != gamePath {
|
||||
UnloadGame()
|
||||
}
|
||||
|
||||
si := state.Global.Core.GetSystemInfo()
|
||||
si := state.Core.GetSystemInfo()
|
||||
|
||||
gi, err := getGameInfo(gamePath, si.BlockExtract)
|
||||
if err != nil {
|
||||
@@ -168,38 +154,36 @@ func LoadGame(gamePath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
ok := state.Global.Core.LoadGame(*gi)
|
||||
ok := state.Core.LoadGame(*gi)
|
||||
if !ok {
|
||||
state.Global.CoreRunning = false
|
||||
state.CoreRunning = false
|
||||
return errors.New("failed to load the game")
|
||||
}
|
||||
|
||||
avi := state.Global.Core.GetSystemAVInfo()
|
||||
avi := state.Core.GetSystemAVInfo()
|
||||
|
||||
vid.Geom = avi.Geometry
|
||||
|
||||
// Append the library name to the window title.
|
||||
if len(si.LibraryName) > 0 {
|
||||
vid.Window.SetTitle("Ludo - " + si.LibraryName)
|
||||
vid.SetTitle("Ludo - " + si.LibraryName)
|
||||
}
|
||||
|
||||
input.Init(vid)
|
||||
audio.Reconfigure(int32(avi.Timing.SampleRate))
|
||||
if state.Global.Core.AudioCallback != nil {
|
||||
state.Global.Core.AudioCallback.SetState(true)
|
||||
if state.Core.AudioCallback != nil {
|
||||
state.Core.AudioCallback.SetState(true)
|
||||
}
|
||||
|
||||
state.Global.Lock()
|
||||
state.Global.CoreRunning = true
|
||||
state.Global.FastForward = false
|
||||
state.Global.GamePath = gamePath
|
||||
state.Global.Unlock()
|
||||
state.CoreRunning = true
|
||||
state.FastForward = false
|
||||
state.GamePath = gamePath
|
||||
|
||||
state.Global.Core.SetControllerPortDevice(0, libretro.DeviceJoypad)
|
||||
state.Global.Core.SetControllerPortDevice(1, libretro.DeviceJoypad)
|
||||
state.Global.Core.SetControllerPortDevice(2, libretro.DeviceJoypad)
|
||||
state.Global.Core.SetControllerPortDevice(3, libretro.DeviceJoypad)
|
||||
state.Global.Core.SetControllerPortDevice(4, libretro.DeviceJoypad)
|
||||
state.Core.SetControllerPortDevice(0, libretro.DeviceJoypad)
|
||||
state.Core.SetControllerPortDevice(1, libretro.DeviceJoypad)
|
||||
state.Core.SetControllerPortDevice(2, libretro.DeviceJoypad)
|
||||
state.Core.SetControllerPortDevice(3, libretro.DeviceJoypad)
|
||||
state.Core.SetControllerPortDevice(4, libretro.DeviceJoypad)
|
||||
|
||||
log.Println("[Core]: Game loaded: " + gamePath)
|
||||
savefiles.LoadSRAM()
|
||||
@@ -209,26 +193,22 @@ func LoadGame(gamePath string) error {
|
||||
|
||||
// Unload unloads a libretro core
|
||||
func Unload() {
|
||||
if state.Global.Core != nil {
|
||||
if state.Core != nil {
|
||||
UnloadGame()
|
||||
state.Global.Core.Deinit()
|
||||
state.Global.Lock()
|
||||
state.Global.CorePath = ""
|
||||
state.Global.Core = nil
|
||||
state.Core.Deinit()
|
||||
state.CorePath = ""
|
||||
state.Core = nil
|
||||
Options = nil
|
||||
state.Global.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// UnloadGame unloads a game.
|
||||
func UnloadGame() {
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
savefiles.SaveSRAM()
|
||||
state.Global.Core.UnloadGame()
|
||||
state.Global.Lock()
|
||||
state.Global.GamePath = ""
|
||||
state.Global.CoreRunning = false
|
||||
state.Global.Unlock()
|
||||
state.Core.UnloadGame()
|
||||
state.GamePath = ""
|
||||
state.CoreRunning = false
|
||||
vid.ResetPitch()
|
||||
vid.ResetRot()
|
||||
}
|
||||
|
||||
+22
-22
@@ -29,17 +29,17 @@ func (m WindowMock) SetTitle(string) {}
|
||||
func (m WindowMock) SwapBuffers() {}
|
||||
|
||||
func Test_coreLoad(t *testing.T) {
|
||||
state.Global.Verbose = true
|
||||
state.Verbose = true
|
||||
|
||||
ext := utils.CoreExt()
|
||||
|
||||
Init(&video.Video{Window: &WindowMock{}})
|
||||
Init(&video.Video{})
|
||||
|
||||
out := utils.CaptureOutput(func() { Load("testdata/vecx_libretro" + ext) })
|
||||
|
||||
t.Run("The core is loaded", func(t *testing.T) {
|
||||
if state.Global.Core == nil {
|
||||
t.Errorf("got = %v, want not nil", state.Global.Core)
|
||||
if state.Core == nil {
|
||||
t.Errorf("got = %v, want not nil", state.Core)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -56,10 +56,10 @@ func Test_coreLoad(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
state.Global.Core.UnloadGame()
|
||||
state.Global.Core.Deinit()
|
||||
state.Global.GamePath = ""
|
||||
state.Global.Verbose = false
|
||||
state.Core.UnloadGame()
|
||||
state.Core.Deinit()
|
||||
state.GamePath = ""
|
||||
state.Verbose = false
|
||||
}
|
||||
|
||||
func Test_getGameInfo(t *testing.T) {
|
||||
@@ -190,11 +190,11 @@ func Test_unzipGame(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_coreLoadGame(t *testing.T) {
|
||||
state.Global.Verbose = true
|
||||
state.Verbose = true
|
||||
|
||||
ext := utils.CoreExt()
|
||||
|
||||
Init(&video.Video{Window: &WindowMock{}})
|
||||
Init(&video.Video{})
|
||||
|
||||
if err := glfw.Init(); err != nil {
|
||||
log.Fatalln("failed to initialize glfw")
|
||||
@@ -212,14 +212,14 @@ func Test_coreLoadGame(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Global state should be set by Load", func(t *testing.T) {
|
||||
if state.Global.Core == nil {
|
||||
t.Errorf("got = %v, want %v", nil, state.Global.Core)
|
||||
if state.Core == nil {
|
||||
t.Errorf("got = %v, want %v", nil, state.Core)
|
||||
}
|
||||
if state.Global.GamePath != "testdata/Polar Rescue (USA).vec" {
|
||||
t.Errorf("got = %v, want %v", state.Global.GamePath, "testdata/Polar Rescue (USA).vec")
|
||||
if state.GamePath != "testdata/Polar Rescue (USA).vec" {
|
||||
t.Errorf("got = %v, want %v", state.GamePath, "testdata/Polar Rescue (USA).vec")
|
||||
}
|
||||
if !state.Global.CoreRunning {
|
||||
t.Errorf("got = %v, want %v", state.Global.CoreRunning, true)
|
||||
if !state.CoreRunning {
|
||||
t.Errorf("got = %v, want %v", state.CoreRunning, true)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -227,14 +227,14 @@ func Test_coreLoadGame(t *testing.T) {
|
||||
Unload()
|
||||
|
||||
t.Run("Global state should be cleared by Unload", func(t *testing.T) {
|
||||
if state.Global.Core != nil {
|
||||
t.Errorf("got = %v, want %v", state.Global.Core, nil)
|
||||
if state.Core != nil {
|
||||
t.Errorf("got = %v, want %v", state.Core, nil)
|
||||
}
|
||||
if state.Global.GamePath != "" {
|
||||
t.Errorf("got = %v, want %v", state.Global.GamePath, "")
|
||||
if state.GamePath != "" {
|
||||
t.Errorf("got = %v, want %v", state.GamePath, "")
|
||||
}
|
||||
if state.Global.CoreRunning {
|
||||
t.Errorf("got = %v, want %v", state.Global.CoreRunning, false)
|
||||
if state.CoreRunning {
|
||||
t.Errorf("got = %v, want %v", state.CoreRunning, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
+6
-6
@@ -136,13 +136,13 @@ func environment(cmd uint32, data unsafe.Pointer) bool {
|
||||
case libretro.EnvironmentGetUsername:
|
||||
return environmentGetUsername(data)
|
||||
case libretro.EnvironmentGetLogInterface:
|
||||
state.Global.Core.BindLogCallback(data, logCallback)
|
||||
state.Core.BindLogCallback(data, logCallback)
|
||||
case libretro.EnvironmentGetPerfInterface:
|
||||
state.Global.Core.BindPerfCallback(data, getTimeUsec)
|
||||
state.Core.BindPerfCallback(data, getTimeUsec)
|
||||
case libretro.EnvironmentSetFrameTimeCallback:
|
||||
state.Global.Core.SetFrameTimeCallback(data)
|
||||
state.Core.SetFrameTimeCallback(data)
|
||||
case libretro.EnvironmentSetAudioCallback:
|
||||
state.Global.Core.SetAudioCallback(data)
|
||||
state.Core.SetAudioCallback(data)
|
||||
case libretro.EnvironmentGetCanDupe:
|
||||
libretro.SetBool(data, true)
|
||||
case libretro.EnvironmentSetPixelFormat:
|
||||
@@ -152,7 +152,7 @@ func environment(cmd uint32, data unsafe.Pointer) bool {
|
||||
case libretro.EnvironmentGetSaveDirectory:
|
||||
return environmentGetSaveDirectory(data)
|
||||
case libretro.EnvironmentShutdown:
|
||||
vid.Window.SetShouldClose(true)
|
||||
vid.SetShouldClose(true)
|
||||
case libretro.EnvironmentGetCoreOptionsVersion:
|
||||
libretro.SetUint(data, 1)
|
||||
case libretro.EnvironmentSetCoreOptions:
|
||||
@@ -172,7 +172,7 @@ func environment(cmd uint32, data unsafe.Pointer) bool {
|
||||
avi := libretro.GetSystemAVInfo(data)
|
||||
vid.Geom = avi.Geometry
|
||||
case libretro.EnvironmentGetFastforwarding:
|
||||
libretro.SetBool(data, state.Global.FastForward)
|
||||
libretro.SetBool(data, state.FastForward)
|
||||
case libretro.EnvironmentGetLanguage:
|
||||
libretro.SetUint(data, 0)
|
||||
default:
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/libretro/ludo/menu"
|
||||
ntf "github.com/libretro/ludo/notifications"
|
||||
"github.com/libretro/ludo/playlists"
|
||||
"github.com/libretro/ludo/savefiles"
|
||||
"github.com/libretro/ludo/scanner"
|
||||
"github.com/libretro/ludo/settings"
|
||||
"github.com/libretro/ludo/state"
|
||||
@@ -26,6 +27,8 @@ func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
var frame = 0
|
||||
|
||||
func runLoop(vid *video.Video, m *menu.Menu) {
|
||||
currTime := time.Now()
|
||||
prevTime := time.Now()
|
||||
@@ -37,17 +40,21 @@ func runLoop(vid *video.Video, m *menu.Menu) {
|
||||
ntf.Process(dt)
|
||||
vid.ResizeViewport()
|
||||
m.UpdatePalette()
|
||||
if !state.Global.MenuActive {
|
||||
if state.Global.CoreRunning {
|
||||
state.Global.Core.Run()
|
||||
if state.Global.Core.FrameTimeCallback != nil {
|
||||
state.Global.Core.FrameTimeCallback.Callback(state.Global.Core.FrameTimeCallback.Reference)
|
||||
if !state.MenuActive {
|
||||
if state.CoreRunning {
|
||||
state.Core.Run()
|
||||
if state.Core.FrameTimeCallback != nil {
|
||||
state.Core.FrameTimeCallback.Callback(state.Core.FrameTimeCallback.Reference)
|
||||
}
|
||||
if state.Global.Core.AudioCallback != nil {
|
||||
state.Global.Core.AudioCallback.Callback()
|
||||
if state.Core.AudioCallback != nil {
|
||||
state.Core.AudioCallback.Callback()
|
||||
}
|
||||
}
|
||||
vid.Render()
|
||||
frame++
|
||||
if frame%600 == 0 { // save sram about every 10 sec
|
||||
savefiles.SaveSRAM()
|
||||
}
|
||||
} else {
|
||||
input.Poll()
|
||||
m.Update(dt)
|
||||
@@ -55,7 +62,7 @@ func runLoop(vid *video.Video, m *menu.Menu) {
|
||||
m.Render(dt)
|
||||
}
|
||||
m.RenderNotifications()
|
||||
if state.Global.FastForward {
|
||||
if state.FastForward {
|
||||
glfw.SwapInterval(0)
|
||||
} else {
|
||||
glfw.SwapInterval(1)
|
||||
@@ -73,9 +80,9 @@ func main() {
|
||||
}
|
||||
|
||||
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
flag.StringVar(&state.Global.CorePath, "L", "", "Path to the libretro core")
|
||||
flag.BoolVar(&state.Global.Verbose, "v", false, "Verbose logs")
|
||||
flag.BoolVar(&state.Global.LudOS, "ludos", false, "Expose the features related to LudOS")
|
||||
flag.StringVar(&state.CorePath, "L", "", "Path to the libretro core")
|
||||
flag.BoolVar(&state.Verbose, "v", false, "Verbose logs")
|
||||
flag.BoolVar(&state.LudOS, "ludos", false, "Expose the features related to LudOS")
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
|
||||
@@ -89,7 +96,7 @@ func main() {
|
||||
}
|
||||
defer glfw.Terminate()
|
||||
|
||||
state.Global.DB, err = scanner.LoadDB(settings.Current.DatabaseDirectory)
|
||||
state.DB, err = scanner.LoadDB(settings.Current.DatabaseDirectory)
|
||||
if err != nil {
|
||||
log.Println("Can't load game database:", err)
|
||||
}
|
||||
@@ -108,8 +115,8 @@ func main() {
|
||||
|
||||
input.Init(vid)
|
||||
|
||||
if len(state.Global.CorePath) > 0 {
|
||||
err := core.Load(state.Global.CorePath)
|
||||
if len(state.CorePath) > 0 {
|
||||
err := core.Load(state.CorePath)
|
||||
if err == nil {
|
||||
if len(gamePath) > 0 {
|
||||
err := core.LoadGame(gamePath)
|
||||
@@ -125,7 +132,7 @@ func main() {
|
||||
}
|
||||
|
||||
// No game running? display the menu
|
||||
state.Global.MenuActive = !state.Global.CoreRunning
|
||||
state.MenuActive = !state.CoreRunning
|
||||
|
||||
runLoop(vid, m)
|
||||
|
||||
|
||||
+4
-4
@@ -7,12 +7,12 @@ import (
|
||||
|
||||
// Used to easily compose different hint bars based on the context.
|
||||
func stackHint(stack *float32, icon uint32, label string, h int) {
|
||||
vid.Font.SetColor(darkGrey)
|
||||
menu.Font.SetColor(darkGrey)
|
||||
*stack += 30 * menu.ratio
|
||||
vid.DrawImage(icon, *stack, float32(h)-70*menu.ratio, 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
menu.DrawImage(icon, *stack, float32(h)-70*menu.ratio, 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
*stack += 70 * menu.ratio
|
||||
vid.Font.Printf(*stack, float32(h)-23*menu.ratio, 0.4*menu.ratio, label)
|
||||
*stack += vid.Font.Width(0.4*menu.ratio, label)
|
||||
menu.Font.Printf(*stack, float32(h)-23*menu.ratio, 0.4*menu.ratio, label)
|
||||
*stack += menu.Font.Width(0.4*menu.ratio, label)
|
||||
}
|
||||
|
||||
func hintIcons() (arrows, upDown, leftRight, a, b, x, y, start, slct, guide uint32) {
|
||||
|
||||
+9
-9
@@ -162,10 +162,10 @@ func (m *Menu) ProcessHotkeys() {
|
||||
combo := input.NewState[0][libretro.DeviceIDJoypadL3] == 1 && input.Pressed[0][libretro.DeviceIDJoypadR3] == 1
|
||||
combo = combo || input.Pressed[0][libretro.DeviceIDJoypadL3] == 1 && input.NewState[0][libretro.DeviceIDJoypadR3] == 1
|
||||
|
||||
if (input.Pressed[0][input.ActionMenuToggle] == 1 || combo) && state.Global.CoreRunning {
|
||||
state.Global.MenuActive = !state.Global.MenuActive
|
||||
state.Global.FastForward = false
|
||||
if state.Global.MenuActive {
|
||||
if (input.Pressed[0][input.ActionMenuToggle] == 1 || combo) && state.CoreRunning {
|
||||
state.MenuActive = !state.MenuActive
|
||||
state.FastForward = false
|
||||
if state.MenuActive {
|
||||
audio.PlayEffect(audio.Effects["notice"])
|
||||
} else {
|
||||
audio.PlayEffect(audio.Effects["notice_back"])
|
||||
@@ -175,7 +175,7 @@ func (m *Menu) ProcessHotkeys() {
|
||||
// Toggle fullscreen if ActionFullscreenToggle is pressed
|
||||
if input.Pressed[0][input.ActionFullscreenToggle] == 1 {
|
||||
settings.Current.VideoFullscreen = !settings.Current.VideoFullscreen
|
||||
vid.Reconfigure(settings.Current.VideoFullscreen)
|
||||
m.Reconfigure(settings.Current.VideoFullscreen)
|
||||
m.ContextReset()
|
||||
err := settings.Save()
|
||||
if err != nil {
|
||||
@@ -183,9 +183,9 @@ func (m *Menu) ProcessHotkeys() {
|
||||
}
|
||||
}
|
||||
|
||||
if input.Pressed[0][input.ActionFastForwardToggle] == 1 && !state.Global.MenuActive {
|
||||
state.Global.FastForward = !state.Global.FastForward
|
||||
if state.Global.FastForward {
|
||||
if input.Pressed[0][input.ActionFastForwardToggle] == 1 && !state.MenuActive {
|
||||
state.FastForward = !state.FastForward
|
||||
if state.FastForward {
|
||||
ntf.DisplayAndLog(ntf.Info, "Menu", "Fast forward ON")
|
||||
} else {
|
||||
ntf.DisplayAndLog(ntf.Info, "Menu", "Fast forward OFF")
|
||||
@@ -196,7 +196,7 @@ func (m *Menu) ProcessHotkeys() {
|
||||
// in case a game is running
|
||||
if input.Pressed[0][input.ActionShouldClose] == 1 {
|
||||
askConfirmation(func() {
|
||||
vid.Window.SetShouldClose(true)
|
||||
m.SetShouldClose(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/libretro/ludo/video"
|
||||
)
|
||||
|
||||
var vid *video.Video
|
||||
var menu *Menu
|
||||
|
||||
// Menu is a type holding the menu state, the stack of scenes, tweens, etc
|
||||
@@ -23,17 +22,18 @@ type Menu struct {
|
||||
scroll float32
|
||||
ratio float32
|
||||
t float64
|
||||
|
||||
*video.Video // we embbed video here to have direct access to drawing functions
|
||||
}
|
||||
|
||||
// Init initializes the menu.
|
||||
// If a game is already running, it will warp the user to the quick menu.
|
||||
// If not, it will display the menu tabs.
|
||||
func Init(v *video.Video) *Menu {
|
||||
vid = v
|
||||
|
||||
w, _ := v.Window.GetFramebufferSize()
|
||||
w, _ := v.GetFramebufferSize()
|
||||
|
||||
menu = &Menu{}
|
||||
menu.Video = v
|
||||
menu.stack = []Scene{}
|
||||
menu.tweens = make(Tweens)
|
||||
menu.ratio = float32(w) / 1920
|
||||
@@ -56,18 +56,18 @@ func (m *Menu) Push(s Scene) {
|
||||
func (m *Menu) Render(dt float32) {
|
||||
// Early return to not render the menu, in case MenuActive is set to false
|
||||
// during the same mainloop iteration
|
||||
if !state.Global.MenuActive {
|
||||
if !state.MenuActive {
|
||||
return
|
||||
}
|
||||
|
||||
m.t += float64(dt * 8)
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
w, h := m.GetFramebufferSize()
|
||||
m.ratio = float32(w) / 1920
|
||||
|
||||
if state.Global.CoreRunning {
|
||||
vid.DrawRect(0, 0, float32(w), float32(h), 0, bgColor.Alpha(0.85))
|
||||
if state.CoreRunning {
|
||||
m.DrawRect(0, 0, float32(w), float32(h), 0, bgColor.Alpha(0.85))
|
||||
} else {
|
||||
vid.DrawRect(0, 0, float32(w), float32(h), 0, bgColor)
|
||||
m.DrawRect(0, 0, float32(w), float32(h), 0, bgColor)
|
||||
}
|
||||
|
||||
m.tweens.Update(dt)
|
||||
|
||||
+2
-22
@@ -5,8 +5,6 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-gl/glfw/v3.3/glfw"
|
||||
|
||||
"github.com/libretro/ludo/state"
|
||||
"github.com/libretro/ludo/video"
|
||||
|
||||
@@ -14,26 +12,8 @@ import (
|
||||
"github.com/tanema/gween/ease"
|
||||
)
|
||||
|
||||
type WindowMock struct{}
|
||||
|
||||
func (m WindowMock) GetFramebufferSize() (width, height int) { return 320, 240 }
|
||||
func (m WindowMock) Destroy() {}
|
||||
func (m WindowMock) MakeContextCurrent() {}
|
||||
func (m WindowMock) SetSizeLimits(minw, minh, maxw, maxh int) {}
|
||||
func (m WindowMock) SetInputMode(mode glfw.InputMode, value int) {}
|
||||
func (m WindowMock) GetKey(key glfw.Key) glfw.Action { return 0 }
|
||||
func (m WindowMock) SetShouldClose(bool) {}
|
||||
func (m WindowMock) ShouldClose() bool { return false }
|
||||
func (m WindowMock) SetTitle(string) {}
|
||||
func (m WindowMock) SwapBuffers() {}
|
||||
|
||||
func Test_WarpToQuickMenu(t *testing.T) {
|
||||
|
||||
var vid = &video.Video{
|
||||
Window: &WindowMock{},
|
||||
}
|
||||
|
||||
m := Init(vid)
|
||||
m := Init(&video.Video{})
|
||||
|
||||
t.Run("Starts with a single scene if no game is running", func(t *testing.T) {
|
||||
got := len(menu.stack)
|
||||
@@ -51,7 +31,7 @@ func Test_WarpToQuickMenu(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
state.Global.CoreRunning = true
|
||||
state.CoreRunning = true
|
||||
m.WarpToQuickMenu()
|
||||
|
||||
t.Run("Warps at the quick menu if a game is launched", func(t *testing.T) {
|
||||
|
||||
@@ -21,8 +21,8 @@ var severityBgColor = map[ntf.Severity]video.Color{
|
||||
|
||||
// RenderNotifications draws the list of notification messages on the viewport
|
||||
func (m *Menu) RenderNotifications() {
|
||||
fbw, fbh := vid.Window.GetFramebufferSize()
|
||||
vid.Font.UpdateResolution(fbw, fbh)
|
||||
fbw, fbh := m.GetFramebufferSize()
|
||||
m.Font.UpdateResolution(fbw, fbh)
|
||||
var h float32 = 75
|
||||
stack := h
|
||||
for _, n := range ntf.List() {
|
||||
@@ -31,10 +31,10 @@ func (m *Menu) RenderNotifications() {
|
||||
fading = 1
|
||||
}
|
||||
offset := fading*h - h
|
||||
lw := vid.Font.Width(0.5*m.ratio, n.Message)
|
||||
lw := m.Font.Width(0.5*m.ratio, n.Message)
|
||||
fg := severityFgColor[n.Severity]
|
||||
bg := severityBgColor[n.Severity]
|
||||
vid.DrawRect(
|
||||
m.DrawRect(
|
||||
25*m.ratio,
|
||||
(stack+offset-46)*m.ratio,
|
||||
lw+40*m.ratio,
|
||||
@@ -42,8 +42,8 @@ func (m *Menu) RenderNotifications() {
|
||||
0.25,
|
||||
bg.Alpha(fading),
|
||||
)
|
||||
vid.Font.SetColor(fg.Alpha(fading))
|
||||
vid.Font.Printf(
|
||||
m.Font.SetColor(fg.Alpha(fading))
|
||||
m.Font.Printf(
|
||||
45*m.ratio,
|
||||
(stack+offset)*m.ratio,
|
||||
0.5*m.ratio,
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ func (m *Menu) UpdatePalette() {
|
||||
cursorBg = cyan
|
||||
textColor = black
|
||||
|
||||
if state.Global.CoreRunning || settings.Current.VideoDarkMode {
|
||||
if state.CoreRunning || settings.Current.VideoDarkMode {
|
||||
bgColor = darkerGrey
|
||||
cursorBg = darkBlue
|
||||
textColor = white
|
||||
|
||||
+17
-17
@@ -149,11 +149,11 @@ func genericSegueNext(list *entry) {
|
||||
// genericDrawCursor draws the blinking rectangular background of the active
|
||||
// menu entry
|
||||
func genericDrawCursor(list *entry) {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawImage(menu.icons["arrow"],
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawImage(menu.icons["arrow"],
|
||||
530*menu.ratio, float32(h)*list.cursor.yp-35*menu.ratio,
|
||||
70*menu.ratio, 70*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha))
|
||||
vid.DrawRect(
|
||||
menu.DrawRect(
|
||||
550*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio,
|
||||
float32(w)-630*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha))
|
||||
}
|
||||
@@ -161,11 +161,11 @@ func genericDrawCursor(list *entry) {
|
||||
// thumbnailDrawCursor draws the blinking rectangular background of the active
|
||||
// menu entry when there is a thumbnail
|
||||
func thumbnailDrawCursor(list *entry) {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawImage(menu.icons["arrow"],
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawImage(menu.icons["arrow"],
|
||||
500*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio,
|
||||
100*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha))
|
||||
vid.DrawRect(
|
||||
menu.DrawRect(
|
||||
530*menu.ratio, float32(h)*list.cursor.yp-120*menu.ratio,
|
||||
float32(w)-630*menu.ratio, 240*menu.ratio, 0.2, cursorBg.Alpha(list.cursor.alpha))
|
||||
}
|
||||
@@ -173,11 +173,11 @@ func thumbnailDrawCursor(list *entry) {
|
||||
// genericRender renders a vertical list of menu entries
|
||||
// It also display values of settings if we are displaying a settings scene
|
||||
func genericRender(list *entry) {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
w, h := menu.GetFramebufferSize()
|
||||
|
||||
genericDrawCursor(list)
|
||||
|
||||
vid.ScissorStart(int32(530*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
menu.ScissorStart(int32(530*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
|
||||
for _, e := range list.children {
|
||||
if e.yp < -0.1 || e.yp > 1.1 {
|
||||
@@ -186,15 +186,15 @@ func genericRender(list *entry) {
|
||||
|
||||
fontOffset := 64 * 0.7 * menu.ratio * 0.3
|
||||
|
||||
vid.DrawImage(menu.icons[e.icon],
|
||||
menu.DrawImage(menu.icons[e.icon],
|
||||
610*menu.ratio-64*0.5*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-64*0.5*menu.ratio+fontOffset,
|
||||
128*menu.ratio, 128*menu.ratio,
|
||||
0.5, textColor.Alpha(e.iconAlpha))
|
||||
|
||||
if e.labelAlpha > 0 {
|
||||
vid.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
vid.Font.Printf(
|
||||
menu.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
menu.Font.Printf(
|
||||
670*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset,
|
||||
0.5*menu.ratio, e.label)
|
||||
@@ -202,8 +202,8 @@ func genericRender(list *entry) {
|
||||
if e.widget != nil {
|
||||
e.widget(&e)
|
||||
} else if e.stringValue != nil {
|
||||
lw := vid.Font.Width(0.5*menu.ratio, e.stringValue())
|
||||
vid.Font.Printf(
|
||||
lw := menu.Font.Width(0.5*menu.ratio, e.stringValue())
|
||||
menu.Font.Printf(
|
||||
float32(w)-lw-128*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset,
|
||||
0.5*menu.ratio, e.stringValue())
|
||||
@@ -211,17 +211,17 @@ func genericRender(list *entry) {
|
||||
}
|
||||
}
|
||||
|
||||
vid.ScissorEnd()
|
||||
menu.ScissorEnd()
|
||||
}
|
||||
|
||||
func genericDrawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
@@ -80,13 +80,13 @@ func (s *sceneCoreOptions) render() {
|
||||
}
|
||||
|
||||
func (s *sceneCoreOptions) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
+16
-16
@@ -47,15 +47,15 @@ func (s *sceneDialog) update(dt float32) {
|
||||
}
|
||||
|
||||
func (s *sceneDialog) render() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
w, h := menu.GetFramebufferSize()
|
||||
fw := float32(w)
|
||||
fh := float32(h)
|
||||
vid.DrawRect(0, 0, fw, fh, 0, black.Alpha(0.85))
|
||||
menu.DrawRect(0, 0, fw, fh, 0, black.Alpha(0.85))
|
||||
|
||||
var width float32 = 1000
|
||||
var height float32 = 400
|
||||
|
||||
vid.DrawRect(
|
||||
menu.DrawRect(
|
||||
fw/2-width/2*menu.ratio,
|
||||
fh/2-height/2*menu.ratio,
|
||||
width*menu.ratio,
|
||||
@@ -64,41 +64,41 @@ func (s *sceneDialog) render() {
|
||||
white,
|
||||
)
|
||||
|
||||
vid.Font.SetColor(orange)
|
||||
menu.Font.SetColor(orange)
|
||||
msg1 := "A game is currently running."
|
||||
lw1 := vid.Font.Width(0.7*menu.ratio, msg1)
|
||||
vid.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio+20*menu.ratio, 0.7*menu.ratio, msg1)
|
||||
vid.Font.SetColor(black)
|
||||
lw1 := menu.Font.Width(0.7*menu.ratio, msg1)
|
||||
menu.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio+20*menu.ratio, 0.7*menu.ratio, msg1)
|
||||
menu.Font.SetColor(black)
|
||||
msg2 := "If you have not saved yet, your progress will be lost."
|
||||
lw2 := vid.Font.Width(0.5*menu.ratio, msg2)
|
||||
vid.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg2)
|
||||
lw2 := menu.Font.Width(0.5*menu.ratio, msg2)
|
||||
menu.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg2)
|
||||
msg3 := "Do you want to exit Ludo anyway?"
|
||||
lw3 := vid.Font.Width(0.5*menu.ratio, msg3)
|
||||
vid.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg3)
|
||||
lw3 := menu.Font.Width(0.5*menu.ratio, msg3)
|
||||
menu.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg3)
|
||||
|
||||
vid.Font.SetColor(darkGrey)
|
||||
menu.Font.SetColor(darkGrey)
|
||||
|
||||
var margin float32 = 15
|
||||
|
||||
_, _, _, a, b, _, _, _, _, _ := hintIcons()
|
||||
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
b,
|
||||
fw/2-width/2*menu.ratio+margin*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio,
|
||||
70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
fw/2-width/2*menu.ratio+margin*menu.ratio+70*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio,
|
||||
0.4*menu.ratio,
|
||||
"NO")
|
||||
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
a,
|
||||
fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio,
|
||||
70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio+70*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio,
|
||||
0.4*menu.ratio,
|
||||
|
||||
+20
-20
@@ -54,14 +54,14 @@ func loadHistoryEntry(list Scene, game history.Game) {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", "Core not found: %s", filepath.Base(corePath))
|
||||
return
|
||||
}
|
||||
if state.Global.CorePath != corePath {
|
||||
if state.CorePath != corePath {
|
||||
err := core.Load(corePath)
|
||||
if err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if state.Global.GamePath != game.Path {
|
||||
if state.GamePath != game.Path {
|
||||
err := core.LoadGame(game.Path)
|
||||
if err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
@@ -76,7 +76,7 @@ func loadHistoryEntry(list Scene, game history.Game) {
|
||||
list.segueNext()
|
||||
menu.Push(buildQuickMenu())
|
||||
menu.tweens.FastForward() // position the elements without animating
|
||||
state.Global.MenuActive = false
|
||||
state.MenuActive = false
|
||||
} else {
|
||||
list.segueNext()
|
||||
menu.Push(buildQuickMenu())
|
||||
@@ -108,11 +108,11 @@ func (s *sceneHistory) update(dt float32) {
|
||||
func (s *sceneHistory) render() {
|
||||
list := &s.entry
|
||||
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
_, h := menu.GetFramebufferSize()
|
||||
|
||||
thumbnailDrawCursor(list)
|
||||
|
||||
vid.ScissorStart(int32(510*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
menu.ScissorStart(int32(510*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
|
||||
for i, e := range list.children {
|
||||
if e.yp < -0.1 || e.yp > 1.1 {
|
||||
@@ -131,18 +131,18 @@ func (s *sceneHistory) render() {
|
||||
170*menu.ratio, 128*menu.ratio,
|
||||
e.scale, white.Alpha(e.iconAlpha),
|
||||
)
|
||||
vid.DrawBorder(
|
||||
menu.DrawBorder(
|
||||
680*menu.ratio-85*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset,
|
||||
170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale,
|
||||
textColor.Alpha(e.iconAlpha))
|
||||
if e.path == state.Global.GamePath && e.path != "" {
|
||||
vid.DrawCircle(
|
||||
if e.path == state.GamePath && e.path != "" {
|
||||
menu.DrawCircle(
|
||||
680*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio+fontOffset,
|
||||
90*menu.ratio*e.scale,
|
||||
black.Alpha(e.iconAlpha))
|
||||
vid.DrawImage(menu.icons["resume"],
|
||||
menu.DrawImage(menu.icons["resume"],
|
||||
680*menu.ratio-25*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset,
|
||||
50*menu.ratio, 50*menu.ratio,
|
||||
@@ -155,47 +155,47 @@ func (s *sceneHistory) render() {
|
||||
slOffset = 30 * menu.ratio * e.subLabelAlpha
|
||||
}
|
||||
|
||||
vid.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
menu.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
stack := 840 * menu.ratio
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
840*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset-slOffset,
|
||||
0.5*menu.ratio, e.label)
|
||||
stack += float32(int(vid.Font.Width(0.5*menu.ratio, e.label)))
|
||||
stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label)))
|
||||
stack += 10
|
||||
|
||||
for _, tag := range e.tags {
|
||||
if _, ok := menu.icons[tag]; ok {
|
||||
stack += 20
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
menu.icons[tag],
|
||||
stack, float32(h)*e.yp-22*menu.ratio-slOffset,
|
||||
60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha))
|
||||
vid.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio-slOffset,
|
||||
menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio-slOffset,
|
||||
60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4))
|
||||
stack += 60 * menu.ratio
|
||||
}
|
||||
}
|
||||
|
||||
vid.Font.SetColor(mediumGrey.Alpha(e.subLabelAlpha))
|
||||
vid.Font.Printf(
|
||||
menu.Font.SetColor(mediumGrey.Alpha(e.subLabelAlpha))
|
||||
menu.Font.Printf(
|
||||
840*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset+60*menu.ratio-slOffset,
|
||||
0.5*menu.ratio, e.subLabel)
|
||||
}
|
||||
}
|
||||
|
||||
vid.ScissorEnd()
|
||||
menu.ScissorEnd()
|
||||
}
|
||||
|
||||
func (s *sceneHistory) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
+15
-15
@@ -55,7 +55,7 @@ func (s *sceneKeyboard) Entry() *entry {
|
||||
}
|
||||
|
||||
func (s *sceneKeyboard) segueMount() {
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
_, h := menu.GetFramebufferSize()
|
||||
s.y = float32(h)
|
||||
s.alpha = 0
|
||||
menu.tweens[&s.y] = gween.New(s.y, 0, 0.15, ease.OutSine)
|
||||
@@ -149,7 +149,7 @@ func (s *sceneKeyboard) update(dt float32) {
|
||||
}
|
||||
|
||||
func (s *sceneKeyboard) render() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
w, h := menu.GetFramebufferSize()
|
||||
lines := float32(4)
|
||||
kbh := float32(h) * 0.6
|
||||
ksp := (kbh - (50 * menu.ratio)) / (lines + 1)
|
||||
@@ -157,34 +157,34 @@ func (s *sceneKeyboard) render() {
|
||||
ttw := 10 * ksp
|
||||
|
||||
// Background
|
||||
vid.DrawRect(0, 0, float32(w), float32(h), 0,
|
||||
menu.DrawRect(0, 0, float32(w), float32(h), 0,
|
||||
white.Alpha(s.alpha))
|
||||
|
||||
// Label
|
||||
vid.Font.SetColor(black)
|
||||
vid.Font.Printf(
|
||||
menu.Font.SetColor(black)
|
||||
menu.Font.Printf(
|
||||
float32(w)/2-ttw/2,
|
||||
s.y+float32(h)*0.15-ksz/2+ksz*0.6,
|
||||
ksz/260, s.label)
|
||||
|
||||
// Value
|
||||
vid.DrawRect(float32(w)/2-ttw/2, s.y+float32(h)*0.25-ksz/2, ttw, ksz, 0,
|
||||
menu.DrawRect(float32(w)/2-ttw/2, s.y+float32(h)*0.25-ksz/2, ttw, ksz, 0,
|
||||
video.Color{R: 0.95, G: 0.95, B: 0.95, A: 1})
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
float32(w)/2-ttw/2+ksz/4,
|
||||
s.y+float32(h)*0.25-ksz/2+ksz*0.62,
|
||||
ksz/200, s.value+"|")
|
||||
|
||||
// Keyboard
|
||||
|
||||
vid.DrawRect(0, s.y+float32(h)-kbh, float32(w), kbh, 0, black)
|
||||
menu.DrawRect(0, s.y+float32(h)-kbh, float32(w), kbh, 0, black)
|
||||
|
||||
vid.Font.SetColor(white)
|
||||
menu.Font.SetColor(white)
|
||||
|
||||
for i, key := range layouts[s.layout] {
|
||||
x := float32(i%10)*ksp - ttw/2 + float32(w)/2
|
||||
y := s.y + float32(i/10)*ksp + ksp/2 + float32(h) - kbh
|
||||
gw := vid.Font.Width(ksz/200, key)
|
||||
gw := menu.Font.Width(ksz/200, key)
|
||||
|
||||
c1 := video.Color{R: 0.15, G: 0.15, B: 0.15, A: 1}
|
||||
c2 := video.Color{R: 0.25, G: 0.25, B: 0.25, A: 1}
|
||||
@@ -193,10 +193,10 @@ func (s *sceneKeyboard) render() {
|
||||
c2 = video.Color{R: 0.45, G: 0.45, B: 0.45, A: 1}
|
||||
}
|
||||
|
||||
vid.DrawRect(x, y, ksz, ksz, 0.2, c1)
|
||||
vid.DrawRect(x, y, ksz, ksz*0.95, 0.2, c2)
|
||||
menu.DrawRect(x, y, ksz, ksz, 0.2, c1)
|
||||
menu.DrawRect(x, y, ksz, ksz*0.95, 0.2, c2)
|
||||
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
x+ksz/2-gw/2,
|
||||
y+ksz*0.6,
|
||||
ksz/200, key)
|
||||
@@ -204,8 +204,8 @@ func (s *sceneKeyboard) render() {
|
||||
}
|
||||
|
||||
func (s *sceneKeyboard) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
arrows, _, _, a, b, x, y, start, _, _ := hintIcons()
|
||||
|
||||
|
||||
+9
-9
@@ -23,7 +23,7 @@ func buildMainMenu() Scene {
|
||||
|
||||
usr, _ := user.Current()
|
||||
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
list.children = append(list.children, entry{
|
||||
label: "Quick Menu",
|
||||
icon: "subsetting",
|
||||
@@ -52,7 +52,7 @@ func buildMainMenu() Scene {
|
||||
label: "Load Game",
|
||||
icon: "subsetting",
|
||||
callbackOK: func() {
|
||||
if state.Global.Core != nil {
|
||||
if state.Core != nil {
|
||||
list.segueNext()
|
||||
menu.Push(buildExplorer(
|
||||
usr.HomeDir,
|
||||
@@ -66,7 +66,7 @@ func buildMainMenu() Scene {
|
||||
},
|
||||
})
|
||||
|
||||
if state.Global.LudOS {
|
||||
if state.LudOS {
|
||||
list.children = append(list.children, entry{
|
||||
label: "Updater",
|
||||
icon: "subsetting",
|
||||
@@ -97,7 +97,7 @@ func buildMainMenu() Scene {
|
||||
icon: "subsetting",
|
||||
callbackOK: func() {
|
||||
askConfirmation(func() {
|
||||
vid.Window.SetShouldClose(true)
|
||||
menu.SetShouldClose(true)
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -126,10 +126,10 @@ func gameExplorerCb(path string) {
|
||||
history.Push(history.Game{
|
||||
Path: path,
|
||||
Name: utils.FileName(path),
|
||||
CorePath: state.Global.CorePath,
|
||||
CorePath: state.CorePath,
|
||||
})
|
||||
menu.WarpToQuickMenu()
|
||||
state.Global.MenuActive = false
|
||||
state.MenuActive = false
|
||||
}
|
||||
|
||||
// Shutdown the operating system
|
||||
@@ -150,9 +150,9 @@ func cleanReboot() {
|
||||
|
||||
// Displays a confirmation dialog before performing an irreversible action
|
||||
func askConfirmation(cb func()) {
|
||||
if state.Global.CoreRunning {
|
||||
if !state.Global.MenuActive {
|
||||
state.Global.MenuActive = true
|
||||
if state.CoreRunning {
|
||||
if !state.MenuActive {
|
||||
state.MenuActive = true
|
||||
}
|
||||
menu.Push(buildDialog(func() {
|
||||
cb()
|
||||
|
||||
+18
-18
@@ -89,13 +89,13 @@ func loadPlaylistEntry(list *scenePlaylist, playlist string, game playlists.Game
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", "Core not found: %s", filepath.Base(corePath))
|
||||
return
|
||||
}
|
||||
if state.Global.CorePath != corePath {
|
||||
if state.CorePath != corePath {
|
||||
if err := core.Load(corePath); err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if state.Global.GamePath != game.Path {
|
||||
if state.GamePath != game.Path {
|
||||
if err := core.LoadGame(game.Path); err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
return
|
||||
@@ -109,7 +109,7 @@ func loadPlaylistEntry(list *scenePlaylist, playlist string, game playlists.Game
|
||||
list.segueNext()
|
||||
menu.Push(buildQuickMenu())
|
||||
menu.tweens.FastForward() // position the elements without animating
|
||||
state.Global.MenuActive = false
|
||||
state.MenuActive = false
|
||||
} else {
|
||||
list.segueNext()
|
||||
menu.Push(buildQuickMenu())
|
||||
@@ -141,11 +141,11 @@ func (s *scenePlaylist) update(dt float32) {
|
||||
func (s *scenePlaylist) render() {
|
||||
list := &s.entry
|
||||
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
_, h := menu.GetFramebufferSize()
|
||||
|
||||
thumbnailDrawCursor(list)
|
||||
|
||||
vid.ScissorStart(int32(510*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
menu.ScissorStart(int32(510*menu.ratio), 0, int32(1310*menu.ratio), int32(h))
|
||||
|
||||
for i, e := range list.children {
|
||||
if e.yp < -0.1 || e.yp > 1.1 {
|
||||
@@ -164,41 +164,41 @@ func (s *scenePlaylist) render() {
|
||||
170*menu.ratio, 128*menu.ratio,
|
||||
e.scale, white.Alpha(e.iconAlpha),
|
||||
)
|
||||
vid.DrawBorder(
|
||||
menu.DrawBorder(
|
||||
680*menu.ratio-85*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset,
|
||||
170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale,
|
||||
textColor.Alpha(e.iconAlpha))
|
||||
if e.path == state.Global.GamePath && e.path != "" {
|
||||
vid.DrawCircle(
|
||||
if e.path == state.GamePath && e.path != "" {
|
||||
menu.DrawCircle(
|
||||
680*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio+fontOffset,
|
||||
90*menu.ratio*e.scale,
|
||||
black.Alpha(e.iconAlpha))
|
||||
vid.DrawImage(menu.icons["resume"],
|
||||
menu.DrawImage(menu.icons["resume"],
|
||||
680*menu.ratio-25*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset,
|
||||
50*menu.ratio, 50*menu.ratio,
|
||||
e.scale, white.Alpha(e.iconAlpha))
|
||||
}
|
||||
|
||||
vid.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
menu.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
stack := 840 * menu.ratio
|
||||
vid.Font.Printf(
|
||||
menu.Font.Printf(
|
||||
840*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset,
|
||||
0.5*menu.ratio, e.label)
|
||||
stack += float32(int(vid.Font.Width(0.5*menu.ratio, e.label)))
|
||||
stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label)))
|
||||
stack += 10
|
||||
|
||||
for _, tag := range e.tags {
|
||||
if _, ok := menu.icons[tag]; ok {
|
||||
stack += 20
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
menu.icons[tag],
|
||||
stack, float32(h)*e.yp-22*menu.ratio,
|
||||
60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha))
|
||||
vid.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio,
|
||||
menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio,
|
||||
60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4))
|
||||
stack += 60 * menu.ratio
|
||||
}
|
||||
@@ -206,17 +206,17 @@ func (s *scenePlaylist) render() {
|
||||
}
|
||||
}
|
||||
|
||||
vid.ScissorEnd()
|
||||
menu.ScissorEnd()
|
||||
}
|
||||
|
||||
func (s *scenePlaylist) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
+7
-7
@@ -18,8 +18,8 @@ func buildQuickMenu() Scene {
|
||||
label: "Resume",
|
||||
icon: "resume",
|
||||
callbackOK: func() {
|
||||
state.Global.MenuActive = false
|
||||
state.Global.FastForward = false
|
||||
state.MenuActive = false
|
||||
state.FastForward = false
|
||||
},
|
||||
})
|
||||
|
||||
@@ -27,9 +27,9 @@ func buildQuickMenu() Scene {
|
||||
label: "Reset",
|
||||
icon: "reset",
|
||||
callbackOK: func() {
|
||||
state.Global.Core.Reset()
|
||||
state.Global.MenuActive = false
|
||||
state.Global.FastForward = false
|
||||
state.Core.Reset()
|
||||
state.MenuActive = false
|
||||
state.FastForward = false
|
||||
},
|
||||
})
|
||||
|
||||
@@ -46,8 +46,8 @@ func buildQuickMenu() Scene {
|
||||
label: "Take Screenshot",
|
||||
icon: "screenshot",
|
||||
callbackOK: func() {
|
||||
name := utils.DatedName(state.Global.GamePath)
|
||||
err := vid.TakeScreenshot(name)
|
||||
name := utils.DatedName(state.GamePath)
|
||||
err := menu.TakeScreenshot(name)
|
||||
if err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
} else {
|
||||
|
||||
+12
-12
@@ -24,8 +24,8 @@ func buildSavestates() Scene {
|
||||
label: "Save State",
|
||||
icon: "savestate",
|
||||
callbackOK: func() {
|
||||
name := utils.DatedName(state.Global.GamePath)
|
||||
err := vid.TakeScreenshot(name)
|
||||
name := utils.DatedName(state.GamePath)
|
||||
err := menu.TakeScreenshot(name)
|
||||
if err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func buildSavestates() Scene {
|
||||
},
|
||||
})
|
||||
|
||||
gameName := utils.FileName(state.Global.GamePath)
|
||||
gameName := utils.FileName(state.GamePath)
|
||||
paths, _ := filepath.Glob(settings.Current.SavestatesDirectory + "/" + gameName + "@*.state")
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(paths)))
|
||||
for _, path := range paths {
|
||||
@@ -55,7 +55,7 @@ func buildSavestates() Scene {
|
||||
if err != nil {
|
||||
ntf.DisplayAndLog(ntf.Error, "Menu", err.Error())
|
||||
} else {
|
||||
state.Global.MenuActive = false
|
||||
state.MenuActive = false
|
||||
|
||||
ntf.DisplayAndLog(ntf.Success, "Menu", "State loaded.")
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (s *sceneSavestates) update(dt float32) {
|
||||
func (s *sceneSavestates) render() {
|
||||
list := &s.entry
|
||||
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
_, h := menu.GetFramebufferSize()
|
||||
|
||||
thumbnailDrawCursor(list)
|
||||
|
||||
@@ -112,21 +112,21 @@ func (s *sceneSavestates) render() {
|
||||
170*menu.ratio, 128*menu.ratio,
|
||||
e.scale, textColor.Alpha(e.iconAlpha),
|
||||
)
|
||||
vid.DrawBorder(
|
||||
menu.DrawBorder(
|
||||
680*menu.ratio-85*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset,
|
||||
170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale,
|
||||
textColor.Alpha(e.iconAlpha))
|
||||
if i == 0 {
|
||||
vid.DrawImage(menu.icons["savestate"],
|
||||
menu.DrawImage(menu.icons["savestate"],
|
||||
680*menu.ratio-25*e.scale*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset,
|
||||
50*menu.ratio, 50*menu.ratio,
|
||||
e.scale, textColor.Alpha(e.iconAlpha))
|
||||
}
|
||||
|
||||
vid.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
vid.Font.Printf(
|
||||
menu.Font.SetColor(textColor.Alpha(e.labelAlpha))
|
||||
menu.Font.Printf(
|
||||
840*menu.ratio,
|
||||
float32(h)*e.yp+fontOffset,
|
||||
0.5*menu.ratio, e.label)
|
||||
@@ -135,15 +135,15 @@ func (s *sceneSavestates) render() {
|
||||
}
|
||||
|
||||
func (s *sceneSavestates) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
ptr := menu.stack[len(menu.stack)-1].Entry().ptr
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
+15
-15
@@ -25,15 +25,15 @@ type sceneSettings struct {
|
||||
// If we're in program mode, hide settings flagged with hide:"program"
|
||||
func isHidden(f *structs.Field) bool {
|
||||
return f.Tag("hide") == "always" ||
|
||||
(state.Global.LudOS && f.Tag("hide") == "ludos") ||
|
||||
(!state.Global.LudOS && f.Tag("hide") == "app")
|
||||
(state.LudOS && f.Tag("hide") == "ludos") ||
|
||||
(!state.LudOS && f.Tag("hide") == "app")
|
||||
}
|
||||
|
||||
func buildSettings() Scene {
|
||||
var list sceneSettings
|
||||
list.label = "Settings"
|
||||
|
||||
if state.Global.LudOS {
|
||||
if state.LudOS {
|
||||
list.children = append(list.children, entry{
|
||||
label: "Wi-Fi",
|
||||
icon: "subsetting",
|
||||
@@ -133,8 +133,8 @@ var widgets = map[string]func(*entry){
|
||||
if e.value().(bool) {
|
||||
icon = "on"
|
||||
}
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawImage(menu.icons[icon],
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawImage(menu.icons[icon],
|
||||
float32(w)-128*menu.ratio-128*menu.ratio,
|
||||
float32(h)*e.yp-64*1.25*menu.ratio,
|
||||
128*menu.ratio, 128*menu.ratio,
|
||||
@@ -143,15 +143,15 @@ var widgets = map[string]func(*entry){
|
||||
|
||||
// Range widget for audio volume and similat float settings
|
||||
"range": func(e *entry) {
|
||||
fbw, fbh := vid.Window.GetFramebufferSize()
|
||||
fbw, fbh := menu.GetFramebufferSize()
|
||||
x := float32(fbw) - 128*menu.ratio - 175*menu.ratio
|
||||
y := float32(fbh)*e.yp - 4*menu.ratio
|
||||
w := 175 * menu.ratio
|
||||
h := 8 * menu.ratio
|
||||
vid.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha/4))
|
||||
menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha/4))
|
||||
w = 175 * menu.ratio * e.value().(float32)
|
||||
vid.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha))
|
||||
vid.DrawCircle(x+w, y+4*menu.ratio, 38*menu.ratio, textColor.Alpha(e.iconAlpha))
|
||||
menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha))
|
||||
menu.DrawCircle(x+w, y+4*menu.ratio, 38*menu.ratio, textColor.Alpha(e.iconAlpha))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ var incrCallbacks = map[string]callbackIncrement{
|
||||
v := f.Value().(bool)
|
||||
v = !v
|
||||
f.Set(v)
|
||||
vid.Reconfigure(settings.Current.VideoFullscreen)
|
||||
menu.Reconfigure(settings.Current.VideoFullscreen)
|
||||
menu.ContextReset()
|
||||
settings.Save()
|
||||
},
|
||||
@@ -177,7 +177,7 @@ var incrCallbacks = map[string]callbackIncrement{
|
||||
v = len(glfw.GetMonitors()) - 1
|
||||
}
|
||||
f.Set(v)
|
||||
vid.Reconfigure(settings.Current.VideoFullscreen)
|
||||
menu.Reconfigure(settings.Current.VideoFullscreen)
|
||||
menu.ContextReset()
|
||||
settings.Save()
|
||||
},
|
||||
@@ -193,7 +193,7 @@ var incrCallbacks = map[string]callbackIncrement{
|
||||
i = 0
|
||||
}
|
||||
f.Set(filters[i])
|
||||
vid.UpdateFilter(filters[i])
|
||||
menu.UpdateFilter(filters[i])
|
||||
settings.Save()
|
||||
},
|
||||
"VideoDarkMode": func(f *structs.Field, direction int) {
|
||||
@@ -272,14 +272,14 @@ func (s *sceneSettings) render() {
|
||||
}
|
||||
|
||||
func (s *sceneSettings) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, leftRight, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
list := menu.stack[len(menu.stack)-1].Entry()
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
|
||||
+11
-11
@@ -257,7 +257,7 @@ func (tabs *sceneTabs) update(dt float32) {
|
||||
}
|
||||
|
||||
func (tabs sceneTabs) render() {
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
_, h := menu.GetFramebufferSize()
|
||||
|
||||
stackWidth := 710 * menu.ratio
|
||||
for i, e := range tabs.children {
|
||||
@@ -270,31 +270,31 @@ func (tabs sceneTabs) render() {
|
||||
stackWidth += e.width*menu.ratio + e.margin*menu.ratio
|
||||
|
||||
if e.labelAlpha > 0 {
|
||||
vid.Font.SetColor(c.Alpha(e.labelAlpha))
|
||||
lw := vid.Font.Width(0.5*menu.ratio, e.label)
|
||||
vid.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio)), 0.5*menu.ratio, e.label)
|
||||
lw = vid.Font.Width(0.4*menu.ratio, e.subLabel)
|
||||
vid.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio)), 0.4*menu.ratio, e.subLabel)
|
||||
menu.Font.SetColor(c.Alpha(e.labelAlpha))
|
||||
lw := menu.Font.Width(0.5*menu.ratio, e.label)
|
||||
menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio)), 0.5*menu.ratio, e.label)
|
||||
lw = menu.Font.Width(0.4*menu.ratio, e.subLabel)
|
||||
menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio)), 0.4*menu.ratio, e.subLabel)
|
||||
}
|
||||
|
||||
vid.DrawImage(menu.icons["hexagon"],
|
||||
menu.DrawImage(menu.icons["hexagon"],
|
||||
x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio,
|
||||
440*menu.ratio, 440*menu.ratio, e.scale, c)
|
||||
|
||||
vid.DrawImage(menu.icons[e.icon],
|
||||
menu.DrawImage(menu.icons[e.icon],
|
||||
x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio,
|
||||
256*menu.ratio, 256*menu.ratio, e.scale, white.Alpha(e.iconAlpha))
|
||||
}
|
||||
}
|
||||
|
||||
func (tabs sceneTabs) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, _, leftRight, a, _, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
if state.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, leftRight, "NAVIGATE", h)
|
||||
|
||||
+2
-2
@@ -85,8 +85,8 @@ func (s *sceneWiFi) render() {
|
||||
}
|
||||
|
||||
func (s *sceneWiFi) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
w, h := menu.GetFramebufferSize()
|
||||
menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, _ := hintIcons()
|
||||
|
||||
|
||||
+2
-2
@@ -76,7 +76,7 @@ func drawThumbnail(list *entry, i int, system, gameName string, x, y, w, h, scal
|
||||
}
|
||||
}
|
||||
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
list.children[i].thumbnail,
|
||||
x, y, w, h, scale,
|
||||
color,
|
||||
@@ -91,7 +91,7 @@ func drawSavestateThumbnail(list *entry, i int, path string, x, y, w, h, scale f
|
||||
}
|
||||
}
|
||||
|
||||
vid.DrawImage(
|
||||
menu.DrawImage(
|
||||
list.children[i].thumbnail,
|
||||
x, y, w, h, scale,
|
||||
color,
|
||||
|
||||
@@ -60,7 +60,7 @@ func Display(severity Severity, message string, duration float32) *Notification
|
||||
// DisplayAndLog creates a new notification and also logs the message to stdout.
|
||||
func DisplayAndLog(severity Severity, prefix, message string, vars ...interface{}) *Notification {
|
||||
msg := fmt.Sprintf(message, vars...)
|
||||
if state.Global.Verbose {
|
||||
if state.Verbose {
|
||||
log.Print("[" + prefix + "]: " + msg + "\n")
|
||||
}
|
||||
return Display(severity, msg, Medium)
|
||||
|
||||
@@ -67,7 +67,7 @@ func Test_DisplayAndLog(t *testing.T) {
|
||||
|
||||
Clear()
|
||||
t.Run("Logs to stdout if verbose", func(t *testing.T) {
|
||||
state.Global.Verbose = true
|
||||
state.Verbose = true
|
||||
got := utils.CaptureOutput(func() { DisplayAndLog(Info, "Test", "Joypad #%d loaded with name %s.", 3, "Foo") })
|
||||
want := "[Test]: Joypad #3 loaded with name Foo.\n"
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
@@ -77,7 +77,7 @@ func Test_DisplayAndLog(t *testing.T) {
|
||||
|
||||
Clear()
|
||||
t.Run("Logs nothing if not verbose", func(t *testing.T) {
|
||||
state.Global.Verbose = false
|
||||
state.Verbose = false
|
||||
got := utils.CaptureOutput(func() { DisplayAndLog(Info, "Test", "Joypad #%d loaded with name %s.", 3, "Foo") })
|
||||
want := ""
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
||||
+2
-2
@@ -83,7 +83,7 @@ func (o *Options) Save() error {
|
||||
return err
|
||||
}
|
||||
|
||||
name := utils.FileName(state.Global.CorePath)
|
||||
name := utils.FileName(state.CorePath)
|
||||
fd, err := os.Create(filepath.Join(home, ".ludo", name+".toml"))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -108,7 +108,7 @@ func (o *Options) load() error {
|
||||
return err
|
||||
}
|
||||
|
||||
name := utils.FileName(state.Global.CorePath)
|
||||
name := utils.FileName(state.CorePath)
|
||||
b, err := ioutil.ReadFile(filepath.Join(home, ".ludo", name+".toml"))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -22,7 +22,7 @@ var mutex sync.Mutex
|
||||
func path() string {
|
||||
return filepath.Join(
|
||||
settings.Current.SavefilesDirectory,
|
||||
utils.FileName(state.Global.GamePath) + ".srm")
|
||||
utils.FileName(state.GamePath)+".srm")
|
||||
}
|
||||
|
||||
// SaveSRAM saves the game SRAM to the filesystem
|
||||
@@ -30,12 +30,12 @@ func SaveSRAM() error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if !state.Global.CoreRunning {
|
||||
if !state.CoreRunning {
|
||||
return errors.New("core not running")
|
||||
}
|
||||
|
||||
len := state.Global.Core.GetMemorySize(libretro.MemorySaveRAM)
|
||||
ptr := state.Global.Core.GetMemoryData(libretro.MemorySaveRAM)
|
||||
len := state.Core.GetMemorySize(libretro.MemorySaveRAM)
|
||||
ptr := state.Core.GetMemoryData(libretro.MemorySaveRAM)
|
||||
if ptr == nil || len == 0 {
|
||||
return errors.New("unable to get SRAM address")
|
||||
}
|
||||
@@ -71,12 +71,12 @@ func LoadSRAM() error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if !state.Global.CoreRunning {
|
||||
if !state.CoreRunning {
|
||||
return errors.New("core not running")
|
||||
}
|
||||
|
||||
len := state.Global.Core.GetMemorySize(libretro.MemorySaveRAM)
|
||||
ptr := state.Global.Core.GetMemoryData(libretro.MemorySaveRAM)
|
||||
len := state.Core.GetMemorySize(libretro.MemorySaveRAM)
|
||||
ptr := state.Core.GetMemoryData(libretro.MemorySaveRAM)
|
||||
if ptr == nil || len == 0 {
|
||||
return errors.New("unable to get SRAM address")
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
// Save the current state to the filesystem. name is the name of the
|
||||
// savestate file to save to, without extension.
|
||||
func Save(name string) error {
|
||||
s := state.Global.Core.SerializeSize()
|
||||
bytes, err := state.Global.Core.Serialize(s)
|
||||
s := state.Core.SerializeSize()
|
||||
bytes, err := state.Core.Serialize(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -29,11 +29,11 @@ func Save(name string) error {
|
||||
|
||||
// Load the state from the filesystem
|
||||
func Load(path string) error {
|
||||
s := state.Global.Core.SerializeSize()
|
||||
s := state.Core.SerializeSize()
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = state.Global.Core.Unserialize(bytes, s)
|
||||
err = state.Core.Unserialize(bytes, s)
|
||||
return err
|
||||
}
|
||||
+5
-5
@@ -121,19 +121,19 @@ func Scan(dir string, roms []string, games chan (dat.Game), n *ntf.Notification)
|
||||
n.Update(ntf.Error, err.Error())
|
||||
continue
|
||||
}
|
||||
state.Global.DB.FindByCRC(f, rom.Name, crc, games)
|
||||
state.Global.DB.FindByCRC(f, rom.Name, crcHeaderless, games)
|
||||
state.DB.FindByCRC(f, rom.Name, crc, games)
|
||||
state.DB.FindByCRC(f, rom.Name, crcHeaderless, games)
|
||||
n.Update(ntf.Info, strconv.Itoa(i)+"/"+strconv.Itoa(len(roms))+" "+f)
|
||||
} else if rom.CRC32 > 0 {
|
||||
// Look for a matching game entry in the database
|
||||
state.Global.DB.FindByCRC(f, rom.Name, rom.CRC32, games)
|
||||
state.DB.FindByCRC(f, rom.Name, rom.CRC32, games)
|
||||
n.Update(ntf.Info, strconv.Itoa(i)+"/"+strconv.Itoa(len(roms))+" "+f)
|
||||
}
|
||||
}
|
||||
z.Close()
|
||||
case ".cue":
|
||||
// Look for a matching game entry in the database
|
||||
state.Global.DB.FindByROMName(f, filepath.Base(f), 0, games)
|
||||
state.DB.FindByROMName(f, filepath.Base(f), 0, games)
|
||||
n.Update(ntf.Info, strconv.Itoa(i)+"/"+strconv.Itoa(len(roms))+" "+f)
|
||||
case ".32x", "a52", ".a78", ".col", ".crt", ".d64", ".pce", ".fds", ".gb", ".gba", ".gbc", ".gen", ".gg", ".ipf", ".j64", ".jag", ".lnx", ".md", ".n64", ".nes", ".ngc", ".nds", ".rom", ".sfc", ".sg", ".smc", ".smd", ".sms", ".ws", ".wsc":
|
||||
bytes, err := ioutil.ReadFile(f)
|
||||
@@ -142,7 +142,7 @@ func Scan(dir string, roms []string, games chan (dat.Game), n *ntf.Notification)
|
||||
continue
|
||||
}
|
||||
CRC32 := crc32.ChecksumIEEE(bytes)
|
||||
state.Global.DB.FindByCRC(f, utils.FileName(f), CRC32, games)
|
||||
state.DB.FindByCRC(f, utils.FileName(f), CRC32, games)
|
||||
n.Update(ntf.Info, strconv.Itoa(i)+"/"+strconv.Itoa(len(roms))+" "+f)
|
||||
}
|
||||
}
|
||||
|
||||
+24
-17
@@ -3,26 +3,33 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/libretro/ludo/dat"
|
||||
"github.com/libretro/ludo/libretro"
|
||||
)
|
||||
|
||||
// State is a type for the global state of the app
|
||||
type State struct {
|
||||
Core *libretro.Core // Current libretro core
|
||||
CoreRunning bool // Should be true if a game or a gameless core is loaded
|
||||
MenuActive bool // When set to true, will display the menu layer
|
||||
Verbose bool // When set to true, will output a lots of logs
|
||||
CorePath string // Path of the current libretro core
|
||||
GamePath string // Path of the current game
|
||||
DB dat.DB // The game database loaded on startup
|
||||
LudOS bool // Run Ludo as a unix desktop environment
|
||||
FastForward bool // Run the core as fast as possible
|
||||
// Core is the current libretro core, if any is loaded
|
||||
var Core *libretro.Core
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
// CoreRunning is true if a game or a gameless core is loaded
|
||||
var CoreRunning bool
|
||||
|
||||
// Global state
|
||||
var Global State
|
||||
// MenuActive is whether to display the menu layer
|
||||
var MenuActive bool
|
||||
|
||||
// Verbose will output more logs
|
||||
var Verbose bool
|
||||
|
||||
// CorePath is the path of the current libretro core
|
||||
var CorePath string
|
||||
|
||||
// GamePath is the path of the current game
|
||||
var GamePath string
|
||||
|
||||
// DB is the game database loaded on startup
|
||||
var DB dat.DB
|
||||
|
||||
// LudOS is whether run Ludo as a unix desktop environment
|
||||
var LudOS bool
|
||||
|
||||
// FastForward will run the core as fast as possible
|
||||
var FastForward bool
|
||||
@@ -1,11 +1,7 @@
|
||||
package video
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-gl/glfw/v3.3/glfw"
|
||||
"github.com/libretro/ludo/libretro"
|
||||
)
|
||||
|
||||
func TestXYWHTo4points(t *testing.T) {
|
||||
@@ -71,95 +67,3 @@ func TestXYWHTo4points(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type WindowMock struct{}
|
||||
|
||||
func (m WindowMock) GetFramebufferSize() (width, height int) { return 320, 240 }
|
||||
func (m WindowMock) Destroy() {}
|
||||
func (m WindowMock) MakeContextCurrent() {}
|
||||
func (m WindowMock) SetSizeLimits(minw, minh, maxw, maxh int) {}
|
||||
func (m WindowMock) SetInputMode(mode glfw.InputMode, value int) {}
|
||||
func (m WindowMock) GetKey(key glfw.Key) glfw.Action { return 0 }
|
||||
func (m WindowMock) SetShouldClose(bool) {}
|
||||
func (m WindowMock) ShouldClose() bool { return false }
|
||||
func (m WindowMock) SetTitle(string) {}
|
||||
func (m WindowMock) SwapBuffers() {}
|
||||
|
||||
func TestVideo_vertexArray(t *testing.T) {
|
||||
|
||||
var myWindowMock WindowMock
|
||||
|
||||
type fields struct {
|
||||
Window WindowInterface
|
||||
Geom libretro.GameGeometry
|
||||
Font *Font
|
||||
program uint32
|
||||
roundedProgram uint32
|
||||
borderProgram uint32
|
||||
circleProgram uint32
|
||||
demulProgram uint32
|
||||
vao uint32
|
||||
vbo uint32
|
||||
texID uint32
|
||||
pitch int32
|
||||
pixFmt uint32
|
||||
pixType uint32
|
||||
bpp int32
|
||||
}
|
||||
type args struct {
|
||||
x float32
|
||||
y float32
|
||||
w float32
|
||||
h float32
|
||||
scale float32
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want []float32
|
||||
}{
|
||||
{
|
||||
name: "Works",
|
||||
fields: fields{
|
||||
Window: myWindowMock,
|
||||
},
|
||||
args: args{
|
||||
x: 10,
|
||||
y: 11,
|
||||
w: 300,
|
||||
h: 400,
|
||||
scale: 2,
|
||||
},
|
||||
want: []float32{
|
||||
-0.9375, -5.758333, 0, 1,
|
||||
-0.9375, 0.9083333, 0, 0,
|
||||
2.8125, -5.758333, 1, 1,
|
||||
2.8125, 0.9083333, 1, 0},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
video := &Video{
|
||||
Window: tt.fields.Window,
|
||||
Geom: tt.fields.Geom,
|
||||
Font: tt.fields.Font,
|
||||
program: tt.fields.program,
|
||||
roundedProgram: tt.fields.roundedProgram,
|
||||
borderProgram: tt.fields.borderProgram,
|
||||
circleProgram: tt.fields.circleProgram,
|
||||
demulProgram: tt.fields.demulProgram,
|
||||
vao: tt.fields.vao,
|
||||
vbo: tt.fields.vbo,
|
||||
texID: tt.fields.texID,
|
||||
pitch: tt.fields.pitch,
|
||||
pixFmt: tt.fields.pixFmt,
|
||||
pixType: tt.fields.pixType,
|
||||
bpp: tt.fields.bpp,
|
||||
}
|
||||
if got := video.vertexArray(tt.args.x, tt.args.y, tt.args.w, tt.args.h, tt.args.scale); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Video.vertexArray() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -31,8 +31,8 @@ func (video *Video) renderScreenshot() {
|
||||
|
||||
// TakeScreenshot captures the ouput of video.Render and writes it to a file
|
||||
func (video *Video) TakeScreenshot(name string) error {
|
||||
state.Global.MenuActive = false
|
||||
defer func() { state.Global.MenuActive = true }()
|
||||
state.MenuActive = false
|
||||
defer func() { state.MenuActive = true }()
|
||||
|
||||
gl.UseProgram(video.defaultProgram)
|
||||
|
||||
|
||||
+32
-22
@@ -5,6 +5,7 @@ package video
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gl/gl/v2.1/gl"
|
||||
@@ -14,24 +15,9 @@ import (
|
||||
"github.com/libretro/ludo/state"
|
||||
)
|
||||
|
||||
// WindowInterface lists all the methods from glfw.Window that we are using.
|
||||
// It is there only to allow mocking during tests.
|
||||
type WindowInterface interface {
|
||||
GetFramebufferSize() (width, height int)
|
||||
Destroy()
|
||||
MakeContextCurrent()
|
||||
SetSizeLimits(minw, minh, maxw, maxh int)
|
||||
SetInputMode(mode glfw.InputMode, value int)
|
||||
GetKey(key glfw.Key) glfw.Action
|
||||
SetShouldClose(bool)
|
||||
ShouldClose() bool
|
||||
SetTitle(string)
|
||||
SwapBuffers()
|
||||
}
|
||||
|
||||
// Video holds the state of the video package
|
||||
type Video struct {
|
||||
Window WindowInterface
|
||||
Window *glfw.Window
|
||||
Geom libretro.GameGeometry
|
||||
Font *Font
|
||||
|
||||
@@ -70,6 +56,30 @@ func (video *Video) Reconfigure(fullscreen bool) {
|
||||
video.Configure(fullscreen)
|
||||
}
|
||||
|
||||
// GetFramebufferSize retrieves the size, in pixels, of the framebuffer of the specified window.
|
||||
func (video *Video) GetFramebufferSize() (int, int) {
|
||||
if video.Window == nil {
|
||||
return 0, 0
|
||||
}
|
||||
return video.Window.GetFramebufferSize()
|
||||
}
|
||||
|
||||
// SetTitle sets the window title, encoded as UTF-8, of the window.
|
||||
func (video *Video) SetTitle(title string) {
|
||||
if video.Window == nil {
|
||||
return
|
||||
}
|
||||
video.Window.SetTitle(title)
|
||||
}
|
||||
|
||||
// SetShouldClose sets the value of the close flag of the window.
|
||||
func (video *Video) SetShouldClose(b bool) {
|
||||
if video.Window == nil {
|
||||
return
|
||||
}
|
||||
video.Window.SetShouldClose(b)
|
||||
}
|
||||
|
||||
// Configure instanciates the video package
|
||||
func (video *Video) Configure(fullscreen bool) {
|
||||
var width, height int
|
||||
@@ -107,8 +117,8 @@ func (video *Video) Configure(fullscreen bool) {
|
||||
fbw, fbh := video.Window.GetFramebufferSize()
|
||||
|
||||
// LoadFont (fontfile, font scale, window width, window height)
|
||||
assets := settings.Current.AssetsDirectory
|
||||
video.Font, err = LoadFont(assets+"/font.ttf", int32(36*2), fbw, fbh)
|
||||
fontPath := filepath.Join(settings.Current.AssetsDirectory, "font.ttf")
|
||||
video.Font, err = LoadFont(fontPath, int32(36*2), fbw, fbh)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -180,7 +190,7 @@ func (video *Video) Configure(fullscreen bool) {
|
||||
gl.GenTextures(1, &video.texID)
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
if video.texID == 0 && state.Global.Verbose {
|
||||
if video.texID == 0 && state.Verbose {
|
||||
log.Println("[Video]: Failed to create the vid texture")
|
||||
}
|
||||
|
||||
@@ -233,7 +243,7 @@ func (video *Video) UpdateFilter(filter string) {
|
||||
// SetPixelFormat is a callback passed to the libretro implementation.
|
||||
// It allows the core or the game to tell us which pixel format should be used for the display.
|
||||
func (video *Video) SetPixelFormat(format uint32) bool {
|
||||
if state.Global.Verbose {
|
||||
if state.Verbose {
|
||||
log.Printf("[Video]: Set Pixel Format: %v\n", format)
|
||||
}
|
||||
|
||||
@@ -315,7 +325,7 @@ func (video *Video) ResizeViewport() {
|
||||
|
||||
// Render the current frame
|
||||
func (video *Video) Render() {
|
||||
if !state.Global.CoreRunning {
|
||||
if !state.CoreRunning {
|
||||
gl.ClearColor(1, 1, 1, 1)
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||
return
|
||||
@@ -367,7 +377,7 @@ func (video *Video) SetRotation(rot uint) bool {
|
||||
// limit to valid values (0, 1, 2, 3, which rotates screen by 0, 90, 180 270 degrees counter-clockwise)
|
||||
video.rot = rot % 4
|
||||
|
||||
if state.Global.Verbose {
|
||||
if state.Verbose {
|
||||
log.Printf("[Video]: Set Rotation: %v", video.rot)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user