Last updated
Last updated
All applications in Force holds by Force::Application class. Application is base class of Force Engine, it holds all user applications, install other engines, managers, load libraries defined by ApplicationSpecification.
To create a application we need create single executable .cpp file, in our case in will be ExampleApplication.cpp.
Then you need to include Force API to get access to engine functionality. You can do it multiple ways for example by including Force.h
or ForceMinInclude.h
and then Main.cpp
. But this is not recommended even if it will work. We will do it properly by creating Config.h
file, that you can copy from engine Config.h
with all description about each define.
So this how our Config file should looks like:
In this config file we can choose how include Force. By defining FE_CONFIG_INCLUDE_FORCE all force public API will be included to ExampleApplication. By defining FE_CONFIG_INCLUDE_FORCE_MIN only minimum requered API will be inlcuded, so for ExampleApplication we choose it. By defining other controlling config stuff see Config.h that stored in Force/Sources.
Now how our ExampleApplication.cpp file should looks like:
Any Application accept the ApplicationSpecification structure in their base constructor. About the specifications we will talk later.
Each Force Core module is divided by different folder and stored in namespaces. Here list with all supported at this moment Force modules.
Let's start with Force
namespace. This is the most important folder where the engine main modules, are stored.
Force::Core
is designed for the engine core. it stores all the most important things for the engine and your application.
Next the Force::IO
namespace where events, input, and output are stored.
In Force::Graphics
as you have already understood everything is stored related to graphics, graphics engines, and so on. Inside it there are namespaces ::GL
,::D3D
that display each API. You don't need to use them this is only for the engine developers side.
Force::Audio
designed for audio and store the Audio Engine.
Force::Platform
stores different system that specific for each platform. You won't need to use it, either.
What you will need to use quite often so it Force::Math
. This namespace stores vectors, matrices, and all that crap about math and computing.
Force::Assets
namespace store all files that need to work with assets and asset system in general.
Force::Scripting
is namespace that store all Mono scripting engine code, and need only for engine developers.
Force::Localization
is localization / language manager module.
Force::Serializaion
is serialization/de-serialization manager module.
Force::Utils
is namespace that store all utilities files for platform, or from standard of C++ or from other libraries.
For base executable files such ExampleApplication its recommended to directly use Force API with namespaces, but for other files you can just defined it.
Note if you not use Config.h
file you should also include Main.cpp
file after Config.h
.
Each application should have its entry point. Entry point is entry of any program in general. In Force entry point defined in Main.cpp
file. Without it, you won't be able to compile and launch the application. This file need to be included once per application project.
Before launching application we need to create implementation of Force::CreateApplication() function.
And that's it! One of base and main things, we have done everything. Now you can just press F5 and build and run your own application written in Force.
Now Applications use the specifications like ApplicationSpecification
, ApplicationUserSpecification
, ApplicationWindowSpecification
, and ApplicationBootSpecification
instead old GetParam API.
When you first configure and run the engine you will have by default are the default settings of window and so on. If you want to add or change your app's settings you will need to use Force::ApplicationSpecification
struct to configurate custom application. Its contains the bunch options that you can apply on application.
As you can see ApplicationSpecification
contains basic, parameter as name or version of your app, but also contains other application sub-specifications.
User specification contains information about user per application. Some of options can be independent of each application, like startProjectPath
or newUser.
But other options is specific for each application.
Window specification contains application window info.
Contains information about boot/start data that comes from Core and Entry Point.
This Application specification you should implement in your CreateApplication
function. For example:
To access to engine main update loop and hold our code properly we use Elements.
Include the Force/Core/Element.h
from Force::Core
namespace. Next creates new file and class ExampleElement.h
somewhere in folder Elements and inherent it from Element
.
Element has pack events that called in some time by application and controls by Force::ElementEngine. List of events called by application:
This example will implement Element as basic test for Force Renderer.
Next create the implementation file ExampleElement.cpp,
and include ExampleElement.h
.
In OnCreate() function we setting up the perspective camera and set its Z position to be 5.0, to make our primitives visible from that camera.
In OnUpdate() function we call few commands from RenderCmd from Force::Graphics to clear main screen view with new color and clear depth and color buffers.
Before we can render anything we need to call Begin() and End() and pass to it camera itself and it calculated view. View matrix can be calculated from any Transform, by GetViewMatrix().
Today Force 2D Renderer support few types of primitive:
Points
Lines
Rects
Rects Textured
Rects Lined
Circles
Circles Thinned
Sprites
AABB's
If you want you can add few more example primitives:
The RenderRectTextured() accept the texture parameter. To create and load a texture use Texture2D from Force::Graphics namespace. Also its accepts Transform instead of Rect because we pass rotationZ value to have opportunity to rotate the rect.
We have finished creating your own rendering element, now you just need to add element to application in Force::CreateApplication().
You can use two ways to do this by AddElementLast() to add element to end of container, and AddElement() to add scene to begin of container. And after that you can run your app with peace of mind.
Check Example\ExampleApplication for full example in ForceDev repository for details.
Force also allows to create a console applications, and cut off a lot of unnecessary API's, such a main window, rendering, assets, languages, IO, and display only console that you can write, read or test or maybe even create a server (even if Force not have this API yet.).
To create a console application all that you need to do is in you CreateApplication
function set consoleApp
to FE_TRUE
:
Also you can disable debug logger that you Force and use specific release logger, that will log only your message to console. To do this set this in you config file inside ManagedInitializeCore
function:
Check Example\ConsoleApplication for full example in ForceDev repository for details.
In the variable LinkForce
we can specify how Force wil be linked and build: "Dynamic" to ".dll" or "Static to ".lib". Force from 23 commit (993651b) of dev using Static linking and to migrate to dynamic requested rewrite hole a bunch of code.
So for now Force supports only static linking and look like this:
Projects in Force separates by few groups: Core, Examples and Libraries and in that order displays in Visual Studio. About libraries we talk about later. Force project list available at this moment is:
If you dont need them to exist you can just turn it off by setting to false
.
Each of this project and libraries defined as Libraries
has its Project Directory ProjDir
relative to ForceDir
. Some of this projects - libraries that stored either relative to Force/Libraries
or some of them relative to vckpg/packages
.
All of this libraries has BinaryDir
depending on build configuration (Debug, Release) where all binaries files stored for that library, then IncludeDir
where all header files stored, and Library
itself thats directly points to static library (.lib) witch you can link to Projects.Core.Force
library.
The code for solution looks like this:
Its basic premake script workspace with two configurations and some flags. Basically here all what you need for solution so dont recommended it to change.
Go to Force and open Force.lua
premake file. This is file that contains definition of the main project, basically all other projects are structured this way.
The most important here is targetdir
and objdir
where project will store when build project. By default it will be Bin/*BuildDir/*ProjectName/Lib
and Bin/*BuildDir/*ProjectName/Obj
Then goes files
and include directories (includedir
) witch project will be included and use, and links
list and already configured for each library of libraries that will be linked to Force.
Defines (defines
) that contains list of predefined FE_LIBRARY_
* macross and other platform libraries.
And the goes that same for each platform and configuration.
When you write applications, you can disable some libraries and especially its linking if you dont use them to decrease size of the your executable. Now it totally achievable. To do that please go to ForceEngine.lua
and find libraries list:
Just set you library to false
and you ready to go. Its disable library linking for static libraries, for dynamic libraries its disable copying its .dll
file in to executable directory, and sets it proper macros FE_LIBRARY_XXX
to 0
. After this you need to fully rebuild the solution for Debug and Release configuration.
Libraries that now can be disables:
For other libraries its not tested, and basically other libraries its tiny and all static linked so you dont have any .dll file requested and dont need to disable.
If you have some problems with compiling or linking Force, please take a look on the latest two below.
The RenderSprite() use the ECS components, one for Transform and another for Sprite. C++ API is almost identical to C#, so you can find more information in this .
Projects and solution we can configure using Premake that written on Lua. Lua is easy to learn scripting language, with minimum dependences and code. Each premake file stores on each of project directories. Main premake file is ForceEngine.lua
stored in root of ForceDev. It contains utility functions to work with projects and solution itself. For reference you can check and documentation.
When you linked Mono and Mono Runtime in to Force you can not have Mono folder with all Runtime .Net Framework. If that happens means you forgot copy proper version of you .Net Framework from MonoSDK. To do that please go to C:\_YourMonoSDKPath_\lib\mono
and select you version of .NET Framework and copy it Mono folder to you working or executable directory or just download this .
Core
Force/Core
Force::Core
IO
Force/IO
Force::IO
Graphics
Force/Graphics
Force::Graphics
Graphics (OpenGL)
Force/Graphics/GL
Force::Graphics::GL
Graphics (DirectX)
Force/Graphics/D3D
Force::Graphics:D3D
Audio
Force/Audio
Force::Audio
Platform
Force/Platform
Force::Platform
Physics
Force/Physics
Force::Physics
Math
Force/Math
Force::Math
Assets
Force/Assets
Force::Assets
Project
Force/ProjectManagment
Force::ProjectManagment
Scene Managment
Force/SceneManagment
Force::SceneManagment
Scripting
Force/Scripting
Force::Scripting
Serialization
Force/Serialization
Force::Serialization
Localization
Force/Localization
Force::Localization
Utils
Force/Utils
Force::Utils
OnWindowCreate()
Calls when application creates platform and window, but before the OnCreate(). Prefer using this for setting custom title. Not use rendering, audio, physics, scripting code here because contexts of it was not created at this point.
OnGuiCreate()
Calls during Dear's ImGui Context creation. This function will not execute if application disable support ImGui. Main usage of this function is customize the ImGui global settings during creation for each application.
OnCreate()
Calls when all application engines was initialized. Difference with OnPostCreate(), that this function calls before showing window.
OnPostCreate()
Calls after OnCreate(). This same as OnCreate() but after showing window.
OnUpdate()
Calls by application in engine main update loop every frame, with passing the delta time variable.
OnEvent()
Calls by application when any event inherited from Event is invokes.
OnRenderGui()
Calls after main rendering, when Dear's ImGui begin their rendering frame. This function was not be called if application disable support of Dear's ImGui.
OnDestroy()
Calls when application exiting from main engine update loop.