230 lines
6.2 KiB
Plaintext
230 lines
6.2 KiB
Plaintext
|
{ GDlib Input device events
|
||
|
Gered King, 2018 }
|
||
|
|
||
|
{$A+,B-,F-,G+,I-,N+,P-,Q-,R-,S-,T-,V-,X+}
|
||
|
|
||
|
unit GDEvents;
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses GDKeybrd, GDMouse;
|
||
|
|
||
|
const
|
||
|
EVENT_TYPE_KEYBOARD = 1;
|
||
|
EVENT_TYPE_MOUSE_MOTION = 2;
|
||
|
EVENT_TYPE_MOUSE_BUTTON = 3;
|
||
|
EVENT_ACTION_PRESSED = 1;
|
||
|
EVENT_ACTION_RELEASED = 2;
|
||
|
EVENT_ACTION_HELD = 3;
|
||
|
|
||
|
type
|
||
|
EventType = byte;
|
||
|
EventAction = byte;
|
||
|
|
||
|
InputEvent = record
|
||
|
case Event: EventType of
|
||
|
EVENT_TYPE_KEYBOARD: (
|
||
|
KB_Key : Key;
|
||
|
KB_Action : EventAction;
|
||
|
KB_Modifier : word;
|
||
|
);
|
||
|
EVENT_TYPE_MOUSE_MOTION: (
|
||
|
MM_X : integer;
|
||
|
MM_Y : integer;
|
||
|
MM_DeltaX : integer;
|
||
|
MM_DeltaY : integer;
|
||
|
MM_Buttons : MouseButton;
|
||
|
);
|
||
|
EVENT_TYPE_MOUSE_BUTTON: (
|
||
|
MB_X : integer;
|
||
|
MB_Y : integer;
|
||
|
MB_Button : MouseButton;
|
||
|
MB_Action : EventAction;
|
||
|
);
|
||
|
end;
|
||
|
|
||
|
PInputEvent = ^InputEvent;
|
||
|
|
||
|
function InitEvents : boolean;
|
||
|
function CloseEvents : boolean;
|
||
|
function IsEventsInitialized : boolean;
|
||
|
function IsEventsEmpty : boolean;
|
||
|
function PollEvents : PInputEvent;
|
||
|
function PeekEvents : PInputEvent;
|
||
|
procedure ClearEvents;
|
||
|
|
||
|
function PushEvent : PInputEvent;
|
||
|
|
||
|
function IsKeyPressedEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
function IsKeyReleasedEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
function IsKeyHeldEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses Toolbox;
|
||
|
|
||
|
const
|
||
|
EVENT_BUFFER_SIZE = 16;
|
||
|
|
||
|
_eventsInitialized : boolean = false;
|
||
|
_bufferStart : integer = 0;
|
||
|
_bufferEnd : integer = 0;
|
||
|
|
||
|
var
|
||
|
_buffer : array[0..(EVENT_BUFFER_SIZE-1)] of InputEvent;
|
||
|
|
||
|
function InitEvents : boolean;
|
||
|
{ initializes the events system, returning true if successful }
|
||
|
begin
|
||
|
if IsEventsInitialized then begin
|
||
|
InitEvents := false;
|
||
|
exit;
|
||
|
end;
|
||
|
|
||
|
ClearEvents;
|
||
|
_eventsInitialized := true;
|
||
|
InitEvents := true;
|
||
|
end;
|
||
|
|
||
|
function CloseEvents : boolean;
|
||
|
{ closes the events system, returning true if successful. }
|
||
|
begin
|
||
|
if not IsEventsInitialized then begin
|
||
|
CloseEvents := true;
|
||
|
exit;
|
||
|
end;
|
||
|
|
||
|
_eventsInitialized := false;
|
||
|
ClearEvents;
|
||
|
CloseEvents := true;
|
||
|
end;
|
||
|
|
||
|
function IsEventsInitialized : boolean;
|
||
|
{ returns true if the events system has been initialized }
|
||
|
begin
|
||
|
IsEventsInitialized := _eventsInitialized;
|
||
|
end;
|
||
|
|
||
|
function IsEventsEmpty : boolean;
|
||
|
{ returns true if there are no events to be processed currently }
|
||
|
begin
|
||
|
IsEventsEmpty := (_bufferStart = _bufferEnd);
|
||
|
end;
|
||
|
|
||
|
function PollEvents : PInputEvent;
|
||
|
{ returns the next input event in the buffer, or nil if there was none.
|
||
|
calling this function moves the input event buffer head to the next event }
|
||
|
begin
|
||
|
if IsEventsEmpty then begin
|
||
|
PollEvents := nil;
|
||
|
exit;
|
||
|
end;
|
||
|
|
||
|
asm cli end;
|
||
|
|
||
|
{ return a pointer to the event at the buffer queue head currently }
|
||
|
PollEvents := @_buffer[_bufferStart];
|
||
|
|
||
|
{ move the buffer queue head to the following event }
|
||
|
inc(_bufferStart);
|
||
|
if _bufferStart >= EVENT_BUFFER_SIZE then
|
||
|
_bufferStart := 0;
|
||
|
|
||
|
asm sti end;
|
||
|
end;
|
||
|
|
||
|
function PeekEvents : PInputEvent;
|
||
|
{ returns the next input event in the buffer, or nil if there was none.
|
||
|
calling this function does not modify the input event buffer in any way
|
||
|
(subsequent calls will return the same event, and/or PollEvents can be
|
||
|
used immediately after to return the same event) }
|
||
|
begin
|
||
|
if IsEventsEmpty then begin
|
||
|
PeekEvents := nil;
|
||
|
exit;
|
||
|
end;
|
||
|
|
||
|
{ return a pointer to the event at the buffer queue head currently }
|
||
|
PeekEvents := @_buffer[_bufferStart];
|
||
|
end;
|
||
|
|
||
|
procedure ClearEvents;
|
||
|
{ clears the event buffer of all events }
|
||
|
begin
|
||
|
asm cli end;
|
||
|
|
||
|
MemFill(@_buffer, 0, SizeOf(_buffer));
|
||
|
_bufferStart := 0;
|
||
|
_bufferEnd := 0;
|
||
|
|
||
|
asm sti end;
|
||
|
end;
|
||
|
|
||
|
function PushEvent : PInputEvent;
|
||
|
{ returns a pointer to the last event on the buffer queue. it is up to the
|
||
|
caller to fill that event structure with the information about the event to
|
||
|
be "pushed" onto the queue. the buffer end pointer is incremented each
|
||
|
time this is called (so it won't return the same pointer for subsequent
|
||
|
calls). this function was mainly intended to be used by GDlib keyboard and
|
||
|
mouse handlers. }
|
||
|
begin
|
||
|
{ return pointer to the last event in the buffer queue (which ensures
|
||
|
FIFO queue behaviour when adding new events) }
|
||
|
PushEvent := @_buffer[_bufferEnd];
|
||
|
|
||
|
{ advance the end pointer }
|
||
|
inc(_bufferEnd);
|
||
|
if _bufferEnd >= EVENT_BUFFER_SIZE then
|
||
|
_bufferEnd := 0;
|
||
|
|
||
|
{ is the events buffer full? (if the end meets up to the start, it is) }
|
||
|
if _bufferEnd = _bufferStart then begin
|
||
|
{ move the start up. this ensures the start always points to the oldest
|
||
|
event in the buffer }
|
||
|
inc(_bufferStart);
|
||
|
if _bufferStart >= EVENT_BUFFER_SIZE then
|
||
|
_bufferStart := 0;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IsKeyPressedEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
{ returns true if this event is a 'key pressed' event for the given key }
|
||
|
begin
|
||
|
if event = nil then
|
||
|
IsKeyPressedEvent := false
|
||
|
else
|
||
|
with event^ do begin
|
||
|
IsKeyPressedEvent := (Event = EVENT_TYPE_KEYBOARD)
|
||
|
and (KB_Action = EVENT_ACTION_PRESSED)
|
||
|
and (KB_Key = k);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IsKeyReleasedEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
{ returns true if this event is a 'key released' event for the given key }
|
||
|
begin
|
||
|
if event = nil then
|
||
|
IsKeyReleasedEvent := false
|
||
|
else
|
||
|
with event^ do begin
|
||
|
IsKeyReleasedEvent := (Event = EVENT_TYPE_KEYBOARD)
|
||
|
and (KB_Action = EVENT_ACTION_RELEASED)
|
||
|
and (KB_Key = k);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IsKeyHeldEvent(event : PInputEvent; k : Key) : boolean;
|
||
|
{ returns true if this event is a 'key held' event for the given key }
|
||
|
begin
|
||
|
if event = nil then
|
||
|
IsKeyHeldEvent := false
|
||
|
else
|
||
|
with event^ do begin
|
||
|
IsKeyHeldEvent := (Event = EVENT_TYPE_KEYBOARD)
|
||
|
and (KB_Action = EVENT_ACTION_HELD)
|
||
|
and (KB_Key = k);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|