Skip to content

Commit

Permalink
fix(UI): Disallow the planet label from jumping around at different z…
Browse files Browse the repository at this point in the history
…ooms (#7342)
  • Loading branch information
quyykk authored Oct 15, 2022
1 parent 56b0a26 commit 1d0976d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 30 deletions.
78 changes: 48 additions & 30 deletions source/PlanetLabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ this program. If not, see <https://www.gnu.org/licenses/>.
#include "pi.h"
#include "Planet.h"
#include "PointerShader.h"
#include "Preferences.h"
#include "RingShader.h"
#include "StellarObject.h"
#include "System.h"
Expand All @@ -39,6 +40,41 @@ namespace {
const double LINE_GAP = 1.7;
const double GAP = 6.;
const double MIN_DISTANCE = 30.;

// Check if the given label for the given stellar object and direction overlaps with any other stellar object in the system.
bool Overlaps(const System &system, const StellarObject &object, double zoom, double width, int direction)
{
Point start = zoom * (object.Position() +
(object.Radius() + INNER_SPACE + LINE_GAP + LINE_LENGTH) * Angle(LINE_ANGLE[direction]).Unit());
// Offset the label correctly depending on its location relative to the stellar object.
Point unit(LINE_ANGLE[direction] > 180. ? -1. : 1., 0.);
Point end = start + unit * width;

for(const StellarObject &other : system.Objects())
{
if(&other == &object)
continue;

double minDistance = (other.Radius() + MIN_DISTANCE) * zoom;

Point otherPos = other.Position() * zoom;
double startDistance = otherPos.Distance(start);
double endDistance = otherPos.Distance(end);
if(startDistance < minDistance || endDistance < minDistance)
return true;

// Check overlap with the middle of the label, when the end and/or start might not overlap.
double projection = (otherPos - start).Dot(unit);
if(projection > 0. && projection < width)
{
double distance = sqrt(startDistance * startDistance - projection * projection);
if(distance < minDistance)
return true;
}
}

return false;
}
}


Expand Down Expand Up @@ -71,42 +107,24 @@ PlanetLabel::PlanetLabel(const Point &position, const StellarObject &object, con

// Figure out how big the label has to be.
double width = max(FontSet::Get(18).Width(name), FontSet::Get(14).Width(government)) + 8.;
for(int d = 0; d < 4; ++d)
{
bool overlaps = false;

Point start = object.Position() * zoom +
(radius + INNER_SPACE + LINE_GAP + LINE_LENGTH) * Angle(LINE_ANGLE[d]).Unit();
Point unit(LINE_ANGLE[d] > 180. ? -1. : 1., 0.);
Point end = start + unit * width;

for(const StellarObject &other : system->Objects())
// Try to find a label direction that not overlapping under any zoom.
for(int d = 0; d < 4; ++d)
if(!Overlaps(*system, object, Preferences::MinViewZoom(), width, d)
&& !Overlaps(*system, object, Preferences::MaxViewZoom(), width, d))
{
if(&other == &object)
continue;

double minDistance = (other.Radius() + MIN_DISTANCE) * zoom;

Point otherPos = other.Position() * zoom;
double startDistance = otherPos.Distance(start);
double endDistance = otherPos.Distance(end);
overlaps |= (startDistance < minDistance || endDistance < minDistance);
double projection = (otherPos - start).Dot(unit);

if(projection > 0. && projection < width)
{
double distance = sqrt(startDistance * startDistance - projection * projection);
overlaps |= (distance < minDistance);
}
if(overlaps)
break;
direction = d;
return;
}
if(!overlaps)

// If we can't find a suitable direction, then try to find a direction under the current
// zoom that is not overlapping.
for(int d = 0; d < 4; ++d)
if(!Overlaps(*system, object, zoom, width, d))
{
direction = d;
break;
return;
}
}
}


Expand Down
14 changes: 14 additions & 0 deletions source/Preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,20 @@ bool Preferences::ZoomViewOut()



double Preferences::MinViewZoom()
{
return ZOOMS[0];
}



double Preferences::MaxViewZoom()
{
return ZOOMS[ZOOMS.size() - 1];
}



void Preferences::ToggleScreenMode()
{
GameWindow::ToggleFullscreen();
Expand Down
2 changes: 2 additions & 0 deletions source/Preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Preferences {
static double ViewZoom();
static bool ZoomViewIn();
static bool ZoomViewOut();
static double MinViewZoom();
static double MaxViewZoom();

static void ToggleScreenMode();
static const std::string &ScreenModeSetting();
Expand Down

0 comments on commit 1d0976d

Please sign in to comment.