31 std::vector<RoomObject>& objects,
const std::vector<size_t>& indices,
33 if (target_value < 0 || target_value > 2) {
34 return absl::InvalidArgumentError(
"Invalid object stream target");
41 std::vector<bool> selected(objects.size(),
false);
42 for (
size_t index : indices) {
43 if (index < objects.size()) {
44 selected[index] =
true;
48 bool room_stream_changed =
false;
49 for (
size_t index = 0; index < objects.size(); ++index) {
52 return absl::InvalidArgumentError(
53 "Torches and pushable blocks only support upper/lower draw-layer "
54 "selector values 0/1");
56 if (selected[index] && objects[index].GetLayerValue() != target_value) {
71 std::vector<RoomObject> reordered = objects;
72 for (
size_t index = 0; index < objects.size(); ++index) {
79 std::vector<size_t> stream_slots;
80 std::array<std::vector<Entry>, 3> stream_buckets;
81 std::vector<Entry> moved_to_target;
83 if (room_stream_changed) {
84 for (
size_t index = 0; index < objects.size(); ++index) {
90 stream_slots.push_back(index);
91 if (selected[index] &&
object.GetLayerValue() != target_value) {
93 moved_to_target.push_back(Entry{std::move(
object), index});
98 std::clamp(
static_cast<int>(
object.GetLayerValue()), 0, 2);
99 stream_buckets[stream].push_back(Entry{std::move(
object), index});
102 for (
auto& entry : moved_to_target) {
103 stream_buckets[target_value].push_back(std::move(entry));
106 size_t stream_slot_index = 0;
107 for (
auto& bucket : stream_buckets) {
108 for (
auto& entry : bucket) {
109 const size_t new_index = stream_slots[stream_slot_index++];
111 reordered[new_index] = std::move(entry.object);
116 for (
size_t old_index = 0; old_index < selected.size(); ++old_index) {
117 if (selected[old_index]) {
123 objects = std::move(reordered);