mirror of https://github.com/adamdruppe/arsd.git
gradient stuff and windows tweaks
This commit is contained in:
parent
b698de70fc
commit
9e9be7cc0d
318
simpledisplay.d
318
simpledisplay.d
|
|
@ -3786,6 +3786,7 @@ struct EventLoopImpl {
|
||||||
}
|
}
|
||||||
} else if(waitResult == handles.length + WAIT_OBJECT_0) {
|
} else if(waitResult == handles.length + WAIT_OBJECT_0) {
|
||||||
// message ready
|
// message ready
|
||||||
|
int count;
|
||||||
while(PeekMessage(&message, null, 0, 0, PM_NOREMOVE)) { // need to peek since sometimes MsgWaitForMultipleObjectsEx returns even though GetMessage can block. tbh i don't fully understand it but the docs say it is foreground activation
|
while(PeekMessage(&message, null, 0, 0, PM_NOREMOVE)) { // need to peek since sometimes MsgWaitForMultipleObjectsEx returns even though GetMessage can block. tbh i don't fully understand it but the docs say it is foreground activation
|
||||||
ret = GetMessage(&message, null, 0, 0);
|
ret = GetMessage(&message, null, 0, 0);
|
||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
|
|
@ -3793,6 +3794,10 @@ struct EventLoopImpl {
|
||||||
TranslateMessage(&message);
|
TranslateMessage(&message);
|
||||||
DispatchMessage(&message);
|
DispatchMessage(&message);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
if(count > 10)
|
||||||
|
break; // take the opportunity to catch up on other events
|
||||||
|
|
||||||
if(ret == 0) // WM_QUIT
|
if(ret == 0) // WM_QUIT
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -8535,7 +8540,7 @@ struct ScreenPainter {
|
||||||
impl.drawArc(upperLeft.x, upperLeft.y, width, height, start, finish);
|
impl.drawArc(upperLeft.x, upperLeft.y, width, height, start, finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this function draws a circle with the drawEllipse() function above, it requires the upper left point and the radius
|
/// this function draws a circle with the drawEllipse() function above, it requires the upper left point and the radius
|
||||||
void drawCircle(Point upperLeft, int diameter) {
|
void drawCircle(Point upperLeft, int diameter) {
|
||||||
drawEllipse(upperLeft, Point(upperLeft.x + diameter, upperLeft.y + diameter));
|
drawEllipse(upperLeft, Point(upperLeft.x + diameter, upperLeft.y + diameter));
|
||||||
}
|
}
|
||||||
|
|
@ -8657,6 +8662,26 @@ class Sprite : CapableOfBeingDrawnUpon {
|
||||||
private Picture xrenderPicture;
|
private Picture xrenderPicture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(X11)
|
||||||
|
private static void requireXRender() {
|
||||||
|
if(!XRenderLibrary.loadAttempted) {
|
||||||
|
XRenderLibrary.loadDynamicLibrary();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!XRenderLibrary.loadSuccessful)
|
||||||
|
throw new Exception("XRender library load failure");
|
||||||
|
|
||||||
|
auto display = XDisplayConnection.get;
|
||||||
|
|
||||||
|
// FIXME: if we migrate X displays, these need to be changed
|
||||||
|
if(RGB24 is null)
|
||||||
|
RGB24 = XRenderFindStandardFormat(display, PictStandardRGB24);
|
||||||
|
if(ARGB32 is null)
|
||||||
|
ARGB32 = XRenderFindStandardFormat(display, PictStandardARGB32);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected this() {}
|
||||||
|
|
||||||
this(SimpleWindow win, int width, int height, bool enableAlpha = false) {
|
this(SimpleWindow win, int width, int height, bool enableAlpha = false) {
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
|
|
@ -8666,22 +8691,12 @@ class Sprite : CapableOfBeingDrawnUpon {
|
||||||
auto display = XDisplayConnection.get();
|
auto display = XDisplayConnection.get();
|
||||||
|
|
||||||
if(enableAlpha) {
|
if(enableAlpha) {
|
||||||
if(!XRenderLibrary.loadAttempted) {
|
requireXRender();
|
||||||
XRenderLibrary.loadDynamicLibrary();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!XRenderLibrary.loadSuccessful)
|
|
||||||
throw new Exception("XRender library load failure");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = XCreatePixmap(display, cast(Drawable) win.window, width, height, enableAlpha ? 32 : DefaultDepthOfDisplay(display));
|
handle = XCreatePixmap(display, cast(Drawable) win.window, width, height, enableAlpha ? 32 : DefaultDepthOfDisplay(display));
|
||||||
|
|
||||||
if(enableAlpha) {
|
if(enableAlpha) {
|
||||||
if(RGB24 is null)
|
|
||||||
RGB24 = XRenderFindStandardFormat(display, PictStandardRGB24);
|
|
||||||
if(ARGB32 is null)
|
|
||||||
ARGB32 = XRenderFindStandardFormat(display, PictStandardARGB32);
|
|
||||||
|
|
||||||
XRenderPictureAttributes attrs;
|
XRenderPictureAttributes attrs;
|
||||||
xrenderPicture = XRenderCreatePicture(display, handle, ARGB32, 0, &attrs);
|
xrenderPicture = XRenderCreatePicture(display, handle, ARGB32, 0, &attrs);
|
||||||
}
|
}
|
||||||
|
|
@ -8816,6 +8831,213 @@ class Sprite : CapableOfBeingDrawnUpon {
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
Represents a display-side gradient pseudo-image. Actually construct it with [LinearGradient], [RadialGradient], or [ConicalGradient].
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 20, 2021 (dub v10.4)
|
||||||
|
+/
|
||||||
|
abstract class Gradient : Sprite {
|
||||||
|
protected this(int w, int h) {
|
||||||
|
version(X11) {
|
||||||
|
Sprite.requireXRender();
|
||||||
|
|
||||||
|
super();
|
||||||
|
enableAlpha = true;
|
||||||
|
_width = w;
|
||||||
|
_height = h;
|
||||||
|
} else version(Windows) {
|
||||||
|
super(null, w, h, true); // on Windows i'm just making a bitmap myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
final void forEachPixel(scope Color delegate(int x, int y) dg) {
|
||||||
|
auto ptr = rawData;
|
||||||
|
foreach(j; 0 .. _height)
|
||||||
|
foreach(i; 0 .. _width) {
|
||||||
|
auto color = dg(i, _height - j - 1); // cuz of upside down bitmap
|
||||||
|
*rawData = (color.a * color.b) / 255; rawData++;
|
||||||
|
*rawData = (color.a * color.g) / 255; rawData++;
|
||||||
|
*rawData = (color.a * color.r) / 255; rawData++;
|
||||||
|
*rawData = color.a; rawData++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version(X11)
|
||||||
|
protected void helper(scope Stop[] stops, scope Picture delegate(scope XFixed[] stopsPositions, scope XRenderColor[] colors) dg) {
|
||||||
|
assert(stops.length > 0);
|
||||||
|
assert(stops.length <= 16, "I got lazy with buffers");
|
||||||
|
|
||||||
|
XFixed[16] stopsPositions = void;
|
||||||
|
XRenderColor[16] colors = void;
|
||||||
|
|
||||||
|
foreach(idx, stop; stops) {
|
||||||
|
stopsPositions[idx] = cast(int)(stop.percentage * ushort.max);
|
||||||
|
auto c = stop.c;
|
||||||
|
colors[idx] = XRenderColor(
|
||||||
|
cast(ushort)(c.r * ushort.max / 255),
|
||||||
|
cast(ushort)(c.g * ushort.max / 255),
|
||||||
|
cast(ushort)(c.b * ushort.max / 255),
|
||||||
|
cast(ushort)(c.a * ubyte.max) // max value here is fractional
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
xrenderPicture = dg(stopsPositions, colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
static struct Stop {
|
||||||
|
float percentage; /// between 0 and 1.0
|
||||||
|
Color c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Creates a linear gradient between p1 and p2.
|
||||||
|
|
||||||
|
X ONLY RIGHT NOW
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 20, 2021 (dub v10.4)
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
Not yet implemented on Windows.
|
||||||
|
+/
|
||||||
|
class LinearGradient : Gradient {
|
||||||
|
/++
|
||||||
|
|
||||||
|
+/
|
||||||
|
this(Point p1, Point p2, Stop[] stops...) {
|
||||||
|
super(p2.x, p2.y);
|
||||||
|
|
||||||
|
version(X11) {
|
||||||
|
XLinearGradient gradient;
|
||||||
|
gradient.p1 = XPointFixed(p1.x * ushort.max, p1.y * ushort.max);
|
||||||
|
gradient.p2 = XPointFixed(p2.x * ushort.max, p2.y * ushort.max);
|
||||||
|
|
||||||
|
helper(stops, (stopsPositions, colors) {
|
||||||
|
return XRenderCreateLinearGradient(
|
||||||
|
XDisplayConnection.get,
|
||||||
|
&gradient,
|
||||||
|
stopsPositions.ptr,
|
||||||
|
colors.ptr,
|
||||||
|
cast(int) stops.length);
|
||||||
|
});
|
||||||
|
} else version(Windows) {
|
||||||
|
// FIXME
|
||||||
|
forEachPixel((int x, int y) {
|
||||||
|
import core.stdc.math;
|
||||||
|
|
||||||
|
//sqrtf(
|
||||||
|
|
||||||
|
return Color.transparent;
|
||||||
|
// return Color(x * 2, y * 2, 0, 128); // this result is so beautiful
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
A conical gradient goes from color to color around a circumference from a center point.
|
||||||
|
|
||||||
|
X ONLY RIGHT NOW
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 20, 2021 (dub v10.4)
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
Not yet implemented on Windows.
|
||||||
|
+/
|
||||||
|
class ConicalGradient : Gradient {
|
||||||
|
/++
|
||||||
|
|
||||||
|
+/
|
||||||
|
this(Point center, float angleInDegrees, Stop[] stops...) {
|
||||||
|
super(center.x * 2, center.y * 2);
|
||||||
|
|
||||||
|
version(X11) {
|
||||||
|
XConicalGradient gradient;
|
||||||
|
gradient.center = XPointFixed(center.x * ushort.max, center.y * ushort.max);
|
||||||
|
gradient.angle = cast(int)(angleInDegrees * ushort.max);
|
||||||
|
|
||||||
|
helper(stops, (stopsPositions, colors) {
|
||||||
|
return XRenderCreateConicalGradient(
|
||||||
|
XDisplayConnection.get,
|
||||||
|
&gradient,
|
||||||
|
stopsPositions.ptr,
|
||||||
|
colors.ptr,
|
||||||
|
cast(int) stops.length);
|
||||||
|
});
|
||||||
|
} else version(Windows) {
|
||||||
|
// FIXME
|
||||||
|
forEachPixel((int x, int y) {
|
||||||
|
import core.stdc.math;
|
||||||
|
|
||||||
|
//sqrtf(
|
||||||
|
|
||||||
|
return Color.transparent;
|
||||||
|
// return Color(x * 2, y * 2, 0, 128); // this result is so beautiful
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
A radial gradient goes from color to color based on distance from the center.
|
||||||
|
It is like rings of color.
|
||||||
|
|
||||||
|
X ONLY RIGHT NOW
|
||||||
|
|
||||||
|
|
||||||
|
More specifically, you create two circles: an inner circle and an outer circle.
|
||||||
|
The gradient is only drawn in the area outside the inner circle but inside the outer
|
||||||
|
circle. The closest line between those two circles forms the line for the gradient
|
||||||
|
and the stops are calculated the same as the [LinearGradient]. Then it just sweeps around.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 20, 2021 (dub v10.4)
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
Not yet implemented on Windows.
|
||||||
|
+/
|
||||||
|
class RadialGradient : Gradient {
|
||||||
|
/++
|
||||||
|
|
||||||
|
+/
|
||||||
|
this(Point innerCenter, float innerRadius, Point outerCenter, float outerRadius, Stop[] stops...) {
|
||||||
|
super(cast(int)(outerCenter.x + outerRadius + 0.5), cast(int)(outerCenter.y + outerRadius + 0.5));
|
||||||
|
|
||||||
|
version(X11) {
|
||||||
|
XRadialGradient gradient;
|
||||||
|
gradient.inner = XCircle(innerCenter.x * ushort.max, innerCenter.y * ushort.max, cast(int) (innerRadius * ushort.max));
|
||||||
|
gradient.outer = XCircle(outerCenter.x * ushort.max, outerCenter.y * ushort.max, cast(int) (outerRadius * ushort.max));
|
||||||
|
|
||||||
|
helper(stops, (stopsPositions, colors) {
|
||||||
|
return XRenderCreateRadialGradient(
|
||||||
|
XDisplayConnection.get,
|
||||||
|
&gradient,
|
||||||
|
stopsPositions.ptr,
|
||||||
|
colors.ptr,
|
||||||
|
cast(int) stops.length);
|
||||||
|
});
|
||||||
|
} else version(Windows) {
|
||||||
|
// FIXME
|
||||||
|
forEachPixel((int x, int y) {
|
||||||
|
import core.stdc.math;
|
||||||
|
|
||||||
|
//sqrtf(
|
||||||
|
|
||||||
|
return Color.transparent;
|
||||||
|
// return Color(x * 2, y * 2, 0, 128); // this result is so beautiful
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/+
|
||||||
NOT IMPLEMENTED
|
NOT IMPLEMENTED
|
||||||
|
|
||||||
A display-stored image optimized for relatively quick drawing, like
|
A display-stored image optimized for relatively quick drawing, like
|
||||||
|
|
@ -10564,6 +10786,9 @@ version(Windows) {
|
||||||
SelectObject(hdcBmp, oldPen);
|
SelectObject(hdcBmp, oldPen);
|
||||||
DeleteDC(hdcBmp);
|
DeleteDC(hdcBmp);
|
||||||
|
|
||||||
|
bmpWidth = width;
|
||||||
|
bmpHeight = height;
|
||||||
|
|
||||||
ReleaseDC(hwnd, hdc); // we keep this in opengl mode since it is a class member now
|
ReleaseDC(hwnd, hdc); // we keep this in opengl mode since it is a class member now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10793,6 +11018,9 @@ version(Windows) {
|
||||||
int oldHeight;
|
int oldHeight;
|
||||||
bool inSizeMove;
|
bool inSizeMove;
|
||||||
|
|
||||||
|
int bmpWidth;
|
||||||
|
int bmpHeight;
|
||||||
|
|
||||||
// the extern(Windows) wndproc should just forward to this
|
// the extern(Windows) wndproc should just forward to this
|
||||||
LRESULT windowProcedure(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
|
LRESULT windowProcedure(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
|
||||||
assert(hwnd is this.hwnd);
|
assert(hwnd is this.hwnd);
|
||||||
|
|
@ -10841,6 +11069,11 @@ version(Windows) {
|
||||||
if(!inSizeMove)
|
if(!inSizeMove)
|
||||||
goto size_changed;
|
goto size_changed;
|
||||||
break;
|
break;
|
||||||
|
/+
|
||||||
|
case WM_SIZING:
|
||||||
|
import std.stdio; writeln("size");
|
||||||
|
break;
|
||||||
|
+/
|
||||||
// I don't like the tearing I get when redrawing on WM_SIZE
|
// I don't like the tearing I get when redrawing on WM_SIZE
|
||||||
// (I know there's other ways to fix that but I don't like that behavior anyway)
|
// (I know there's other ways to fix that but I don't like that behavior anyway)
|
||||||
// so instead it is going to redraw only at the end of a size.
|
// so instead it is going to redraw only at the end of a size.
|
||||||
|
|
@ -10851,39 +11084,44 @@ version(Windows) {
|
||||||
break;
|
break;
|
||||||
case 0x0232: /* WM_EXITSIZEMOVE */
|
case 0x0232: /* WM_EXITSIZEMOVE */
|
||||||
inSizeMove = false;
|
inSizeMove = false;
|
||||||
|
|
||||||
|
size_changed:
|
||||||
|
|
||||||
// nothing relevant changed, don't bother redrawing
|
// nothing relevant changed, don't bother redrawing
|
||||||
if(oldWidth == width && oldHeight == height)
|
if(oldWidth == width && oldHeight == height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
size_changed:
|
|
||||||
|
|
||||||
// note: OpenGL windows don't use a backing bmp, so no need to change them
|
// note: OpenGL windows don't use a backing bmp, so no need to change them
|
||||||
// if resizability is anything other than allowResizing, it is meant to either stretch the one image or just do nothing
|
// if resizability is anything other than allowResizing, it is meant to either stretch the one image or just do nothing
|
||||||
if(openglMode == OpenGlOptions.no) { // && resizability == Resizability.allowResizing) {
|
if(openglMode == OpenGlOptions.no) { // && resizability == Resizability.allowResizing) {
|
||||||
// gotta get the double buffer bmp to match the window
|
// gotta get the double buffer bmp to match the window
|
||||||
// FIXME: could this be more efficient? It isn't really necessary to make
|
// FIXME: could this be more efficient? it never relinquishes a large bitmap
|
||||||
// a new buffer if we're sizing down at least.
|
if(width > bmpWidth || height > bmpHeight) {
|
||||||
auto hdc = GetDC(hwnd);
|
auto hdc = GetDC(hwnd);
|
||||||
auto oldBuffer = buffer;
|
auto oldBuffer = buffer;
|
||||||
buffer = CreateCompatibleBitmap(hdc, width, height);
|
buffer = CreateCompatibleBitmap(hdc, width, height);
|
||||||
|
|
||||||
auto hdcBmp = CreateCompatibleDC(hdc);
|
auto hdcBmp = CreateCompatibleDC(hdc);
|
||||||
auto oldBmp = SelectObject(hdcBmp, buffer);
|
auto oldBmp = SelectObject(hdcBmp, buffer);
|
||||||
|
|
||||||
auto hdcOldBmp = CreateCompatibleDC(hdc);
|
auto hdcOldBmp = CreateCompatibleDC(hdc);
|
||||||
auto oldOldBmp = SelectObject(hdcOldBmp, oldBmp);
|
auto oldOldBmp = SelectObject(hdcOldBmp, oldBmp);
|
||||||
|
|
||||||
BitBlt(hdcBmp, 0, 0, width, height, hdcOldBmp, oldWidth, oldHeight, SRCCOPY);
|
BitBlt(hdcBmp, 0, 0, width, height, hdcOldBmp, oldWidth, oldHeight, SRCCOPY);
|
||||||
|
|
||||||
SelectObject(hdcOldBmp, oldOldBmp);
|
bmpWidth = width;
|
||||||
DeleteDC(hdcOldBmp);
|
bmpHeight = height;
|
||||||
|
|
||||||
SelectObject(hdcBmp, oldBmp);
|
SelectObject(hdcOldBmp, oldOldBmp);
|
||||||
DeleteDC(hdcBmp);
|
DeleteDC(hdcOldBmp);
|
||||||
|
|
||||||
ReleaseDC(hwnd, hdc);
|
SelectObject(hdcBmp, oldBmp);
|
||||||
|
DeleteDC(hdcBmp);
|
||||||
|
|
||||||
DeleteObject(oldBuffer);
|
ReleaseDC(hwnd, hdc);
|
||||||
|
|
||||||
|
DeleteObject(oldBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version(without_opengl) {} else
|
version(without_opengl) {} else
|
||||||
|
|
@ -11067,7 +11305,7 @@ version(Windows) {
|
||||||
rawData[offset + 1] = (a * what[idx + 1]) / 255; // g
|
rawData[offset + 1] = (a * what[idx + 1]) / 255; // g
|
||||||
rawData[offset + 0] = (a * what[idx + 2]) / 255; // b
|
rawData[offset + 0] = (a * what[idx + 2]) / 255; // b
|
||||||
rawData[offset + 3] = a; // a
|
rawData[offset + 3] = a; // a
|
||||||
premultiplyBgra(rawData[offset .. offset + 4]);
|
//premultiplyBgra(rawData[offset .. offset + 4]);
|
||||||
offset++;
|
offset++;
|
||||||
} else {
|
} else {
|
||||||
rawData[offset + 2] = what[idx + 0]; // r
|
rawData[offset + 2] = what[idx + 0]; // r
|
||||||
|
|
@ -16897,6 +17135,8 @@ extern(System) nothrow @nogc {
|
||||||
GLint glGetUniformLocation(GLuint, const(GLchar)*);
|
GLint glGetUniformLocation(GLuint, const(GLchar)*);
|
||||||
void glGenBuffers(GLsizei, GLuint*);
|
void glGenBuffers(GLsizei, GLuint*);
|
||||||
void glUniform4fv(GLint, GLsizei, const(GLfloat)*);
|
void glUniform4fv(GLint, GLsizei, const(GLfloat)*);
|
||||||
|
void glUniform1f(GLint, float);
|
||||||
|
void glUniform2f(GLint, float, float);
|
||||||
void glUniform4f(GLint, float, float, float, float);
|
void glUniform4f(GLint, float, float, float, float);
|
||||||
void glColorMask(GLboolean, GLboolean, GLboolean, GLboolean);
|
void glColorMask(GLboolean, GLboolean, GLboolean, GLboolean);
|
||||||
void glStencilOpSeparate(GLenum, GLenum, GLenum, GLenum);
|
void glStencilOpSeparate(GLenum, GLenum, GLenum, GLenum);
|
||||||
|
|
@ -17323,8 +17563,19 @@ final class OpenGlShader {
|
||||||
|
|
||||||
/// Assigns the 4 floats. You will probably have to call this via the .opAssign name
|
/// Assigns the 4 floats. You will probably have to call this via the .opAssign name
|
||||||
void opAssign(float x, float y, float z, float w) {
|
void opAssign(float x, float y, float z, float w) {
|
||||||
|
if(id != -1)
|
||||||
glUniform4f(id, x, y, z, w);
|
glUniform4f(id, x, y, z, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opAssign(float x) {
|
||||||
|
if(id != -1)
|
||||||
|
glUniform1f(id, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void opAssign(float x, float y) {
|
||||||
|
if(id != -1)
|
||||||
|
glUniform2f(id, x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct UniformsHelper {
|
static struct UniformsHelper {
|
||||||
|
|
@ -17332,8 +17583,9 @@ final class OpenGlShader {
|
||||||
|
|
||||||
@property Uniform opDispatch(string name)() {
|
@property Uniform opDispatch(string name)() {
|
||||||
auto i = glGetUniformLocation(_shader.shaderProgram, name.ptr);
|
auto i = glGetUniformLocation(_shader.shaderProgram, name.ptr);
|
||||||
if(i == -1)
|
// FIXME: decide what to do here; the exception is liable to be swallowed by the event syste
|
||||||
throw new Exception("Could not find uniform " ~ name);
|
//if(i == -1)
|
||||||
|
//throw new Exception("Could not find uniform " ~ name);
|
||||||
return Uniform(i);
|
return Uniform(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue