Add z distance checking to entity picking. Fixes issue 521
parent
6c2b967790
commit
142252ddf8
10
src/draw.cpp
10
src/draw.cpp
|
@ -342,6 +342,8 @@ GraphicsWindow::Selection GraphicsWindow::ChooseFromHoverToSelect() {
|
||||||
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
|
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
|
||||||
int bestOrder = -1;
|
int bestOrder = -1;
|
||||||
int bestZIndex = 0;
|
int bestZIndex = 0;
|
||||||
|
double bestDepth = VERY_POSITIVE;
|
||||||
|
|
||||||
for(const Hover &hov : hoverList) {
|
for(const Hover &hov : hoverList) {
|
||||||
hGroup hg = {};
|
hGroup hg = {};
|
||||||
if(hov.selection.entity.v != 0) {
|
if(hov.selection.entity.v != 0) {
|
||||||
|
@ -353,8 +355,11 @@ GraphicsWindow::Selection GraphicsWindow::ChooseFromHoverToSelect() {
|
||||||
Group *g = SK.GetGroup(hg);
|
Group *g = SK.GetGroup(hg);
|
||||||
if(g->order > activeGroup->order) continue;
|
if(g->order > activeGroup->order) continue;
|
||||||
if(bestOrder != -1 && (bestOrder > g->order || bestZIndex > hov.zIndex)) continue;
|
if(bestOrder != -1 && (bestOrder > g->order || bestZIndex > hov.zIndex)) continue;
|
||||||
|
// we have hov.zIndex is >= best and hov.group is >= best (but not > active group)
|
||||||
|
if(hov.depth > bestDepth && bestOrder == g->order && bestZIndex == hov.zIndex) continue;
|
||||||
bestOrder = g->order;
|
bestOrder = g->order;
|
||||||
bestZIndex = hov.zIndex;
|
bestZIndex = hov.zIndex;
|
||||||
|
bestDepth = hov.depth;
|
||||||
sel = hov.selection;
|
sel = hov.selection;
|
||||||
}
|
}
|
||||||
return sel;
|
return sel;
|
||||||
|
@ -370,6 +375,8 @@ GraphicsWindow::Selection GraphicsWindow::ChooseFromHoverToDrag() {
|
||||||
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
|
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
|
||||||
int bestOrder = -1;
|
int bestOrder = -1;
|
||||||
int bestZIndex = 0;
|
int bestZIndex = 0;
|
||||||
|
double bestDepth = VERY_POSITIVE;
|
||||||
|
|
||||||
for(const Hover &hov : hoverList) {
|
for(const Hover &hov : hoverList) {
|
||||||
hGroup hg = {};
|
hGroup hg = {};
|
||||||
if(hov.selection.entity.v != 0) {
|
if(hov.selection.entity.v != 0) {
|
||||||
|
@ -383,6 +390,8 @@ GraphicsWindow::Selection GraphicsWindow::ChooseFromHoverToDrag() {
|
||||||
Group *g = SK.GetGroup(hg);
|
Group *g = SK.GetGroup(hg);
|
||||||
if(g->order > activeGroup->order) continue;
|
if(g->order > activeGroup->order) continue;
|
||||||
if(bestOrder != -1 && (bestOrder > g->order || bestZIndex > hov.zIndex)) continue;
|
if(bestOrder != -1 && (bestOrder > g->order || bestZIndex > hov.zIndex)) continue;
|
||||||
|
// we have hov.zIndex is >= best and hov.group is >= best (but not > active group)
|
||||||
|
if(hov.depth > bestDepth && bestOrder == g->order && bestZIndex == hov.zIndex) continue;
|
||||||
bestOrder = g->order;
|
bestOrder = g->order;
|
||||||
bestZIndex = hov.zIndex;
|
bestZIndex = hov.zIndex;
|
||||||
sel = hov.selection;
|
sel = hov.selection;
|
||||||
|
@ -439,6 +448,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
Hover hov = {};
|
Hover hov = {};
|
||||||
hov.distance = canvas.minDistance;
|
hov.distance = canvas.minDistance;
|
||||||
hov.zIndex = canvas.maxZIndex;
|
hov.zIndex = canvas.maxZIndex;
|
||||||
|
hov.depth = canvas.minDepth;
|
||||||
hov.selection.entity = e.h;
|
hov.selection.entity = e.h;
|
||||||
hoverList.Add(&hov);
|
hoverList.Add(&hov);
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,9 +343,10 @@ void UiCanvas::DrawBitmapText(const std::string &str, int x, int y, RgbaColor co
|
||||||
// A canvas that performs picking against drawn geometry.
|
// A canvas that performs picking against drawn geometry.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ObjectPicker::DoCompare(double distance, int zIndex, int comparePosition) {
|
void ObjectPicker::DoCompare(double depth, double distance, int zIndex, int comparePosition) {
|
||||||
if(distance > selRadius) return;
|
if(distance > selRadius) return;
|
||||||
if((zIndex == maxZIndex && distance < minDistance) || (zIndex > maxZIndex)) {
|
if((zIndex == maxZIndex && distance < minDistance) || (zIndex > maxZIndex)) {
|
||||||
|
minDepth = depth;
|
||||||
minDistance = distance;
|
minDistance = distance;
|
||||||
maxZIndex = zIndex;
|
maxZIndex = zIndex;
|
||||||
position = comparePosition;
|
position = comparePosition;
|
||||||
|
@ -372,10 +373,10 @@ void ObjectPicker::DoQuad(const Vector &a, const Vector &b, const Vector &c, con
|
||||||
|
|
||||||
bool insideQuad = (minNegative == VERY_NEGATIVE || maxPositive == VERY_POSITIVE);
|
bool insideQuad = (minNegative == VERY_NEGATIVE || maxPositive == VERY_POSITIVE);
|
||||||
if(insideQuad) {
|
if(insideQuad) {
|
||||||
DoCompare(0.0, zIndex, comparePosition);
|
DoCompare(0, 0.0, zIndex, comparePosition);
|
||||||
} else {
|
} else {
|
||||||
double distance = std::min(fabs(minNegative), fabs(maxPositive));
|
double distance = std::min(fabs(minNegative), fabs(maxPositive));
|
||||||
DoCompare(distance, zIndex, comparePosition);
|
DoCompare(0, distance, zIndex, comparePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +385,8 @@ void ObjectPicker::DrawLine(const Vector &a, const Vector &b, hStroke hcs) {
|
||||||
Point2d ap = camera.ProjectPoint(a);
|
Point2d ap = camera.ProjectPoint(a);
|
||||||
Point2d bp = camera.ProjectPoint(b);
|
Point2d bp = camera.ProjectPoint(b);
|
||||||
double distance = point.DistanceToLine(ap, bp.Minus(ap), /*asSegment=*/true);
|
double distance = point.DistanceToLine(ap, bp.Minus(ap), /*asSegment=*/true);
|
||||||
DoCompare(distance - stroke->width / 2.0, stroke->zIndex);
|
double depth = 0.5 * (camera.ProjectPoint3(a).z + camera.ProjectPoint3(b).z) ;
|
||||||
|
DoCompare(depth, distance - stroke->width / 2.0, stroke->zIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPicker::DrawEdges(const SEdgeList &el, hStroke hcs) {
|
void ObjectPicker::DrawEdges(const SEdgeList &el, hStroke hcs) {
|
||||||
|
@ -393,7 +395,8 @@ void ObjectPicker::DrawEdges(const SEdgeList &el, hStroke hcs) {
|
||||||
Point2d ap = camera.ProjectPoint(e.a);
|
Point2d ap = camera.ProjectPoint(e.a);
|
||||||
Point2d bp = camera.ProjectPoint(e.b);
|
Point2d bp = camera.ProjectPoint(e.b);
|
||||||
double distance = point.DistanceToLine(ap, bp.Minus(ap), /*asSegment=*/true);
|
double distance = point.DistanceToLine(ap, bp.Minus(ap), /*asSegment=*/true);
|
||||||
DoCompare(distance - stroke->width / 2.0, stroke->zIndex, e.auxB);
|
double depth = 0.5 * (camera.ProjectPoint3(e.a).z + camera.ProjectPoint3(e.b).z) ;
|
||||||
|
DoCompare(depth, distance - stroke->width / 2.0, stroke->zIndex, e.auxB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +426,8 @@ void ObjectPicker::DrawQuad(const Vector &a, const Vector &b, const Vector &c, c
|
||||||
void ObjectPicker::DrawPoint(const Vector &o, Canvas::hStroke hcs) {
|
void ObjectPicker::DrawPoint(const Vector &o, Canvas::hStroke hcs) {
|
||||||
Stroke *stroke = strokes.FindById(hcs);
|
Stroke *stroke = strokes.FindById(hcs);
|
||||||
double distance = point.DistanceTo(camera.ProjectPoint(o)) - stroke->width / 2;
|
double distance = point.DistanceTo(camera.ProjectPoint(o)) - stroke->width / 2;
|
||||||
DoCompare(distance, stroke->zIndex);
|
double depth = camera.ProjectPoint3(o).z;
|
||||||
|
DoCompare(depth, distance, stroke->zIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPicker::DrawPolygon(const SPolygon &p, hFill hcf) {
|
void ObjectPicker::DrawPolygon(const SPolygon &p, hFill hcf) {
|
||||||
|
@ -445,6 +449,7 @@ void ObjectPicker::DrawPixmap(std::shared_ptr<const Pixmap> pm,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectPicker::Pick(const std::function<void()> &drawFn) {
|
bool ObjectPicker::Pick(const std::function<void()> &drawFn) {
|
||||||
|
minDepth = VERY_POSITIVE;
|
||||||
minDistance = VERY_POSITIVE;
|
minDistance = VERY_POSITIVE;
|
||||||
maxZIndex = INT_MIN;
|
maxZIndex = INT_MIN;
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,7 @@ public:
|
||||||
double selRadius = 0.0;
|
double selRadius = 0.0;
|
||||||
// Picking state.
|
// Picking state.
|
||||||
double minDistance = 0.0;
|
double minDistance = 0.0;
|
||||||
|
double minDepth = 1e10;
|
||||||
int maxZIndex = 0;
|
int maxZIndex = 0;
|
||||||
uint32_t position = 0;
|
uint32_t position = 0;
|
||||||
|
|
||||||
|
@ -257,7 +258,7 @@ public:
|
||||||
const Point2d &ta, const Point2d &tb, hFill hcf) override;
|
const Point2d &ta, const Point2d &tb, hFill hcf) override;
|
||||||
void InvalidatePixmap(std::shared_ptr<const Pixmap> pm) override {}
|
void InvalidatePixmap(std::shared_ptr<const Pixmap> pm) override {}
|
||||||
|
|
||||||
void DoCompare(double distance, int zIndex, int comparePosition = 0);
|
void DoCompare(double depth, double distance, int zIndex, int comparePosition = 0);
|
||||||
void DoQuad(const Vector &a, const Vector &b, const Vector &c, const Vector &d,
|
void DoQuad(const Vector &a, const Vector &b, const Vector &c, const Vector &d,
|
||||||
int zIndex, int comparePosition = 0);
|
int zIndex, int comparePosition = 0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue