use concinnity_cook::authoring::registry::RegisteredType;
use concinnity_core::ecs::World;
use crate::editor::filter;
use crate::editor::hook::{EditorHook, scroll_step};
use crate::editor::panels::content_panel::{self, ContentAction};
use crate::editor::thumbs;
use crate::editor::widget;
pub(in crate::editor::hook) const VISUAL_TYPES: [RegisteredType; 7] = [
RegisteredType::EnvironmentMap,
RegisteredType::Material,
RegisteredType::Mesh,
RegisteredType::Model,
RegisteredType::Prefab,
RegisteredType::ProceduralMesh,
RegisteredType::Texture,
];
impl EditorHook {
pub(in crate::editor::hook) fn content_type_caption(&self) -> &'static str {
match self.content_type {
0 => "All",
i => VISUAL_TYPES[(i - 1).min(VISUAL_TYPES.len() - 1)].as_str(),
}
}
pub(in crate::editor::hook) fn cycle_content_type(&mut self) {
self.content_type = (self.content_type + 1) % (VISUAL_TYPES.len() + 1);
self.content_scroll = 0;
}
pub(super) fn content_items(&self, world: &World) -> Vec<(String, RegisteredType)> {
let mut items: Vec<(String, RegisteredType)> = self
.tree_groups
.iter()
.flat_map(|g| g.assets.iter())
.filter(|a| VISUAL_TYPES.contains(&a.asset_type))
.filter(|a| match self.content_type {
0 => true,
i => a.asset_type == VISUAL_TYPES[i - 1],
})
.map(|a| (a.name.clone(), a.asset_type))
.collect();
items.sort_by(|a, b| (&a.0, a.1.as_str()).cmp(&(&b.0, b.1.as_str())));
items.dedup();
let query = widget::field_text(world, content_panel::SEARCH_INPUT);
if query.trim().is_empty() {
return items;
}
filter::ranked(items.iter().map(|(n, t)| (n.as_str(), t.as_str())), &query)
.into_iter()
.map(|i| items[i].clone())
.collect()
}
pub(in crate::editor::hook) fn content_cells(
&self,
world: &World,
) -> (Vec<content_panel::CellView>, usize) {
let items = self.content_items(world);
let thumbs = thumbs::injected();
let selected = self.selected_names();
let first = self.content_scroll * content_panel::COLS;
let cells = items
.iter()
.skip(first)
.take(content_panel::CELLS)
.map(|(name, ty)| content_panel::CellView {
thumb: thumbs.get(name),
selected: selected.contains(name),
name: name.clone(),
asset_type: *ty,
})
.collect();
(cells, items.len())
}
pub(in crate::editor::hook) fn scroll_content(&mut self, delta: f32, world: &World) {
let total = self.content_items(world).len();
let rows = total.div_ceil(content_panel::COLS);
let max = rows.saturating_sub(content_panel::GRID_ROWS);
self.content_scroll = scroll_step(self.content_scroll, delta, max);
}
pub(in crate::editor::hook) fn apply_content_action(
&mut self,
action: ContentAction,
world: &mut World,
at: [f32; 2],
) {
match action {
ContentAction::FocusSearch => {
self.content_search_focus = true;
let text = widget::field_text(world, content_panel::SEARCH_INPUT);
widget::focus_field_with(world, content_panel::SEARCH_INPUT, &text);
}
ContentAction::CycleType => {
self.content_search_focus = false;
self.cycle_content_type();
}
ContentAction::SelectCell(slot) => {
self.content_search_focus = false;
let items = self.content_items(world);
let index = self.content_scroll * content_panel::COLS + slot;
if let Some((name, ty)) = items.get(index) {
if self.shift_held {
self.toggle_named(name);
} else {
self.select_named(name);
self.arm_content_drag(name.clone(), *ty, at);
}
}
}
ContentAction::Consume => self.content_search_focus = false,
}
}
}