Fix iterator issues

This commit is contained in:
Ted John 2022-03-13 13:17:56 +00:00
parent 4eef86dc50
commit b39f7643f0
3 changed files with 68 additions and 12 deletions

View File

@ -1165,15 +1165,26 @@ declare global {
interface TrackIterator {
/**
* The position and direction of the current track segment, from the first element.
* The position and direction of the current track segment. Usually this is the position of the
* element of the segment, however for some segments, it may be offset.
*/
readonly position: CoordsXYZD;
/**
* The current track segment or undefined if at the beginning or end of a disconnected circuit.
* The current track segment.
*/
readonly segment: TrackSegment | undefined;
/**
* Gets the position of where the previous track element should start.
*/
readonly previousPosition: CoordsXYZD | undefined;
/**
* Gets the position of where the next track element should start.
*/
readonly nextPosition: CoordsXYZD | undefined;
/**
* Moves the iterator to the previous track segment.
* @returns true if there is a previous segment, otherwise false.

View File

@ -42,6 +42,8 @@ void ScTrackIterator::Register(duk_context* ctx)
{
dukglue_register_property(ctx, &ScTrackIterator::position_get, nullptr, "position");
dukglue_register_property(ctx, &ScTrackIterator::segment_get, nullptr, "segment");
dukglue_register_property(ctx, &ScTrackIterator::previousPosition_get, nullptr, "previousPosition");
dukglue_register_property(ctx, &ScTrackIterator::nextPosition_get, nullptr, "nextPosition");
dukglue_register_method(ctx, &ScTrackIterator::previous, "previous");
dukglue_register_method(ctx, &ScTrackIterator::next, "next");
}
@ -64,28 +66,69 @@ DukValue ScTrackIterator::segment_get() const
return GetObjectAsDukValue(ctx, std::make_shared<ScTrackSegment>(_type));
}
DukValue ScTrackIterator::previousPosition_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto ctx = scriptEngine.GetContext();
auto& ted = GetTrackElementDescriptor(_type);
auto& seq0 = ted.Block;
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
auto el = map_get_track_element_at_of_type_seq(pos, _type, 0);
if (el == nullptr)
return ToDuk(ctx, undefined);
auto posEl = CoordsXYE(pos.x, pos.y, reinterpret_cast<TileElement*>(el));
track_begin_end tbe{};
track_block_get_previous(posEl, &tbe);
CoordsXYZD result(tbe.end_x, tbe.end_y, tbe.begin_z, tbe.begin_direction);
return ToDuk(ctx, result);
}
DukValue ScTrackIterator::nextPosition_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto ctx = scriptEngine.GetContext();
auto& ted = GetTrackElementDescriptor(_type);
auto& seq0 = ted.Block;
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
auto el = map_get_track_element_at_of_type_seq(pos, _type, 0);
if (el == nullptr)
return ToDuk(ctx, undefined);
auto posEl = CoordsXYE(_position.x, _position.y, reinterpret_cast<TileElement*>(el));
CoordsXYE next;
int32_t z{};
int32_t direction{};
track_block_get_next(&posEl, &next, &z, &direction);
CoordsXYZD result(next.x, next.y, z, direction);
return ToDuk(ctx, result);
}
bool ScTrackIterator::previous()
{
auto& ted = GetTrackElementDescriptor(_type);
auto& seq0 = ted.Block;
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
auto el = map_get_track_element_at(pos);
auto el = map_get_track_element_at_of_type_seq(pos, _type, 0);
if (el == nullptr)
return false;
auto posEl = CoordsXYE(pos.x, pos.y, reinterpret_cast<TileElement*>(el));
track_begin_end tbe{};
auto value = track_block_get_previous(posEl, &tbe);
if (tbe.begin_element != nullptr)
if (track_block_get_previous(posEl, &tbe))
{
auto prev = CoordsXYE(tbe.begin_x, tbe.begin_y, tbe.begin_element);
auto prev = CoordsXYE(tbe.end_x, tbe.end_y, tbe.begin_element);
auto origin = GetTrackSegmentOrigin(prev);
if (origin)
{
_position = *origin;
_type = prev.element->AsTrack()->GetTrackType();
return value;
return true;
}
}
return false;
@ -97,23 +140,22 @@ bool ScTrackIterator::next()
auto& seq0 = ted.Block;
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
auto el = map_get_track_element_at(pos);
auto el = map_get_track_element_at_of_type_seq(pos, _type, 0);
if (el == nullptr)
return false;
auto posEl = CoordsXYE(_position.x, _position.y, reinterpret_cast<TileElement*>(el));
CoordsXYE next;
int32_t z{};
int32_t direction = -1;
auto value = track_block_get_next(&posEl, &next, &z, &direction);
if (next.element != nullptr)
int32_t direction{};
if (track_block_get_next(&posEl, &next, &z, &direction))
{
auto origin = GetTrackSegmentOrigin(next);
if (origin)
{
_position = *origin;
_type = next.element->AsTrack()->GetTrackType();
return value;
return true;
}
}
return false;

View File

@ -35,6 +35,9 @@ namespace OpenRCT2::Scripting
private:
DukValue position_get() const;
DukValue segment_get() const;
DukValue previousPosition_get() const;
DukValue nextPosition_get() const;
bool previous();
bool next();
};