133 if (tile_handler.was_placement_blocked()) {
135 tile_handler.clear_placement_blocked();
139 "Object limit reached (%d max) - placement blocked",
152 auto& sprite_handler = coordinator.sprite_handler();
153 if (sprite_handler.was_placement_blocked()) {
154 const auto reason = sprite_handler.placement_block_reason();
155 sprite_handler.clear_placement_blocked();
159 "Sprite limit reached (%d max) - placement blocked",
172 auto& door_handler = coordinator.door_handler();
173 if (door_handler.was_placement_blocked()) {
174 const auto reason = door_handler.placement_block_reason();
175 door_handler.clear_placement_blocked();
179 "Door limit reached (%d max) - placement blocked", max_doors));
195 float available_height = ImGui::GetContentRegionAvail().y;
196 float browser_height = std::max(240.0f, available_height);
200 ImGui::BeginChild(
"ObjectBrowserRegion", ImVec2(0, browser_height),
false);
238 const auto snapshot = viewer !=
nullptr
240 viewer->object_interaction(), viewer->rooms(),
241 viewer->current_room_id())
244 ImGui::AlignTextToFramePadding();
267 ImGui::TextColored(theme.status_warning,
272 const float cancel_width = ImGui::CalcTextSize(cancel_label).x +
273 ImGui::GetStyle().FramePadding.x * 2.0f;
274 const float next_x = ImGui::GetItemRectMax().x +
275 ImGui::GetStyle().ItemSpacing.x + cancel_width;
276 const float line_right =
277 ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
278 if (next_x <= line_right) {
281 if (ImGui::SmallButton(cancel_label)) {
285 ImGui::TextColored(theme.status_success,
289 ImGui::TextColored(theme.status_success,
296 ImGui::TextColored(theme.status_success,
308 " Browse, filter, and click an object below to queue placement.");
315 size_t object_count = room.GetTileObjects().
size();
316 size_t sprite_count = room.GetSprites().size();
317 size_t door_count = room.GetDoors().size();
319 for (
const auto& obj : room.GetTileObjects()) {
320 if (obj.id_ >= 0xF9 && obj.id_ <= 0xFD) {
330 auto usage_color = [&](
size_t count,
int max_val,
331 bool exact_capacity_warning) -> ImVec4 {
332 if (exact_capacity_warning) {
334 theme.text_secondary_gray);
336 float ratio =
static_cast<float>(count) /
static_cast<float>(max_val);
338 return theme.status_error;
340 if (ratio >= 0.75f) {
341 return theme.status_warning;
343 return theme.text_secondary_gray;
351 {{
ICON_MD_WIDGETS, absl::StrFormat(
"%zu/%d", object_count, kMaxObjects),
352 usage_color(object_count, kMaxObjects,
true)},
354 absl::StrFormat(
"%zu/%d", sprite_count, kMaxSprites),
355 usage_color(sprite_count, kMaxSprites,
true)},
357 usage_color(door_count, kMaxDoors,
true)},
359 absl::StrFormat(
"%d/%d", chest_count, kMaxChests),
360 usage_color(chest_count, kMaxChests,
false)}});
362 if (!result.errors.empty() || !result.warnings.empty()) {
364 result.errors.empty() ? theme.status_warning : theme.status_error,
365 tr(
"%s %zu issue%s"),
367 result.errors.size() + result.warnings.size(),
368 (result.errors.size() + result.warnings.size()) == 1 ?
"" :
"s");
369 if (ImGui::IsItemHovered()) {
370 ImGui::BeginTooltip();
371 for (
const auto& err : result.errors) {
375 for (
const auto& warn : result.warnings) {
384 ImGui::TextColored(theme.text_secondary_gray,
void SetPlacementError(const std::string &message)
static constexpr double kPlacementErrorDuration
std::function< DungeonCanvasViewer *()> canvas_viewer_provider_
zelda3::RoomObject preview_object_
DungeonCanvasViewer * ResolveCanvasViewer()
std::shared_ptr< zelda3::DungeonObjectEditor > object_editor_
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)
DungeonCanvasViewer * canvas_viewer_
DungeonObjectSelector object_selector_
void Draw(bool *p_open) override
Draw the panel content.
void SetAgentOptimizedLayout(bool enabled)
void DrawInlineInspectButton(const std::function< void()> &callback)
void DrawUsageChips(std::initializer_list< UsageChip > chips)