twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

input.go (8310B)


      1 // Copyright 2015 Hajime Hoshi
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // +build darwin freebsd linux windows
     16 // +build !android
     17 // +build !ios
     18 
     19 package glfw
     20 
     21 import (
     22 	"sync"
     23 	"unicode"
     24 
     25 	"github.com/hajimehoshi/ebiten/v2/internal/driver"
     26 	"github.com/hajimehoshi/ebiten/v2/internal/glfw"
     27 )
     28 
     29 type gamePad struct {
     30 	valid         bool
     31 	guid          string
     32 	name          string
     33 	axisNum       int
     34 	axes          [16]float64
     35 	buttonNum     int
     36 	buttonPressed [256]bool
     37 }
     38 
     39 type Input struct {
     40 	keyPressed         map[glfw.Key]bool
     41 	mouseButtonPressed map[glfw.MouseButton]bool
     42 	onceCallback       sync.Once
     43 	scrollX            float64
     44 	scrollY            float64
     45 	cursorX            int
     46 	cursorY            int
     47 	gamepads           [16]gamePad
     48 	touches            map[driver.TouchID]pos // TODO: Implement this (#417)
     49 	runeBuffer         []rune
     50 	ui                 *UserInterface
     51 }
     52 
     53 type pos struct {
     54 	X int
     55 	Y int
     56 }
     57 
     58 func (i *Input) CursorPosition() (x, y int) {
     59 	if !i.ui.isRunning() {
     60 		return 0, 0
     61 	}
     62 	var cx, cy int
     63 	_ = i.ui.t.Call(func() error {
     64 		cx, cy = i.cursorX, i.cursorY
     65 		return nil
     66 	})
     67 	return cx, cy
     68 }
     69 
     70 func (i *Input) GamepadIDs() []driver.GamepadID {
     71 	if !i.ui.isRunning() {
     72 		return nil
     73 	}
     74 	var r []driver.GamepadID
     75 	_ = i.ui.t.Call(func() error {
     76 		for id, g := range i.gamepads {
     77 			if g.valid {
     78 				r = append(r, driver.GamepadID(id))
     79 			}
     80 		}
     81 		return nil
     82 	})
     83 	return r
     84 }
     85 
     86 func (i *Input) GamepadSDLID(id driver.GamepadID) string {
     87 	if !i.ui.isRunning() {
     88 		return ""
     89 	}
     90 	var r string
     91 	_ = i.ui.t.Call(func() error {
     92 		if len(i.gamepads) <= int(id) {
     93 			return nil
     94 		}
     95 		r = i.gamepads[id].guid
     96 		return nil
     97 	})
     98 	return r
     99 }
    100 
    101 func (i *Input) GamepadName(id driver.GamepadID) string {
    102 	if !i.ui.isRunning() {
    103 		return ""
    104 	}
    105 	var r string
    106 	_ = i.ui.t.Call(func() error {
    107 		if len(i.gamepads) <= int(id) {
    108 			return nil
    109 		}
    110 		r = i.gamepads[id].name
    111 		return nil
    112 	})
    113 	return r
    114 }
    115 
    116 func (i *Input) GamepadAxisNum(id driver.GamepadID) int {
    117 	if !i.ui.isRunning() {
    118 		return 0
    119 	}
    120 	var r int
    121 	_ = i.ui.t.Call(func() error {
    122 		if len(i.gamepads) <= int(id) {
    123 			return nil
    124 		}
    125 		r = i.gamepads[id].axisNum
    126 		return nil
    127 	})
    128 	return r
    129 }
    130 
    131 func (i *Input) GamepadAxis(id driver.GamepadID, axis int) float64 {
    132 	if !i.ui.isRunning() {
    133 		return 0
    134 	}
    135 	var r float64
    136 	_ = i.ui.t.Call(func() error {
    137 		if len(i.gamepads) <= int(id) {
    138 			return nil
    139 		}
    140 		r = i.gamepads[id].axes[axis]
    141 		return nil
    142 	})
    143 	return r
    144 }
    145 
    146 func (i *Input) GamepadButtonNum(id driver.GamepadID) int {
    147 	if !i.ui.isRunning() {
    148 		return 0
    149 	}
    150 	var r int
    151 	_ = i.ui.t.Call(func() error {
    152 		if len(i.gamepads) <= int(id) {
    153 			return nil
    154 		}
    155 		r = i.gamepads[id].buttonNum
    156 		return nil
    157 	})
    158 	return r
    159 }
    160 
    161 func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.GamepadButton) bool {
    162 	if !i.ui.isRunning() {
    163 		return false
    164 	}
    165 	var r bool
    166 	_ = i.ui.t.Call(func() error {
    167 		if len(i.gamepads) <= int(id) {
    168 			return nil
    169 		}
    170 		r = i.gamepads[id].buttonPressed[button]
    171 		return nil
    172 	})
    173 	return r
    174 }
    175 
    176 func (i *Input) TouchIDs() []driver.TouchID {
    177 	if !i.ui.isRunning() {
    178 		return nil
    179 	}
    180 	var ids []driver.TouchID
    181 	_ = i.ui.t.Call(func() error {
    182 		if len(i.touches) == 0 {
    183 			return nil
    184 		}
    185 		for id := range i.touches {
    186 			ids = append(ids, id)
    187 		}
    188 		return nil
    189 	})
    190 	return ids
    191 }
    192 
    193 func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
    194 	if !i.ui.isRunning() {
    195 		return 0, 0
    196 	}
    197 	var found bool
    198 	var p pos
    199 	_ = i.ui.t.Call(func() error {
    200 		for tid, pos := range i.touches {
    201 			if id == tid {
    202 				p = pos
    203 				found = true
    204 				break
    205 			}
    206 		}
    207 		return nil
    208 	})
    209 	if !found {
    210 		return 0, 0
    211 	}
    212 	return p.X, p.Y
    213 }
    214 
    215 func (i *Input) RuneBuffer() []rune {
    216 	if !i.ui.isRunning() {
    217 		return nil
    218 	}
    219 	var r []rune
    220 	_ = i.ui.t.Call(func() error {
    221 		r = i.runeBuffer
    222 		return nil
    223 	})
    224 	return r
    225 }
    226 
    227 func (i *Input) resetForFrame() {
    228 	if !i.ui.isRunning() {
    229 		return
    230 	}
    231 	_ = i.ui.t.Call(func() error {
    232 		i.runeBuffer = i.runeBuffer[:0]
    233 		i.scrollX, i.scrollY = 0, 0
    234 		return nil
    235 	})
    236 }
    237 
    238 func (i *Input) IsKeyPressed(key driver.Key) bool {
    239 	if !i.ui.isRunning() {
    240 		return false
    241 	}
    242 	var r bool
    243 	_ = i.ui.t.Call(func() error {
    244 		if i.keyPressed == nil {
    245 			i.keyPressed = map[glfw.Key]bool{}
    246 		}
    247 		gk, ok := driverKeyToGLFWKey[key]
    248 		if ok && i.keyPressed[gk] {
    249 			r = true
    250 			return nil
    251 		}
    252 		return nil
    253 	})
    254 	return r
    255 }
    256 
    257 func (i *Input) IsMouseButtonPressed(button driver.MouseButton) bool {
    258 	if !i.ui.isRunning() {
    259 		return false
    260 	}
    261 	var r bool
    262 	_ = i.ui.t.Call(func() error {
    263 		if i.mouseButtonPressed == nil {
    264 			i.mouseButtonPressed = map[glfw.MouseButton]bool{}
    265 		}
    266 		for gb, b := range glfwMouseButtonToMouseButton {
    267 			if b != button {
    268 				continue
    269 			}
    270 			if i.mouseButtonPressed[gb] {
    271 				r = true
    272 				return nil
    273 			}
    274 		}
    275 		return nil
    276 	})
    277 	return r
    278 }
    279 
    280 func (i *Input) Wheel() (xoff, yoff float64) {
    281 	if !i.ui.isRunning() {
    282 		return 0, 0
    283 	}
    284 	_ = i.ui.t.Call(func() error {
    285 		xoff, yoff = i.scrollX, i.scrollY
    286 		return nil
    287 	})
    288 	return
    289 }
    290 
    291 var glfwMouseButtonToMouseButton = map[glfw.MouseButton]driver.MouseButton{
    292 	glfw.MouseButtonLeft:   driver.MouseButtonLeft,
    293 	glfw.MouseButtonRight:  driver.MouseButtonRight,
    294 	glfw.MouseButtonMiddle: driver.MouseButtonMiddle,
    295 }
    296 
    297 func (i *Input) appendRuneBuffer(char rune) {
    298 	// As this function is called from GLFW callbacks, the current thread is main.
    299 	if !unicode.IsPrint(char) {
    300 		return
    301 	}
    302 	i.runeBuffer = append(i.runeBuffer, char)
    303 }
    304 
    305 func (i *Input) setWheel(xoff, yoff float64) {
    306 	// As this function is called from GLFW callbacks, the current thread is main.
    307 	i.scrollX = xoff
    308 	i.scrollY = yoff
    309 }
    310 
    311 func (i *Input) update(window *glfw.Window, context driver.UIContext) {
    312 	var cx, cy float64
    313 	_ = i.ui.t.Call(func() error {
    314 		i.onceCallback.Do(func() {
    315 			window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
    316 				i.appendRuneBuffer(char)
    317 			})
    318 			window.SetScrollCallback(func(w *glfw.Window, xoff float64, yoff float64) {
    319 				i.setWheel(xoff, yoff)
    320 			})
    321 		})
    322 		if i.keyPressed == nil {
    323 			i.keyPressed = map[glfw.Key]bool{}
    324 		}
    325 		for gk := range glfwKeyToDriverKey {
    326 			i.keyPressed[gk] = window.GetKey(gk) == glfw.Press
    327 		}
    328 		if i.mouseButtonPressed == nil {
    329 			i.mouseButtonPressed = map[glfw.MouseButton]bool{}
    330 		}
    331 		for gb := range glfwMouseButtonToMouseButton {
    332 			i.mouseButtonPressed[gb] = window.GetMouseButton(gb) == glfw.Press
    333 		}
    334 		cx, cy = window.GetCursorPos()
    335 		// TODO: This is tricky. Rename the function?
    336 		cx = i.ui.fromGLFWMonitorPixel(cx)
    337 		cy = i.ui.fromGLFWMonitorPixel(cy)
    338 		return nil
    339 	})
    340 
    341 	cx, cy = context.AdjustPosition(cx, cy)
    342 
    343 	_ = i.ui.t.Call(func() error {
    344 		i.cursorX, i.cursorY = int(cx), int(cy)
    345 
    346 		for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
    347 			i.gamepads[id].valid = false
    348 			if !id.Present() {
    349 				continue
    350 			}
    351 
    352 			buttons := id.GetButtons()
    353 
    354 			// A gamepad can be detected even though there are not. Apparently, some special devices are
    355 			// recognized as gamepads by GLFW. In this case, the number of the 'buttons' can exceeds the
    356 			// maximum. Skip such devices as a tentative solution (#1173).
    357 			if len(buttons) > driver.GamepadButtonNum {
    358 				continue
    359 			}
    360 
    361 			i.gamepads[id].valid = true
    362 
    363 			i.gamepads[id].buttonNum = len(buttons)
    364 			for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
    365 				if len(buttons) <= b {
    366 					i.gamepads[id].buttonPressed[b] = false
    367 					continue
    368 				}
    369 				i.gamepads[id].buttonPressed[b] = glfw.Action(buttons[b]) == glfw.Press
    370 			}
    371 
    372 			axes32 := id.GetAxes()
    373 			i.gamepads[id].axisNum = len(axes32)
    374 			for a := 0; a < len(i.gamepads[id].axes); a++ {
    375 				if len(axes32) <= a {
    376 					i.gamepads[id].axes[a] = 0
    377 					continue
    378 				}
    379 				i.gamepads[id].axes[a] = float64(axes32[a])
    380 			}
    381 
    382 			// Note that GLFW's gamepad GUID follows SDL's GUID.
    383 			i.gamepads[id].guid = id.GetGUID()
    384 			i.gamepads[id].name = id.GetName()
    385 		}
    386 		return nil
    387 	})
    388 }