Skip to content

Commit

Permalink
application
Browse files Browse the repository at this point in the history
  • Loading branch information
jankrassnigg committed Oct 15, 2024
1 parent e9f48cb commit 6e6fd6e
Show file tree
Hide file tree
Showing 19 changed files with 122 additions and 25 deletions.
4 changes: 2 additions & 2 deletions pages/docs/appendix/library-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The **Core** library is built on top of Foundation. This library contains engine

The **TestFramework** library implements code to manage our unit-tests. You can ignore this entirely.

**GameEngine** builds on top of all the other libraries, including the rendering code. It contains the most high-level code for a game engine, such as AI and Animation, [ezGameApplication (TODO)](../runtime/application/application.md) and [ezGameState](../runtime/application/game-state.md), which are the basis for any game application built with EZ, the prefab system, the visual scripting and much more.
**GameEngine** builds on top of all the other libraries, including the rendering code. It contains the most high-level code for a game engine, such as AI and Animation, [ezGameApplication](../runtime/application/application.md) and [ezGameState](../runtime/application/game-state.md), which are the basis for any game application built with EZ, the prefab system, the visual scripting and much more.

In general the most interesting libraries to look at are **Foundation**, **Core** and **GameEngine**.

Expand Down Expand Up @@ -82,7 +82,7 @@ In **GameEngine** you will find all the high-level code needed in a game engine.

**GameEngine\\Console** contains code for a Quake-like in-game console that can be used for changing the game configuration (through `ezCVar` or custom functions) and to see the `ezLog` output.

