Added user events & possibility to 'refresh'.

- Refresh unblocks event loop for the next redraw.
This commit is contained in:
Sander Schobers 2019-03-06 18:18:35 +01:00
parent c08474a01c
commit 0387e313de
3 changed files with 59 additions and 2 deletions

View File

@ -1,6 +1,15 @@
package allg5 package allg5
// #include <allegro5/allegro.h> /*
#include <allegro5/allegro.h>
#define USER_EVENT_TYPE ALLEGRO_GET_EVENT_TYPE('u', 's', 'e', 'r')
void init_user_event(ALLEGRO_EVENT* e)
{
e->user.type = USER_EVENT_TYPE;
}
*/
import "C" import "C"
import ( import (
@ -117,6 +126,14 @@ type MouseMoveEvent struct {
Pressure float32 Pressure float32
} }
type UserEvent struct {
EventBase
}
type UserEventSource struct {
source *C.ALLEGRO_EVENT_SOURCE
}
func NewEventQueue() (*EventQueue, error) { func NewEventQueue() (*EventQueue, error) {
q := C.al_create_event_queue() q := C.al_create_event_queue()
if q == nil { if q == nil {
@ -141,6 +158,10 @@ func (eq *EventQueue) RegisterKeyboard() {
eq.register(C.al_get_keyboard_event_source()) eq.register(C.al_get_keyboard_event_source())
} }
func (eq *EventQueue) RegisterUserEvents(source *UserEventSource) {
eq.register(source.source)
}
func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event { func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event {
any := (*C.ALLEGRO_ANY_EVENT)(unsafe.Pointer(e)) any := (*C.ALLEGRO_ANY_EVENT)(unsafe.Pointer(e))
eb := EventBase{float64(any.timestamp)} eb := EventBase{float64(any.timestamp)}
@ -172,6 +193,8 @@ func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event {
case C.ALLEGRO_EVENT_KEY_CHAR: case C.ALLEGRO_EVENT_KEY_CHAR:
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e)) key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
return &KeyCharEvent{KeyEvent{eb, Key(key.keycode), nil}, rune(key.unichar), KeyMod(key.modifiers), bool(key.repeat)} return &KeyCharEvent{KeyEvent{eb, Key(key.keycode), nil}, rune(key.unichar), KeyMod(key.modifiers), bool(key.repeat)}
case C.USER_EVENT_TYPE:
return &UserEvent{eb}
} }
return nil return nil
} }
@ -193,3 +216,21 @@ func (eq *EventQueue) GetWait() Event {
func (eq *EventQueue) Destroy() { func (eq *EventQueue) Destroy() {
C.al_destroy_event_queue(eq.queue) C.al_destroy_event_queue(eq.queue)
} }
func NewUserEventSource() *UserEventSource {
s := (*C.ALLEGRO_EVENT_SOURCE)(C.malloc(C.sizeof_ALLEGRO_EVENT_SOURCE))
source := &UserEventSource{s}
C.al_init_user_event_source(s)
return source
}
func (s *UserEventSource) Destroy() {
C.al_destroy_user_event_source(s.source)
C.free(unsafe.Pointer(s.source))
}
func (s *UserEventSource) EmitEvent() bool {
e := (*C.ALLEGRO_EVENT)(C.malloc(C.sizeof_ALLEGRO_EVENT))
C.init_user_event(e)
return bool(C.al_emit_user_event(s.source, e, nil))
}

View File

@ -28,11 +28,13 @@ func NewRenderer(w, h int, opts allg5.NewDisplayOptions) (*Renderer, error) {
return nil, err return nil, err
} }
user := allg5.NewUserEventSource()
eq.RegisterKeyboard() eq.RegisterKeyboard()
eq.RegisterMouse() eq.RegisterMouse()
eq.RegisterDisplay(disp) eq.RegisterDisplay(disp)
eq.RegisterUserEvents(user)
return &Renderer{disp, eq, map[string]*font{}}, nil return &Renderer{disp, eq, map[string]*font{}, user}, nil
} }
// Renderer implements ui.Renderer using Allegro 5. // Renderer implements ui.Renderer using Allegro 5.
@ -40,6 +42,7 @@ type Renderer struct {
disp *allg5.Display disp *allg5.Display
eq *allg5.EventQueue eq *allg5.EventQueue
ft map[string]*font ft map[string]*font
user *allg5.UserEventSource
} }
// Renderer implementation (events) // Renderer implementation (events)
@ -60,14 +63,21 @@ func (r *Renderer) PushEvents(t ui.EventTarget, wait bool) {
t.Handle(&ui.MouseButtonUpEvent{MouseEvent: mouseEvent(e.MouseEvent), Button: ui.MouseButton(e.Button)}) t.Handle(&ui.MouseButtonUpEvent{MouseEvent: mouseEvent(e.MouseEvent), Button: ui.MouseButton(e.Button)})
case *allg5.MouseMoveEvent: case *allg5.MouseMoveEvent:
t.Handle(&ui.MouseMoveEvent{MouseEvent: mouseEvent(e.MouseEvent), MouseWheel: float32(e.DeltaZ)}) t.Handle(&ui.MouseMoveEvent{MouseEvent: mouseEvent(e.MouseEvent), MouseWheel: float32(e.DeltaZ)})
case *allg5.UserEvent:
// used to unblock the wait for events.
} }
ev = r.eq.Get() ev = r.eq.Get()
} }
} }
func (r *Renderer) Refresh() {
r.user.EmitEvent()
}
// Renderer implementation (lifetime) // Renderer implementation (lifetime)
func (r *Renderer) Destroy() error { func (r *Renderer) Destroy() error {
r.user.Destroy()
r.eq.Destroy() r.eq.Destroy()
r.disp.Destroy() r.disp.Destroy()
return nil return nil
@ -168,6 +178,11 @@ func (r *Renderer) Size() geom.PointF32 {
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height())) return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
} }
func (r *Renderer) SetIcon(im ui.Image) {
bmp := r.mustGetBitmap(im)
r.disp.SetIcon(bmp)
}
func (r *Renderer) SetWindowTitle(t string) { func (r *Renderer) SetWindowTitle(t string) {
r.disp.SetWindowTitle(t) r.disp.SetWindowTitle(t)
} }

View File

@ -10,6 +10,7 @@ import (
type Renderer interface { type Renderer interface {
// Events // Events
PushEvents(t EventTarget, wait bool) PushEvents(t EventTarget, wait bool)
Refresh()
// Lifetime // Lifetime
Destroy() error Destroy() error