fruit-popper/GDLIB/GDEVENTS.PAS

230 lines
6.2 KiB
Plaintext
Raw Permalink Normal View History

{ 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.