Creating Custom Components
You can extend the initial set of components that can be added to entities by adding custom ones. As an example let us consider adding a water drop component for the Be-200 aircraft available in the IG Template.
Workflow#
Follow the instructions given below to create you own custom component.
- Create a new project using the IG Template and Component System as described here.NoticeWhen creating a project, don't forget to check the Component System option.
- Add the following initialization code for the Component System to the AppSystemLogic::init() method in the AppSystemLogic.cpp file:
Source code (C++)
virtual int AppSystemLogic::init() { // initialize ComponentSystem and register all components ComponentSystem::get()->initialize(); /*...*/ return 1; }
- Create (or add) the following files describing your new component to the C++ project:
-
WaterDropAircraftController.h
Source code (C++)#ifndef _WATER_DROP_AIRCRAFT_CONTROLLER_INCLUDED_ #define _WATER_DROP_AIRCRAFT_CONTROLLER_INCLUDED_ #include <UnigineGame.h> #include "ComponentSystem/ComponentSystem.h" class WaterDropAircraftController final : public ComponentBase { public: COMPONENT(WaterDropAircraftController, ComponentBase); COMPONENT_INIT(init); COMPONENT_UPDATE(update); COMPONENT_SHUTDOWN(shutdown); // Specifying the name of the property file and parameters for our component PROP_NAME("WaterDropAircraftController"); PROP_PARAM(Toggle, open, false); PROP_PARAM(Float, flow, 1.0f); private: void init(); void update(); void shutdown(); // Declaring a callback on changing property parameters void parameterChanged(Unigine::PropertyPtr property, int propID); void openWaterDropSystem(bool open); void setWaterDrowSystemFlow(float value); private: // Declaring a particle system to be used for the water drop effect Unigine::ObjectParticlesPtr dropWaterEffect; }; #endif // _WATER_DROP_AIRCRAFT_CONTROLLER_INCLUDED_
-
WaterDropAircraftController.cpp
Source code (C++)#include "WaterDropAircraftController.h" #include <UnigineProperties.h> #include <UnigineObjects.h> #include <UnigineEditor.h> // Registering the component in the Component System REGISTER_COMPONENT(WaterDropAircraftController); void WaterDropAircraftController::init() { using namespace Unigine; // Adding a callback on changing property parameters getProperty()->addCallback(Property::CALLBACK_PARAMETER_CHANGED, MakeCallback(this, &WaterDropAircraftController::parameterChanged)); // Creating a particle system for our effect and setting its parameters dropWaterEffect = ObjectParticles::create(); dropWaterEffect->release(); Editor::get()->addNode(dropWaterEffect->getNode(), true); dropWaterEffect->setParent(getNode()); dropWaterEffect->setParticlesType(ObjectParticles::TYPE_LENGTH); dropWaterEffect->setEmitterType(ObjectParticles::EMITTER_BOX); dropWaterEffect->setEmitterSize(Math::vec3(3.0f, 3.0f, 0.5f)); dropWaterEffect->setWarming(false); dropWaterEffect->setCulling(true); dropWaterEffect->setSpawnRate(100.0f); dropWaterEffect->setLengthStretch(0.1f); dropWaterEffect->setEmitterEnabled(true); dropWaterEffect->setEmitterDirection(-Math::vec3::UP); dropWaterEffect->setEmitterSpread(Math::vec3(0.5f, 0.5f, 0.5f)); dropWaterEffect->setLife(15.0f, 1.0f); dropWaterEffect->setRadius(0.5f, 0.0f); dropWaterEffect->setVelocity(10.0f, 2.0f); dropWaterEffect->setGrowth(1.0f, 0.5f); dropWaterEffect->setGravity(Math::vec3(0.0f, 0.0f, -15.0f)); dropWaterEffect->setEnabled(false); } void WaterDropAircraftController::update() {} void WaterDropAircraftController::shutdown() {} /// Callback function to be executed on changing property parameters void WaterDropAircraftController::parameterChanged(Unigine::PropertyPtr prop, int propID) { if (open.getID() == propID) { const auto value = prop->getParameterPtr(propID)->getValueToggle(); openWaterDropSystem(value); } else if (flow.getID() == propID) { const auto value = prop->getParameterPtr(propID)->getValueFloat(); setWaterDropSystemFlow(value); } } void WaterDropAircraftController::openWaterDropSystem(bool value) { if(dropWaterEffect) dropWaterEffect->setEnabled(value); } void WaterDropAircraftController::setWaterDropSystemFlow(float value) { if (dropWaterEffect) { const float SPAWN_RATE_FACTOR = 100.0f; dropWaterEffect->setSpawnRate(value * SPAWN_RATE_FACTOR); } }
In the header file (WaterDropAircraftController.h) define the name for the property file and describe parameters of the component:
Source code (C++)// WaterDropAircraftController.h // ... // Specifying the name of the property file and parameters for our component PROP_NAME("WaterDropAircraftController"); PROP_PARAM(Toggle, open, false); PROP_PARAM(Float, flow, 1.0f); // ...
In the implementation file (WaterDropAircraftController.cpp) write your component's logic. At the initialization stage subscribe to parameter change event, as this component(property) will be associated with IG components changing these parameters when receiving commands from a host.
Source code (C++)// WaterDropAircraftController.cpp) // ... void WaterDropAircraftController::init() { using namespace Unigine; // Adding a callback on changing property parameters getProperty()->addCallback(Property::CALLBACK_PARAMETER_CHANGED, MakeCallback(this, &WaterDropAircraftController::parameterChanged)); // ... }
-
- Build and launch your project. At the initialization stage the Component System will create a property file named WaterDropAircraftController.prop for our component.
Source code (XML)
<?xml version="1.0" encoding="utf-8"?> <property version="2.7.3.0" name="WaterDropAircraftController" manual="1" parent_name="node_base"> <parameter name="open" type="toggle">0</parameter> <parameter name="flow" type="float">1</parameter> </property>
- Via the UnigineEditor assign the new created property file (WaterDropAircraftController.prop) to a node, for which the component was created (Be-200 in our case).
- Add the description of our component to the desired entity in the IG configuration file (ig_config.xml). Its name and parameters must correspond to the ones described in the component's header file (see Step 3).
Source code (XML)
<!-- ..... --> <entity id="200" name="be-200"> <!-- ..... --> <component id="6" name="water_drop"> <property>WaterDropAircraftController</property> <parameter name="state">open</parameter> <parameter name="data1">flow</parameter> </component> <!-- ..... --> </entity> <!-- ..... -->
- To test the new component add its description to the configuration file of the host emulator (<path_to_host>/Default/Entities.def) NoticeComponent ID must be the same as the one specified in the ig_config.xmlSource code
entity { name = "Be-200"; type = 200; class = fixedwing; .... component { name = "water_drop"; id = 6; def_state = 0; state { name = "close"; value = 0; } state { name = "open"; value = 1; } } }
After launching your host application or a CIGI Host Emulator you can control your custom component by sending the corresponding packets to the IG.