mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-02 14:04:28 +01:00
ui: Add SetWindowResizable
This change also fixes example/windowsize. Fixes #320
This commit is contained in:
parent
4aa80de34d
commit
049aa552d4
@ -50,11 +50,14 @@ var (
|
|||||||
// * ebiten.RunGame
|
// * ebiten.RunGame
|
||||||
// * ebiten.SetWindowSize
|
// * ebiten.SetWindowSize
|
||||||
// * ebiten.WindowSize
|
// * ebiten.WindowSize
|
||||||
|
//
|
||||||
|
// A resizable window is available only when flagLegacy is false.
|
||||||
flagLegacy = flag.Bool("legacy", false, "use the legacy API")
|
flagLegacy = flag.Bool("legacy", false, "use the legacy API")
|
||||||
|
|
||||||
flagFullscreen = flag.Bool("fullscreen", false, "fullscreen")
|
flagFullscreen = flag.Bool("fullscreen", false, "fullscreen")
|
||||||
flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)")
|
flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)")
|
||||||
flagScreenTransparent = flag.Bool("screentransparent", false, "screen transparent")
|
flagScreenTransparent = flag.Bool("screentransparent", false, "screen transparent")
|
||||||
|
flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -98,6 +101,10 @@ type game struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||||
|
if *flagAutoAdjusting {
|
||||||
|
g.width, g.height = outsideWidth, outsideHeight
|
||||||
|
return outsideWidth, outsideHeight
|
||||||
|
}
|
||||||
// Ignore the outside size. This means that the offscreen is not adjusted with the outside world.
|
// Ignore the outside size. This means that the offscreen is not adjusted with the outside world.
|
||||||
return g.width, g.height
|
return g.width, g.height
|
||||||
}
|
}
|
||||||
@ -114,9 +121,8 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
} else {
|
} else {
|
||||||
screenWidth = g.width
|
screenWidth = g.width
|
||||||
screenHeight = g.height
|
screenHeight = g.height
|
||||||
ww, _ := ebiten.WindowSize()
|
if ww, wh := ebiten.WindowSize(); ww > 0 && wh > 0 {
|
||||||
if ww > 0 {
|
screenScale = math.Min(float64(ww)/float64(g.width), float64(wh)/float64(g.height))
|
||||||
screenScale = float64(ww) / float64(g.width)
|
|
||||||
} else {
|
} else {
|
||||||
// ebiten.WindowSize can return (0, 0) on browsers or mobiles.
|
// ebiten.WindowSize can return (0, 0) on browsers or mobiles.
|
||||||
screenScale = 1
|
screenScale = 1
|
||||||
@ -131,24 +137,30 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
decorated := ebiten.IsWindowDecorated()
|
decorated := ebiten.IsWindowDecorated()
|
||||||
positionX, positionY := ebiten.WindowPosition()
|
positionX, positionY := ebiten.WindowPosition()
|
||||||
transparent := ebiten.IsScreenTransparent()
|
transparent := ebiten.IsScreenTransparent()
|
||||||
|
resizable := ebiten.IsWindowResizable()
|
||||||
|
|
||||||
const d = 16
|
const d = 16
|
||||||
|
toUpdateWindowSize := false
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyShift) {
|
if ebiten.IsKeyPressed(ebiten.KeyShift) {
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
|
||||||
screenHeight += d
|
screenHeight += d
|
||||||
|
toUpdateWindowSize = true
|
||||||
}
|
}
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
|
||||||
if 16 < screenHeight && d < screenHeight {
|
if 16 < screenHeight && d < screenHeight {
|
||||||
screenHeight -= d
|
screenHeight -= d
|
||||||
|
toUpdateWindowSize = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {
|
||||||
if 16 < screenWidth && d < screenWidth {
|
if 16 < screenWidth && d < screenWidth {
|
||||||
screenWidth -= d
|
screenWidth -= d
|
||||||
|
toUpdateWindowSize = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyRight) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyRight) {
|
||||||
screenWidth += d
|
screenWidth += d
|
||||||
|
toUpdateWindowSize = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
|
||||||
@ -164,19 +176,18 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
positionX += d
|
positionX += d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyS) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyS) && !*flagAutoAdjusting {
|
||||||
switch screenScale {
|
switch {
|
||||||
case 0.75:
|
case screenScale < 1:
|
||||||
screenScale = 1
|
screenScale = 1
|
||||||
case 1:
|
case screenScale < 1.5:
|
||||||
screenScale = 1.5
|
screenScale = 1.5
|
||||||
case 1.5:
|
case screenScale < 2:
|
||||||
screenScale = 2
|
screenScale = 2
|
||||||
case 2:
|
|
||||||
screenScale = 0.75
|
|
||||||
default:
|
default:
|
||||||
panic("not reached")
|
screenScale = 0.75
|
||||||
}
|
}
|
||||||
|
toUpdateWindowSize = true
|
||||||
}
|
}
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyF) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyF) {
|
||||||
fullscreen = !fullscreen
|
fullscreen = !fullscreen
|
||||||
@ -207,14 +218,19 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
if inpututil.IsKeyJustPressed(ebiten.KeyD) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyD) {
|
||||||
decorated = !decorated
|
decorated = !decorated
|
||||||
}
|
}
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyR) {
|
||||||
|
resizable = !resizable
|
||||||
|
}
|
||||||
|
|
||||||
if *flagLegacy {
|
if toUpdateWindowSize {
|
||||||
ebiten.SetScreenSize(screenWidth, screenHeight)
|
if *flagLegacy {
|
||||||
ebiten.SetScreenScale(screenScale)
|
ebiten.SetScreenSize(screenWidth, screenHeight)
|
||||||
} else {
|
ebiten.SetScreenScale(screenScale)
|
||||||
g.width = screenWidth
|
} else {
|
||||||
g.height = screenHeight
|
g.width = screenWidth
|
||||||
ebiten.SetWindowSize(int(float64(screenWidth)*screenScale), int(float64(screenHeight)*screenScale))
|
g.height = screenHeight
|
||||||
|
ebiten.SetWindowSize(int(float64(screenWidth)*screenScale), int(float64(screenHeight)*screenScale))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ebiten.SetFullscreen(fullscreen)
|
ebiten.SetFullscreen(fullscreen)
|
||||||
ebiten.SetRunnableInBackground(runnableInBackground)
|
ebiten.SetRunnableInBackground(runnableInBackground)
|
||||||
@ -223,6 +239,10 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
ebiten.SetMaxTPS(tps)
|
ebiten.SetMaxTPS(tps)
|
||||||
ebiten.SetWindowDecorated(decorated)
|
ebiten.SetWindowDecorated(decorated)
|
||||||
ebiten.SetWindowPosition(positionX, positionY)
|
ebiten.SetWindowPosition(positionX, positionY)
|
||||||
|
if !*flagLegacy {
|
||||||
|
// A resizable window is available only with RunGame.
|
||||||
|
ebiten.SetWindowResizable(resizable)
|
||||||
|
}
|
||||||
|
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyI) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyI) {
|
||||||
ebiten.SetWindowIcon([]image.Image{createRandomIconImage()})
|
ebiten.SetWindowIcon([]image.Image{createRandomIconImage()})
|
||||||
@ -252,21 +272,29 @@ func (g *game) Update(screen *ebiten.Image) error {
|
|||||||
if t := ebiten.MaxTPS(); t != ebiten.UncappedTPS {
|
if t := ebiten.MaxTPS(); t != ebiten.UncappedTPS {
|
||||||
tpsStr = fmt.Sprintf("%d", t)
|
tpsStr = fmt.Sprintf("%d", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msgS string
|
||||||
|
var msgR string
|
||||||
|
if *flagLegacy {
|
||||||
|
msgS = "Press S key to change the window scale (only for desktops)\n"
|
||||||
|
} else {
|
||||||
|
msgR = "Press R key to switch the window resizable state (only for desktops)\n"
|
||||||
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf(`Press arrow keys to move the window
|
msg := fmt.Sprintf(`Press arrow keys to move the window
|
||||||
Press shift + arrow keys to change the window size
|
Press shift + arrow keys to change the window size
|
||||||
Press S key to change the window scale (only for desktops)
|
%sPress F key to switch the fullscreen state (only for desktops)
|
||||||
Press F key to switch the fullscreen state (only for desktops)
|
|
||||||
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 (only for desktops)
|
Press I key to change the window icon (only for desktops)
|
||||||
Press V key to switch vsync
|
Press V key to switch vsync
|
||||||
Press T key to switch TPS (ticks per second)
|
Press T key to switch TPS (ticks per second)
|
||||||
Press D key to switch the window decoration
|
Press D key to switch the window decoration (only for desktops)
|
||||||
Windows Position: (%d, %d)
|
%sWindows Position: (%d, %d)
|
||||||
Cursor: (%d, %d)
|
Cursor: (%d, %d)
|
||||||
TPS: Current: %0.2f / Max: %s
|
TPS: Current: %0.2f / Max: %s
|
||||||
FPS: %0.2f
|
FPS: %0.2f
|
||||||
Device Scale Factor: %0.2f`, wx, wy, cx, cy, ebiten.CurrentTPS(), tpsStr, ebiten.CurrentFPS(), ebiten.DeviceScaleFactor())
|
Device Scale Factor: %0.2f`, msgS, msgR, wx, wy, cx, cy, ebiten.CurrentTPS(), tpsStr, ebiten.CurrentFPS(), ebiten.DeviceScaleFactor())
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
ebitenutil.DebugPrint(screen, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -295,6 +323,10 @@ func main() {
|
|||||||
w, h := ebiten.ScreenSizeInFullscreen()
|
w, h := ebiten.ScreenSizeInFullscreen()
|
||||||
fmt.Printf("Screen size in fullscreen: %d, %d\n", w, h)
|
fmt.Printf("Screen size in fullscreen: %d, %d\n", w, h)
|
||||||
|
|
||||||
|
if !*flagLegacy {
|
||||||
|
fmt.Println("Tip: With -autoadjusting flag, you can make an adjustable game screen.")
|
||||||
|
}
|
||||||
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
// Decode image from a byte slice instead of a file so that
|
||||||
// this example works in any working directory.
|
// this example works in any working directory.
|
||||||
// If you want to use a file, there are some options:
|
// If you want to use a file, there are some options:
|
||||||
@ -325,6 +357,12 @@ func main() {
|
|||||||
if *flagFullscreen {
|
if *flagFullscreen {
|
||||||
ebiten.SetFullscreen(true)
|
ebiten.SetFullscreen(true)
|
||||||
}
|
}
|
||||||
|
if *flagAutoAdjusting {
|
||||||
|
if *flagLegacy {
|
||||||
|
log.Println("-autoadjusting flag cannot work with -legacy flag")
|
||||||
|
}
|
||||||
|
ebiten.SetWindowResizable(true)
|
||||||
|
}
|
||||||
|
|
||||||
const title = "Window Size (Ebiten Demo)"
|
const title = "Window Size (Ebiten Demo)"
|
||||||
if *flagLegacy {
|
if *flagLegacy {
|
||||||
|
@ -552,10 +552,14 @@ func (u *UserInterface) SetWindowResizable(resizable bool) {
|
|||||||
u.setInitWindowResizable(resizable)
|
u.setInitWindowResizable(resizable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
_ = u.t.Call(func() error {
|
||||||
panic("glfw: SetWindowResizable can't be called after the main loop so far.")
|
v := glfw.False
|
||||||
|
if resizable {
|
||||||
// TODO: Now SetAttrib doesn't exist on GLFW 3.2. Revisit later (#556).
|
v = glfw.True
|
||||||
|
}
|
||||||
|
u.window.SetAttrib(glfw.Resizable, v)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) DeviceScaleFactor() float64 {
|
func (u *UserInterface) DeviceScaleFactor() float64 {
|
||||||
|
3
run.go
3
run.go
@ -153,6 +153,9 @@ func IsRunningSlowly() bool {
|
|||||||
//
|
//
|
||||||
// Don't call Run twice or more in one process.
|
// Don't call Run twice or more in one process.
|
||||||
func Run(f func(*Image) error, width, height int, scale float64, title string) error {
|
func Run(f func(*Image) error, width, height int, scale float64, title string) error {
|
||||||
|
if IsWindowResizable() {
|
||||||
|
panic("ebiten: a resizable window works with RunGame, not Run")
|
||||||
|
}
|
||||||
game := &defaultGame{
|
game := &defaultGame{
|
||||||
update: (&imageDumper{f: f}).update,
|
update: (&imageDumper{f: f}).update,
|
||||||
width: width,
|
width: width,
|
||||||
|
12
uicontext.go
12
uicontext.go
@ -184,6 +184,18 @@ func (c *uiContext) updateOffscreen() {
|
|||||||
// scale. This is fine since ebiten.ScreenScale will be deprecated.
|
// scale. This is fine since ebiten.ScreenScale will be deprecated.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *uiContext) setWindowResizable(resizable bool) {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
if resizable && c.game != nil {
|
||||||
|
if _, ok := c.game.(*defaultGame); ok {
|
||||||
|
panic("ebiten: a resizable window works with RunGame, not Run")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uiDriver().SetWindowResizable(resizable)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *uiContext) screenScale() float64 {
|
func (c *uiContext) screenScale() float64 {
|
||||||
if c.offscreen == nil {
|
if c.offscreen == nil {
|
||||||
return 0
|
return 0
|
||||||
|
13
window.go
13
window.go
@ -62,13 +62,24 @@ func setWindowResizable(resizable bool) {
|
|||||||
uiDriver().SetWindowResizable(resizable)
|
uiDriver().SetWindowResizable(resizable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWindowResizable reports whether the window is resizable.
|
// IsWindowResizable reports whether the window is resizable by the user's dragging on desktops.
|
||||||
|
// On the other environments, IsWindowResizable always returns false.
|
||||||
//
|
//
|
||||||
// IsWindowResizable is concurrent-safe.
|
// IsWindowResizable is concurrent-safe.
|
||||||
func IsWindowResizable() bool {
|
func IsWindowResizable() bool {
|
||||||
return uiDriver().IsWindowResizable()
|
return uiDriver().IsWindowResizable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetWindowResizable sets whether the window is resizable by the user's dragging on desktops.
|
||||||
|
// On the other environments, SetWindowResizable does nothing.
|
||||||
|
//
|
||||||
|
// If SetWindowResizable is called with true and Run is used, SetWindowResizable panics. Use RunGame instead.
|
||||||
|
//
|
||||||
|
// SetWindowResizable is concurrent-safe.
|
||||||
|
func SetWindowResizable(resizable bool) {
|
||||||
|
theUIContext.setWindowResizable(resizable)
|
||||||
|
}
|
||||||
|
|
||||||
// SetWindowTitle sets the title of the window.
|
// SetWindowTitle sets the title of the window.
|
||||||
//
|
//
|
||||||
// SetWindowTitle does nothing on mobiles.
|
// SetWindowTitle does nothing on mobiles.
|
||||||
|
Loading…
Reference in New Issue
Block a user