mirror of https://github.com/adamdruppe/arsd.git
#279 - facility for spritesheets
This commit is contained in:
parent
c4c52d8723
commit
7198a9f15e
159
simpledisplay.d
159
simpledisplay.d
|
@ -1753,6 +1753,42 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
`close` is one of the few methods that can be called from other threads. This `shared` overload reflects that.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Overload added on March 7, 2021.
|
||||||
|
+/
|
||||||
|
void close() shared {
|
||||||
|
(cast() this).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
|
||||||
|
+/
|
||||||
|
void maximize() {
|
||||||
|
version(Windows)
|
||||||
|
ShowWindow(impl.hwnd, SW_MAXIMIZE);
|
||||||
|
else version(X11) {
|
||||||
|
// I actually could set both at once...
|
||||||
|
setNetWmStateAtom(this.impl.window, GetAtom!("_NET_WM_STATE_MAXIMIZED_VERT", false)(XDisplayConnection.get), true, GetAtom!("_NET_WM_STATE_MAXIMIZED_HORZ", false)(XDisplayConnection.get));
|
||||||
|
|
||||||
|
// also note _NET_WM_STATE_FULLSCREEN
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Note: only implemented on Windows. No-op on other platforms. You may want to use [hide] instead.
|
||||||
|
|
||||||
|
+/
|
||||||
|
void minimize() {
|
||||||
|
version(Windows)
|
||||||
|
ShowWindow(impl.hwnd, SW_MINIMIZE);
|
||||||
|
//else version(X11)
|
||||||
|
//setNetWmStateAtom(this, GetAtom!("_NET_WM_STATE_MINIMIZED", false)(XDisplayConnection.get), true);
|
||||||
|
}
|
||||||
|
|
||||||
/// Alias for `hidden = false`
|
/// Alias for `hidden = false`
|
||||||
void show() {
|
void show() {
|
||||||
hidden = false;
|
hidden = false;
|
||||||
|
@ -7448,8 +7484,9 @@ class OperatingSystemFont {
|
||||||
int height() {
|
int height() {
|
||||||
version(X11) {
|
version(X11) {
|
||||||
version(with_xft)
|
version(with_xft)
|
||||||
if(isXft && xftFont !is null)
|
if(isXft && xftFont !is null) {
|
||||||
return xftFont.height;
|
return xftFont.ascent + xftFont.descent; // i don't use height here because it doesn't include the baseline pixel
|
||||||
|
}
|
||||||
if(font is null)
|
if(font is null)
|
||||||
return 0;
|
return 0;
|
||||||
return font.max_bounds.ascent + font.max_bounds.descent;
|
return font.max_bounds.ascent + font.max_bounds.descent;
|
||||||
|
@ -7766,13 +7803,22 @@ struct ScreenPainter {
|
||||||
drawRectangle(Point(0, 0), window.width, window.height);
|
drawRectangle(Point(0, 0), window.width, window.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
/++
|
||||||
|
Draws a pixmap (represented by the [Sprite] class) on the drawable.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
upperLeft = point on the window where the upper left corner of the image will be drawn
|
||||||
|
imageUpperLeft = point on the image to start the slice to draw
|
||||||
|
sliceSize = size of the slice of the image to draw on the window. If width or height is 0, it uses the entire width or height of the image.
|
||||||
|
History:
|
||||||
|
The `imageUpperLeft` and `sliceSize` parameters were added on March 11, 2021 (dub v9.3.0)
|
||||||
|
+/
|
||||||
version(OSXCocoa) {} else // NotYetImplementedException
|
version(OSXCocoa) {} else // NotYetImplementedException
|
||||||
void drawPixmap(Sprite s, Point upperLeft) {
|
void drawPixmap(Sprite s, Point upperLeft, Point imageUpperLeft = Point(0, 0), Size sliceSize = Size(0, 0)) {
|
||||||
if(impl is null) return;
|
if(impl is null) return;
|
||||||
if(isClipped(upperLeft, s.width, s.height)) return;
|
if(isClipped(upperLeft, s.width, s.height)) return;
|
||||||
transform(upperLeft);
|
transform(upperLeft);
|
||||||
impl.drawPixmap(s, upperLeft.x, upperLeft.y);
|
impl.drawPixmap(s, upperLeft.x, upperLeft.y, imageUpperLeft.x, imageUpperLeft.y, sliceSize.width, sliceSize.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -8122,9 +8168,16 @@ class Sprite : CapableOfBeingDrawnUpon {
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Draws the image on the specified painter at the specified point. The point is the upper-left point where the image will be drawn.
|
Draws the image on the specified painter at the specified point. The point is the upper-left point where the image will be drawn.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
where = point on the window where the upper left corner of the image will be drawn
|
||||||
|
imageUpperLeft = point on the image to start the slice to draw
|
||||||
|
sliceSize = size of the slice of the image to draw on the window. If width or height is 0, it uses the entire width or height of the image.
|
||||||
|
History:
|
||||||
|
The `imageUpperLeft` and `sliceSize` parameters were added on March 11, 2021 (dub v9.3.0)
|
||||||
+/
|
+/
|
||||||
void drawAt(ScreenPainter painter, Point where) {
|
void drawAt(ScreenPainter painter, Point where, Point imageUpperLeft = Point(0, 0), Size sliceSize = Size(0, 0)) {
|
||||||
painter.drawPixmap(this, where);
|
painter.drawPixmap(this, where, imageUpperLeft, sliceSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8433,6 +8486,79 @@ private void guiThreadFinalize() {
|
||||||
runPendingRunInGuiThreadDelegates();
|
runPendingRunInGuiThreadDelegates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/+
|
||||||
|
interface IPromise {
|
||||||
|
void reportProgress(int current, int max, string message);
|
||||||
|
|
||||||
|
/+ // not formally in cuz of templates but still
|
||||||
|
IPromise Then();
|
||||||
|
IPromise Catch();
|
||||||
|
IPromise Finally();
|
||||||
|
+/
|
||||||
|
}
|
||||||
|
|
||||||
|
/+
|
||||||
|
auto promise = async({ ... });
|
||||||
|
promise.Then(whatever).
|
||||||
|
Then(whateverelse).
|
||||||
|
Catch((exception) { });
|
||||||
|
|
||||||
|
|
||||||
|
A promise is run inside a fiber and it looks something like:
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto res = whatever();
|
||||||
|
auto res2 = whateverelse(res);
|
||||||
|
} catch(Exception e) {
|
||||||
|
{ }(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
When a thing succeeds, it is passed as an arg to the next
|
||||||
|
+/
|
||||||
|
class Promise(T) : IPromise {
|
||||||
|
auto Then() { return null; }
|
||||||
|
auto Catch() { return null; }
|
||||||
|
auto Finally() { return null; }
|
||||||
|
|
||||||
|
// wait for it to resolve and return the value, or rethrow the error if that occurred.
|
||||||
|
// cannot be called from the gui thread, but this is caught at runtime instead of compile time.
|
||||||
|
T await();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Task {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Resolvable(T) : Task {
|
||||||
|
void run();
|
||||||
|
|
||||||
|
void resolve(T);
|
||||||
|
|
||||||
|
Resolvable!T then(void delegate(T)); // returns a new promise
|
||||||
|
Resolvable!T error(Throwable); // js catch
|
||||||
|
Resolvable!T completed(); // js finally
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Runs `work` in a helper thread and sends its return value back to the main gui
|
||||||
|
thread as the argument to `uponCompletion`. If `work` throws, the exception is
|
||||||
|
sent to the `uponThrown` if given, or if null, rethrown from the event loop to
|
||||||
|
kill the program.
|
||||||
|
|
||||||
|
You can call reportProgress(position, max, message) to update your parent window
|
||||||
|
on your progress.
|
||||||
|
|
||||||
|
I should also use `shared` methods. FIXME
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added March 6, 2021 (dub version 9.3).
|
||||||
|
+/
|
||||||
|
void runInWorkerThread(T)(T delegate(Task) work, void delegate(T) uponCompletion) {
|
||||||
|
uponCompletion(work(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
+/
|
||||||
|
|
||||||
/// Used internal to dispatch events to various classes.
|
/// Used internal to dispatch events to various classes.
|
||||||
interface CapableOfHandlingNativeEvent {
|
interface CapableOfHandlingNativeEvent {
|
||||||
NativeEventHandler getNativeEventHandler();
|
NativeEventHandler getNativeEventHandler();
|
||||||
|
@ -9412,7 +9538,7 @@ version(Windows) {
|
||||||
DeleteDC(hdcMem);
|
DeleteDC(hdcMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawPixmap(Sprite s, int x, int y) {
|
void drawPixmap(Sprite s, int x, int y, int ix, int iy, int w, int h) {
|
||||||
BITMAP bm;
|
BITMAP bm;
|
||||||
|
|
||||||
HDC hdcMem = CreateCompatibleDC(hdc);
|
HDC hdcMem = CreateCompatibleDC(hdc);
|
||||||
|
@ -9421,7 +9547,7 @@ version(Windows) {
|
||||||
GetObject(s.handle, bm.sizeof, &bm);
|
GetObject(s.handle, bm.sizeof, &bm);
|
||||||
|
|
||||||
// or should I AlphaBlend!??!?! note it is supposed to be premultiplied http://www.fengyuan.com/article/alphablend.html
|
// or should I AlphaBlend!??!?! note it is supposed to be premultiplied http://www.fengyuan.com/article/alphablend.html
|
||||||
BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
|
BitBlt(hdc, x, y, w ? w : bm.bmWidth, h ? h : bm.bmHeight, hdcMem, ix, iy, SRCCOPY);
|
||||||
|
|
||||||
SelectObject(hdcMem, hbmOld);
|
SelectObject(hdcMem, hbmOld);
|
||||||
DeleteDC(hdcMem);
|
DeleteDC(hdcMem);
|
||||||
|
@ -10646,8 +10772,8 @@ version(X11) {
|
||||||
XPutImage(display, d, gc, i.handle, ix, iy, x, y, w, h);
|
XPutImage(display, d, gc, i.handle, ix, iy, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawPixmap(Sprite s, int x, int y) {
|
void drawPixmap(Sprite s, int x, int y, int ix, int iy, int w, int h) {
|
||||||
XCopyArea(display, s.handle, d, gc, 0, 0, s.width, s.height, x, y);
|
XCopyArea(display, s.handle, d, gc, ix, iy, w ? w : s.width, h ? h : s.height, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fontHeight() {
|
int fontHeight() {
|
||||||
|
@ -18639,8 +18765,11 @@ void demandAttention(SimpleWindow window, bool needs = true) {
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
void demandAttention(Window window, bool needs = true) {
|
void demandAttention(Window window, bool needs = true) {
|
||||||
|
setNetWmStateAtom(window, GetAtom!("_NET_WM_STATE_DEMANDS_ATTENTION", false)(XDisplayConnection.get), needs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNetWmStateAtom(Window window, Atom atom, bool set = true, Atom atom2 = None) {
|
||||||
auto display = XDisplayConnection.get();
|
auto display = XDisplayConnection.get();
|
||||||
auto atom = XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", true);
|
|
||||||
if(atom == None)
|
if(atom == None)
|
||||||
return; // non-failure error
|
return; // non-failure error
|
||||||
//auto atom2 = GetAtom!"_NET_WM_STATE_SHADED"(display);
|
//auto atom2 = GetAtom!"_NET_WM_STATE_SHADED"(display);
|
||||||
|
@ -18651,10 +18780,10 @@ void demandAttention(Window window, bool needs = true) {
|
||||||
xclient.window = window;
|
xclient.window = window;
|
||||||
xclient.message_type = GetAtom!"_NET_WM_STATE"(display);
|
xclient.message_type = GetAtom!"_NET_WM_STATE"(display);
|
||||||
xclient.format = 32;
|
xclient.format = 32;
|
||||||
xclient.data.l[0] = needs ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
xclient.data.l[0] = set ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||||
xclient.data.l[1] = atom;
|
xclient.data.l[1] = atom;
|
||||||
//xclient.data.l[2] = atom2;
|
xclient.data.l[2] = atom2;
|
||||||
// [2] == a second property
|
xclient.data.l[3] = 1;
|
||||||
// [3] == source. 0 == unknown, 1 == app, 2 == else
|
// [3] == source. 0 == unknown, 1 == app, 2 == else
|
||||||
|
|
||||||
XSendEvent(
|
XSendEvent(
|
||||||
|
|
Loading…
Reference in New Issue