Skip to content

Occlude the cursor when covered by tiles #198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 50 additions & 32 deletions GUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,50 +484,49 @@ void DrawCurrentLevelOutline(bool backPart)

namespace
{
void drawSelectionCursor(WorldSegment* segment)
void drawCursorAt(WorldSegment* segment, Crd3D& cursor, const ALLEGRO_COLOR& color)
{
auto& ssConfig = stonesenseState.ssConfig;
std::array<dirRelative, 8> directions = { eUpLeft, eUp, eUpRight, eRight, eDownRight, eDown, eDownLeft, eLeft };
std::array<Tile*, 8> dirs = {};

Crd3D selection = segment->segState.dfSelection;
if ((selection.x != -30000 && ssConfig.config.follow_DFcursor)
|| (ssConfig.config.track_mode == Config::TRACKING_FOCUS)) {
segment->CorrectTileForSegmentOffset(selection.x, selection.y, selection.z);
segment->CorrectTileForSegmentRotation(selection.x, selection.y, selection.z);
for (unsigned int i = 0; i < directions.size(); i++) {
dirs[i] = segment->getTileRelativeTo(cursor.x, cursor.y, cursor.z, directions[i]);
}
else {
return;

auto isObscuring = [&](Tile* tile) {
auto& buildType = tile->building.type;
return tile &&
buildType != BUILDINGTYPE_NA &&
buildType != df::enums::building_type::Civzone &&
buildType != df::enums::building_type::Stockpile;
};

// Check the tiles in front of the cursor
bool occludeCursor = false;
for (int i : {3, 4, 5}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend against using a copy of the dirs array used in SegmentProcessing, as it stores more directions than needed as well as being specialized for border calculations. Instead I would recommend an implementation similar to the following:

Tile* temp;
for (const dirRelative& dir : {eRight, eDownRight, eDown}) {
    temp = segment->getTileRelativeTo(cursor.x, cursor.y, cursor.z, dir);
    if (!temp)
        continue;
    // Do whatever checks are needed
}

if (occludeCursor) break;
if (!dirs[i]) {
continue;
}
int shape = dirs[i]->tileShapeBasic();
if (isObscuring(dirs[i]) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checks on tileShapeBasic likely make sense to be moved into your isObscuring function.
Additionally, the name of the function may be misleading as the method doesn't check if the cursor is obscuring a tile, but rather if the tile is obscuring the cursor.

shape == df::tiletype_shape_basic::Ramp ||
shape == df::tiletype_shape_basic::Wall) {
occludeCursor = true;
}
}
Crd2D point = LocalTileToScreen(selection.x, selection.y, selection.z);
int sheetx = SPRITEOBJECT_CURSOR % SHEET_OBJECTSWIDE;
int sheety = SPRITEOBJECT_CURSOR / SHEET_OBJECTSWIDE;
al_draw_tinted_scaled_bitmap(
stonesenseState.IMGObjectSheet,
uiColor(3),
sheetx * SPRITEWIDTH,
sheety * SPRITEHEIGHT,
SPRITEWIDTH,
SPRITEHEIGHT,
point.x - ((SPRITEWIDTH / 2) * ssConfig.scale),
point.y - (WALLHEIGHT)*ssConfig.scale,
SPRITEWIDTH * ssConfig.scale,
SPRITEHEIGHT * ssConfig.scale,
0);
}

void drawDebugCursor(WorldSegment* segment)
{
auto& ssConfig = stonesenseState.ssConfig;

Crd3D cursor = segment->segState.dfCursor;
segment->CorrectTileForSegmentOffset(cursor.x, cursor.y, cursor.z);
segment->CorrectTileForSegmentRotation(cursor.x, cursor.y, cursor.z);

Crd2D point = LocalTileToScreen(cursor.x, cursor.y, cursor.z);
int sheetx = SPRITEOBJECT_CURSOR % SHEET_OBJECTSWIDE;
int sheety = SPRITEOBJECT_CURSOR / SHEET_OBJECTSWIDE;
int spriteIDX = (occludeCursor ? SPRITEOBJECT_CURSOROCCLUDE : SPRITEOBJECT_CURSOR);
int sheetx = spriteIDX % SHEET_OBJECTSWIDE;
int sheety = spriteIDX / SHEET_OBJECTSWIDE;
al_draw_tinted_scaled_bitmap(
stonesenseState.IMGObjectSheet,
uiColor(2),
color,
sheetx * SPRITEWIDTH,
sheety * SPRITEHEIGHT,
SPRITEWIDTH,
Expand All @@ -539,6 +538,25 @@ namespace
0);
}

void drawSelectionCursor(WorldSegment* segment)
{
auto& ssConfig = stonesenseState.ssConfig;
Crd3D& selection = segment->segState.dfSelection;
if ((selection.x != -30000 && ssConfig.config.follow_DFcursor)
|| (ssConfig.config.track_mode == Config::TRACKING_FOCUS)) {
drawCursorAt(segment, selection, uiColor(3));
}
else {
return;
}
}

void drawDebugCursor(WorldSegment* segment)
{
Crd3D& cursor = segment->segState.dfCursor;
drawCursorAt(segment, cursor, uiColor(2));
}

void drawAdvmodeMenuTalk(const ALLEGRO_FONT* font, int x, int y)
{
//df::adventure * menu = df::global::adventure;
Expand Down
1 change: 1 addition & 0 deletions SpriteMaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum enumObjectSprites {
SPRITEOBJECT_BLUEPRINT = 321,
SPRITEOBJECT_STOCKPILE = 322,
SPRITEOBJECT_CURSOR = 323,
SPRITEOBJECT_CURSOROCCLUDE = 304,

};

Expand Down
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Template for new versions:
- `stonesense`: improved the way altars look
- `stonesense`: fog no longer unnecessarily renders to a separate bitmap
- `stonesense`: added new connective tiles for pools of blood and vomit
- `stonesense`: made the cursor change sprites when it is partially covered by tiles relative to the camera view

# 51.02-r1

Expand Down
Loading