**GameEngine\\GameApplication** contains [ezGameApplication (TODO)](../runtime/application/application.md), which extends `ezApplication` with higher-level, more game specific functionality. This is one of the most important high-level classes to look at and extend when writing your own, stand-alone game application (assuming you can't do so with `ezGameState` alone).
**GameEngine\\GameApplication** contains [ezGameApplication](../runtime/application/application.md), which extends `ezApplication` with higher-level, more game specific functionality. This is one of the most important high-level classes to look at and extend when writing your own, stand-alone game application (assuming you can't do so with `ezGameState` alone).

In **GameEngine\\GameState** you find [ezGameState](../runtime/application/game-state.md), which is the most important class to extend when writing your own game code, especially if you want to be able to run your code within the editor.

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/build/sdk-root.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Using a redirection file is the least invasive method and it works for all EZ ap

## Custom SDK Root

You can fully control where the SDK root should be and how it is found, if you write your own [application (TODO)](../runtime/application/application.md). During early startup you can simply set the path of the SDK root folder with `ezFileSystem::SetSdkRootDirectory()`.
You can fully control where the SDK root should be and how it is found, if you write your own [application](../runtime/application/application.md). During early startup you can simply set the path of the SDK root folder with `ezFileSystem::SetSdkRootDirectory()`.

This can be preferable when you use a very different structure.

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/custom-code/cpp/cpp-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Finally, have a look at [profiling](../../performance/profiling.md), to know whe

## Standalone App

If you want to write your own stand-alone application, have a look at the [application (TODO)](../../runtime/application/application.md) chapter. However, we encourage you to have your entire game code in a plugin, otherwise you can't use any of it in the editor. You would mostly need your own application for the finishing touches of how you present the main menu, etc, and a good starting point is to just copy the [ezPlayer](../../tools/player.md) and make adjustments.
If you want to write your own stand-alone application, have a look at the [application](../../runtime/application/application.md) chapter. However, we encourage you to have your entire game code in a plugin, otherwise you can't use any of it in the editor. You would mostly need your own application for the finishing touches of how you present the main menu, etc, and a good starting point is to just copy the [ezPlayer](../../tools/player.md) and make adjustments.

## See Also

Expand Down
4 changes: 2 additions & 2 deletions pages/docs/custom-code/cpp/engine-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Engine plugins are the best way to get your custom code into the engine, such that it is accessible by the editor and also [ezPlayer](../../tools/player.md).

Contrary to using a plugin, you could also build your own [application (TODO)](../../runtime/application/application.md), which may link to static libraries that contain your code. However, that approach means that your code cannot be loaded into the editor process and therefore you won't be able to leverage those tools to their full extent. We strongly advise against that.
Contrary to using a plugin, you could also build your own [application](../../runtime/application/application.md), which may link to static libraries that contain your code. However, that approach means that your code cannot be loaded into the editor process and therefore you won't be able to leverage those tools to their full extent. We strongly advise against that.

## Creating a Plugin

Expand Down Expand Up @@ -67,7 +67,7 @@ These callbacks are optional, though in some cases you may want to register and

If you want to load a plugin from code, you would use `ezPlugin::LoadPlugin()` and provide only the name (no path) of your plugin. Make sure that the DLL is stored in the same directory as all other DLLs and EXEs.

The more convenient way to load your game plugin, though, is to enable it in the [project settings](../../projects/plugin-selection.md). Then it will be automatically loaded by every [application (TODO)](../../runtime/application/application.md).
The more convenient way to load your game plugin, though, is to enable it in the [project settings](../../projects/plugin-selection.md). Then it will be automatically loaded by every [application](../../runtime/application/application.md).

## Add Custom Code

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/debugging/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ There are multiple ways to see the content of the log:
* In the [ezEditor](../../getting-started/editor-overview.md) you can open *Panels > Log* to see two logs, the one for the editor and the one from the engine process.
* [ezInspector](../tools/inspector.md) shows the log of the connected process.
* The in-game [console](console.md) outputs the log messages.
* By default all EZ [applications (TODO)](../runtime/application/application.md) also write the log output to a `Log.htm` file in the application's *appdata* folder.
* By default all EZ [applications](../runtime/application/application.md) also write the log output to a `Log.htm` file in the application's *appdata* folder.

## Thread-local logging

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/debugging/renderdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ezEngine has a dedicated *RenderDocPlugin*, to integrate RenderDoc support even

## Taking Captures

If you write your own [application (TODO)](../runtime/application/application.md) you can hook up RenderDoc in different ways, however, by default these methods are available:
If you write your own [application](../runtime/application/application.md) you can hook up RenderDoc in different ways, however, by default these methods are available:

* **Press F11:** The `F11` key will take a capture of the current frame.
* Type `CaptureFrame()` into the game [console](console.md).
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/performance/profiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Profiling an application means to record information about its performance to an

## Capturing Profiling Data

ezEngine has a built in profiling system with which you can record the function call graph, across all active threads, with precise timing information. The profiling system is very efficient, which is why in development builds it is constantly recording data to a ring buffer, which allows you to write recent profiling data to disk at any time. That means whenever you encounter a situation with bad performance, you can just press a button (in stock [applications (TODO)](../runtime/application/application.md) such as [ezPlayer](../tools/player.md) it's the `F8` key) to save a snapshot.
ezEngine has a built in profiling system with which you can record the function call graph, across all active threads, with precise timing information. The profiling system is very efficient, which is why in development builds it is constantly recording data to a ring buffer, which allows you to write recent profiling data to disk at any time. That means whenever you encounter a situation with bad performance, you can just press a button (in stock [applications](../runtime/application/application.md) such as [ezPlayer](../tools/player.md) it's the `F8` key) to save a snapshot.

The application will write to the [log](../debugging/logging.md) where it stored the profiling snapshot. You can see this in the [console](../debugging/console.md):

Expand Down
4 changes: 2 additions & 2 deletions pages/docs/projects/data-directories.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ You may notice the `>sdk` and `>project` prefixes. These are *special directory*

### From Custom Code

You can also mount data directories from code. Usually you would do this either in a custom [application (TODO)](../runtime/application/application.md) class or in a [game state](../runtime/application/game-state.md). Either way, you should do this early at game startup. For more more information, see the [filesystem documentation](../runtime/filesystem.md#data-directories).
You can also mount data directories from code. Usually you would do this either in a custom [application](../runtime/application/application.md) class or in a [game state](../runtime/application/game-state.md). Either way, you should do this early at game startup. For more more information, see the [filesystem documentation](../runtime/filesystem.md#data-directories).

## See Also


* [FileSystem](../runtime/filesystem.md)
* [FileServe](../tools/fileserve.md)
* [Projects](projects-overview.md)
* [Application (TODO)](../runtime/application/application.md)
* [Application](../runtime/application/application.md)
* [Game States](../runtime/application/game-state.md)
4 changes: 2 additions & 2 deletions pages/docs/projects/project-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ In the editor you will find the project settings under *Project > Project Settin

![Window Configuration](media/editor-window-config.png)

These settings allow you to configure basic window settings for Play-the-Game mode and when running an exported scene in [ezPlayer](../tools/player.md). A proper game would typically implement this logic in a custom [application (TODO)](../runtime/application/application.md) and should allow the user to choose settings such as the resolution. The window configuration dialog is mainly for use during development.
These settings allow you to configure basic window settings for Play-the-Game mode and when running an exported scene in [ezPlayer](../tools/player.md). A proper game would typically implement this logic in a custom [application](../runtime/application/application.md) and should allow the user to choose settings such as the resolution. The window configuration dialog is mainly for use during development.

There are two separately stored configurations:

Expand All @@ -44,7 +44,7 @@ If plugins provide additional editor options, they are typically found under *Pr

### Loading Plugins from Code

A custom [application (TODO)](../runtime/application/application.md) or [game state](../runtime/application/game-state.md) can load plugins directly from code if necessary. For example the `ezInspectorPlugin` is automatically loaded for you by stock EZ applications, when building the code for development.
A custom [application](../runtime/application/application.md) or [game state](../runtime/application/game-state.md) can load plugins directly from code if necessary. For example the `ezInspectorPlugin` is automatically loaded for you by stock EZ applications, when building the code for development.

## FMOD

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/projects/projects-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The term *project* refers to one game or application, its global settings, and a

## Creating a Project

You can use ezEngine entirely without the editor. In that case, you do not need to create a project, at all. Your [application (TODO)](../runtime/application/application.md) is your project and you set up things like the [fileSystem](../runtime/filesystem.md), the [plugins](../custom-code/cpp/engine-plugins.md) and so on, entirely from code.
You can use ezEngine entirely without the editor. In that case, you do not need to create a project, at all. Your [application](../runtime/application/application.md) is your project and you set up things like the [fileSystem](../runtime/filesystem.md), the [plugins](../custom-code/cpp/engine-plugins.md) and so on, entirely from code.

It is more convenient, though, to maintain your project through the editor. To create a new project, open the editor's [dashboard](../editor/dashboard.md) (*Project > Show Dashboard*) and select **New** from the top-right corner:

Expand Down
103 changes: 100 additions & 3 deletions pages/docs/runtime/application/application.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,107 @@
# Application

See [Game States](game-state.md)
Every C++ application has one function that is the entry point for running the application. The name, signature and behavior of this function can differ across platforms. As a game developer you rarely care about interacting with the system on the lowest level. However, depending on what kind of application you write (for example a tool, rather than a game), you may either want to get a fully setup engine where all you add is your custom game code, or you may prefer to have a rather bare bones application, where you have full control.

<!-- PAGE IS TODO -->
Therefore EZ uses a number of abstraction layers, where each layer adds some functionality, and thus convenience for making a game. You build your application by overriding the layer that makes most sense for the intended use case.

The classes `ezApplication`, `ezGameApplicationBase` and `ezGameApplication` are fully functional, but currently undocumented.
> **NOTE**
>
> This is an *advanced* topic for people who are either building custom tools, using a completely custom renderer or are close to shipping and want a custom binary (rather than using [ezPlayer](../../tools/player.md)). As long as you only want to write game code, add a [custom game state](game-state.md) inside an [engine plugin](../../custom-code/cpp/engine-plugins.md). See [C++ Project Generation](../../custom-code/cpp/cpp-project-generation.md) for the most convenient way to get started with this.
## Custom Application Use Cases

> **ATTENTION**
>
> Don't put game functionality into a custom application. If you do so, you'll lose the ability to test your game logic inside the editor. Only use a custom application to polish the overall game presentation.
There are two main situations in which you'll need to write your own application:

1. You want to write a custom tool. Usually a command line application to process some data.
1. You are preparing you game for shipping and don't want to run it through [ezPlayer](../../tools/player.md) anymore.

In the first case, you'll typically build your application on top of `ezApplication` which gives you a streamlined entry point similar to to a regular C++ `main` function.

In the second case you usually build your application on top of `ezGameApplication`. It is assumed that you already have a custom [Game State](game-state.md) anyway. The easiest way to get started, is simply to copy the [ezPlayer](../../tools/player.md) application and modify it to suit your needs, such as:

* Custom binary name
* Custom icon
* Startup videos
* Way to select graphics and other options
* Pause / mute game when it doesn't have focus

## Application Structure Diagram

The diagram below shows the structure that ezEngine uses. The chapters below describe each aspect in detail.

![Application Structure Diagram](media/application.png)

## Application Entry Point Macro

On the lowest C++ level platforms differ significantly how they execute an application. Therefore EZ uses the macro `EZ_APPLICATION_ENTRY_POINT` to generate the necessary, platform-specific code. This needs to be put into some cpp file of your application and you have to pass in the class name of your custom application. This class must be derived from `ezApplication` or `ezGameApplication`.

**Example:**

```cpp
class ezPlayerApplication : public ezGameApplication
{
// ...
};

EZ_APPLICATION_ENTRY_POINT(ezPlayerApplication);
```
Some platforms (mainly Windows) differentiate between *console apps* and *window apps*. Console apps are executed inside a command prompt and typically do not have graphical output, whereas *window apps* create their own window to display output and interact with.
By default, applications are treated as *console apps* and thus show a command prompt on these platforms. This can be convenient for debugging, as you see the [log output](../../debugging/logging.md) there. To remove the command prompt, you need to configure you application as a *window app*. To do so, the *CMakeLists.txt* file for your application has to call `ez_make_windowapp`:
```cmake
ez_create_target(APPLICATION ${PROJECT_NAME})
ez_make_windowapp(${PROJECT_NAME})
```

## ezApplication Based Apps

If you are building an application that doesn't need the full engine, derive you application class directly from `ezApplication`.

The most important functions to override are the following:

* `ezApplication::AfterCoreSystemsStartup()` - to set configure systems.
* `ezApplication::Run()` - the main loop

Note that `Run` will be called repeatedly until you call `RequestApplicationQuit()`.

For applications that process data and may be integrated into automatic build chains, it is also useful to use:

* `ezApplication::SetReturnCode()` - to set the return code passed to the operating system
* `ezApplication::TranslateReturnCode()` - to provide a human readable string for each return code

## ezGameApplication Based Apps

`ezGameApplicationBase` is built on top of `ezApplication` and implements the actual setup of the engine. It also adds the [Game State](game-state.md) functionality and other [common application features](common-application-features.md). `ezGameApplication` further adds functionality to setup the EZ renderer. In theory you can build a game that doesn't use the EZ renderer, by deriving from `ezGameApplicationBase`, but this is a very advanced topic and only makes sense in very specific circumstances.

In practice you should derive your game class from `ezGameApplication`, but be aware that there are additional virtual functions in `ezGameApplicationBase` that you can (and may need to) override.

These functions are of particular interest:

* `ezGameApplicationBase::CreateGameState()` - to hardcode which game state to use for your game
* `ezGameApplicationBase::FindProjectDirectory()` - to adjust where your project data is located
* `ezGameApplicationBase::Init_...()` - these init functions configure all sorts of aspects of the engine
* `ezGameApplicationBase::Init_ConfigureInput()` - you may need to set up input mappings for the main menu and closing the app
* `ezGameApplicationBase::Run_ProcessApplicationInput()` - handle input for the application

The best way to go about writing your own game application, is to copy the [ezPlayer](../../tools/player.md) code and adjust it to fit your needs.

If all you have is a game state, but you want to build a dedicated binary for your game, you can also do it like the [Asteroids sample](../../../samples/asteroids.md) which simply uses `ezGameApplication` directly to create an application instance with a single line of code:

```cpp
EZ_APPLICATION_ENTRY_POINT(ezGameApplication, "Asteroids", "Data/Samples/Asteroids");
```
## Game State vs. Application
[Game States](game-state.md) play the role of encapsulating all of your game logic. Application classes are used to define how your app behaves within the operating system environment. The two are very clearly separated in what they are meant to do, thus there should never be the question whether you use a custom game state or a custom application. Everything that relates to the game logic should go into the game state. Only the few things that cannot be done there, should go into the application class.
The intended effect is, that you can [run your game](../../editor/run-scene.md) in the editor or through [ezPlayer](../../tools/player.md) and thus have multiple convenient ways to test it.
## See Also
Expand Down
Loading

0 comments on commit 6e6fd6e

Please sign in to comment.