khora_editor/widgets/inspector/display.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8
9//! Display heuristics — icon, type tag, category labels for the Inspector.
10//!
11//! Pure functions over `InspectedEntity` / domain tag — no state. Component
12//! authors that want a different icon / tag for their type can extend the
13//! match arms here (or, in a later iteration, register through the
14//! `inventory` registry that already carries per-component metadata).
15
16use khora_sdk::editor_ui::{Icon, InspectedEntity};
17
18/// Picks an Inspector header icon based on the most "interesting"
19/// component on the entity. The fallback is a cube (mesh-like).
20pub fn pick_icon(i: &InspectedEntity) -> Icon {
21 let names: std::collections::HashSet<&str> = i
22 .components_json
23 .iter()
24 .map(|c| c.type_name.as_str())
25 .collect();
26 if names.contains("Camera") {
27 Icon::Camera
28 } else if names.contains("Light") {
29 Icon::Light
30 } else if names.contains("AudioSource") || names.contains("AudioListener") {
31 Icon::Music
32 } else {
33 Icon::Cube
34 }
35}
36
37/// Picks a short type tag for the Inspector meta row.
38pub fn pick_type_tag(i: &InspectedEntity) -> &'static str {
39 let names: std::collections::HashSet<&str> = i
40 .components_json
41 .iter()
42 .map(|c| c.type_name.as_str())
43 .collect();
44 if names.contains("Camera") {
45 "Camera"
46 } else if names.contains("Light") {
47 "Light"
48 } else if names.contains("AudioSource") || names.contains("AudioListener") {
49 "Audio"
50 } else {
51 "Mesh"
52 }
53}
54
55/// Per-domain card icon. Domain tags come from the macro-generated
56/// `ComponentRegistration::domain` field.
57pub fn icon_for_domain_tag(tag: Option<u8>) -> Icon {
58 match tag {
59 Some(0) => Icon::Axes, // Spatial
60 Some(1) => Icon::Image, // Render
61 Some(2) => Icon::Music, // Audio
62 Some(3) => Icon::Zap, // Physics
63 Some(4) => Icon::Layers, // UI
64 _ => Icon::More,
65 }
66}
67
68/// Add-Component menu sub-header label per domain tag.
69pub fn category_label_for_tag(tag: Option<u8>) -> &'static str {
70 match tag {
71 Some(0) => "Spatial",
72 Some(1) => "Render",
73 Some(2) => "Audio",
74 Some(3) => "Physics",
75 Some(4) => "UI",
76 _ => "Other",
77 }
78}