mirror of https://github.com/adamdruppe/arsd.git
catchup
This commit is contained in:
parent
c2e8c8bcce
commit
5419cfed70
47
color.d
47
color.d
|
@ -1577,6 +1577,8 @@ struct Rectangle {
|
|||
Implements a flood fill algorithm, like the bucket tool in
|
||||
MS Paint.
|
||||
|
||||
Note it assumes `what.length == width*height`.
|
||||
|
||||
Params:
|
||||
what = the canvas to work with, arranged as top to bottom, left to right elements
|
||||
width = the width of the canvas
|
||||
|
@ -1585,13 +1587,17 @@ struct Rectangle {
|
|||
replacement = the replacement value
|
||||
x = the x-coordinate to start the fill (think of where the user clicked in Paint)
|
||||
y = the y-coordinate to start the fill
|
||||
additionalCheck = A custom additional check to perform on each square before continuing. Returning true means keep flooding, returning false means stop.
|
||||
additionalCheck = A custom additional check to perform on each square before continuing. Returning true means keep flooding, returning false means stop. If null, it is not used.
|
||||
+/
|
||||
void floodFill(T)(
|
||||
T[] what, int width, int height, // the canvas to inspect
|
||||
T target, T replacement, // fill params
|
||||
int x, int y, bool delegate(int x, int y) @safe additionalCheck) // the node
|
||||
|
||||
// in(what.length == width * height) // gdc doesn't support this syntax yet so not gonna use it until that comes out.
|
||||
{
|
||||
assert(what.length == width * height); // will use the contract above when gdc supports it
|
||||
|
||||
T node = what[y * width + x];
|
||||
|
||||
if(target == replacement) return;
|
||||
|
@ -1604,6 +1610,44 @@ void floodFill(T)(
|
|||
if(!additionalCheck(x, y))
|
||||
return;
|
||||
|
||||
Point[] queue;
|
||||
|
||||
queue ~= Point(x, y);
|
||||
|
||||
while(queue.length) {
|
||||
auto n = queue[0];
|
||||
queue = queue[1 .. $];
|
||||
//queue.assumeSafeAppend(); // lol @safe breakage
|
||||
|
||||
auto w = n;
|
||||
int offset = cast(int) (n.y * width + n.x);
|
||||
auto e = n;
|
||||
auto eoffset = offset;
|
||||
w.x--;
|
||||
offset--;
|
||||
while(w.x >= 0 && what[offset] == target && additionalCheck(w.x, w.y)) {
|
||||
w.x--;
|
||||
offset--;
|
||||
}
|
||||
while(e.x < width && what[eoffset] == target && additionalCheck(e.x, e.y)) {
|
||||
e.x++;
|
||||
eoffset++;
|
||||
}
|
||||
|
||||
// to make it inclusive again
|
||||
w.x++;
|
||||
offset++;
|
||||
foreach(o ; offset .. eoffset) {
|
||||
what[o] = replacement;
|
||||
if(w.y && what[o - width] == target && additionalCheck(w.x, w.y))
|
||||
queue ~= Point(w.x, w.y - 1);
|
||||
if(w.y + 1 < height && what[o + width] == target && additionalCheck(w.x, w.y))
|
||||
queue ~= Point(w.x, w.y + 1);
|
||||
w.x++;
|
||||
}
|
||||
}
|
||||
|
||||
/+
|
||||
what[y * width + x] = replacement;
|
||||
|
||||
if(x)
|
||||
|
@ -1621,6 +1665,7 @@ void floodFill(T)(
|
|||
if(y != height - 1)
|
||||
floodFill(what, width, height, target, replacement,
|
||||
x, y + 1, additionalCheck);
|
||||
+/
|
||||
}
|
||||
|
||||
// for scripting, so you can tag it without strictly needing to import arsd.jsvar
|
||||
|
|
|
@ -394,6 +394,7 @@ final class OpenGlTexture {
|
|||
|
||||
/// After you delete it with dispose, you may rebind it to something else with this.
|
||||
void bindFrom(TrueColorImage from) {
|
||||
assert(from !is null);
|
||||
assert(from.width > 0 && from.height > 0);
|
||||
|
||||
import core.stdc.stdlib;
|
||||
|
|
56
jsvar.d
56
jsvar.d
|
@ -549,6 +549,7 @@ struct var {
|
|||
}
|
||||
}
|
||||
|
||||
/// `if(some_var)` will call this and give behavior based on the dynamic type. Shouldn't be too surprising.
|
||||
public bool opCast(T:bool)() {
|
||||
final switch(this._type) {
|
||||
case Type.Object:
|
||||
|
@ -568,6 +569,7 @@ struct var {
|
|||
}
|
||||
}
|
||||
|
||||
/// You can foreach over a var.
|
||||
public int opApply(scope int delegate(ref var) dg) {
|
||||
foreach(i, item; this)
|
||||
if(auto result = dg(item))
|
||||
|
@ -575,6 +577,7 @@ struct var {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
public int opApply(scope int delegate(var, ref var) dg) {
|
||||
if(this.payloadType() == Type.Array) {
|
||||
foreach(i, ref v; this._payload._array)
|
||||
|
@ -606,15 +609,30 @@ struct var {
|
|||
}
|
||||
|
||||
|
||||
/// Alias for [get]. e.g. `string s = cast(string) v;`
|
||||
public T opCast(T)() {
|
||||
return this.get!T;
|
||||
}
|
||||
|
||||
/// Calls [get] for a type automatically. `int a; var b; b.putInto(a);` will auto-convert to `int`.
|
||||
public auto ref putInto(T)(ref T t) {
|
||||
return t = this.get!T;
|
||||
}
|
||||
|
||||
// if it is var, we'll just blit it over
|
||||
/++
|
||||
Assigns a value to the var. It will do necessary implicit conversions
|
||||
and wrapping.
|
||||
|
||||
You can make a method `toArsdJsvar` on your own objects to override this
|
||||
default. It should return a [var].
|
||||
|
||||
History:
|
||||
On April 20, 2020, I changed the default mode for class assignment
|
||||
to [wrapNativeObject]. Previously it was [wrapOpaquely].
|
||||
|
||||
With the new [wrapNativeObject] behavior, you can mark methods
|
||||
@[scriptable] to expose them to the script.
|
||||
+/
|
||||
public var opAssign(T)(T t) if(!is(T == var)) {
|
||||
static if(__traits(compiles, this = t.toArsdJsvar())) {
|
||||
static if(__traits(compiles, t is null)) {
|
||||
|
@ -661,7 +679,10 @@ struct var {
|
|||
// so prewrapped stuff can be easily passed.
|
||||
this._type = Type.Object;
|
||||
this._payload._object = t;
|
||||
} else static if(is(T == class) || .isScriptableOpaque!T) {
|
||||
} else static if(is(T == class)) {
|
||||
this._type = Type.Object;
|
||||
this._payload._object = wrapNativeObject(t);
|
||||
} else static if(.isScriptableOpaque!T) {
|
||||
// auto-wrap other classes with reference semantics
|
||||
this._type = Type.Object;
|
||||
this._payload._object = wrapOpaquely(t);
|
||||
|
@ -846,6 +867,31 @@ struct var {
|
|||
return null;
|
||||
}
|
||||
|
||||
/++
|
||||
Gets the var converted to type `T` as best it can. `T` may be constructed
|
||||
from `T.fromJsVar`, or through type conversions (coercing as needed). If
|
||||
`T` happens to be a struct, it will automatically introspect to convert
|
||||
the var object member-by-member.
|
||||
|
||||
History:
|
||||
On April 21, 2020, I changed the behavior of
|
||||
|
||||
---
|
||||
var a = null;
|
||||
string b = a.get!string;
|
||||
---
|
||||
|
||||
Previously, `b == "null"`, which would print the word
|
||||
when writeln'd. Now, `b is null`, which prints the empty string,
|
||||
which is a bit less user-friendly, but more consistent with
|
||||
converting to/from D strings in general.
|
||||
|
||||
If you are printing, you can check `a.get!string is null` and print
|
||||
null at that point if you like.
|
||||
|
||||
I also wrote the first draft of this documentation at that time,
|
||||
even though the function has been public since the beginning.
|
||||
+/
|
||||
public T get(T)() if(!is(T == void)) {
|
||||
static if(is(T == var)) {
|
||||
return this;
|
||||
|
@ -920,7 +966,7 @@ struct var {
|
|||
} else static if(isSomeString!T) {
|
||||
if(this._object !is null)
|
||||
return this._object.toString();
|
||||
return "null";
|
||||
return null;// "null";
|
||||
} else
|
||||
return T.init;
|
||||
case Type.Integral:
|
||||
|
@ -1126,18 +1172,22 @@ struct var {
|
|||
return var(null);
|
||||
}
|
||||
|
||||
/// Forwards to [opIndex]
|
||||
public @property ref var opDispatch(string name, string file = __FILE__, size_t line = __LINE__)() {
|
||||
return this[name];
|
||||
}
|
||||
|
||||
/// Forwards to [opIndexAssign]
|
||||
public @property ref var opDispatch(string name, string file = __FILE__, size_t line = __LINE__, T)(T r) {
|
||||
return this.opIndexAssign!T(r, name);
|
||||
}
|
||||
|
||||
/// Looks up a sub-property of the object
|
||||
public ref var opIndex(var name, string file = __FILE__, size_t line = __LINE__) {
|
||||
return opIndex(name.get!string, file, line);
|
||||
}
|
||||
|
||||
/// Sets a sub-property of the object
|
||||
public ref var opIndexAssign(T)(T t, var name, string file = __FILE__, size_t line = __LINE__) {
|
||||
return opIndexAssign(t, name.get!string, file, line);
|
||||
}
|
||||
|
|
|
@ -3150,7 +3150,7 @@ class TabWidget : Widget {
|
|||
}
|
||||
|
||||
override int marginTop() { return 4; }
|
||||
override int marginBottom() { return 4; }
|
||||
override int paddingBottom() { return 4; }
|
||||
|
||||
override int minHeight() {
|
||||
int max = 0;
|
||||
|
|
|
@ -13459,6 +13459,8 @@ extern(System) nothrow @nogc {
|
|||
uint/*GLenum*/ format, uint/*GLenum*/ type, in void* pixels);
|
||||
void glTexEnvf(uint/*GLenum*/ target, uint/*GLenum*/ pname, float param);
|
||||
|
||||
void glLineWidth(int);
|
||||
|
||||
|
||||
void glTexCoord2f(float, float);
|
||||
void glVertex2i(int, int);
|
||||
|
|
Loading…
Reference in New Issue