ui: Add SetIcon (#386)

This commit is contained in:
Hajime Hoshi 2017-09-23 04:12:02 +09:00
parent d97331ef04
commit dacda0d176
5 changed files with 98 additions and 0 deletions

View File

@ -18,15 +18,22 @@ package main
import ( import (
"fmt" "fmt"
"image"
"image/color" "image/color"
_ "image/jpeg" _ "image/jpeg"
"log" "log"
"math" "math"
"math/rand"
"time"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil" "github.com/hajimehoshi/ebiten/ebitenutil"
) )
func init() {
rand.Seed(time.Now().UnixNano())
}
const ( const (
initScreenWidth = 320 initScreenWidth = 320
initScreenHeight = 240 initScreenHeight = 240
@ -44,10 +51,30 @@ var (
ebiten.KeyF: 0, ebiten.KeyF: 0,
ebiten.KeyB: 0, ebiten.KeyB: 0,
ebiten.KeyC: 0, ebiten.KeyC: 0,
ebiten.KeyI: 0,
} }
count = 0 count = 0
) )
func createRandomIconImage() image.Image {
const size = 32
r := uint8(rand.Intn(0x100))
g := uint8(rand.Intn(0x100))
b := uint8(rand.Intn(0x100))
img := image.NewNRGBA(image.Rect(0, 0, size, size))
for j := 0; j < size; j++ {
for i := 0; i < size; i++ {
img.Pix[j*img.Stride+4*i] = r
img.Pix[j*img.Stride+4*i+1] = g
img.Pix[j*img.Stride+4*i+2] = b
img.Pix[j*img.Stride+4*i+3] = uint8(float64(i+j) / float64(2*size) * 0xff)
}
}
return img
}
func update(screen *ebiten.Image) error { func update(screen *ebiten.Image) error {
for key := range keyStates { for key := range keyStates {
if !ebiten.IsKeyPressed(key) { if !ebiten.IsKeyPressed(key) {
@ -106,6 +133,10 @@ func update(screen *ebiten.Image) error {
ebiten.SetRunnableInBackground(runnableInBackground) ebiten.SetRunnableInBackground(runnableInBackground)
ebiten.SetCursorVisibility(cursorVisible) ebiten.SetCursorVisibility(cursorVisible)
if keyStates[ebiten.KeyI] == 1 {
ebiten.SetIcon([]image.Image{createRandomIconImage()})
}
count++ count++
if ebiten.IsRunningSlowly() { if ebiten.IsRunningSlowly() {
@ -128,6 +159,7 @@ Press S key to change the window scale
Press F key to switch the fullscreen state Press F key to switch the fullscreen state
Press B key to switch the run-in-background state Press B key to switch the run-in-background state
Press C key to switch the cursor visibility Press C key to switch the cursor visibility
Press I key to change the window icon
Cursor: (%d, %d) Cursor: (%d, %d)
FPS: %0.2f`, x, y, ebiten.CurrentFPS()) FPS: %0.2f`, x, y, ebiten.CurrentFPS())
ebitenutil.DebugPrint(screen, msg) ebitenutil.DebugPrint(screen, msg)
@ -140,6 +172,9 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
ebiten.SetIcon([]image.Image{createRandomIconImage()})
if err := ebiten.Run(update, initScreenWidth, initScreenHeight, initScreenScale, "Window Size (Ebiten Demo)"); err != nil { if err := ebiten.Run(update, initScreenWidth, initScreenHeight, initScreenScale, "Window Size (Ebiten Demo)"); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -21,6 +21,7 @@ package ui
import ( import (
"errors" "errors"
"image"
"runtime" "runtime"
"sync" "sync"
"time" "time"
@ -45,6 +46,7 @@ type userInterface struct {
origPosY int origPosY int
initFullscreen bool initFullscreen bool
initCursorVisible bool initCursorVisible bool
initIconImages []image.Image
runnableInBackground bool runnableInBackground bool
m sync.Mutex m sync.Mutex
} }
@ -87,6 +89,9 @@ func initialize() error {
if !currentUI.isInitCursorVisible() { if !currentUI.isInitCursorVisible() {
mode = glfw.CursorHidden mode = glfw.CursorHidden
} }
if i := currentUI.getInitIconImages(); i != nil {
currentUI.window.SetIcon(i)
}
currentUI.window.SetInputMode(glfw.CursorMode, mode) currentUI.window.SetInputMode(glfw.CursorMode, mode)
currentUI.window.SetInputMode(glfw.StickyMouseButtonsMode, glfw.True) currentUI.window.SetInputMode(glfw.StickyMouseButtonsMode, glfw.True)
currentUI.window.SetInputMode(glfw.StickyKeysMode, glfw.True) currentUI.window.SetInputMode(glfw.StickyKeysMode, glfw.True)
@ -169,6 +174,19 @@ func (u *userInterface) setRunnableInBackground(runnableInBackground bool) {
u.m.Unlock() u.m.Unlock()
} }
func (u *userInterface) getInitIconImages() []image.Image {
u.m.Lock()
i := u.initIconImages
u.m.Unlock()
return i
}
func (u *userInterface) setInitIconImages(iconImages []image.Image) {
u.m.Lock()
u.initIconImages = iconImages
u.m.Unlock()
}
func (u *userInterface) runOnMainThread(f func() error) error { func (u *userInterface) runOnMainThread(f func() error) error {
if u.funcs == nil { if u.funcs == nil {
// already closed // already closed
@ -259,6 +277,17 @@ func IsRunnableInBackground() bool {
return currentUI.isRunnableInBackground() return currentUI.isRunnableInBackground()
} }
func SetIcon(iconImages []image.Image) {
if !currentUI.isRunning() {
currentUI.setInitIconImages(iconImages)
return
}
_ = currentUI.runOnMainThread(func() error {
currentUI.window.SetIcon(iconImages)
return nil
})
}
func ScreenOffset() (float64, float64) { func ScreenOffset() (float64, float64) {
u := currentUI u := currentUI
if !u.isRunning() { if !u.isRunning() {

View File

@ -17,6 +17,7 @@
package ui package ui
import ( import (
"image"
"strconv" "strconv"
"unicode" "unicode"
@ -97,6 +98,10 @@ func SetCursorVisibility(visibility bool) {
} }
} }
func SetIcon(iconImages []image.Image) {
// Do nothing
}
func (u *userInterface) getScale() float64 { func (u *userInterface) getScale() float64 {
if !u.fullscreen { if !u.fullscreen {
return u.scale return u.scale

View File

@ -18,6 +18,7 @@ package ui
import ( import (
"errors" "errors"
"image"
"runtime" "runtime"
"time" "time"
@ -140,6 +141,10 @@ func IsRunnableInBackground() bool {
return false return false
} }
func SetIcon(iconImages []image.Image) {
// Do nothing
}
func (u *userInterface) actualScreenScale() float64 { func (u *userInterface) actualScreenScale() float64 {
return u.scale * deviceScale() return u.scale * deviceScale()
} }

24
run.go
View File

@ -15,6 +15,7 @@
package ebiten package ebiten
import ( import (
"image"
"sync/atomic" "sync/atomic"
"github.com/hajimehoshi/ebiten/internal/clock" "github.com/hajimehoshi/ebiten/internal/clock"
@ -245,3 +246,26 @@ func IsRunnableInBackground() bool {
func SetRunnableInBackground(runnableInBackground bool) { func SetRunnableInBackground(runnableInBackground bool) {
ui.SetRunnableInBackground(runnableInBackground) ui.SetRunnableInBackground(runnableInBackground)
} }
// SetIcon sets the icon of the game window.
//
// If len(iconImages) is 0, SetIcon reverts the icon to the default one.
//
// For desktops, see the document of glfwSetWindowIcon of GLFW 3.2:
//
// This function sets the icon of the specified window.
// If passed an array of candidate images, those of or closest to the sizes
// desired by the system are selected.
// If no images are specified, the window reverts to its default icon.
//
// The desired image sizes varies depending on platform and system settings.
// The selected images will be rescaled as needed. Good sizes include 16x16, 32x32 and 48x48.
//
// As macOS windows don't have icons, SetIcon doesn't work on macOS.
//
// SetIcon doesn't work on browsers or mobiles.
//
// This function is concurrent-safe.
func SetIcon(iconImages []image.Image) {
ui.SetIcon(iconImages)
}