mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
uidriver/glfw: Reduce (*thread).Call at (*Input).update
This commit is contained in:
parent
495b2b722a
commit
1864c22ad6
@ -22,7 +22,9 @@ import (
|
|||||||
type UIContext interface {
|
type UIContext interface {
|
||||||
Update() error
|
Update() error
|
||||||
Layout(outsideWidth, outsideHeight float64)
|
Layout(outsideWidth, outsideHeight float64)
|
||||||
AdjustPosition(x, y float64) (float64, float64)
|
|
||||||
|
// AdjustPosition can be called from a different goroutine from Update's or Layout's.
|
||||||
|
AdjustPosition(x, y float64, deviceScaleFactor float64) (float64, float64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegularTermination represents a regular termination.
|
// RegularTermination represents a regular termination.
|
||||||
|
@ -308,81 +308,73 @@ func (i *Input) setWheel(xoff, yoff float64) {
|
|||||||
i.scrollY = yoff
|
i.scrollY = yoff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update must be called from the main thread.
|
||||||
func (i *Input) update(window *glfw.Window, context driver.UIContext) {
|
func (i *Input) update(window *glfw.Window, context driver.UIContext) {
|
||||||
var cx, cy float64
|
i.onceCallback.Do(func() {
|
||||||
_ = i.ui.t.Call(func() error {
|
window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
|
||||||
i.onceCallback.Do(func() {
|
i.appendRuneBuffer(char)
|
||||||
window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
|
})
|
||||||
i.appendRuneBuffer(char)
|
window.SetScrollCallback(func(w *glfw.Window, xoff float64, yoff float64) {
|
||||||
})
|
i.setWheel(xoff, yoff)
|
||||||
window.SetScrollCallback(func(w *glfw.Window, xoff float64, yoff float64) {
|
|
||||||
i.setWheel(xoff, yoff)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
if i.keyPressed == nil {
|
|
||||||
i.keyPressed = map[glfw.Key]bool{}
|
|
||||||
}
|
|
||||||
for gk := range glfwKeyToDriverKey {
|
|
||||||
i.keyPressed[gk] = window.GetKey(gk) == glfw.Press
|
|
||||||
}
|
|
||||||
if i.mouseButtonPressed == nil {
|
|
||||||
i.mouseButtonPressed = map[glfw.MouseButton]bool{}
|
|
||||||
}
|
|
||||||
for gb := range glfwMouseButtonToMouseButton {
|
|
||||||
i.mouseButtonPressed[gb] = window.GetMouseButton(gb) == glfw.Press
|
|
||||||
}
|
|
||||||
cx, cy = window.GetCursorPos()
|
|
||||||
// TODO: This is tricky. Rename the function?
|
|
||||||
cx = i.ui.fromGLFWMonitorPixel(cx)
|
|
||||||
cy = i.ui.fromGLFWMonitorPixel(cy)
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
if i.keyPressed == nil {
|
||||||
|
i.keyPressed = map[glfw.Key]bool{}
|
||||||
|
}
|
||||||
|
for gk := range glfwKeyToDriverKey {
|
||||||
|
i.keyPressed[gk] = window.GetKey(gk) == glfw.Press
|
||||||
|
}
|
||||||
|
if i.mouseButtonPressed == nil {
|
||||||
|
i.mouseButtonPressed = map[glfw.MouseButton]bool{}
|
||||||
|
}
|
||||||
|
for gb := range glfwMouseButtonToMouseButton {
|
||||||
|
i.mouseButtonPressed[gb] = window.GetMouseButton(gb) == glfw.Press
|
||||||
|
}
|
||||||
|
cx, cy := window.GetCursorPos()
|
||||||
|
// TODO: This is tricky. Rename the function?
|
||||||
|
cx = i.ui.fromGLFWMonitorPixel(cx)
|
||||||
|
cy = i.ui.fromGLFWMonitorPixel(cy)
|
||||||
|
cx, cy = context.AdjustPosition(cx, cy, i.ui.deviceScaleFactor())
|
||||||
|
i.cursorX, i.cursorY = int(cx), int(cy)
|
||||||
|
|
||||||
cx, cy = context.AdjustPosition(cx, cy)
|
for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
|
||||||
|
i.gamepads[id].valid = false
|
||||||
|
if !id.Present() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
_ = i.ui.t.Call(func() error {
|
buttons := id.GetButtons()
|
||||||
i.cursorX, i.cursorY = int(cx), int(cy)
|
|
||||||
|
|
||||||
for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
|
// A gamepad can be detected even though there are not. Apparently, some special devices are
|
||||||
i.gamepads[id].valid = false
|
// recognized as gamepads by GLFW. In this case, the number of the 'buttons' can exceeds the
|
||||||
if !id.Present() {
|
// maximum. Skip such devices as a tentative solution (#1173).
|
||||||
|
if len(buttons) > driver.GamepadButtonNum {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
i.gamepads[id].valid = true
|
||||||
|
|
||||||
|
i.gamepads[id].buttonNum = len(buttons)
|
||||||
|
for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
|
||||||
|
if len(buttons) <= b {
|
||||||
|
i.gamepads[id].buttonPressed[b] = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
i.gamepads[id].buttonPressed[b] = glfw.Action(buttons[b]) == glfw.Press
|
||||||
|
}
|
||||||
|
|
||||||
buttons := id.GetButtons()
|
axes32 := id.GetAxes()
|
||||||
|
i.gamepads[id].axisNum = len(axes32)
|
||||||
// A gamepad can be detected even though there are not. Apparently, some special devices are
|
for a := 0; a < len(i.gamepads[id].axes); a++ {
|
||||||
// recognized as gamepads by GLFW. In this case, the number of the 'buttons' can exceeds the
|
if len(axes32) <= a {
|
||||||
// maximum. Skip such devices as a tentative solution (#1173).
|
i.gamepads[id].axes[a] = 0
|
||||||
if len(buttons) > driver.GamepadButtonNum {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
i.gamepads[id].axes[a] = float64(axes32[a])
|
||||||
i.gamepads[id].valid = true
|
|
||||||
|
|
||||||
i.gamepads[id].buttonNum = len(buttons)
|
|
||||||
for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
|
|
||||||
if len(buttons) <= b {
|
|
||||||
i.gamepads[id].buttonPressed[b] = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i.gamepads[id].buttonPressed[b] = glfw.Action(buttons[b]) == glfw.Press
|
|
||||||
}
|
|
||||||
|
|
||||||
axes32 := id.GetAxes()
|
|
||||||
i.gamepads[id].axisNum = len(axes32)
|
|
||||||
for a := 0; a < len(i.gamepads[id].axes); a++ {
|
|
||||||
if len(axes32) <= a {
|
|
||||||
i.gamepads[id].axes[a] = 0
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i.gamepads[id].axes[a] = float64(axes32[a])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that GLFW's gamepad GUID follows SDL's GUID.
|
|
||||||
i.gamepads[id].guid = id.GetGUID()
|
|
||||||
i.gamepads[id].name = id.GetName()
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
})
|
// Note that GLFW's gamepad GUID follows SDL's GUID.
|
||||||
|
i.gamepads[id].guid = id.GetGUID()
|
||||||
|
i.gamepads[id].name = id.GetName()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,12 +834,9 @@ func (u *UserInterface) update() error {
|
|||||||
|
|
||||||
_ = u.t.Call(func() error {
|
_ = u.t.Call(func() error {
|
||||||
glfw.PollEvents()
|
glfw.PollEvents()
|
||||||
return nil
|
u.input.update(u.window, u.context)
|
||||||
})
|
|
||||||
u.input.update(u.window, u.context)
|
|
||||||
_ = u.t.Call(func() error {
|
|
||||||
defer hooks.ResumeAudio()
|
|
||||||
|
|
||||||
|
defer hooks.ResumeAudio()
|
||||||
for !u.isRunnableOnUnfocused() && u.window.GetAttrib(glfw.Focused) == 0 && !u.window.ShouldClose() {
|
for !u.isRunnableOnUnfocused() && u.window.GetAttrib(glfw.Focused) == 0 && !u.window.ShouldClose() {
|
||||||
hooks.SuspendAudio()
|
hooks.SuspendAudio()
|
||||||
// Wait for an arbitrary period to avoid busy loop.
|
// Wait for an arbitrary period to avoid busy loop.
|
||||||
|
@ -52,7 +52,7 @@ type Input struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) CursorPosition() (x, y int) {
|
func (i *Input) CursorPosition() (x, y int) {
|
||||||
xf, yf := i.ui.context.AdjustPosition(float64(i.cursorX), float64(i.cursorY))
|
xf, yf := i.ui.context.AdjustPosition(float64(i.cursorX), float64(i.cursorY), i.ui.DeviceScaleFactor())
|
||||||
return int(xf), int(yf)
|
return int(xf), int(yf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +131,10 @@ func (i *Input) TouchIDs() []driver.TouchID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
|
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
|
||||||
|
d := i.ui.DeviceScaleFactor()
|
||||||
for tid, pos := range i.touches {
|
for tid, pos := range i.touches {
|
||||||
if id == tid {
|
if id == tid {
|
||||||
x, y := i.ui.context.AdjustPosition(float64(pos.X), float64(pos.Y))
|
x, y := i.ui.context.AdjustPosition(float64(pos.X), float64(pos.Y), d)
|
||||||
return int(x), int(y)
|
return int(x), int(y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ func (u *UserInterface) setGBuildSize(widthPx, heightPx int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) adjustPosition(x, y int) (int, int) {
|
func (u *UserInterface) adjustPosition(x, y int) (int, int) {
|
||||||
xf, yf := u.context.AdjustPosition(float64(x), float64(y))
|
xf, yf := u.context.AdjustPosition(float64(x), float64(y), deviceScale())
|
||||||
return int(xf), int(yf)
|
return int(xf), int(yf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
uicontext.go
29
uicontext.go
@ -112,27 +112,27 @@ func (c *uiContext) setWindowResizable(resizable bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *uiContext) screenScale() float64 {
|
func (c *uiContext) screenScale(deviceScaleFactor float64) float64 {
|
||||||
if c.offscreen == nil {
|
if c.offscreen == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
sw, sh := c.offscreen.Size()
|
sw, sh := c.offscreen.Size()
|
||||||
d := uiDriver().DeviceScaleFactor()
|
scaleX := c.outsideWidth / float64(sw) * deviceScaleFactor
|
||||||
scaleX := c.outsideWidth / float64(sw) * d
|
scaleY := c.outsideHeight / float64(sh) * deviceScaleFactor
|
||||||
scaleY := c.outsideHeight / float64(sh) * d
|
|
||||||
return math.Min(scaleX, scaleY)
|
return math.Min(scaleX, scaleY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *uiContext) offsets() (float64, float64) {
|
func (c *uiContext) offsets(deviceScaleFactor float64) (float64, float64) {
|
||||||
if c.offscreen == nil {
|
if c.offscreen == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
sw, sh := c.offscreen.Size()
|
sw, sh := c.offscreen.Size()
|
||||||
d := uiDriver().DeviceScaleFactor()
|
s := c.screenScale(deviceScaleFactor)
|
||||||
s := c.screenScale()
|
|
||||||
width := float64(sw) * s
|
width := float64(sw) * s
|
||||||
height := float64(sh) * s
|
height := float64(sh) * s
|
||||||
return (c.outsideWidth*d - width) / 2, (c.outsideHeight*d - height) / 2
|
x := (c.outsideWidth*deviceScaleFactor - width) / 2
|
||||||
|
y := (c.outsideHeight*deviceScaleFactor - height) / 2
|
||||||
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *uiContext) Update() error {
|
func (c *uiContext) Update() error {
|
||||||
@ -185,7 +185,7 @@ func (c *uiContext) update() error {
|
|||||||
|
|
||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
|
|
||||||
s := c.screenScale()
|
s := c.screenScale(uiDriver().DeviceScaleFactor())
|
||||||
switch vd := uiDriver().Graphics().FramebufferYDirection(); vd {
|
switch vd := uiDriver().Graphics().FramebufferYDirection(); vd {
|
||||||
case driver.Upward:
|
case driver.Upward:
|
||||||
op.GeoM.Scale(s, -s)
|
op.GeoM.Scale(s, -s)
|
||||||
@ -197,7 +197,7 @@ func (c *uiContext) update() error {
|
|||||||
panic(fmt.Sprintf("ebiten: invalid v-direction: %d", vd))
|
panic(fmt.Sprintf("ebiten: invalid v-direction: %d", vd))
|
||||||
}
|
}
|
||||||
|
|
||||||
op.GeoM.Translate(c.offsets())
|
op.GeoM.Translate(c.offsets(uiDriver().DeviceScaleFactor()))
|
||||||
op.CompositeMode = CompositeModeCopy
|
op.CompositeMode = CompositeModeCopy
|
||||||
|
|
||||||
// filterScreen works with >=1 scale, but does not well with <1 scale.
|
// filterScreen works with >=1 scale, but does not well with <1 scale.
|
||||||
@ -211,9 +211,8 @@ func (c *uiContext) update() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *uiContext) AdjustPosition(x, y float64) (float64, float64) {
|
func (c *uiContext) AdjustPosition(x, y float64, deviceScaleFactor float64) (float64, float64) {
|
||||||
d := uiDriver().DeviceScaleFactor()
|
ox, oy := c.offsets(deviceScaleFactor)
|
||||||
ox, oy := c.offsets()
|
s := c.screenScale(deviceScaleFactor)
|
||||||
s := c.screenScale()
|
return (x*deviceScaleFactor - ox) / s, (y*deviceScaleFactor - oy) / s
|
||||||
return (x*d - ox) / s, (y*d - oy) / s
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user