forked from JoshParnell/libphx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ClipRect.cpp
121 lines (107 loc) · 2.86 KB
/
ClipRect.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "ClipRect.h"
#include "OpenGL.h"
#include "PhxMath.h"
#include "Vec2.h"
#include "Viewport.h"
#define MAX_STACK_DEPTH 128
struct ClipRectTransform {
float tx, ty;
float sx, sy;
};
static ClipRectTransform transform[MAX_STACK_DEPTH];
static int transformIndex = -1;
struct ClipRect {
float x, y;
float sx, sy;
bool enabled;
};
static ClipRect rect[MAX_STACK_DEPTH];
static int rectIndex = -1;
inline static void TransformRect (float* x, float* y, float* sx, float* sy) {
if (transformIndex >= 0) {
ClipRectTransform* curr = transform + transformIndex;
*x = curr->sx * (*x) + curr->tx;
*y = curr->sy * (*y) + curr->ty;
*sx = curr->sx * (*sx);
*sy = curr->sy * (*sy);
}
}
void ClipRect_Activate (ClipRect* self) {
if (self && self->enabled) {
Vec2i vpSize;
Viewport_GetSize(&vpSize);
GLCALL(glEnable(GL_SCISSOR_TEST))
float x = self->x;
float y = self->y;
float sx = self->sx;
float sy = self->sy;
TransformRect(&x, &y, &sx, &sy);
GLCALL(glScissor(
(int)x,
vpSize.y - (int)(y + sy),
(int)sx,
(int)sy))
} else {
GLCALL(glDisable(GL_SCISSOR_TEST))
}
}
void ClipRect_Push (float x, float y, float sx, float sy) {
if (rectIndex + 1 >= MAX_STACK_DEPTH)
Fatal("ClipRect_Push: Maximum stack depth exceeded");
rectIndex++;
ClipRect* curr = rect + rectIndex;
curr->x = x;
curr->y = y;
curr->sx = sx;
curr->sy = sy;
curr->enabled = true;
ClipRect_Activate(curr);
}
void ClipRect_PushCombined (float x, float y, float sx, float sy) {
ClipRect* curr = rect + rectIndex;
if (rectIndex >= 0 && curr->enabled) {
float maxX = x + sx;
float maxY = y + sy;
x = Max(x, curr->x);
y = Max(y, curr->y);
ClipRect_Push(x, y,
Min(maxX, curr->x + curr->sx) - x,
Min(maxY, curr->y + curr->sy) - y
);
} else {
ClipRect_Push(x, y, sx, sy);
}
}
void ClipRect_PushDisabled () {
if (rectIndex + 1 >= MAX_STACK_DEPTH)
Fatal("ClipRect_Push: Maximum stack depth exceeded");
rectIndex++;
ClipRect* curr = rect + rectIndex;
curr->enabled = false;
ClipRect_Activate(curr);
}
void ClipRect_PushTransform (float tx, float ty, float sx, float sy) {
if (transformIndex + 1 >= MAX_STACK_DEPTH)
Fatal("ClipRect_PushTransform: Maximum stack depth exceeded");
transformIndex++;
ClipRectTransform* curr = transform + transformIndex;
curr->tx = tx;
curr->ty = ty;
curr->sx = sx;
curr->sy = sy;
if (rectIndex >= 0)
ClipRect_Activate(rect + rectIndex);
}
void ClipRect_Pop () {
if (rectIndex < 0)
Fatal("ClipRect_Pop: Attempting to pop an empty stack");
rectIndex--;
ClipRect_Activate(rectIndex >= 0 ? rect + rectIndex : 0);
}
void ClipRect_PopTransform () {
if (transformIndex < 0)
Fatal("ClipRect_PopTransform: Attempting to pop an empty stack");
transformIndex--;
if (rectIndex >= 0)
ClipRect_Activate(rect + rectIndex);
}