Antkeeper  0.0.1
metamorphosis-system.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
30 #include <engine/debug/log.hpp>
31 #include <execution>
32 
35 {}
36 
37 void metamorphosis_system::update(float t, float dt)
38 {
39  // Scale timestep
40  const auto scaled_timestep = dt * m_time_scale;
41 
42  // Incubate eggs
43  auto egg_group = registry.group<egg_component>(entt::get<ant_genome_component>);
44  std::for_each
45  (
46  std::execution::seq,
47  egg_group.begin(),
48  egg_group.end(),
49  [&](auto entity_id)
50  {
51  auto& egg = egg_group.get<egg_component>(entity_id);
52  if (egg.incubation_phase >= 1.0f)
53  {
54  return;
55  }
56 
57  // Advance incubation phase
58  egg.incubation_phase += scaled_timestep / egg.incubation_period;
59 
60  // If incubation complete
61  if (egg.incubation_phase >= 1.0f)
62  {
63  const auto& genome = *egg_group.get<ant_genome_component>(entity_id).genome;
64  const auto layer_mask = registry.get<scene_component>(entity_id).layer_mask;
65  auto& rigid_body = *registry.get<rigid_body_component>(entity_id).body;
66 
67  // Calculate scales of first and final instars
68  const auto egg_scale = rigid_body.get_scale().x();
69  const auto first_instar_scale = egg_scale * genome.larva->phenes.front().first_instar_scale;
70  const auto final_instar_scale = egg_scale;
71 
72  // Calculate larval growth rate
73  const auto growth_rate = (final_instar_scale - first_instar_scale) / genome.larva->phenes.front().development_period;
74 
75  // Erase egg component
76  registry.erase<egg_component>(entity_id);
77 
78  // Replace egg model with larva model
79  registry.erase<scene_component>(entity_id);
80  registry.emplace<scene_component>(entity_id, std::make_shared<scene::skeletal_mesh>(genome.larva->phenes.front().model), layer_mask);
81 
82  // Init larva scale
83  rigid_body.set_scale(first_instar_scale);
84  rigid_body.set_previous_scale(first_instar_scale);
85 
86  // Define larval development period
87  larva_component larva;
88  larva.development_period = genome.larva->phenes.front().development_period;
89  larva.spinning_period = genome.larva->phenes.front().spinning_period;
90  registry.emplace<larva_component>(entity_id, std::move(larva));
91 
92  // Begin isometric growth
93  registry.emplace<isometric_growth_component>(entity_id, growth_rate);
94  }
95  }
96  );
97 
98  // Develop larvae
99  auto larva_group = registry.group<larva_component>(entt::get<ant_genome_component>);
100  std::for_each
101  (
102  std::execution::seq,
103  larva_group.begin(),
104  larva_group.end(),
105  [&](auto entity_id)
106  {
107  auto& larva = larva_group.get<larva_component>(entity_id);
108 
109  if (larva.development_phase < 1.0f)
110  {
111  // Advance larval development phase
112  larva.development_phase += scaled_timestep / larva.development_period;
113 
114  // If larval development complete
115  if (larva.development_phase >= 1.0f)
116  {
117  const auto& rigid_body = *registry.get<rigid_body_component>(entity_id).body;
118  const auto& genome = *larva_group.get<ant_genome_component>(entity_id).genome;
119  const auto layer_mask = registry.get<scene_component>(entity_id).layer_mask;
120 
121  // Halt isometric growth
122  registry.remove<isometric_growth_component>(entity_id);
123 
124  // Construct cocoon mesh
125  auto cocoon_mesh = std::make_shared<scene::static_mesh>(genome.pupa->phenes.front().cocoon_model);
126  cocoon_mesh->set_transform(rigid_body.get_transform());
127 
128  // Construct copy of cocoon material
129  auto cocoon_material = std::make_shared<render::material>(*cocoon_mesh->get_model()->get_groups().front().material);
130 
131  // Store cocoon material spinning phase variable
132  larva.spinning_phase_matvar = std::static_pointer_cast<render::matvar_float>(cocoon_material->get_variable("spinning_phase"));
133  larva.spinning_phase_matvar->set(0.0f);
134 
135  // Replace cocoon mesh material
136  cocoon_mesh->set_material(0, std::move(cocoon_material));
137 
138  // Construct cocoon entity
139  larva.cocoon_eid = registry.create();
140  registry.emplace<scene_component>(larva.cocoon_eid, std::move(cocoon_mesh), layer_mask);
141  }
142  }
143  else if (larva.spinning_phase < 1.0f)
144  {
145  const auto& genome = *larva_group.get<ant_genome_component>(entity_id).genome;
146 
147  // Advance cocoon-spinning phase
148  larva.spinning_phase += scaled_timestep / larva.spinning_period;
149 
150  // Update spinning phase material variable
151  larva.spinning_phase_matvar->set(larva.spinning_phase);
152 
153  // If cocoon-spinning complete
154  if (larva.spinning_phase >= 1.0f)
155  {
156  // Erase larva component
157  registry.erase<larva_component>(entity_id);
158 
159  // Erase scene component
160  registry.erase<scene_component>(entity_id);
161 
162  // Define pupal development period
163  pupa_component pupa;
164  pupa.development_period = genome.pupa->phenes.front().development_period;
165  registry.emplace<pupa_component>(entity_id, std::move(pupa));
166  }
167  }
168  }
169  );
170 
171  // Develop pupae
172  auto pupa_group = registry.group<pupa_component>(entt::get<ant_genome_component>);
173  std::for_each
174  (
175  std::execution::seq,
176  pupa_group.begin(),
177  pupa_group.end(),
178  [&](auto entity_id)
179  {
180  auto& pupa = pupa_group.get<pupa_component>(entity_id);
181  if (pupa.development_phase >= 1.0f)
182  {
183  return;
184  }
185 
186  // Advance pupal development phase
187  pupa.development_phase += scaled_timestep / pupa.development_period;
188 
189  // If pupal development complete
190  if (pupa.development_phase >= 1.0f)
191  {
192  const auto& genome = *pupa_group.get<ant_genome_component>(entity_id).genome;
193 
194  // Erase pupa component
195  registry.erase<pupa_component>(entity_id);
196 
197  // Construct adult model
198  // registry.emplace<scene_component>(entity_id, std::make_shared<scene::skeletal_mesh>(ant_model), layer_mask);
199  }
200  }
201  );
202 }
metamorphosis_system(entity::registry &registry)
virtual void update(float t, float dt)
Perform's a system's update() function.
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
entt::registry registry
Component registry type.
Definition: registry.hpp:28
Egg incubation parameters.
Larval development parameters.
Pupal development parameters.