From 397b3dc06ec5d4c36376933388d9d4206fc13eab Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Wed, 31 Dec 2014 01:23:30 +0000 Subject: [PATCH 01/14] Alberth work --- src/coaster_gui.cpp | 10 +- src/fence_build.cpp | 17 +-- src/gamecontrol.cpp | 7 +- src/geometry.h | 56 +++++++++- src/map.cpp | 4 +- src/path.cpp | 86 ++++++---------- src/path.h | 7 +- src/path_build.cpp | 292 ++++++++++++++++++++++++---------------------------- src/path_build.h | 4 +- src/person.cpp | 8 +- src/ride_gui.cpp | 6 +- src/terraform.cpp | 16 +-- src/viewport.cpp | 286 +++++++++++++++++++++----------------------------- src/viewport.h | 37 +++---- src/window.h | 2 +- 15 files changed, 393 insertions(+), 445 deletions(-) diff --git a/src/coaster_gui.cpp b/src/coaster_gui.cpp index 8466802..18b2489 100644 --- a/src/coaster_gui.cpp +++ b/src/coaster_gui.cpp @@ -1340,18 +1340,18 @@ void CoasterBuildMode::UpdateDisplay(bool mousepos_changed) return; } /* Found ground, is the position the same? */ - if (mousepos_changed && fdata.xvoxel == this->track_xpos && fdata.yvoxel == this->track_ypos && fdata.zvoxel == this->track_zpos) { + if (mousepos_changed && fdata.voxel_pos.x == this->track_xpos && fdata.voxel_pos.y == this->track_ypos && fdata.voxel_pos.z == this->track_zpos) { return; } - this->track_xpos = fdata.xvoxel; - this->track_ypos = fdata.yvoxel; - this->track_zpos = fdata.zvoxel; + this->track_xpos = fdata.voxel_pos.x; + this->track_ypos = fdata.voxel_pos.y; + this->track_zpos = fdata.voxel_pos.z; } _additions.Clear(); EnableWorldAdditions(); PositionedTrackPiece ptp(this->track_xpos, this->track_ypos, this->track_zpos, this->cur_piece); CoasterInstance *ci = static_cast(_rides_manager.GetRideInstance(this->instance)); if (ptp.CanBePlaced()) ci->PlaceTrackPieceInAdditions(ptp); - vp->arrow_cursor.SetCursor(this->track_xpos, this->track_ypos, this->track_zpos, (CursorType)(CUR_TYPE_ARROW_NE + this->direction)); + vp->arrow_cursor.SetCursor(XYZPoint16(this->track_xpos, this->track_ypos, this->track_zpos), (CursorType)(CUR_TYPE_ARROW_NE + this->direction)); } diff --git a/src/fence_build.cpp b/src/fence_build.cpp index dd021d1..fe2de15 100644 --- a/src/fence_build.cpp +++ b/src/fence_build.cpp @@ -73,7 +73,7 @@ void FenceBuildManager::SetCursors() FinderData fdata(CS_GROUND_EDGE, FW_EDGE); if (vp->ComputeCursorPosition(&fdata) != CS_NONE && fdata.cursor >= CUR_TYPE_EDGE_NE && fdata.cursor <= CUR_TYPE_EDGE_NW) { TileEdge edge = (TileEdge)((uint8)fdata.cursor - (uint8)CUR_TYPE_EDGE_NE); - const Voxel *v = _world.GetVoxel(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel); + const Voxel *v = _world.GetVoxel(fdata.voxel_pos.x, fdata.voxel_pos.y, fdata.voxel_pos.z); assert(v != nullptr); TileSlope slope = ExpandTileSlope(v->GetGroundSlope()); /* @@ -85,7 +85,7 @@ void FenceBuildManager::SetCursors() int32 extra_z = 0; if ((slope & TSB_TOP) == 0 && IsRaisedEdge(edge, slope)) { extra_z = 1; - v = _world.GetCreateVoxel(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel + extra_z, true); + v = _world.GetCreateVoxel(fdata.voxel_pos.x, fdata.voxel_pos.y, fdata.voxel_pos.z + extra_z, true); assert(v != nullptr); } const SpriteStorage *ss = _sprite_manager.GetSprites(vp->tile_width); @@ -98,7 +98,8 @@ void FenceBuildManager::SetCursors() bool steep_lower_edge = (slope & TSB_STEEP) != 0 && (slope & (1 << edge)) == 0 && (slope & (1 << ((edge + 1) % 4))) == 0; - vp->edge_cursor.SetCursor(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel + extra_z, fdata.cursor, sprite, steep_lower_edge ? vp->tile_height : 0); + fdata.voxel_pos.z += extra_z; + vp->edge_cursor.SetCursor(fdata.voxel_pos, fdata.cursor, sprite, steep_lower_edge ? vp->tile_height : 0); } } @@ -133,21 +134,21 @@ void FenceBuildManager::OnMouseButtonEvent(Viewport *vp, uint8 state) if ((this->mouse_state & MB_LEFT) != 0) { // Left-click -> build fence EdgeCursor *c = &vp->edge_cursor; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(c->xpos, c->ypos) != OWN_PARK) return; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(c->cursor_pos.x, c->cursor_pos.y) != OWN_PARK) return; TileEdge edge = (TileEdge)((uint8)c->type - (uint8)CUR_TYPE_EDGE_NE); - VoxelStack *vs = _world.GetModifyStack(c->xpos, c->ypos); - Voxel *v = vs->GetCreate(c->zpos, false); + VoxelStack *vs = _world.GetModifyStack(c->cursor_pos.x, c->cursor_pos.y); + Voxel *v = vs->GetCreate(c->cursor_pos.z, false); assert(v != nullptr); TileSlope slope = ExpandTileSlope(v->GetGroundSlope()); int32 extra_z = 0; if ((slope & TSB_TOP) == 0 && IsRaisedEdge(edge, slope)) { extra_z = 1; - v = vs->GetCreate(c->zpos + extra_z, true); + v = vs->GetCreate(c->cursor_pos.z + extra_z, true); assert(v != nullptr); } v->SetFenceType(edge, this->selected_fence_type); - vp->MarkVoxelDirty(c->xpos, c->ypos, c->zpos + extra_z); + vp->MarkVoxelDirty(XYZPoint16(c->cursor_pos.x, c->cursor_pos.y, c->cursor_pos.z + extra_z)); } } diff --git a/src/gamecontrol.cpp b/src/gamecontrol.cpp index 6cc01c6..74c3615 100644 --- a/src/gamecontrol.cpp +++ b/src/gamecontrol.cpp @@ -41,11 +41,8 @@ void StartNewGame() _game_mode_mgr.SetGameMode(GM_PLAY); - uint32 xview = _world.GetXSize() * 256 / 2; - uint32 yview = _world.GetYSize() * 256 / 2; - uint32 zview = 8 * 256; - - ShowMainDisplay(xview, yview, zview); + XYZPoint32 view_pos(_world.GetXSize() * 256 / 2, _world.GetYSize() * 256 / 2, 8 * 256); + ShowMainDisplay(view_pos); ShowToolbar(); ShowBottomToolbar(); } diff --git a/src/geometry.h b/src/geometry.h index e5b60fb..2354159 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -18,7 +18,6 @@ */ template struct Point { - Point() = default; /** @@ -67,6 +66,61 @@ inline bool operator==(const Point &p, const Point &q) } /** + * Generic 3D point template. + * @tparam CT Type of the coordinates. + */ +template +struct XYZPoint { + XYZPoint() = default; + + /** + * Constructor for creating a point at a given coordinate. + * @param x X coordinate. + * @param y Y coordinate. + * @param z Z coordinate. + */ + XYZPoint(CT x, CT y, CT z) + { + this->x = x; + this->y = y; + this->z = z; + } + + typedef CT CoordType; ///< Type of the coordinate value. + + CT x; ///< X coordinate. + CT y; ///< Y coordinate. + CT z; ///< Z coordinate. +}; + +typedef XYZPoint XYZPoint32; ///< 32 bit 3D point. +typedef XYZPoint XYZPoint16; ///< 16 bit 3D point. + +/** + * Test for 3D point equality. + * @param p First point to compare. + * @param q Second point to compare. + * @return Points are logically equal (same x, y, and z position). + */ +template +inline bool operator==(const XYZPoint &p, const XYZPoint &q) +{ + return p.x == q.x && p.y == q.y && p.z == q.z; +} + +/** + * Test for 3D point inequality. + * @param p First point to compare. + * @param q Second point to compare. + * @return Points are logically inequal (x, y, or z position is different). + */ +template +inline bool operator!=(const XYZPoint &p, const XYZPoint &q) +{ + return !(p == q); +} + +/** * An area in 2D. * @tparam PT Base point type. * @tparam SZ Size type. diff --git a/src/map.cpp b/src/map.cpp index ce7f320..1365102 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -142,7 +142,7 @@ VoxelObject::~VoxelObject() /** Mark the voxel containing the voxel object as dirty, so it is repainted. */ void VoxelObject::MarkDirty() { - MarkVoxelDirty(this->x_vox, this->y_vox, this->z_vox); + MarkVoxelDirty(XYZPoint16(this->x_vox, this->y_vox, this->z_vox)); } /** Default constructor. */ @@ -707,6 +707,6 @@ void WorldAdditions::MarkDirty(Viewport *vp) for (const auto &iter : this->modified_stacks) { const Point32 pt = iter.first; const VoxelStack *vstack = iter.second; - if (vstack != nullptr) vp->MarkVoxelDirty(pt.x, pt.x, vstack->base, vstack->height); + if (vstack != nullptr) vp->MarkVoxelDirty(XYZPoint16(pt.x, pt.x, vstack->base), vstack->height); } } diff --git a/src/path.cpp b/src/path.cpp index 514d297..069035f 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -240,39 +240,22 @@ uint8 GetPathExits(const Voxel *v) } /** - * Find all edges that are an exit for a path in the given voxel. No investigation is performed whether the exits connect to anything. - * @param xpos X position of the voxel. - * @param ypos Y position of the voxel. - * @param zpos Z position of the voxel. - * @return Exits for a path in the queried voxel. Lower 4 bits are exits at the bottom; upper 4 bits are exits at the top. - */ -uint8 GetPathExits(int xpos, int ypos, int zpos) -{ - if (!IsVoxelstackInsideWorld(xpos, ypos)) return 0; - const Voxel *v = _world.GetVoxel(xpos, ypos, zpos); - if (v == nullptr) return 0; - return GetPathExits(v); -} - -/** * Walk over a queue path from the given entry edge at the given position. * If it leads to a new voxel edge, the provided position and edge is update with the exit point. - * @param xp [inout] Start voxel X position before the queue path, updated to last voxel position. - * @param yp [inout] Start voxel Y position before the queue path, updated to last voxel position. - * @param zp [inout] Start voxel Z position before the queue path, updated to last voxel position. + * @param voxel_pos [inout] Start voxel position before the queue path, updated to last voxel position. * @param entry Direction used for entry to the path, updated to last edge exit direction. * @return Whether a (possibly) new last voxel could be found, \c false means the path leads to nowhere. * @note Parameter values may get changed during the call, do not rely on their values except when \c true is returned. */ -bool TravelQueuePath(int *xp, int *yp, int *zp, TileEdge *entry) +bool TravelQueuePath(XYZPoint16 *voxel_pos, TileEdge *entry) { - int orig_xp = *xp; - int orig_yp = *yp; - int orig_zp = *zp; + int orig_xp = voxel_pos->x; + int orig_yp = voxel_pos->y; + int orig_zp = voxel_pos->z; - int xpos = *xp; - int ypos = *yp; - int zpos = *zp; + int xpos = voxel_pos->x; + int ypos = voxel_pos->y; + int zpos = voxel_pos->z; TileEdge edge = *entry; /* Check that entry voxel actually exists. */ @@ -298,7 +281,7 @@ bool TravelQueuePath(int *xp, int *yp, int *zp, TileEdge *entry) if (_sprite_manager.GetPathStatus(GetPathType(vx->GetInstanceData())) != PAS_QUEUE_PATH) return true; /* At this point: - * *xp, *yp, *zp, edge (and *entry) contain the last valid voxel edge. + * voxel_pos->x, voxel_pos->y, voxel_pos->z, edge (and *entry) contain the last valid voxel edge. * xpos, ypos, zpos, vx is the next queue path tile position. */ @@ -306,8 +289,8 @@ bool TravelQueuePath(int *xp, int *yp, int *zp, TileEdge *entry) /* Check that the new tile can go back to our last tile. */ uint8 rev_edge = (edge + 2) % 4; - if (!((exits & (0x01 << rev_edge)) != 0 && zpos == *zp) && - !((exits & (0x10 << rev_edge)) != 0 && zpos == *zp -1)) { + if (!((exits & (0x01 << rev_edge)) != 0 && zpos == voxel_pos->z) && + !((exits & (0x10 << rev_edge)) != 0 && zpos == voxel_pos->z - 1)) { return false; } @@ -323,9 +306,9 @@ bool TravelQueuePath(int *xp, int *yp, int *zp, TileEdge *entry) if (edge == EDGE_COUNT) return false; // Queue path doesn't have a second exit. - *xp = xpos; - *yp = ypos; - *zp = zpos; + voxel_pos->x = xpos; + voxel_pos->y = ypos; + voxel_pos->z = zpos; *entry = edge; } } @@ -385,9 +368,7 @@ static int GetQuePathEdgeConnectCount(uint8 impl_slope) /** * Examine, and perhaps modify a neighbouring path edge or ride connection, to make it connect (or not if not \a add_edges) * to the centre examined tile. - * @param xpos X coordinate of the neighbouring voxel. - * @param ypos Y coordinate of the neighbouring voxel. - * @param zpos Z coordinate of the neighbouring voxel. + * @param voxel_pos Coordinate of the neighbouring voxel. * @param use_additions Use #_additions rather than #_world. * @param edge Edge to examine, and/or connected to. * @param add_edges If set, add edges (else, remove them). @@ -397,7 +378,7 @@ static int GetQuePathEdgeConnectCount(uint8 impl_slope) * @param dest_status [out] Status of the neighbouring path. * @return Neighbouring voxel was (logically) connected to the centre tile. */ -static bool ExamineNeighbourPathEdge(uint16 xpos, uint16 ypos, uint8 zpos, bool use_additions, TileEdge edge, bool add_edges, bool at_bottom, +static bool ExamineNeighbourPathEdge(const XYZPoint16 &voxel_pos, bool use_additions, TileEdge edge, bool add_edges, bool at_bottom, Voxel **dest_voxel, uint16 *dest_inst_data, PathStatus *dest_status) { Voxel *v; @@ -407,9 +388,9 @@ static bool ExamineNeighbourPathEdge(uint16 xpos, uint16 ypos, uint8 zpos, bool *dest_inst_data = PATH_INVALID; if (use_additions) { - v = _additions.GetCreateVoxel(xpos, ypos, zpos, false); + v = _additions.GetCreateVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z, false); } else { - v = _world.GetCreateVoxel(xpos, ypos, zpos, false); + v = _world.GetCreateVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z, false); } if (v == nullptr) return false; @@ -448,21 +429,19 @@ static bool ExamineNeighbourPathEdge(uint16 xpos, uint16 ypos, uint8 zpos, bool /** * Add edges of the neighbouring path tiles. - * @param xpos X coordinate of the central voxel with a path tile. - * @param ypos Y coordinate of the central voxel with a path tile. - * @param zpos Z coordinate of the central voxel with a path tile. + * @param voxel_pos Coordinate of the central voxel with a path tile. * @param slope Imploded path slope of the central voxel. * @param dirs Edge directions to change (bitset of #TileEdge), usually #EDGE_ALL. * @param use_additions Use #_additions rather than #_world. * @param status Status of the path. #PAS_UNUSED means to remove the edges. * @return Updated (imploded) slope at the central voxel. */ -uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint8 dirs, bool use_additions, PathStatus status) +uint8 AddRemovePathEdges(const XYZPoint16 &voxel_pos, uint8 slope, uint8 dirs, bool use_additions, PathStatus status) { PathStatus ngb_status[4]; // Neighbour path status, #PAS_UNUSED means do not connect. Voxel *ngb_voxel[4]; // Neighbour voxels with path, may be null if it doesn't need changing. uint16 ngb_instance_data[4]; // New instance data, if the voxel exists. - uint8 ngb_zpos[4]; // Z coordinate of the neighbouring voxel. + XYZPoint16 ngb_pos[4]; // Coordinate of the neighbouring voxel. std::fill_n(ngb_status, lengthof(ngb_status), PAS_UNUSED); // Clear path all statuses to prevent connecting to it if an edge is skipped. for (TileEdge edge = EDGE_BEGIN; edge < EDGE_COUNT; edge++) { @@ -476,20 +455,21 @@ uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint } } Point16 dxy = _tile_dxy[edge]; - if ((dxy.x < 0 && xpos == 0) || (dxy.x > 0 && xpos == _world.GetXSize() - 1)) continue; - if ((dxy.y < 0 && ypos == 0) || (dxy.y > 0 && ypos == _world.GetYSize() - 1)) continue; + ngb_pos[edge].x = voxel_pos.x + dxy.x; + ngb_pos[edge].y = voxel_pos.y + dxy.y; + if (!IsVoxelstackInsideWorld(ngb_pos[edge].x, ngb_pos[edge].y)) continue; TileEdge edge2 = (TileEdge)((edge + 2) % 4); bool modified = false; - if (delta_z <= 0 || zpos < WORLD_Z_SIZE - 1) { - ngb_zpos[edge] = zpos + delta_z; - modified = ExamineNeighbourPathEdge(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, use_additions, edge2, status != PAS_UNUSED, true, + if (delta_z <= 0 || voxel_pos.z < WORLD_Z_SIZE - 1) { + ngb_pos[edge].z = voxel_pos.z + delta_z; + modified = ExamineNeighbourPathEdge(ngb_pos[edge], use_additions, edge2, status != PAS_UNUSED, true, &ngb_voxel[edge], &ngb_instance_data[edge], &ngb_status[edge]); } delta_z--; - if (!modified && (delta_z >= 0 || zpos > 0)) { - ngb_zpos[edge] = zpos + delta_z; - ExamineNeighbourPathEdge(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, use_additions, edge2, status != PAS_UNUSED, false, + if (!modified && (delta_z >= 0 || voxel_pos.z > 0)) { + ngb_pos[edge].z = voxel_pos.z + delta_z; + ExamineNeighbourPathEdge(ngb_pos[edge], use_additions, edge2, status != PAS_UNUSED, false, &ngb_voxel[edge], &ngb_instance_data[edge], &ngb_status[edge]); } } @@ -502,7 +482,7 @@ uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint if (slope < PATH_FLAT_COUNT) slope = SetPathEdge(slope, edge, status != PAS_UNUSED); if (ngb_voxel[edge] != nullptr) { ngb_voxel[edge]->SetInstanceData(ngb_instance_data[edge]); - MarkVoxelDirty(xpos + _tile_dxy[edge].x, ypos + _tile_dxy[edge].y, ngb_zpos[edge]); + MarkVoxelDirty(ngb_pos[edge]); } } } @@ -517,7 +497,7 @@ uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint if (slope < PATH_FLAT_COUNT) slope = SetPathEdge(slope, edge, true); if (ngb_voxel[edge] != nullptr) { ngb_voxel[edge]->SetInstanceData(ngb_instance_data[edge]); - MarkVoxelDirty(xpos + _tile_dxy[edge].x, ypos + _tile_dxy[edge].y, ngb_zpos[edge]); + MarkVoxelDirty(ngb_pos[edge]); } } } @@ -529,7 +509,7 @@ uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint if (slope < PATH_FLAT_COUNT) slope = SetPathEdge(slope, edge, true); if (ngb_voxel[edge] != nullptr) { ngb_voxel[edge]->SetInstanceData(ngb_instance_data[edge]); - MarkVoxelDirty(xpos + _tile_dxy[edge].x, ypos + _tile_dxy[edge].y, ngb_zpos[edge]); + MarkVoxelDirty(ngb_pos[edge]); } } } diff --git a/src/path.h b/src/path.h index e739679..05e6664 100644 --- a/src/path.h +++ b/src/path.h @@ -127,12 +127,11 @@ extern const uint8 _path_rotation[PATH_COUNT][4]; struct Voxel; uint8 GetPathExits(const Voxel *v); -uint8 GetPathExits(int xpos, int ypos, int zpos); -bool TravelQueuePath(int *xp, int *yp, int *zp, TileEdge *entry); +bool TravelQueuePath(XYZPoint16 *voxel_pos, TileEdge *entry); -bool PathExistsAtBottomEdge(int xpos, int ypos, int zpos, TileEdge edge); +bool PathExistsAtBottomEdge(XYZPoint16 voxel_pos, TileEdge edge); uint8 SetPathEdge(uint8 slope, TileEdge edge, bool connect); -uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint8 dirs, bool use_additions, PathStatus status); +uint8 AddRemovePathEdges(const XYZPoint16 &voxel_pos, uint8 slope, uint8 dirs, bool use_additions, PathStatus status); #endif diff --git a/src/path_build.cpp b/src/path_build.cpp index 4a3fa8a..79f0b5a 100644 --- a/src/path_build.cpp +++ b/src/path_build.cpp @@ -20,87 +20,82 @@ PathBuildManager _path_builder; ///< %Path build manager. /** * Build a path at a tile, and claim the voxels above it as well. - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param path_type The type of path to build. * @param path_spr Imploded sprite number. * @see RemovePathAtTile */ -static void BuildPathAtTile(int xpos, int ypos, int zpos, PathType path_type, uint8 path_spr) +static void BuildPathAtTile(const XYZPoint16 &voxel_pos, PathType path_type, uint8 path_spr) { - VoxelStack *avs = _additions.GetModifyStack(xpos, ypos); + VoxelStack *avs = _additions.GetModifyStack(voxel_pos.x, voxel_pos.y); - Voxel *av = avs->GetCreate(zpos, true); + Voxel *av = avs->GetCreate(voxel_pos.z, true); av->SetInstance(SRI_PATH); - uint8 slope = AddRemovePathEdges(xpos, ypos, zpos, path_spr, EDGE_ALL, true, _sprite_manager.GetPathStatus(path_type)); + uint8 slope = AddRemovePathEdges(voxel_pos, path_spr, EDGE_ALL, true, _sprite_manager.GetPathStatus(path_type)); av->SetInstanceData(MakePathInstanceData(slope, path_type)); - av = avs->GetCreate(zpos + 1, true); + av = avs->GetCreate(voxel_pos.z + 1, true); av->ClearVoxel(); av->SetInstance(SRI_PATH); av->SetInstanceData(PATH_INVALID); if (path_spr >= PATH_FLAT_COUNT) { // For non-flat sprites, add another voxel. - av = avs->GetCreate(zpos + 2, true); + av = avs->GetCreate(voxel_pos.z + 2, true); av->ClearVoxel(); av->SetInstance(SRI_PATH); av->SetInstanceData(PATH_INVALID); } - MarkVoxelDirty(xpos, ypos, zpos); + MarkVoxelDirty(voxel_pos); } /** * Remove a path from a tile, and free the voxels above it as well. - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param path_spr Imploded sprite number. * @see BuildPathAtTile */ -static void RemovePathAtTile(int xpos, int ypos, int zpos, uint8 path_spr) +static void RemovePathAtTile(const XYZPoint16 &voxel_pos, uint8 path_spr) { - VoxelStack *avs = _additions.GetModifyStack(xpos, ypos); + VoxelStack *avs = _additions.GetModifyStack(voxel_pos.x, voxel_pos.y); - Voxel *av = avs->GetCreate(zpos, false); - av->SetInstance(SRI_FREE); - av->SetInstanceData(0); - AddRemovePathEdges(xpos, ypos, zpos, path_spr, EDGE_ALL, true, PAS_UNUSED); - MarkVoxelDirty(xpos, ypos, zpos); + Voxel *av = avs->GetCreate(voxel_pos.z, false); + av->SetInstance(SRI_FREE); + av->SetInstanceData(0); + AddRemovePathEdges(voxel_pos, path_spr, EDGE_ALL, true, PAS_UNUSED); + MarkVoxelDirty(voxel_pos); + + av = avs->GetCreate(voxel_pos.z + 1, false); + av->SetInstance(SRI_FREE); + av->SetInstanceData(0); - av = avs->GetCreate(zpos + 1, false); + if (path_spr >= PATH_FLAT_COUNT) { + av = avs->GetCreate(voxel_pos.z + 2, false); av->SetInstance(SRI_FREE); av->SetInstanceData(0); - - if (path_spr >= PATH_FLAT_COUNT) { - av = avs->GetCreate(zpos + 2, false); - av->SetInstance(SRI_FREE); - av->SetInstanceData(0); - } + } } /** * Does a path run at/to the bottom the given voxel in the neighbouring voxel? - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param edge Direction to move to get the neighbouring voxel. * @return Whether a path exists at the bottom of the neighbouring voxel. * @pre voxel coordinate must be valid in the world. * @todo Merge with path computations in the path placement. */ -bool PathExistsAtBottomEdge(int xpos, int ypos, int zpos, TileEdge edge) +bool PathExistsAtBottomEdge(XYZPoint16 voxel_pos, TileEdge edge) { - xpos += _tile_dxy[edge].x; - ypos += _tile_dxy[edge].y; - if (!IsVoxelstackInsideWorld(xpos, ypos)) return false; + voxel_pos.x += _tile_dxy[edge].x; + voxel_pos.y += _tile_dxy[edge].y; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return false; - const Voxel *vx = _world.GetVoxel(xpos, ypos, zpos); + const Voxel *vx = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z); if (vx == nullptr || !HasValidPath(vx)) { /* No path here, check the voxel below. */ - if (zpos == 0) return false; - vx = _world.GetVoxel(xpos, ypos, zpos - 1); + if (voxel_pos.z == 0) return false; + voxel_pos.z--; + vx = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z); if (vx == nullptr || !HasValidPath(vx)) return false; /* Path must end at the top of the voxel. */ return GetImplodedPathSlope(vx) == _path_up_from_edge[edge]; @@ -111,30 +106,28 @@ bool PathExistsAtBottomEdge(int xpos, int ypos, int zpos, TileEdge edge) /** * In the given voxel, can an upward path be build in the voxel from the bottom at the given edge? - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param edge Entry edge. * @param path_type For building (ie not \a test_only), the type of path to build. * @param test_only Only test whether it could be created. * @return Whether the path is or could be built. */ -static bool BuildUpwardPath(int16 xpos, int16 ypos, int8 zpos, TileEdge edge, PathType path_type, bool test_only) +static bool BuildUpwardPath(const XYZPoint16 &voxel_pos, TileEdge edge, PathType path_type, bool test_only) { /* xy position should be valid, and allow path building. */ - if (!IsVoxelstackInsideWorld(xpos, ypos)) return false; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(xpos, ypos) != OWN_PARK) return false; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return false; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(voxel_pos.x, voxel_pos.y) != OWN_PARK) return false; - if (zpos < 0 || zpos > WORLD_Z_SIZE - 3) return false; // Z range should be valid. + if (voxel_pos.z < 0 || voxel_pos.z > WORLD_Z_SIZE - 3) return false; // Z range should be valid. - const VoxelStack *vs = _world.GetStack(xpos, ypos); - const Voxel *v = vs->Get(zpos + 1); // Voxel above the path should be empty. + const VoxelStack *vs = _world.GetStack(voxel_pos.x, voxel_pos.y); + const Voxel *v = vs->Get(voxel_pos.z + 1); // Voxel above the path should be empty. if (v != nullptr && !v->IsEmpty()) return false; - v = vs->Get(zpos + 2); // 2 voxels higher should also be empty. + v = vs->Get(voxel_pos.z + 2); // 2 voxels higher should also be empty. if (v != nullptr && !v->IsEmpty()) return false; - v = vs->Get(zpos); + v = vs->Get(voxel_pos.z); if (v != nullptr) { if (v->GetInstance() != SRI_FREE) return false; // Voxel should have no other rides. if (v->GetGroundType() != GTP_INVALID) { @@ -149,31 +142,29 @@ static bool BuildUpwardPath(int16 xpos, int16 ypos, int8 zpos, TileEdge edge, Pa } } - if (!test_only) BuildPathAtTile(xpos, ypos, zpos, path_type, _path_up_from_edge[edge]); + if (!test_only) BuildPathAtTile(voxel_pos, path_type, _path_up_from_edge[edge]); return true; } /** * In the given voxel, can a flat path be build in the voxel? - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param path_type For building (ie not \a test_only), the type of path to build. * @param test_only Only test whether it could be created. * @return Whether the path is or could be built. */ -static bool BuildFlatPath(int16 xpos, int16 ypos, int8 zpos, PathType path_type, bool test_only) +static bool BuildFlatPath(const XYZPoint16 &voxel_pos, PathType path_type, bool test_only) { /* xy position should be valid, and allow path building. */ - if (!IsVoxelstackInsideWorld(xpos, ypos)) return false; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(xpos, ypos) != OWN_PARK) return false; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return false; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(voxel_pos.x, voxel_pos.y) != OWN_PARK) return false; - if (zpos < 0 || zpos > WORLD_Z_SIZE - 2) return false; // Z range should be valid. + if (voxel_pos.z < 0 || voxel_pos.z > WORLD_Z_SIZE - 2) return false; // Z range should be valid. - const VoxelStack *vs = _world.GetStack(xpos, ypos); - const Voxel *v = vs->Get(zpos + 1); // Voxel above the path should be empty. + const VoxelStack *vs = _world.GetStack(voxel_pos.x, voxel_pos.y); + const Voxel *v = vs->Get(voxel_pos.z + 1); // Voxel above the path should be empty. if (v != nullptr && !v->IsEmpty()) return false; - v = vs->Get(zpos); + v = vs->Get(voxel_pos.z); if (v != nullptr) { if (v->GetInstance() != SRI_FREE) return false; // Voxel should have no other rides. if (v->GetGroundType() != GTP_INVALID) { @@ -186,36 +177,34 @@ static bool BuildFlatPath(int16 xpos, int16 ypos, int8 zpos, PathType path_type, } } - if (!test_only) BuildPathAtTile(xpos, ypos, zpos, path_type, PATH_EMPTY); + if (!test_only) BuildPathAtTile(voxel_pos, path_type, PATH_EMPTY); return true; } /** * In the given voxel, can an downward path be build in the voxel from the bottom at the given edge? - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param edge Entry edge. * @param path_type For building (ie not \a test_only), the type of path to build. * @param test_only Only test whether it could be created. * @return Whether the path is or could be built. */ -static bool BuildDownwardPath(int16 xpos, int16 ypos, int8 zpos, TileEdge edge, PathType path_type, bool test_only) +static bool BuildDownwardPath(XYZPoint16 voxel_pos, TileEdge edge, PathType path_type, bool test_only) { /* xy position should be valid, and allow path building. */ - if (!IsVoxelstackInsideWorld(xpos, ypos)) return false; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(xpos, ypos) != OWN_PARK) return false; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return false; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(voxel_pos.x, voxel_pos.y) != OWN_PARK) return false; - if (zpos <= 0 || zpos > WORLD_Z_SIZE - 3) return false; // Z range should be valid. + if (voxel_pos.z <= 0 || voxel_pos.z > WORLD_Z_SIZE - 3) return false; // Z range should be valid. - const VoxelStack *vs = _world.GetStack(xpos, ypos); - const Voxel *v = vs->Get(zpos); // Voxel above the path should be empty. + const VoxelStack *vs = _world.GetStack(voxel_pos.x, voxel_pos.y); + const Voxel *v = vs->Get(voxel_pos.z); // Voxel above the path should be empty. if (v != nullptr && !v->IsEmpty()) return false; - v = vs->Get(zpos + 1); // 1 voxel higher should also be empty. + v = vs->Get(voxel_pos.z + 1); // 1 voxel higher should also be empty. if (v != nullptr && !v->IsEmpty()) return false; - v = vs->Get(zpos - 1); + v = vs->Get(voxel_pos.z - 1); if (v != nullptr) { if (v->GetInstance() != SRI_FREE) return false; // Voxel should have no other rides. if (v->GetGroundType() != GTP_INVALID) { @@ -230,111 +219,110 @@ static bool BuildDownwardPath(int16 xpos, int16 ypos, int8 zpos, TileEdge edge, } } - if (!test_only) BuildPathAtTile(xpos, ypos, zpos - 1, path_type, _path_down_from_edge[edge]); + if (!test_only) { + voxel_pos.z--; + BuildPathAtTile(voxel_pos, path_type, _path_down_from_edge[edge]); + } return true; } /** * (Try to) remove a path from the given voxel. - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param test_only Only test whether it could be removed. * @return Whether the path is or could be removed. */ -static bool RemovePath(int16 xpos, int16 ypos, int8 zpos, bool test_only) +static bool RemovePath(const XYZPoint16 &voxel_pos, bool test_only) { /* xy position should be valid, and allow path building. */ - if (!IsVoxelstackInsideWorld(xpos, ypos)) return false; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(xpos, ypos) != OWN_PARK) return false; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return false; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(voxel_pos.x, voxel_pos.y) != OWN_PARK) return false; - if (zpos <= 0 || zpos > WORLD_Z_SIZE - 2) return false; // Z range should be valid. + if (voxel_pos.z <= 0 || voxel_pos.z > WORLD_Z_SIZE - 2) return false; // Z range should be valid. - const VoxelStack *vs = _world.GetStack(xpos, ypos); - const Voxel *v = vs->Get(zpos); + const VoxelStack *vs = _world.GetStack(voxel_pos.x, voxel_pos.y); + const Voxel *v = vs->Get(voxel_pos.z); if (v == nullptr || !HasValidPath(v)) return false; PathSprites ps = GetImplodedPathSlope(v); assert(ps < PATH_COUNT); - v = vs->Get(zpos + 1); + v = vs->Get(voxel_pos.z + 1); assert(v->GetInstance() == SRI_PATH && !HasValidPath(v->GetInstanceData())); if (ps >= PATH_FLAT_COUNT) { - v = vs->Get(zpos + 2); + v = vs->Get(voxel_pos.z + 2); assert(v->GetInstance() == SRI_PATH && !HasValidPath(v->GetInstanceData())); } - if (!test_only) RemovePathAtTile(xpos, ypos, zpos, ps); + if (!test_only) RemovePathAtTile(voxel_pos, ps); return true; } /** * In the given voxel, can a path be build in the voxel from the bottom at the given edge? - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @param edge Entry edge. * @return Bit-set of track slopes, indicating the directions of building paths. */ -static uint8 CanBuildPathFromEdge(int16 xpos, int16 ypos, int8 zpos, TileEdge edge) +static uint8 CanBuildPathFromEdge(const XYZPoint16 &voxel_pos, TileEdge edge) { - if (!IsVoxelstackInsideWorld(xpos, ypos)) return 0; - if (zpos < 0 || zpos >= WORLD_Z_SIZE - 1) return 0; + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return 0; + if (voxel_pos.z < 0 || voxel_pos.z >= WORLD_Z_SIZE - 1) return 0; /* If other side of the edge is not on-world or not owned, don't compute path options. */ Point16 dxy = _tile_dxy[edge]; - if (!IsVoxelstackInsideWorld(xpos + dxy.x, ypos + dxy.y) || - (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(xpos + dxy.x, ypos + dxy.y) != OWN_PARK)) return 0; + if (!IsVoxelstackInsideWorld(voxel_pos.x + dxy.x, voxel_pos.y + dxy.y) || + (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(voxel_pos.x + dxy.x, voxel_pos.y + dxy.y) != OWN_PARK)) return 0; - const Voxel *v = _world.GetVoxel(xpos, ypos, zpos); + const Voxel *v = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z); if (v != nullptr && HasValidPath(v)) { PathSprites ps = GetImplodedPathSlope(v); if (ps < PATH_FLAT_COUNT) return 1 << TSL_FLAT; if (ps == _path_up_from_edge[edge]) return 1 << TSL_UP; } - if (zpos > 0) { - v = _world.GetVoxel(xpos, ypos, zpos - 1); + if (voxel_pos.z > 0) { + v = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z - 1); if (v != nullptr && HasValidPath(v) && GetImplodedPathSlope(v) == _path_down_from_edge[edge]) return 1 << TSL_DOWN; } uint8 slopes = 0; // XXX Check for already existing paths. - if (BuildDownwardPath(xpos, ypos, zpos, edge, PAT_INVALID, true)) slopes |= 1 << TSL_DOWN; - if (BuildFlatPath(xpos, ypos, zpos, PAT_INVALID, true)) slopes |= 1 << TSL_FLAT; - if (BuildUpwardPath(xpos, ypos, zpos, edge, PAT_INVALID, true)) slopes |= 1 << TSL_UP; + if (BuildDownwardPath(voxel_pos, edge, PAT_INVALID, true)) slopes |= 1 << TSL_DOWN; + if (BuildFlatPath(voxel_pos, PAT_INVALID, true)) slopes |= 1 << TSL_FLAT; + if (BuildUpwardPath(voxel_pos, edge, PAT_INVALID, true)) slopes |= 1 << TSL_UP; return slopes; } /** * Compute the attach points of a path in a voxel. - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param voxel_pos Coordinate of the voxel. * @return Attach points for paths starting from the given voxel coordinates. * Upper 4 bits are the edges at the top of the voxel, lower 4 bits are the attach points for the bottom of the voxel. */ -static uint8 GetPathAttachPoints(int16 xpos, int16 ypos, int8 zpos) +static uint8 GetPathAttachPoints(const XYZPoint16 &voxel_pos) { - if (!IsVoxelstackInsideWorld(xpos, ypos)) return 0; - if (zpos >= WORLD_Z_SIZE - 1) return 0; // The voxel containing the flat path, and one above it. + if (!IsVoxelstackInsideWorld(voxel_pos.x, voxel_pos.y)) return 0; + if (voxel_pos.z >= WORLD_Z_SIZE - 1) return 0; // The voxel containing the flat path, and one above it. - const Voxel *v = _world.GetVoxel(xpos, ypos, zpos); + const Voxel *v = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z); if (v == nullptr) return 0; uint8 edges = 0; for (TileEdge edge = EDGE_BEGIN; edge < EDGE_COUNT; edge++) { - uint16 x = xpos + _tile_dxy[edge].x; - uint16 y = ypos + _tile_dxy[edge].y; + uint16 x = voxel_pos.x + _tile_dxy[edge].x; + uint16 y = voxel_pos.y + _tile_dxy[edge].y; if (!IsVoxelstackInsideWorld(x, y)) continue; + const XYZPoint16 new_pos(x, y, voxel_pos.z); if (HasValidPath(v)) { PathSprites ps = GetImplodedPathSlope(v); if (ps < PATH_FLAT_COUNT) { - if (CanBuildPathFromEdge(x, y, zpos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; + if (CanBuildPathFromEdge(new_pos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; } else { + const XYZPoint16 new_above(x, y, voxel_pos.z + 1); if (_path_up_from_edge[edge] == ps - && CanBuildPathFromEdge(x, y, zpos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; + && CanBuildPathFromEdge(new_pos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; if (_path_down_from_edge[edge] == ps - && CanBuildPathFromEdge(x, y, zpos + 1, (TileEdge)((edge + 2) % 4)) != 0) edges |= (1 << edge) << 4; + && CanBuildPathFromEdge(new_above, (TileEdge)((edge + 2) % 4)) != 0) edges |= (1 << edge) << 4; } continue; } @@ -342,9 +330,10 @@ static uint8 GetPathAttachPoints(int16 xpos, int16 ypos, int8 zpos) TileSlope ts = ExpandTileSlope(v->GetGroundSlope()); if ((ts & TSB_STEEP) != 0) continue; if ((ts & _corners_at_edge[edge]) == 0) { - if (CanBuildPathFromEdge(x, y, zpos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; + if (CanBuildPathFromEdge(new_pos, (TileEdge)((edge + 2) % 4)) != 0) edges |= 1 << edge; } else { - if (CanBuildPathFromEdge(x, y, zpos + 1, (TileEdge)((edge + 2) % 4)) != 0) edges |= (1 << edge) << 4; + const XYZPoint16 new_above(x, y, voxel_pos.z + 1); + if (CanBuildPathFromEdge(new_above, (TileEdge)((edge + 2) % 4)) != 0) edges |= (1 << edge) << 4; } continue; } @@ -406,7 +395,7 @@ void PathBuildManager::OnMouseMoveEvent(Viewport *vp, const Point16 &old_pos, co if (this->state == PBS_WAIT_VOXEL) { FinderData fdata((CS_GROUND | CS_PATH), FW_TILE); if (vp->ComputeCursorPosition(&fdata) != CS_NONE) { - vp->tile_cursor.SetCursor(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel, fdata.cursor); + vp->tile_cursor.SetCursor(fdata.voxel_pos, fdata.cursor); } } } @@ -421,9 +410,7 @@ void PathBuildManager::OnMouseButtonEvent(Viewport *vp, uint8 state) this->ConfirmLongPath(); } else { FinderData fdata((CS_GROUND | CS_PATH), FW_TILE); - if (vp->ComputeCursorPosition(&fdata) != CS_NONE) { - this->TileClicked(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel); - } + if (vp->ComputeCursorPosition(&fdata) != CS_NONE) this->TileClicked(fdata.voxel_pos); } } } @@ -442,19 +429,17 @@ void PathBuildManager::SetPathGuiState(bool opened) /** * User clicked somewhere. Check whether it is a good tile or path, and if so, move the building process forward. - * @param xpos X coordinate of the voxel. - * @param ypos Y coordinate of the voxel. - * @param zpos Z coordinate of the voxel. + * @param click_pos Coordinate of the voxel. */ -void PathBuildManager::TileClicked(uint16 xpos, uint16 ypos, uint8 zpos) +void PathBuildManager::TileClicked(const XYZPoint16 &click_pos) { if (this->state == PBS_IDLE || this->state > PBS_WAIT_BUY) return; - uint8 dirs = GetPathAttachPoints(xpos, ypos, zpos); + uint8 dirs = GetPathAttachPoints(click_pos); if (dirs == 0) return; - this->xpos = xpos; - this->ypos = ypos; - this->zpos = zpos; + this->xpos = click_pos.x; + this->ypos = click_pos.y; + this->zpos = click_pos.z; this->allowed_arrows = dirs; this->state = PBS_WAIT_ARROW; this->UpdateState(); @@ -577,30 +562,27 @@ void PathBuildManager::SelectMovement(bool move_forward) /** * Compute the voxel to display the arrow cursor. - * @param xpos [out] Computed X position of the voxel that should contain the arrow cursor. - * @param ypos [out] Computed Y position of the voxel that should contain the arrow cursor. - * @param zpos [out] Computed Z position of the voxel that should contain the arrow cursor. + * @return Computed position of the voxel that should contain the arrow cursor. */ -void PathBuildManager::ComputeArrowCursorPosition(uint16 *xpos, uint16 *ypos, uint8 *zpos) +XYZPoint16 PathBuildManager::ComputeArrowCursorPosition() { assert(this->state > PBS_WAIT_ARROW && this->state <= PBS_WAIT_BUY); assert(this->selected_arrow != INVALID_EDGE); Point16 dxy = _tile_dxy[this->selected_arrow]; - *xpos = this->xpos + dxy.x; - *ypos = this->ypos + dxy.y; + int xpos = this->xpos + dxy.x; + int ypos = this->ypos + dxy.y; uint8 bit = 1 << this->selected_arrow; - *zpos = this->zpos; + int zpos = this->zpos; if ((bit & this->allowed_arrows) == 0) { // Build direction is not at the bottom of the voxel. assert(((bit << 4) & this->allowed_arrows) != 0); // Should be available at the top of the voxel. - (*zpos)++; + zpos++; } /* Do some paranoia checking. */ - assert(*xpos < _world.GetXSize()); - assert(*ypos < _world.GetYSize()); - assert(*zpos < WORLD_Z_SIZE); + assert(IsVoxelInsideWorld(xpos, ypos, zpos)); + return XYZPoint16(xpos, ypos, zpos); } /** Compute the new contents of the voxel where the path should be added from the #_world. */ @@ -611,21 +593,19 @@ void PathBuildManager::ComputeWorldAdditions() if (((1 << this->selected_slope) & this->allowed_slopes) == 0) return; - uint16 xpos, ypos; - uint8 zpos; - this->ComputeArrowCursorPosition(&xpos, &ypos, &zpos); + XYZPoint16 arrow_pos = this->ComputeArrowCursorPosition(); TileEdge edge = (TileEdge)((this->selected_arrow + 2) % 4); switch (this->selected_slope) { case TSL_DOWN: - BuildDownwardPath(xpos, ypos, zpos, edge, this->path_type, false); + BuildDownwardPath(arrow_pos, edge, this->path_type, false); break; case TSL_FLAT: - BuildFlatPath(xpos, ypos, zpos, this->path_type, false); + BuildFlatPath(arrow_pos, this->path_type, false); break; case TSL_UP: - BuildUpwardPath(xpos, ypos, zpos, edge, this->path_type, false); + BuildUpwardPath(arrow_pos, edge, this->path_type, false); break; default: @@ -645,12 +625,12 @@ void PathBuildManager::UpdateState() /* The tile cursor is controlled by the viewport if waiting for a voxel or earlier. */ if (vp != nullptr && this->state > PBS_WAIT_VOXEL && this->state <= PBS_WAIT_BUY) { - vp->tile_cursor.SetCursor(this->xpos, this->ypos, this->zpos, CUR_TYPE_TILE); + vp->tile_cursor.SetCursor(XYZPoint16(this->xpos, this->ypos, this->zpos), CUR_TYPE_TILE); } /* See whether the PBS_WAIT_ARROW state can be left automatically. */ if (this->state == PBS_WAIT_ARROW) { - this->allowed_arrows = GetPathAttachPoints(this->xpos, this->ypos, this->zpos); + this->allowed_arrows = GetPathAttachPoints(XYZPoint16(this->xpos, this->ypos, this->zpos)); /* If a valid selection has been made, or if only one choice exists, take it. */ if (this->selected_arrow != INVALID_EDGE && ((0x11 << this->selected_arrow) & this->allowed_arrows) != 0) { @@ -673,10 +653,8 @@ void PathBuildManager::UpdateState() /* Set the arrow cursor. Note that display is controlled later. */ if (vp != nullptr) { if (this->state > PBS_WAIT_ARROW && this->state <= PBS_WAIT_BUY) { - uint16 x_arrow, y_arrow; - uint8 z_arrow; - this->ComputeArrowCursorPosition(&x_arrow, &y_arrow, &z_arrow); - vp->arrow_cursor.SetCursor(x_arrow, y_arrow, z_arrow, (CursorType)(CUR_TYPE_ARROW_NE + this->selected_arrow)); + XYZPoint16 arrow_pos = this->ComputeArrowCursorPosition(); + vp->arrow_cursor.SetCursor(arrow_pos, (CursorType)(CUR_TYPE_ARROW_NE + this->selected_arrow)); } else { vp->arrow_cursor.SetInvalid(); } @@ -685,10 +663,8 @@ void PathBuildManager::UpdateState() /* See whether the PBS_WAIT_SLOPE state can be left automatically. */ if (this->state == PBS_WAIT_SLOPE) { /* Compute allowed slopes. */ - uint16 x_arrow, y_arrow; - uint8 z_arrow; - this->ComputeArrowCursorPosition(&x_arrow, &y_arrow, &z_arrow); - this->allowed_slopes = CanBuildPathFromEdge(x_arrow, y_arrow, z_arrow, (TileEdge)((this->selected_arrow + 2) % 4)); + XYZPoint16 arrow_pos = this->ComputeArrowCursorPosition(); + this->allowed_slopes = CanBuildPathFromEdge(arrow_pos, (TileEdge)((this->selected_arrow + 2) % 4)); /* If a valid selection has been made, or if only one choice exists, take it. */ if (this->selected_slope != TSL_INVALID && ((1 << this->selected_slope) & this->allowed_slopes) != 0) { @@ -816,12 +792,12 @@ void PathBuildManager::ComputeNewLongPath(const Point32 &mousexy) /* X constant. */ vx /= 256; vy = Clamp(mousexy.y + c1 * lambda_x, 0, _world.GetYSize() * 256 - 1) / 256; - vz = Clamp(vp->zview + c3 * lambda_x, 0, WORLD_Z_SIZE * 256 - 1) / 256; + vz = Clamp(vp->view_pos.z + c3 * lambda_x, 0, WORLD_Z_SIZE * 256 - 1) / 256; } else { /* Y constant. */ vx = Clamp(mousexy.x + c1 * lambda_y, 0, _world.GetXSize() * 256 - 1) / 256; vy /= 256; - vz = Clamp(vp->zview + c2 * lambda_y, 0, WORLD_Z_SIZE * 256 - 1) / 256; + vz = Clamp(vp->view_pos.z + c2 * lambda_y, 0, WORLD_Z_SIZE * 256 - 1) / 256; } if (this->xlong != vx || this->ylong != vy || this->zlong != vz) { @@ -845,7 +821,7 @@ void PathBuildManager::ComputeNewLongPath(const Point32 &mousexy) /* 'Walk' to the cursor as long as possible. */ while (vx != this->xlong || vy != this->ylong) { - uint8 slopes = CanBuildPathFromEdge(vx, vy, vz, direction); + uint8 slopes = CanBuildPathFromEdge(XYZPoint16(vx, vy, vz), direction); const TrackSlope *slope_prio; /* Get order of slope preference. */ if (vz > this->zlong) { @@ -862,13 +838,13 @@ void PathBuildManager::ComputeNewLongPath(const Point32 &mousexy) vx += dxy.x; vy += dxy.y; if (*slope_prio == TSL_UP) { - if (!BuildUpwardPath(vx, vy, vz, static_cast((direction + 2) & 3), this->path_type, false)) break; + if (!BuildUpwardPath(XYZPoint16(vx, vy, vz), static_cast((direction + 2) & 3), this->path_type, false)) break; vz++; } else if (*slope_prio == TSL_DOWN) { - if (!BuildDownwardPath(vx, vy, vz, static_cast((direction + 2) & 3), this->path_type, false)) break; + if (!BuildDownwardPath(XYZPoint16(vx, vy, vz), static_cast((direction + 2) & 3), this->path_type, false)) break; vz--; } else { - if (!BuildFlatPath(vx, vy, vz, this->path_type, false)) break; + if (!BuildFlatPath(XYZPoint16(vx, vy, vz), this->path_type, false)) break; } } @@ -919,7 +895,7 @@ void PathBuildManager::SelectBuyRemove(bool buying) PathSprites ps = GetImplodedPathSlope(v); _additions.Clear(); - if (RemovePath(this->xpos, this->ypos, this->zpos, false)) { + if (RemovePath(XYZPoint16(this->xpos, this->ypos, this->zpos), false)) { _additions.Commit(); } diff --git a/src/path_build.h b/src/path_build.h index a72a675..73fb8af 100644 --- a/src/path_build.h +++ b/src/path_build.h @@ -44,7 +44,7 @@ public: void SetPathGuiState(bool opened); - void TileClicked(uint16 xpos, uint16 ypos, uint8 zpos); + void TileClicked(const XYZPoint16 &click_pos); void ComputeNewLongPath(const Point32 &mousexy); void ConfirmLongPath(); void SelectArrow(TileEdge direction); @@ -82,7 +82,7 @@ private: uint8 allowed_slopes; ///< Allowed slope directions for the build direction. TrackSlope selected_slope; ///< Last selected slope (#TSL_INVALID if none has been chosen). - void ComputeArrowCursorPosition(uint16 *xpos, uint16 *ypos, uint8 *zpos); + XYZPoint16 ComputeArrowCursorPosition(); void ComputeWorldAdditions(); void MoveCursor(TileEdge edge, bool move_up); void UpdateState(); diff --git a/src/person.cpp b/src/person.cpp index 5d92f68..99568c8 100644 --- a/src/person.cpp +++ b/src/person.cpp @@ -395,10 +395,14 @@ RideVisitDesire Guest::ComputeExitDesire(TileEdge current_edge, int x, int y, in { if (current_edge == exit_edge) return RVD_NO_VISIT; // Skip incoming edge (may get added later if no other options exist). - bool travel = TravelQueuePath(&x, &y, &z, &exit_edge); + XYZPoint16 voxel_pos(x, y, z); + bool travel = TravelQueuePath(&voxel_pos, &exit_edge); if (!travel) return RVD_NO_VISIT; // Path leads to nowhere. + x = voxel_pos.x; + y = voxel_pos.y; + z = voxel_pos.z; - if (PathExistsAtBottomEdge(x, y, z, exit_edge)) return RVD_NO_RIDE; // Found a path. + if (PathExistsAtBottomEdge(XYZPoint16(x, y, z), exit_edge)) return RVD_NO_RIDE; // Found a path. RideInstance *ri = RideExistsAtBottom(x, y, z, exit_edge); if (ri == nullptr || ri->state != RIS_OPEN) return RVD_NO_VISIT; // No ride, or a closed one. diff --git a/src/ride_gui.cpp b/src/ride_gui.cpp index f72631d..8d7153d 100644 --- a/src/ride_gui.cpp +++ b/src/ride_gui.cpp @@ -393,7 +393,7 @@ bool ShopPlacementManager::CanPlaceShop(const ShopType *selected_shop, int xpos, for (TileEdge entrance = EDGE_BEGIN; entrance < EDGE_COUNT; entrance++) { // Loop over the 4 unrotated directions. if ((selected_shop->flags & (1 << entrance)) == 0) continue; // No entrance here. TileEdge entr = (TileEdge)((entrance + vp->orientation + this->orientation) & 3); // Perform rotation specified by the user in the GUI. - if (PathExistsAtBottomEdge(xpos, ypos, zpos, entr)) return true; + if (PathExistsAtBottomEdge(XYZPoint16(xpos, ypos, zpos), entr)) return true; } return false; } @@ -467,7 +467,7 @@ void ShopPlacementManager::PlaceShop(const Point16 &pos) Point32 wxy = vp->ComputeHorizontalTranslation(vp->rect.width / 2 - pos.x, vp->rect.height / 2 - pos.y); /* Clean current display if needed. */ - switch (this->ComputeShopVoxel(wxy.x, wxy.y, vp->zview)) { + switch (this->ComputeShopVoxel(wxy.x, wxy.y, vp->view_pos.z)) { case RPR_FAIL: if (this->state == SPS_BAD_POS) return; // Nothing to do. _additions.MarkDirty(vp); @@ -491,7 +491,7 @@ void ShopPlacementManager::PlaceShop(const Point16 &pos) vx->SetInstance((SmallRideInstance)this->instance); uint8 entrances = si->GetEntranceDirections(si->xpos, si->ypos, si->zpos); vx->SetInstanceData(entrances); - AddRemovePathEdges(si->xpos, si->ypos, si->zpos, PATH_EMPTY, entrances, true, PAS_QUEUE_PATH); + AddRemovePathEdges(XYZPoint16(si->xpos, si->ypos, si->zpos), PATH_EMPTY, entrances, true, PAS_QUEUE_PATH); _additions.MarkDirty(vp); vp->EnsureAdditionsAreVisible(); this->state = SPS_GOOD_POS; diff --git a/src/terraform.cpp b/src/terraform.cpp index 81efe68..ac814e7 100644 --- a/src/terraform.cpp +++ b/src/terraform.cpp @@ -650,10 +650,10 @@ void TileTerraformMouseMode::SetCursors() FinderData fdata(CS_GROUND, single ? FW_CORNER : FW_TILE); if (vp->ComputeCursorPosition(&fdata) != CS_NONE) { if (single) { - vp->tile_cursor.SetCursor(fdata.xvoxel, fdata.yvoxel, fdata.zvoxel, fdata.cursor); + vp->tile_cursor.SetCursor(fdata.voxel_pos, fdata.cursor); vp->area_cursor.SetInvalid(); } else { - Rectangle32 rect(fdata.xvoxel - this->xsize / 2, fdata.yvoxel - this->ysize / 2, this->xsize, this->ysize); + Rectangle32 rect(fdata.voxel_pos.x - this->xsize / 2, fdata.voxel_pos.y - this->ysize / 2, this->xsize, this->ysize); vp->tile_cursor.SetInvalid(); vp->area_cursor.SetCursor(rect, CUR_TYPE_TILE); } @@ -690,7 +690,7 @@ void TileTerraformMouseMode::OnMouseButtonEvent(Viewport *vp, uint8 state) static void ChangeTileCursorMode(Viewport *vp, bool levelling, int direction, bool dot_mode) { Cursor *c = &vp->tile_cursor; - if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(c->xpos, c->ypos) != OWN_PARK) return; + if (_game_mode_mgr.InPlayMode() && _world.GetTileOwner(c->cursor_pos.x, c->cursor_pos.y) != OWN_PARK) return; Point32 p; uint16 w, h; @@ -700,13 +700,13 @@ static void ChangeTileCursorMode(Viewport *vp, bool levelling, int direction, bo w = _world.GetXSize(); h = _world.GetYSize(); } else { // Single tile mode. - p = {c->xpos, c->ypos}; + p = {c->cursor_pos.x, c->cursor_pos.y}; w = 1; h = 1; } TerrainChanges changes(p, w, h); - p = {c->xpos, c->ypos}; + p = {c->cursor_pos.x, c->cursor_pos.y}; bool ok; switch (c->type) { @@ -737,10 +737,10 @@ static void ChangeTileCursorMode(Viewport *vp, bool levelling, int direction, bo * Note that the mouse cursor position is not changed at all, it still points at the original position. * The coupling is restored with the next mouse movement. */ - c->zpos = _world.GetGroundHeight(c->xpos, c->ypos); + c->cursor_pos.z = _world.GetGroundHeight(c->cursor_pos.x, c->cursor_pos.y); for (const auto &iter : changes.changes) { const Point32 &pt = iter.first; - vp->MarkVoxelDirty(pt.x, pt.y, iter.second.height); + vp->MarkVoxelDirty(XYZPoint16(pt.x, pt.y, iter.second.height)); } } } @@ -791,7 +791,7 @@ static void ChangeAreaCursorMode(Viewport *vp, bool levelling, int direction) for (const auto &iter : changes.changes) { const Point32 &pt = iter.first; c->ResetZPosition(pt); - vp->MarkVoxelDirty(pt.x, pt.y, iter.second.height); + vp->MarkVoxelDirty(XYZPoint16(pt.x, pt.y, iter.second.height)); } } diff --git a/src/viewport.cpp b/src/viewport.cpp index 418b901..12610bd 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -187,10 +187,7 @@ public: return ComputeYFunction(x, y, z, this->orient, this->tile_width, this->tile_height); } - int32 xview; ///< X position of the centre point of the display. - int32 yview; ///< Y position of the centre point of the display. - int32 zview; ///< Z position of the centre point of the display. - + XYZPoint32 view_pos; ///< Position of the centre point of the display. uint16 tile_width; ///< Width of a tile. uint16 tile_height; ///< Height of a tile. ViewOrientation orient; ///< Direction of view. @@ -213,15 +210,13 @@ protected: /** * Handle a voxel that should be collected. - * @param vx %Voxel to add, \c nullptr means 'cursor above stack'. - * @param xpos X world position. - * @param ypos Y world position. - * @param zpos Z world position. + * @param vx %Voxel to add, \c nullptr means 'cursor above stack'. + * @param view_pos World position. * @param xnorth X coordinate of the north corner at the display. * @param ynorth y coordinate of the north corner at the display. * @note Implement in a derived class. */ - virtual void CollectVoxel(const Voxel *vx, int xpos, int ypos, int zpos, int32 xnorth, int32 ynorth) = 0; + virtual void CollectVoxel(const Voxel *vx, const XYZPoint16 &view_pos, int32 xnorth, int32 ynorth) = 0; }; /** @@ -274,9 +269,9 @@ public: bool enable_cursors; ///< Enable cursor drawing. protected: - void CollectVoxel(const Voxel *vx, int xpos, int ypos, int zpos, int32 xnorth, int32 ynorth) override; + void CollectVoxel(const Voxel *vx, const XYZPoint16 &voxel_pos, int32 xnorth, int32 ynorth) override; void SetupSupports(const VoxelStack *stack, uint xpos, uint ypos) override; - const ImageData *GetCursorSpriteAtPos(uint16 xpos, uint16 ypos, uint8 zpos, uint8 tslope, uint8 &yoffset); + const ImageData *GetCursorSpriteAtPos(const XYZPoint16 &voxel_pos, uint8 tslope, uint8 &yoffset); /** For each orientation the location of the real northern corner of a tile relative to the northern displayed corner. */ Point16 north_offsets[4]; @@ -301,7 +296,7 @@ public: FinderData *fdata; ///< Finder data to return. protected: - void CollectVoxel(const Voxel *vx, int xpos, int ypos, int zpos, int32 xnorth, int32 ynorth) override; + void CollectVoxel(const Voxel *vx, const XYZPoint16 &voxel_pos, int32 xnorth, int32 ynorth) override; }; /** @@ -313,9 +308,7 @@ protected: VoxelCollector::VoxelCollector(Viewport *vp, bool draw_above_stack) { this->vp = vp; - this->xview = vp->xview; - this->yview = vp->yview; - this->zview = vp->zview; + this->view_pos = vp->view_pos; this->tile_width = vp->tile_width; this->tile_height = vp->tile_height; this->orient = vp->orientation; @@ -331,7 +324,7 @@ VoxelCollector::~VoxelCollector() } /** - * Set screen area of interest (relative to the (#xview, #yview, and #zview position). + * Set screen area of interest (relative to the (#voxel_pos position). * @param xpos Horizontal position of the top-left corner. * @param ypos Vertical position of the top-left corner. * @param width Width of the area. @@ -339,8 +332,8 @@ VoxelCollector::~VoxelCollector() */ void VoxelCollector::SetWindowSize(int16 xpos, int16 ypos, uint16 width, uint16 height) { - this->rect.base.x = this->ComputeX(this->xview, this->yview) + xpos; - this->rect.base.y = this->ComputeY(this->xview, this->yview, this->zview) + ypos; + this->rect.base.x = this->ComputeX(this->view_pos.x, this->view_pos.y) + xpos; + this->rect.base.y = this->ComputeY(this->view_pos.x, this->view_pos.y, this->view_pos.z) + ypos; this->rect.width = width; this->rect.height = height; } @@ -370,7 +363,7 @@ void VoxelCollector::Collect(bool use_additions) if (north_y - this->tile_height >= (int32)(this->rect.base.y + this->rect.height)) continue; // Voxel is below the window. if (north_y + this->tile_width / 2 + this->tile_height <= (int32)this->rect.base.y) break; // Above the window and rising! - this->CollectVoxel(&stack->voxels[count], xpos, ypos, zpos, north_x, north_y); + this->CollectVoxel(&stack->voxels[count], XYZPoint16(xpos, ypos, zpos), north_x, north_y); } /* Possibly cursors should be drawn above this. */ if (this->draw_above_stack) { @@ -380,7 +373,7 @@ void VoxelCollector::Collect(bool use_additions) if (north_y - this->tile_height >= (int32)(this->rect.base.y + this->rect.height)) continue; // Voxel is below the window. if (north_y + this->tile_width / 2 + this->tile_height <= (int32)this->rect.base.y) break; // Above the window and rising! - this->CollectVoxel(nullptr, xpos, ypos, zpos, north_x, north_y); + this->CollectVoxel(nullptr, XYZPoint16(xpos, ypos, zpos), north_x, north_y); } } } @@ -497,52 +490,44 @@ void BaseCursor::SetInvalid() */ Cursor::Cursor(Viewport *vp) : BaseCursor(vp) { - this->xpos = 0; - this->ypos = 0; - this->zpos = 0; + this->cursor_pos = XYZPoint16(0, 0, 0); } void Cursor::MarkDirty() { - if (this->type != CUR_TYPE_INVALID) this->vp->MarkVoxelDirty(this->xpos, this->ypos, this->zpos); + if (this->type != CUR_TYPE_INVALID) this->vp->MarkVoxelDirty(this->cursor_pos); } /** * Get a cursor. - * @param xpos Expected x coordinate of the cursor. - * @param ypos Expected y coordinate of the cursor. - * @param zpos Expected z coordinate of the cursor. + * @param cursor_pos Expected coordinate of the cursor. * @return The cursor sprite if the cursor exists and the coordinates are correct, else \c nullptr. */ -CursorType Cursor::GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) +CursorType Cursor::GetCursor(const XYZPoint16 &cursor_pos) { - if (this->xpos != xpos || this->ypos != ypos || this->zpos != zpos) return CUR_TYPE_INVALID; + if (this->cursor_pos != cursor_pos) return CUR_TYPE_INVALID; return this->type; } uint8 Cursor::GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) { if (this->type == CUR_TYPE_INVALID) return zpos; - if (this->xpos != xpos || this->ypos != ypos || zpos >= this->zpos) return zpos; - return this->zpos; + if (this->cursor_pos.x != xpos || this->cursor_pos.y != ypos || zpos >= this->cursor_pos.z) return zpos; + return this->cursor_pos.z; } /** * Set a cursor. - * @param xpos X position of the voxel containing the cursor. - * @param ypos Y position of the voxel containing the cursor. - * @param zpos Z position of the voxel containing the cursor. + * @param cursor_pos Position of the voxel containing the cursor. * @param type Type of cursor to set. * @param always Always set the cursor (else, only set it if it changed). * @return %Cursor has been set/changed. */ -bool Cursor::SetCursor(uint16 xpos, uint16 ypos, uint8 zpos, CursorType type, bool always) +bool Cursor::SetCursor(const XYZPoint16 &cursor_pos, CursorType type, bool always) { - if (!always && this->xpos == xpos && this->ypos == ypos && this->zpos == zpos && this->type == type) return false; + if (!always && this->cursor_pos == cursor_pos && this->type == type) return false; this->MarkDirty(); - this->xpos = xpos; - this->ypos = ypos; - this->zpos = zpos; + this->cursor_pos = cursor_pos; this->type = type; this->MarkDirty(); return true; @@ -603,19 +588,19 @@ void MultiCursor::MarkDirty() for (uint x = 0; x < this->rect.width; x++) { for (uint y = 0; y < this->rect.height; y++) { - this->vp->MarkVoxelDirty(this->rect.base.x + x, this->rect.base.y + y, - this->GetZpos(this->rect.base.x + x, this->rect.base.y + y)); + this->vp->MarkVoxelDirty(XYZPoint16(this->rect.base.x + x, this->rect.base.y + y, + this->GetZpos(this->rect.base.x + x, this->rect.base.y + y))); } } } -CursorType MultiCursor::GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) +CursorType MultiCursor::GetCursor(const XYZPoint16 &cursor_pos) { if (this->type == CUR_TYPE_INVALID) return CUR_TYPE_INVALID; - Point32 pt(xpos, ypos); + Point32 pt(cursor_pos.x, cursor_pos.y); if (!this->rect.IsPointInside(pt)) return CUR_TYPE_INVALID; - if (zpos != this->GetZpos(xpos, ypos)) return CUR_TYPE_INVALID; + if (cursor_pos.z != this->GetZpos(cursor_pos.x, cursor_pos.y)) return CUR_TYPE_INVALID; return CUR_TYPE_TILE; } @@ -675,54 +660,46 @@ bool MultiCursor::SetCursor(const Rectangle32 &rect, CursorType type, bool alway */ EdgeCursor::EdgeCursor(Viewport *vp) : BaseCursor(vp) { - this->xpos = 0; - this->ypos = 0; - this->zpos = 0; + this->cursor_pos = XYZPoint16(0, 0, 0); } void EdgeCursor::MarkDirty() { - if (this->type != CUR_TYPE_INVALID) this->vp->MarkVoxelDirty(this->xpos, this->ypos, this->zpos); + if (this->type != CUR_TYPE_INVALID) this->vp->MarkVoxelDirty(this->cursor_pos); } /** * Get a cursor. - * @param xpos Expected x coordinate of the cursor. - * @param ypos Expected y coordinate of the cursor. - * @param zpos Expected z coordinate of the cursor. + * @param cursor_pos Expected coordinate of the cursor. * @return The cursor sprite if the cursor exists and the coordinates are correct, else \c nullptr. */ -CursorType EdgeCursor::GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) +CursorType EdgeCursor::GetCursor(const XYZPoint16 &cursor_pos) { - if (this->xpos != xpos || this->ypos != ypos || this->zpos != zpos) return CUR_TYPE_INVALID; + if (this->cursor_pos != cursor_pos) return CUR_TYPE_INVALID; return this->type; } uint8 EdgeCursor::GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) { if (this->type == CUR_TYPE_INVALID) return zpos; - if (this->xpos != xpos || this->ypos != ypos || zpos >= this->zpos) return zpos; - return this->zpos; + if (this->cursor_pos.x != xpos || this->cursor_pos.y != ypos || zpos >= this->cursor_pos.z) return zpos; + return this->cursor_pos.z; } /** * Set a cursor. - * @param xpos X position of the voxel containing the cursor. - * @param ypos Y position of the voxel containing the cursor. - * @param zpos Z position of the voxel containing the cursor. + * @param cursor_pos Position of the voxel containing the cursor. * @param type Type of cursor to set. * @param sprite Sprite to display. * @param yoffset Offset in screen y coordinates for where to render the sprite related to given voxel. * @param always Always set the cursor (else, only set it if it changed). * @return %Cursor has been set/changed. */ -bool EdgeCursor::SetCursor(uint16 xpos, uint16 ypos, uint8 zpos, CursorType type, const ImageData *sprite, uint8 yoffset, bool always) +bool EdgeCursor::SetCursor(const XYZPoint16 &cursor_pos, CursorType type, const ImageData *sprite, uint8 yoffset, bool always) { - if (!always && this->xpos == xpos && this->ypos == ypos && this->zpos == zpos && this->type == type) return false; + if (!always && this->cursor_pos == cursor_pos && this->type == type) return false; this->MarkDirty(); - this->xpos = xpos; - this->ypos = ypos; - this->zpos = zpos; + this->cursor_pos = cursor_pos; this->type = type; this->sprite = sprite; this->yoffset = yoffset; @@ -733,24 +710,22 @@ bool EdgeCursor::SetCursor(uint16 xpos, uint16 ypos, uint8 zpos, CursorType type /** * Get the cursor type at a given position. - * @param xpos X position of the voxel being drawn. - * @param ypos Y position of the voxel being drawn. - * @param zpos Z position of the voxel being drawn. + * @param voxel_pos Position of the voxel being drawn. * @return %Cursor type at the position (\c CUR_TYPE_INVALID means no cursor available). */ -CursorType Viewport::GetCursorAtPos(uint16 xpos, uint16 ypos, uint8 zpos) +CursorType Viewport::GetCursorAtPos(const XYZPoint16 &voxel_pos) { CursorType ct = CUR_TYPE_INVALID; if (this->additions_enabled && !this->additions_displayed) { - ct = this->arrow_cursor.GetCursor(xpos, ypos, zpos); + ct = this->arrow_cursor.GetCursor(voxel_pos); if (ct != CUR_TYPE_INVALID) return ct; } - ct = this->tile_cursor.GetCursor(xpos, ypos, zpos); + ct = this->tile_cursor.GetCursor(voxel_pos); if (ct != CUR_TYPE_INVALID) return ct; - ct = this->area_cursor.GetCursor(xpos, ypos, zpos); + ct = this->area_cursor.GetCursor(voxel_pos); if (ct != CUR_TYPE_INVALID) return ct; - return this->edge_cursor.GetCursor(xpos, ypos, zpos); + return this->edge_cursor.GetCursor(voxel_pos); } /** @@ -774,19 +749,17 @@ uint8 Viewport::GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) /** * Get the cursor sprite at a given voxel. - * @param xpos X position of the voxel being drawn. - * @param ypos Y position of the voxel being drawn. - * @param zpos Z position of the voxel being drawn. + * @param voxel_pos Position of the voxel being drawn. * @param tslope Slope of the tile. * @param yoffset Offset in screen y coordinates for where to render the sprite related to given voxel. * @return Pointer to the cursor sprite, or \c nullptr if no cursor available. */ -const ImageData *SpriteCollector::GetCursorSpriteAtPos(uint16 xpos, uint16 ypos, uint8 zpos, uint8 tslope, uint8 &yoffset) +const ImageData *SpriteCollector::GetCursorSpriteAtPos(const XYZPoint16 &voxel_pos, uint8 tslope, uint8 &yoffset) { yoffset = 0; if (!this->enable_cursors) return nullptr; - CursorType ctype = this->vp->GetCursorAtPos(xpos, ypos, zpos); + CursorType ctype = this->vp->GetCursorAtPos(voxel_pos); switch (ctype) { case CUR_TYPE_NORTH: case CUR_TYPE_EAST: @@ -881,31 +854,29 @@ static int DrawRide(int32 slice, int zpos, int32 basex, int32 basey, ViewOrienta /** * Add all sprites of the voxel to the set of sprites to draw. * @param voxel %Voxel to add, \c nullptr means 'cursor above stack'. - * @param xpos X world position. - * @param ypos Y world position. - * @param zpos Z world position. + * @param voxel_pos World position. * @param xnorth X coordinate of the north corner at the display. * @param ynorth y coordinate of the north corner at the display. * @todo Can we gain time by checking for cursors once at every voxel stack, and only test every \a zpos when there is one in a stack? */ -void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, int32 xnorth, int32 ynorth) +void SpriteCollector::CollectVoxel(const Voxel *voxel, const XYZPoint16 &voxel_pos, int32 xnorth, int32 ynorth) { int32 slice; switch (this->orient) { - case 0: slice = xpos + ypos; break; - case 1: slice = xpos - ypos; break; - case 2: slice = -xpos - ypos; break; - case 3: slice = -xpos + ypos; break; + case 0: slice = voxel_pos.x + voxel_pos.y; break; + case 1: slice = voxel_pos.x - voxel_pos.y; break; + case 2: slice = -voxel_pos.x - voxel_pos.y; break; + case 3: slice = -voxel_pos.x + voxel_pos.y; break; default: NOT_REACHED(); } if (voxel == nullptr) { // Draw cursor above stack. uint8 yoffset = 0; - const ImageData *mspr = this->GetCursorSpriteAtPos(xpos, ypos, zpos, SL_FLAT, yoffset); + const ImageData *mspr = this->GetCursorSpriteAtPos(voxel_pos, SL_FLAT, yoffset); if (mspr != nullptr) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_CURSOR; dd.sprite = mspr; dd.base.x = this->xoffset + xnorth - this->rect.base.x; @@ -922,7 +893,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (sri == SRI_PATH && HasValidPath(instance_data)) { // A path (and not something reserved above it). DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_PATH; platform_shape = _path_rotation[GetImplodedPathSlope(instance_data)][this->orient]; dd.sprite = this->sprites->GetPathSprite(GetPathType(instance_data), GetImplodedPathSlope(instance_data), this->orient); @@ -932,7 +903,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z this->draw_images.insert(dd); } else if (sri >= SRI_FULL_RIDES) { // A normal ride. DrawData dd[4]; - int count = DrawRide(slice, zpos, + int count = DrawRide(slice, voxel_pos.z, this->xoffset + xnorth - this->rect.base.x, this->yoffset + ynorth - this->rect.base.y, this->orient, sri, instance_data, dd, &platform_shape); for (int i = 0; i < count; i++) this->draw_images.insert(dd[i]); @@ -955,7 +926,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (img != nullptr) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_FOUNDATION; dd.sprite = img; dd.base.x = this->xoffset + xnorth - this->rect.base.x; @@ -969,7 +940,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (img != nullptr) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_FOUNDATION; dd.sprite = img; dd.base.x = this->xoffset + xnorth - this->rect.base.x; @@ -985,7 +956,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (voxel->GetGroundType() != GTP_INVALID) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_GROUND; uint8 slope = voxel->GetGroundSlope(); dd.sprite = this->sprites->GetSurfaceSprite(voxel->GetGroundType(), slope, this->orient); @@ -1029,7 +1000,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (fence_type != FENCE_TYPE_INVALID) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = (edge + 4 * this->orient + 1) % 4 < EDGE_SW ? SO_FENCE_BACK : SO_FENCE_FRONT; TileSlope slope = ExpandTileSlope(voxel->GetGroundSlope()); dd.sprite = this->sprites->GetFenceSprite(fence_type, edge, slope, this->orient); @@ -1052,11 +1023,11 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z /* Sprite cursor (arrow) */ uint8 cursor_yoffset = 0; - const ImageData *mspr = this->GetCursorSpriteAtPos(xpos, ypos, zpos, gslope, cursor_yoffset); + const ImageData *mspr = this->GetCursorSpriteAtPos(voxel_pos, gslope, cursor_yoffset); if (mspr != nullptr) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_CURSOR; dd.sprite = mspr; dd.base.x = this->xoffset + xnorth - this->rect.base.x; @@ -1079,7 +1050,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z if (pl_spr != nullptr) { DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_PLATFORM; dd.sprite = pl_spr; dd.base.x = this->xoffset + xnorth - this->rect.base.x; @@ -1094,11 +1065,11 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z uint16 height = this->ground_height; this->ground_height = -1; uint8 slope = this->ground_slope; - while (height < zpos) { - int yoffset = (zpos - height) * this->vp->tile_height; // Compensate y position of support. + while (height < voxel_pos.z) { + int yoffset = (voxel_pos.z - height) * this->vp->tile_height; // Compensate y position of support. uint sprnum; if (slope == SL_FLAT) { - if (height + 1 < zpos) { + if (height + 1 < voxel_pos.z) { sprnum = SSP_FLAT_DOUBLE_NS + (this->orient & 1); height += 2; } else { @@ -1138,7 +1109,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z int x_off = ComputeX(vo->x_pos, vo->y_pos); int y_off = ComputeY(vo->x_pos, vo->y_pos, vo->z_pos); dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_PERSON; dd.sprite = anim_spr; dd.base.x = this->xoffset + this->north_offsets[this->orient].x + xnorth - this->rect.base.x + x_off; @@ -1181,9 +1152,7 @@ PixelFinder::PixelFinder(Viewport *vp, FinderData *fdata) : VoxelCollector(vp, f this->pixel = _palette[0]; // 0 is transparent, and is not used in sprites. this->fdata = fdata; - fdata->xvoxel = 0; - fdata->yvoxel = 0; - fdata->zvoxel = 0; + fdata->voxel_pos = XYZPoint16(0, 0, 0); fdata->person = nullptr; fdata->ride = INVALID_RIDE_INSTANCE; } @@ -1195,20 +1164,18 @@ PixelFinder::~PixelFinder() /** * Find the closest sprite. * @param voxel %Voxel to examine, \c nullptr means 'cursor above stack'. - * @param xpos X world position. - * @param ypos Y world position. - * @param zpos Z world position. + * @param voxel_pos World position. * @param xnorth X coordinate of the north corner at the display. * @param ynorth y coordinate of the north corner at the display. */ -void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, int32 xnorth, int32 ynorth) +void PixelFinder::CollectVoxel(const Voxel *voxel, const XYZPoint16 &voxel_pos, int32 xnorth, int32 ynorth) { int32 slice; switch (this->orient) { - case 0: slice = xpos + ypos; break; - case 1: slice = xpos - ypos; break; - case 2: slice = -xpos - ypos; break; - case 3: slice = -xpos + ypos; break; + case 0: slice = voxel_pos.x + voxel_pos.y; break; + case 1: slice = voxel_pos.x - voxel_pos.y; break; + case 2: slice = -voxel_pos.x - voxel_pos.y; break; + case 3: slice = -voxel_pos.x + voxel_pos.y; break; default: NOT_REACHED(); } /* Looking for surface edge? */ @@ -1216,7 +1183,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, const ImageData *spr = this->sprites->GetSurfaceSprite(GTP_CURSOR_EDGE_TEST, voxel->GetGroundSlope(), this->orient); DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_GROUND_EDGE; dd.sprite = nullptr; dd.base.x = this->rect.base.x - xnorth; @@ -1227,9 +1194,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if (pixel != 0) { this->found = true; this->data = dd; - this->fdata->xvoxel = xpos; - this->fdata->yvoxel = ypos; - this->fdata->zvoxel = zpos; + this->fdata->voxel_pos = voxel_pos; this->pixel = pixel; } } @@ -1241,7 +1206,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if ((this->allowed & CS_RIDE) != 0 && number >= SRI_FULL_RIDES) { /* Looking for a ride? */ DrawData dd[4]; - int count = DrawRide(slice, zpos, this->rect.base.x - xnorth, this->rect.base.y - ynorth, + int count = DrawRide(slice, voxel_pos.z, this->rect.base.x - xnorth, this->rect.base.y - ynorth, this->orient, number, voxel->GetInstanceData(), dd, nullptr); for (int i = 0; i < count; i++) { if (!this->found || this->data < dd[i]) { @@ -1250,9 +1215,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if (GetA(pixel) != TRANSPARENT) { this->found = true; this->data = dd[i]; - this->fdata->xvoxel = xpos; - this->fdata->yvoxel = ypos; - this->fdata->zvoxel = zpos; + this->fdata->voxel_pos = voxel_pos; this->pixel = pixel; this->fdata->ride = number; } @@ -1264,7 +1227,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, const ImageData *img = this->sprites->GetPathSprite(GetPathType(instance_data), GetImplodedPathSlope(instance_data), this->orient); DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_PATH; dd.sprite = nullptr; dd.base.x = this->rect.base.x - xnorth; @@ -1275,9 +1238,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if (GetA(pixel) != TRANSPARENT) { this->found = true; this->data = dd; - this->fdata->xvoxel = xpos; - this->fdata->yvoxel = ypos; - this->fdata->zvoxel = zpos; + this->fdata->voxel_pos = voxel_pos; this->pixel = pixel; } } @@ -1286,7 +1247,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, const ImageData *spr = this->sprites->GetSurfaceSprite(GTP_CURSOR_TEST, voxel->GetGroundSlope(), this->orient); DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_GROUND; dd.sprite = nullptr; dd.base.x = this->rect.base.x - xnorth; @@ -1297,9 +1258,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if (GetA(pixel) != TRANSPARENT) { this->found = true; this->data = dd; - this->fdata->xvoxel = xpos; - this->fdata->yvoxel = ypos; - this->fdata->zvoxel = zpos; + this->fdata->voxel_pos = voxel_pos; this->pixel = pixel; } } @@ -1315,7 +1274,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, int y_off = ComputeY(pers->x_pos, pers->y_pos, pers->z_pos); DrawData dd; dd.level = slice; - dd.z_height = zpos; + dd.z_height = voxel_pos.z; dd.order = SO_PERSON; dd.sprite = nullptr; dd.base.x = this->rect.base.x - xnorth - x_off; @@ -1326,9 +1285,7 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, if (GetA(pixel) != TRANSPARENT) { this->found = true; this->data = dd; - this->fdata->xvoxel = xpos; - this->fdata->yvoxel = ypos; - this->fdata->zvoxel = zpos; + this->fdata->voxel_pos = voxel_pos; this->pixel = pixel; this->fdata->person = pers; } @@ -1340,16 +1297,11 @@ void PixelFinder::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int zpos, /** * %Viewport constructor. - * @param xview X pixel position of the center viewpoint of the main display. - * @param yview Y pixel position of the center viewpoint of the main display. - * @param zview Z pixel position of the center viewpoint of the main display. + * @param view_pos Pixel position of the center viewpoint of the main display. */ -Viewport::Viewport(uint32 xview, uint32 yview, uint32 zview) : Window(WC_MAINDISPLAY, ALL_WINDOWS_OF_TYPE), tile_cursor(this), arrow_cursor(this), area_cursor(this), edge_cursor(this) +Viewport::Viewport(const XYZPoint32 &view_pos) : Window(WC_MAINDISPLAY, ALL_WINDOWS_OF_TYPE), tile_cursor(this), arrow_cursor(this), area_cursor(this), edge_cursor(this) { - this->xview = xview; - this->yview = yview; - this->zview = zview; - + this->view_pos = view_pos; this->tile_width = 64; this->tile_height = 16; this->orientation = VOR_NORTH; @@ -1423,15 +1375,13 @@ void Viewport::OnDraw() /** * Mark a voxel as in need of getting painted. - * @param xpos X position of the voxel. - * @param ypos Y position of the voxel. - * @param zpos Z position of the voxel. + * @param voxel_pos Position of the voxel. * @param height Number of voxels to mark above the specified coordinate (\c 0 means inspect the voxel itself). */ -void Viewport::MarkVoxelDirty(int16 xpos, int16 ypos, int16 zpos, int16 height) +void Viewport::MarkVoxelDirty(const XYZPoint16 &voxel_pos, int16 height) { if (height <= 0) { - const Voxel *v = _world.GetVoxel(xpos, ypos, zpos); + const Voxel *v = _world.GetVoxel(voxel_pos.x, voxel_pos.y, voxel_pos.z); if (v == nullptr) { height = 1; } else { @@ -1461,22 +1411,22 @@ void Viewport::MarkVoxelDirty(int16 xpos, int16 ypos, int16 zpos, int16 height) Rectangle32 rect; const Point16 *pt; - int32 center_x = this->ComputeX(this->xview, this->yview) - this->rect.base.x - this->rect.width / 2; - int32 center_y = this->ComputeY(this->xview, this->yview, this->zview) - this->rect.base.y - this->rect.height / 2; + int32 center_x = this->ComputeX(this->view_pos.x, this->view_pos.y) - this->rect.base.x - this->rect.width / 2; + int32 center_y = this->ComputeY(this->view_pos.x, this->view_pos.y, this->view_pos.z) - this->rect.base.y - this->rect.height / 2; pt = &_corner_dxy[this->orientation]; - rect.base.y = this->ComputeY((xpos + pt->x) * 256, (ypos + pt->y) * 256, (zpos + height) * 256) - center_y; + rect.base.y = this->ComputeY((voxel_pos.x + pt->x) * 256, (voxel_pos.y + pt->y) * 256, (voxel_pos.z + height) * 256) - center_y; pt = &_corner_dxy[RotateCounterClockwise(this->orientation)]; - rect.base.x = this->ComputeX((xpos + pt->x) * 256, (ypos + pt->y) * 256) - center_x; + rect.base.x = this->ComputeX((voxel_pos.x + pt->x) * 256, (voxel_pos.y + pt->y) * 256) - center_x; pt = &_corner_dxy[RotateClockwise(this->orientation)]; - int32 d = this->ComputeX((xpos + pt->x) * 256, (ypos + pt->y) * 256) - center_x; + int32 d = this->ComputeX((voxel_pos.x + pt->x) * 256, (voxel_pos.y + pt->y) * 256) - center_x; assert(d >= rect.base.x); rect.width = d - rect.base.x + 1; pt = &_corner_dxy[RotateClockwise(RotateClockwise(this->orientation))]; - d = this->ComputeY((xpos + pt->x) * 256, (ypos + pt->y) * 256, zpos * 256) - center_y; + d = this->ComputeY((voxel_pos.x + pt->x) * 256, (voxel_pos.y + pt->y) * 256, voxel_pos.z * 256) - center_y; assert(d >= rect.base.y); rect.height = d - rect.base.y + 1; @@ -1552,23 +1502,23 @@ Point32 Viewport::ComputeHorizontalTranslation(int dx, int dy) Point32 new_xy; switch (this->orientation) { case VOR_NORTH: - new_xy.x = this->xview + dx * 256 / this->tile_width - dy * 512 / this->tile_width; - new_xy.y = this->yview - dx * 256 / this->tile_width - dy * 512 / this->tile_width; + new_xy.x = this->view_pos.x + dx * 256 / this->tile_width - dy * 512 / this->tile_width; + new_xy.y = this->view_pos.y - dx * 256 / this->tile_width - dy * 512 / this->tile_width; break; case VOR_EAST: - new_xy.x = this->xview - dx * 256 / this->tile_width - dy * 512 / this->tile_width; - new_xy.y = this->yview - dx * 256 / this->tile_width + dy * 512 / this->tile_width; + new_xy.x = this->view_pos.x - dx * 256 / this->tile_width - dy * 512 / this->tile_width; + new_xy.y = this->view_pos.y - dx * 256 / this->tile_width + dy * 512 / this->tile_width; break; case VOR_SOUTH: - new_xy.x = this->xview - dx * 256 / this->tile_width + dy * 512 / this->tile_width; - new_xy.y = this->yview + dx * 256 / this->tile_width + dy * 512 / this->tile_width; + new_xy.x = this->view_pos.x - dx * 256 / this->tile_width + dy * 512 / this->tile_width; + new_xy.y = this->view_pos.y + dx * 256 / this->tile_width + dy * 512 / this->tile_width; break; case VOR_WEST: - new_xy.x = this->xview + dx * 256 / this->tile_width + dy * 512 / this->tile_width; - new_xy.y = this->yview + dx * 256 / this->tile_width - dy * 512 / this->tile_width; + new_xy.x = this->view_pos.x + dx * 256 / this->tile_width + dy * 512 / this->tile_width; + new_xy.y = this->view_pos.y + dx * 256 / this->tile_width - dy * 512 / this->tile_width; break; default: @@ -1589,9 +1539,9 @@ void Viewport::MoveViewport(int dx, int dy) Point32 new_xy = this->ComputeHorizontalTranslation(dx, dy); int32 new_x = Clamp(new_xy.x, 0, _world.GetXSize() * 256 - 1); int32 new_y = Clamp(new_xy.y, 0, _world.GetYSize() * 256 - 1); - if (new_x != this->xview || new_y != this->yview) { - this->xview = new_x; - this->yview = new_y; + if (new_x != this->view_pos.x || new_y != this->view_pos.y) { + this->view_pos.x = new_x; + this->view_pos.y = new_y; this->MarkDirty(); } } @@ -1708,15 +1658,13 @@ Viewport *GetViewport() /** * Mark a voxel as in need of getting painted. - * @param xpos X position of the voxel. - * @param ypos Y position of the voxel. - * @param zpos Z position of the voxel. + * @param voxel_pos Position of the voxel. * @param height Number of voxels to mark above the specified coordinate (\c 0 means inspect the voxel itself). */ -void MarkVoxelDirty(int16 xpos, int16 ypos, int16 zpos, int16 height) +void MarkVoxelDirty(const XYZPoint16 &voxel_pos, int16 height) { Viewport *vp = GetViewport(); - if (vp != nullptr) vp->MarkVoxelDirty(xpos, ypos, zpos, height); + if (vp != nullptr) vp->MarkVoxelDirty(voxel_pos, height); } /** @@ -1793,14 +1741,12 @@ ViewportMouseMode MouseModes::GetMouseMode() /** * Open the main isometric display window. - * @param xview X pixel position of the center viewpoint of the main display. - * @param yview Y pixel position of the center viewpoint of the main display. - * @param zview Z pixel position of the center viewpoint of the main display. + * @param view_pos Pixel position of the center viewpoint of the main display. * @ingroup viewport_group */ -void ShowMainDisplay(uint32 xview, uint32 yview, uint32 zview) +void ShowMainDisplay(const XYZPoint32 &view_pos) { - new Viewport(xview, yview, zview); + new Viewport(view_pos); _mouse_modes.SetViewportMousemode(); } diff --git a/src/viewport.h b/src/viewport.h index 1778158..4935518 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -113,9 +113,7 @@ public: GroundTilePart select; ///< What part to select of a ground tile. CursorType cursor; ///< Type of cursor suggested. - uint16 xvoxel; ///< X position of the voxel with the closest sprite. - uint16 yvoxel; ///< Y position of the voxel with the closest sprite. - uint8 zvoxel; ///< Z position of the voxel with the closest sprite. + XYZPoint16 voxel_pos; ///< Position of the voxel with the closest sprite. const Person *person; ///< Found person, if any. uint16 ride; ///< Found ride instance, if any. }; @@ -142,7 +140,7 @@ public: * @param zpos Expected z coordinate of the cursor. * @return The cursor sprite if the cursor exists and the coordinates are correct, else \c nullptr. */ - virtual CursorType GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) = 0; + virtual CursorType GetCursor(const XYZPoint16 &cursor_pos) = 0; /** * Get the maximum height of the \a xpos, \a ypos stack that needs to be examined. @@ -164,14 +162,12 @@ class Cursor : public BaseCursor { public: Cursor(Viewport *vp); - uint16 xpos; ///< %Voxel x position of the cursor. - uint16 ypos; ///< %Voxel y position of the cursor. - uint8 zpos; ///< %Voxel z position of the cursor. + XYZPoint16 cursor_pos; ///< %Voxel position of the cursor. - bool SetCursor(uint16 xpos, uint16 ypos, uint8 zpos, CursorType type, bool always = false); + bool SetCursor(const XYZPoint16 &cursor_pos, CursorType type, bool always = false); void MarkDirty() override; - CursorType GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) override; + CursorType GetCursor(const XYZPoint16 &cursor_pos) override; uint8 GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) override; }; @@ -189,7 +185,7 @@ public: bool SetCursor(const Rectangle32 &rect, CursorType type, bool always = false); void MarkDirty() override; - CursorType GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) override; + CursorType GetCursor(const XYZPoint16 &cursor_pos) override; uint8 GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) override; void ClearZPositions(); @@ -205,16 +201,14 @@ class EdgeCursor : public BaseCursor { // XXX todo: later on, check if this will public: EdgeCursor(Viewport *vp); - uint16 xpos; ///< %Voxel x position of the cursor. - uint16 ypos; ///< %Voxel y position of the cursor. - uint8 zpos; ///< %Voxel z position of the cursor. + XYZPoint16 cursor_pos; ///< %Voxel position of the cursor. const ImageData *sprite; ///< Cursor sprite. uint8 yoffset; ///< Y offset for where to render the sprite on the screen. - bool SetCursor(uint16 xpos, uint16 ypos, uint8 zpos, CursorType type, const ImageData *sprite, uint8 yoffset, bool always = false); + bool SetCursor(const XYZPoint16 &cursor_pos, CursorType type, const ImageData *sprite, uint8 yoffset, bool always = false); void MarkDirty() override; - CursorType GetCursor(uint16 xpos, uint16 ypos, uint8 zpos) override; + CursorType GetCursor(const XYZPoint16 &cursor_pos) override; uint8 GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos) override; }; @@ -225,17 +219,17 @@ public: */ class Viewport : public Window { public: - Viewport(uint32 xview, uint32 yview, uint32 zview); + Viewport(const XYZPoint32 &view_pos); ~Viewport(); - void MarkVoxelDirty(int16 xpos, int16 ypos, int16 zpos, int16 height = 0); + void MarkVoxelDirty(const XYZPoint16 &voxel_pos, int16 height = 0); void OnDraw() override; void Rotate(int direction); void MoveViewport(int dx, int dy); ClickableSprite ComputeCursorPosition(FinderData *fdata); - CursorType GetCursorAtPos(uint16 xpos, uint16 ypos, uint8 zpos); + CursorType GetCursorAtPos(const XYZPoint16 &voxel_pos); uint8 GetMaxCursorHeight(uint16 xpos, uint16 ypos, uint8 zpos); void EnableWorldAdditions(); @@ -246,10 +240,7 @@ public: int32 ComputeX(int32 xpos, int32 ypos); int32 ComputeY(int32 xpos, int32 ypos, int32 zpos); - int32 xview; ///< X position of the centre point of the viewport. - int32 yview; ///< Y position of the centre point of the viewport. - int32 zview; ///< Z position of the centre point of the viewport. - + XYZPoint32 view_pos; ///< Position of the centre point of the viewport. uint16 tile_width; ///< Width of a tile. uint16 tile_height; ///< Height of a tile. ViewOrientation orientation; ///< Direction of view. @@ -343,6 +334,6 @@ void EnableWorldAdditions(); void DisableWorldAdditions(); Viewport *GetViewport(); -void MarkVoxelDirty(int16 xpos, int16 ypos, int16 zpos, int16 height = 0); +void MarkVoxelDirty(const XYZPoint16 &voxel_pos, int16 height = 0); #endif diff --git a/src/window.h b/src/window.h index ee3bcc0..17b8667 100644 --- a/src/window.h +++ b/src/window.h @@ -353,7 +353,7 @@ void NotifyChange(WindowTypes wtype, WindowNumber wnumber, ChangeCode code, uint class RideInstance; class CoasterInstance; -void ShowMainDisplay(uint32 xview, uint32 yview, uint32 zview); +void ShowMainDisplay(const XYZPoint32 &view_pos); void ShowToolbar(); void ShowBottomToolbar(); void ShowGuestInfoGui(const Person *person); -- 2.2.1