mirror of https://github.com/adamdruppe/arsd.git
ketmar patches
This commit is contained in:
parent
bb111a1af2
commit
a1c57fa9eb
47
nanovega.d
47
nanovega.d
|
@ -1845,6 +1845,9 @@ public void beginFrame (NVGContext ctx, int windowWidth, int windowHeight, float
|
|||
ctx.recset = null;
|
||||
ctx.recstart = -1;
|
||||
|
||||
ctx.pathPickId = NVGNoPick;
|
||||
ctx.pathPickRegistered = 0;
|
||||
|
||||
ctx.drawCallCount = 0;
|
||||
ctx.fillTriCount = 0;
|
||||
ctx.strokeTriCount = 0;
|
||||
|
@ -5208,6 +5211,8 @@ public void currFillHitId (NVGContext ctx, int id) nothrow @trusted @nogc {
|
|||
nvg__pickSceneInsert(ps, pp);
|
||||
}
|
||||
|
||||
public alias currFillPickId = currFillHitId; /// Ditto.
|
||||
|
||||
/// Marks the stroke of the current path as pickable with the specified id.
|
||||
/// Note that you can create and mark path without rasterizing it.
|
||||
/// Group: picking_api
|
||||
|
@ -5217,6 +5222,8 @@ public void currStrokeHitId (NVGContext ctx, int id) nothrow @trusted @nogc {
|
|||
nvg__pickSceneInsert(ps, pp);
|
||||
}
|
||||
|
||||
public alias currStrokePickId = currStrokeHitId; /// Ditto.
|
||||
|
||||
// Marks the saved path set (fill) as pickable with the specified id.
|
||||
// $(WARNING this doesn't work right yet (it is using current context transformation and other settings instead of record settings)!)
|
||||
// Group: picking_api
|
||||
|
@ -5612,6 +5619,7 @@ void nvg__segmentDir (NVGpickScene* ps, NVGpickSubPath* psp, NVGsegment* seg, fl
|
|||
}
|
||||
|
||||
void nvg__pickSubPathAddFillSupports (NVGpickScene* ps, NVGpickSubPath* psp) {
|
||||
if (psp.firstSegment == -1) return;
|
||||
NVGsegment* segments = &ps.segments[psp.firstSegment];
|
||||
for (int s = 0; s < psp.nsegments; ++s) {
|
||||
NVGsegment* seg = &segments[s];
|
||||
|
@ -5626,6 +5634,7 @@ void nvg__pickSubPathAddFillSupports (NVGpickScene* ps, NVGpickSubPath* psp) {
|
|||
}
|
||||
|
||||
void nvg__pickSubPathAddStrokeSupports (NVGpickScene* ps, NVGpickSubPath* psp, float strokeWidth, int lineCap, int lineJoin, float miterLimit) {
|
||||
if (psp.firstSegment == -1) return;
|
||||
immutable bool closed = psp.closed;
|
||||
const(float)* points = ps.points;
|
||||
NVGsegment* seg = null;
|
||||
|
@ -5770,7 +5779,7 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
float[2] start = void;
|
||||
int firstPoint;
|
||||
|
||||
int hasHoles = 0;
|
||||
//bool hasHoles = false;
|
||||
NVGpickSubPath* prev = null;
|
||||
|
||||
float[8] points = void;
|
||||
|
@ -5788,6 +5797,17 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
|
||||
pp.id = id;
|
||||
|
||||
bool hasPoints = false;
|
||||
|
||||
void closeIt () {
|
||||
if (psp is null || !hasPoints) return;
|
||||
if (ps.points[(ps.npoints-1)*2] != start.ptr[0] || ps.points[(ps.npoints-1)*2+1] != start.ptr[1]) {
|
||||
firstPoint = nvg__pickSceneAddPoints(ps, start.ptr, 1);
|
||||
nvg__pickSubPathAddSegment(ps, psp, firstPoint-1, Command.LineTo, NVGSegmentFlags.Corner);
|
||||
}
|
||||
psp.closed = true;
|
||||
}
|
||||
|
||||
while (i < ncommands) {
|
||||
int cmd = cast(int)commands[i++];
|
||||
switch (cmd) {
|
||||
|
@ -5807,12 +5827,14 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
psp.next = prev;
|
||||
|
||||
nvg__pickSceneAddPoints(ps, tfxy, 1);
|
||||
hasPoints = true;
|
||||
break;
|
||||
case Command.LineTo: // one coordinate pair
|
||||
const(float)* tfxy = commands+i;
|
||||
i += 2;
|
||||
firstPoint = nvg__pickSceneAddPoints(ps, tfxy, 1);
|
||||
nvg__pickSubPathAddSegment(ps, psp, firstPoint-1, cmd, NVGSegmentFlags.Corner);
|
||||
hasPoints = true;
|
||||
break;
|
||||
case Command.BezierTo: // three coordinate pairs
|
||||
const(float)* tfxy = commands+i;
|
||||
|
@ -5860,17 +5882,14 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
firstPoint = nvg__pickSceneAddPoints(ps, tfxy, 3);
|
||||
nvg__pickSubPathAddSegment(ps, psp, firstPoint-1, cmd, NVGSegmentFlags.Corner);
|
||||
}
|
||||
hasPoints = true;
|
||||
break;
|
||||
case Command.Close:
|
||||
if (ps.points[(ps.npoints-1)*2] != start.ptr[0] || ps.points[(ps.npoints-1)*2+1] != start.ptr[1]) {
|
||||
firstPoint = nvg__pickSceneAddPoints(ps, start.ptr, 1);
|
||||
nvg__pickSubPathAddSegment(ps, psp, firstPoint-1, Command.LineTo, NVGSegmentFlags.Corner);
|
||||
}
|
||||
psp.closed = true;
|
||||
closeIt();
|
||||
break;
|
||||
case Command.Winding:
|
||||
psp.winding = cast(short)cast(int)commands[i];
|
||||
if (psp.winding == NVGSolidity.Hole) hasHoles = 1;
|
||||
//if (psp.winding == NVGSolidity.Hole) hasHoles = true;
|
||||
i += 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -5878,6 +5897,9 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
}
|
||||
}
|
||||
|
||||
// force-close filled pathes
|
||||
if (psp !is null && !forStroke && hasPoints && !psp.closed) closeIt();
|
||||
|
||||
pp.flags = (forStroke ? NVGPathFlags.Stroke : NVGPathFlags.Fill);
|
||||
pp.subPaths = psp;
|
||||
pp.strokeWidth = state.strokeWidth*0.5f;
|
||||
|
@ -5895,6 +5917,7 @@ NVGpickPath* nvg__pickPathCreate (NVGContext context, const(float)[] acommands,
|
|||
nvg__pickSubPathAddFillSupports(ps, curpsp);
|
||||
}
|
||||
|
||||
if (curpsp.firstSegment == -1) continue;
|
||||
segments = &ps.segments[curpsp.firstSegment];
|
||||
nvg__initBounds(curpsp.bounds);
|
||||
for (int s = 0; s < curpsp.nsegments; ++s) {
|
||||
|
@ -6388,6 +6411,7 @@ void nvg__closestBezier (const(float)* points, float x, float y, float* closest,
|
|||
// 0 If (x,y) is not contained by the path.
|
||||
int nvg__pickSubPathStroke (const NVGpickScene* ps, const NVGpickSubPath* psp, float x, float y, float strokeWidth, int lineCap, int lineJoin) {
|
||||
if (!nvg__pointInBounds(x, y, psp.bounds)) return 0;
|
||||
if (psp.firstSegment == -1) return 0;
|
||||
|
||||
float[2] closest = void;
|
||||
float[2] d = void;
|
||||
|
@ -6478,6 +6502,7 @@ int nvg__pickSubPathStroke (const NVGpickScene* ps, const NVGpickSubPath* psp, f
|
|||
// 0 If (x,y) is not contained by the path.
|
||||
int nvg__pickSubPath (const NVGpickScene* ps, const NVGpickSubPath* psp, float x, float y, bool evenOddMode) {
|
||||
if (!nvg__pointInBounds(x, y, psp.bounds)) return 0;
|
||||
if (psp.firstSegment == -1) return 0;
|
||||
|
||||
const(NVGsegment)* seg = &ps.segments[psp.firstSegment];
|
||||
int nsegments = psp.nsegments;
|
||||
|
@ -6564,10 +6589,10 @@ bool nvg__pickPathTestBounds (NVGContext ctx, const NVGpickScene* ps, const NVGp
|
|||
return false;
|
||||
}
|
||||
|
||||
int nvg__countBitsUsed (int v) {
|
||||
int nvg__countBitsUsed (uint v) pure {
|
||||
pragma(inline, true);
|
||||
import core.bitop : popcnt;
|
||||
return (v != 0 ? popcnt(cast(uint)v) : 0);
|
||||
import core.bitop : bsr;
|
||||
return (v != 0 ? bsr(v)+1 : 0);
|
||||
}
|
||||
|
||||
void nvg__pickSceneInsert (NVGpickScene* ps, NVGpickPath* pp) {
|
||||
|
@ -6598,6 +6623,8 @@ void nvg__pickSceneInsert (NVGpickScene* ps, NVGpickPath* pp) {
|
|||
// to calculate the level to insert at (the level at which the bounds fit in a single cell)
|
||||
level = nvg__min(base-nvg__countBitsUsed(cellbounds.ptr[0]), base-nvg__countBitsUsed(cellbounds.ptr[1]));
|
||||
if (level < 0) level = 0;
|
||||
//{ import core.stdc.stdio; printf("LEVEL: %d; bounds=(%g,%g)-(%g,%g)\n", level, pp.bounds[0], pp.bounds[1], pp.bounds[2], pp.bounds[3]); }
|
||||
//level = 0;
|
||||
|
||||
// Find the correct cell in the chosen level, clamping to the edges.
|
||||
levelwidth = 1<<level;
|
||||
|
|
|
@ -4826,9 +4826,21 @@ struct MouseEvent {
|
|||
static bool equStr() (in auto ref MouseEvent event, const(char)[] str) pure nothrow @trusted @nogc {
|
||||
if (str.length == 0) return false; // just in case
|
||||
debug(arsd_mevent_strcmp) { import iv.cmdcon; conwriteln("str=<", str, ">"); }
|
||||
enum Flag : uint { Up = 0x8000_0000U, Down = 0x4000_0000U, Any = 0x1000_0000U }
|
||||
auto anchor = str;
|
||||
uint mods = 0; // uint.max == any
|
||||
// interesting bits in kmod
|
||||
uint kmodmask =
|
||||
ModifierState.shift|
|
||||
ModifierState.ctrl|
|
||||
ModifierState.alt|
|
||||
ModifierState.windows|
|
||||
ModifierState.leftButtonDown|
|
||||
ModifierState.middleButtonDown|
|
||||
ModifierState.rightButtonDown|
|
||||
0;
|
||||
uint lastButt = uint.max; // otherwise, bit 31 means "down"
|
||||
bool wasButtons = false;
|
||||
while (str.length) {
|
||||
if (str.ptr[0] <= ' ') {
|
||||
while (str.length && str.ptr[0] <= ' ') str = str[1..$];
|
||||
|
@ -4872,24 +4884,28 @@ struct MouseEvent {
|
|||
}
|
||||
if (wep == 0) return false; // just in case
|
||||
uint bnum;
|
||||
enum UpDown { None = -1, Up, Down }
|
||||
enum UpDown { None = -1, Up, Down, Any }
|
||||
auto updown = UpDown.None; // 0: up; 1: down
|
||||
switch (buf[0..wep]) {
|
||||
// left button
|
||||
case "lmbup": case "leftup": updown = UpDown.Up; goto case "lmb";
|
||||
case "lmbdown": case "leftdown": updown = UpDown.Down; goto case "lmb";
|
||||
case "lmbany": case "leftany": updown = UpDown.Any; goto case "lmb";
|
||||
case "lmb": case "left": bnum = 0; break;
|
||||
// middle button
|
||||
case "mmbup": case "middleup": updown = UpDown.Up; goto case "mmb";
|
||||
case "mmbdown": case "middledown": updown = UpDown.Down; goto case "mmb";
|
||||
case "mmbany": case "middleany": updown = UpDown.Any; goto case "mmb";
|
||||
case "mmb": case "middle": bnum = 1; break;
|
||||
// right button
|
||||
case "rmbup": case "rightup": updown = UpDown.Up; goto case "rmb";
|
||||
case "rmbdown": case "rightdown": updown = UpDown.Down; goto case "rmb";
|
||||
case "rmbany": case "rightany": updown = UpDown.Any; goto case "rmb";
|
||||
case "rmb": case "right": bnum = 2; break;
|
||||
// wheel
|
||||
case "wheelup": updown = UpDown.Up; goto case "wheel";
|
||||
case "wheeldown": updown = UpDown.Down; goto case "wheel";
|
||||
case "wheelany": updown = UpDown.Any; goto case "wheel";
|
||||
case "wheel": bnum = 3; break;
|
||||
// motion
|
||||
case "motion": bnum = 7; break;
|
||||
|
@ -4910,14 +4926,17 @@ struct MouseEvent {
|
|||
}
|
||||
if (wep == 2 && buf[0..wep] == "up") updown = UpDown.Up;
|
||||
else if (wep == 4 && buf[0..wep] == "down") updown = UpDown.Down;
|
||||
else if (wep == 3 && buf[0..wep] == "any") updown = UpDown.Any;
|
||||
// remove parsed part
|
||||
if (updown != UpDown.None) str = str[wep+1..$];
|
||||
} else if (updown == UpDown.None) {
|
||||
updown = (bnum < 7 ? UpDown.Down : UpDown.Up);
|
||||
}
|
||||
assert(updown != UpDown.None);
|
||||
if (updown == UpDown.None) {
|
||||
updown = UpDown.Down;
|
||||
}
|
||||
wasButtons = wasButtons || (bnum <= 2);
|
||||
//assert(updown != UpDown.None);
|
||||
debug(arsd_mevent_strcmp) { import iv.cmdcon; conprintfln(" 1: mods=0x%08x; bnum=%u; updown=%s [%s]", mods, bnum, updown, str); }
|
||||
// if we have a previous button, it goes to modifiers (unless it is a wheel)
|
||||
// if we have a previous button, it goes to modifiers (unless it is a wheel or motion)
|
||||
if (lastButt != lastButt.max) {
|
||||
if ((lastButt&0xff) >= 3) return false; // wheel or motion
|
||||
if (mods != mods.max) {
|
||||
|
@ -4927,38 +4946,45 @@ struct MouseEvent {
|
|||
case 1: butbit = ModifierState.middleButtonDown; break;
|
||||
case 2: butbit = ModifierState.rightButtonDown; break;
|
||||
}
|
||||
if (lastButt >= 0x8000_0000U) mods |= butbit; else mods &= ~butbit;
|
||||
if (lastButt&Flag.Down) mods |= butbit;
|
||||
else if (lastButt&Flag.Up) mods &= ~butbit;
|
||||
else if (lastButt&Flag.Any) kmodmask &= ~butbit;
|
||||
}
|
||||
}
|
||||
// remember last button
|
||||
lastButt = bnum|(updown == UpDown.Up ? 0 : 0x8000_0000U);
|
||||
lastButt = bnum|(updown == UpDown.Up ? Flag.Up : updown == UpDown.Any ? Flag.Any : Flag.Down);
|
||||
}
|
||||
// no button -- nothing to do
|
||||
if (lastButt == lastButt.max) return false;
|
||||
// done parsing, check if something's left
|
||||
foreach (immutable char ch; str) if (ch > ' ') return false; // oops
|
||||
debug(arsd_mevent_strcmp) { import iv.cmdcon; conprintfln(" *: mods=0x%08x; lastButt=0x%08x; kmod=0x%08x; type=%s", mods, lastButt, event.modifierState, event.type); }
|
||||
// remove action button from mask
|
||||
if ((lastButt&0xff) < 3) {
|
||||
final switch (lastButt&0x03) {
|
||||
case 0: kmodmask &= ~cast(uint)ModifierState.leftButtonDown; break;
|
||||
case 1: kmodmask &= ~cast(uint)ModifierState.middleButtonDown; break;
|
||||
case 2: kmodmask &= ~cast(uint)ModifierState.rightButtonDown; break;
|
||||
}
|
||||
}
|
||||
// special case: "Motion" means "ignore buttons"
|
||||
if ((lastButt&0xff) == 7 && !wasButtons) {
|
||||
debug(arsd_mevent_strcmp) { import iv.cmdcon; conwriteln(" *: special motion"); }
|
||||
kmodmask &= ~cast(uint)(ModifierState.leftButtonDown|ModifierState.middleButtonDown|ModifierState.rightButtonDown);
|
||||
}
|
||||
uint kmod = event.modifierState&kmodmask;
|
||||
debug(arsd_mevent_strcmp) { import iv.cmdcon; conprintfln(" *: mods=0x%08x; lastButt=0x%08x; kmod=0x%08x; type=%s", mods, lastButt, kmod, event.type); }
|
||||
// check modifier state
|
||||
if (mods != mods.max) {
|
||||
enum InterestingMods =
|
||||
ModifierState.shift|
|
||||
ModifierState.ctrl|
|
||||
ModifierState.alt|
|
||||
ModifierState.windows|
|
||||
ModifierState.leftButtonDown|
|
||||
ModifierState.middleButtonDown|
|
||||
ModifierState.rightButtonDown|
|
||||
0;
|
||||
if ((event.modifierState&InterestingMods) != mods) return false;
|
||||
if (kmod != mods) return false;
|
||||
}
|
||||
// now check type
|
||||
if ((lastButt&0xff) == 7) {
|
||||
// motion
|
||||
if (event.type != MouseEventType.motion) return false;
|
||||
} else {
|
||||
// buttions
|
||||
if ((lastButt >= 0x8000_0000U && event.type != MouseEventType.buttonPressed) ||
|
||||
(lastButt < 0x8000_0000U && event.type != MouseEventType.buttonReleased))
|
||||
// buttons
|
||||
if (((lastButt&Flag.Down) != 0 && event.type != MouseEventType.buttonPressed) ||
|
||||
((lastButt&Flag.Up) != 0 && event.type != MouseEventType.buttonReleased))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue