Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Certainly! You can implement the `From<&Scene>` trait for your `ECS` struct by recursively processing each node in your `Scene`. Here's how you can do it:
- ```rust
- impl From<&Scene> for ECS {
- fn from(value: &Scene) -> Self {
- let mut new_ecs = ECS::new();
- let mut node_id_counter = 0; // Start entity IDs from 0
- new_ecs.scene_name = value.name.clone();
- new_ecs.scene_resource_path = value.resource_path.clone();
- new_ecs.scene_id = value.id.clone();
- // Process the root node and its children recursively
- let root_entity = new_ecs.process_game_node(&value.root_node, &mut node_id_counter, None);
- new_ecs.scene_root = root_entity;
- new_ecs
- }
- }
- ```
- Now, let's implement the `process_game_node` function. This function will:
- - Assign a unique `Entity` ID to each node.
- - Update the relevant fields in the `ECS` struct.
- - Recursively process the children of each node.
- Here's the implementation:
- ```rust
- impl ECS {
- // ... existing methods ...
- fn process_game_node(
- &mut self,
- node: &GameNodeKind,
- node_id_counter: &mut usize,
- parent_entity: Option<Entity>,
- ) -> Entity {
- // Assign a new Entity ID
- let entity = Entity(*node_id_counter);
- *node_id_counter += 1;
- // Map GameNodeKind to GameNodeKindClean for storage
- let kind_clean = match node {
- GameNodeKind::Instance(_) => GameNodeKindClean::Instance,
- GameNodeKind::Node2D(_) => GameNodeKindClean::Node2D,
- };
- self.game_node_kind.insert(entity, kind_clean);
- // Process the node based on its kind
- match node {
- GameNodeKind::Instance(game_node) => {
- // Update general node information
- self.game_node_id.insert(entity, game_node.id);
- self.game_node_name.insert(entity, game_node.name.clone());
- if let Some(script) = &game_node.script {
- self.game_node_script.insert(entity, script.clone());
- }
- // Process children recursively
- let mut child_entities = Vec::new();
- for child in &game_node.children {
- let child_entity = self.process_game_node(child, node_id_counter, Some(entity));
- child_entities.push(child_entity);
- }
- self.game_node_children.insert(entity, child_entities);
- }
- GameNodeKind::Node2D(game_node) => {
- // Update general node information
- self.game_node_id.insert(entity, game_node.id);
- self.game_node_name.insert(entity, game_node.name.clone());
- if let Some(script) = &game_node.script {
- self.game_node_script.insert(entity, script.clone());
- }
- // Update transform information
- self.transforms.insert(entity, game_node.data.transform.clone());
- // Map Node2DKind to Node2DKindClean and process specific data
- match &game_node.data.kind {
- Node2DKind::Node2D(_) => {
- self.node_2d_kind.insert(entity, Node2DKindClean::Node2D);
- }
- Node2DKind::RigidBody(rigid_body) => {
- self.node_2d_kind.insert(entity, Node2DKindClean::RigidBody);
- self.rigid_body_velocity.insert(entity, rigid_body.velocity);
- self.rigid_body_type.insert(entity, rigid_body.body.clone());
- }
- Node2DKind::Collider(collider) => {
- self.node_2d_kind.insert(entity, Node2DKindClean::Collider);
- self.collider.insert(entity, collider.clone());
- }
- Node2DKind::Render(render) => {
- self.node_2d_kind.insert(entity, Node2DKindClean::Render);
- self.render_offset.insert(entity, render.offset);
- self.render_layer.insert(entity, render.layer.clone());
- // Map RenderKind to RenderKindClean and update GID
- let render_kind_clean = match &render.kind {
- RenderKind::AnimatedSprite(gid) => {
- self.render_gid.insert(entity, gid.clone());
- RenderKindClean::AnimatedSprite
- }
- RenderKind::Sprite(gid) => {
- self.render_gid.insert(entity, gid.clone());
- RenderKindClean::Sprite
- }
- };
- self.render_kind.insert(entity, render_kind_clean);
- }
- }
- // Process children recursively
- let mut child_entities = Vec::new();
- for child in &game_node.children {
- let child_entity = self.process_game_node(child, node_id_counter, Some(entity));
- child_entities.push(child_entity);
- }
- self.game_node_children.insert(entity, child_entities);
- }
- }
- // If there's a parent entity, you can handle parent-specific logic here if needed
- entity
- }
- }
- ```
- **Explanation:**
- - **Entity Assignment:** We use `node_id_counter` to assign a unique `Entity` ID to each node.
- - **Kind Mapping:** We map `GameNodeKind` and `Node2DKind` to their corresponding `Clean` enums for storage in the `ECS` HashMaps.
- - **Data Insertion:** We insert the node's ID, name, script, and kind into the respective HashMaps.
- - **Transform and Specific Data:** For `Node2D` nodes, we insert transform data and handle specific kinds like `RigidBody`, `Collider`, and `Render`.
- - **Children Processing:** We recursively process each child node and collect their `Entity` IDs to build the `game_node_children` mapping.
- - **Parent-Child Relationships:** We store the children of each node in the `game_node_children` HashMap. If you need to track parents, you can add a similar mapping.
- **Notes:**
- - Ensure that all fields in your `ECS` struct are correctly updated based on the data in your `Scene`.
- - The `entity_id` field in `GameNode<T>` seems optional and might be used elsewhere. Since we're assigning new `Entity` IDs during the conversion, you might not need to use it directly in this context.
- - This implementation assumes that the `ECS` struct's HashMaps are meant to store components associated with each `Entity`.
- **Testing:**
- You can test this implementation by creating a `Scene` with various nodes and ensuring that the resulting `ECS` struct contains all the expected data.
- **Example Usage:**
- ```rust
- fn main() {
- let scene = Scene {
- id: "ExampleScene".to_string(),
- name: "Example Scene".to_string(),
- resource_path: ResourcePath("path/to/resource".to_string()),
- root_node: GameNodeKind::Node2D(GameNode {
- id: GameNodeId(Entity(0)),
- name: "RootNode".to_string(),
- entity_id: None,
- data: Node2D {
- transform: Transform {
- position: (0.0, 0.0),
- scale: (1.0, 1.0),
- velocity: (0.0, 0.0),
- rotation: 0.0,
- },
- kind: Node2DKind::Render(Render {
- offset: (0.0, 0.0),
- layer: LayerKind::Background,
- kind: RenderKind::Sprite(Gid(1)),
- }),
- },
- script: Some("root_script".to_string()),
- children: vec![],
- }),
- };
- let ecs: ECS = (&scene).into();
- // Now, ecs contains all the data from the scene
- }
- ```
- This approach should help you convert your `Scene` into the `ECS` format effectively.
Advertisement
Add Comment
Please, Sign In to add comment