149 if (tile_handler.was_placement_blocked()) {
151 tile_handler.clear_placement_blocked();
155 "Object limit reached (%d max) - placement blocked",
163 std::string(tile_handler.mutation_status().message()));
172 auto& sprite_handler = coordinator.sprite_handler();
173 if (sprite_handler.was_placement_blocked()) {
174 const auto reason = sprite_handler.placement_block_reason();
175 sprite_handler.clear_placement_blocked();
179 "Sprite limit reached (%d max) - placement blocked",
187 std::string(sprite_handler.mutation_status().message()));
196 auto& door_handler = coordinator.door_handler();
197 if (door_handler.was_placement_blocked()) {
198 const auto reason = door_handler.placement_block_reason();
199 door_handler.clear_placement_blocked();
203 "Door limit reached (%d max) - placement blocked", max_doors));
213 std::string(door_handler.mutation_status().message()));
228 : ImGui::GetTextLineHeightWithSpacing() * 8.0f);
262 bool show_placement_summary) {
265 const auto snapshot = viewer !=
nullptr
267 viewer->object_interaction(), viewer->rooms(),
268 viewer->current_room_id())
271 bool drew_primary_status =
false;
277 drew_primary_status =
true;
283 const auto* preview =
284 viewer ? viewer->object_interaction().GetPlacementPreview() :
nullptr;
285 const bool is_placing = preview !=
nullptr;
290 if (is_placing && show_placement_summary) {
291 if (drew_primary_status) {
294 ImGui::TextColored(theme.status_warning,
298 const float cancel_width = ImGui::CalcTextSize(cancel_label).x +
299 ImGui::GetStyle().FramePadding.x * 2.0f;
300 const float next_x = ImGui::GetItemRectMax().x +
301 ImGui::GetStyle().ItemSpacing.x + cancel_width;
302 const float line_right =
303 ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
304 if (next_x <= line_right) {
307 if (ImGui::SmallButton(cancel_label)) {
310 drew_primary_status =
true;
316 const ImVec2 available = ImGui::GetContentRegionAvail();
317 const bool show_secondary_status =
318 available.x >= 420.0f && available.y >= 260.0f;
319 if (!is_placing && show_secondary_status &&
321 ImGui::TextColored(theme.status_success,
324 }
else if (!is_placing && show_secondary_status &&
326 ImGui::TextColored(theme.status_success,
330 }
else if (!is_placing && show_secondary_status &&
334 ImGui::TextColored(theme.status_success,
338 }
else if (!is_placing && show_secondary_status &&
346 if (!show_secondary_status) {
354 size_t object_count = room.GetTileObjects().
size();
355 size_t sprite_count = room.GetSprites().size();
356 size_t door_count = room.GetDoors().size();
358 for (
const auto& obj : room.GetTileObjects()) {
370 auto usage_color = [&](
size_t count,
int max_val,
371 bool exact_capacity_warning) -> ImVec4 {
372 if (exact_capacity_warning) {
374 theme.text_secondary_gray);
376 float ratio =
static_cast<float>(count) /
static_cast<float>(max_val);
378 return theme.status_error;
380 if (ratio >= 0.75f) {
381 return theme.status_warning;
383 return theme.text_secondary_gray;
391 {{
ICON_MD_WIDGETS, absl::StrFormat(
"%zu/%d", object_count, kMaxObjects),
392 usage_color(object_count, kMaxObjects,
true)},
394 absl::StrFormat(
"%zu/%d", sprite_count, kMaxSprites),
395 usage_color(sprite_count, kMaxSprites,
true)},
397 usage_color(door_count, kMaxDoors,
true)},
399 absl::StrFormat(
"%d/%d", chest_count, kMaxChests),
400 usage_color(chest_count, kMaxChests,
false)}});
402 if (!result.errors.empty() || !result.warnings.empty()) {
404 result.errors.empty() ? theme.status_warning : theme.status_error,
405 tr(
"%s %zu issue%s"),
407 result.errors.size() + result.warnings.size(),
408 (result.errors.size() + result.warnings.size()) == 1 ?
"" :
"s");
409 if (ImGui::IsItemHovered()) {
410 ImGui::BeginTooltip();
411 for (
const auto& err : result.errors) {
415 for (
const auto& warn : result.warnings) {
void DrawObjectSelector(float minimum_grid_height=1.0f)
void SetPlacementError(const std::string &message)
static constexpr double kPlacementErrorDuration
std::function< DungeonCanvasViewer *()> canvas_viewer_provider_
std::shared_ptr< zelda3::DungeonObjectEditor > object_editor_
void DrawContent(bool show_placement_summary)
std::function< void()> open_object_editor_callback_
ObjectSelectorContent(Rom *rom, DungeonCanvasViewer *canvas_viewer, std::shared_ptr< zelda3::DungeonObjectEditor > object_editor=nullptr, ToastManager *toast_manager=nullptr)
void DrawInteractionSummary(bool show_placement_summary)
void Draw(bool *p_open) override
Draw the panel content.
void DrawInlineInspectButton(const std::function< void()> &callback)
void DrawUsageChips(std::initializer_list< UsageChip > chips)