24 if ((stamp.
size != 1 && stamp.
size != 2) || stamp.
x < 0 || stamp.
y < 0 ||
25 stamp.
x > 64 - stamp.
size || stamp.
y > 64 - stamp.
size ||
27 return absl::InvalidArgumentError(
"Choose a rail stamp inside the room");
30 for (
int y = stamp.
y; y < stamp.
y + stamp.
size; ++y) {
31 for (
int x = stamp.
x; x < stamp.
x + stamp.
size; ++x) {
32 const auto old = before.
tiles[y * 64 + x];
33 if (before.
HasOverride(y * 64 + x) && !IsRail(old)) {
34 return absl::FailedPreconditionError(
35 "Other collision occupies this cell; use the collision inspector");
37 if (stamp.
value != 0 && ((IsStop(old) && !IsStop(stamp.
value)) ||
38 (IsSwitch(old) && !IsSwitch(stamp.
value)))) {
39 return absl::FailedPreconditionError(
40 "Stop or switch protected; choose the matching behavior tool");
42 if (stamp.
value == 0) {
44 after.ClearOverride(y * 64 + x);
46 after.SetOverride(y * 64 + x, stamp.
value);
56 int room_id, uint8_t value,
int size,
60 if (!rt.
hovered || x < 0 || y < 0 || x >= 64 || y >= 64) {
71 const auto delta = ImGui::GetIO().MouseDelta;
72 if (
message_.empty() || delta.x != 0 || delta.y != 0 || !preview.ok()) {
74 ?
"Click to stamp. Click the room canvas, then Escape "
76 : std::string(preview.status().message());
83 const auto color = ImGui::GetColorU32(preview.ok() ? theme.status_warning
84 : theme.status_error);
85 for (
int dy = 0; dy < size; ++dy) {
86 for (
int dx = 0; dx < size; ++dx) {
90 ImVec2((x + dx + 1) * 8, (y + dy + 1) * 8));
91 rt.
draw_list->AddRectFilled(p, q, (color & 0x00FFFFFF) | 0x55000000);
97 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && preview.ok() && apply &&
98 !ImGui::IsMouseDown(ImGuiMouseButton_Middle) &&
99 !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
100 const auto status = apply(room_id, collision, stamp);
102 message_ = std::string(status.message());
104 ImGui::BeginTooltip();
105 ImGui::Text(
"Upper layer: %d x %d cells at %d, %d", size, size, x, y);
106 ImGui::TextUnformatted(
message_.c_str());