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()));
224 if (show_placement_summary)
261 bool show_placement_summary) {
264 const auto snapshot = viewer !=
nullptr
266 viewer->object_interaction(), viewer->rooms(),
267 viewer->current_room_id())
270 bool drew_primary_status =
false;
276 drew_primary_status =
true;
282 const auto* preview =
283 viewer ? viewer->object_interaction().GetPlacementPreview() :
nullptr;
284 const bool is_placing = preview !=
nullptr;
289 if (is_placing && show_placement_summary) {
290 if (drew_primary_status) {
293 ImGui::TextColored(theme.status_warning,
297 const float cancel_width = ImGui::CalcTextSize(cancel_label).x +
298 ImGui::GetStyle().FramePadding.x * 2.0f;
299 const float next_x = ImGui::GetItemRectMax().x +
300 ImGui::GetStyle().ItemSpacing.x + cancel_width;
301 const float line_right =
302 ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
303 if (next_x <= line_right) {
306 if (ImGui::SmallButton(cancel_label)) {
309 drew_primary_status =
true;
315 const ImVec2 available = ImGui::GetContentRegionAvail();
316 const bool show_secondary_status =
317 available.x >= 420.0f && available.y >= 260.0f;
318 if (!is_placing && show_secondary_status &&
320 ImGui::TextColored(theme.status_success,
323 }
else if (!is_placing && show_secondary_status &&
325 ImGui::TextColored(theme.status_success,
329 }
else if (!is_placing && show_secondary_status &&
333 ImGui::TextColored(theme.status_success,
337 }
else if (!is_placing && show_secondary_status &&
345 if (!show_secondary_status) {
353 size_t object_count = room.GetTileObjects().
size();
354 size_t sprite_count = room.GetSprites().size();
355 size_t door_count = room.GetDoors().size();
357 for (
const auto& obj : room.GetTileObjects()) {
369 auto usage_color = [&](
size_t count,
int max_val,
370 bool exact_capacity_warning) -> ImVec4 {
371 if (exact_capacity_warning) {
373 theme.text_secondary_gray);
375 float ratio =
static_cast<float>(count) /
static_cast<float>(max_val);
377 return theme.status_error;
379 if (ratio >= 0.75f) {
380 return theme.status_warning;
382 return theme.text_secondary_gray;
390 {{
ICON_MD_WIDGETS, absl::StrFormat(
"%zu/%d", object_count, kMaxObjects),
391 usage_color(object_count, kMaxObjects,
true)},
393 absl::StrFormat(
"%zu/%d", sprite_count, kMaxSprites),
394 usage_color(sprite_count, kMaxSprites,
true)},
396 usage_color(door_count, kMaxDoors,
true)},
398 absl::StrFormat(
"%d/%d", chest_count, kMaxChests),
399 usage_color(chest_count, kMaxChests,
false)}});
401 if (!result.errors.empty() || !result.warnings.empty()) {
403 result.errors.empty() ? theme.status_warning : theme.status_error,
404 tr(
"%s %zu issue%s"),
406 result.errors.size() + result.warnings.size(),
407 (result.errors.size() + result.warnings.size()) == 1 ?
"" :
"s");
408 if (ImGui::IsItemHovered()) {
409 ImGui::BeginTooltip();
410 for (
const auto& err : result.errors) {
414 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)