Toying with event recording to see if it can be used for testing
This commit is contained in:
@@ -227,6 +227,9 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
|
|||||||
|
|
||||||
void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
|
void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
|
||||||
Scratch scratch((Arena *)buffer->allocator.object);
|
Scratch scratch((Arena *)buffer->allocator.object);
|
||||||
|
Assert(buffer->data[0]);
|
||||||
|
Assert(buffer->allocator.proc);
|
||||||
|
Assert(buffer->lines.len);
|
||||||
|
|
||||||
// Figure out how much we insert and how much we delete so
|
// Figure out how much we insert and how much we delete so
|
||||||
// we can resize buffers properly if necessary
|
// we can resize buffers properly if necessary
|
||||||
@@ -356,13 +359,22 @@ void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
|
|||||||
}
|
}
|
||||||
buffer->lines.add({base_index, base_index + string.len});
|
buffer->lines.add({base_index, base_index + string.len});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert(buffer->data[0]);
|
||||||
|
Assert(buffer->allocator.proc);
|
||||||
|
Assert(buffer->lines.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitBuffer(Buffer *buffer) {
|
void InitBuffer(Allocator allocator, Buffer *buffer, int64_t _size = 4096) {
|
||||||
Scratch scratch;
|
int64_t size = AlignUp(_size, 4096);
|
||||||
Array<Edit> edits = {};
|
buffer->allocator = allocator;
|
||||||
AddEdit(&edits, {}, "");
|
for (int i = 0; i < 2; i += 1) {
|
||||||
ApplyEdits(buffer, edits);
|
buffer->data[i] = AllocArray(allocator, char, size);
|
||||||
|
Assert(buffer->data[i]);
|
||||||
|
}
|
||||||
|
buffer->cap = size;
|
||||||
|
buffer->lines.allocator = allocator;
|
||||||
|
buffer->lines.add({});
|
||||||
}
|
}
|
||||||
|
|
||||||
String CopyNullTerminated(Allocator allocator, Buffer &buffer, Range range) {
|
String CopyNullTerminated(Allocator allocator, Buffer &buffer, Range range) {
|
||||||
@@ -569,3 +581,29 @@ int64_t Seek(Buffer &buffer, int64_t pos, int64_t direction = ITERATE_FORWARD) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t MoveRight(Buffer &buffer, int64_t pos) {
|
||||||
|
pos = pos + 1;
|
||||||
|
pos = AdjustUTF8Pos(buffer, pos);
|
||||||
|
Assert(pos >= 0 && pos <= buffer.len);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MoveLeft(Buffer &buffer, int64_t pos) {
|
||||||
|
pos = pos - 1;
|
||||||
|
pos = AdjustUTF8Pos(buffer, pos, -1);
|
||||||
|
Assert(pos >= 0 && pos <= buffer.len);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MoveDown(Buffer &buffer, int64_t pos) {
|
||||||
|
LineAndColumn info = FindLineAndColumn(buffer, pos);
|
||||||
|
int64_t new_pos = FindPos(buffer, info.line.number + 1, info.column);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MoveUp(Buffer &buffer, int64_t pos) {
|
||||||
|
LineAndColumn info = FindLineAndColumn(buffer, pos);
|
||||||
|
int64_t new_pos = FindPos(buffer, info.line.number - 1, info.column);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
133
src/text_editor/event_recording.cpp
Normal file
133
src/text_editor/event_recording.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
bool EventRecording = false;
|
||||||
|
bool EventPlaying = false;
|
||||||
|
AutomationEventList EventList;
|
||||||
|
Array<AutomationEventList> EventsToPlay;
|
||||||
|
unsigned int frameCounter;
|
||||||
|
unsigned int playFrameCounter;
|
||||||
|
unsigned int currentPlayFrame;
|
||||||
|
|
||||||
|
void InitEventRecording() {
|
||||||
|
EventList = LoadAutomationEventList(0);
|
||||||
|
SetAutomationEventList(&EventList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartNextEvent() {
|
||||||
|
Assert(EventPlaying);
|
||||||
|
if (EventsToPlay.len > 0) {
|
||||||
|
AutomationEventList event = EventsToPlay.pop();
|
||||||
|
EventList = event;
|
||||||
|
SetAutomationEventList(&EventList);
|
||||||
|
} else {
|
||||||
|
EventPlaying = false;
|
||||||
|
SetTargetFPS(60);
|
||||||
|
}
|
||||||
|
currentPlayFrame = 0;
|
||||||
|
playFrameCounter = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateEventRecording() {
|
||||||
|
if (IsKeyPressed(KEY_F5)) {
|
||||||
|
if (EventRecording) {
|
||||||
|
Scratch scratch;
|
||||||
|
EventRecording = false;
|
||||||
|
|
||||||
|
StopAutomationEventRecording();
|
||||||
|
int random_value = GetRandomValue(0, INT_MAX);
|
||||||
|
String path = Format(scratch, "%d.rae", random_value);
|
||||||
|
|
||||||
|
if (!IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||||
|
ExportAutomationEventList(EventList, path.data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetAutomationEventBaseFrame(0);
|
||||||
|
StartAutomationEventRecording();
|
||||||
|
EventRecording = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_F8)) {
|
||||||
|
if (!EventPlaying) {
|
||||||
|
FilePathList list = LoadDirectoryFiles(".");
|
||||||
|
for (unsigned int i = 0; i < list.count; i += 1) {
|
||||||
|
String path = list.paths[i];
|
||||||
|
if (EndsWith(path, "rae")) {
|
||||||
|
AutomationEventList rae = LoadAutomationEventList(path.data);
|
||||||
|
EventsToPlay.add(rae);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnloadDirectoryFiles(list);
|
||||||
|
|
||||||
|
EventPlaying = true;
|
||||||
|
SetTargetFPS(3000);
|
||||||
|
StartNextEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EventPlaying) {
|
||||||
|
// NOTE: Multiple events could be executed in a single frame
|
||||||
|
while (playFrameCounter == EventList.events[currentPlayFrame].frame) {
|
||||||
|
TraceLog(LOG_INFO, "PLAYING: PlayFrameCount: %i | currentPlayFrame: %i | Event Frame: %i, param: %i",
|
||||||
|
playFrameCounter, currentPlayFrame, EventList.events[currentPlayFrame].frame, EventList.events[currentPlayFrame].params[0]);
|
||||||
|
|
||||||
|
PlayAutomationEvent(EventList.events[currentPlayFrame]);
|
||||||
|
currentPlayFrame++;
|
||||||
|
|
||||||
|
if (currentPlayFrame == EventList.count) {
|
||||||
|
StartNextEvent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playFrameCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecording_SimulateGetCharPressed(Window *focused_window) {
|
||||||
|
if (!EventPlaying) return;
|
||||||
|
Scratch scratch;
|
||||||
|
for (int i = KEY_A; i <= KEY_Z; i += 1) {
|
||||||
|
bool press = IsKeyPressed(i) || IsKeyPressedRepeat(i);
|
||||||
|
if (press) {
|
||||||
|
String string = "?";
|
||||||
|
int offset = 32;
|
||||||
|
if (IsKeyDown(KEY_LEFT_SHIFT)) offset = 0;
|
||||||
|
UTF8Result utf8 = UTF32ToUTF8((uint32_t)i + offset);
|
||||||
|
if (utf8.error == 0) {
|
||||||
|
string = {(char *)utf8.out_str, (int64_t)utf8.len};
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeEdit(focused_window);
|
||||||
|
Array<Edit> edits = {scratch};
|
||||||
|
For(focused_window->cursors) {
|
||||||
|
AddEdit(&edits, it.range, string);
|
||||||
|
}
|
||||||
|
ApplyEdits(&focused_window->buffer, edits);
|
||||||
|
AfterEdit(focused_window, edits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecording_Draw() {
|
||||||
|
if (EventRecording) Assert(EventPlaying == false);
|
||||||
|
if (EventPlaying) Assert(EventRecording == false);
|
||||||
|
Rect2 screen = GetScreenRect();
|
||||||
|
Color color = {};
|
||||||
|
|
||||||
|
Rect2 l = CutLeft(&screen, 4);
|
||||||
|
Rect2 r = CutRight(&screen, 4);
|
||||||
|
Rect2 t = CutTop(&screen, 4);
|
||||||
|
Rect2 b = CutBottom(&screen, 4);
|
||||||
|
|
||||||
|
if (EventPlaying) {
|
||||||
|
color = BLUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EventRecording) {
|
||||||
|
color = RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRectangleRec(ToRectangle(l), color);
|
||||||
|
DrawRectangleRec(ToRectangle(r), color);
|
||||||
|
DrawRectangleRec(ToRectangle(t), color);
|
||||||
|
DrawRectangleRec(ToRectangle(b), color);
|
||||||
|
}
|
||||||
@@ -239,4 +239,54 @@ Array<LayoutColumn> CalculateVisibleColumns(Arena *arena, Window &window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BeforeEdit(Window *window) {
|
||||||
|
// Merge cursors that overlap, this needs to be handled before any edits to
|
||||||
|
// make sure overlapping edits won't happen.
|
||||||
|
for (int64_t cursor_i = 0; cursor_i < window->cursors.len; cursor_i += 1) {
|
||||||
|
Cursor &cursor = window->cursors[cursor_i];
|
||||||
|
IterRemove(window->cursors) {
|
||||||
|
IterRemovePrepare(window->cursors);
|
||||||
|
if (&cursor == &it) continue;
|
||||||
|
|
||||||
|
if (cursor.range.max >= it.range.min && cursor.range.max <= it.range.max) {
|
||||||
|
remove_item = true;
|
||||||
|
cursor.range.max = it.range.max;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AfterEdit(Window *window, Array<Edit> edits) {
|
||||||
|
// Offset all cursors by edits
|
||||||
|
ForItem(edit, edits) {
|
||||||
|
int64_t remove_size = GetRangeSize(edit.range);
|
||||||
|
int64_t insert_size = edit.string.len;
|
||||||
|
int64_t offset = insert_size - remove_size;
|
||||||
|
|
||||||
|
ForItem(cursor, window->cursors) {
|
||||||
|
if (edit.range.min == cursor.range.min) {
|
||||||
|
if (GetRangeSize(edit.range)) {
|
||||||
|
cursor.range.min += edit.string.len;
|
||||||
|
} else {
|
||||||
|
cursor.range.min += offset;
|
||||||
|
}
|
||||||
|
cursor.range.max = cursor.range.min;
|
||||||
|
} else if (edit.range.min <= cursor.range.min) {
|
||||||
|
if (GetRangeSize(edit.range)) {
|
||||||
|
cursor.range.min += edit.string.len;
|
||||||
|
}
|
||||||
|
cursor.range.min += offset;
|
||||||
|
cursor.range.max = cursor.range.min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure all cursors are in range
|
||||||
|
For(window->cursors) it.range = Clamp(window->buffer, it.range);
|
||||||
|
|
||||||
|
Clear(&window->layout_arena);
|
||||||
|
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,96 +8,8 @@
|
|||||||
#include "rect2.cpp"
|
#include "rect2.cpp"
|
||||||
#include "buffer.cpp"
|
#include "buffer.cpp"
|
||||||
#include "layout.cpp"
|
#include "layout.cpp"
|
||||||
|
#include "utils.cpp"
|
||||||
Rect2 GetScreenRect() {
|
#include "event_recording.cpp"
|
||||||
Rect2 result = {
|
|
||||||
{ 0, 0},
|
|
||||||
{(float)GetRenderWidth(), (float)GetRenderHeight()}
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MoveRight(Buffer &buffer, int64_t pos) {
|
|
||||||
pos = pos + 1;
|
|
||||||
pos = AdjustUTF8Pos(buffer, pos);
|
|
||||||
Assert(pos >= 0 && pos <= buffer.len);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MoveLeft(Buffer &buffer, int64_t pos) {
|
|
||||||
pos = pos - 1;
|
|
||||||
pos = AdjustUTF8Pos(buffer, pos, -1);
|
|
||||||
Assert(pos >= 0 && pos <= buffer.len);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo: when at the end of line, it resets to first position on next line
|
|
||||||
int64_t MoveDown(Buffer &buffer, int64_t pos) {
|
|
||||||
LineAndColumn info = FindLineAndColumn(buffer, pos);
|
|
||||||
int64_t new_pos = FindPos(buffer, info.line.number + 1, info.column);
|
|
||||||
return new_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MoveUp(Buffer &buffer, int64_t pos) {
|
|
||||||
LineAndColumn info = FindLineAndColumn(buffer, pos);
|
|
||||||
int64_t new_pos = FindPos(buffer, info.line.number - 1, info.column);
|
|
||||||
return new_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AreEqual(float a, float b, float epsilon = 0.001f) {
|
|
||||||
bool result = (a - epsilon < b && a + epsilon > b);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeforeEdit(Window *window) {
|
|
||||||
// Merge cursors that overlap, this needs to be handled before any edits to
|
|
||||||
// make sure overlapping edits won't happen.
|
|
||||||
for (int64_t cursor_i = 0; cursor_i < window->cursors.len; cursor_i += 1) {
|
|
||||||
Cursor &cursor = window->cursors[cursor_i];
|
|
||||||
IterRemove(window->cursors) {
|
|
||||||
IterRemovePrepare(window->cursors);
|
|
||||||
if (&cursor == &it) continue;
|
|
||||||
|
|
||||||
if (cursor.range.max >= it.range.min && cursor.range.max <= it.range.max) {
|
|
||||||
remove_item = true;
|
|
||||||
cursor.range.max = it.range.max;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AfterEdit(Window *window, Array<Edit> edits) {
|
|
||||||
// Offset all cursors by edits
|
|
||||||
ForItem(edit, edits) {
|
|
||||||
int64_t remove_size = GetRangeSize(edit.range);
|
|
||||||
int64_t insert_size = edit.string.len;
|
|
||||||
int64_t offset = insert_size - remove_size;
|
|
||||||
|
|
||||||
ForItem(cursor, window->cursors) {
|
|
||||||
if (edit.range.min == cursor.range.min) {
|
|
||||||
if (GetRangeSize(edit.range)) {
|
|
||||||
cursor.range.min += edit.string.len;
|
|
||||||
} else {
|
|
||||||
cursor.range.min += offset;
|
|
||||||
}
|
|
||||||
cursor.range.max = cursor.range.min;
|
|
||||||
} else if (edit.range.min <= cursor.range.min) {
|
|
||||||
if (GetRangeSize(edit.range)) {
|
|
||||||
cursor.range.min += edit.string.len;
|
|
||||||
}
|
|
||||||
cursor.range.min += offset;
|
|
||||||
cursor.range.max = cursor.range.min;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure all cursors are in range
|
|
||||||
For(window->cursors) it.range = Clamp(window->buffer, it.range);
|
|
||||||
|
|
||||||
Clear(&window->layout_arena);
|
|
||||||
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena PermArena;
|
Arena PermArena;
|
||||||
Arena FrameArena;
|
Arena FrameArena;
|
||||||
@@ -126,68 +38,6 @@ void Dbg_Draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventRecording = false;
|
|
||||||
bool EventPlaying = false;
|
|
||||||
AutomationEventList EventList;
|
|
||||||
|
|
||||||
void InitEventRecording() {
|
|
||||||
EventList = LoadAutomationEventList(0);
|
|
||||||
SetAutomationEventList(&EventList);
|
|
||||||
EventList = LoadAutomationEventList("automation.rae");
|
|
||||||
EventPlaying = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ModifiedGetCharPressed() {
|
|
||||||
static int i;
|
|
||||||
int result = GetCharPressed();
|
|
||||||
if (EventPlaying && (i % 2) == 0) {
|
|
||||||
result = 'a';
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateEventRecording() {
|
|
||||||
static unsigned int frameCounter;
|
|
||||||
static unsigned int playFrameCounter;
|
|
||||||
static unsigned int currentPlayFrame;
|
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_F5)) {
|
|
||||||
if (EventRecording) {
|
|
||||||
StopAutomationEventRecording();
|
|
||||||
ExportAutomationEventList(EventList, "automation.rae");
|
|
||||||
EventRecording = false;
|
|
||||||
} else {
|
|
||||||
SetAutomationEventBaseFrame(0);
|
|
||||||
StartAutomationEventRecording();
|
|
||||||
EventRecording = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EventPlaying) {
|
|
||||||
// NOTE: Multiple events could be executed in a single frame
|
|
||||||
while (playFrameCounter == EventList.events[currentPlayFrame].frame) {
|
|
||||||
TraceLog(LOG_INFO, "PLAYING: PlayFrameCount: %i | currentPlayFrame: %i | Event Frame: %i, param: %i",
|
|
||||||
playFrameCounter, currentPlayFrame, EventList.events[currentPlayFrame].frame, EventList.events[currentPlayFrame].params[0]);
|
|
||||||
|
|
||||||
PlayAutomationEvent(EventList.events[currentPlayFrame]);
|
|
||||||
currentPlayFrame++;
|
|
||||||
|
|
||||||
if (currentPlayFrame == EventList.count) {
|
|
||||||
EventPlaying = false;
|
|
||||||
currentPlayFrame = 0;
|
|
||||||
playFrameCounter = 0;
|
|
||||||
|
|
||||||
TraceLog(LOG_INFO, "FINISH PLAYING!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playFrameCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
InitScratch();
|
InitScratch();
|
||||||
InitWindow(800, 600, "Hello");
|
InitWindow(800, 600, "Hello");
|
||||||
@@ -210,7 +60,7 @@ int main() {
|
|||||||
window.font_spacing;
|
window.font_spacing;
|
||||||
InitArena(&window.layout_arena);
|
InitArena(&window.layout_arena);
|
||||||
|
|
||||||
InitBuffer(&window.buffer);
|
InitBuffer(GetSystemAllocator(), &window.buffer);
|
||||||
if (1) {
|
if (1) {
|
||||||
// Array<Edit> edits = {FrameArena};
|
// Array<Edit> edits = {FrameArena};
|
||||||
// AddEdit(&edits, GetEnd(window.buffer), Format(FrameArena, "line number: 1"));
|
// AddEdit(&edits, GetEnd(window.buffer), Format(FrameArena, "line number: 1"));
|
||||||
@@ -475,7 +325,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_ENTER)) {
|
if (IsKeyPressed(KEY_ENTER) || IsKeyPressedRepeat(KEY_ENTER)) {
|
||||||
if (IsKeyDown(KEY_LEFT_CONTROL)) {
|
if (IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||||
For(focused_window->cursors) {
|
For(focused_window->cursors) {
|
||||||
int64_t front = GetFront(it);
|
int64_t front = GetFront(it);
|
||||||
@@ -493,7 +343,7 @@ int main() {
|
|||||||
|
|
||||||
// Handle user input
|
// Handle user input
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int c = ModifiedGetCharPressed();
|
int c = GetCharPressed();
|
||||||
if (!c) break;
|
if (!c) break;
|
||||||
|
|
||||||
String string = "?";
|
String string = "?";
|
||||||
@@ -510,6 +360,7 @@ int main() {
|
|||||||
ApplyEdits(&focused_window->buffer, edits);
|
ApplyEdits(&focused_window->buffer, edits);
|
||||||
AfterEdit(focused_window, edits);
|
AfterEdit(focused_window, edits);
|
||||||
}
|
}
|
||||||
|
EventRecording_SimulateGetCharPressed(focused_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
@@ -654,6 +505,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dbg_Draw();
|
Dbg_Draw();
|
||||||
|
EventRecording_Draw();
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12
src/text_editor/utils.cpp
Normal file
12
src/text_editor/utils.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Rect2 GetScreenRect() {
|
||||||
|
Rect2 result = {
|
||||||
|
{ 0, 0},
|
||||||
|
{(float)GetRenderWidth(), (float)GetRenderHeight()}
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AreEqual(float a, float b, float epsilon = 0.001f) {
|
||||||
|
bool result = (a - epsilon < b && a + epsilon > b);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user