khora_data/ecs/components/
handle.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// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Defines a generic component for attaching asset handles to entities.
16
17use khora_core::asset::{Asset, AssetHandle, AssetUUID};
18use std::ops::Deref;
19
20use crate::ecs::Component;
21
22/// A generic ECS component that associates an entity with a shared asset resource.
23/// It holds both a handle to the loaded data and the asset's unique identifier.
24pub struct HandleComponent<T: Asset> {
25    /// A shared, reference-counted pointer to the asset's data.
26    pub handle: AssetHandle<T>,
27    /// The unique, persistent identifier of the asset.
28    pub uuid: AssetUUID,
29}
30
31/// Implement the `Component` trait to make `HandleComponent` usable by the ECS.
32impl<T: Asset> Component for HandleComponent<T> {}
33
34/// Manual implementation of `Clone`.
35/// This is cheap as it only clones the reference-counted pointer and the UUID.
36/// It correctly does NOT require `T` to be `Clone`.
37impl<T: Asset> Clone for HandleComponent<T> {
38    fn clone(&self) -> Self {
39        Self {
40            handle: self.handle.clone(),
41            uuid: self.uuid, // AssetUUID is Copy
42        }
43    }
44}
45
46/// Implement `Deref` to the inner `AssetHandle` for ergonomic access to the asset data.
47/// This allows calling methods of `T` directly on the component (e.g., `my_mesh_component.vertex_size()`).
48impl<T: Asset> Deref for HandleComponent<T> {
49    type Target = T;
50
51    fn deref(&self) -> &Self::Target {
52        &self.handle
53    }
54}