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:
Jean-André Santoni authored and GitHub committed 2021-05-14 19:53:47 +07:00
1 parent d201e5321d
commit b83eff4369
34 files changed
+373 -485

No files matched your search

+30 -30
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+22 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+6 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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
View File
@@ -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
+7 -7
View File
@@ -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")
}
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
-96
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}