diff --git a/Makefile b/Makefile index cedcf1bd60..da6c6a2ae9 100644 --- a/Makefile +++ b/Makefile @@ -22,14 +22,14 @@ install: $(BUILDDIR) .PHONY: run run: build - $(BUILDDIR)/run game + cd $(BUILDDIR) && ./run game .PHONY: test test: tests checkfast .PHONY: tests tests: build - $(BUILDDIR)/run test -a + cd $(BUILDDIR) && ./run test -a .PHONY: build build: $(BUILDDIR) diff --git a/README.md b/README.md index b3693ce6c8..f40bd91d3f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ [![openage](/assets/logo/banner.svg)](http://openage.dev) ========================================================= -**openage**: a volunteer project to create a free engine clone of the *Genie Engine* used by *Age of Empires*, *Age of Empires II (HD)* and *Star Wars: Galactic Battlegrounds*, comparable to projects like [OpenMW](https://openmw.org/), [OpenRA](http://openra.net/), [OpenSAGE](https://github.com/OpenSAGE/OpenSAGE/), [OpenTTD](https://openttd.org/) and [OpenRCT2](https://openrct2.org/). At the moment we focus our efforts on the integration of *Age of Empires II*, while being primarily aimed at POSIX platforms such as **GNU/Linux**. +**openage**: a volunteer project to create a free engine clone of the *Genie Engine* used by *Age of Empires*, *Age of Empires II (HD)* and *Star Wars: Galactic Battlegrounds*, comparable to projects like [OpenMW](https://openmw.org/), [OpenRA](http://openra.net/), [OpenSAGE](https://github.com/OpenSAGE/OpenSAGE/), [OpenTTD](https://openttd.org/) and [OpenRCT2](https://openrct2.org/). openage uses the original game assets (such as sounds and graphics), but (for obvious reasons) doesn't ship them. -To play, you require *an original AoE II: TC, [AoE II: HD](http://store.steampowered.com/app/221380/)* or [AoE II: DE](https://store.steampowered.com/app/813780) installation (via [Wine](https://www.winehq.org/) or [Steam-Linux](doc/media_convert.md)). +To play, you require *[any of the original games (AoE1, AoE2)](/doc/media_convert.md)* or their *Definitive Edition* releases. [![github stars](https://img.shields.io/github/stars/SFTtech/openage.svg)](https://github.com/SFTtech/openage/stargazers) [![#sfttech on matrix.org](/assets/doc/matrixroom.svg)](https://matrix.to/#/#sfttech:matrix.org) @@ -13,32 +13,41 @@ To play, you require *an original AoE II: TC, [AoE II: HD](http://store.steampow Contact ------- -Contact | Where? ------------------|------- -Issue Tracker | [GitHub SFTtech/openage](https://github.com/SFTtech/openage/issues) -Development Blog | [blog.openage.dev](https://blog.openage.dev) -Subreddit | [![reddit](/assets/doc/reddit.svg) /r/openage](https://www.reddit.com/r/openage/) -Discussions | [GitHub Discussions](https://github.com/SFTtech/openage/discussions) -Matrix Chat | [![matrix](/assets/doc/matrix.svg) `#sfttech:matrix.org`](https://matrix.to/#/#sfttech:matrix.org) -Money Sink | [![money sink](/assets/doc/liberapay.svg)](https://liberapay.com/SFTtech) - +| Contact | Where? | +| ---------------- | -------------------------------------------------------------------------------------------------- | +| Issue Tracker | [GitHub SFTtech/openage] | +| Development Blog | [blog.openage.dev] | +| Subreddit | [![reddit](/assets/doc/reddit.svg) /r/openage](https://www.reddit.com/r/openage/) | +| Discussions | [GitHub Discussions] | +| Matrix Chat | [![matrix](/assets/doc/matrix.svg) `#sfttech:matrix.org`](https://matrix.to/#/#sfttech:matrix.org) | +| Money Sink | [![money sink](/assets/doc/liberapay.svg)](https://liberapay.com/SFTtech) | + +[GitHub SFTtech/openage]: https://github.com/SFTtech/openage/issues +[blog.openage.dev]: https://blog.openage.dev +[GitHub Discussions]: https://github.com/SFTtech/openage/discussions Technical foundation -------------------- -Technology | Component ----------------|---------- -**C++20** | Engine core -**Python3** | Scripting, media conversion, in-game console, code generation -**Qt6** | Graphical user interface -**Cython** | Python/C++ Glue code -**CMake** | Build system -**OpenGL3.3** | Rendering, shaders -**SDL2** | Cross-platform Audio/Input/Window handling -**Opus** | Audio codec -[**nyan**](https://github.com/SFTtech/nyan) | Content Configuration and Modding -**Humans** | Mixing together all of the above - +| Technology | Component | +| ------------ | ------------------------------------------------------------- | +| **C++20** | Engine core | +| **Python3** | Scripting, media conversion, in-game console, code generation | +| [**Cython**] | Python/C++ Glue code | +| [**Qt6**] | Graphical user interface | +| [**CMake**] | Build system | +| [**OpenGL**] | Rendering, shaders | +| [**Opus**] | Audio codec | +| [**nyan**] | Content Configuration and Modding | +| [**Humans**] | Mixing together all of the above | + +[**Cython**]: https://cython.org/ +[**Qt6**]: https://contribute.qt-project.org/ +[**CMake**]: https://cmake.org/ +[**OpenGL**]: https://www.opengl.org/ +[**Opus**]: https://opus-codec.org/ +[**nyan**]: https://github.com/SFTtech/nyan +[**Humans**]: https://www.youtube.com/watch?v=fQGbXmkSArs&t=20s Goals ----- @@ -72,26 +81,19 @@ Current State of the Project We're implementing the internal game simulation (how units even do anything) with simplicity and extensibility in mind, so we had to get rid of the temporary (but kind of working) previous version. With these changes we can (finally) actually make use of our converted asset packs and our nyan API! We're working day and night to make gameplay return\*. -If you're interested, we wrote detailed explanations on our blog: [Part 1](https://blog.openage.dev/new-gamestate-2020.html), [Part 2](https://blog.openage.dev/engine-core-modules.html). +If you're interested, we wrote detailed explanations on our blog: [Part 1](https://blog.openage.dev/new-gamestate-2020.html), [Part 2](https://blog.openage.dev/engine-core-modules.html), [Monthly Devlog](https://blog.openage.dev/tag/news.html). *\* may not actually be every day and night* -Operating System | Build status -:------------------:|:--------------: -Debian Sid | [Todo: Kevin #11](https://github.com/SFTtech/kevin/issues/11) -Ubuntu 22.04 LTS | [![Ubuntu 22.04 build status](https://github.com/SFTTech/openage/actions/workflows/ubuntu-22.04.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/ubuntu-22.04.yml) -macOS | [![macOS build status](https://github.com/SFTtech/openage/workflows/macOS-CI/badge.svg)](https://github.com/SFTtech/openage/actions?query=workflow%3AmacOS-CI) -Windows Server 2019 | [![Windows Server 2019 build status](https://github.com/SFTtech/openage/actions/workflows/windows-server-2019.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/windows-server-2019.yml) -Windows Server 2022 | [![Windows Server 2022 build status](https://github.com/SFTtech/openage/actions/workflows/windows-server-2022.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/windows-server-2022.yml) - -* Which **platforms** are supported? - * Linux (primary), Windows & macOS (at least we try :) - -* What **features** are currently implemented? - * See [status page](https://github.com/SFTtech/openage/projects). +| Operating System | Build status | +| :-----------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| Debian Sid | [Todo: Kevin #11] | +| Ubuntu 22.04 LTS | [![Ubuntu 22.04 build status](https://github.com/SFTTech/openage/actions/workflows/ubuntu-22.04.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/ubuntu-22.04.yml) | +| macOS | [![macOS build status](https://github.com/SFTtech/openage/workflows/macOS-CI/badge.svg)](https://github.com/SFTtech/openage/actions?query=workflow%3AmacOS-CI) | +| Windows Server 2019 | [![Windows Server 2019 build status](https://github.com/SFTtech/openage/actions/workflows/windows-server-2019.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/windows-server-2019.yml) | +| Windows Server 2022 | [![Windows Server 2022 build status](https://github.com/SFTtech/openage/actions/workflows/windows-server-2022.yml/badge.svg?branch=master)](https://github.com/SFTtech/openage/actions/workflows/windows-server-2022.yml) | -* What's the **plan**? - * See [doc/milestones.md](/doc/milestones.md). We also have [lists of crazy xor good ideas](/doc/ideas) and a [technical overview for requested features](/doc/ideas/fr_technical_overview.md). +[Todo: Kevin #11]: https://github.com/SFTtech/kevin/issues/11 Installation Packages @@ -116,15 +118,21 @@ If you need help, maybe our [troubleshooting guide](/doc/troubleshooting.md) hel Quickstart ---------- -* How do I get this to run on my box? - * See [doc/building.md](/doc/building.md). +* **How do I get this to run on my box?** + 1. [Clone](https://docs.github.com/repositories/creating-and-managing-repositories/cloning-a-repository) the repo. + 2. Install dependencies. See [doc/building.md](/doc/building.md#dependency-installation) to get instructions for your favorite platform. + 3. Build the project: + ``` + ./configure --download-nyan + make + ``` -* I compiled everything. Now how do I run it? +* **I compiled everything. Now how do I run it?** * Execute `./bin/run`. * [The convert script](/doc/media_convert.md) will transform original assets into openage formats, which are a lot saner and more moddable. * Use your brain and react to the things you'll see. -* Waaaaaah! It +* **Waaaaaah! It...** * segfaults * prints error messages I don't want to read * ate my dog @@ -141,26 +149,14 @@ or the [bug tracker](https://github.com/SFTtech/openage/issues). Contributing ============ -You might ask yourself now "Yeah, this sounds cool and all, but how do *I* participate +You might ask yourself now "Sounds cool, but how do I participate and ~~get famous~~ contribute useful features?". Fortunately for you, there is a lot to do and we are very grateful for help. ## Where do I start? -* The engine has several [core parts](https://github.com/SFTtech/openage/projects) that need help. - You can look at the project related issues and find something for you, for example: - * **Asset Converter:** Converts whatever proprietary format used by a Age of Empires 2 into - open formats. Written mostly in Python 3. There are a lot of TODOs and beginner issues available - right now, so it's a good place to get your feet wet. - * **Game simulation:** Also known as the gameplay implementation. Written in C++, using the - Entity-Component-System paradigm in addition to an event-driven simulation. - * **Documentation:** We not only document code, but also anything technical about the Genie engine - and its games. If you like documenting [file formats](/doc/media) - or thoroughly investigating [game mechanics](/doc/reverse_engineering), - then this might be the right place to start. -* **Check the issues** [labelled with good first issues](https://github.com/SFTtech/openage/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). These are tasks that you can start right away - and don't require much previous knowledge. +* **Check the issues** [labelled with `good first issue`](https://github.com/SFTtech/openage/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). These are tasks that you can start right away and don't require much previous knowledge. * **Ask us** in the [chat](https://matrix.to/#/#sfttech:matrix.org). Someone there could need help with something. * You can also **take the initiative** and fix a bug you found, create an issue for discussion or diff --git a/doc/ai/interface.md b/doc/ai/interface.md deleted file mode 100644 index 3ac52bbdf6..0000000000 --- a/doc/ai/interface.md +++ /dev/null @@ -1,93 +0,0 @@ -AI Interface -============ - -This is a very early draft with some ideas taken -from http://bwmirror.jurenka.sk/javadoc/bwapi/package-summary.html - -This file shall provide information about the AI interface design. - - -General ideas -------------- - - * An AI registers hooks for desired events - * The C++ engine triggers python AI functions when desired events occur - * The AI then can trigger actions on the controllable units - * Periodically (1 Hz?), the AI gets ticked to allow event independent decisions - - -Event types ------------ - -Python interface basic events: - - * on_start(GameInfo info) - * on_frame(Game game) - * on_end(Player winner) - -Some AIs may prefer an event driven approach (rule based AI): - - * on_unit_discover(Unit unit) - * on_unit_complete(Unit unit) - * on_unit_lost(Unit unit) - * many more... - - -Some AIs will need to simulate ticks into the future to help -make decisions for the current tick. (min-max, MCTS, etc.) - - -Relevant structures for the AI ------------------------------- - -Remember: These are just some ideas for possible interfaces, -they are not existent in the game yet. - -```cpp -struct game_info { - int num_players; - int map_size; - int pop_limit; - resources_type; - map_view; - starting_age; - victory_mode; -} -``` - -```cpp -class Game { - Player[] allies(); // all the ally players that have not left or been defeated. - bool canBuildHere(Unit builder, TilePosition position, UnitType type); - bool canMake(Unit builder, UnitType type); - bool canResearch(Unit unit, TechType type); - bool canUpgrade(Unit unit, UpgradeType type); - Player[] enemies(); // all the enemy players that have not left or been defeated. - Unit[] getAllUnits(); // returns all the visible units. - - // many more examples at: http://bwmirror.jurenka.sk/javadoc/bwapi/Game.html -} -``` - -```cpp -class Player { - string getName(); // returns the name of the player. - Race getRace(); // returns the race of the player. - Unit[] getUnits(); // returns the set of units the player own. - bool hasResearched(TechType tech); - int getWood() // Returns the amount of wood the player owns. - // many more... -} -``` - -```cpp -class Unit { - // used to get information about individual units as well as issue orders to units -} -``` - -```cpp -class Calculation { - // used to get computation heavy calculations from the C++ engine -} -``` diff --git a/doc/architecture.md b/doc/architecture.md deleted file mode 100644 index 154a303361..0000000000 --- a/doc/architecture.md +++ /dev/null @@ -1,74 +0,0 @@ -# openage architecture - -openage is separated into many modules ("subsystems"). - - -## Overview - -Some of the components are already implemented, others are not. -All of them need to be revisited to implement the goal architecture. - - -### Components - -* Audio system -* Configuration system -* [Coordinate system](code/coordinate-systems.md) -* [Converter](code/converter/) -* Input system -* Networking -* [Game rule database](nyan/) -* [Pathfinding](code/pathfinding.md) -* Rendering -* Simulation -* [User interface](code/gui.md) - - -### Utilities - -* Datastructures -* Error handling -* Filesystem abstraction -* Job dispatching -* Live reloading -* Logging system -* Python interface -* Random number generator -* Test and demo infrastructure - - -## Information flow - -### Current architecture - -The current data flow of openage is just to display the raw simulation data. - -``` -input -> simulation -> renderer -> output -``` - - -### Goal architecture - -``` -0 input -> -1 network -> -2 simulation -> -3 network -> -4 prediction/interpolation -> -5 renderer -> -6 output -``` - -For *singleplayer* we could bypass `1 network` and `3 network` by using direct function calls or talk to a local socket. -For *multiplayer* this means that we will have a single authoritative server that is just running -the simulation. Each client then receives the data visible for it. - -The current architecture can be extended by adding the missing components in -between. - -The `prediction/interpolation` reuses the `simulation` code, but is -non-authoritative: The data provided from `2` has higher priority. - -There exists a link of `0 input -> 4 prediction` so that input -is immediately accounted in the prediction, thus displayed. diff --git a/doc/code/architecture.md b/doc/code/architecture.md new file mode 100644 index 0000000000..a45cc73dd9 --- /dev/null +++ b/doc/code/architecture.md @@ -0,0 +1,103 @@ +# openage architecture + +openage is separated into many modules ("subsystems"). + +1. [Overview](#overview) + 1. [Components](#components) + 2. [Utilities](#utilities) +2. [Information flow](#information-flow) + 1. [Current architecture](#current-architecture) + 2. [Goal architecture](#goal-architecture) + + +## Overview + +Some of the components are already implemented, others are not. +All of them need to be revisited to implement the goal architecture. + + +### Components + +* Audio system +* Configuration system +* [Coordinate system](coordinate-systems.md) +* [Converter](converter/) +* [Input system](input/) +* Networking +* [Game data database](/doc/nyan/) +* [Rendering](renderer/) +* [Simulation](game_simulation/) +* [Time management](time.md) +* [User interface](gui.md) + + +### Utilities + +* Datastructures + * [Curves](curves.md) +* [Error handling](exceptions.md) +* Filesystem abstraction +* Job dispatching +* Live reloading +* [Logging system](logger.md) +* [Python interface](pyinterface.md) +* Random number generator +* [Test and demo infrastructure](testing.md) + + +## Information flow + +### Current architecture + +The current data flow of openage is just to display the raw simulation data. + +![Engine architecture workflow](images/engine_architecture.svg) + +The presenter, simulation, and time subsystems each run in a loop in their own threads. +They are largely decoupled from each other and only communicate via defined interfaces. + +Communication between all subsystems forms a larger *main* loop that encompasses everything +happening in an engine run. It's workflow is roughly like this: + +``` +renderer (window system) -> input -> event system -> simulation -> renderer -> output +``` + +openage does not have simulation steps or *ticks* since everything in the simulation is +event-based and scheduled by time. Therefore, updates between threads should generally work +asynchronously. + +Decoupling allows us to treat some subsystems as optional such as the renderer and input +system (basically everything from the presenter). + + +### Goal architecture + +The goal architecture extends the current workflow by subsystems for networking and +scripting: + +![Goal architecture workflow](images/engine_target_architecture.svg) + +Both of these are supposed to be decoupled and optional. The current architecture can be extended +by adding the missing components in between. + +Networking forwards the relevant events and simulation parameters during multiplayer. +We will have a single authoritative server that is also running the simulation asynchronously. +Each client then receives the data visible for it. + +Scripting extends the event system with external sources targets for events. Most +scripting should be integrated using event logic. + +The new workflow would then look something like this: + +``` + ---------> scripting + | ^ + | | + v v +renderer (window system) -> input -> event system -> simulation -> renderer -> output + ^ ^ + | | + | v + ---------> network +``` diff --git a/doc/code/converter/architecture_overview.md b/doc/code/converter/architecture_overview.md index a1f57917b6..9247952246 100644 --- a/doc/code/converter/architecture_overview.md +++ b/doc/code/converter/architecture_overview.md @@ -2,6 +2,14 @@ This document describes the code architecture of the openage converter module. +1. [Design Principles](#design-principles) + 1. [Value Object](#value-object) + 2. [Entity Object](#entity-object) + 3. [Service](#service) + 4. [Processor](#processor) + 5. [Tool](#tool) + + ## Design Principles Our converter uses hierarchical multi-layered object-oriented code principles similar to those found in diff --git a/doc/code/converter/workflow.md b/doc/code/converter/workflow.md index 427be6052c..5ddd2db621 100644 --- a/doc/code/converter/workflow.md +++ b/doc/code/converter/workflow.md @@ -8,6 +8,17 @@ must test with all supported version when you add a feature. ![workflow structogram](images/workflow.svg) +1. [Game and Version detection](#game-and-version-detection) +2. [Mounting](#mounting) +3. [Reader](#reader) + 1. [Game Data](#game-data) +4. [Processor](#processor) + 1. [Preprocessing](#preprocessing) + 2. [Grouping/Linking](#groupinglinking) + 3. [Mapping](#mapping) +5. [Exporter](#exporter) + + ## Game and Version detection The conversion process starts with determining the game version. Users diff --git a/doc/code/coordinate-systems.md b/doc/code/coordinate-systems.md index 284575f1db..c537074a1e 100644 --- a/doc/code/coordinate-systems.md +++ b/doc/code/coordinate-systems.md @@ -205,7 +205,7 @@ viewport --> normalized device space (Eigen::Vector2f) The translations make use of current coordinate state (e.g. scroll position, stored in `CoordManager`) and additional infos to solve -degrees of freedom (see [below](#Parameters)). +degrees of freedom (see [below](#parameters)). * `input` -> `viewport`: just flip the y axis diff --git a/doc/code/curves.md b/doc/code/curves.md new file mode 100644 index 0000000000..2ead4a8c77 --- /dev/null +++ b/doc/code/curves.md @@ -0,0 +1,223 @@ +# Curves + +*Curves* are data structures that manage changes to data over time. More precisely, +they do not only store data but time-value pairs (keyframes) that allow the retrieval +of a curve data value for any point in time. + +Curves are an integral part of openage's event-based game simulation. + +1. [Motivation](#motivation) +2. [Architecture](#architecture) +3. [Curve Types](#curve-types) + 1. [Primitive](#primitive) + 1. [Common Operations](#common-operations) + 2. [Discrete](#discrete) + 3. [Continuous](#continuous) + 4. [Segmented](#segmented) + 2. [Container](#container) + 1. [Queue](#queue) + 2. [Unordered Map](#unordered-map) + + +## Motivation + +The openage curve structures are inspired by a [similar implementation](https://www.forrestthewoods.com/blog/tech_of_planetary_annihilation_chrono_cam/#.lmxbu3vld) from the game Planetary Annihilation. + +Curves intend to solve synchronicity problems in games. In traditional implementations +like lockstep, data is changed incrementally in regular intervals (ticks). Keeping +these changes and the overall gamestate consistent/in sync over network or across threads +is very important, as one missing change can result in a desync of the entire simulation. +Recovering from a desync can also be very hard. + +In comparison, simulation with curves allows both async operations and an easier recovery +from desync states. Data is not changed incrementally but is instead calculated using +*keyframe interpolation*. In other words, changes to data are treated as keyframes on +a timeline with in-between values being interpolated from adjacent keyframes. + +![Curve keyframes example](images/continuous_curve.png) + +Additionally, curves cannot only access values for the current simulation time but also for +any past or even future times. Keyframes can also be inserted for any point in time without +directly invalidating the state, making curves more reliable in async scenarios (although +resolving dependencies for keyframes in the past can still be challenging). + +The usage of curves has a few downsides though. They are less space efficient due to the +keyframe storage, interpolation are more costly more costly than incremental changes, and +their integration is more complex than the usage of simpler data structures. However, in +situations where operations are predictable, long-lasting, and easy to calculate - which +is the case for most RTS games - the positives may outweigh the downsides. + +## Architecture + +![Curve classes hierarchy UML](images/curve_classes_uml.svg) + +openage provides several curve types with different interpolation behaviour that each have +their specific use case. Primitive data types are covered by the `BaseCurve` interface +and its derivates of which the `Discrete`, `Continuous`, and `Segmented` are the practically +usable types. For containers, there are classes for `Queue` and `UnorderedMap` available. +All curve types are templated, so that they can store any type of value (with some constraints). +The usable types are explained in more detail in the [Curve Types](#curve-types) section. + +Keyframes are implemented as time-value pairs by the `Keyframe` class. `KeyframeContainer` +is used by all curves to manage their keyframe storage. It also provides functionality to +efficiently access and insert keyframes as wel as sorting them by time. For the time +type, the [simulation time type](/doc/code/time.md) from the `openage::time` namespace is +used. + +It should be noted that curves are not useful in every situation as keyframe insertion, +interpolation, and searching keyframes based on time create significant overhead. Curves +should be used for variables or members where + +* data values must be tracked over time (e.g. HP of a game entity), or +* data values are not modified/read very often (e.g. not every frame), or +* data values are supposed to be sent over the network. + +This is usually the case for all game data in [game entity components](/doc/code/game_simulation/components.md) +inside the game simulation. + +Curves should generally not be used for variables or members where + +* data values are not tracked over time (e.g. for temporary variables), or +* data values are modified/read very often (e.g. in the rendering loop), or +* data values don't affect the simulation state (e.g. visual settings). + + +## Curve Types + +This section provides an overview over the available curves types. + +### Primitive + +![Primitive curve types UML](images/primitive_curves_uml.svg) + +Primitive curves are intended for members with single value types. These include, for example, +the primitive C++ types (e.g. `int`, `float`, `std::string`), simple structs and data classes, +and shared pointers. + +On contruction of a primitive curve object, a keyframe with time `t = time::time_t::min_value()` +and the value's type is instanciated with its default constructor. This is done to ensure that for any +requested time `t`, there is always a valid value to be returned. This mirrors the expected +behaviour from declaring primitive values in C++ where members may be auto-initialized without +explicit assignment to a default value. The default value for curves can also be explicitely +assigned in the constructor. Types that don't have a default constructor require that a +default value is passed to the curve constructor. + +`BaseCurve` objects can be targeted by or trigger events from the [event system](/doc/code/event_system.md). +As a consequence, curves are not copy constructable as they require a unique ID for +event management. However, it is possible to copy the keyframes of one curve to +the other using the `sync(..)` method. `sync(..)` also works for curves with different +values types if a converter function from one value type to the other is supplied. + +#### Common Operations + +All primitive curves support the following operations. They may work slightly different +for specific curve types. + +**Read** + +Read operations retrieve values for a specific point in time. + +| Method | Description | +| --------------- | ----------------------------------------------------------- | +| `get(t)` | Get (interpolated) value at time `t` | +| `frame(t)` | Get the previous keyframe (time and value) before or at `t` | +| `next_frame(t)` | Get the next keyframe (time and value) after `t` | + +**Modify** + +Modify operations insert values for a specific point in time. + +| Method | Description | +| ----------------------- | --------------------------------------------------------------------------------- | +| `set_insert(t, value)` | Insert a new keyframe value at time `t` | +| `set_last(t, value)` | Insert a new keyframe value at time `t`; delete all keyframes after time `t` | +| `set_replace(t, value)` | Insert a new keyframe value at time `t`; remove all other keyframes with time `t` | + +**Copy** + +Copy operations transfer keyframes from one curve to another. + +| Method | Description | +| ---------------- | ------------------------------------------------------------------------------------------------ | +| `sync(Curve, t)` | Replace all keyframes from self after time `t` with keyframes from source `Curve` after time `t` | + + +#### Discrete + +![Discrete curve function example](images/discrete_curve.png) + +Discrete curves implement **constant interpolation** between keyframes. This means +that the value returned by `get(t)` is always equal to the value of the previous +keyframe. + +Discrete curves should be used for values that only change at specific points in time, +e.g. for the health of a game entity. + + +#### Continuous + +![Continuous curve function example](images/continuous_curve.png) + +Continuous curves implement **linear interpolation** between keyframes. This means +that the value returned by `get(t)` is calculated from the value difference +between the keyframes before and after `t`. If there is no keyframe after `t`, +the value of the previous keyframe is used (like on discrete curves). + +Value types on continuous curves need to implement methods for the `operator*(..)` and +`operator-(..)` operations to support linear interpolation. In particular, `operator*(..)` +must support multiplication with `time::time_t` and `operator-(..)` must support +substraction for values of the same type. + +Continuous curves do not allow jumps between keyframe values (hence "continuous"). +Therefore, there cannot be two keyframes inserted for the same time `t`. + +Continuous curves should be used for values that change gradually over time, +e.g. a game entity's position or the construction progress of a building. + + +#### Segmented + +![Segmented curve function example](images/segmented_curve.png) + +Segmented curves implement **linear interpolation** between keyframes and additionally +allow jumps between keyframe values. As with continuous curves, the value returned by `get(t)` +is calculated from the value difference between the keyframes before and after `t`. + +Jumps are inserted using the special methods `set_insert_jump(..)` and `set_last_jump(..)`: + +| Method | Description | +| ------------------------------------ | --------------------------------------------------------------------------------- | +| `set_insert_jump(t, value1, value2)` | Insert a two new keyframes at time `t`: `(t, value1)` and `(t, value2)` | +| `set_last_jump(t, value1, value2)` | Insert a two new keyframes at time `t` like above; delete all keyframes after `t` | + +Segmented curves should be used for values that change gradually but are not on +connected intervals. Typically, this are values that wrap around at some point, +e.g. angles between 0 and 360 degrees. + + +### Container + +Container curves are intended for storing changes to collections and containers. +The currently supported containers are `Queue` and `UnorderedMap`. + +The most important distinction between regular C++ containers and curve containers +is that curve containers keep track of when modifications happen and what changes +to an element are made. Deleting elements also does not erase elements from memory. +Instead, they are simply hidden for requests for time `t1` after the deletion time `t2` if +`t1 > t2`. + + +#### Queue + +Queue curve containers store elements in first-in-first-out (FIFO) insertion order +while additionally keeping track of element insertion time. Requests for the front element +at time `t` will return the element that is in front of the queue at that time. +The queue can also be iterated over for a specific time `t` which allows access to +all elements that were in the queue at time `t`. + +#### Unordered Map + +Unordered map curve containers store key-value pairs while additionally keeping +track of element insertion time. Requests for a key `k` at time `t` will return the value +of `k` at that time. The unordered map can also be iterated over for a specific time `t` which +allows access to all key-value pairs that were in the map at time `t`. diff --git a/doc/code/event_system.md b/doc/code/event_system.md new file mode 100644 index 0000000000..762583df3f --- /dev/null +++ b/doc/code/event_system.md @@ -0,0 +1,111 @@ +# Event System + +Game simulation in openage is event-driven. The internal event system +manages the creation, scheduling, and execution of these events. + +1. [Architecture](#architecture) +2. [Event Handler Setup](#event-handler-setup) +3. [Event Instances](#event-instances) +4. [Triggering/Targeting Events](#triggeringtargeting-events) +5. [Canceling Events](#canceling-events) + + +## Architecture + +![event system UML](images/event_classes_uml.svg) + +The central component of the event system is the *event loop* (`EventLoop`). It is +the main point of interaction between the game simulation logic and the event system. +New events (`Event` instances) are added via the `create_event(..)` method and scheduled based on the +configuration of the associated *[event handler](#event-handler-setup)* (`EventHandler`). +Internally, the event is stored inside an *event queue* (`EventQueue`) instance +sorts the events by invoke time. + +Events are executed by passing the current [simulation time](time.md) to the +event loop's `reach_time(..)` method. This executes all not-yet-executed events +until the given target time stamp + +``` +t_old < t_e <= t_cur +``` + +where `t_cur` is the current simulation time, `t_old` is the last time `reach_time(..)` was +called, and `t_e` is the event's scheduled invoke time. Events are executed in order of +earliest to latest invoke time. During execution, events may trigger the rescheduling of +other events if there are dependencies between the events. + +Both the creation and execution of events require passing a `State` object that functions +as a persistant global storage for values that are not linked to a specific event executions. +In practice, `State` is primarily used to pass the state of the [game simulation](/doc/code/game_simulation/) +to the event system via an object of the derived `GameState` class. This object allows +access to the indexing structures of the current game that can be used to retrieve +the available game entities, for example. + + +## Event Handler Setup + +Event effects on the game simulation are implemented by *event handlers*. Event handlers +are attached to the event on creation and are invoked when the event is executed by the event +loop. They are also used for (re-)scheduling the invocation time of the event. + +Event handlers are implemented as derivatives of the `EventHandler` class. Event handlers +must implement 3 methods: + +* `invoke(..)`: Called by the event loop when the event is executed. +* `predict_invoke_time(..)`: Called when the event handler shall determine a new invocation time of an event, + i.e. (re)place it on the event queue +* `setup_event(..)`: Sets up dependencies during creation of the event. + +Additionally, event handlers require a unique ID (defined as a string) as well as +a *trigger type* which defines under which circumstances an event is executed. +These parameters can be defined at runtime when instantiating the event handler. + +New events require that an event handler object is attached during creation. This +can be done by passing the event handler object to the `create_event(..)` method. +If the event handler should be reusable, it can also be registered on the event loop +via the `add_event_handler(..)` method. When calling `create_event(..)` on the event +loop to create a new event, the event handler can then be referenced by a unique +ID string. + + +## Event Instances + +When calling `create_event(..)` on the event loop, an `Event` instance is returned which +allows access to the configuration parameters of the event. Event instances store +references to: + +* **Event target**: Entity targeted by the event, i.e. the event entity that the event effects should be applied on. Implemented as a weak reference to let the target expire. +* **Event handler**: Event handler object used for rescheduling and executing the event. +* **Invoke time**: Determines when the event is executed. +* **Time of last change**: Time of the last change to invocation time. Used for rescheduling the event. +* **Event payload**: Optional map of parameters passed to the event handler on invocation. + +These parameters may be changed after creating the event. Alternatively, it is possible to +[cancel](#canceling-events) the event and create a new event with the updated parameters. + + +## Triggering/Targeting Events + +To allow an event to modify an object in its invocation, the object's class must be +a derivative of the `EventEntity` class. By inheriting from `EventEntity`, a class can +be targeted by events, trigger or change events, or both. + +An event target is passed during the creation of an event (i.e. in `create_event(..)`) +and later when executing the event via the event handler's `invoke(..)` method. Events +can only have one target at a time. + +`EventEntity` derivatives may also be used to trigger or reschedule the invocation of events. To do this, +the event has to be added as a dependent for the event entity using the `add_dependent(..)` +method of `EventEntity`. Calling the `changes(..)` method of `EventEntity` will then result +in a rescheduling of the event in the next iteration of the event loop. + + +## Canceling Events + +Events are automatically canceled if their targeted event entity has expired, i.e. it has been deleted +from memory. To accomplish this target references are implemented using `std::weak_ptr` +which are checked for expiration before event execution. + +Manually canceling events can also be done by calling `cancel(..)` on an `Event` instance. +In the current implementation, this change is effective immediately, even if the provided +reference time is in the future. diff --git a/doc/code/game_simulation/README.md b/doc/code/game_simulation/README.md new file mode 100644 index 0000000000..0f8910a36b --- /dev/null +++ b/doc/code/game_simulation/README.md @@ -0,0 +1,53 @@ +# Game Simulation + +*Game simulation* is the engine subsystem that implements game mechanics and data structures +used for gameplay. + +The subsystem only contains components that are strictly necessary to simulate a game. Everything else, +e.g. the [input system](/doc/code/input/), [rendering](/doc/code/renderer/), +networking or scripting, are handled as separate subsystems. + +1. [Architecture](#architecture) +2. [Workflow](#workflow) + + +## Architecture + +![Game simulation overview UML](images/simulation_uml.svg) + +The game simulation is instantiated from the main thread via a `GameSimulation` object. +This object controls the game loop, the current game session, and other simulation +parameters necessary to run the game. + +The `Game` class represents a game session. Its instances store information about the +gamestate via a `GameState` object which includes references to objects inside the game world +(e.g. players or game entities). It also contains gameplay settings for the current session. + +"Physical" objects in the game world are represented by `Terrain` and `GameEntity`. `Terrain` +is used to model the underlying map terrain, while [`GameEntity`](game_entity.md) +is used for every type of world object (e.g. units, buildings, trees, resources, ambience). + + +## Workflow + +To initiate a game, a `GameSimulation` object must be created. This is usually done by +the `Engine` object in the main thread. On initialization, the game simulation automatically sets up + several subcomponents required for running the game such as: + +* [Event loop](/doc/code/event_system.md) for executing events +* Entity factory for creating game entities +* Mod manager for detecting/loading [openage modpacks](/doc/media/openage/modpacks.md) + +After the `GameSimulation` object is initialized, modpacks that should be loaded in +the game session can be passed via the `set_modpacks(..)` method. + +The game simulation loop is started using the `run()` method of the `GameSimulation` object. +`run()` should be run in its own thread with no other looping subsystems present. Before +the simulation loop is entered, the simulation sets up a new game session (as a `Game` +object). This loads the modpacks specified in the `set_modpacks(..)` method into the +session. + +The logic of the simulation loop is quite simple as most of the execution happens in the +[event system](/doc/code/event_system.md). In every loop iteration, the current simulation time is fetched from the +[time subsystem](/doc/code/time.md). This time value is then passed to the simulation's +event loop which executes all events queued until this time. diff --git a/doc/code/game_simulation/activity.md b/doc/code/game_simulation/activity.md new file mode 100644 index 0000000000..0b84864fe9 --- /dev/null +++ b/doc/code/game_simulation/activity.md @@ -0,0 +1,58 @@ +# Activity Control Flow + +The *activity control flow* is openage's method to make complex game entity behaviour +configurable. + +1. [Motivation](#motivation) +2. [Architecture](#architecture) +3. [Node Types](#node-types) + + +## Motivation + +Unit behaviour in RTS games can get very complex. In many cases, units are not +just controlled by commands but other automated mechanisms, e.g. attacking enemy +units in the line of sight. Furthermore, commands do not always translate to a single +well-defined action. For example, an attack command usually results in a move action +and a subsequent attack action. Some commands may even execute different actions depending +on context. + +All this means that we cannot view the control flow of a unit as a simple mapping of +command to action as is done in other games. Instead, we have to treat unit behaviour +as a complex chain of actions with branching paths, wait states for events, triggers +and feedback loops. Unless we want every command to be a hardcoded action chain, managing +this complexity is key to making unit behaviour configurable. + + +## Architecture + +Game entity control flows in openage are modelled as directed node graph, so-called *activities*. +Nodes in the graph correspond to actions that execute for the game entity or conditional queries +and event triggers that indicate which path to take next. By traversing the node graph along +its paths, the game entities actions are determined. The currently visited node in the graph +corresponds to the current action of a unit. + +Activities are reusable, i.e. they are intended to be shared by many game entities Usually, +all game entities of the same type should share the same behaviour, so they get assigned +the same activity node graph. + +An activity can also be represented visually like this: + +![graph example](images/activity_graph.svg) + +The design is heavily inpired by the [BPMN](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) +representation. You don't need to know BPMN to understand the activity control flow because +we explain everything important about the graphs in our documentation. However, +you can use available [BPMN tools](https://bpmn.io/) to draw activity node graphs. + +## Node Types + + +| Type | Inputs | Outputs | Description | +| ---------------- | ------ | ------- | ------------------------- | +| `START` | 0 | 1 | Start of activity | +| `END` | 1 | 0 | End of activity | +| `TASK_SYSTEM` | 1 | 1 | Run built-in system | +| `TASK_CUSTOM` | 1 | 1 | Run custom function | +| `XOR_EVENT_GATE` | 1 | 1+ | Wait for event and branch | +| `XOR_GATE` | 1 | 1+ | Branch on condition | diff --git a/doc/code/game_simulation/components.md b/doc/code/game_simulation/components.md new file mode 100644 index 0000000000..dc385a368b --- /dev/null +++ b/doc/code/game_simulation/components.md @@ -0,0 +1,130 @@ +# Built-in Components + +Overview of the built-in game entity components in the game simulation. + +1. [Internal](#internal) + 1. [Activity](#activity) + 2. [CommandQueue](#commandqueue) + 3. [Ownership](#ownership) + 4. [Position](#position) +2. [API](#api) + 1. [Idle](#idle) + 2. [Live](#live) + 3. [Move](#move) + 4. [Turn](#turn) + + +## Internal + +Internal components do not have a corresponding nyan API object and thus only +store runtime data. + +### Activity + +![Activity Component UML](images/component_activity_uml.svg) + +The `Activity` component stores a reference to the top-level activity for the +game entity. Essentially, this gives access to the entire activity node graph +used by the entity. + +Additionally, the current activity state is stored on a discrete curve that +contains the last visited node. + +`Activity` also stores the handles of events initiated by the activity system +for advancing to the next node. Once the next node is visited, these events +should be canceled via the `cancel_events(..)` method. + + +### CommandQueue + +![CommandQueue Component UML](images/component_activity_uml.svg) + +The `CommandQueue` component stores commands for the game entity in a [queue curve container](/doc/code/curves.md#queue). + +Commands in the queue use `Command` class derivatives which specify a command type +and payload for the command. + + +### Ownership + +![Ownership Component UML](images/component_ownership_uml.svg) + +The `Ownership` component stores the ID of the player who owns the game entity. + + +### Position + +![Position Component UML](images/component_position_uml.svg) + +The `Position` component stores the location and direction of the game entity +inside the game world. + +The 3D position of the game entity is stored on a continuous curve with value type +`phys3`. + +Directions are stored as angles relative to the camera vector using clock-wise +rotation. Here are some example values for reference to see how that works in +practice: + +| Angle (degrees) | Direction | +| --------------- | --------------------- | +| 0 | look towards camera | +| 90 | look left | +| 180 | look away from camera | +| 270 | look right | + +Angles are stored on a segmented curve. + +## API + +API components have a corresponding nyan API object of type `engine.ability.Ability` defined +in the nyan API. This API object can be retrieved using the `get_ability(..)` method of the +component. + +### Idle + +![Idle Component UML](images/component_idle_uml.svg) + +**nyan API object:** [`engine.ability.type.Idle`](/doc/nyan/api_reference/reference_ability.md#abilitytypeidle) + +The `Idle` component represents the ingame "idle" state of the game entity, i.e. when +it is doing nothing. + +The component stores no runtime data. + + +### Live + +![Live Component UML](images/component_live_uml.svg) + +**nyan API object:** [`engine.ability.type.Live`](/doc/nyan/api_reference/reference_ability.md#abilitytypelive) + +The `Live` component represents the game entity's ability to have attributes (e.g. health). + +An attribute's maximum limit is stored in the nyan API object, while +the game entity's current attribute values are stored in the component +on a discrete curve. + + +### Move + +![Move Component UML](images/component_move_uml.svg) + +**nyan API object:** [`engine.ability.type.Move`](/doc/nyan/api_reference/reference_ability.md#abilitytypemove) + +The `Move` component represents the game entity's ability to move in the game world. +This also allows moving the game entity with move commands. + +The component stores no runtime data. + + +### Turn + +![Turn Component UML](images/component_turn_uml.svg) + +**nyan API object:** [`engine.ability.type.Turn`](/doc/nyan/api_reference/reference_ability.md#abilitytypeturn) + +The `Turn` component represents the game entity's ability to change directions in the game world. +Turning is implicitely required for moving but it also works on its own. + +The component stores no runtime data. diff --git a/doc/code/game_simulation/game_entity.md b/doc/code/game_simulation/game_entity.md new file mode 100644 index 0000000000..b511a626a9 --- /dev/null +++ b/doc/code/game_simulation/game_entity.md @@ -0,0 +1,141 @@ +# Game Entity + +Game entities represent objects inside the game world. + +1. [Architecture](#architecture) +2. [Game Entity class](#game-entity-class) +3. [Component Data Storage](#component-data-storage) +4. [Control Flow](#control-flow) + 1. [System](#system) + 2. [Activities](#activities) + 3. [Manager](#manager) + + +## Architecture + +![Game entity UML](images/game_entity_overview.svg) + +Game entity mechanics are structured using the concept of *separation of concerns*. +This means that there is not one single `GameEntity` class that implements all data +and game logic. Instead, data and logic are separated into distinct engine components +that each have a dedicated, clearly-defined purpose. + +Data storage is handled by `Component` objects that manage references to the [nyan](/doc/nyan/nyan.md) +database and store runtime data on [curves](/doc/code/curves.md). Game logic is implemented +in *systems*, which are best described as independent functions that perform a specific action +on an entity. Event handling is done by the `GameEntityManager` which initiates and directs +the entity's individual control flow. + +It should be noted that while the terminology we use here is very similar to names +in the *Entity-Component-System* (ECS) architecture, you shouldn't think of the openage +game simulation as a traditional ECS-driven architecture. We merely use this terminology +because we can't think of anything better (and because we are too lazy to find better names). + + +## Game Entity class + +![Game entity class UML](images/game_entity_uml.svg) + +The `GameEntity` class primarily provides references to the game entity's unique ID, assigned +components, and event handling manager. If the game entity is supposed to be animated, +a [render entity](/doc/code/renderer/level2.md#updating-render-stages-from-the-gamestate) +can also be set. This allows requesting animations for the game entity. + +`GameEntity` follows the principle of *composition over inheritance*. Therefore, capabilities +and attributes of a game entity are defined by the assigned components rather than properties +of its class. The `GameEntity` class is merely a thin wrapper with a reference ID for +a set of components storing the actual data (via `Component` subclasses). Components +of the specific entity can be accessed via the `GameEntity` object's `get_component(..)` method. + + +## Component Data Storage + +For a description of the available components, check the [component reference](components.md). + +![Component class UML](images/component_uml.svg) + +Components are data storage objects for a game entity that also perform the dual role +of signifying what a game entity can do or is depending on their component type. Component +types are usually associated with a subclass of `Component`, e.g. `Move`. For example, assigning +a `Move` component to a game entity signifies that the game entity can perform move +actions during gameplay. Movement data relevant to the game entity is then also stored in this +component object. + +In general, component classes are designed to be atomic, i.e. they don't depend on other +components to be assigned to the game entity. While some components may have a close relationship, +e.g. `Move` and `Position`, it should never be assumed that all components are assigned +when operating on a game entity. + +Persistent game data, i.e. data that is the same in every game like unit stats, is not +managed by the component itself but in the game's [nyan](/doc/nyan/nyan.md) database. The component +only holds a reference to the nyan object associated with the component. Data from nyan +must be fetched via the [openage nyan interface](/doc/nyan/openage-lib.md). +Component types usually have a corresponding nyan object type in the nyan API, e.g. the `Move` +component corresponds to the `engine.ability.type.Move` nyan type. + +Runtime data, i.e. data that changes due to gameplay interactions, is stored on [curves](/doc/code/curves.md) +managed by the component object. Curves are keyframe-based time-value storages that track +changes to the data over time. Components can provide helper methods to interact with +the curve, e.g. `Position` provides `set_position` to insert a new keyframe on its +`position` data curve. + + +## Control Flow + +The control flow is organized into 3 core mechanisms: Systems, activities, and +managers. This again tries to achieve a *separation of concern* design to +make the game logic maintanable and extensible. + +### System + +For a description of the available systems, check the [system reference](systems.md). + +A *system* in openage is basically a function that operates on game entity +components. They are explicitely separated from game entity and component objects +to allow for more flexible implementation. In practice, systems are implemented as static +functions inside the `gamestate::system` namespace. + +Systems are *stateless*, so they don't remember anything about the game entity +components they operate on. If something about the execution state should be remembered, +it needs to be stored in a component. Additionally, system execution is always +immediate. This means that a system never waits for events or for a certain amount +of time. Waiting is handled by the [game entity manager](#manager) and the +[activity control flow](#activities) instead. + +When adding new systems to the engine, interdependencies to other systems should +be avoided at all cost, i.e. a system should never call another system directly. +Exceptions should only be made for direct subsystems implementing subroutines +or to avoid code redundancies. The reasoning behind this is that dependencies +between systems may quickly become unmanageable. + + +### Activities + +![Activity Example](images/activity_graph.svg) + +*Activities* connect systems together in a node graph to describe the overall control flow +for a game entity. In openage, activity node graphs are used to model the complex behaviour +behaviour and action chains of RTS game entities, while also allowing the behaviour to +be as configurable as possible. One could also think of activities as a behaviour graph +where paths are taken based on the inputs a game entity receives. The architecture +of the activity control flow is described in more detail in the +[activity control flow documentation](activity.md). + +A game entity's current activity state is stored in its `Activity` component. This component +holds a reference to the activity node graph used by the entity as well as the +last visited node. This node describes which action/behavioural state the +game entity currently is in. + +Advancement to the next node can be initiated in several ways, depending on the +[node type](activity.md#node-types) of the current node. +It can happen automatically or be triggered by an event. In the latter case, +the event is handled by the `GameEntityManager` which calls an activity *system* +that processes the event to choose the next node. + +![Activity Workflow](images/activity_workflow.png) + + +### Manager + +The game entity listens for events that target the entity and takes the +associated action depending on the event type. diff --git a/doc/code/game_simulation/images/activity_graph.svg b/doc/code/game_simulation/images/activity_graph.svg new file mode 100644 index 0000000000..bf87f779fa --- /dev/null +++ b/doc/code/game_simulation/images/activity_graph.svg @@ -0,0 +1,4 @@ + + + +IdleMoveStartMoveable?Can MoveCan't MoveWait for commandWait for Move to FinishEnd \ No newline at end of file diff --git a/doc/code/game_simulation/images/activity_workflow.png b/doc/code/game_simulation/images/activity_workflow.png new file mode 100644 index 0000000000..188d48d3cc Binary files /dev/null and b/doc/code/game_simulation/images/activity_workflow.png differ diff --git a/doc/code/game_simulation/images/component_activity_uml.svg b/doc/code/game_simulation/images/component_activity_uml.svg new file mode 100644 index 0000000000..c05314eeff --- /dev/null +++ b/doc/code/game_simulation/images/component_activity_uml.svg @@ -0,0 +1,82 @@ + + +NodeActivityActivitystart_activity: Activitynode: curve::Discretescheduled_events: vector<Event>get_start_activity(): Activityget_node(time_t): Nodeset_node(time_t, Node): voidinit(time_t): voidadd_event(Event): voidcancel_events(): void diff --git a/doc/code/game_simulation/images/component_command_queue_uml.svg b/doc/code/game_simulation/images/component_command_queue_uml.svg new file mode 100644 index 0000000000..cabb92d98b --- /dev/null +++ b/doc/code/game_simulation/images/component_command_queue_uml.svg @@ -0,0 +1,51 @@ + + +CommandCommandQueuecommand_queue: curve::Queueadd_command(time_t, Command): voidget_queue(): curve::Queue diff --git a/doc/code/game_simulation/images/component_idle_uml.svg b/doc/code/game_simulation/images/component_idle_uml.svg new file mode 100644 index 0000000000..439a7c39af --- /dev/null +++ b/doc/code/game_simulation/images/component_idle_uml.svg @@ -0,0 +1,25 @@ + + +Idle diff --git a/doc/code/game_simulation/images/component_live_uml.svg b/doc/code/game_simulation/images/component_live_uml.svg new file mode 100644 index 0000000000..b7d47a963e --- /dev/null +++ b/doc/code/game_simulation/images/component_live_uml.svg @@ -0,0 +1,33 @@ + + +Liveattribute_values: curve::UnorderedMapadd_attribute(time_t, fqon_t, curve::Discrete)set_attribute(time_t, fqon_t, int64_t): void diff --git a/doc/code/game_simulation/images/component_move_uml.svg b/doc/code/game_simulation/images/component_move_uml.svg new file mode 100644 index 0000000000..6076927c78 --- /dev/null +++ b/doc/code/game_simulation/images/component_move_uml.svg @@ -0,0 +1,25 @@ + + +Move diff --git a/doc/code/game_simulation/images/component_ownership_uml.svg b/doc/code/game_simulation/images/component_ownership_uml.svg new file mode 100644 index 0000000000..141bd5c7ef --- /dev/null +++ b/doc/code/game_simulation/images/component_ownership_uml.svg @@ -0,0 +1,33 @@ + + +Ownershipowner: curve::Discreteset_owner(time_t, ownership_id_t): voidget_owners(): curve::Discrete diff --git a/doc/code/game_simulation/images/component_position_uml.svg b/doc/code/game_simulation/images/component_position_uml.svg new file mode 100644 index 0000000000..6f090fcb9e --- /dev/null +++ b/doc/code/game_simulation/images/component_position_uml.svg @@ -0,0 +1,39 @@ + + +Positionposition: curve::Continuousangle: curve::Segmentedget_positions(): curve::Continuousget_angles(): curve::Segmentedset_position(time_t, coord::phys3): voidset_angle(time_t, phys_angle_t): void diff --git a/doc/code/game_simulation/images/component_turn_uml.svg b/doc/code/game_simulation/images/component_turn_uml.svg new file mode 100644 index 0000000000..9f06b9f662 --- /dev/null +++ b/doc/code/game_simulation/images/component_turn_uml.svg @@ -0,0 +1,25 @@ + + +Turn diff --git a/doc/code/game_simulation/images/component_uml.svg b/doc/code/game_simulation/images/component_uml.svg new file mode 100644 index 0000000000..06c5c3c74e --- /dev/null +++ b/doc/code/game_simulation/images/component_uml.svg @@ -0,0 +1,170 @@ + + +TurnMoveLiveIdlePositionOwnershipCommandQueueActivity«interface»APIComponent«interface»InternalComponent«interface»Component diff --git a/doc/code/game_simulation/images/game_entity_overview.svg b/doc/code/game_simulation/images/game_entity_overview.svg new file mode 100644 index 0000000000..f57806cd39 --- /dev/null +++ b/doc/code/game_simulation/images/game_entity_overview.svg @@ -0,0 +1,73 @@ + + +systems...GameEntityManagerComponentGameEntity diff --git a/doc/code/game_simulation/images/game_entity_uml.svg b/doc/code/game_simulation/images/game_entity_uml.svg new file mode 100644 index 0000000000..d3a24bdfd6 --- /dev/null +++ b/doc/code/game_simulation/images/game_entity_uml.svg @@ -0,0 +1,94 @@ + + +WorldRenderEntityGameEntityManagerComponentGameEntityid: entity_id_tcomponents: unordered_maprender_entity: WorldRenderEntitymanager: GameEntityManagercopy(): GameEntityget_component(): Componentadd_component(Component): voidhas_component(component_t): boolrender_update(time_t, string): void diff --git a/doc/code/game_simulation/images/simulation_uml.svg b/doc/code/game_simulation/images/simulation_uml.svg new file mode 100644 index 0000000000..36b67458cd --- /dev/null +++ b/doc/code/game_simulation/images/simulation_uml.svg @@ -0,0 +1,134 @@ + + +TimeLoopEventLoopTerrainGameEntityGameStateGameSimulationrunning: boolgame: Gameset_modpacks(vector<string>): voidinit_event_handlers(): voidrun(): voidstart(): voidstop(): voidGame diff --git a/doc/code/game_simulation/images/system_idle.svg b/doc/code/game_simulation/images/system_idle.svg new file mode 100644 index 0000000000..3da9289b05 --- /dev/null +++ b/doc/code/game_simulation/images/system_idle.svg @@ -0,0 +1,28 @@ + + +Idleidle(GameEntity, time_t): time_t diff --git a/doc/code/game_simulation/images/system_move.svg b/doc/code/game_simulation/images/system_move.svg new file mode 100644 index 0000000000..46966a4b4f --- /dev/null +++ b/doc/code/game_simulation/images/system_move.svg @@ -0,0 +1,30 @@ + + +Movemove_default(GameEntity, phys3, time_t): time_tmove_command(GameEntity, time_t): time_t diff --git a/doc/code/game_simulation/systems.md b/doc/code/game_simulation/systems.md new file mode 100644 index 0000000000..61ea2fcf34 --- /dev/null +++ b/doc/code/game_simulation/systems.md @@ -0,0 +1,36 @@ +# Built-in Systems + +Overview of the built-in systems in the game simulation. + +1. [Idle](#idle) +2. [Move](#move) + + +## Idle + +![Idle systems class UML](images/system_idle.svg) + +Handles idle actions for game entities. + +`idle(..)` updates the animation of the game entity. This requires the game +entity to have the `Idle` component. The function returns a time of 0 since +no actionsconsuming simulation time are taken. + + +## Move + +![Move systems class UML](images/system_move.svg) + +Handles movement actions for game entities. + +`move_default(..)` moves a game entity to the new position specified in the function +call. This requires the game entity to have the `Move` and `Turn` components. +Waypoints for the exact path are fetched from the pathfinder. +For every straight path between waypoints, the game entity is turned first, then +moved (same as in *Age of Empires*). If an animation is available for the `Move` +component, this animation is forwarded as the game entity's active animation to the +renderer. The function returns the cumulative time of all turn and movement actions +initiated by this function. + +`move_command(..)` processes the payload from a move *command* to call `move_default(..)` +with the payload parameters. diff --git a/doc/code/gui.md b/doc/code/gui.md index 17196b4b09..6c548c2b65 100644 --- a/doc/code/gui.md +++ b/doc/code/gui.md @@ -1,5 +1,7 @@ # QtQuick-based Graphical User Interface +**Important Notice**: This document is outdated and subject to change. + ## Using Qt Creator Integrated Development Environment (IDE) See [Qt Creator IDE](/doc/ide/qt_creator.md). @@ -30,7 +32,7 @@ Example: ## Exposing components to the GUI layer Components are adapted by writing QObject counterparts for them. -Look for the examples in the `libopenage/gui` directory. +Look for the examples in the `libopenage/renderer/gui` directory. There is a property-based approach and a model-based extension to it. @@ -40,7 +42,7 @@ Let's suppose we have a class `ResourceAmount` in `libopenage/economy`, and we w In order to do that: -1. A class `ResourceAmountLink` must be created in the `libopenage/gui`. +1. A class `ResourceAmountLink` must be created in the `libopenage/renderer/gui`. It must derive from `GuiItemQObject` and `GuiItem`. It must be registered in the QML type system using a usual Qt approach: ```cpp @@ -85,7 +87,7 @@ this->setv("player_radius", 10); this->set_csv("player_names", std::vector{"name1", "name2"}); ``` -3. A class `GeneratorParametersLink` must be created in the `libopenage/gui`. +3. A class `GeneratorParametersLink` must be created in the `libopenage/renderer/gui`. It must derive from `QObject` and `GuiItemListModel`. It must be registered in the QML type system using a usual Qt approach: ```cpp @@ -166,11 +168,11 @@ void EditorModeLink::on_core_adopted() { ### Including headers -The files that are outside of the `libopenage/gui/` are allowed to include only the headers from the `libopenage/gui/guisys/public` and `libopenage/gui/integration/public`. +The files that are outside of the `libopenage/renderer/gui/` are allowed to include only the headers from the `libopenage/renderer/gui/guisys/public` and `libopenage/renderer/gui/integration/public`. ## Directory structure -The subsystem resides in the `libopenage/gui`. +The subsystem resides in the `libopenage/renderer/gui`. * random files in the directory - bindings for the game components * `guisys/` - non-openage-specific part diff --git a/doc/code/images/component_classes.uxf b/doc/code/images/component_classes.uxf new file mode 100644 index 0000000000..7329e11d96 --- /dev/null +++ b/doc/code/images/component_classes.uxf @@ -0,0 +1,250 @@ + + + // Uncomment the following line to change the fontsize and font: +fontsize=14 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 15 + + UMLClass + + 720 + 435 + 420 + 240 + + **CommandQueue** +-- +command_queue: curve::Queue +-- +add_command(time_t, Command): void +get_queue(): curve::Queue + + + + Text + + 660 + 0 + 540 + 105 + + **Components** +style=wordwrap +fontsize=20 + + + + UMLClass + + 1260 + 435 + 195 + 90 + + +**Command** + + + + Relation + + 1125 + 465 + 165 + 45 + + lt=<. + 90.0;10.0;10.0;10.0 + + + UMLClass + + 720 + 75 + 420 + 300 + + **Activity** +-- +start_activity: Activity +node: curve::Discrete +scheduled_events: vector<Event> +-- +get_start_activity(): Activity +get_node(time_t): Node +set_node(time_t, Node): void +init(time_t): void +add_event(Event): void +cancel_events(): void + + + + + UMLClass + + 1260 + 75 + 195 + 90 + + +**Activity** + + + + Relation + + 1125 + 105 + 165 + 45 + + lt=<. + 90.0;10.0;10.0;10.0 + + + UMLClass + + 1260 + 210 + 195 + 90 + + +**Node** + + + + Relation + + 1125 + 240 + 165 + 45 + + lt=<. + 90.0;10.0;10.0;10.0 + + + Relation + + 1350 + 150 + 45 + 90 + + lt=<. + 10.0;40.0;10.0;10.0 + + + UMLClass + + 720 + 720 + 420 + 240 + + **Ownership** +-- +owner: curve::Discrete +-- +set_owner(time_t, ownership_id_t): void +get_owners(): curve::Discrete + + + + UMLClass + + 720 + 1020 + 420 + 240 + + **Position** +-- +position: curve::Continuous +angle: curve::Segmented +-- +get_positions(): curve::Continuous +get_angles(): curve::Segmented +set_position(time_t, coord::phys3): void +set_angle(time_t, phys_angle_t): void + + + + UMLClass + + 855 + 1305 + 165 + 90 + + +**Idle** + + + + + UMLClass + + 720 + 1455 + 465 + 240 + + **Live** +-- +attribute_values: curve::UnorderedMap +-- +add_attribute(time_t, fqon_t, curve::Discrete) +set_attribute(time_t, fqon_t, int64_t): void + + + + UMLClass + + 855 + 1740 + 165 + 90 + + +**Move** + + + + + UMLClass + + 855 + 1890 + 165 + 90 + + +**Turn** + + + + diff --git a/doc/code/images/continuous_curve.ggb b/doc/code/images/continuous_curve.ggb new file mode 100644 index 0000000000..e55f6ee926 Binary files /dev/null and b/doc/code/images/continuous_curve.ggb differ diff --git a/doc/code/images/continuous_curve.png b/doc/code/images/continuous_curve.png new file mode 100644 index 0000000000..a7bc237111 Binary files /dev/null and b/doc/code/images/continuous_curve.png differ diff --git a/doc/code/images/curve_classes_uml.svg b/doc/code/images/curve_classes_uml.svg new file mode 100644 index 0000000000..95295b7c13 --- /dev/null +++ b/doc/code/images/curve_classes_uml.svg @@ -0,0 +1,149 @@ + + +UnorderedMapQueueKeyframeKeyframeContainerSegmentedContinuous«interface»InterpolatedDiscrete«interface»BaseCurve diff --git a/doc/code/images/curves_classes.uxf b/doc/code/images/curves_classes.uxf new file mode 100644 index 0000000000..351ad7255e --- /dev/null +++ b/doc/code/images/curves_classes.uxf @@ -0,0 +1,418 @@ + + + // Uncomment the following line to change the fontsize and font: +fontsize=14 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 15 + + UMLClass + + 510 + 120 + 195 + 90 + + <<interface>> +**BaseCurve** +bg=pink + + + + + UMLClass + + 390 + 510 + 180 + 90 + + +**Discrete** +bg=green + + + + UMLClass + + 720 + 315 + 180 + 90 + + <<interface>> +**Interpolated** +bg=pink + + + + + UMLClass + + 615 + 510 + 180 + 90 + + +**Continuous** +bg=green + + + + + UMLClass + + 840 + 510 + 165 + 90 + + +**Segmented** +bg=green + + + + + Relation + + 510 + 195 + 45 + 345 + + lt=<<- + 10.0;10.0;10.0;210.0 + + + Relation + + 660 + 195 + 90 + 195 + + lt=<<- + 10.0;10.0;10.0;110.0;40.0;110.0 + + + Relation + + 750 + 390 + 45 + 150 + + lt=<<- + 10.0;10.0;10.0;80.0 + + + Relation + + 855 + 390 + 45 + 150 + + lt=<<- + 10.0;10.0;10.0;80.0 + + + UMLClass + + 930 + 120 + 255 + 90 + + +**KeyframeContainer** + + + + + Relation + + 690 + 150 + 270 + 45 + + lt=<. + 160.0;10.0;10.0;10.0 + + + UMLClass + + 1275 + 120 + 150 + 90 + + +**Keyframe** + + + + + Relation + + 1170 + 150 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + + UMLClass + + 1050 + 510 + 165 + 90 + + +**Queue** +bg=green + + + + + UMLClass + + 1260 + 510 + 195 + 90 + + +**UnorderedMap** +bg=green + + + + + Text + + 300 + 0 + 375 + 105 + + **Overview** +style=wordwrap +fontsize=20 + + + + Text + + 315 + 675 + 375 + 105 + + **Primitive Curves** +style=wordwrap +fontsize=20 + + + + UMLClass + + 330 + 765 + 360 + 270 + + <<interface>> +**BaseCurve<T>** +bg=pink +-- +/get(time_t): T/ +frame(time_t): pair<time_t, T> +next_frame(time_t): pair<time_t, T> +set_insert(time_t, T): void +set_last(time_t, T): void +set_replace(time_t, T): void +sync(BaseCurve<T>, time_t): void + + + + UMLClass + + 270 + 1290 + 270 + 135 + + **Discrete** +bg=green +-- +get(time_t): T +get_time(time_t): T +get_previous(time_t): T + + + + UMLClass + + 765 + 1095 + 255 + 120 + + <<interface>> +**Interpolated** +bg=pink +-- +get(time_t): T + + + + UMLClass + + 600 + 1290 + 270 + 135 + + **Continuous** +bg=green +-- +set_insert(time_t, T): void +set_last(time_t, T): void + + + + UMLClass + + 930 + 1290 + 345 + 135 + + **Segmented** +bg=green +-- +set_insert_jump(time_t, T, T): void +set_last_jump(time_t, T, T): void + + + + + Relation + + 420 + 1020 + 45 + 300 + + lt=<<- + 10.0;10.0;10.0;180.0 + + + Relation + + 615 + 1020 + 180 + 150 + + lt=<<- + 10.0;10.0;10.0;80.0;100.0;80.0 + + + Relation + + 780 + 1200 + 45 + 120 + + lt=<<- + 10.0;10.0;10.0;60.0 + + + Relation + + 975 + 1200 + 45 + 120 + + lt=<<- + 10.0;10.0;10.0;60.0 + + + UMLClass + + 915 + 750 + 255 + 90 + + +**KeyframeContainer** + + + + + Relation + + 675 + 780 + 270 + 45 + + lt=<. + 160.0;10.0;10.0;10.0 + + + UMLClass + + 1260 + 750 + 150 + 90 + + +**Keyframe** + + + + + Relation + + 1155 + 780 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + diff --git a/doc/code/images/discrete_curve.ggb b/doc/code/images/discrete_curve.ggb new file mode 100644 index 0000000000..c49ddd65c6 Binary files /dev/null and b/doc/code/images/discrete_curve.ggb differ diff --git a/doc/code/images/discrete_curve.png b/doc/code/images/discrete_curve.png new file mode 100644 index 0000000000..e3a27942a8 Binary files /dev/null and b/doc/code/images/discrete_curve.png differ diff --git a/doc/code/images/engine_architecture.svg b/doc/code/images/engine_architecture.svg new file mode 100644 index 0000000000..c24199612c --- /dev/null +++ b/doc/code/images/engine_architecture.svg @@ -0,0 +1,269 @@ + + +Current timeAnimation requestsCurrent timeScheduled eventsCurrent timeEntity updatesInput eventsMouse eventsKey/Mouse eventsClockTimePresenterSimulationEventLoopGUIRendererInput diff --git a/doc/code/images/engine_architecture.uxf b/doc/code/images/engine_architecture.uxf new file mode 100644 index 0000000000..35b2297706 --- /dev/null +++ b/doc/code/images/engine_architecture.uxf @@ -0,0 +1,1092 @@ + + + // Uncomment the following line to change the fontsize and font: +fontsize=14 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 15 + + UMLClass + + 690 + 345 + 195 + 90 + + +**Input** + + + + UMLClass + + 1020 + 180 + 195 + 90 + + +**Renderer** + + + + UMLClass + + 690 + 90 + 195 + 90 + + +**GUI** + + + + UMLClass + + 1035 + 600 + 195 + 90 + + +**EventLoop** + + + + UMLClass + + 1275 + 405 + 195 + 90 + + +**Simulation** + + + + Text + + 525 + 15 + 195 + 60 + + **Presenter** +fontsize=20 + +style=wordwrap + + + + Relation + + 510 + 0 + 780 + 45 + + lt=. + 10.0;10.0;500.0;10.0 + + + Relation + + 510 + 0 + 45 + 600 + + lt=. + 10.0;380.0;10.0;10.0 + + + Relation + + 510 + 555 + 450 + 45 + + lt=. + 280.0;10.0;10.0;10.0 + + + Relation + + 1245 + 0 + 45 + 360 + + lt=. + 10.0;220.0;10.0;10.0 + + + Relation + + 915 + 315 + 375 + 285 + + lt=. + 10.0;170.0;230.0;10.0 + + + Text + + 1620 + 90 + 105 + 60 + + **Time** +fontsize=20 + +style=wordwrap + + + + UMLClass + + 1500 + 180 + 135 + 90 + + +**Clock** + + + + Relation + + 1245 + 75 + 495 + 45 + + lt=. + 10.0;10.0;310.0;10.0 + + + Relation + + 1695 + 75 + 45 + 285 + + lt=. + 10.0;170.0;10.0;10.0 + + + Relation + + 1440 + 315 + 300 + 45 + + lt=. + 180.0;10.0;10.0;10.0 + + + Relation + + 1695 + 315 + 45 + 510 + + lt=. + 10.0;320.0;10.0;10.0 + + + Relation + + 1245 + 315 + 495 + 45 + + lt=. + 10.0;10.0;310.0;10.0 + + + Relation + + 915 + 780 + 825 + 45 + + lt=. + 530.0;10.0;10.0;10.0 + + + Relation + + 915 + 555 + 45 + 270 + + lt=. + 10.0;10.0;10.0;160.0 + + + Relation + + 840 + 225 + 210 + 150 + + lt=<- + 10.0;80.0;10.0;10.0;120.0;10.0 + + + Relation + + 765 + 165 + 45 + 210 + + lt=<- + 10.0;10.0;10.0;120.0 + + + Relation + + 870 + 375 + 255 + 255 + + lt=<- + 150.0;150.0;150.0;10.0;10.0;10.0 + + + Relation + + 1185 + 465 + 120 + 165 + + lt=<- + 60.0;10.0;10.0;10.0;10.0;90.0 + + + Relation + + 1155 + 255 + 150 + 195 + + lt=<- + 10.0;10.0;10.0;110.0;80.0;110.0 + + + Relation + + 1455 + 255 + 150 + 225 + + lt=<- + 10.0;130.0;80.0;130.0;80.0;10.0 + + + Relation + + 1200 + 210 + 330 + 45 + + lt=<- + 10.0;10.0;200.0;10.0 + + + Text + + 840 + 210 + 225 + 45 + + Key/Mouse events +fontsize=12 +style=wordwrap + + + + Text + + 630 + 225 + 150 + 45 + + Mouse events +fontsize=12 +style=wordwrap + + + + Text + + 915 + 390 + 150 + 45 + + Input events +fontsize=12 +style=wordwrap + + + + Text + + 1200 + 510 + 180 + 45 + + Entity updates +fontsize=12 +style=wordwrap + + + + Relation + + 1155 + 450 + 150 + 180 + + lt=<- + 10.0;100.0;10.0;10.0;80.0;10.0 + + + Text + + 1500 + 450 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + Text + + 1110 + 435 + 180 + 45 + + Scheduled events +fontsize=12 +style=wordwrap + + + + Relation + + 1215 + 435 + 390 + 240 + + lt=<- + 10.0;140.0;240.0;140.0;240.0;10.0 + + + Text + + 1440 + 645 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + Text + + 990 + 285 + 195 + 45 + + Animation requests +fontsize=12 +style=wordwrap + + + + Text + + 1380 + 195 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + UMLClass + + 690 + 1215 + 195 + 90 + + +**Input** + + + + UMLClass + + 1020 + 1050 + 195 + 90 + + +**Renderer** + + + + UMLClass + + 690 + 960 + 195 + 90 + + +**GUI** + + + + UMLClass + + 1035 + 1470 + 195 + 90 + + +**EventLoop** + + + + UMLClass + + 1275 + 1275 + 195 + 90 + + +**Simulation** + + + + Text + + 525 + 885 + 195 + 60 + + **Presenter** +fontsize=20 + +style=wordwrap + + + + Relation + + 510 + 870 + 780 + 45 + + lt=. + 10.0;10.0;500.0;10.0 + + + Relation + + 510 + 870 + 45 + 600 + + lt=. + 10.0;380.0;10.0;10.0 + + + Relation + + 510 + 1425 + 450 + 45 + + lt=. + 280.0;10.0;10.0;10.0 + + + Relation + + 1245 + 870 + 45 + 360 + + lt=. + 10.0;220.0;10.0;10.0 + + + Relation + + 915 + 1185 + 375 + 285 + + lt=. + 10.0;170.0;230.0;10.0 + + + Text + + 1620 + 960 + 105 + 60 + + **Time** +fontsize=20 + +style=wordwrap + + + + UMLClass + + 1500 + 1050 + 135 + 90 + + +**Clock** + + + + Relation + + 1245 + 945 + 495 + 45 + + lt=. + 10.0;10.0;310.0;10.0 + + + Relation + + 1695 + 945 + 45 + 285 + + lt=. + 10.0;170.0;10.0;10.0 + + + Relation + + 1440 + 1185 + 300 + 45 + + lt=. + 180.0;10.0;10.0;10.0 + + + Relation + + 1695 + 1185 + 45 + 510 + + lt=. + 10.0;320.0;10.0;10.0 + + + Relation + + 1245 + 1185 + 495 + 45 + + lt=. + 10.0;10.0;310.0;10.0 + + + Relation + + 915 + 1650 + 825 + 45 + + lt=. + 530.0;10.0;10.0;10.0 + + + Relation + + 915 + 1425 + 45 + 270 + + lt=. + 10.0;10.0;10.0;160.0 + + + Relation + + 840 + 1095 + 210 + 150 + + lt=<- + 10.0;80.0;10.0;10.0;120.0;10.0 + + + Relation + + 765 + 1035 + 45 + 210 + + lt=<- + 10.0;10.0;10.0;120.0 + + + Relation + + 870 + 1245 + 255 + 255 + + lt=<- + 150.0;150.0;150.0;10.0;10.0;10.0 + + + Relation + + 1185 + 1335 + 120 + 165 + + lt=<- + 60.0;10.0;10.0;10.0;10.0;90.0 + + + Relation + + 1155 + 1125 + 150 + 195 + + lt=<- + 10.0;10.0;10.0;110.0;80.0;110.0 + + + Relation + + 1455 + 1125 + 150 + 225 + + lt=<- + 10.0;130.0;80.0;130.0;80.0;10.0 + + + Relation + + 1200 + 1080 + 330 + 45 + + lt=<- + 10.0;10.0;200.0;10.0 + + + Text + + 840 + 1080 + 225 + 45 + + Key/Mouse events +fontsize=12 +style=wordwrap + + + + Text + + 630 + 1095 + 150 + 45 + + Mouse events +fontsize=12 +style=wordwrap + + + + Text + + 915 + 1260 + 150 + 45 + + Input events +fontsize=12 +style=wordwrap + + + + Text + + 1200 + 1380 + 180 + 45 + + Entity updates +fontsize=12 +style=wordwrap + + + + Relation + + 1155 + 1320 + 150 + 180 + + lt=<- + 10.0;100.0;10.0;10.0;80.0;10.0 + + + Text + + 1500 + 1320 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + Text + + 1110 + 1305 + 180 + 45 + + Scheduled events +fontsize=12 +style=wordwrap + + + + Relation + + 1215 + 1305 + 390 + 240 + + lt=<- + 10.0;140.0;240.0;140.0;240.0;10.0 + + + Text + + 1440 + 1515 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + Text + + 990 + 1155 + 195 + 45 + + Animation requests +fontsize=12 +style=wordwrap + + + + Text + + 1380 + 1065 + 180 + 45 + + Current time +fontsize=12 +style=wordwrap + + + + UMLClass + + 1035 + 1770 + 195 + 90 + + +**Networking** + + + + UMLClass + + 660 + 1470 + 195 + 90 + + +**Scripting** + + + + Relation + + 840 + 1485 + 225 + 45 + + lt=<- + 130.0;10.0;10.0;10.0 + + + Relation + + 840 + 1515 + 225 + 45 + + lt=<- + 10.0;10.0;130.0;10.0 + + + Relation + + 1065 + 1545 + 45 + 255 + + lt=<- + 10.0;150.0;10.0;10.0 + + + Relation + + 1110 + 1545 + 45 + 255 + + lt=<- + 10.0;10.0;10.0;150.0 + + + Relation + + 1215 + 1350 + 225 + 510 + + lt=<- + 130.0;10.0;130.0;320.0;10.0;320.0 + + + Relation + + 1215 + 1350 + 195 + 480 + + lt=<- + 10.0;300.0;110.0;300.0;110.0;10.0 + + + Text + + 1335 + 1830 + 180 + 45 + + Server updates +fontsize=12 +style=wordwrap + + + + Text + + 1275 + 1755 + 180 + 45 + + Client data +fontsize=12 +style=wordwrap + + + + Text + + 1125 + 1665 + 180 + 45 + + Server events +fontsize=12 +style=wordwrap + + + + Text + + 960 + 1665 + 180 + 45 + + Client events +fontsize=12 +style=wordwrap + + + + Text + + 870 + 1530 + 180 + 45 + + Event notifiers +fontsize=12 +style=wordwrap + + + + Text + + 870 + 1470 + 180 + 45 + + Script events +fontsize=12 +style=wordwrap + + + diff --git a/doc/code/images/engine_target_architecture.svg b/doc/code/images/engine_target_architecture.svg new file mode 100644 index 0000000000..fbc026c06a --- /dev/null +++ b/doc/code/images/engine_target_architecture.svg @@ -0,0 +1,344 @@ + + +Script eventsEvent notifiersClient eventsServer eventsClient dataServer updatesScriptingNetworkingCurrent timeAnimation requestsCurrent timeScheduled eventsCurrent timeEntity updatesInput eventsMouse eventsKey/Mouse eventsClockTimePresenterSimulationEventLoopGUIRendererInput diff --git a/doc/code/images/event_classes.uxf b/doc/code/images/event_classes.uxf new file mode 100644 index 0000000000..d9be3fd902 --- /dev/null +++ b/doc/code/images/event_classes.uxf @@ -0,0 +1,177 @@ + + + // Uncomment the following line to change the fontsize and font: +fontsize=14 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 15 + + UMLClass + + 750 + 450 + 180 + 90 + + +**EventLoop** + + + + UMLClass + + 1095 + 450 + 180 + 90 + + +**EventQueue** + + + + UMLClass + + 1005 + 645 + 150 + 90 + + +**Event** + + + + UMLClass + + 735 + 780 + 180 + 90 + + +**EventHandler** + + + + UMLClass + + 585 + 645 + 120 + 90 + + +**State** + + + + Relation + + 915 + 480 + 210 + 45 + + lt=<. + 120.0;10.0;10.0;10.0 + + + Relation + + 870 + 525 + 165 + 195 + + lt=<. + 90.0;110.0;10.0;110.0;10.0;10.0 + + + Relation + + 1110 + 525 + 45 + 150 + + lt=<. + 10.0;80.0;10.0;10.0 + + + Relation + + 795 + 525 + 45 + 285 + + lt=<. + 10.0;170.0;10.0;10.0 + + + Relation + + 900 + 720 + 165 + 135 + + lt=<. + 10.0;70.0;90.0;70.0;90.0;10.0 + + + Relation + + 630 + 480 + 150 + 195 + + lt=<. + 10.0;110.0;10.0;10.0;80.0;10.0 + + + UMLClass + + 1185 + 780 + 150 + 90 + + +**EventEntity** + + + + Relation + + 1095 + 720 + 120 + 135 + + lt=<. + 60.0;70.0;10.0;70.0;10.0;10.0 + + diff --git a/doc/code/images/event_classes_uml.svg b/doc/code/images/event_classes_uml.svg new file mode 100644 index 0000000000..9db8ffea01 --- /dev/null +++ b/doc/code/images/event_classes_uml.svg @@ -0,0 +1,124 @@ + + +EventEntityStateEventHandlerEventEventQueueEventLoop diff --git a/doc/code/images/game_entity_classes.uxf b/doc/code/images/game_entity_classes.uxf new file mode 100644 index 0000000000..fedf65862a --- /dev/null +++ b/doc/code/images/game_entity_classes.uxf @@ -0,0 +1,450 @@ + + + 15 + + UMLClass + + 0 + 390 + 390 + 285 + + **GameEntity** +-- +id: entity_id_t +components: unordered_map +render_entity: WorldRenderEntity +manager: GameEntityManager +-- +copy(): GameEntity +get_component(): Component +add_component(Component): void +has_component(component_t): bool +render_update(time_t, string): void + + + + UMLClass + + 510 + 405 + 210 + 90 + + +**Component** + + + + UMLClass + + 510 + 555 + 255 + 90 + + +**GameEntityManager** + + + + UMLClass + + 75 + 765 + 255 + 90 + + +**WorldRenderEntity** + + + + Relation + + 180 + 660 + 45 + 135 + + lt=<. + 10.0;70.0;10.0;10.0 + + + Relation + + 375 + 585 + 165 + 45 + + lt=<.> + 90.0;10.0;10.0;10.0 + + + Relation + + 375 + 435 + 165 + 45 + + lt=<. + 90.0;10.0;10.0;10.0 + + + UMLClass + + 90 + 0 + 210 + 90 + + +**GameEntity** + + + + UMLClass + + 375 + 0 + 210 + 90 + + +**Component** + + + + UMLClass + + 90 + 165 + 255 + 90 + + +**GameEntityManager** + + + + Relation + + 195 + 75 + 45 + 120 + + lt=<.> + 10.0;60.0;10.0;10.0 + + + Relation + + 285 + 30 + 120 + 45 + + lt=<. + 60.0;10.0;10.0;10.0 + + + Relation + + 330 + 195 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + + Text + + 465 + 195 + 150 + 105 + + /systems.../ + + + + UMLClass + + 1290 + 375 + 210 + 90 + + <<interface>> +**Component** +bg=pink + + + + UMLClass + + 1095 + 525 + 270 + 90 + + <<interface>> +**InternalComponent** +bg=pink + + + + UMLClass + + 1425 + 525 + 255 + 90 + + <<interface>> +**APIComponent** +bg=pink + + + + Relation + + 1320 + 450 + 45 + 105 + + lt=<<- + 10.0;10.0;10.0;50.0 + + + Relation + + 1440 + 450 + 45 + 105 + + lt=<<- + 10.0;10.0;10.0;50.0 + + + UMLClass + + 1065 + 675 + 210 + 90 + + +**Activity** +bg=green + + + + UMLClass + + 1065 + 780 + 210 + 90 + + +**CommandQueue** +bg=green + + + + UMLClass + + 1065 + 885 + 210 + 90 + + +**Ownership** +bg=green + + + + UMLClass + + 1065 + 990 + 210 + 90 + + +**Position** +bg=green + + + + UMLClass + + 1515 + 675 + 210 + 90 + + +**Idle** +bg=green + + + + UMLClass + + 1515 + 780 + 210 + 90 + + +**Live** +bg=green + + + + UMLClass + + 1515 + 885 + 210 + 90 + + +**Move** +bg=green + + + + UMLClass + + 1515 + 990 + 210 + 90 + + +**Turn** +bg=green + + + + Relation + + 1305 + 600 + 45 + 465 + + lt=<<- + 10.0;10.0;10.0;290.0 + + + Relation + + 1455 + 600 + 45 + 465 + + lt=<<- + 10.0;10.0;10.0;290.0 + + + Relation + + 1260 + 705 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1260 + 810 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1260 + 915 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1260 + 1020 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1455 + 1020 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1455 + 915 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1455 + 810 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + + Relation + + 1455 + 705 + 90 + 45 + + lt=- + 40.0;10.0;10.0;10.0 + + diff --git a/doc/code/images/primitive_curves_uml.svg b/doc/code/images/primitive_curves_uml.svg new file mode 100644 index 0000000000..1ff0be8d94 --- /dev/null +++ b/doc/code/images/primitive_curves_uml.svg @@ -0,0 +1,171 @@ + + +KeyframeKeyframeContainerSegmentedset_insert_jump(time_t, T, T): voidset_last_jump(time_t, T, T): voidContinuousset_insert(time_t, T): voidset_last(time_t, T): void«interface»Interpolatedget(time_t): TDiscreteget(time_t): Tget_time(time_t): Tget_previous(time_t): T«interface»BaseCurve<T>get(time_t): Tframe(time_t): pair<time_t, T>next_frame(time_t): pair<time_t, T>set_insert(time_t, T): voidset_last(time_t, T): voidset_replace(time_t, T): voidsync(BaseCurve<T>, time_t): void diff --git a/doc/code/images/segmented_curve.ggb b/doc/code/images/segmented_curve.ggb new file mode 100644 index 0000000000..97beced399 Binary files /dev/null and b/doc/code/images/segmented_curve.ggb differ diff --git a/doc/code/images/segmented_curve.png b/doc/code/images/segmented_curve.png new file mode 100644 index 0000000000..5b8038af82 Binary files /dev/null and b/doc/code/images/segmented_curve.png differ diff --git a/doc/code/images/simulation.uxf b/doc/code/images/simulation.uxf new file mode 100644 index 0000000000..e7fc0893f7 --- /dev/null +++ b/doc/code/images/simulation.uxf @@ -0,0 +1,162 @@ + + + 15 + + UMLClass + + 1170 + 525 + 150 + 90 + + +**Game** + + + + UMLClass + + 705 + 495 + 375 + 285 + + **GameSimulation** +-- +running: bool +game: Game +-- +set_modpacks(vector<string>): void +init_event_handlers(): void +run(): void +start(): void +stop(): void + + + + UMLClass + + 1170 + 690 + 180 + 90 + + +**GameState** + + + + UMLClass + + 1440 + 645 + 195 + 90 + + +**GameEntity** + + + + UMLClass + + 1440 + 750 + 165 + 90 + + +**Terrain** + + + + Relation + + 1335 + 690 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + + Relation + + 1335 + 750 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + + Relation + + 1245 + 600 + 45 + 120 + + lt=<. + 10.0;60.0;10.0;10.0 + + + Relation + + 1065 + 555 + 135 + 45 + + lt=<. + 70.0;10.0;10.0;10.0 + + + UMLClass + + 705 + 870 + 150 + 90 + + +**EventLoop** + + + + UMLClass + + 900 + 870 + 150 + 90 + + +**TimeLoop** + + + + Relation + + 960 + 765 + 45 + 135 + + lt=<. + 10.0;70.0;10.0;10.0 + + + Relation + + 765 + 765 + 45 + 135 + + lt=<. + 10.0;70.0;10.0;10.0 + + diff --git a/doc/code/images/system_classes.uxf b/doc/code/images/system_classes.uxf new file mode 100644 index 0000000000..7143f89e14 --- /dev/null +++ b/doc/code/images/system_classes.uxf @@ -0,0 +1,31 @@ + + + 15 + + UMLClass + + 795 + 405 + 510 + 165 + + **Move** +-- +move_default(GameEntity, phys3, time_t): time_t +move_command(GameEntity, time_t): time_t + + + + UMLClass + + 810 + 630 + 375 + 165 + + **Idle** +-- +idle(GameEntity, time_t): time_t + + + diff --git a/doc/code/images/time_classes.uxf b/doc/code/images/time_classes.uxf new file mode 100644 index 0000000000..55f0e4992c --- /dev/null +++ b/doc/code/images/time_classes.uxf @@ -0,0 +1,76 @@ + + + // Uncomment the following line to change the fontsize and font: +fontsize=14 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 15 + + UMLClass + + 675 + 300 + 315 + 180 + + **TimeLoop** +-- +get_clock(): Clock +run(): void +start(): void +stop(): void + + + + UMLClass + + 1095 + 300 + 315 + 285 + + **Clock** +-- +update_time(): void +get_time(): time_t +get_real_time(): time_t +get_speed(): speed_t +set_speed(speed_t): void +start(): void +stop(): void +pause(): void +resume(): void + + + + Relation + + 975 + 375 + 150 + 45 + + lt=<. + 80.0;10.0;10.0;10.0 + + diff --git a/doc/code/images/time_classes_uml.svg b/doc/code/images/time_classes_uml.svg new file mode 100644 index 0000000000..aed04e35b7 --- /dev/null +++ b/doc/code/images/time_classes_uml.svg @@ -0,0 +1,71 @@ + + +Clockupdate_time(): voidget_time(): time_tget_real_time(): time_tget_speed(): speed_tset_speed(speed_t): voidstart(): voidstop(): voidpause(): voidresume(): voidTimeLoopget_clock(): Clockrun(): voidstart(): voidstop(): void diff --git a/doc/code/input/README.md b/doc/code/input/README.md index d7c048a882..ab059a668f 100644 --- a/doc/code/input/README.md +++ b/doc/code/input/README.md @@ -4,6 +4,17 @@ Input managment concerns the handling external input sources that are used to in The most common example for such input sources are probably **keyboard and mouse**, but other things like the **GUI**, **networking** and **scripting** also fall under this umbrella. +1. [Motivation](#motivation) +2. [Basic Architecture](#basic-architecture) +3. [Window System](#window-system) + 1. [Workflow](#workflow) + 2. [Class Relationships](#class-relationships) + 3. [Low-level Interface](#low-level-interface) + 4. [High-Level Interface (Controller)](#high-level-interface-controller) +4. [Scripting](#scripting) +5. [Network](#network) +6. [AI](#ai) + ## Motivation diff --git a/doc/code/optimization.md b/doc/code/optimization.md new file mode 100644 index 0000000000..36b3f03a22 --- /dev/null +++ b/doc/code/optimization.md @@ -0,0 +1,46 @@ +# Code Optimization + +openage should be efficient in its resource usage and offer high performance. +As we are building a game engine, it is kind of expected that everything runs +smoothly out-of-the-box. + +1. [Basic Rules](#basic-rules) +2. [Checking Performance](#checking-performance) + + +## Basic Rules + +Before anyone dives into the codebase and starts changing things around for better performance, +they should consider these simple rules: + +- **readability comes first**: openage depends on outsiders being able to understand the engine code. If the code is super fast but totally incomprehensible, then nobody is going to maintain it. +- **avoid premature optimization**: optimization without reason wastes time, reduces readability, and can sometimes lead to even worse performance. It's often better to implement a workable solution first and then use profiling to identify bottlenecks. Modern compilers are often smart enough to find small improvements during compilation anyway. +- **prefer architecture improvements over speeding up specific use cases**: openage is a game *engine*, so we don't exactly know what people will use it for. We want the general case to be fast, not the edge cases. + + +## Checking Performance + +Performance bottlenecks are best identified with a *profiler* of your choice. + +For **Python**, the built-in modules [cProfile](https://docs.python.org/3/library/profile.html) +(speed) and [tracemalloc](https://docs.python.org/3/library/tracemalloc.html) (memory) are recommended. +openage also provides convenience functions for them in its `openage.util.profiler` module. + +For **C++**, [valgrind](https://valgrind.org/info/tools.html) with `callgrind` (speed) and +`memcheck` (memory) can be used. If you use valgrind, you should supply it the suppression +file in our repo: [`etc/valgrind-python.supp`](/etc/valgrind-python.supp). This lets +valgrind handle the Python parts of the engine a bit better. + +Any other profiler will also do the trick as long as you know how to use it (e.g. `perf`, +`VTune`, `uProf`, etc.). + +Profiling a full engine run can be very resource intensive to profile. Therefore, it +can be beneficial to profile engine [demos](/doc/code/testing.md#demos) for a specific +subsystem, e.g. the renderer or the event system. This is also useful to +check the performance of subsystems in isolation. However, consider that a full engine +run may have different bottlenecks that are not obvious in the demos. + +Stresstests are demos that are specifically designed to test performance, particularly +in the renderer subsystem. They can also include benchmarks with additional +information, e.g. an FPS counter. When profiling performance critical code, implementing +a stresstest should be considered to complement profiling results. diff --git a/doc/code/pathfinding.md b/doc/code/pathfinding.md deleted file mode 100644 index 9ed33e129c..0000000000 --- a/doc/code/pathfinding.md +++ /dev/null @@ -1,22 +0,0 @@ -Original algorithm ------------------- - -Short range pathfinder: -Don't check all possible points and vectors. - -Path from (x0, y0) to (x1, y1): - -Draw line from (x0, y0)->(x1, y1). - -Query obstruction manager for collisions: -Obstruction manager stores 2D outline of all relevant objects, -dynamically adjusts outline sizes for the size of the moving unit. -Just stores the area and shapes on the map occupied by everything. - -If obstruction manager detects no collision: unit walks the line. -Else: -find the 0. collision point (=c0), find way on outline around obstruction: -branch path at c0 into 2 new ones in an `A*` like search tree. -The new paths go to the each side of the obstruction, -each one attempts to build a new path from their end to (x1, y1). -For speedup: assemble multiple obstructions to convex hulls. diff --git a/doc/code/renderer/level1.md b/doc/code/renderer/level1.md index 9d163d3d69..8a7d4e1eb0 100644 --- a/doc/code/renderer/level1.md +++ b/doc/code/renderer/level1.md @@ -4,19 +4,19 @@ Low-level renderer for communicating with the OpenGL and Vulkan APIs. ## Overview -1. [Level 1 Renderer](#level-1-renderer) - 1. [Overview](#overview) - 2. [Architecture](#architecture) - 3. [Basic Usage](#basic--usage) - 1. [Window/Renderer Creation](#windowrenderer-creation) - 2. [Adding a Shader Program](#adding-a-shader-program) - 3. [Creating a Renderable](#creating-a-renderable) - 4. [Rendering and Displaying the Result](#rendering-and-displaying-the-result) - 4. [Advanced Usage](#advanced-usage) - 1. [Framebuffers / Multiple Render Passes](#framebuffers--multiple-render-passes) - 2. [Complex Geometry](#complex-geometry) - 3. [Uniform Buffers](#uniform-buffers) - 5. [Thread-safety](#thread-safety) +1. [Overview](#overview) +2. [Architecture](#architecture) +3. [Basic Usage](#basic--usage) + 1. [Window/Renderer Creation](#windowrenderer-creation) + 2. [Adding a Shader Program](#adding-a-shader-program) + 3. [Creating a Renderable](#creating-a-renderable) + 4. [Rendering and Displaying the Result](#rendering-and-displaying-the-result) +4. [Advanced Usage](#advanced-usage) + 1. [Addressing Uniforms via numeric IDs](#addressing-uniforms-via-numeric-ids) + 2. [Framebuffers / Multiple Render Passes](#framebuffers--multiple-render-passes) + 3. [Complex Geometry](#complex-geometry) + 4. [Uniform Buffers](#uniform-buffers) +5. [Thread-safety](#thread-safety) ## Architecture @@ -46,7 +46,8 @@ abstract interface of the renderer renderer to make them usable with graphics ha ## Basic Usage -- see demos in libopenage/renderer/demo +Code examples can be found in the [renderer demos](/libopenage/renderer/demo/). +See the [testing docs](/doc/code/testing.md#python-demos) on how to try them out. ### Window/Renderer Creation @@ -142,10 +143,14 @@ std::shared_ptr input = shader_prog->new_uniform_input( ); ``` -Input values are passed to the method in pairs consisting of the uniform variable -name (as a string) and the input value. The definition order doesn't matter and the -method doesn't differentiate between different shader stages, so uniform inputs -for vertex and fragment shaders can be freely mixed. +Note that the definition order doesn't matter and the method doesn't differentiate +between different shader stages, so uniform inputs for vertex and fragment shaders +can be freely mixed. + +Input values are passed to the method in pairs consisting of the uniform ID and the +input value. Uniform IDs can either be the uniform name from the shader source (as +shown above) or a numeric ID that is determined at load time by the shader program. +Numeric ID usage is explained in [this section](#addressing-uniforms-via-numeric-ids). Uniform input values are automatically converted to the correct types expected by the uniform definition, e.g. a `uint8_t` for a uniform with type `uint` will be transformed to the @@ -209,6 +214,31 @@ window->update(); These are some of the more advanced features of the renderer. +### Addressing Uniforms via numeric IDs + +Numeric uniform IDs are unique identifiers for a uniform in a shader program. They are +assigned at load time and can be used to address uniforms instead of their string names. +The type used for numeric IDs is `renderer::uniform_id_t`. The numeric ID of a uniform +can be fetched from the shader program using the uniform name by calling the +`renderer::ShaderProgram::get_uniform_id(..)` method. + +```c++ +uniform_id_t color_id = shader_prog->get_uniform_id("color"); +uniform_id_t time_id = shader_prog->get_uniform_id("time"); +uniform_id_t num_id = shader_prog->get_uniform_id("num"); +std::shared_ptr input = shader_prog->new_uniform_input( + color_id, Eigen::Vector3f{ 0.0f, 1.0f, 0.0f }, + time_id, 0.0f, + num_id, 1337 +); +``` + +Setting uniform values via numeric IDs can be much faster than using strings as +string lookups are avoided. This is especially useful for uniforms which are updated +very frequently, e.g. every frame. However, this requires that the IDs are fetched +at runtime and have to be stored somewhere. + + ### Framebuffers / Multiple Render Passes Sometimes it is useful to render the scene in multiple passes, e.g. for post-processing diff --git a/doc/code/terrain.md b/doc/code/terrain.md deleted file mode 100644 index 974296dc68..0000000000 --- a/doc/code/terrain.md +++ /dev/null @@ -1,37 +0,0 @@ -terrain implementation -====================== - - -if you ever asked yourself, -"hey, myself, how is terrain stuff implemented in openage?", -this document may enlighten your mind. - - -ideas ------ - -You might know the infinite terrain epicness of minecraft. That's exactly what we are doing in openage. - -The terrain consists of loads of small tiles, grouped in "chunks". - -One chunk contains an area of (currently) 16×16 tiles. Terrain is blended by the technique described in [doc/media/blendomatic.md](/doc/media/blendomatic.md). - -(short summary: -a neighbor tile is blended onto the current one, -if neighbor.priority > current.priority: - the neighbor tile is drawn onto the current tile, - but before that, parts are alphamasked. -) - - -master terrain --------------- - -this is the container of all chunks. - - - -chunk ------ - -a grouped piece of terrain. diff --git a/doc/code/testing.md b/doc/code/testing.md index e23f4a366f..b64b51d9bb 100644 --- a/doc/code/testing.md +++ b/doc/code/testing.md @@ -15,9 +15,9 @@ Tests run without user interaction to check for errors automatically. All tests are run automatically by [Kevin](https://github.com/SFTtech/kevin/) for pullrequests. -You can invoke them with `./run test -a` or `make test` +You can invoke them with `bin/run test -a` or `make test` -Have a look at `./run test --help` for further options. +Have a look at `bin/run test --help` for further options. You are encouraged to write tests for all your contributions, as well as other components that currently lack testing. @@ -35,7 +35,7 @@ They usually produce lots of output on stdout or may even be interactive. Python All tests must be registered in `openage/testing/testlist.py` (else the game won't know about them). -Also see `./run test --help`. +Also see `bin/run test --help`. ## Adding new tests @@ -135,7 +135,7 @@ C++ demos don't support `argv`; if you want that, make it a Python demo in a `.p Similar to Python tests, but have one argument, `argv`. Pass arguments in the invocation: - ./run test -d prime_demo 100 + bin/run test -d prime_demo 100 Example demo: diff --git a/doc/code/time.md b/doc/code/time.md new file mode 100644 index 0000000000..fcbdde0b0f --- /dev/null +++ b/doc/code/time.md @@ -0,0 +1,39 @@ +# Simulation Time + +*Simulation time* is the driving force behind pretty much all internal routines of the engine. +Its used to schedule and execute events in the [event system](event_system.md), +managing data of game entities at runtime via [curves](curves.md), and time +animations in the [renderer](/doc/code/renderer/level2.md). + +To keep track of and synchronize time between different engine components, openage implements +a low-level time control interface in the `openage::time` namespace. This system is very simple: +Basically, it consists of a loop in a dedicated thread that constantly updates an internal clock. + +![time loop UML](images/time_classes_uml.svg) + +`TimeLoop` provides a basic interface to create an internal clock and run the update loop. Once +initialized, the `Clock` instance can be accessed with the `get_clock()` method. For most calculations, +the clock object is sufficient. Access to the time loop is only necessary if you want to +pause/stop the entire simulation. + +openage represents time with the internal type `time::time_t` (which must not be confused with the C standard +type `time_t`). `time::time_t` is a 64 bit signed fixed-point value (scaling factor 16) +which represents the time passed in **seconds**, i.e. a value of `1.25` denotes 1.25 seconds or +1250 milliseconds, respectively. + +`Clock` manages the current simulation time using the system clock. It also allows the configuration +of a simulation speed (which can be negative). Time is advanced in each +loop iteration of `TimeLoop` by calling the clock object's `update_time()` method. This method +first calculates the real time difference between the previous and current update call. The result +is then multiplied by the simulation speed and added to the total simulation time. Additionally, `Clock` +keeps track of how much real time has passed, regardless of simulation speed. Real time is used +in the renderer to time animation frames which should not affected by simulation speed. + +The time resolution used for the system clock is **milliseconds**. When requesting the current time +from a clock via `get_time()` or `get_real_time()`, this gets converted into the openage `time::time_t` +format. + +To prevent the clock updates from advancing too far if the program is stopped by the operating system +or a debugger, `update_time()` sets a maximum limit on how much real time can pass between two update +calls. This limit is currently hardcoded to 50ms. Similarly, there is a minimum limit of 1ms to +prevent the time loop thread from stalling. diff --git a/doc/contributing.md b/doc/contributing.md index cdbbd6245a..6498b10f95 100644 --- a/doc/contributing.md +++ b/doc/contributing.md @@ -28,7 +28,7 @@ What's the concept? We basically do whatever we think is good to do. -The [openage architecture](/doc/architecture.md) is the foundation. +The [openage architecture](/doc/code/architecture.md) is the foundation. For our development concept, see the [development guide](/doc/development.md). If you need some inspiration [what to work on, see above](#what-can-i-do). @@ -81,15 +81,15 @@ For tiny stuff like typo fixes, just create your PR and be done with it. - You can always update to upstream state by [rebasing](#rebasing). - Discuss your ideas and your work: - On the [group chats](/README.md#contact) - - That way, "bad ideas" can be "resolved" beforehand and "better ideas" are found + - That way, "bad" ideas can be resolved beforehand and "better" ideas are found - "Release early and often!" also applies to pull requests! - - Once your branch has some visible work, create `[WIP]` pull request + - Once your branch has some visible work, create a draft/`[WIP]` pull request - Give the pull request a description of what you did or want to do, so we can discuss it - Make sure you are in the `copying.md` file - People will be able to look at your code and give feedback - You'll get free checks from the build bot -- Once your work is done, remove the `[WIP]` so it can be merged +- Once your work is done, mark it as ready for review/remove the `[WIP]` so it can be merged - Do the changes that are requested by the reviewers. - Aaaaaand you're done. diff --git a/doc/convert/README.md b/doc/convert/README.md index 8d97992042..1bf72efe36 100644 --- a/doc/convert/README.md +++ b/doc/convert/README.md @@ -1,5 +1,4 @@ -Convert Script -============== +# Convert Script The convert script transforms media files to openage-compatible formats, and generates code for parsing the generated files. It is written @@ -13,92 +12,21 @@ so we need to convert the files to a format that is less special, and more usable. This is what the convert script does. -The convert script is divided into two parts: -original media dependent and independent exports. +The convert script is divided into two usage modes: *singlefile media conversion* and +*modpack conversion*. -Converting Media ----------------- +## Singlefile Media Conversion -* depends on existing original game installation -* converts images, sounds, units and all other data values - to compatible formats -* creates files for the proprietary data package, - its files will be used if free media files are missing. +This converts graphics and sounds to open/compatible formats. Graphics are +exported to PNG files. If the graphics file is an animation with multiple +sprites, the converter will automatically pack all of them into a spritesheet. +Sounds are exported to OPUS files. -Exporting Structures --------------------- +[See here](convert_single_file.md) for usage examples of the singlefile conversion. -* totally independent of original game installation -* exports original content structures -* prevents redundancy: - * data structures are needed for media export (to convert them) - * data structures are needed to import them in the game - * => structure definition at a single point. -* generation is integrated into make system -* generated files placed in `libopenage/gamedata/` +## Modpack Conversion -Conversion Procedure -==================== - -Media Files ------------ - -A media file is a sound or image file. In the original media files, they are -stored in [drs archives](/doc/media/drs-files.md). - -Each media file has an id and a file extension. -Files can be "redefined" by overlay archives. - -All available archives have to be ordered, so that 'high priority' files -override 'low priority' files. Mods have a higher priority than the base game -to be able to apply their modifications. - -The overlay procedure works by assigning unique media files to the desired -file source or archive. - -A dict has to be filled with values to assign the data source: - - (fileid, extension, destination) => (file archive) - -The resulting dict is a mapping between all available media files and the -archive each should be obtained from. - -The files can then be converted to the appropriate format, the conversion -procedure is selected by their file extension. Graphics are stored in the -[SLP format](/doc/media/slp-files.md) and are converted to *png*. Sounds are -*wav* files which are compressed to *opus*. - - -Original metadata files ------------------------ - -This data describes the configuration and behavior of the original game and its -entities. Namely this defines the available buildings, units, their creation -cost, etc. - -The [gamedata files](/doc/media/original_metadata.md) are parsed and converted to a -huge tree of *csv* files. This is not optimal and will be improved soon(tm). - - -### Data Updates ### - -To modify any data extracted from the original files in a hardcoded manner, -simply update or delete values in the parsed python data structure. These -modifications can be applied like this: - -```python -def fix_data(data): - # make lists for all units building locations - for each unit: - unit.building_loc = [unit.building_loc] - - huskarl_castle.building_loc.append(huskarl_barracks.building_loc) - delete huskarl_barracks - - # value updating is done like this: - get_unit(data, "hussar")["hp"] = 9001 - data.terrain.terrains[6].slp_id = 1337 - - return data -``` +Modpack conversion takes an original game installation and converts its data +and media files into an [openage modpack](/doc/media/openage/modpacks.md). +The converted game can then be run inside openage. diff --git a/doc/convert/convert_single_file.md b/doc/convert/convert_single_file.md index e998b7ad5d..f8c7f16d31 100644 --- a/doc/convert/convert_single_file.md +++ b/doc/convert/convert_single_file.md @@ -1,8 +1,7 @@ -Single file conversion -====================== +# Singlefile conversion -You can use openage to convert a single slp image from some drs archive to a -png image. +You can use openage to convert a single graphics file to PNG or sound file to OPUS. The +asset can also be unpacked from a DRS archive. The invocation could be: @@ -16,6 +15,11 @@ Standalone SLPs (Age of Empires 1: DE and Age of Empires 2: HD): python3 -m openage convert-file --palette-file ~/games/aoe2hd/Data/50500.bina 326.slp /tmp/rofl.png ``` +Standalone SLDs (Age of Empires 2: DE): +``` +python3 -m openage convert-file --player-palette-file ~/games/aoe2de/Data/playercolor_blue.pal --palette-file ~/games/aoe2de/Data/b_west.pal u_elite_eagle.sld /tmp/rofl.png +``` + Standalone SMXs (Age of Empires 2: DE): ``` python3 -m openage convert-file --player-palette-file ~/games/aoe2de/Data/playercolor_blue.pal --palette-file ~/games/aoe2de/Data/b_west.pal u_elite_eagle.smx /tmp/rofl.png @@ -26,6 +30,16 @@ Standalone SMPs (Age of Empires 2: DE): python3 -m openage convert-file --player-palette-file ~/games/aoe2de/Data/playercolor_blue.pal --palette-file ~/games/aoe2de/Data/b_west.pal u_elite_eagle.smp /tmp/rofl.png ``` +WAVs in DRS archives (for older versions of Age of Empires 1, Age of Empires 2 and SWGB): +``` +python3 -m openage convert-file --drs ~/games/aoe2/Data/sounds.drs 123.wav /tmp/rofl.opus +``` + +Standalone WAVs (Age of Empires 2: HD Edition): +``` +python3 -m openage convert-file ~/games/aoe2/resources/123.wav /tmp/rofl.opus +``` + Have a look at `openage/convert/singlefile.py`, this is also a simple API demo for how to interact with the aoe files. diff --git a/doc/convert/nyan.md b/doc/convert/nyan.md new file mode 100644 index 0000000000..5d28947c6a --- /dev/null +++ b/doc/convert/nyan.md @@ -0,0 +1,9 @@ +# nyan data conversion + +We depend on the original game. +We have a converter which spits out a files in our formats +by parsing the original data. + +## Gamedata conversion + +`openage/convert/value_object/read/media/datfile/` specifies the format of the `.dat` from various games. diff --git a/doc/debug.md b/doc/debug.md index 01d3c0fac9..e8f838e0b2 100644 --- a/doc/debug.md +++ b/doc/debug.md @@ -1,6 +1,9 @@ # How to debug openage? -## Qt Creator IDE -See [qt_creator.md](/doc/ide/qt_creator.md) + +## Your favorite IDE + +Check the docs in [the `/doc/ide` subfolder](/doc/ide/). + ## GDB GDB can be used to debug C++ code in a terminal. diff --git a/doc/development.md b/doc/development.md index 99bc5650e0..05d5f2a26f 100644 --- a/doc/development.md +++ b/doc/development.md @@ -4,12 +4,11 @@ About development Dev team -------- -There is a "core dev team" (*mic_e*, *JJ*, *zuntrax*, but there's more) -who work on the project in their free time, +There is a "core dev team" who work on the project in their free time, but since we all have other life-originating interrupts and fluctuating motivation, our activity will alternate equally over time (just take a look at the commit statistics). We "core devs" have known each other personally for a long time; -thus, communication happens mostly over private channels (XMPP, Mumble, maybe even real life). +thus, communication happens mostly over private channels (Matrix chats, Mumble, maybe even real life). Development workflow @@ -20,7 +19,7 @@ or an issue on the [issue tracker](https://github.com/sfttech/openage/issues). The pull requests are then open for review by everybody. If the pull request author thinks that their goals aren't met yet, -it is tagged with `[WIP] $title`. +they create it as a draft or tag it with `[WIP] $title`. The author removes it once the goals are met. In the big picture, we're working on completing those WIP pull requests, @@ -32,7 +31,7 @@ just convenient to implement, or needed right now. We're releasing early and often: whenever we add/improve a feature or fix a bug and the code still compiles, we push the code to the github master. Once significant changes have accumulated, -we tag that commit with a new minor version. +we tag that commit with a new version. We don't have dedicated "subsystem maintainers" yet. You can track down the person who did things with `git log` or `git blame`. diff --git a/doc/ideas/ai.md b/doc/ideas/ai.md index 991dbcb596..b7471a5a82 100644 --- a/doc/ideas/ai.md +++ b/doc/ideas/ai.md @@ -1,7 +1,102 @@ +# Artificial Intelligence + +## Interface + +This is a very early draft with some ideas taken +from http://bwmirror.jurenka.sk/javadoc/bwapi/package-summary.html + +This file shall provide information about the AI interface design. + + +### General ideas + + * An AI registers hooks for desired events + * The C++ engine triggers python AI functions when desired events occur + * The AI then can trigger actions on the controllable units + * Periodically (1 Hz?), the AI gets ticked to allow event independent decisions + * Get the AI its own dedicated thread + + +### Event types + +Python interface basic events: + + * on_start(GameInfo info) + * on_frame(Game game) + * on_end(Player winner) + +Some AIs may prefer an event driven approach (rule based AI): + + * on_unit_discover(Unit unit) + * on_unit_complete(Unit unit) + * on_unit_lost(Unit unit) + * many more... + + +Some AIs will need to simulate ticks into the future to help +make decisions for the current tick. (min-max, MCTS, etc.) + + +### Relevant structures for the AI + +Remember: These are just some ideas for possible interfaces, +they are not existent in the game yet. + +```cpp +struct game_info { + int num_players; + int map_size; + int pop_limit; + resources_type; + map_view; + starting_age; + victory_mode; +} +``` + +```cpp +class Game { + Player[] allies(); // all the ally players that have not left or been defeated. + bool can_build_at(Unit builder, TilePosition position, UnitType type); + bool can_create(Unit builder, UnitType type); + bool can_research(Unit unit, TechType type); + bool can_upgrade(Unit unit, UpgradeType type); + Player[] enemies(); // all the enemy players that have not left or been defeated. + Unit[] get_all_units(); // returns all the visible units. + + // many more examples at: http://bwmirror.jurenka.sk/javadoc/bwapi/Game.html +} +``` + +```cpp +class Player { + string get_name(); // returns the name of the player. + Faction get_faction(); // returns the faction of the player. + Unit[] get_units(); // returns the set of units the player own. + bool has_researched(TechType tech); + int get_resource() // Returns the amount of resources the player owns. + // many more... +} +``` + +```cpp +class Unit { + // used to get information about individual units as well as issue orders to units +} +``` + +```cpp +class Calculation { + // used to get computation heavy calculations from the C++ engine +} +``` + + +## Gameplay + Improvements for the AI's gameplay -Villagers ---------- +### Villagers - Don't collect resources in hazardous areas / send the military to clear them out - Send military task forces to guard strategic resources / tower them @@ -10,8 +105,7 @@ Villagers - Prefer to build castles and towers near the water/thin places - Create more trade cogs and trade ships -Military --------- +### Military - Avoid fighting in hazardous areas / prefer fighting in range of own castles - Coordinates reaction to attacks on units (during march, ...) (including attacks by towers/castles) @@ -23,7 +117,6 @@ Military - send smaller amount of troops earlier in the game to annoy you - while building up a big army in the back -Ship --------- +### Ship - Transport ship can deliver villagers to another islands diff --git a/doc/media/openage/modpack_definition_file.md b/doc/media/openage/modpack_definition_file.md index c4549f4cc9..a9ff6d6a41 100644 --- a/doc/media/openage/modpack_definition_file.md +++ b/doc/media/openage/modpack_definition_file.md @@ -1,6 +1,6 @@ # Modpack Definition File -**Format Version:** 1 +**Format Version:** 2 The modpack definition file is the header file for [modpacks](modpacks.md). @@ -22,54 +22,55 @@ find this specification document. The following parameters have to be specified. -Parameter | Data Type | Optional | Description ----------------------|-----------|----------|------------ -`file_version` | String | No | Version of the modpack definition file format. +| Parameter | Data Type | Optional | Description | +| -------------- | --------- | -------- | ---------------------------------------------- | +| `file_version` | String | No | Version of the modpack definition file format. | ## [info] Section `[info]` contains general information about the modpack. -Parameter | Data Type | Optional | Description --------------------|---------------|----------|------------ -`packagename` | String | No | Name of the modpack. -`version` | String | No | Version number. -`repo` | String | Yes | Name of the repo where the package is hosted. -`alias` | String | Yes | Alias of the modpack. Aliases can be used for replacing other modpacks. -`title` | String | Yes | Title used in UI. -`description` | String | Yes | Path to a file with a short description (max 500 chars). -`long_description` | String | Yes | Path to a file with a detailed description. -`url` | String | Yes | Link to the modpack's website. -`license` | Array[String] | Yes | License(s) of the modpack. +| Parameter | Data Type | Optional | Description | +| ------------------ | ------------- | -------- | ------------------------------------------------------------------------ | +| `packagename` | String | No | Name of the modpack. | +| `version` | String | No | Internal version number. Must have [semver](https://semver.org/) format. | +| `versionstr` | String | Yes | Human-readable version string. | +| `repo` | String | Yes | Name of the repo where the package is hosted. | +| `alias` | String | Yes | Alias of the modpack. Aliases can be used for replacing other modpacks. | +| `title` | String | Yes | Title used in UI. | +| `description` | String | Yes | Path to a file with a short description (max 500 chars). | +| `long_description` | String | Yes | Path to a file with a detailed description. | +| `url` | String | Yes | Link to the modpack's website. | +| `license` | Array[String] | Yes | License(s) of the modpack. | ## [assets] Section `[assets]` contains paths to assets in the modpack. -Parameter | Data Type | Optional | Description ----------------|----------------|----------|------------ -`include` | Array[String] | No | List of paths to assets that should be mounted on load time. Paths are allowed to contain wildcards. -`exclude` | Array[String] | Yes | List of paths to assets that should be excluded from mounting. Paths are allowed to contain wildcards. +| Parameter | Data Type | Optional | Description | +| --------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------ | +| `include` | Array[String] | No | List of paths to assets that should be mounted on load time. Paths are allowed to contain wildcards. | +| `exclude` | Array[String] | Yes | List of paths to assets that should be excluded from mounting. Paths are allowed to contain wildcards. | ## [dependency] Section `[dependency]` contains a list of other modpacks that the modpack depends on. -Parameter | Data Type | Optional | Description ----------------|----------------|----------|------------ -`modpacks` | Array[String] | Yes | List of modpack aliases or identifiers. +| Parameter | Data Type | Optional | Description | +| ---------- | ------------- | -------- | --------------------------------------- | +| `modpacks` | Array[String] | Yes | List of modpack aliases or identifiers. | ## [conflict] Section `[conflict]` contains a list of other modpacks that the modpack conflicts with. -Parameter | Data Type | Optional | Description ----------------|----------------|----------|------------ -`modpacks` | Array[String] | Yes | List of modpack aliases or identifiers. +| Parameter | Data Type | Optional | Description | +| ---------- | ------------- | -------- | --------------------------------------- | +| `modpacks` | Array[String] | Yes | List of modpack aliases or identifiers. | ## [authors] Section @@ -78,29 +79,29 @@ Parameter | Data Type | Optional | Description Every author must have their own subtable `[authors.{authorname}]`. The subtable can set the following parameters. -Parameter | Data Type | Optional | Description ------------|---------------|----------|------------ -`name` | String | No | Nickname of the author. Must be unique for the modpack. -`fullname` | String | Yes | Full name of the author. -`since` | String | Yes | Version number of the release where the author started to contribute. -`until` | String | Yes | Version number of the release where the author stopped to contribute. -`roles` | Array[String] | Yes | List of roles of the author during the creation of the modpack. -`contact` | Table | Yes | Contact information (see below). +| Parameter | Data Type | Optional | Description | +| ---------- | ------------- | -------- | --------------------------------------------------------------------- | +| `name` | String | No | Nickname of the author. Must be unique for the modpack. | +| `fullname` | String | Yes | Full name of the author. | +| `since` | String | Yes | Version number of the release where the author started to contribute. | +| `until` | String | Yes | Version number of the release where the author stopped to contribute. | +| `roles` | Array[String] | Yes | List of roles of the author during the creation of the modpack. | +| `contact` | Table | Yes | Contact information (see below). | The contact table can use the following parameters. -Parameter | Data Type | Optional | Description ------------|---------------|----------|------------ -`discord` | String | Yes | Discord username. -`email` | String | Yes | Email address. -`github` | String | Yes | GitHub username. -`gitlab` | String | Yes | Gitlab username. -`irc` | String | Yes | IRC username. -`mastodon` | String | Yes | Mastodon username. -`matrix` | String | Yes | Matrix username. -`reddit` | String | Yes | Reddit username. -`twitter` | String | Yes | Twitter username. -`youtube` | String | Yes | YouTube username. +| Parameter | Data Type | Optional | Description | +| ---------- | --------- | -------- | ------------------ | +| `discord` | String | Yes | Discord username. | +| `email` | String | Yes | Email address. | +| `github` | String | Yes | GitHub username. | +| `gitlab` | String | Yes | Gitlab username. | +| `irc` | String | Yes | IRC username. | +| `mastodon` | String | Yes | Mastodon username. | +| `matrix` | String | Yes | Matrix username. | +| `reddit` | String | Yes | Reddit username. | +| `twitter` | String | Yes | Twitter username. | +| `youtube` | String | Yes | YouTube username. | ## [authorgroups] Section @@ -110,8 +111,8 @@ It can be used in addition to `[authors]` to signify that the modpack is a team effort. -Parameter | Data Type | Optional | Description ---------------|---------------|----------|------------ -`name` | String | No | Group or team name. -`authors` | Array[String] | No | List of author identifiers. These must match up with subtable keys in the `[authors]` section, e.g. `"xxbunny123"` references `[authors.xxbunny123]`. -`description` | String | Yes | Path to a file with a description of the team. +| Parameter | Data Type | Optional | Description | +| ------------- | ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | String | No | Group or team name. | +| `authors` | Array[String] | No | List of author identifiers. These must match up with subtable keys in the `[authors]` section, e.g. `"xxbunny123"` references `[authors.xxbunny123]`. | +| `description` | String | Yes | Path to a file with a description of the team. | diff --git a/doc/media/openage/modpacks.md b/doc/media/openage/modpacks.md index 4bbf9c580e..f475a6a636 100644 --- a/doc/media/openage/modpacks.md +++ b/doc/media/openage/modpacks.md @@ -13,7 +13,7 @@ anything from minor enhancements to standalone games. Apart from game-related data, modpacks store configuration data for loading them into the engine. Most of this data is located in the -**[modpack definition file](###modpack-definition-file)**. Modpacks can define +**[modpack definition file](#modpack-definition-file)**. Modpacks can define their interaction with other modpacks by specifying **dependencies** and **conflicts**. diff --git a/doc/media/original-metadata.md b/doc/media/original-metadata.md index 318630fa34..5e5540fe44 100644 --- a/doc/media/original-metadata.md +++ b/doc/media/original-metadata.md @@ -5,7 +5,7 @@ All data relevant for the game (e.g. how much costs building the castle? What cultures exist? Can my priest overclock his "Wololo?") are stored in a binary format in the file `empires2_x1_p1.dat`. -The format is described in the [huge struct definition](/openage/convert/gamedata/empiresdat.py). +The format is described in the [huge struct definition](/openage/convert/value_object/read/media/datfile/empiresdat.py). These data files are basically a huge tree structure. diff --git a/doc/media_convert.md b/doc/media_convert.md index 04f72554b1..a6526de99e 100644 --- a/doc/media_convert.md +++ b/doc/media_convert.md @@ -8,12 +8,9 @@ Currently we *support* conversion for these games: * **RoR**: Age of Empires 1 (1997) + Rise of Rome * **AoC**: Age of Empires 2 (1999) + The Conqueror's * **SWGB**: Star Wars: Galactic Battlegrounds + Clone Campaigns -* **DE2**: Age of Empires 2: Definitve Edition - -The following versions are currently *unsupported*, but will be added later: - * **HD**: Age of Empires 2 (2013) (formerly: Age of Empires 2: HD Edition) * **DE1**: Age of Empires 1: Definitive Edition +* **DE2**: Age of Empires 2: Definitve Edition On Linux, you may have to use additional measures to download DE2 versions from Steam: @@ -26,7 +23,7 @@ On Linux, you may have to use additional measures to download DE2 versions from `./steamcmd.sh +@sSteamCmdForcePlatformType windows +login USERNAME +force_install_dir ASSET_DIR +app_update GAME_APP_ID validate +quit` The game version vs Game_ID table such as below: - Age of Empires(2013): 221380 + Age of Empires (2013): 221380 Age of Empires: Definitive Edition: 1017900 Age of Empires II (Rise of the Rajas): 488060 Age of Empires II: Definitive Edition: 813780 @@ -44,4 +41,10 @@ The game will ask for your AoE II installation folder; examples include: ~/.steam/steam/SteamApps/common/Age2HD ~/Library/Application Support/Steam/steamapps/common/Age2HD +Alternatively, if your game installation is not found, you can trigger the conversion manually: + +``` +python3 -m openage convert --force --source-dir /path/to/game/install +``` + You will find the converted files in `assets/converted`. diff --git a/doc/milestones.md b/doc/milestones.md deleted file mode 100644 index f0c66f094d..0000000000 --- a/doc/milestones.md +++ /dev/null @@ -1,32 +0,0 @@ -Milestones -========== - - -- [x] 0: decide on the technology and architecture we're using. - * language, libraries, build system, coding standards, ... - * may be incomplete, will be changed later on anyway -- [x] 1: Create a database format for game data ([nyan](https://github.com/SFTtech/nyan)) -- [x] 2: Renderer using OpenGL and Vulkan ([code doc](https://github.com/SFTtech/openage/tree/master/doc/code/renderer)) -- [x] 3: Event system for the game simulation -- [x] 4: Design a modding API for the engine ([reference sheet](https://github.com/SFTtech/openage/tree/master/doc/nyan/api_reference)) -- [X] 5: Convert AoE2 game data to our engine formats ([code doc](https://github.com/SFTtech/openage/tree/master/doc/code/converter)) -- [ ] 6: Gamestate calculation with curves logic ([blogpost](https://blog.openage.dev/t1-curves-logic.html)) -- [ ] 7: Gameplay simulation! Where everything comes together -- [ ] 8: Multiplayer - -things to be done sometime: - -* game recording, playback -* lobby + lobby server -* implement AI Python API (use GlaDOS?) -* messaging and taunts (important!) -* random map generation (RMS scripts?) -* age2 map reader - * scenario reader - * maybe even the singleplayer campaigns - -things to keep in mind: - -* performance (responsiveness, fps, needed resources) -* high-quality code -* having fun! diff --git a/doc/nyan/nyan.md b/doc/nyan/README.md similarity index 75% rename from doc/nyan/nyan.md rename to doc/nyan/README.md index 28fa0a5aaf..dcada2c2f6 100644 --- a/doc/nyan/nyan.md +++ b/doc/nyan/README.md @@ -1,13 +1,11 @@ -nyan -==== +# nyan nyan - yet another notation https://github.com/SFTtech/nyan -Idea ----- +## Idea nyan is the data storage format for openage. @@ -32,18 +30,23 @@ it can actually store unit upgrades, unit abilities, research, civ bonuses and age upgrades. -Technical specification ------------------------ +## Technical specification -[nyan specification](https://github.com/SFTtech/nyan/blob/master/doc/nyan.md) +[nyan specification](https://github.com/SFTtech/nyan/blob/master/doc/README.md) -openage specifics ------------------ +## openage specifics nyan is a general purpose data language, the following describes the openage specific usage of it. * [data conversion](conversion.md) * [openage engine nyan interface](openage-lib.md) -* [examples](examples.md) + +## Examples + +For the beginning, you can look at these resources to find examples of the nyan notation: + +* [nyan docs](https://github.com/SFTtech/nyan/blob/master/doc/nyan.md) +* converted game assets from [our converter](/doc/convert/) +* [openage modding guide for nyan](https://github.com/SFTtech/openage-modding/tree/master/tutorials/nyan) diff --git a/doc/nyan/conversion.md b/doc/nyan/conversion.md deleted file mode 100644 index b094c0f1fb..0000000000 --- a/doc/nyan/conversion.md +++ /dev/null @@ -1,20 +0,0 @@ -nyan data conversion -==================== - -We depend on the original game. -We have a converter which spits out a files in our formats -by parsing the original data. - -Gamedata conversion -------------------- - -* `openage/convert/gamedata/` specifies the format of `empires_x1_p1.dat` - * this format allows reading the binary file and storing it into tables - * these tables and the original format suck, - information is redundant and we can heavily improve it - * buuut: the file format is given (every original game has it.) - * :arrow_right: data transformation. -* the original file will be read according to the original format (we can't help it) -* a transformation is specified - * mapping: original format -> our awesome format - * redundancy is purged (e.g. no more double huskarl unit (1x castle, 1x barracs)) diff --git a/doc/nyan/examples.md b/doc/nyan/examples.md deleted file mode 100644 index a4b5d02d76..0000000000 --- a/doc/nyan/examples.md +++ /dev/null @@ -1,9 +0,0 @@ -openage nyan examples -===================== - -openage will make excessive use of the nyan data storage. - -This file will help you understand how you'd create nyan files -to modify or extend the behavior of openage. - -For the beginning, you can look [here](https://github.com/SFTtech/nyan/blob/master/doc/nyan.md) for examples. diff --git a/doc/nyan/openage-lib.md b/doc/nyan/openage-lib.md index 69f7efda99..751dd7fe97 100644 --- a/doc/nyan/openage-lib.md +++ b/doc/nyan/openage-lib.md @@ -1,13 +1,22 @@ -openage nyan library -==================== +# openage nyan library The openage engine defines all kinds of `NyanObject`s so the nyan interpreter can verify data integrity. Together, the defined objects provide the API that can be used by the games running on the engine. This interface will be described here. +1. [Design principles](#design-principles) +2. [API objects](#api-objects) + 1. [Entity](#entity) + 2. [GameEntity](#gameentity) + 3. [Ability](#ability) + 4. [Modifier](#modifier) + 5. [Effect](#effect) +3. [C++ Interface](#c-interface) + + ## Design principles -In addition to the [nyan design goals](https://github.com/SFTtech/nyan/blob/master/doc/nyan.md#design-goals), the openage mod API follows its own design principles. It is recommended to follow these principles when extending the API. +In addition to the [nyan design goals](https://github.com/SFTtech/nyan/blob/master/doc/README.md#design-idea), the openage mod API follows its own design principles. It is recommended to follow these principles when extending the API. **Single API tree** @@ -80,3 +89,8 @@ By default, modifiers apply to the abilities of the game entity that stores them There are two major types of effects: Discrete and continuous. Discrete effects happen at a *specific point in time*, while continuous effects are applied *over time* at a per second rate. Any discrete effect can be combined with every other discrete effect. The same applies for continuous effects. For an effect to apply, the effector's `Effect` needs a corresponding `Resistance` object on the resistor's side. Otherwise the effect is not evaluated. + +## C++ Interface + +openage provides a thin nyan API layer to make interacing with nyan more accessible. This layer is implemented in `libopenage/gamestate/api` and +covers the most common use caes for retrieving objects and reading values. Using/extending the nyan API layer should be preferred when adding game logic that accesses nyan to the engine. diff --git a/doc/project_structure.md b/doc/project_structure.md index 945ef5c3b9..4b2498aae8 100644 --- a/doc/project_structure.md +++ b/doc/project_structure.md @@ -1,6 +1,4 @@ -Project Structure -================= - +# Project Structure One of the biggest problems for newcomers who want to contribute code to free software projects is that they have no idea where to start. @@ -9,21 +7,36 @@ Reading, understanding and finding the relevant code part is hard. This file explains the modular structure of the project. +1. [Architecture](#architecture) +2. [Languages](#languages) +3. [Folders](#folders) + 1. [assets/](#assets) + 2. [buildsystem/](#buildsystem) + 3. [cfg/](#cfg) + 4. [dist/](#dist) + 5. [doc/](#doc) + 6. [etc/](#etc) + 7. [legal/](#legal) + 8. [libopenage/](#libopenage) + 9. [openage/](#openage) + 10. [packaging/](#packaging) + + ## Architecture -The [overall architecture](/doc/architecture.md) describes the conceptual overview. +The [overall architecture](/doc/code/architecture.md) describes the conceptual overview. ## Languages We use Python, Cython and C++. -Extension | Language | Usage ---------------|-----------|--------- -`.py` | Python | Everything that does not crunch data -`.pyx` `.pxd` | Cython | Fast Python code, glue between C/C++ and Python -`.h` `.cpp` | C++ | Data crunching code: simulation, graphics, sound, ... +| Extension | Language | Usage | +| ------------- | -------- | ----------------------------------------------------- | +| `.py` | Python | Everything that does not crunch data | +| `.pyx` `.pxd` | Cython | Fast Python code, glue between C/C++ and Python | +| `.h` `.cpp` | C++ | Data crunching code: simulation, graphics, sound, ... | ## Folders @@ -37,8 +50,8 @@ of the project. Game assets required at run time are placed in here. This includes everything that is converted from the original assets (see [asset conversion](media_convert.md)) -and other input like shaders etc. The directory is installed to `/usr/share/openage/assets` -or whatever the platform recommends. +and other input like shaders etc. The directory is `assets` for local builds or +installed to `/usr/share/openage/assets` or whatever the platform recommends. ### buildsystem/ @@ -68,6 +81,10 @@ The code itself is commented with `/** doxygen comments */`. See [doc/README.md](/doc/README.md) for documentation guidelines. +### etc/ + +Additional resources for development tools, e.g. pylint and valgrind configs. + ### legal/ diff --git a/doc/releasing.md b/doc/releasing.md index 23c834aa67..8a3f37f955 100644 --- a/doc/releasing.md +++ b/doc/releasing.md @@ -1,15 +1,15 @@ # Releasing -* Bump the version number in `openage_version`. Given `0.y.z`, both `0.y.(z+1)` and `0.(y+1).0` are valid. The latter will probably be more common, but which of those you choose doesn't really matter. +openage uses [Semver](https://semver.org).. People often seem to overlook the special rules for initial development versions. Please avoid prerelease versions (`-alpha`, `-beta`, `-rc.1`, ...) for now. We might decide to include build metadata like date or commit hash, that's up for discussion. - Read up on [Semver](https://semver.org) for details. People often seem to overlook the special rules for initial development versions. Please avoid prerelease versions (`-alpha`, `-beta`, `-rc.1`, ...) for now. We might decide to include build metadata like date or commit hash, that's up for discussion. -* Create a new changelog named `doc/changelogs/engine/$VERSION.md`. -* Commit, PR, merge, pull as usual. -* OPTIONAL: Set up [commit signing](https://help.github.com/en/articles/managing-commit-signature-verification), signing tags will make a "verified" badge show up on the release later. -* Tag the merge commit, something like `git tag -s v0.5.0`. The prefixed `v` is mandatory. -* Push the tag to GitHub. -* Use the GitHub web interface to publish a release from the tag. Make it look nice, see previous release description. If in doubt, save the draft and have someone else proof read it. Also include the changelog. -* In the future, kevin will automatically attach build artifacts like installers to the release. For now, you will need to do that manually. Have fun setting up a windows build environment or if you feel like being lazy, go bug someone who already has. Actually, taking care of where to build for windows before publishing the release might not be a bad idea. -* OPTIONAL: Brag on social media. /r/openage, /r/aoe2 and AoE2 Discords might be the right place to do so. +Release guide: -If you need help or are not completely sure what you are doing, ask in [`#sfttech:matrix.org`](https://app.element.io/#/room/#sfttech:matrix.org) and highlight `zuntrax` or someone else who has done it before. Better having someone help you than screwing up a release. +1. Create a new changelog named `doc/changelogs/engine/$VERSION.md`. +1. Bump the version number in `openage_version`. Given `0.y.z`, both `0.y.(z+1)` and `0.(y+1).0` are valid. The latter will probably be more common, but which of those you choose doesn't really matter. +1. Commit, PR, merge, pull as usual. + * OPTIONAL: Set up [commit signing](https://help.github.com/en/articles/managing-commit-signature-verification), signing tags will make a "verified" badge show up on the release later. +1. Tag the merge commit, something like `git tag -s v0.5.0`. The prefixed `v` is mandatory. +1. Push the tag to GitHub. +1. Use the GitHub web interface to publish a release from the tag. Make it look nice, see previous release description. If in doubt, save the draft and have someone else proof read it. Also include the changelog. +1. In the future, kevin will automatically attach build artifacts like installers to the release. For now, you will need to do that manually. Have fun setting up a windows build environment or if you feel like being lazy, go bug someone who already has. Actually, taking care of where to build for windows before publishing the release might not be a bad idea. + * OPTIONAL: Brag on social media. /r/openage, /r/aoe2 and AoE2 Discords might be the right place to do so. diff --git a/doc/reverse_engineering/game_mechanics/formations.md b/doc/reverse_engineering/game_mechanics/formations.md index 86d4fd2443..dd39371ccd 100644 --- a/doc/reverse_engineering/game_mechanics/formations.md +++ b/doc/reverse_engineering/game_mechanics/formations.md @@ -89,7 +89,7 @@ For a start one has to look at the behavior of an individual subformation. Let's ............ ``` -The number of lines (or `row_count`) in this subformation is always determined by the number of its units. Unit width and different unit types have no influence here. The `row_count` can be calculated by an algorithm ([see here](https://gist.github.com/Piruzzolo/e744c9da5ed18898fae85f29a560e90f)). After the value has been calculated the units will be sorted into the lines starting from the top left. +The number of lines (or `row_count`) in this subformation is always determined by the number of its units. Unit width and different unit types have no influence here. The `row_count` can be calculated by an algorithm. After the value has been calculated the units will be sorted into the lines starting from the top left. ``` ............ diff --git a/doc/reverse_engineering/game_mechanics/swgb/shields.md b/doc/reverse_engineering/game_mechanics/swgb/shields.md index 962182271f..2ab7a4d570 100644 --- a/doc/reverse_engineering/game_mechanics/swgb/shields.md +++ b/doc/reverse_engineering/game_mechanics/swgb/shields.md @@ -12,7 +12,7 @@ A shielded unit gradually fills a shield bar (originally yellow and placed under the health bar), that doubles its health points. Aditionally, shielded units have a yellow glow effect, and [the UI](user-interface.md#cap) lights the leftmost indicator in yellow when a shielded unit is selected, as visible -[here]([https://www.youtube.com/watch?v=pwAtMv_eiM4&feature=youtu.be&t=1786]). +[here](https://www.youtube.com/watch?v=pwAtMv_eiM4&t=1786). Shields are depleted first when taking hits, before the regular health bar. Regenerating shields do not affect the health bar. diff --git a/doc/reverse_engineering/networking/01-general.md b/doc/reverse_engineering/networking/01-general.md index 4ac6cc1fa7..e171eb4703 100644 --- a/doc/reverse_engineering/networking/01-general.md +++ b/doc/reverse_engineering/networking/01-general.md @@ -25,59 +25,59 @@ Sync packets can be further categorized into periodic (sent in regular intervals Packets are recognized by a one byte long "command byte" in the header. So far 12 different network commands have been identified. -Command | Purpose ---------|-------------- -0x31 | Sync -0x32 | Sync -0x35 | Sync (Lobby) -0x3e | Player-issued -0x41 | Sync -0x43 | Chat Message -0x44 | Sync -0x4d | Sync -0x51 | De-Sync -0x52 | Readying (Lobby) -0x53 | Sync -0x5a | Lobby +| Command | Purpose | +| ------- | ---------------- | +| 0x31 | Sync | +| 0x32 | Sync | +| 0x35 | Sync (Lobby) | +| 0x3e | Player-issued | +| 0x41 | Sync | +| 0x43 | Chat Message | +| 0x44 | Sync | +| 0x4d | Sync | +| 0x51 | De-Sync | +| 0x52 | Readying (Lobby) | +| 0x53 | Sync | +| 0x5a | Lobby | All packets with command `0x3e` have a second "command byte" after the header that represents the command a player has given ingame. To avoid confusion, we will call all player-issued commands "actions" and reserve the term "commands" for the actual network commands seen above. Furthermore, the identifier for a player's action will be called "action byte". 34 of these can be found in network packets. -Action | Purpose --------|------------ -0x00 | Primary Action (Attacking, Resource gathering, Boarding Transport Ship) -0x01 | Stop -0x02 | Primary Action (AI) -0x03 | Move -0x0a | Move (AI) -0x0b | Resign -0x10 | Set waypoint -0x12 | Stance -0x13 | Guard -0x14 | Follow -0x15 | Patrol -0x17 | Formation -0x1b | Save & Exit -0x1f | Coordinated Move (AI) -0x64 | Train unit (AI) -0x65 | Research -0x66 | Build -0x67 | Diplomacy/Cheats/Change Speed -0x69 | Build wall -0x6a | Delete -0x6b | Attack ground -0x6c | Tribute -0x6e | Repair -0x6f | Unboard/Ungarrison -0x72 | Toggle gate -0x73 | Flare -0x75 | Garrison/Stop building unit -0x77 | Train unit (Human) -0x78 | Rally point -0x7a | Sell -0x7b | Buy -0x7e | Drop relic -0x7f | Toggle townbell -0x80 | Back to work +| Action | Purpose | +| ------ | ----------------------------------------------------------------------- | +| 0x00 | Primary Action (Attacking, Resource gathering, Boarding Transport Ship) | +| 0x01 | Stop | +| 0x02 | Primary Action (AI) | +| 0x03 | Move | +| 0x0a | Move (AI) | +| 0x0b | Resign | +| 0x10 | Set waypoint | +| 0x12 | Stance | +| 0x13 | Guard | +| 0x14 | Follow | +| 0x15 | Patrol | +| 0x17 | Formation | +| 0x1b | Save & Exit | +| 0x1f | Coordinated Move (AI) | +| 0x64 | Train unit (AI) | +| 0x65 | Research | +| 0x66 | Build | +| 0x67 | Diplomacy/Cheats/Change Speed | +| 0x69 | Build wall | +| 0x6a | Delete | +| 0x6b | Attack ground | +| 0x6c | Tribute | +| 0x6e | Repair | +| 0x6f | Unboard/Ungarrison | +| 0x72 | Toggle gate | +| 0x73 | Flare | +| 0x75 | Garrison/Stop building unit | +| 0x77 | Train unit (Human) | +| 0x78 | Rally point | +| 0x7a | Sell | +| 0x7b | Buy | +| 0x7e | Drop relic | +| 0x7f | Toggle townbell | +| 0x80 | Back to work | When the game is recorded, the UDP data stream of a `0x3e` packet (without the header) is written straight into the .mgx files with few changes. Viewing the recording will therefore simulate the exact actions that were done by the players. For more information on this, check the **Further Reading** section below. @@ -89,12 +89,12 @@ Values in the network protocol can have a length of one, two or four byte. Littl The data is described with few data types, which are shown in the table below. -Length | Data Types ----------|------------ -1 byte | int8, (ASCII) char -2 byte | int16 -4 byte | int32, float -other | (1-dimensional) array +| Length | Data Types | +| ------ | --------------------- | +| 1 byte | int8, (ASCII) char | +| 2 byte | int16 | +| 4 byte | int32, float | +| other | (1-dimensional) array | Most of the fields present in the network protocol have a fixed length. The use cases for variable length fields are usually lists of `unit_id`s or waypoints and will be handled as arrays in this documentation. @@ -113,10 +113,10 @@ In this document, we will assume that AoC uses a carthesian coordinate system wi To get a better understanding of the networking design and the underlying principles, it might be beneficial to read these sources. [1] Dave Pottering, *1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond*, 2001 -https://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php?page=1 +https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond [2] Matthew Pritchard, *How to Hurt the Hackers: The Scoop on Internet Cheating and How You Can Combat It*, 2000 -https://www.gamasutra.com/view/feature/3149/how_to_hurt_the_hackers_the_scoop_.php +https://www.gamedeveloper.com/design/how-to-hurt-the-hackers-the-scoop-on-internet-cheating-and-how-you-can-combat-it [3] Stefan Kolb, *Age of Empires 2: The Conquerors — Savegame File Format Specification*, https://github.com/stefan-kolb/aoc-mgx-format diff --git a/doc/running.md b/doc/running.md new file mode 100644 index 0000000000..ffcdf15e76 --- /dev/null +++ b/doc/running.md @@ -0,0 +1,121 @@ +# How to run openage? + +This document explains the different run modes in openage. + +1. [Quickstart](#quickstart) +2. [Modes](#modes) + 1. [`game`](#game) + 2. [`main`](#main) + 3. [`test`](#test) + 4. [`convert`](#convert) + 5. [`convert-file`](#convert-file) + 6. [`convert-export-api`](#convert-export-api) + 7. [`codegen`](#codegen) + + +## Quickstart + +After building the project with the commands + +``` +./configure +make +``` + +you can execute + +``` +bin/run +``` + +from the same subfolder. This automatically selects the [`game` mode](#game) as default +to start a new game instance and also creates all necessary configs. + +If prompts appear, follow the instructions and choose what you think is best. It's +almost idiot-proof! + + +## Modes + +Modes can be selected manually by appending the `bin/run` prompt with the mode name. + +### `game` + +``` +bin/run game +``` + +Start the engine and immediately create a new game instance. This run mode is supposed +to jump straight into a game (or replay recording). + +If no converted modpacks can be found, this mode will start with a prompt asking if +the user wants to convert any before initializing the game. + +It's the default run mode. + + +### `main` + +``` +bin/run main +``` + +This run mode is supposed to start a main menu or launcher which allows configuring a +game. Neither of these are implemented at the moment, so `main` just does the same +thing as `game`. + + +### `test` + +``` +bin/run test +``` + +Used for running [tests and engine demos](code/testing.md). These show off selected +subsystems of the engine. + + +### `convert` + +``` +bin/run convert +``` + +Runs the [asset conversion](media_convert.md) subsystem which creates openage modpacks +from original game installations. + + +### `convert-file` + +``` +bin/run convert-file +``` + +Allows converting single media files using the original game formats to open formats +(PNG for graphics, OPUS for sounds). + + +### `convert-export-api` + +``` +bin/run convert-export-api +``` + +Exports the [openage modding API](nyan/README.md) nyan objects to a modpack that can +be loaded by the engine. + +This is supposed to be temporary solution until the modding API is finalized. Currently, +the modding API nyan objects are hardcoded into the converter. In the future, the +modding API modpack should be part of the engine config which is loaded by both the engine +the converter subsystem as a single source of truth. + + +### `codegen` + +``` +bin/run codegen +``` + +Runs the code generation logic for the build process. In particular, this generates code +for [mako](https://www.makotemplates.org/) templates and creates the test lists for the +[testing](code/testing.md) subsystem. diff --git a/libopenage/CMakeLists.txt b/libopenage/CMakeLists.txt index dafe823c2e..f1772bfc36 100644 --- a/libopenage/CMakeLists.txt +++ b/libopenage/CMakeLists.txt @@ -364,6 +364,7 @@ add_subdirectory("rng") add_subdirectory("shader") add_subdirectory("terrain") add_subdirectory("testing") +add_subdirectory("time") add_subdirectory("unit") add_subdirectory("util") add_subdirectory("versions") diff --git a/libopenage/assets/mod_manager.h b/libopenage/assets/mod_manager.h index 6d7ec5277b..b049603f83 100644 --- a/libopenage/assets/mod_manager.h +++ b/libopenage/assets/mod_manager.h @@ -5,8 +5,11 @@ #include #include #include +#include +#include "error/error.h" #include "log/log.h" +#include "log/message.h" #include "assets/modpack.h" #include "util/path.h" diff --git a/libopenage/assets/modpack.cpp b/libopenage/assets/modpack.cpp index 8d784ef92e..acc3865696 100644 --- a/libopenage/assets/modpack.cpp +++ b/libopenage/assets/modpack.cpp @@ -33,6 +33,9 @@ ModpackInfo parse_modepack_def(const util::Path &info_file) { } // optionals + if (info.contains("versionstr")) { + def.versionstr = info.at("versionstr").as_string(); + } if (info.contains("repo")) { def.repo = info.at("repo").as_string(); } diff --git a/libopenage/assets/modpack.h b/libopenage/assets/modpack.h index 96ee08fa29..7c858b5ed7 100644 --- a/libopenage/assets/modpack.h +++ b/libopenage/assets/modpack.h @@ -43,6 +43,7 @@ struct ModpackInfo { // see /doc/media/openage/modpack_definition_file.md std::string id; std::string version; + std::string versionstr; std::string repo; std::string alias; std::string title; diff --git a/libopenage/coord/phys.cpp b/libopenage/coord/phys.cpp index 9f6ccacd3c..bb5e89498d 100644 --- a/libopenage/coord/phys.cpp +++ b/libopenage/coord/phys.cpp @@ -8,6 +8,7 @@ #include "coord/tile.h" #include "terrain/terrain.h" #include "util/math.h" +#include "util/math_constants.h" namespace openage::coord { @@ -38,7 +39,7 @@ phys_angle_t phys2_delta::to_angle(const coord::phys2_delta &other) const { auto det = other.ne.to_float() * this->se.to_float() - this->ne.to_float() * other.se.to_float(); auto dot = this->ne.to_float() * other.ne.to_float() + this->se.to_float() * other.se.to_float(); - auto angle = std::atan2(det, dot) * 180 / std::numbers::pi; + auto angle = std::atan2(det, dot) * 180 / math::PI; if (angle < 0) { angle += 360; } @@ -99,7 +100,7 @@ phys_angle_t phys3_delta::to_angle(const coord::phys2_delta &other) const { auto det = other.ne.to_float() * this->se.to_float() - this->ne.to_float() * other.se.to_float(); auto dot = this->ne.to_float() * other.ne.to_float() + this->se.to_float() * other.se.to_float(); - auto angle = std::atan2(det, dot) * 180 / std::numbers::pi; + auto angle = std::atan2(det, dot) * 180 / math::PI; if (angle < 0) { angle += 360; } diff --git a/libopenage/coord/scene.cpp b/libopenage/coord/scene.cpp index 7ea121750d..d34519bfe4 100644 --- a/libopenage/coord/scene.cpp +++ b/libopenage/coord/scene.cpp @@ -8,6 +8,7 @@ #include "coord/pixel.h" #include "coord/tile.h" #include "util/math.h" +#include "util/math_constants.h" namespace openage::coord { @@ -53,7 +54,7 @@ float scene2_delta::to_angle(const coord::scene2_delta &other) const { auto det = other.ne.to_float() * this->se.to_float() - this->ne.to_float() * other.se.to_float(); auto dot = this->ne.to_float() * other.ne.to_float() + this->se.to_float() * other.se.to_float(); - auto angle = std::atan2(det, dot) * 180 / std::numbers::pi; + auto angle = std::atan2(det, dot) * 180 / math::PI; if (angle < 0) { angle += 360; } diff --git a/libopenage/curve/CMakeLists.txt b/libopenage/curve/CMakeLists.txt index 8554b14f39..1aa1efb55b 100644 --- a/libopenage/curve/CMakeLists.txt +++ b/libopenage/curve/CMakeLists.txt @@ -1,7 +1,6 @@ add_sources(libopenage base_curve.cpp continuous.cpp - curve.cpp discrete.cpp discrete_mod.cpp interpolated.cpp diff --git a/libopenage/curve/base_curve.h b/libopenage/curve/base_curve.h index 5534cf43dc..8c56586637 100644 --- a/libopenage/curve/base_curve.h +++ b/libopenage/curve/base_curve.h @@ -2,14 +2,30 @@ #pragma once +#include +#include +#include +#include #include +#include +#include + +#include "error/error.h" +#include "log/log.h" +#include "log/message.h" #include "curve/keyframe_container.h" -#include "event/event_loop.h" #include "event/evententity.h" +#include "time/time.h" +#include "util/fixed_point.h" + +namespace openage { +namespace event { +class EventLoop; +} -namespace openage::curve { +namespace curve { template class BaseCurve : public event::EventEntity { @@ -35,9 +51,9 @@ class BaseCurve : public event::EventEntity { BaseCurve(BaseCurve &&) = default; - virtual T get(const time_t &t) const = 0; + virtual T get(const time::time_t &t) const = 0; - virtual T operator()(const time_t &now) { + virtual T operator()(const time::time_t &now) { return get(now); } @@ -46,14 +62,14 @@ class BaseCurve : public event::EventEntity { * * @return Keyframe time and value. */ - virtual std::pair frame(const time_t &time) const; + virtual std::pair frame(const time::time_t &time) const; /** * Get the closest keyframe with t > \p time. * * @return Keyframe time and value. */ - virtual std::pair next_frame(const time_t &time) const; + virtual std::pair next_frame(const time::time_t &time) const; /** * Insert/overwrite given value at given time and erase all elements @@ -61,26 +77,26 @@ class BaseCurve : public event::EventEntity { * If multiple elements exist at the given time, * overwrite the last one. */ - virtual void set_last(const time_t &at, const T &value); + virtual void set_last(const time::time_t &at, const T &value); /** * Insert a value at the given time. * If there already is a value at this time, * the value is inserted directly after the existing one. */ - virtual void set_insert(const time_t &at, const T &value); + virtual void set_insert(const time::time_t &at, const T &value); /** * Insert a value at the given time. * If there already is a value at this time, * the given value will replace the first value with the same time. */ - virtual void set_replace(const time_t &at, const T &value); + virtual void set_replace(const time::time_t &at, const T &value); /** * Remove all values that have the given time. */ - virtual void erase(const time_t &at); + virtual void erase(const time::time_t &at); /** * Integrity check, for debugging/testing reasons only. @@ -99,7 +115,7 @@ class BaseCurve : public event::EventEntity { * the keyframes of \p other. */ void sync(const BaseCurve &other, - const time_t &start = std::numeric_limits::min()); + const time::time_t &start = std::numeric_limits::min()); /** * Copy keyframes from another curve (with a different element type) to this curve. @@ -118,7 +134,7 @@ class BaseCurve : public event::EventEntity { template void sync(const BaseCurve &other, const std::function &converter, - const time_t &start = std::numeric_limits::min()); + const time::time_t &start = std::numeric_limits::min()); /** * Get the identifier of this curve. @@ -184,7 +200,7 @@ class BaseCurve : public event::EventEntity { template -void BaseCurve::set_last(const time_t &at, const T &value) { +void BaseCurve::set_last(const time::time_t &at, const T &value) { auto hint = this->container.last(at, this->last_element); // erase max one same-time value @@ -202,7 +218,7 @@ void BaseCurve::set_last(const time_t &at, const T &value) { template -void BaseCurve::set_insert(const time_t &at, const T &value) { +void BaseCurve::set_insert(const time::time_t &at, const T &value) { auto hint = this->container.insert_after(at, value, this->last_element); // check if this is now the final keyframe if (hint->time > this->last_element->time) { @@ -213,28 +229,28 @@ void BaseCurve::set_insert(const time_t &at, const T &value) { template -void BaseCurve::set_replace(const time_t &at, const T &value) { +void BaseCurve::set_replace(const time::time_t &at, const T &value) { this->container.insert_overwrite(at, value, this->last_element); this->changes(at); } template -void BaseCurve::erase(const time_t &at) { +void BaseCurve::erase(const time::time_t &at) { this->last_element = this->container.erase(at, this->last_element); this->changes(at); } template -std::pair BaseCurve::frame(const time_t &time) const { +std::pair BaseCurve::frame(const time::time_t &time) const { auto e = this->container.last(time, this->container.end()); return std::make_pair(e->time, e->value); } template -std::pair BaseCurve::next_frame(const time_t &time) const { +std::pair BaseCurve::next_frame(const time::time_t &time) const { auto e = this->container.last(time, this->container.end()); e++; return std::make_pair(e->time, e->value); @@ -254,10 +270,10 @@ std::string BaseCurve::str() const { template void BaseCurve::check_integrity() const { - time_t last_time = std::numeric_limits::min(); + time::time_t last_time = std::numeric_limits::min(); for (const auto &keyframe : this->container) { if (keyframe.time < last_time) { - throw Error{ERR << "curve is broken after t=" << last_time << ": " << this->str()}; + throw Error{MSG(err) << "curve is broken after t=" << last_time << ": " << this->str()}; } last_time = keyframe.time; } @@ -265,9 +281,9 @@ void BaseCurve::check_integrity() const { template void BaseCurve::sync(const BaseCurve &other, - const time_t &start) { + const time::time_t &start) { // Copy keyframes between containers for t >= start - this->last_element = this->container.sync_after(other.container, start); + this->last_element = this->container.sync(other.container, start); // Check if this->get() returns the same value as other->get() for t = start // If not, insert a new keyframe at start @@ -284,9 +300,9 @@ template template void BaseCurve::sync(const BaseCurve &other, const std::function &converter, - const time_t &start) { + const time::time_t &start) { // Copy keyframes between containers for t >= start - this->last_element = this->container.sync_after(other.get_container(), converter, start); + this->last_element = this->container.sync(other.get_container(), converter, start); // Check if this->get() returns the same value as other->get() for t = start // If not, insert a new keyframe at start @@ -298,4 +314,5 @@ void BaseCurve::sync(const BaseCurve &other, this->changes(start); } -} // namespace openage::curve +} // namespace curve +} // namespace openage diff --git a/libopenage/curve/continuous.h b/libopenage/curve/continuous.h index 0d32f14629..3eb7170ddb 100644 --- a/libopenage/curve/continuous.h +++ b/libopenage/curve/continuous.h @@ -1,12 +1,13 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include #include +#include + +#include "curve/interpolated.h" +#include "time/time.h" -#include "interpolated.h" -#include "../log/log.h" namespace openage::curve { @@ -19,9 +20,9 @@ namespace openage::curve { * interpolation. * * The bound template type T has to implement `operator+(T)` and - * `operator*(time_t)`. + * `operator*(time::time_t)`. */ -template +template class Continuous : public Interpolated { public: using Interpolated::Interpolated; @@ -32,10 +33,10 @@ class Continuous : public Interpolated { * If multiple elements exist at the given time, * overwrite all of them. */ - void set_last(const time_t &t, const T &value) override; + void set_last(const time::time_t &t, const T &value) override; /** This just calls set_replace in order to guarantee the continuity. */ - void set_insert(const time_t &t, const T &value) override; + void set_insert(const time::time_t &t, const T &value) override; /** human readable identifier */ std::string idstr() const override; @@ -43,7 +44,7 @@ class Continuous : public Interpolated { template -void Continuous::set_last(const time_t &at, const T &value) { +void Continuous::set_last(const time::time_t &at, const T &value) { auto hint = this->container.last(at, this->last_element); // erase all same-time entries @@ -61,7 +62,7 @@ void Continuous::set_last(const time_t &at, const T &value) { template -void Continuous::set_insert(const time_t &t, const T &value) { +void Continuous::set_insert(const time::time_t &t, const T &value) { this->set_replace(t, value); } @@ -81,4 +82,4 @@ std::string Continuous::idstr() const { } -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/curve.cpp b/libopenage/curve/curve.cpp deleted file mode 100644 index 4ec84fe407..0000000000 --- a/libopenage/curve/curve.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. - -#include "curve.h" - -namespace openage::curve { - -// This file is intended to be empty - -} // openage::curve diff --git a/libopenage/curve/discrete.h b/libopenage/curve/discrete.h index 085f85b0fd..cdcb3daa31 100644 --- a/libopenage/curve/discrete.h +++ b/libopenage/curve/discrete.h @@ -4,9 +4,12 @@ #include #include +#include +#include #include -#include "base_curve.h" +#include "curve/base_curve.h" +#include "time/time.h" namespace openage::curve { @@ -29,7 +32,7 @@ class Discrete : public BaseCurve { * Does not interpolate anything, * just returns gives the raw value of the last keyframe with time <= t. */ - T get(const time_t &t) const override; + T get(const time::time_t &t) const override; /** * Get a human readable id string. @@ -39,17 +42,17 @@ class Discrete : public BaseCurve { /** * Return the last time and keyframe with time <= t. */ - std::pair get_time(const time_t &t) const; + std::pair get_time(const time::time_t &t) const; /** * Return, if existing, the time and value of keyframe with time < t */ - std::optional> get_previous(const time_t &t) const; + std::optional> get_previous(const time::time_t &t) const; }; template -T Discrete::get(const time_t &time) const { +T Discrete::get(const time::time_t &time) const { auto e = this->container.last(time, this->last_element); this->last_element = e; // TODO if Caching? return e->value; @@ -72,7 +75,7 @@ std::string Discrete::idstr() const { template -std::pair Discrete::get_time(const time_t &time) const { +std::pair Discrete::get_time(const time::time_t &time) const { auto e = this->container.last(time, this->last_element); this->last_element = e; return std::make_pair(e->time, e->value); @@ -80,7 +83,7 @@ std::pair Discrete::get_time(const time_t &time) const { template -std::optional> Discrete::get_previous(const time_t &time) const { +std::optional> Discrete::get_previous(const time::time_t &time) const { auto e = this->container.last(time, this->last_element); this->last_element = e; diff --git a/libopenage/curve/discrete_mod.h b/libopenage/curve/discrete_mod.h index ef16b23088..a641541688 100644 --- a/libopenage/curve/discrete_mod.h +++ b/libopenage/curve/discrete_mod.h @@ -2,7 +2,16 @@ #pragma once +#include +#include +#include +#include +#include + +#include "curve/base_curve.h" #include "curve/discrete.h" +#include "time/time.h" +#include "util/fixed_point.h" namespace openage::curve { @@ -30,9 +39,9 @@ class DiscreteMod : public Discrete { // Override insertion/erasure to get interval time - void set_last(const time_t &at, const T &value) override; - void set_insert(const time_t &at, const T &value) override; - void erase(const time_t &at) override; + void set_last(const time::time_t &at, const T &value) override; + void set_insert(const time::time_t &at, const T &value) override; + void erase(const time::time_t &at) override; /** * Get a human readable id string. @@ -42,35 +51,35 @@ class DiscreteMod : public Discrete { /** * Get the raw value of the last keyframe with time <= (t - start) % interval_length. */ - T get_mod(const time_t &t, const time_t &start) const; + T get_mod(const time::time_t &t, const time::time_t &start) const; /** * Get the last time and keyframe with time <= (t - start) % interval_length. */ - std::pair get_time_mod(const time_t &t, const time_t &start) const; + std::pair get_time_mod(const time::time_t &t, const time::time_t &start) const; /** * Get, if existing, the time and value of keyframe with time < (t - start) % interval_length. */ - std::optional> get_previous_mod(const time_t &t, const time_t &start) const; + std::optional> get_previous_mod(const time::time_t &t, const time::time_t &start) const; private: /** * Length of the time interval of this curve (time between first and last keyframe). */ - time_t time_length; + time::time_t time_length; }; template -void DiscreteMod::set_last(const time_t &at, const T &value) { +void DiscreteMod::set_last(const time::time_t &at, const T &value) { BaseCurve::set_last(at, value); this->time_length = at; } template -void DiscreteMod::set_insert(const time_t &at, const T &value) { +void DiscreteMod::set_insert(const time::time_t &at, const T &value) { BaseCurve::set_insert(at, value); if (this->time_length < at) { @@ -80,7 +89,7 @@ void DiscreteMod::set_insert(const time_t &at, const T &value) { template -void DiscreteMod::erase(const time_t &at) { +void DiscreteMod::erase(const time::time_t &at) { BaseCurve::erase(at); if (this->time_length == at) { @@ -105,40 +114,40 @@ std::string DiscreteMod::idstr() const { template -T DiscreteMod::get_mod(const time_t &time, const time_t &start) const { - time_t offset = time - start; +T DiscreteMod::get_mod(const time::time_t &time, const time::time_t &start) const { + time::time_t offset = time - start; if (this->time_length == 0) { // modulo would fail here so return early return Discrete::get(0); } - time_t mod = offset % this->time_length; + time::time_t mod = offset % this->time_length; return Discrete::get(mod); } template -std::pair DiscreteMod::get_time_mod(const time_t &time, const time_t &start) const { - time_t offset = time - start; +std::pair DiscreteMod::get_time_mod(const time::time_t &time, const time::time_t &start) const { + time::time_t offset = time - start; if (this->time_length == 0) { // modulo would fail here so return early return Discrete::get_time(0); } - time_t mod = offset % this->time_length; + time::time_t mod = offset % this->time_length; return Discrete::get_time(mod); } template -std::optional> DiscreteMod::get_previous_mod(const time_t &time, const time_t &start) const { - time_t offset = time - start; +std::optional> DiscreteMod::get_previous_mod(const time::time_t &time, const time::time_t &start) const { + time::time_t offset = time - start; if (this->time_length == 0) { // modulo would fail here so return early return Discrete::get_previous(0); } - time_t mod = offset % this->time_length; + time::time_t mod = offset % this->time_length; return Discrete::get_previous(mod); } diff --git a/libopenage/curve/interpolated.h b/libopenage/curve/interpolated.h index bdb1fe1743..49a189a124 100644 --- a/libopenage/curve/interpolated.h +++ b/libopenage/curve/interpolated.h @@ -2,10 +2,10 @@ #pragma once -#include +#include "curve/base_curve.h" +#include "time/time.h" +#include "util/fixed_point.h" -#include "../log/log.h" -#include "base_curve.h" namespace openage::curve { @@ -15,7 +15,7 @@ namespace openage::curve { * Extends the value container to support interpolation between values. * * The bound template type T has to implement `operator +(T)` and - * `operator *(time_t)`. + * `operator *(time::time_t)`. */ template class Interpolated : public BaseCurve { @@ -34,19 +34,19 @@ class Interpolated : public BaseCurve { * val([a:x, b:y], t) = x + (y - x)/(b - a) * (t - a) */ - T get(const time_t &) const override; + T get(const time::time_t &) const override; }; template -T Interpolated::get(const time_t &time) const { +T Interpolated::get(const time::time_t &time) const { const auto &e = this->container.last(time, this->last_element); this->last_element = e; auto nxt = e; ++nxt; - time_t interval = 0; + time::time_t interval = 0; auto offset = time - e->time; diff --git a/libopenage/curve/iterator.h b/libopenage/curve/iterator.h index b965b65640..2500e083cd 100644 --- a/libopenage/curve/iterator.h +++ b/libopenage/curve/iterator.h @@ -1,8 +1,10 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include "curve.h" +#include "time/time.h" +#include "util/fixed_point.h" + namespace openage::curve { @@ -11,7 +13,7 @@ namespace openage::curve { */ template + typename iterator_t = typename container_t::const_iterator> class CurveIterator { public: /** @@ -28,12 +30,11 @@ class CurveIterator { /** * The iterator needs a reference to the container */ - explicit CurveIterator(const container_t *c) - : + explicit CurveIterator(const container_t *c) : base{}, container{c}, - from{-std::numeric_limits::max()}, - to{+std::numeric_limits::max()} {} + from{-std::numeric_limits::max()}, + to{+std::numeric_limits::max()} {} protected: /** @@ -41,9 +42,8 @@ class CurveIterator { */ CurveIterator(const iterator_t &base, const container_t *container, - const time_t &from, - const time_t &to) - : + const time::time_t &from, + const time::time_t &to) : base{base}, container{container}, from{from}, @@ -51,21 +51,21 @@ class CurveIterator { public: /** Default copy c'tor */ - CurveIterator (const CurveIterator &) = default; + CurveIterator(const CurveIterator &) = default; virtual ~CurveIterator() = default; /** Default assignment operator */ - CurveIterator &operator= ( + CurveIterator &operator=( const CurveIterator &) = default; /** Dereference will call the virtual function */ - virtual const val_t &operator *() const { + virtual const val_t &operator*() const { return this->value(); } /** Dereference will call the virutal function */ - virtual const val_t *operator ->() const { + virtual const val_t *operator->() const { return &this->value(); } @@ -73,7 +73,7 @@ class CurveIterator { * For equalness only the base iterator will be testet - not the timespans * this is defined in. */ - virtual bool operator ==(const CurveIterator &rhs) const { + virtual bool operator==(const CurveIterator &rhs) const { return this->base == rhs.base; } @@ -81,17 +81,18 @@ class CurveIterator { * For unequalness only the base iterator will be testet - not the timespans * this is defined in. */ - virtual bool operator !=(const CurveIterator &rhs) const { + virtual bool operator!=(const CurveIterator &rhs) const { return this->base != rhs.base; } /** * Advance to the next valid element. */ - virtual CurveIterator &operator ++() { + virtual CurveIterator &operator++() { do { ++this->base; - } while (this->container->end().base != this->base and not this->valid()); + } + while (this->container->end().base != this->base and not this->valid()); return *this; } @@ -106,14 +107,14 @@ class CurveIterator { /** * Access the lower end value of the defined time frame */ - const time_t &get_from() const { + const time::time_t &get_from() const { return from; } /** * Access the higher end value of the defined time frame */ - const time_t &get_to() const { + const time::time_t &get_to() const { return to; } @@ -125,11 +126,11 @@ class CurveIterator { const container_t *container; /// The time, from where this iterator started to iterate. - time_t from; + time::time_t from; /// The time, to where this iterator will iterate. - time_t to; + time::time_t to; }; -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/keyframe.h b/libopenage/curve/keyframe.h index a0fc39d1e6..d6b90af4b5 100644 --- a/libopenage/curve/keyframe.h +++ b/libopenage/curve/keyframe.h @@ -1,10 +1,10 @@ -// Copyright 2019-2019 the openage authors. See copying.md for legal info. +// Copyright 2019-2023 the openage authors. See copying.md for legal info. #pragma once -#include +#include "time/time.h" +#include "util/fixed_point.h" -#include "curve.h" namespace openage::curve { @@ -23,18 +23,18 @@ class Keyframe { /** * New, default-constructed element at the given time */ - Keyframe(const time_t &time) : + Keyframe(const time::time_t &time) : time{time} {} /** * New element fron time and value */ - Keyframe(const time_t &time, const T &value) : + Keyframe(const time::time_t &time, const T &value) : time{time}, value{value} {} - const time_t time = std::numeric_limits::min(); + const time::time_t time = std::numeric_limits::min(); T value = T{}; }; -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/keyframe_container.h b/libopenage/curve/keyframe_container.h index e025de1a4d..1d7079498b 100644 --- a/libopenage/curve/keyframe_container.h +++ b/libopenage/curve/keyframe_container.h @@ -2,14 +2,15 @@ #pragma once +#include +#include #include -#include #include -#include "curve/curve.h" #include "curve/keyframe.h" -#include "error/error.h" -#include "util/compiler.h" +#include "time/time.h" +#include "util/fixed_point.h" + namespace openage::curve { @@ -78,7 +79,7 @@ class KeyframeContainer { * Get the last element in the curve which is at or before the given time. * (i.e. elem->time <= time). Given a hint where to start the search. */ - iterator last(const time_t &time, + iterator last(const time::time_t &time, const iterator &hint) const; /** @@ -89,7 +90,7 @@ class KeyframeContainer { * no chance for you to have a hint (or the container is known to be nearly * empty) */ - iterator last(const time_t &time) const { + iterator last(const time::time_t &time) const { return this->last(time, std::end(this->container)); } @@ -97,14 +98,14 @@ class KeyframeContainer { * Get the last element in the curve which is before the given time. * (i.e. elem->time < time). Given a hint where to start the search. */ - iterator last_before(const time_t &time, + iterator last_before(const time::time_t &time, const iterator &hint) const; /** * Get the last element with elem->time < time, without a hint where to start * searching. */ - iterator last_before(const time_t &time) const { + iterator last_before(const time::time_t &time) const { return this->last_before(time, std::end(this->container)); } @@ -134,7 +135,7 @@ class KeyframeContainer { * discouraged, use it only, if your really do not have the possibility to * get a hint. */ - iterator insert_before(const time_t &time, const T &value) { + iterator insert_before(const time::time_t &time, const T &value) { return this->insert_before(keyframe_t(time, value), std::end(this->container)); } @@ -143,7 +144,7 @@ class KeyframeContainer { * If there is a value with identical time, this will insert the new value * before the old one. */ - iterator insert_before(const time_t &time, const T &value, const iterator &hint) { + iterator insert_before(const time::time_t &time, const T &value, const iterator &hint) { return this->insert_before(keyframe_t(time, value), hint); } @@ -164,7 +165,7 @@ class KeyframeContainer { * from the end of the data. The use of this function is discouraged, use it * only, if your really do not have the possibility to get a hint. */ - iterator insert_overwrite(const time_t &time, const T &value) { + iterator insert_overwrite(const time::time_t &time, const T &value) { return this->insert_overwrite(keyframe_t(time, value), std::end(this->container)); } @@ -176,7 +177,7 @@ class KeyframeContainer { * Provide a insertion hint to abbreviate the search for the * insertion point. */ - iterator insert_overwrite(const time_t &time, + iterator insert_overwrite(const time::time_t &time, const T &value, const iterator &hint, bool overwrite_all = false) { @@ -196,7 +197,7 @@ class KeyframeContainer { * time from the end of the data. The use of this function is discouraged, * use it only, if your really do not have the possibility to get a hint. */ - iterator insert_after(const time_t &time, const T &value) { + iterator insert_after(const time::time_t &time, const T &value) { return this->insert_after(keyframe_t(time, value), std::end(this->container)); } @@ -205,7 +206,7 @@ class KeyframeContainer { * Create and insert a new element, which is added after a previous element with * identical time. Provide a insertion hint to abbreviate the search for the insertion point. */ - iterator insert_after(const time_t &time, const T &value, const iterator &hint) { + iterator insert_after(const time::time_t &time, const T &value, const iterator &hint) { return this->insert_after(keyframe_t(time, value), hint); } @@ -225,7 +226,7 @@ class KeyframeContainer { * Variant without hint, starts the search at the end of the container. * Returns the iterator after the deleted elements. */ - iterator erase(const time_t &time) { + iterator erase(const time::time_t &time) { return this->erase(time, std::end(this->container)); } @@ -238,7 +239,7 @@ class KeyframeContainer { * Or, if no elements with this time exist, * the iterator to the first element after the requested time is returned */ - iterator erase(const time_t &time, + iterator erase(const time::time_t &time, const iterator &hint) { return this->erase_group(time, this->last(time, hint)); } @@ -279,8 +280,8 @@ class KeyframeContainer { * Using the default value replaces ALL keyframes of \p this with * the keyframes of \p other. */ - iterator sync_after(const KeyframeContainer &other, - const time_t &start = std::numeric_limits::min()); + iterator sync(const KeyframeContainer &other, + const time::time_t &start = std::numeric_limits::min()); /** * Copy keyframes from another container (with a different element type) to this container. @@ -295,9 +296,9 @@ class KeyframeContainer { * the keyframes of \p other. */ template - iterator sync_after(const KeyframeContainer &other, - const std::function &converter, - const time_t &start = std::numeric_limits::min()); + iterator sync(const KeyframeContainer &other, + const std::function &converter, + const time::time_t &start = std::numeric_limits::min()); /** * Debugging method to be used from gdb to understand bugs better. @@ -313,7 +314,7 @@ class KeyframeContainer { * Erase elements with this time. * The iterator has to point to the last element of the same-time group. */ - iterator erase_group(const time_t &time, + iterator erase_group(const time::time_t &time, const iterator &last_elem); /** @@ -327,7 +328,7 @@ template KeyframeContainer::KeyframeContainer() { // Create a default element at -Inf, that can always be dereferenced - so // there will by definition never be a element that cannot be dereferenced - this->container.push_back(keyframe_t(std::numeric_limits::min(), T())); + this->container.push_back(keyframe_t(std::numeric_limits::min(), T())); } @@ -335,7 +336,7 @@ template KeyframeContainer::KeyframeContainer(const T &defaultval) { // Create a default element at -Inf, that can always be dereferenced - so // there will by definition never be a element that cannot be dereferenced - this->container.push_back(keyframe_t(std::numeric_limits::min(), defaultval)); + this->container.push_back(keyframe_t(std::numeric_limits::min(), defaultval)); } @@ -354,7 +355,7 @@ size_t KeyframeContainer::size() const { * that determines the curve value for a searched time. */ template -typename KeyframeContainer::iterator KeyframeContainer::last(const time_t &time, +typename KeyframeContainer::iterator KeyframeContainer::last(const time::time_t &time, const iterator &hint) const { iterator e = hint; auto end = std::end(this->container); @@ -388,7 +389,7 @@ typename KeyframeContainer::iterator KeyframeContainer::last(const time_t * first element that matches the search time. */ template -typename KeyframeContainer::iterator KeyframeContainer::last_before(const time_t &time, +typename KeyframeContainer::iterator KeyframeContainer::last_before(const time::time_t &time, const iterator &hint) const { iterator e = hint; auto end = std::end(this->container); @@ -511,8 +512,8 @@ KeyframeContainer::erase(KeyframeContainer::iterator e) { template typename KeyframeContainer::iterator -KeyframeContainer::sync_after(const KeyframeContainer &other, - const time_t &start) { +KeyframeContainer::sync(const KeyframeContainer &other, + const time::time_t &start) { // Delete elements after start time iterator at = this->last_before(start, this->end()); at = this->erase_after(at); @@ -535,9 +536,9 @@ KeyframeContainer::sync_after(const KeyframeContainer &other, template template typename KeyframeContainer::iterator -KeyframeContainer::sync_after(const KeyframeContainer &other, - const std::function &converter, - const time_t &start) { +KeyframeContainer::sync(const KeyframeContainer &other, + const std::function &converter, + const time::time_t &start) { // Delete elements after start time iterator at = this->last_before(start, this->end()); at = this->erase_after(at); @@ -560,7 +561,7 @@ KeyframeContainer::sync_after(const KeyframeContainer &other, template typename KeyframeContainer::iterator -KeyframeContainer::erase_group(const time_t &time, +KeyframeContainer::erase_group(const time::time_t &time, const iterator &last_elem) { iterator at = last_elem; diff --git a/libopenage/curve/map.h b/libopenage/curve/map.h index 8fefda4023..3a8374a128 100644 --- a/libopenage/curve/map.h +++ b/libopenage/curve/map.h @@ -1,13 +1,15 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include "curve.h" -#include "map_filter_iterator.h" - -#include #include +#include #include +#include + +#include "curve/map_filter_iterator.h" +#include "time/time.h" +#include "util/fixed_point.h" namespace openage::curve { @@ -20,15 +22,14 @@ template class UnorderedMap { /** Internal container to access all data and metadata */ struct map_element { - map_element (const val_t &v, const time_t &a, const time_t &d) - : + map_element(const val_t &v, const time::time_t &a, const time::time_t &d) : value(v), alive(a), dead(d) {} val_t value; - time_t alive; - time_t dead; + time::time_t alive; + time::time_t dead; }; /** @@ -41,97 +42,94 @@ class UnorderedMap { using const_iterator = typename std::unordered_map::const_iterator; std::optional> - operator ()(const time_t&, const key_t &) const; + operator()(const time::time_t &, const key_t &) const; std::optional> - at(const time_t &, const key_t &) const; + at(const time::time_t &, const key_t &) const; MapFilterIterator - begin(const time_t &e = std::numeric_limits::max()) const; + begin(const time::time_t &e = std::numeric_limits::max()) const; MapFilterIterator - end(const time_t &e = std::numeric_limits::max()) const; + end(const time::time_t &e = std::numeric_limits::max()) const; MapFilterIterator - insert(const time_t &birth, const key_t &, const val_t &); + insert(const time::time_t &birth, const key_t &, const val_t &); MapFilterIterator - insert(const time_t &birth, const time_t &death, const key_t &key, const val_t &value); + insert(const time::time_t &birth, const time::time_t &death, const key_t &key, const val_t &value); MapFilterIterator - between(const time_t &start, const time_t &to) const; + between(const time::time_t &start, const time::time_t &to) const; - void birth(const time_t &, const key_t &); - void birth(const time_t &, + void birth(const time::time_t &, const key_t &); + void birth(const time::time_t &, const MapFilterIterator &); - void kill(const time_t &, const key_t &); - void kill(const time_t &, + void kill(const time::time_t &, const key_t &); + void kill(const time::time_t &, const MapFilterIterator &); // remove all dead elements before that point in time - void clean(const time_t &); + void clean(const time::time_t &); /** * gdb helper method. */ void dump() { for (auto i : container) { - std::cout << "Element: " << i.second.value << std::endl;; + std::cout << "Element: " << i.second.value << std::endl; } } }; -template +template std::optional>> -UnorderedMap::operator()(const time_t &time, +UnorderedMap::operator()(const time::time_t &time, const key_t &key) const { return this->at(time, key); } -template +template std::optional>> -UnorderedMap::at(const time_t & time, - const key_t & key) const { +UnorderedMap::at(const time::time_t &time, + const key_t &key) const { auto e = this->container.find(key); - if (e != this->container.end() and - e->second.alive <= time and - e->second.dead > time) { - + if (e != this->container.end() and e->second.alive <= time and e->second.dead > time) { return MapFilterIterator>( e, this, time, - std::numeric_limits::max() - ); - } else { + std::numeric_limits::max()); + } + else { return {}; } } -template +template MapFilterIterator> -UnorderedMap::begin(const time_t &time) const { +UnorderedMap::begin(const time::time_t &time) const { return MapFilterIterator>( this->container.begin(), this, time, - std::numeric_limits::max()); + std::numeric_limits::max()); } -template +template MapFilterIterator> -UnorderedMap::end(const time_t &time) const { +UnorderedMap::end(const time::time_t &time) const { return MapFilterIterator>( this->container.end(), this, - -std::numeric_limits::max(), + -std::numeric_limits::max(), time); } -template +template MapFilterIterator> -UnorderedMap::between(const time_t &from, const time_t &to) const { +UnorderedMap::between(const time::time_t &from, const time::time_t &to) const { auto it = MapFilterIterator>( this->container.begin(), this, @@ -144,22 +142,22 @@ UnorderedMap::between(const time_t &from, const time_t &to) const return it; } -template +template MapFilterIterator> -UnorderedMap::insert(const time_t &alive, +UnorderedMap::insert(const time::time_t &alive, const key_t &key, const val_t &value) { return this->insert( alive, - std::numeric_limits::max(), + std::numeric_limits::max(), key, value); } -template +template MapFilterIterator> -UnorderedMap::insert(const time_t &alive, - const time_t &dead, +UnorderedMap::insert(const time::time_t &alive, + const time::time_t &dead, const key_t &key, const val_t &value) { map_element e(value, alive, dead); @@ -171,8 +169,8 @@ UnorderedMap::insert(const time_t &alive, dead); } -template -void UnorderedMap::birth(const time_t &time, +template +void UnorderedMap::birth(const time::time_t &time, const key_t &key) { auto it = this->container.find(key); if (it != this->container.end()) { @@ -180,15 +178,14 @@ void UnorderedMap::birth(const time_t &time, } } -template -void UnorderedMap::birth(const time_t &time, - const MapFilterIterator &it) { +template +void UnorderedMap::birth(const time::time_t &time, + const MapFilterIterator &it) { it->second.alive = time; } -template -void UnorderedMap::kill(const time_t &time, +template +void UnorderedMap::kill(const time::time_t &time, const key_t &key) { auto it = this->container.find(key); if (it != this->container.end()) { @@ -196,15 +193,15 @@ void UnorderedMap::kill(const time_t &time, } } -template -void UnorderedMap::kill(const time_t &time, +template +void UnorderedMap::kill(const time::time_t &time, const MapFilterIterator &it) { it->second.dead = time; } -template -void UnorderedMap::clean(const time_t &) { +template +void UnorderedMap::clean(const time::time_t &) { // TODO save everything to a file and be happy. } -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/map_filter_iterator.h b/libopenage/curve/map_filter_iterator.h index 97ff70960e..e514330f67 100644 --- a/libopenage/curve/map_filter_iterator.h +++ b/libopenage/curve/map_filter_iterator.h @@ -1,12 +1,10 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include "curve.h" -#include "iterator.h" +#include "curve/iterator.h" +#include "time/time.h" -#include -#include namespace openage::curve { @@ -30,9 +28,8 @@ class MapFilterIterator : public CurveIterator { */ MapFilterIterator(const iterator_t &base, const container_t *container, - const time_t &from, - const time_t &to) - : + const time::time_t &from, + const time::time_t &to) : CurveIterator(base, container, from, to) {} MapFilterIterator(const MapFilterIterator &) = default; @@ -58,7 +55,6 @@ class MapFilterIterator : public CurveIterator { const key_t &key() const { return this->get_base()->first; } - }; -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/queue.h b/libopenage/curve/queue.h index f48213842d..3ac8d20d9a 100644 --- a/libopenage/curve/queue.h +++ b/libopenage/curve/queue.h @@ -2,15 +2,25 @@ #pragma once +#include #include #include +#include +#include -#include "curve/curve.h" +#include "curve/iterator.h" #include "curve/queue_filter_iterator.h" #include "event/evententity.h" +#include "time/time.h" +#include "util/fixed_point.h" -namespace openage::curve { +namespace openage { +namespace event { +class EventLoop; +} + +namespace curve { /** * A container that manages events on a timeline. Every event has exactly one @@ -20,14 +30,14 @@ namespace openage::curve { template class Queue : public event::EventEntity { struct queue_wrapper { - time_t _time; + time::time_t _time; T value; - queue_wrapper(const time_t &time, const T &value) : + queue_wrapper(const time::time_t &time, const T &value) : _time{time}, value{value} {} - time_t time() const { + time::time_t time() const { return _time; } }; @@ -56,7 +66,7 @@ class Queue : public event::EventEntity { * @param time The time to get the element at. * @return Queue element. */ - const T &front(const time_t &time) const; + const T &front(const time::time_t &time) const; /** * Get the first element in the queue at the given time. @@ -64,14 +74,14 @@ class Queue : public event::EventEntity { * @param time The time to get the element at. * @param value Queue element. */ - const T &pop_front(const time_t &time); + const T &pop_front(const time::time_t &time); /** * Check if the queue is empty at a given time. * * @return true if the queue is empty, false otherwise. */ - bool empty(const time_t &time) const; + bool empty(const time::time_t &time) const; // Modifying access @@ -82,7 +92,7 @@ class Queue : public event::EventEntity { * @return Iterator to the first element. */ QueueFilterIterator> begin( - const time_t &t = -std::numeric_limits::max()) const; + const time::time_t &t = -std::numeric_limits::max()) const; /** * Get an iterator to the last element in the queue at the given time. @@ -91,7 +101,7 @@ class Queue : public event::EventEntity { * @return Iterator to the last element. */ QueueFilterIterator> end( - const time_t &t = std::numeric_limits::max()) const; + const time::time_t &t = std::numeric_limits::max()) const; /** * Get an iterator to elements that are in the queue between two time frames. @@ -101,8 +111,8 @@ class Queue : public event::EventEntity { * @return Iterator to the first element in the time frame. */ QueueFilterIterator> between( - const time_t &begin = std::numeric_limits::max(), - const time_t &end = std::numeric_limits::max()) const; + const time::time_t &begin = std::numeric_limits::max(), + const time::time_t &end = std::numeric_limits::max()) const; /** * Erase an element from the queue. @@ -118,14 +128,14 @@ class Queue : public event::EventEntity { * @param e The element to insert. * @return Iterator to the inserted element. */ - QueueFilterIterator> insert(const time_t &, const T &e); + QueueFilterIterator> insert(const time::time_t &, const T &e); /** * Erase all elements that are at or after the given time. * * @param time The time to clear at. */ - void clear(const time_t &); + void clear(const time::time_t &); /** * Print the queue to stdout. @@ -178,30 +188,30 @@ class Queue : public event::EventEntity { template -const T &Queue::front(const time_t &t) const { +const T &Queue::front(const time::time_t &t) const { return this->begin(t).value(); } template -bool Queue::empty(const time_t &time) const { +bool Queue::empty(const time::time_t &time) const { return this->last_front == this->begin(time).get_base(); } template -inline const T &Queue::pop_front(const time_t &time) { +inline const T &Queue::pop_front(const time::time_t &time) { this->last_front = this->begin(time).get_base(); return this->front(time); } template -QueueFilterIterator> Queue::begin(const time_t &t) const { +QueueFilterIterator> Queue::begin(const time::time_t &t) const { for (auto it = this->container.begin(); it != this->container.end(); ++it) { if (it->time() >= t) { return QueueFilterIterator>( it, this, t, - std::numeric_limits::max()); + std::numeric_limits::max()); } } @@ -210,19 +220,19 @@ QueueFilterIterator> Queue::begin(const time_t &t) const { template -QueueFilterIterator> Queue::end(const time_t &t) const { +QueueFilterIterator> Queue::end(const time::time_t &t) const { return QueueFilterIterator>( container.end(), this, t, - std::numeric_limits::max()); + std::numeric_limits::max()); } template QueueFilterIterator> Queue::between( - const time_t &begin, - const time_t &end) const { + const time::time_t &begin, + const time::time_t &end) const { auto it = QueueFilterIterator>( container.begin(), this, @@ -244,7 +254,7 @@ void Queue::erase(const CurveIterator> &it) { template QueueFilterIterator> Queue::insert( - const time_t &time, + const time::time_t &time, const T &e) { const_iterator insertion_point = this->container.end(); for (auto it = this->container.begin(); it != this->container.end(); ++it) { @@ -262,7 +272,7 @@ QueueFilterIterator> Queue::insert( insertion_point, this, time, - std::numeric_limits::max()); + std::numeric_limits::max()); if (!ct.valid()) { ++ct; @@ -275,7 +285,7 @@ QueueFilterIterator> Queue::insert( template -void Queue::clear(const time_t &time) { +void Queue::clear(const time::time_t &time) { for (auto it = this->container.begin(); it != this->container.end() and it->time() < time; it = this->container.erase(it)) { @@ -285,4 +295,5 @@ void Queue::clear(const time_t &time) { } -} // namespace openage::curve +} // namespace curve +} // namespace openage diff --git a/libopenage/curve/queue_filter_iterator.h b/libopenage/curve/queue_filter_iterator.h index 0c6eaaf18c..b8ecf77036 100644 --- a/libopenage/curve/queue_filter_iterator.h +++ b/libopenage/curve/queue_filter_iterator.h @@ -1,12 +1,9 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include "curve.h" -#include "iterator.h" - -#include -#include +#include "curve/iterator.h" +#include "time/time.h" namespace openage::curve { @@ -19,8 +16,8 @@ namespace openage::curve { * It depends on val_t as its value type, container_t is the container * to operate on and the function valid_f, that checks if an element is alive. */ -template +template class QueueFilterIterator : public CurveIterator { public: using const_iterator = typename container_t::const_iterator; @@ -30,15 +27,13 @@ class QueueFilterIterator : public CurveIterator(base, base_container, from, to) {} virtual bool valid() const override { if (this->container->end().get_base() != this->get_base()) { - return (this->get_base()->time() >= this->from and - this->get_base()->time() < this->to); + return (this->get_base()->time() >= this->from and this->get_base()->time() < this->to); } return false; } @@ -49,4 +44,4 @@ class QueueFilterIterator : public CurveIterator #include +#include + +#include "curve/interpolated.h" +#include "time/time.h" -#include "interpolated.h" -#include "../log/log.h" namespace openage::curve { @@ -22,9 +23,9 @@ namespace openage::curve { * Use the insertion operators of `ValueContainer`: `set_last`, `set_insert` and `set_replace`. * * The bound template type T has to implement `operator +(T)` and - * `operator *(time_t)`. + * `operator *(time::time_t)`. */ -template +template class Segmented : public Interpolated { public: using Interpolated::Interpolated; @@ -34,14 +35,14 @@ class Segmented : public Interpolated { * The right value is used for queries at >= time, * the left value for queries at < time. */ - void set_insert_jump(const time_t &, const T &leftval, const T &rightval); + void set_insert_jump(const time::time_t &, const T &leftval, const T &rightval); /** * Insert/replace a value jump with given left and right values. * All following curve keyframes will be deleted, so the * last two values of the curve will be `leftval` and `rightval`. */ - void set_last_jump(const time_t &, const T &leftval, const T &rightval); + void set_last_jump(const time::time_t &, const T &leftval, const T &rightval); /** human readable identifier */ std::string idstr() const override; @@ -49,7 +50,7 @@ class Segmented : public Interpolated { template -void Segmented::set_insert_jump(const time_t &at, const T &leftval, const T &rightval) { +void Segmented::set_insert_jump(const time::time_t &at, const T &leftval, const T &rightval) { auto hint = this->container.insert_overwrite(at, leftval, this->last_element, true); this->container.insert_after(at, rightval, hint); this->changes(at); @@ -57,7 +58,7 @@ void Segmented::set_insert_jump(const time_t &at, const T &leftval, const T & template -void Segmented::set_last_jump(const time_t &at, const T &leftval, const T &rightval) { +void Segmented::set_last_jump(const time::time_t &at, const T &leftval, const T &rightval) { auto hint = this->container.last(at, this->last_element); // erase all one same-time values @@ -90,4 +91,4 @@ std::string Segmented::idstr() const { } -} // openage::curve +} // namespace openage::curve diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 2d6257f165..a5efbf2887 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -1,15 +1,22 @@ // Copyright 2017-2023 the openage authors. See copying.md for legal info. -#include "../../testing/testing.h" -#include "../continuous.h" -#include "../curve.h" -#include "../discrete.h" -#include "../map.h" -#include "../queue.h" - +#include +#include +#include +#include +#include +#include #include #include +#include "curve/iterator.h" +#include "curve/map.h" +#include "curve/map_filter_iterator.h" +#include "curve/queue.h" +#include "curve/queue_filter_iterator.h" +#include "event/event_loop.h" +#include "testing/testing.h" + namespace openage::curve::tests { diff --git a/libopenage/curve/tests/curve_types.cpp b/libopenage/curve/tests/curve_types.cpp index 53b305c055..cab8473bc3 100644 --- a/libopenage/curve/tests/curve_types.cpp +++ b/libopenage/curve/tests/curve_types.cpp @@ -1,16 +1,20 @@ // Copyright 2017-2023 the openage authors. See copying.md for legal info. -#include "curve/curve.h" +#include +#include +#include +#include + #include "curve/continuous.h" #include "curve/discrete.h" #include "curve/discrete_mod.h" +#include "curve/keyframe.h" #include "curve/keyframe_container.h" #include "curve/segmented.h" #include "event/event_loop.h" -#include "log/log.h" #include "testing/testing.h" - -#include "util/compiler.h" +#include "time/time.h" +#include "util/fixed_point.h" namespace openage::curve::tests { @@ -33,7 +37,7 @@ void curve_types() { { auto it = c.begin(); TESTEQUALS(it->value, 0); - TESTEQUALS(it->time, std::numeric_limits::min()); + TESTEQUALS(it->time, std::numeric_limits::min()); TESTEQUALS((++it)->time, 0); TESTEQUALS(it->value, 0); TESTEQUALS((++it)->time, 1); @@ -136,7 +140,7 @@ void curve_types() { { auto it = c.begin(); - TESTEQUALS(it->time, std::numeric_limits::min()); + TESTEQUALS(it->time, std::numeric_limits::min()); TESTEQUALS(it->value, 0); TESTEQUALS((++it)->time, 0); @@ -164,7 +168,7 @@ void curve_types() { // TODO: test c.insert_overwrite and c.insert_after KeyframeContainer c2; - c2.sync_after(c, 1); + c2.sync(c, 1); // now c2 should be [-inf: 0, 1: 15, 2: 20, 3: 25] TESTEQUALS(c2.last(0)->value, 0); TESTEQUALS(c2.last(1)->value, 15); diff --git a/libopenage/datastructure/tests.cpp b/libopenage/datastructure/tests.cpp index e6f140e810..95fa02a9da 100644 --- a/libopenage/datastructure/tests.cpp +++ b/libopenage/datastructure/tests.cpp @@ -1,14 +1,17 @@ -// Copyright 2014-2020 the openage authors. See copying.md for legal info. +// Copyright 2014-2023 the openage authors. See copying.md for legal info. #include "tests.h" +#include +#include +#include #include -#include "../testing/testing.h" +#include "testing/testing.h" -#include "constexpr_map.h" -#include "pairing_heap.h" -#include "concurrent_queue.h" +#include "datastructure/concurrent_queue.h" +#include "datastructure/constexpr_map.h" +#include "datastructure/pairing_heap.h" namespace openage::datastructure::tests { @@ -155,33 +158,41 @@ void constexpr_map() { static_assert(create_const_map(std::make_pair(0, 42)).size() == 1, "wrong size"); static_assert(create_const_map(std::make_pair(0, 42), - std::make_pair(13, 37)).size() == 2, + std::make_pair(13, 37)) + .size() + == 2, "wrong size"); static_assert(not create_const_map().contains(9001), "empty map doesn't contain anything"); static_assert(create_const_map(std::make_pair(42, 0), - std::make_pair(13, 37)).contains(42), + std::make_pair(13, 37)) + .contains(42), "contained element missing"); static_assert(create_const_map(std::make_pair(42, 0), - std::make_pair(13, 37)).contains(13), + std::make_pair(13, 37)) + .contains(13), "contained element missing"); static_assert(not create_const_map(std::make_pair(42, 0), - std::make_pair(13, 37)).contains(9001), + std::make_pair(13, 37)) + .contains(9001), "uncontained element seems to be contained."); static_assert(create_const_map(std::make_pair(42, 9001), - std::make_pair(13, 37)).get(42) == 9001, + std::make_pair(13, 37)) + .get(42) + == 9001, "fetched wrong value"); static_assert(create_const_map(std::make_pair(42, 9001), - std::make_pair(13, 37)).get(13) == 37, + std::make_pair(13, 37)) + .get(13) + == 37, "fetched wrong value"); - constexpr ConstMap cmap { + constexpr ConstMap cmap{ std::pair(0, 0), std::pair(13, 37), - std::pair(42, 9001) - }; + std::pair(42, 9001)}; cmap.contains(0) or TESTFAIL; not cmap.contains(18) or TESTFAIL; @@ -194,7 +205,7 @@ void constexpr_map() { /** * A simple class that can be move-constructed but not copy-constructed */ -class MoveOnly{ +class MoveOnly { private: int data; @@ -205,9 +216,11 @@ class MoveOnly{ } public: - MoveOnly(int data): data(data) {} + MoveOnly(int data) : + data(data) {} MoveOnly(const MoveOnly &) = delete; - MoveOnly(MoveOnly&& other): data(other.release()) {} + MoveOnly(MoveOnly &&other) : + data(other.release()) {} ~MoveOnly() {} int get() const { @@ -218,13 +231,16 @@ class MoveOnly{ /** * A simple class that can be copy-constructed but not move-constructed */ -class CopyOnly{ +class CopyOnly { private: int data; + public: - CopyOnly(int data): data(data) {} - CopyOnly(const CopyOnly & other): data(other.get()) {} - CopyOnly(CopyOnly&&) = delete; + CopyOnly(int data) : + data(data) {} + CopyOnly(const CopyOnly &other) : + data(other.get()) {} + CopyOnly(CopyOnly &&) = delete; ~CopyOnly() {} int get() const { @@ -235,7 +251,7 @@ class CopyOnly{ /** * A simple class that can be both copy-constructed and move-constructed */ -class CopyMove{ +class CopyMove { private: int data; @@ -254,16 +270,19 @@ class CopyMove{ } public: - CopyMove(int data): data(data) { + CopyMove(int data) : + data(data) { atomic_inc(); } - CopyMove(const CopyMove & other): data(other.get()) { + CopyMove(const CopyMove &other) : + data(other.get()) { atomic_inc(); } // Move constructor does not increase global counter - CopyMove(CopyMove&& other): data(other.release()) {} + CopyMove(CopyMove &&other) : + data(other.release()) {} ~CopyMove() {} @@ -333,4 +352,4 @@ void concurrent_queue() { concurrent_queue_copy_move_elements_compilation(); } -} // openage::datastructure::tests +} // namespace openage::datastructure::tests diff --git a/libopenage/datastructure/tests.h b/libopenage/datastructure/tests.h index 6777c75eab..d615eaf6ba 100644 --- a/libopenage/datastructure/tests.h +++ b/libopenage/datastructure/tests.h @@ -1,10 +1,10 @@ -// Copyright 2014-2020 the openage authors. See copying.md for legal info. +// Copyright 2014-2023 the openage authors. See copying.md for legal info. #pragma once +#include #include -#include -#include + namespace openage::datastructure::tests { @@ -14,11 +14,11 @@ namespace openage::datastructure::tests { struct heap_elem { int data; - bool operator <(const heap_elem &other) const { + bool operator<(const heap_elem &other) const { return this->data < other.data; } - bool operator ==(const heap_elem &other) const { + bool operator==(const heap_elem &other) const { return this->data == other.data; } }; @@ -30,9 +30,9 @@ namespace std { /** * hash function for the simple heap_elem */ -template<> +template <> struct hash { - size_t operator ()(const openage::datastructure::tests::heap_elem &elem) const { + size_t operator()(const openage::datastructure::tests::heap_elem &elem) const { return elem.data; } }; diff --git a/libopenage/engine/engine.cpp b/libopenage/engine/engine.cpp index fc53c82f8a..1278506629 100644 --- a/libopenage/engine/engine.cpp +++ b/libopenage/engine/engine.cpp @@ -3,11 +3,13 @@ #include "engine.h" #include "log/log.h" +#include "log/message.h" #include "cvar/cvar.h" -#include "event/time_loop.h" #include "gamestate/simulation.h" #include "presenter/presenter.h" +#include "time/time_loop.h" + namespace openage::engine { @@ -27,7 +29,7 @@ Engine::Engine(mode mode, cvar_manager->load_all(); // time loop - this->time_loop = std::make_shared(); + this->time_loop = std::make_shared(); this->simulation = std::make_shared(this->root_dir, this->cvar_manager, diff --git a/libopenage/engine/engine.h b/libopenage/engine/engine.h index be54ab5555..d01fe9c4c2 100644 --- a/libopenage/engine/engine.h +++ b/libopenage/engine/engine.h @@ -2,6 +2,8 @@ #pragma once +#include +#include #include #include @@ -14,12 +16,20 @@ namespace std { class jthread : public thread { public: using thread::thread; // needed constructors + jthread(const jthread &) = delete; + jthread &operator=(const jthread &) = delete; + jthread(jthread &&) = default; + jthread &operator=(jthread &&) = default; ~jthread() { this->join(); } }; } // namespace std +#else +#error "jthread is supported now, remove custom definition" #endif +#else +#include #endif @@ -29,10 +39,6 @@ namespace cvar { class CVarManager; } // namespace cvar -namespace event { -class TimeLoop; -} // namespace event - namespace gamestate { class GameSimulation; } // namespace gamestate @@ -41,6 +47,10 @@ namespace presenter { class Presenter; } // namespace presenter +namespace time { +class TimeLoop; +} // namespace time + namespace engine { @@ -109,7 +119,7 @@ class Engine { /** * Controls and update the clock for time-based measurements. */ - std::shared_ptr time_loop; + std::shared_ptr time_loop; /** * Gameplay simulation. diff --git a/libopenage/error/demo.cpp b/libopenage/error/demo.cpp index 8e385c7d1d..f330705cd6 100644 --- a/libopenage/error/demo.cpp +++ b/libopenage/error/demo.cpp @@ -1,15 +1,14 @@ -// Copyright 2015-2017 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. -#include -#include +#include +#include -#include "../log/log.h" -#include "backtrace.h" -#include "error.h" +#include "error/error.h" +#include "log/log.h" +#include "log/message.h" -namespace openage { -namespace error { +namespace openage::error { // anonymous namespace to prevent linkage for exception demo helper functions. @@ -25,7 +24,8 @@ void bar(int i) { if (i % 5 == 3) { try { foo(); - } catch (...) { + } + catch (...) { // Note: pokemon exception handling is generally discouraged. // This serves as a demo how the Error constructor nevertheless // manages to correctly capture the cause exception. @@ -33,7 +33,8 @@ void bar(int i) { throw Error(MSG(crit).fmt("exception in foo. i=%d", i)); } - } else { + } + else { bar(i + 1); } } @@ -45,17 +46,17 @@ void bar(int i) { void demo() { try { bar(0); - } catch (Error &exc) { + } + catch (Error &exc) { if (exc.backtrace) { exc.trim_backtrace(); } - log::log(MSG(info) << - "exception_demo: captured the following exception:" << std::endl << - exc << std::endl << - "exception_demo: end of exception"); + log::log(MSG(info) << "exception_demo: captured the following exception:" << std::endl + << exc << std::endl + << "exception_demo: end of exception"); } } -}} // openage::error +} // namespace openage::error diff --git a/libopenage/error/error.cpp b/libopenage/error/error.cpp index 5d02074be9..a47e0cccfe 100644 --- a/libopenage/error/error.cpp +++ b/libopenage/error/error.cpp @@ -2,11 +2,12 @@ #include "error.h" +#include #include -#include "../util/compiler.h" +#include "util/compiler.h" -#include "stackanalyzer.h" +#include "error/stackanalyzer.h" namespace openage::error { @@ -18,11 +19,9 @@ void Error::debug_break_on_create(bool state) { enable_break_on_create = state; } -Error::Error(const log::message &msg, bool generate_backtrace, bool store_cause) - : +Error::Error(const log::message &msg, bool generate_backtrace, bool store_cause) : std::runtime_error{runtime_error_message}, msg(msg) { - if (enable_break_on_create) [[unlikely]] { BREAKPOINT; } @@ -49,10 +48,12 @@ void Error::store_cause() { try { throw; - } catch (Error &cause) { + } + catch (Error &cause) { cause.trim_backtrace(); this->cause = std::current_exception(); - } catch (...) { + } + catch (...) { this->cause = std::current_exception(); } } @@ -65,8 +66,7 @@ void Error::trim_backtrace() { } -Error::Error() - : +Error::Error() : std::runtime_error{runtime_error_message} {} @@ -87,28 +87,34 @@ void Error::rethrow_cause() const { } -std::ostream &operator <<(std::ostream &os, const Error &e) { +std::ostream &operator<<(std::ostream &os, const Error &e) { // output the exception cause bool had_a_cause = true; try { e.rethrow_cause(); had_a_cause = false; - } catch (Error &cause) { + } + catch (Error &cause) { os << cause << std::endl; - } catch (std::exception &cause) { + } + catch (std::exception &cause) { os << util::typestring(cause) << ": " << cause.what() << std::endl; - } catch (...) { + } + catch (...) { os << "unknown non std::exception cause!" << std::endl; } if (had_a_cause) { - os << std::endl << "The above exception was the direct cause of the following exception:" << std::endl << std::endl; + os << std::endl + << "The above exception was the direct cause of the following exception:" << std::endl + << std::endl; } // output the exception backtrace if (e.backtrace) { os << *e.backtrace; - } else { + } + else { os << "origin:" << std::endl; } @@ -117,7 +123,8 @@ std::ostream &operator <<(std::ostream &os, const Error &e) { e.msg.filename, e.msg.lineno, e.msg.functionname, - nullptr} << std::endl; + nullptr} + << std::endl; os << e.type_name(); @@ -129,4 +136,4 @@ std::ostream &operator <<(std::ostream &os, const Error &e) { } -} // openage::error +} // namespace openage::error diff --git a/libopenage/error/error.h b/libopenage/error/error.h index 1aabc33390..cbd9b949ac 100644 --- a/libopenage/error/error.h +++ b/libopenage/error/error.h @@ -2,6 +2,8 @@ #pragma once +#include + // pxd: from libcpp cimport bool #include #include @@ -18,13 +20,15 @@ namespace openage { namespace error { // forward-declaration to avoid the header include. class Backtrace; -}} +} // namespace error +} // namespace openage namespace openage { namespace pyinterface { // forward-declaration for use in the 'friend' declaration below. class PyException; -}} +} // namespace pyinterface +} // namespace openage namespace openage { @@ -63,7 +67,7 @@ class OAAPI Error : public std::runtime_error { * If true, a pointer to the causing exception is * collected and stored (default true). */ - Error(const log::message &msg, bool generate_backtrace=true, bool store_cause=true); + Error(const log::message &msg, bool generate_backtrace = true, bool store_cause = true); /** @@ -142,17 +146,21 @@ class OAAPI Error : public std::runtime_error { }; -std::ostream &operator <<(std::ostream &os, const Error &e); +std::ostream &operator<<(std::ostream &os, const Error &e); -[[deprecated("add message to the ENSURE before pushing, please")]] -inline std::string no_ensuring_message() -{ +[[deprecated("add message to the ENSURE before pushing, please")]] inline std::string no_ensuring_message() { return std::string{}; } // ENSURE(condition, errormessage << variable << etcetc) -#define ENSURE(...) do { if (not OPENAGE_ENS_FIRST(__VA_ARGS__)) [[unlikely]] { throw ::openage::error::Error(MSG(err) OPENAGE_ENS_REST(__VA_ARGS__)); } } while (0) +#define ENSURE(...) \ + do { \ + if (not OPENAGE_ENS_FIRST(__VA_ARGS__)) [[unlikely]] { \ + throw ::openage::error::Error(MSG(err) OPENAGE_ENS_REST(__VA_ARGS__)); \ + } \ + } \ + while (0) /* * expands to the first argument @@ -160,7 +168,7 @@ inline std::string no_ensuring_message() * https://stackoverflow.com/a/9338429 */ #define OPENAGE_PP_GLUE(macro, args) macro args -#define OPENAGE_ENS_FIRST(...) OPENAGE_PP_GLUE(OPENAGE_ENS_FIRST_HELPER,(__VA_ARGS__, throwaway)) +#define OPENAGE_ENS_FIRST(...) OPENAGE_PP_GLUE(OPENAGE_ENS_FIRST_HELPER, (__VA_ARGS__, throwaway)) #define OPENAGE_ENS_FIRST_HELPER(first, ...) (first) /* @@ -181,8 +189,8 @@ inline std::string no_ensuring_message() #define OPENAGE_ENS_NUM_IMPL(args) OPENAGE_ENS_SELECT_2ND args #define OPENAGE_ENS_SELECT_2ND(a1, a2, a3, ...) a3 -} // error +} // namespace error using error::Error; -} // openage::error +} // namespace openage diff --git a/libopenage/error/gl_debug.cpp b/libopenage/error/gl_debug.cpp index bad32aede4..fc89d33d74 100644 --- a/libopenage/error/gl_debug.cpp +++ b/libopenage/error/gl_debug.cpp @@ -1,16 +1,17 @@ -// Copyright 2016-2017 the openage authors. See copying.md for legal info. +// Copyright 2016-2023 the openage authors. See copying.md for legal info. #include "gl_debug.h" #include -#include "error.h" +#include "log/message.h" -namespace openage { -namespace error { +#include "error/error.h" + +namespace openage::error { namespace { -void APIENTRY callback(GLenum source, GLenum, GLuint, GLenum, GLsizei, const GLchar *message, const void*) { +void APIENTRY callback(GLenum source, GLenum, GLuint, GLenum, GLsizei, const GLchar *message, const void *) { const char *source_name; switch (source) { @@ -40,7 +41,7 @@ void APIENTRY callback(GLenum source, GLenum, GLuint, GLenum, GLsizei, const GLc throw Error(MSG(err) << "OpenGL error from " << source_name << ": '" << message << "'."); } -} +} // namespace SDL_GLContext create_debug_context(SDL_Window *window) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); @@ -52,7 +53,7 @@ SDL_GLContext create_debug_context(SDL_Window *window) { glGetIntegerv(GL_CONTEXT_FLAGS, &flags); if (!(flags & GL_CONTEXT_FLAG_DEBUG_BIT)) - throw Error(MSG(err)<< "Failed creating a debug OpenGL context."); + throw Error(MSG(err) << "Failed creating a debug OpenGL context."); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE); @@ -66,4 +67,4 @@ SDL_GLContext create_debug_context(SDL_Window *window) { return ctx; } -}} // openage::error +} // namespace openage::error diff --git a/libopenage/error/handlers.cpp b/libopenage/error/handlers.cpp index c10defe678..f608b0e78f 100644 --- a/libopenage/error/handlers.cpp +++ b/libopenage/error/handlers.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2021 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. /* * This file holds handlers for std::terminate and SIGSEGV. @@ -12,9 +12,9 @@ #include "handlers.h" +#include #include #include -#include #ifdef _MSC_VER #include @@ -22,12 +22,13 @@ #include #endif -#include "../util/signal.h" -#include "../util/init.h" -#include "../util/language.h" +#include "util/init.h" +#include "util/language.h" +#include "util/signal.h" + +#include "error/error.h" +#include "error/stackanalyzer.h" -#include "error.h" -#include "stackanalyzer.h" namespace openage { namespace error { @@ -73,23 +74,25 @@ util::OnDeInit restore_handlers([]() { std::cout << "\n\x1b[31;1mFATAL: terminate has been called\x1b[m" << std::endl; if (std::exception_ptr e_ptr = std::current_exception()) { - std::cout << "\n\x1b[33muncaught exception\x1b[m\n" << std::endl; + std::cout << "\n\x1b[33muncaught exception\x1b[m\n" + << std::endl; try { std::rethrow_exception(e_ptr); - } catch (Error &exc) { + } + catch (Error &exc) { std::cout << exc << std::endl; - } catch (std::exception &exc) { - std::cout << - "std::exception of type " << - util::typestring(exc) << - ": " << exc.what() << std::endl; - } catch (...) { + } + catch (std::exception &exc) { + std::cout << "std::exception of type " << util::typestring(exc) << ": " << exc.what() << std::endl; + } + catch (...) { std::cout << "non-standard exception object" << std::endl; } } - std::cout << "\n\x1b[33mcurrent stack:\x1b[m\n" << std::endl; + std::cout << "\n\x1b[33mcurrent stack:\x1b[m\n" + << std::endl; StackAnalyzer backtrace; backtrace.analyze(); @@ -98,7 +101,8 @@ util::OnDeInit restore_handlers([]() { // die again to enable debugger functionality. // that maybe print some additional useful info that we forgot about. // TODO: we maybe want to prevent that for end-users. - std::cout << "\x1b[33mhanding over to the system...\x1b[m\n" << std::endl; + std::cout << "\x1b[33mhanding over to the system...\x1b[m\n" + << std::endl; std::terminate(); } @@ -124,9 +128,12 @@ void exit_handler() { // The actual proper way of exiting the running game is via throwing // an exception or similar action. - if (exit_ok) { return; } + if (exit_ok) { + return; + } - std::cout << "\x1b[31;1mexit() was called in an illegal place\x1b[m\n" << std::endl; + std::cout << "\x1b[31;1mexit() was called in an illegal place\x1b[m\n" + << std::endl; } @@ -135,4 +142,5 @@ void set_exit_ok(bool value) { } -}} // openage::error +} // namespace error +} // namespace openage diff --git a/libopenage/error/stackanalyzer.cpp b/libopenage/error/stackanalyzer.cpp index 97b12ce9dc..878cb01025 100644 --- a/libopenage/error/stackanalyzer.cpp +++ b/libopenage/error/stackanalyzer.cpp @@ -1,12 +1,14 @@ -// Copyright 2015-2019 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "stackanalyzer.h" -#include "config.h" -#include "../log/log.h" -#include "../util/compiler.h" -#include "../util/init.h" +#include +#include +#include "config.h" +#include "log/log.h" +#include "util/compiler.h" +#include "util/init.h" namespace openage::error { @@ -23,8 +25,7 @@ constexpr uint64_t skip_entry_frames = 1; */ constexpr uint64_t base_skip_frames = 1; -} // openage::error - +} // namespace openage::error #if WITH_BACKTRACE @@ -57,10 +58,10 @@ struct backtrace_state *bt_state; util::OnInit init_backtrace_state([]() { bt_state = backtrace_create_state( - nullptr, // auto-determine filename - 1, // threaded + nullptr, // auto-determine filename + 1, // threaded backtrace_error_callback, - nullptr // passed to the callback + nullptr // passed to the callback ); // There's no documentaton on how to free the state. @@ -82,7 +83,6 @@ void backtrace_syminfo_callback( const char *symname, uintptr_t /*unused symval*/, uintptr_t /*unused symsize*/) { - // in this fallback case, we can't get filename or line info, but at least we // can get and demangle the symbol name... hopefully. @@ -92,8 +92,7 @@ void backtrace_syminfo_callback( "", 0, (symname == nullptr) ? "" : util::demangle(symname), - reinterpret_cast(pc) - }); + reinterpret_cast(pc)}); } @@ -109,15 +108,14 @@ int backtrace_pcinfo_callback(void *data, uintptr_t pc, const char *filename, in "", 0, util::symbol_name(reinterpret_cast(pc), false, true), - reinterpret_cast(pc) - }); - } else { + reinterpret_cast(pc)}); + } + else { symbol_vector->emplace_back(backtrace_symbol{ (filename == nullptr) ? "" : filename, static_cast(lineno), util::demangle(function), - reinterpret_cast(pc) - }); + reinterpret_cast(pc)}); } return 0; @@ -135,9 +133,9 @@ void backtrace_pcinfo_error_callback(void *data, const char *msg, int errorno) { info_cb_data->pc, backtrace_syminfo_callback, backtrace_error_callback, - info_cb_data - ); - } else { + info_cb_data); + } + else { // invoke the general error callback, which prints the message. backtrace_error_callback(nullptr, msg, errorno); } @@ -149,15 +147,14 @@ void backtrace_pcinfo_error_callback(void *data, const char *msg, int errorno) { void StackAnalyzer::analyze() { backtrace_simple( bt_state, - base_skip_frames, // skip some frames at "most recent call" + base_skip_frames, // skip some frames at "most recent call" backtrace_simple_callback, backtrace_error_callback, - reinterpret_cast(this) - ); + reinterpret_cast(this)); } -void StackAnalyzer::get_symbols(std::function cb, bool reversed) const { +void StackAnalyzer::get_symbols(std::function cb, bool reversed) const { info_cb_data_t info_cb_data; for (void *pc : this->stack_addrs) { @@ -171,8 +168,7 @@ void StackAnalyzer::get_symbols(std::function c info_cb_data.pc, backtrace_pcinfo_callback, backtrace_pcinfo_error_callback, - reinterpret_cast(&info_cb_data) - ); + reinterpret_cast(&info_cb_data)); } if (reversed) { @@ -180,14 +176,16 @@ void StackAnalyzer::get_symbols(std::function c for (size_t idx = info_cb_data.symbols.size(); idx-- > 0;) { cb(&info_cb_data.symbols[idx]); } - } else { + } + else { for (backtrace_symbol &symbol : info_cb_data.symbols) { cb(&symbol); } } } -}} // openage::error +} // namespace error +} // namespace openage #else // WITHOUT_BACKTRACE @@ -207,7 +205,8 @@ void StackAnalyzer::analyze() { this->stack_addrs = std::move(buffer); } -}} // openage::error +} // namespace error +} // namespace openage #else // not _MSC_VER @@ -255,14 +254,14 @@ void StackAnalyzer::analyze() { } } -} // openage::error +} // namespace openage::error #endif // for _MSC_VER or GNU execinfo namespace openage::error { -void StackAnalyzer::get_symbols(std::function cb, +void StackAnalyzer::get_symbols(std::function cb, bool reversed) const { backtrace_symbol symbol; symbol.filename = ""; @@ -290,7 +289,7 @@ void StackAnalyzer::get_symbols(std::function c } -} // openage::error +} // namespace openage::error #endif // WITHOUT_BACKTRACE @@ -313,4 +312,4 @@ void StackAnalyzer::trim_to_current_stack_frame() { } -} // openage::error +} // namespace openage::error diff --git a/libopenage/error/stackanalyzer.h b/libopenage/error/stackanalyzer.h index 290ae82aee..0b801a1f66 100644 --- a/libopenage/error/stackanalyzer.h +++ b/libopenage/error/stackanalyzer.h @@ -1,8 +1,12 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once -#include "backtrace.h" +#include +#include + +#include "error/backtrace.h" + namespace openage { namespace error { @@ -43,9 +47,10 @@ class StackAnalyzer : public Backtrace { std::vector stack_addrs; // Looks up symbol names for the program counter values. - void get_symbols(std::function cb, bool reversed) const override; + void get_symbols(std::function cb, bool reversed) const override; void trim_to_current_stack_frame() override; }; -}} // openage::error +} // namespace error +} // namespace openage diff --git a/libopenage/event/CMakeLists.txt b/libopenage/event/CMakeLists.txt index af5f9b7148..d62326b2ba 100644 --- a/libopenage/event/CMakeLists.txt +++ b/libopenage/event/CMakeLists.txt @@ -1,5 +1,4 @@ add_sources(libopenage - clock.cpp event_loop.cpp event.cpp evententity.cpp @@ -8,7 +7,6 @@ add_sources(libopenage eventstore.cpp state.cpp tests.cpp - time_loop.cpp ) add_subdirectory("demo") diff --git a/libopenage/event/demo/aicontroller.cpp b/libopenage/event/demo/aicontroller.cpp index dbfcda1a14..e65935f627 100644 --- a/libopenage/event/demo/aicontroller.cpp +++ b/libopenage/event/demo/aicontroller.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #include "aicontroller.h" @@ -6,7 +6,7 @@ namespace openage::event::demo { std::vector get_ai_inputs(const std::shared_ptr &player, const std::shared_ptr &ball, - const curve::time_t &now) { + const time::time_t &now) { std::vector ret; auto position = player->position->get(now); diff --git a/libopenage/event/demo/aicontroller.h b/libopenage/event/demo/aicontroller.h index 892cef3610..6200b1d99d 100644 --- a/libopenage/event/demo/aicontroller.h +++ b/libopenage/event/demo/aicontroller.h @@ -1,4 +1,4 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once @@ -10,6 +10,6 @@ namespace openage::event::demo { std::vector get_ai_inputs(const std::shared_ptr &player, const std::shared_ptr &ball, - const curve::time_t &now); + const time::time_t &now); } // openage::event::demo diff --git a/libopenage/event/demo/gamestate.h b/libopenage/event/demo/gamestate.h index 55974b577f..b92b22ee93 100644 --- a/libopenage/event/demo/gamestate.h +++ b/libopenage/event/demo/gamestate.h @@ -2,20 +2,28 @@ #pragma once +#include #include +#include +#include #include +#include #include "config.h" #include "curve/continuous.h" #include "curve/discrete.h" -#include "event/event_loop.h" #include "event/evententity.h" #include "event/state.h" +#include "time/time.h" +#include "util/fixed_point.h" #include "util/strings.h" #include "util/vector.h" -namespace openage::event::demo { +namespace openage::event { +class EventLoop; + +namespace demo { #if WITH_NCURSES class Gui; @@ -95,7 +103,7 @@ class PongPlayer : public EventEntity { } private: - void child_changes(const curve::time_t &time) { + void child_changes(const time::time_t &time) { this->changes(time); } }; @@ -131,7 +139,7 @@ class PongBall : public EventEntity { } private: - void child_changes(const curve::time_t &time) { + void child_changes(const time::time_t &time) { this->changes(time); } size_t _id; @@ -170,4 +178,5 @@ class PongState : public State { #endif }; -} // namespace openage::event::demo +} // namespace demo +} // namespace openage::event diff --git a/libopenage/event/demo/gui.cpp b/libopenage/event/demo/gui.cpp index 3361419d49..100509c0f4 100644 --- a/libopenage/event/demo/gui.cpp +++ b/libopenage/event/demo/gui.cpp @@ -6,7 +6,9 @@ #if WITH_NCURSES #include -#include +#include +#include +#include #ifdef __MINGW32__ #include #else @@ -14,6 +16,10 @@ #endif // __MINGW32__ #include +#include "curve/continuous.h" +#include "curve/discrete.h" +#include "event/demo/gamestate.h" +#include "util/fixed_point.h" namespace openage::event::demo { @@ -151,7 +157,7 @@ void Gui::clear() { void Gui::get_display_size(const std::shared_ptr &state, - const curve::time_t & /*now*/) { + const time::time_t & /*now*/) { // record the screen dimensions in the game state // TODO: make the display_boundary a curve as well. @@ -160,7 +166,7 @@ void Gui::get_display_size(const std::shared_ptr &state, } -void Gui::draw(const std::shared_ptr &state, const curve::time_t &now) { +void Gui::draw(const std::shared_ptr &state, const time::time_t &now) { attron(COLOR_PAIR(COLOR_DEBUG)); // print the score @@ -182,7 +188,7 @@ void Gui::draw(const std::shared_ptr &state, const curve::time_t &now // ball position predictions, 10s into the future for (int i = 0; i < 10; i++) { - auto i_as_ctt = curve::time_t::from_int(i); + auto i_as_ctt = time::time_t::from_int(i); mvprintw((5 + i), 1, "BALL in %03f: %f | %f; SPEED: %f | %f | PLpos: %f, PRpos: %f", i_as_ctt.to_double(), state->ball->position->get(now + i_as_ctt)[0], state->ball->position->get(now + i_as_ctt)[1], state->ball->speed->get(now + i_as_ctt)[0], state->ball->speed->get(now + i_as_ctt)[1], state->p1->position->get(now + i_as_ctt), state->p2->position->get(now + i_as_ctt)); } @@ -215,7 +221,7 @@ void Gui::draw(const std::shared_ptr &state, const curve::time_t &now // ball position prediction 10s into the future attron(COLOR_PAIR(COLOR_1)); for (int i = 1; i < 100; ++i) { - auto i_as_ctt = curve::time_t::from_double(i / 10.0); + auto i_as_ctt = time::time_t::from_double(i / 10.0); draw_ball(state->ball->position->get(now + i_as_ctt), "x"); } diff --git a/libopenage/event/demo/gui.h b/libopenage/event/demo/gui.h index 64660ad8b3..de21a99d02 100644 --- a/libopenage/event/demo/gui.h +++ b/libopenage/event/demo/gui.h @@ -1,23 +1,22 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once - #include "config.h" #if WITH_NCURSES -#include #include +#include +#include +#include -#include "gamestate.h" +#include "event/demo/gamestate.h" +#include "time/time.h" +#include "util/vector.h" namespace openage::event::demo { -class PongEvent; -class PongState; -class PongPlayer; - class Gui { public: @@ -28,9 +27,9 @@ class Gui { const std::vector &get_inputs(const std::shared_ptr &player); void get_display_size(const std::shared_ptr &state, - const curve::time_t &now); + const time::time_t &now); - void draw(const std::shared_ptr &state, const curve::time_t &now); + void draw(const std::shared_ptr &state, const time::time_t &now); void draw_ball(util::Vector2d ball, const char *str); void log(const std::string &msg); @@ -40,6 +39,6 @@ class Gui { std::deque log_msgs; }; -} // openage::event::demo +} // namespace openage::event::demo #endif diff --git a/libopenage/event/demo/main.cpp b/libopenage/event/demo/main.cpp index 2f36c1156d..442e9910c7 100644 --- a/libopenage/event/demo/main.cpp +++ b/libopenage/event/demo/main.cpp @@ -7,11 +7,12 @@ #include #include "config.h" -#include "../event.h" -#include "aicontroller.h" -#include "gamestate.h" -#include "gui.h" -#include "physics.h" +#include "event/demo/aicontroller.h" +#include "event/demo/gamestate.h" +#include "event/demo/gui.h" +#include "event/demo/physics.h" +#include "event/event.h" +#include "event/event_loop.h" #if WITH_NCURSES #ifdef __MINGW32__ @@ -40,7 +41,6 @@ enum class timescale { void curvepong(bool disable_gui, bool no_human) { - bool enable_gui = not disable_gui; bool human_player = not no_human; @@ -59,12 +59,13 @@ void curvepong(bool disable_gui, bool no_human) { while (running) { auto loop = std::make_shared(); - curve::time_t now = 1; + time::time_t now = 1; Physics phys; auto state = std::make_shared(loop, enable_gui #if WITH_NCURSES - , gui + , + gui #endif ); Physics::init(state, loop, now); @@ -78,7 +79,7 @@ void curvepong(bool disable_gui, bool no_human) { #if WITH_NCURSES if (state->enable_gui) { gui->clear(); - gui->get_display_size(state, now); // update gui related parameters + gui->get_display_size(state, now); // update gui related parameters } else { #endif @@ -95,9 +96,7 @@ void curvepong(bool disable_gui, bool no_human) { std::vector inputs; // this is the game loop, running while both players live! - while (state->p1->lives->get(now) > 0 and - state->p2->lives->get(now) > 0) { - + while (state->p1->lives->get(now) > 0 and state->p2->lives->get(now) > 0) { auto loop_start = Clock::now(); #if WITH_NCURSES @@ -111,19 +110,13 @@ void curvepong(bool disable_gui, bool no_human) { // player 1 can be AI or human. if (human_player) { - phys.process_input(state, state->p1, - inputs, loop, now); + phys.process_input(state, state->p1, inputs, loop, now); } else { - - phys.process_input(state, state->p1, - get_ai_inputs(state->p1, state->ball, now), - loop, now); + phys.process_input(state, state->p1, get_ai_inputs(state->p1, state->ball, now), loop, now); } - phys.process_input(state, state->p2, - get_ai_inputs(state->p2, state->ball, now), - loop, now); + phys.process_input(state, state->p2, get_ai_inputs(state->p2, state->ball, now), loop, now); // paddle x positions state->p1->paddle_x = 0; @@ -137,12 +130,9 @@ void curvepong(bool disable_gui, bool no_human) { gui->draw(state, now); int pos = 1; - mvprintw(pos++, state->display_boundary[0]/2 + 10, "Enqueued events:"); + mvprintw(pos++, state->display_boundary[0] / 2 + 10, "Enqueued events:"); for (const auto &e : loop->get_queue().get_event_queue().get_sorted_events()) { - mvprintw(pos++, state->display_boundary[0]/2 + 10, - "%f: %s", - e->get_time().to_double(), - e->get_eventhandler()->id().c_str()); + mvprintw(pos++, state->display_boundary[0] / 2 + 10, "%f: %s", e->get_time().to_double(), e->get_eventhandler()->id().c_str()); } gui->update_screen(); @@ -163,7 +153,7 @@ void curvepong(bool disable_gui, bool no_human) { // microseconds per frame // 30fps = 1s/30 = 1000000us/30 per frame constexpr static std::chrono::microseconds per_frame = 33333us; - constexpr static curve::time_t per_frame_s = std::chrono::duration_cast(per_frame).count(); + constexpr static time::time_t per_frame_s = std::chrono::duration_cast(per_frame).count(); if (speed == timescale::NOSLEEP) { // increase the simulation loop time a bit @@ -205,4 +195,4 @@ void curvepong(bool disable_gui, bool no_human) { } -} // openage::event::demo +} // namespace openage::event::demo diff --git a/libopenage/event/demo/physics.cpp b/libopenage/event/demo/physics.cpp index 6ed8b9b42b..d43365f042 100644 --- a/libopenage/event/demo/physics.cpp +++ b/libopenage/event/demo/physics.cpp @@ -2,8 +2,11 @@ #include "physics.h" -#include -#include +#include +#include +#include +#include +#include #if WITH_NCURSES #ifdef __MINGW32__ @@ -15,10 +18,25 @@ #include "gui.h" #endif +#include "error/error.h" +#include "log/log.h" +#include "log/message.h" + #include "config.h" -#include "../../error/error.h" -#include "../../rng/global_rng.h" -#include "../../util/stringformatter.h" +#include "curve/continuous.h" +#include "curve/discrete.h" +#include "error/error.h" +#include "event/demo/gamestate.h" +#include "event/event.h" +#include "event/event_loop.h" +#include "event/eventhandler.h" +#include "log/log.h" +#include "log/message.h" +#include "rng/global_rng.h" +#include "time/time.h" +#include "util/fixed_point.h" +#include "util/stringformatter.h" +#include "util/vector.h" namespace openage::event::demo { @@ -26,11 +44,11 @@ namespace openage::event::demo { class BallReflectWall : public DependencyEventHandler { public: - BallReflectWall() : DependencyEventHandler("demo.ball.reflect_wall") {} + BallReflectWall() : + DependencyEventHandler("demo.ball.reflect_wall") {} void setup_event(const std::shared_ptr &evnt, const std::shared_ptr &gstate) override { - auto state = std::dynamic_pointer_cast(gstate); // FIXME dependency to a full ball object so that any curve @@ -46,9 +64,8 @@ class BallReflectWall : public DependencyEventHandler { void invoke(EventLoop &, const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &now, - const EventHandler::param_map &/*param*/) override { - + const time::time_t &now, + const EventHandler::param_map & /*param*/) override { auto positioncurve = std::dynamic_pointer_cast>(target); auto state = std::dynamic_pointer_cast(gstate); auto speedcurve = state->ball->speed; @@ -64,25 +81,22 @@ class BallReflectWall : public DependencyEventHandler { return; } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[1] > 0) { - ty = curve::time_t::from_double( - (state->display_boundary[1] - pos[1]) / speed[1] - ); + ty = time::time_t::from_double( + (state->display_boundary[1] - pos[1]) / speed[1]); } else if (speed[1] < 0) { - ty = curve::time_t::from_double( - pos[1] / -speed[1] - ); + ty = time::time_t::from_double( + pos[1] / -speed[1]); } state->ball->position->set_last(now + ty, pos + (speed * ty.to_double())); } - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &gstate, - const curve::time_t &now) override { - + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &gstate, + const time::time_t &now) override { auto positioncurve = std::dynamic_pointer_cast>(target); auto state = std::dynamic_pointer_cast(gstate); @@ -90,22 +104,24 @@ class BallReflectWall : public DependencyEventHandler { auto pos = positioncurve->get(now); if (speed[1] == 0) { - return std::numeric_limits::max(); + return std::numeric_limits::max(); } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[1] > 0) { - ty = curve::time_t::from_double((state->display_boundary[1] - pos[1]) / speed[1]); + ty = time::time_t::from_double((state->display_boundary[1] - pos[1]) / speed[1]); } else if (speed[1] < 0) { - ty = curve::time_t::from_double(pos[1] / -speed[1]); + ty = time::time_t::from_double(pos[1] / -speed[1]); } #if WITH_NCURSES if (state->enable_gui) { util::FString str; str.fmt("WALL TY %f NOW %f, NOWTY %f ", - ty.to_double(), now.to_double(), (now + ty).to_double()); + ty.to_double(), + now.to_double(), + (now + ty).to_double()); state->gui->log(str); }; #endif @@ -116,13 +132,11 @@ class BallReflectWall : public DependencyEventHandler { class BallReflectPanel : public DependencyEventHandler { public: - BallReflectPanel () - : + BallReflectPanel() : DependencyEventHandler("demo.ball.reflect_panel") {} void setup_event(const std::shared_ptr &target, const std::shared_ptr &gstate) override { - auto state = std::dynamic_pointer_cast(gstate); // FIXME dependency to a full ball object @@ -136,11 +150,10 @@ class BallReflectPanel : public DependencyEventHandler { // FIXME we REALLY need dependencies to objects void invoke(EventLoop &mgr, - const std::shared_ptr &/*target*/, + const std::shared_ptr & /*target*/, const std::shared_ptr &gstate, - const curve::time_t &now, - const EventHandler::param_map &/*param*/) override { - + const time::time_t &now, + const EventHandler::param_map & /*param*/) override { auto state = std::dynamic_pointer_cast(gstate); auto pos = state->ball->position->get(now); @@ -160,11 +173,7 @@ class BallReflectPanel : public DependencyEventHandler { } #endif - if (pos[0] <= 1 and - speed[0] < 0 and - (pos[1] < state->p1->position->get(now) - state->p1->size->get(now) / 2 or - pos[1] > state->p1->position->get(now) + state->p1->size->get(now) / 2)) { - + if (pos[0] <= 1 and speed[0] < 0 and (pos[1] < state->p1->position->get(now) - state->p1->size->get(now) / 2 or pos[1] > state->p1->position->get(now) + state->p1->size->get(now) / 2)) { // ball missed the paddle of player 1 auto l = state->p1->lives->get(now); l--; @@ -174,11 +183,7 @@ class BallReflectPanel : public DependencyEventHandler { Physics::reset(state, mgr, now); } - else if (pos[0] >= state->display_boundary[0] - 1 and - speed[0] > 0 and - (pos[1] < state->p2->position->get(now) - state->p2->size->get(now) / 2 or - pos[1] > state->p2->position->get(now) + state->p2->size->get(now) / 2)) { - + else if (pos[0] >= state->display_boundary[0] - 1 and speed[0] > 0 and (pos[1] < state->p2->position->get(now) - state->p2->size->get(now) / 2 or pos[1] > state->p2->position->get(now) + state->p2->size->get(now) / 2)) { // ball missed the paddel of player 2 auto l = state->p2->lives->get(now); l--; @@ -187,18 +192,18 @@ class BallReflectPanel : public DependencyEventHandler { Physics::reset(state, mgr, now); } - else if (pos[0] >= state->display_boundary[0]- 1 || pos[0] <= 1) { + else if (pos[0] >= state->display_boundary[0] - 1 || pos[0] <= 1) { speed[0] *= -1; state->ball->speed->set_last(now, speed); state->ball->position->set_last(now, pos); } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[0] > 0) { - ty = curve::time_t::from_double((state->display_boundary[0] - pos[0]) / speed[0]); + ty = time::time_t::from_double((state->display_boundary[0] - pos[0]) / speed[0]); } else if (speed[0] < 0) { - ty = curve::time_t::from_double(pos[0] / -speed[0]); + ty = time::time_t::from_double(pos[0] / -speed[0]); } auto hit_pos = pos + speed * ty.to_double(); @@ -212,10 +217,9 @@ class BallReflectPanel : public DependencyEventHandler { state->ball->position->set_last(now + ty, hit_pos); } - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &gstate, - const curve::time_t &now) override { - + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &gstate, + const time::time_t &now) override { auto positioncurve = std::dynamic_pointer_cast>(target); auto state = std::dynamic_pointer_cast(gstate); @@ -223,15 +227,15 @@ class BallReflectPanel : public DependencyEventHandler { auto pos = positioncurve->get(now); if (speed[0] == 0) - return std::numeric_limits::max(); + return std::numeric_limits::max(); - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[0] > 0) { - ty = curve::time_t::from_double((state->display_boundary[0] - pos[0]) / speed[0]); + ty = time::time_t::from_double((state->display_boundary[0] - pos[0]) / speed[0]); } else if (speed[0] < 0) { - ty = curve::time_t::from_double(pos[0] / -speed[0]); + ty = time::time_t::from_double(pos[0] / -speed[0]); } #if WITH_NCURSES @@ -243,7 +247,7 @@ class BallReflectPanel : public DependencyEventHandler { else { #endif log::log(INFO << "predicting panel reflection at t=" << now - << ", next reflection at t=" << (now + ty)); + << ", next reflection at t=" << (now + ty)); #if WITH_NCURSES } #endif @@ -265,19 +269,17 @@ class BallReflectPanel : public DependencyEventHandler { class ResetGame : public OnceEventHandler { public: - ResetGame () - : + ResetGame() : OnceEventHandler("demo.reset") {} - void setup_event(const std::shared_ptr &/*target*/, - const std::shared_ptr &/*state*/) override {} + void setup_event(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/) override {} - void invoke(EventLoop &/*mgr*/, - const std::shared_ptr &/*target*/, + void invoke(EventLoop & /*mgr*/, + const std::shared_ptr & /*target*/, const std::shared_ptr &gstate, - const curve::time_t &now, - const EventHandler::param_map &/*param*/) override { - + const time::time_t &now, + const EventHandler::param_map & /*param*/) override { auto state = std::dynamic_pointer_cast(gstate); // Check if the condition still applies @@ -290,7 +292,7 @@ class ResetGame : public OnceEventHandler { } // move ball to the center - state->ball->position->set_last(now - curve::time_t::from_double(0.1), + state->ball->position->set_last(now - time::time_t::from_double(0.1), state->ball->position->get(now)); state->ball->position->set_last(now, state->display_boundary * 0.5); @@ -302,8 +304,7 @@ class ResetGame : public OnceEventHandler { float diry = (rng::random() % 2) ? 1 : -1; auto init_speed = util::Vector2d( dirx * (10 + (rng::random() % 100) / 4.f), - diry * (0.3 + (rng::random() % 100) / 18.f) - ); + diry * (0.3 + (rng::random() % 100) / 18.f)); state->ball->speed->set_last(now, init_speed); auto pos = state->ball->position->get(now); @@ -328,32 +329,32 @@ class ResetGame : public OnceEventHandler { } #endif - curve::time_t ty = 0; + time::time_t ty = 0; // calculate the wall-hit-times if (init_speed[1] > 0) { - ty = curve::time_t::from_double((state->display_boundary[1] - pos[1]) / init_speed[1]); + ty = time::time_t::from_double((state->display_boundary[1] - pos[1]) / init_speed[1]); } else if (init_speed[1] < 0) { - ty = curve::time_t::from_double(pos[1] / -init_speed[1]); + ty = time::time_t::from_double(pos[1] / -init_speed[1]); } else { // currently never happens, but this would be a non-vertically-moving ball // fallback to calculating panel-hit-times if (init_speed[0] > 0) { - ty = curve::time_t::from_double((state->display_boundary[0] - pos[0]) / init_speed[0]); + ty = time::time_t::from_double((state->display_boundary[0] - pos[0]) / init_speed[0]); } else { - ty = curve::time_t::from_double(pos[0] / -init_speed[0]); + ty = time::time_t::from_double(pos[0] / -init_speed[0]); } } state->ball->position->set_last(now + ty, pos + init_speed * ty.to_double()); } - curve::time_t predict_invoke_time(const std::shared_ptr &/*target*/, - const std::shared_ptr &/*state*/, - const curve::time_t &old_time) override { + time::time_t predict_invoke_time(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/, + const time::time_t &old_time) override { return old_time; } }; @@ -361,8 +362,7 @@ class ResetGame : public OnceEventHandler { void Physics::init(const std::shared_ptr &gstate, const std::shared_ptr &loop, - const curve::time_t &now) { - + const time::time_t &now) { auto state = std::dynamic_pointer_cast(gstate); if (not state->enable_gui) { @@ -384,19 +384,16 @@ void Physics::process_input(const std::shared_ptr &state, const std::shared_ptr &player, const std::vector &events, const std::shared_ptr &mgr, - const curve::time_t &now) { - + const time::time_t &now) { // seconds into the future - constexpr static auto predicted_movement_time = curve::time_t::from_double(5.0); + constexpr static auto predicted_movement_time = time::time_t::from_double(5.0); // lines per second constexpr static double movement_speed = 8.0; - for (auto& evnt : events) { - + for (auto &evnt : events) { // Process only if the future has changed if (player->state->get(now).state != evnt.state) { - // log the new input in the state curve player->state->set_last(now, evnt); @@ -408,7 +405,7 @@ void Physics::process_input(const std::shared_ptr &state, extend_previous_prediction = true; } - switch(evnt.state) { + switch (evnt.state) { case PongEvent::UP: case PongEvent::DOWN: { float current_pos = player->position->get(now); @@ -432,14 +429,11 @@ void Physics::process_input(const std::shared_ptr &state, break; } - curve::time_t move_stop_guess = now + predicted_movement_time; + time::time_t move_stop_guess = now + predicted_movement_time; // change the position by integrating the speed curve. // TODO: add native integral to curves. - float new_pos = current_pos + - (((player->speed->get(move_stop_guess) + - player->speed->get(now)) / 2.0) * - predicted_movement_time.to_double()); + float new_pos = current_pos + (((player->speed->get(move_stop_guess) + player->speed->get(now)) / 2.0) * predicted_movement_time.to_double()); // if paddle will get out-of-bounds, calculate the bound hit time @@ -488,10 +482,9 @@ void Physics::process_input(const std::shared_ptr &state, void Physics::reset(const std::shared_ptr &gstate, EventLoop &mgr, - const curve::time_t &now) { - + const time::time_t &now) { auto state = std::dynamic_pointer_cast(gstate); mgr.create_event("demo.reset", state->ball->position, state, now); } -} // openage::event::demo +} // namespace openage::event::demo diff --git a/libopenage/event/demo/physics.h b/libopenage/event/demo/physics.h index 5210f58832..7b46c250c9 100644 --- a/libopenage/event/demo/physics.h +++ b/libopenage/event/demo/physics.h @@ -2,33 +2,39 @@ #pragma once -#include "gamestate.h" -#include "../../curve/curve.h" - +#include #include +#include "time/time.h" + namespace openage::event { class EventLoop; +class State; namespace demo { +class PongEvent; +class PongPlayer; +class PongState; + class Physics { public: static void init(const std::shared_ptr &, const std::shared_ptr &mgr, - const curve::time_t &); + const time::time_t &); void process_input(const std::shared_ptr &, const std::shared_ptr &, const std::vector &input, const std::shared_ptr &mgr, - const curve::time_t &now); + const time::time_t &now); static void reset(const std::shared_ptr &, EventLoop &mgr, - const curve::time_t &); + const time::time_t &); }; -}} // openage::event::demo +} // namespace demo +} // namespace openage::event diff --git a/libopenage/event/event.cpp b/libopenage/event/event.cpp index 07cf8e6d22..67b5cbc814 100644 --- a/libopenage/event/event.cpp +++ b/libopenage/event/event.cpp @@ -2,13 +2,19 @@ #include "event.h" -#include +#include +#include +#include -#include "evententity.h" -#include "eventhandler.h" +#include "log/log.h" +#include "log/message.h" + +#include "event/evententity.h" +#include "event/eventhandler.h" +#include "time/time.h" +#include "util/fixed_point.h" +#include "util/hash.h" -#include "../log/log.h" -#include "../util/hash.h" namespace openage::event { @@ -35,7 +41,7 @@ void Event::depend_on(const std::shared_ptr &dependency) { } -void Event::cancel(const curve::time_t reference_time) { +void Event::cancel(const time::time_t reference_time) { log::log(DBG << "Canceling event from EventHandler " << this->get_eventhandler()->id() << " for time t=" << this->get_time()); diff --git a/libopenage/event/event.h b/libopenage/event/event.h index 7458c24bdf..72c943d807 100644 --- a/libopenage/event/event.h +++ b/libopenage/event/event.h @@ -2,14 +2,14 @@ #pragma once +#include #include -#include "../curve/curve.h" -#include "eventhandler.h" +#include "event/eventhandler.h" +#include "time/time.h" -namespace openage::event { -class EventQueue; +namespace openage::event { class EventEntity; /** @@ -34,17 +34,17 @@ class Event : public std::enable_shared_from_this { * Reschedule will call the predict_invoke_time method to initiate a reschedule * for the event it uses the reference_time as base for its calculation */ - void reschedule(const curve::time_t reference_time); + void reschedule(const time::time_t reference_time); size_t hash() const { return this->myhash; } - const curve::time_t &get_time() const { + const time::time_t &get_time() const { return this->time; } - void set_time(const curve::time_t &t) { + void set_time(const time::time_t &t) { this->time = t; } @@ -63,7 +63,7 @@ class Event : public std::enable_shared_from_this { /** * Cancel the event. */ - void cancel(const curve::time_t reference_time); + void cancel(const time::time_t reference_time); /** * For sorting events by their trigger time. @@ -78,14 +78,14 @@ class Event : public std::enable_shared_from_this { * When changes happen after `last_change_time` in the same time-reaching-round, * they can be ignored since the earlies point in time determines all implications. */ - void set_last_changed(const curve::time_t &t) { + void set_last_changed(const time::time_t &t) { this->last_change_time = t; } /** * Get the time the event was changed the last time. */ - const curve::time_t &get_last_changed() const { + const time::time_t &get_last_changed() const { return this->last_change_time; } @@ -105,10 +105,10 @@ class Event : public std::enable_shared_from_this { * Time this event occurs/occured. * It establishes the order of events in the EventQueue. */ - curve::time_t time; + time::time_t time; /** Time this event was registered to be changed last. */ - curve::time_t last_change_time = curve::time_t::min_value(); + time::time_t last_change_time = time::time_t::min_value(); /** Precalculated std::hash for the event */ size_t myhash; diff --git a/libopenage/event/event_loop.cpp b/libopenage/event/event_loop.cpp index d57e06804b..eb9e8ca6f1 100644 --- a/libopenage/event/event_loop.cpp +++ b/libopenage/event/event_loop.cpp @@ -2,12 +2,21 @@ #include "event_loop.h" -#include "event.h" -#include "evententity.h" -#include "eventhandler.h" -#include "eventqueue.h" +#include +#include +#include +#include -#include "../log/log.h" +#include "log/log.h" +#include "log/message.h" + +#include "error/error.h" +#include "event/event.h" +#include "event/evententity.h" +#include "event/eventhandler.h" +#include "event/eventqueue.h" +#include "event/eventstore.h" +#include "util/fixed_point.h" namespace openage::event { @@ -23,7 +32,7 @@ void EventLoop::add_event_handler(const std::shared_ptr eventhandl std::shared_ptr EventLoop::create_event(const std::string name, const std::shared_ptr target, const std::shared_ptr state, - const curve::time_t reference_time, + const time::time_t reference_time, const EventHandler::param_map params) { std::unique_lock lock{this->mutex}; @@ -40,7 +49,7 @@ std::shared_ptr EventLoop::create_event(const std::string name, std::shared_ptr EventLoop::create_event(const std::shared_ptr eventhandler, const std::shared_ptr target, const std::shared_ptr state, - const curve::time_t reference_time, + const time::time_t reference_time, const EventHandler::param_map params) { std::unique_lock lock{this->mutex}; @@ -59,7 +68,7 @@ std::shared_ptr EventLoop::create_event(const std::shared_ptr &state) { std::unique_lock lock{this->mutex}; @@ -98,7 +107,7 @@ void EventLoop::reach_time(const curve::time_t &time_until, } -int EventLoop::execute_events(const curve::time_t &time_until, +int EventLoop::execute_events(const time::time_t &time_until, const std::shared_ptr &state) { log::log(SPAM << "Loop: Pending events in the queue (# = " << this->queue.get_event_queue().size() << "):"); @@ -139,10 +148,10 @@ int EventLoop::execute_events(const curve::time_t &time_until, // if the event is REPEAT, readd the event. if (event->get_eventhandler()->type == EventHandler::trigger_type::REPEAT) { - curve::time_t new_time = event->get_eventhandler()->predict_invoke_time( + time::time_t new_time = event->get_eventhandler()->predict_invoke_time( target, state, event->get_time()); - if (new_time != std::numeric_limits::min()) { + if (new_time != std::numeric_limits::min()) { event->set_time(new_time); log::log(DBG << "Loop: repeating event \"" << event->get_eventhandler()->id() @@ -166,7 +175,7 @@ int EventLoop::execute_events(const curve::time_t &time_until, void EventLoop::create_change(const std::shared_ptr evnt, - const curve::time_t changes_at) { + const time::time_t changes_at) { std::unique_lock lock{this->mutex}; this->queue.add_change(evnt, changes_at); @@ -192,10 +201,10 @@ void EventLoop::update_changes(const std::shared_ptr &state) { auto entity = evnt->get_entity().lock(); if (entity) { - curve::time_t new_time = evnt->get_eventhandler() - ->predict_invoke_time(entity, state, change.time); + time::time_t new_time = evnt->get_eventhandler() + ->predict_invoke_time(entity, state, change.time); - if (new_time != std::numeric_limits::min()) { + if (new_time != std::numeric_limits::min()) { log::log(DBG << "Loop: due to a change, rescheduling event of '" << evnt->get_eventhandler()->id() << "' on entity '" << entity->idstr() diff --git a/libopenage/event/event_loop.h b/libopenage/event/event_loop.h index bdc4287962..5a5a45bc64 100644 --- a/libopenage/event/event_loop.h +++ b/libopenage/event/event_loop.h @@ -2,16 +2,15 @@ #pragma once -#include -#include #include #include +#include #include -#include "curve/curve.h" -#include "event.h" -#include "eventqueue.h" -#include "log/log.h" +#include "event/eventhandler.h" +#include "event/eventqueue.h" +#include "time/time.h" + namespace openage::event { @@ -63,7 +62,7 @@ class EventLoop { std::shared_ptr create_event(const std::string eventhandler, const std::shared_ptr target, const std::shared_ptr state, - const curve::time_t reference_time, + const time::time_t reference_time, const EventHandler::param_map params = EventHandler::param_map({})); /** @@ -85,7 +84,7 @@ class EventLoop { std::shared_ptr create_event(const std::shared_ptr eventhandler, const std::shared_ptr target, const std::shared_ptr state, - const curve::time_t reference_time, + const time::time_t reference_time, const EventHandler::param_map params = EventHandler::param_map({})); /** @@ -94,7 +93,7 @@ class EventLoop { * @param time_until Maximum time until which events are executed. * @param state Global state. */ - void reach_time(const curve::time_t &time_until, + void reach_time(const time::time_t &time_until, const std::shared_ptr &state); /** @@ -110,7 +109,7 @@ class EventLoop { * @param changes_at Time at which the event should be reevaluated. */ void create_change(const std::shared_ptr event, - const curve::time_t changes_at); + const time::time_t changes_at); /** * Get the event queue. @@ -130,7 +129,7 @@ class EventLoop { * * @returns number of events processed */ - int execute_events(const curve::time_t &time_until, + int execute_events(const time::time_t &time_until, const std::shared_ptr &state); /** diff --git a/libopenage/event/evententity.cpp b/libopenage/event/evententity.cpp index 28549cea37..f5fcfaebf1 100644 --- a/libopenage/event/evententity.cpp +++ b/libopenage/event/evententity.cpp @@ -2,19 +2,21 @@ #include "evententity.h" -#include - -#include "event.h" -#include "event_loop.h" -#include "eventhandler.h" +#include #include "log/log.h" +#include "log/message.h" + +#include "event/event.h" +#include "event/event_loop.h" +#include "event/eventhandler.h" +#include "util/fixed_point.h" namespace openage::event { -void EventEntity::changes(const curve::time_t &time) { +void EventEntity::changes(const time::time_t &time) { // This target has some change, so we have to notify all dependents // that subscribed on this entity. @@ -46,7 +48,7 @@ void EventEntity::changes(const curve::time_t &time) { case EventHandler::trigger_type::ONCE: // If the dependent is a ONCE-event // forget the change if the once event has been notified already. - if (dependent->get_last_changed() > curve::time_t::min_value()) { + if (dependent->get_last_changed() > time::time_t::min_value()) { it = this->dependents.erase(it); } else { @@ -74,7 +76,7 @@ void EventEntity::changes(const curve::time_t &time) { } -void EventEntity::trigger(const curve::time_t &last_valid_time) { +void EventEntity::trigger(const time::time_t &last_valid_time) { // notify all dependent events that are triggered `on_keyframe` // that the this target changed. // the only events that is "notified" by are TRIGGER. diff --git a/libopenage/event/evententity.h b/libopenage/event/evententity.h index bef9a467c6..6dc90c4716 100644 --- a/libopenage/event/evententity.h +++ b/libopenage/event/evententity.h @@ -2,17 +2,18 @@ #pragma once +#include #include #include #include +#include -#include "curve/curve.h" +#include "time/time.h" namespace openage::event { class Event; class EventLoop; -class EventHandler; /** * Every Object in the gameworld that wants to be targeted by events or as @@ -26,7 +27,7 @@ class EventEntity { /** Give a human-readable identifier for this target */ virtual std::string idstr() const = 0; - using single_change_notifier = std::function; + using single_change_notifier = std::function; protected: /** @@ -60,12 +61,12 @@ class EventEntity { * Call this whenever some data in the target changes. * This triggers the reevaluation of dependent events. */ - void changes(const curve::time_t &change_time); + void changes(const time::time_t &change_time); /** * Call this when depending TriggerEventHandleres should be invoked. */ - void trigger(const curve::time_t &invoke_time); + void trigger(const time::time_t &invoke_time); private: /** Event loop this target is registered to */ diff --git a/libopenage/event/eventhandler.cpp b/libopenage/event/eventhandler.cpp index 1e7575e3b1..162b38cc71 100644 --- a/libopenage/event/eventhandler.cpp +++ b/libopenage/event/eventhandler.cpp @@ -1,12 +1,7 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #include "eventhandler.h" -#include "event.h" -#include "evententity.h" - -#include "../log/log.h" - namespace openage::event { @@ -20,29 +15,24 @@ const std::string &EventHandler::id() { } -DependencyEventHandler::DependencyEventHandler(const std::string &name) - : +DependencyEventHandler::DependencyEventHandler(const std::string &name) : EventHandler(name, EventHandler::trigger_type::DEPENDENCY) {} -DependencyImmediatelyEventHandler::DependencyImmediatelyEventHandler(const std::string &name) - : +DependencyImmediatelyEventHandler::DependencyImmediatelyEventHandler(const std::string &name) : EventHandler(name, EventHandler::trigger_type::DEPENDENCY_IMMEDIATELY) {} -TriggerEventHandler::TriggerEventHandler(const std::string &name) - : +TriggerEventHandler::TriggerEventHandler(const std::string &name) : EventHandler(name, EventHandler::trigger_type::TRIGGER) {} -RepeatEventHandler::RepeatEventHandler(const std::string &name) - : +RepeatEventHandler::RepeatEventHandler(const std::string &name) : EventHandler(name, EventHandler::trigger_type::REPEAT) {} -OnceEventHandler::OnceEventHandler(const std::string &name) - : +OnceEventHandler::OnceEventHandler(const std::string &name) : EventHandler(name, EventHandler::trigger_type::ONCE) {} -} // openage::event +} // namespace openage::event diff --git a/libopenage/event/eventhandler.h b/libopenage/event/eventhandler.h index 966ff1cc68..598aa290b7 100644 --- a/libopenage/event/eventhandler.h +++ b/libopenage/event/eventhandler.h @@ -2,14 +2,15 @@ #pragma once -#include "../curve/curve.h" - - #include +#include #include #include #include #include +#include + +#include "time/time.h" namespace openage::event { @@ -75,19 +76,22 @@ class EventHandler { using map_t = std::unordered_map; param_map() {} - param_map(std::initializer_list l) : map(l) {} - param_map(const map_t &map) : map{std::move(map)} {} + param_map(std::initializer_list l) : + map(l) {} + param_map(const map_t &map) : + map{std::move(map)} {} /** * Returns the value, if it exists and is the right type. * defaultval if not. */ - template - T get(const std::string &key, const T &defaultval=T()) const { + template + T get(const std::string &key, const T &defaultval = T()) const { auto it = this->map.find(key); if (it != this->map.end() && this->check_type(it)) { return std::any_cast(it->second); - } else { + } + else { return defaultval; } } @@ -102,7 +106,7 @@ class EventHandler { /** * Check if the type of a map entry is correct. */ - template + template bool check_type(const std::string &key) const { auto it = map.find(key); if (it != map.end()) { @@ -112,7 +116,7 @@ class EventHandler { } private: - template + template bool check_type(const map_t::const_iterator &it) const { return it->second.type() == typeid(T); } @@ -157,7 +161,7 @@ class EventHandler { virtual void invoke(EventLoop &loop, const std::shared_ptr &target, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) = 0; /** @@ -176,9 +180,9 @@ class EventHandler { * then dependencies may not be resolved perfectly anymore * (if other events have already been calculated before that). */ - virtual curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &state, - const curve::time_t &at) = 0; + virtual time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &state, + const time::time_t &at) = 0; private: /** @@ -216,4 +220,4 @@ class OnceEventHandler : public EventHandler { }; -} // openage::event +} // namespace openage::event diff --git a/libopenage/event/eventqueue.cpp b/libopenage/event/eventqueue.cpp index 67437b2b70..83a96e6e16 100644 --- a/libopenage/event/eventqueue.cpp +++ b/libopenage/event/eventqueue.cpp @@ -1,15 +1,20 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #include "eventqueue.h" -#include +#include +#include #include -#include "event.h" -#include "eventhandler.h" -#include "evententity.h" -#include "../log/log.h" -#include "../util/compiler.h" +#include "log/message.h" + +#include "event/event.h" +#include "event/evententity.h" +#include "event/eventhandler.h" +#include "event/eventstore.h" +#include "log/log.h" +#include "time/time.h" +#include "util/fixed_point.h" namespace openage::event { @@ -17,24 +22,22 @@ namespace openage::event { std::shared_ptr EventQueue::create_event(const std::shared_ptr &trgt, const std::shared_ptr &cls, const std::shared_ptr &state, - const curve::time_t &reference_time, + const time::time_t &reference_time, const EventHandler::param_map ¶ms) { - auto event = std::make_shared(trgt, cls, params); cls->setup_event(event, state); - switch(cls->type) { + switch (cls->type) { case EventHandler::trigger_type::DEPENDENCY: case EventHandler::trigger_type::REPEAT: case EventHandler::trigger_type::ONCE: event->set_time(event->get_eventhandler() - ->predict_invoke_time(trgt, state, reference_time)); + ->predict_invoke_time(trgt, state, reference_time)); - if (event->get_time() == std::numeric_limits::min()) { + if (event->get_time() == std::numeric_limits::min()) { log::log(DBG << "Queue: ignoring insertion of event " - << event->get_eventhandler()->id() << - " because no execution was scheduled."); + << event->get_eventhandler()->id() << " because no execution was scheduled."); return {}; } @@ -46,12 +49,11 @@ std::shared_ptr EventQueue::create_event(const std::shared_ptrget_eventhandler()->id() << - " into queue to be executed at t=" << event->get_time()); + log::log(DBG << "Queue: inserting event " << event->get_eventhandler()->id() << " into queue to be executed at t=" << event->get_time()); // store the event // or enqueue it for execution - switch(event->get_eventhandler()->type) { + switch (event->get_eventhandler()->type) { case EventHandler::trigger_type::DEPENDENCY: this->dependency_events.insert(event); break; @@ -74,16 +76,14 @@ std::shared_ptr EventQueue::create_event(const std::shared_ptr &event, - const curve::time_t &changed_at) { - - const curve::time_t event_previous_changed = event->get_last_changed(); + const time::time_t &changed_at) { + const time::time_t event_previous_changed = event->get_last_changed(); // Has the event already been fired in this round? if (event_previous_changed < changed_at) { @@ -94,8 +94,8 @@ void EventQueue::add_change(const std::shared_ptr &event, // Is the new change dated _before_ the old one? if (changed_at < it->time) { log::log(DBG << "Queue: adjusting time in change queue: moving event of " - << event->get_eventhandler()->id() - << " to earlier time"); + << event->get_eventhandler()->id() + << " to earlier time"); // Save the element Change change = *it; @@ -109,24 +109,24 @@ void EventQueue::add_change(const std::shared_ptr &event, else { // this change is to be ignored log::log(DBG << "Queue: skipping change for " << event->get_eventhandler()->id() - << " at " << changed_at - << " because there was already an earlier one at t=" << it->time); + << " at " << changed_at + << " because there was already an earlier one at t=" << it->time); } } else { // the change was not in the to be changed list this->changes->emplace(event, changed_at); log::log(DBG << "Queue: inserting change for event from " - << event->get_eventhandler()->id() - << " to be applied at t=" << changed_at); + << event->get_eventhandler()->id() + << " to be applied at t=" << changed_at); } } else { // the event has been triggered in this round already, so skip it this time this->future_changes->emplace(event, changed_at); log::log(DBG << "Queue: ignoring change at t=" << changed_at - << " for event for handler " << event->get_eventhandler()->id() - << " because it's already processed as change at t=" << event_previous_changed); + << " for event for handler " << event->get_eventhandler()->id() + << " because it's already processed as change at t=" << event_previous_changed); } event->set_last_changed(changed_at); @@ -161,7 +161,7 @@ const EventStore &EventQueue::get_event_queue() const { } -std::shared_ptr EventQueue::take_event(const curve::time_t &max_time) { +std::shared_ptr EventQueue::take_event(const time::time_t &max_time) { if (this->event_queue.size() == 0) { return nullptr; } @@ -198,22 +198,22 @@ void EventQueue::swap_changesets() { EventQueue::Change::Change(const std::shared_ptr &evnt, - curve::time_t time) - : + time::time_t time) : time{std::move(time)}, evnt{evnt}, hash{evnt->hash()} {} -size_t EventQueue::Change::Equal::operator()(const Change& left, - const Change& right) const { +size_t EventQueue::Change::Equal::operator()(const Change &left, + const Change &right) const { auto left_evnt = left.evnt.lock(); auto right_evnt = right.evnt.lock(); if (left_evnt && right_evnt) { if (left_evnt->get_eventhandler()->id() == right_evnt->get_eventhandler()->id()) { return true; } - } else { + } + else { return false; } diff --git a/libopenage/event/eventqueue.h b/libopenage/event/eventqueue.h index c3549ee1b8..6cc12c93cb 100644 --- a/libopenage/event/eventqueue.h +++ b/libopenage/event/eventqueue.h @@ -2,46 +2,46 @@ #pragma once +#include #include #include -#include "eventhandler.h" -#include "eventstore.h" -#include "../curve/curve.h" +#include "event/eventhandler.h" +#include "event/eventstore.h" +#include "time/time.h" namespace openage::event { class Event; -class EventLoop; class EventEntity; +class State; /** * The core event handler for execution and execution dependencies. */ class EventQueue final { public: - class Change { public: Change(const std::shared_ptr &evnt, - curve::time_t time); + time::time_t time); - curve::time_t time; + time::time_t time; std::weak_ptr evnt; const size_t hash; class Hasher { public: - size_t operator ()(const Change& e) const { + size_t operator()(const Change &e) const { return e.hash; } }; class Equal { public: - size_t operator ()(const Change& left, - const Change& right) const; + size_t operator()(const Change &left, + const Change &right) const; }; }; @@ -67,7 +67,7 @@ class EventQueue final { std::shared_ptr create_event(const std::shared_ptr &evententity, const std::shared_ptr &eventhandler, const std::shared_ptr &state, - const curve::time_t &reference_time, + const time::time_t &reference_time, const EventHandler::param_map ¶ms); /** @@ -93,7 +93,7 @@ class EventQueue final { * An event target has changed, and the event shall be retriggered */ void add_change(const std::shared_ptr &event, - const curve::time_t &changed_at); + const time::time_t &changed_at); /** * Get an accessor to the running queue for state output purpose. @@ -103,7 +103,7 @@ class EventQueue final { /** * Obtain the next event from the `event_queue` that happens before `<= max_time`. */ - std::shared_ptr take_event(const curve::time_t &max_time); + std::shared_ptr take_event(const time::time_t &max_time); /** * Get the change_set to process changes. @@ -122,7 +122,6 @@ class EventQueue final { void swap_changesets(); private: - // Implement double buffering around changesets, that we do not run into deadlocks // those point to the `changeset_A` and `changeset_B`. change_set *changes; @@ -154,4 +153,4 @@ class EventQueue final { EventStore event_queue; }; -} // openage::event +} // namespace openage::event diff --git a/libopenage/event/eventstore.cpp b/libopenage/event/eventstore.cpp index dfa8dcc35d..7e88b4e638 100644 --- a/libopenage/event/eventstore.cpp +++ b/libopenage/event/eventstore.cpp @@ -3,11 +3,12 @@ #include "eventstore.h" #include +#include +#include -#include "event.h" +#include "log/message.h" -#include "../util/compiler.h" -#include "../error/error.h" +#include "error/error.h" namespace openage::event { @@ -39,8 +40,8 @@ std::shared_ptr EventStore::pop() { throw Error{ERR << "inconsistent: prev_heap=" << heap_s << " prev_map=" << evnt_s}; } - //ENSURE(this->heap.size() == this->events.size(), - // "heap and event set are inconsistent 1"); + //ENSURE(this->heap.size() == this->events.size(), + // "heap and event set are inconsistent 1"); return event; } @@ -107,18 +108,16 @@ std::vector> EventStore::get_sorted_events() const { std::back_inserter(ret), [](const auto &elem) { return elem.first; - } - ); + }); std::sort( std::begin(ret), std::end(ret), [](const auto &a, const auto &b) { return *a < *b; - } - ); + }); return ret; } -} // openage::event +} // namespace openage::event diff --git a/libopenage/event/eventstore.h b/libopenage/event/eventstore.h index f557303f24..be67743fb0 100644 --- a/libopenage/event/eventstore.h +++ b/libopenage/event/eventstore.h @@ -1,17 +1,18 @@ -// Copyright 2018-2018 the openage authors. See copying.md for legal info. +// Copyright 2018-2023 the openage authors. See copying.md for legal info. #pragma once -#include "../datastructure/pairing_heap.h" -#include "../util/misc.h" - +#include #include #include +#include +#include "datastructure/pairing_heap.h" +#include "event/event.h" +#include "util/misc.h" -namespace openage::event { -class Event; +namespace openage::event { /** * Sorted storage for events. @@ -19,7 +20,6 @@ class Event; */ class EventStore { public: - // TODO: don't store a double-sharedpointer. // instead, use the event-sharedpointer directly. using heap_t = datastructure::PairingHeap, @@ -48,4 +48,4 @@ class EventStore { }; -} // openage::event +} // namespace openage::event diff --git a/libopenage/event/tests.cpp b/libopenage/event/tests.cpp index 5333ad7a3f..779f1ed09f 100644 --- a/libopenage/event/tests.cpp +++ b/libopenage/event/tests.cpp @@ -1,17 +1,25 @@ // Copyright 2017-2023 the openage authors. See copying.md for legal info. +#include #include #include -#include +#include +#include +#include +#include #include #include "log/log.h" +#include "log/message.h" #include "testing/testing.h" -#include "event.h" -#include "event_loop.h" -#include "evententity.h" -#include "state.h" +#include "event/event.h" +#include "event/event_loop.h" +#include "event/evententity.h" +#include "event/eventhandler.h" +#include "event/state.h" +#include "time/time.h" +#include "util/fixed_point.h" namespace openage::event::tests { @@ -28,9 +36,9 @@ class TestState : public State { _id{id}, number(0) {} - void set_number(int number, const curve::time_t &time) { + void set_number(int number, const time::time_t &time) { this->number = number; - this->changes(time + curve::time_t::from_double(1)); + this->changes(time + time::time_t::from_double(1)); } [[nodiscard]] size_t id() const override { @@ -43,7 +51,7 @@ class TestState : public State { return ss.str(); } - void test_trigger(const curve::time_t &time) { + void test_trigger(const time::time_t &time) { this->trigger(time); } @@ -59,11 +67,11 @@ class TestState : public State { std::shared_ptr objectB; struct traceelement { - traceelement(std::string event, curve::time_t time) : + traceelement(std::string event, time::time_t time) : time{std::move(time)}, name{std::move(event)} {} - curve::time_t time; + time::time_t time; std::string name; }; @@ -105,7 +113,7 @@ class TestEventHandler : public EventHandler { void invoke(EventLoop & /*loop*/, const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &time, + const time::time_t &time, const EventHandler::param_map & /*param*/) override { auto state = std::dynamic_pointer_cast(gstate); @@ -126,10 +134,10 @@ class TestEventHandler : public EventHandler { } } - curve::time_t predict_invoke_time(const std::shared_ptr & /*target*/, - const std::shared_ptr & /*state*/, - const curve::time_t &at) override { - return at + curve::time_t::from_double(2); + time::time_t predict_invoke_time(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/, + const time::time_t &at) override { + return at + time::time_t::from_double(2); } }; @@ -148,7 +156,7 @@ class TestEventHandlerTwo : public EventHandler { void invoke(EventLoop & /*loop*/, const std::shared_ptr >arget, const std::shared_ptr &gstate, - const curve::time_t &time, + const time::time_t &time, const EventHandler::param_map & /*param*/) override { auto state = std::dynamic_pointer_cast(gstate); auto target = std::dynamic_pointer_cast(gtarget); @@ -158,11 +166,11 @@ class TestEventHandlerTwo : public EventHandler { state->trace.emplace_back("B", time); } - curve::time_t predict_invoke_time(const std::shared_ptr & /*target*/, - const std::shared_ptr & /*state*/, - const curve::time_t &at) override { + time::time_t predict_invoke_time(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/, + const time::time_t &at) override { // TODO recalculate a hit time - return at + curve::time_t::from_double(1); + return at + time::time_t::from_double(1); } }; @@ -184,7 +192,7 @@ class EventTypeTestClass : public EventHandler { void invoke(EventLoop & /*loop*/, const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &time, + const time::time_t &time, const EventHandler::param_map & /*param*/) override { auto state = std::dynamic_pointer_cast(gstate); @@ -195,13 +203,13 @@ class EventTypeTestClass : public EventHandler { state->trace.emplace_back(this->id(), time); } - curve::time_t predict_invoke_time(const std::shared_ptr & /*target*/, - const std::shared_ptr & /*state*/, - const curve::time_t &at) override { + time::time_t predict_invoke_time(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/, + const time::time_t &at) override { switch (this->type) { case EventHandler::trigger_type::DEPENDENCY: // Execute 1 after the change (usually it is neccessary to recalculate a collision - return at + curve::time_t::from_double(1); + return at + time::time_t::from_double(1); case EventHandler::trigger_type::DEPENDENCY_IMMEDIATELY: TESTFAILMSG("DEPENDENCY_IMMEDIATELY does not recalculate time!"); @@ -213,7 +221,7 @@ class EventTypeTestClass : public EventHandler { case EventHandler::trigger_type::REPEAT: // This will force the execution every 5ms - return at + curve::time_t::from_double(5); + return at + time::time_t::from_double(5); case EventHandler::trigger_type::ONCE: return 10; // even if data changed it will happen at the given time! @@ -261,7 +269,7 @@ void eventtrigger() { int i = 0; - curve::time_t last_time = 0; + time::time_t last_time = 0; for (const auto &e : state->trace) { if (last_time > e.time) { TESTFAILMSG("You broke the time continuum: one shall not execute randomly!"); @@ -336,7 +344,7 @@ void eventtrigger() { } int i = 0; - curve::time_t last_time = 0; + time::time_t last_time = 0; for (const auto &e : state->trace) { if (last_time > e.time) { @@ -539,7 +547,7 @@ void eventtrigger() { void invoke(EventLoop & /*loop*/, const std::shared_ptr & /*target*/, const std::shared_ptr & /*state*/, - const curve::time_t & /*time*/, + const time::time_t & /*time*/, const EventHandler::param_map ¶m) override { log::log(DBG << "Testing unknown parameter"); TESTEQUALS(param.contains("tomato"), false); @@ -566,9 +574,9 @@ void eventtrigger() { TESTEQUALS(param.get("testStdString"), "stdstring"); } - curve::time_t predict_invoke_time(const std::shared_ptr & /*target*/, - const std::shared_ptr & /*state*/, - const curve::time_t &at) override { + time::time_t predict_invoke_time(const std::shared_ptr & /*target*/, + const std::shared_ptr & /*state*/, + const time::time_t &at) override { return at; } }; diff --git a/libopenage/gamestate/activity/activity.h b/libopenage/gamestate/activity/activity.h index 1a52f2a337..f5be9d254a 100644 --- a/libopenage/gamestate/activity/activity.h +++ b/libopenage/gamestate/activity/activity.h @@ -2,12 +2,13 @@ #pragma once +#include #include - -#include "gamestate/activity/node.h" +#include namespace openage::gamestate::activity { +class Node; using activity_id = size_t; using activity_label = std::string; diff --git a/libopenage/gamestate/activity/end_node.cpp b/libopenage/gamestate/activity/end_node.cpp index dbb8bbebf4..01ecfebade 100644 --- a/libopenage/gamestate/activity/end_node.cpp +++ b/libopenage/gamestate/activity/end_node.cpp @@ -2,6 +2,9 @@ #include "end_node.h" +#include "error/error.h" +#include "log/message.h" + namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/end_node.h b/libopenage/gamestate/activity/end_node.h index 59500daaaf..c068f39475 100644 --- a/libopenage/gamestate/activity/end_node.h +++ b/libopenage/gamestate/activity/end_node.h @@ -5,6 +5,7 @@ #include #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/event_node.cpp b/libopenage/gamestate/activity/event_node.cpp index 92f703641e..3d28e007a3 100644 --- a/libopenage/gamestate/activity/event_node.cpp +++ b/libopenage/gamestate/activity/event_node.cpp @@ -2,10 +2,12 @@ #include "event_node.h" +#include + namespace openage::gamestate::activity { -EventNode::EventNode(node_id id, +XorEventGate::XorEventGate(node_id id, node_label label, const std::vector> &outputs, event_primer_func_t primer_func, @@ -15,23 +17,23 @@ EventNode::EventNode(node_id id, next_func{next_func} { } -void EventNode::add_output(const std::shared_ptr &output) { +void XorEventGate::add_output(const std::shared_ptr &output) { this->outputs.emplace(output->get_id(), output); } -void EventNode::set_primer_func(event_primer_func_t primer_func) { +void XorEventGate::set_primer_func(event_primer_func_t primer_func) { this->primer_func = primer_func; } -void EventNode::set_next_func(event_next_func_t next_func) { +void XorEventGate::set_next_func(event_next_func_t next_func) { this->next_func = next_func; } -event_primer_func_t EventNode::get_primer_func() const { +event_primer_func_t XorEventGate::get_primer_func() const { return this->primer_func; } -event_next_func_t EventNode::get_next_func() const { +event_next_func_t XorEventGate::get_next_func() const { return this->next_func; } diff --git a/libopenage/gamestate/activity/event_node.h b/libopenage/gamestate/activity/event_node.h index 17c035df56..a753682b68 100644 --- a/libopenage/gamestate/activity/event_node.h +++ b/libopenage/gamestate/activity/event_node.h @@ -2,7 +2,16 @@ #pragma once +#include +#include +#include + +#include "error/error.h" +#include "log/message.h" + #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" +#include "time/time.h" namespace openage { @@ -30,7 +39,7 @@ using event_store_t = std::vector>; * * @return List of events registered on the event loop. */ -using event_primer_func_t = std::function &, const std::shared_ptr &, const std::shared_ptr &)>; @@ -45,13 +54,13 @@ using event_primer_func_t = std::function &, const std::shared_ptr &, const std::shared_ptr &)>; -static const event_primer_func_t no_event = [](const curve::time_t &, +static const event_primer_func_t no_event = [](const time::time_t &, const std::shared_ptr &, const std::shared_ptr &, const std::shared_ptr &) { @@ -59,7 +68,7 @@ static const event_primer_func_t no_event = [](const curve::time_t &, return event_store_t{}; }; -static const event_next_func_t no_next = [](const curve::time_t &, +static const event_next_func_t no_next = [](const time::time_t &, const std::shared_ptr &, const std::shared_ptr &, const std::shared_ptr &) { @@ -71,10 +80,10 @@ static const event_next_func_t no_next = [](const curve::time_t &, /** * Waits for an event to be executed before continuing the control flow. */ -class EventNode : public Node { +class XorEventGate : public Node { public: /** - * Create a new event node. + * Create a new exclusive event gateway. * * @param id Unique identifier for this node. * @param label Human-readable label (optional). @@ -82,15 +91,15 @@ class EventNode : public Node { * @param primer_func Function to create and register the event. * @param next_func Function to decide which node to visit after the event is handled. */ - EventNode(node_id id, - node_label label = "Event", - const std::vector> &outputs = {}, - event_primer_func_t primer_func = no_event, - event_next_func_t next_func = no_next); - virtual ~EventNode() = default; + XorEventGate(node_id id, + node_label label = "Event", + const std::vector> &outputs = {}, + event_primer_func_t primer_func = no_event, + event_next_func_t next_func = no_next); + virtual ~XorEventGate() = default; inline node_t get_type() const override { - return node_t::EVENT_GATEWAY; + return node_t::XOR_EVENT_GATE; } /** diff --git a/libopenage/gamestate/activity/node.cpp b/libopenage/gamestate/activity/node.cpp index 62e924b8ea..5c7f007d74 100644 --- a/libopenage/gamestate/activity/node.cpp +++ b/libopenage/gamestate/activity/node.cpp @@ -2,6 +2,11 @@ #include "node.h" +#include + +#include "error/error.h" +#include "log/message.h" + namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/node.h b/libopenage/gamestate/activity/node.h index 4abec66e6f..9a8edfcf9f 100644 --- a/libopenage/gamestate/activity/node.h +++ b/libopenage/gamestate/activity/node.h @@ -2,10 +2,12 @@ #pragma once +#include #include +#include #include +#include -#include "curve/curve.h" #include "gamestate/activity/types.h" diff --git a/libopenage/gamestate/activity/start_node.cpp b/libopenage/gamestate/activity/start_node.cpp index adf2ffc912..8686fc2f4e 100644 --- a/libopenage/gamestate/activity/start_node.cpp +++ b/libopenage/gamestate/activity/start_node.cpp @@ -2,6 +2,9 @@ #include "start_node.h" +#include +#include + namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/start_node.h b/libopenage/gamestate/activity/start_node.h index d69616b70d..bec65e6ea7 100644 --- a/libopenage/gamestate/activity/start_node.h +++ b/libopenage/gamestate/activity/start_node.h @@ -5,6 +5,7 @@ #include #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/task_node.cpp b/libopenage/gamestate/activity/task_node.cpp index 36033cb954..36b5de6663 100644 --- a/libopenage/gamestate/activity/task_node.cpp +++ b/libopenage/gamestate/activity/task_node.cpp @@ -2,10 +2,13 @@ #include "task_node.h" +#include +#include + namespace openage::gamestate::activity { -TaskNode::TaskNode(node_id id, +TaskCustom::TaskCustom(node_id id, node_label label, const std::shared_ptr &output, task_func_t task_func) : @@ -16,20 +19,20 @@ TaskNode::TaskNode(node_id id, } } -void TaskNode::add_output(const std::shared_ptr &output) { +void TaskCustom::add_output(const std::shared_ptr &output) { this->outputs.clear(); this->outputs.emplace(output->get_id(), output); } -void TaskNode::set_task_func(task_func_t task_func) { +void TaskCustom::set_task_func(task_func_t task_func) { this->task_func = task_func; } -task_func_t TaskNode::get_task_func() const { +task_func_t TaskCustom::get_task_func() const { return this->task_func; } -node_id TaskNode::get_next() const { +node_id TaskCustom::get_next() const { return (*this->outputs.begin()).first; } diff --git a/libopenage/gamestate/activity/task_node.h b/libopenage/gamestate/activity/task_node.h index bb9a72ebd6..0efd3f784b 100644 --- a/libopenage/gamestate/activity/task_node.h +++ b/libopenage/gamestate/activity/task_node.h @@ -5,7 +5,12 @@ #include #include +#include "error/error.h" +#include "log/message.h" + #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" +#include "time/time.h" namespace openage::gamestate { @@ -13,10 +18,10 @@ class GameEntity; namespace activity { -using task_func_t = std::function &)>; -static const task_func_t no_task = [](const curve::time_t &, +static const task_func_t no_task = [](const time::time_t &, const std::shared_ptr &) { throw Error{ERR << "No task defined for this node."}; }; @@ -24,7 +29,7 @@ static const task_func_t no_task = [](const curve::time_t &, /** * Executes a function when visited. */ -class TaskNode : public Node { +class TaskCustom : public Node { public: /** * Create a new task node. @@ -34,14 +39,14 @@ class TaskNode : public Node { * @param task_func Action to perform when visiting this node (can be set later). * @param output Next node to visit (optional). */ - TaskNode(node_id id, - node_label label = "Task", - const std::shared_ptr &output = nullptr, - task_func_t task_func = no_task); - virtual ~TaskNode() = default; + TaskCustom(node_id id, + node_label label = "TaskCustom", + const std::shared_ptr &output = nullptr, + task_func_t task_func = no_task); + virtual ~TaskCustom() = default; inline node_t get_type() const override { - return node_t::TASK; + return node_t::TASK_CUSTOM; } /** diff --git a/libopenage/gamestate/activity/task_system_node.cpp b/libopenage/gamestate/activity/task_system_node.cpp index 97c0f461d4..158bcc41b2 100644 --- a/libopenage/gamestate/activity/task_system_node.cpp +++ b/libopenage/gamestate/activity/task_system_node.cpp @@ -2,6 +2,9 @@ #include "task_system_node.h" +#include +#include + namespace openage::gamestate::activity { diff --git a/libopenage/gamestate/activity/task_system_node.h b/libopenage/gamestate/activity/task_system_node.h index 3619a042fa..8f9e6b1163 100644 --- a/libopenage/gamestate/activity/task_system_node.h +++ b/libopenage/gamestate/activity/task_system_node.h @@ -5,19 +5,20 @@ #include #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" #include "gamestate/system/types.h" namespace openage::gamestate::activity { /** - * Similar to the tas node, but runs a built-in system function + * Similar to the custom task node, but runs a built-in system function * when visited. */ class TaskSystemNode : public Node { public: /** - * Create a new task system node. + * Create a new custom task system node. * * @param id Unique identifier for this node. * @param label Human-readable label (optional). diff --git a/libopenage/gamestate/activity/tests.cpp b/libopenage/gamestate/activity/tests.cpp index 61d7fe0659..7588e5a9b0 100644 --- a/libopenage/gamestate/activity/tests.cpp +++ b/libopenage/gamestate/activity/tests.cpp @@ -1,19 +1,28 @@ // Copyright 2023-2023 the openage authors. See copying.md for legal info. -#include "log/log.h" +#include +#include +#include +#include -#include "event/event.h" #include "event/event_loop.h" #include "event/evententity.h" #include "event/eventhandler.h" #include "event/state.h" +#include "error/error.h" +#include "log/log.h" +#include "log/message.h" + #include "gamestate/activity/end_node.h" #include "gamestate/activity/event_node.h" +#include "gamestate/activity/node.h" #include "gamestate/activity/start_node.h" #include "gamestate/activity/task_node.h" #include "gamestate/activity/types.h" #include "gamestate/activity/xor_node.h" +#include "time/time.h" + namespace openage::gamestate::tests { @@ -83,15 +92,15 @@ class TestActivityHandler : public event::OnceEventHandler { void invoke(event::EventLoop & /* loop */, const std::shared_ptr &target, const std::shared_ptr & /* state */, - const curve::time_t & /* time */, + const time::time_t & /* time */, const param_map & /* params */) override { auto mgr_target = std::dynamic_pointer_cast(target); mgr_target->run(); } - curve::time_t predict_invoke_time(const std::shared_ptr & /* target */, - const std::shared_ptr & /* state */, - const curve::time_t &at) override { + time::time_t predict_invoke_time(const std::shared_ptr & /* target */, + const std::shared_ptr & /* state */, + const time::time_t &at) override { return at; } }; @@ -100,8 +109,8 @@ class TestActivityHandler : public event::OnceEventHandler { const std::shared_ptr activity_flow(const std::shared_ptr ¤t_node) { auto current = current_node; - if (current->get_type() == activity::node_t::EVENT_GATEWAY) { - auto node = std::static_pointer_cast(current); + if (current->get_type() == activity::node_t::XOR_EVENT_GATE) { + auto node = std::static_pointer_cast(current); auto event_next = node->get_next_func(); auto next_id = event_next(0, nullptr, nullptr, nullptr); current = node->next(next_id); @@ -120,21 +129,21 @@ const std::shared_ptr activity_flow(const std::shared_ptr(current); + case activity::node_t::TASK_CUSTOM: { + auto node = std::static_pointer_cast(current); auto task = node->get_task_func(); task(0, nullptr); auto next_id = node->get_next(); current = node->next(next_id); } break; - case activity::node_t::XOR_GATEWAY: { - auto node = std::static_pointer_cast(current); + case activity::node_t::XOR_GATE: { + auto node = std::static_pointer_cast(current); auto condition = node->get_condition_func(); auto next_id = condition(0, nullptr); current = node->next(next_id); } break; - case activity::node_t::EVENT_GATEWAY: { - auto node = std::static_pointer_cast(current); + case activity::node_t::XOR_EVENT_GATE: { + auto node = std::static_pointer_cast(current); auto event_primer = node->get_primer_func(); event_primer(0, nullptr, nullptr, nullptr); @@ -172,10 +181,10 @@ void activity_demo() { // create the nodes in the graph // connections are created further below auto start = std::make_shared(0); - auto task1 = std::make_shared(1); - auto xor_node = std::make_shared(2); - auto event_node = std::make_shared(3); - auto task2 = std::make_shared(4); + auto task1 = std::make_shared(1); + auto xor_node = std::make_shared(2); + auto event_node = std::make_shared(3); + auto task2 = std::make_shared(4); auto end = std::make_shared(5); // create an activity manager that controls the flow @@ -188,7 +197,7 @@ void activity_demo() { // task 1 task1->add_output(xor_node); - task1->set_task_func([](const curve::time_t & /* time */, + task1->set_task_func([](const time::time_t & /* time */, const std::shared_ptr & /* entity */) { log::log(INFO << "Running task 1"); }); @@ -197,7 +206,7 @@ void activity_demo() { size_t counter = 0; xor_node->add_output(task1); xor_node->add_output(event_node); - xor_node->set_condition_func([&](const curve::time_t & /* time */, + xor_node->set_condition_func([&](const time::time_t & /* time */, const std::shared_ptr & /* entity */) { log::log(INFO << "Checking condition (counter < 4): counter=" << counter); if (counter < 4) { @@ -214,7 +223,7 @@ void activity_demo() { // event node event_node->add_output(task2); - event_node->set_primer_func([&](const curve::time_t & /* time */, + event_node->set_primer_func([&](const time::time_t & /* time */, const std::shared_ptr & /* entity */, const std::shared_ptr & /* loop */, const std::shared_ptr & /* state */) { @@ -225,7 +234,7 @@ void activity_demo() { 0); return activity::event_store_t{ev}; }); - event_node->set_next_func([&task2](const curve::time_t & /* time */, + event_node->set_next_func([&task2](const time::time_t & /* time */, const std::shared_ptr & /* entity */, const std::shared_ptr & /* loop */, const std::shared_ptr & /* state */) { @@ -235,7 +244,7 @@ void activity_demo() { // task 2 task2->add_output(end); - task2->set_task_func([](const curve::time_t & /* time */, + task2->set_task_func([](const time::time_t & /* time */, const std::shared_ptr & /* entity */) { log::log(INFO << "Running task 2"); }); diff --git a/libopenage/gamestate/activity/types.h b/libopenage/gamestate/activity/types.h index 0315e3d672..ac2189e5ab 100644 --- a/libopenage/gamestate/activity/types.h +++ b/libopenage/gamestate/activity/types.h @@ -11,9 +11,9 @@ namespace openage::gamestate::activity { enum class node_t { START, END, - EVENT_GATEWAY, - XOR_GATEWAY, - TASK, + XOR_EVENT_GATE, + XOR_GATE, + TASK_CUSTOM, TASK_SYSTEM, }; diff --git a/libopenage/gamestate/activity/xor_node.cpp b/libopenage/gamestate/activity/xor_node.cpp index cd5a744197..644362f877 100644 --- a/libopenage/gamestate/activity/xor_node.cpp +++ b/libopenage/gamestate/activity/xor_node.cpp @@ -2,10 +2,12 @@ #include "xor_node.h" +#include + namespace openage::gamestate::activity { -ConditionNode::ConditionNode(node_id id, +XorGate::XorGate(node_id id, node_label label, const std::vector> &outputs, condition_func_t condition_func) : @@ -13,15 +15,15 @@ ConditionNode::ConditionNode(node_id id, condition_func{condition_func} { } -void ConditionNode::add_output(const std::shared_ptr &output) { +void XorGate::add_output(const std::shared_ptr &output) { this->outputs.emplace(output->get_id(), output); } -void ConditionNode::set_condition_func(condition_func_t condition_func) { +void XorGate::set_condition_func(condition_func_t condition_func) { this->condition_func = condition_func; } -condition_func_t ConditionNode::get_condition_func() const { +condition_func_t XorGate::get_condition_func() const { return this->condition_func; } diff --git a/libopenage/gamestate/activity/xor_node.h b/libopenage/gamestate/activity/xor_node.h index 907bbf5aca..39efca6209 100644 --- a/libopenage/gamestate/activity/xor_node.h +++ b/libopenage/gamestate/activity/xor_node.h @@ -2,7 +2,16 @@ #pragma once +#include +#include +#include + +#include "error/error.h" +#include "log/message.h" + #include "gamestate/activity/node.h" +#include "gamestate/activity/types.h" +#include "time/time.h" namespace openage::gamestate { @@ -10,10 +19,10 @@ class GameEntity; namespace activity { -using condition_func_t = std::function &)>; -static const condition_func_t no_condition = [](const curve::time_t &, +static const condition_func_t no_condition = [](const time::time_t &, const std::shared_ptr &) -> node_id { throw Error{MSG(err) << "No condition function set."}; }; @@ -22,7 +31,7 @@ static const condition_func_t no_condition = [](const curve::time_t &, /** * Chooses one of its output nodes based on a condition. */ -class ConditionNode : public Node { +class XorGate : public Node { public: /** * Creates a new condition node. @@ -33,14 +42,14 @@ class ConditionNode : public Node { * @param condition_func Function that determines which output node is chosen (can be set later). * This must be a valid node ID of one of the output nodes. */ - ConditionNode(node_id id, - node_label label = "Condition", - const std::vector> &outputs = {}, - condition_func_t condition_func = no_condition); - virtual ~ConditionNode() = default; + XorGate(node_id id, + node_label label = "ExclusiveGateway", + const std::vector> &outputs = {}, + condition_func_t condition_func = no_condition); + virtual ~XorGate() = default; inline node_t get_type() const override { - return node_t::XOR_GATEWAY; + return node_t::XOR_GATE; } /** diff --git a/libopenage/gamestate/api/ability.cpp b/libopenage/gamestate/api/ability.cpp index bd56040a2f..49ecfad48f 100644 --- a/libopenage/gamestate/api/ability.cpp +++ b/libopenage/gamestate/api/ability.cpp @@ -2,8 +2,17 @@ #include "ability.h" +#include +#include +#include +#include + +#include + +#include "datastructure/constexpr_map.h" #include "gamestate/api/definitions.h" + namespace openage::gamestate::api { bool APIAbility::is_ability(const nyan::Object &obj) { diff --git a/libopenage/gamestate/api/animation.cpp b/libopenage/gamestate/api/animation.cpp index 2dd79a4ca0..86cbfe6014 100644 --- a/libopenage/gamestate/api/animation.cpp +++ b/libopenage/gamestate/api/animation.cpp @@ -2,8 +2,11 @@ #include "animation.h" +#include + #include "gamestate/api/util.h" + namespace openage::gamestate::api { bool APIAnimation::is_animation(nyan::Object &obj) { diff --git a/libopenage/gamestate/api/animation.h b/libopenage/gamestate/api/animation.h index 0d9c235464..a002749786 100644 --- a/libopenage/gamestate/api/animation.h +++ b/libopenage/gamestate/api/animation.h @@ -2,6 +2,9 @@ #pragma once +#include +#include + #include diff --git a/libopenage/gamestate/api/definitions.h b/libopenage/gamestate/api/definitions.h index c884e32386..d06553c89e 100644 --- a/libopenage/gamestate/api/definitions.h +++ b/libopenage/gamestate/api/definitions.h @@ -2,11 +2,15 @@ #pragma once +#include +#include + #include #include "datastructure/constexpr_map.h" #include "gamestate/api/types.h" + namespace openage::gamestate::api { /** Maps internal ability types to nyan API values **/ diff --git a/libopenage/gamestate/api/patch.cpp b/libopenage/gamestate/api/patch.cpp index 9f4d2a0453..05c2f67d5f 100644 --- a/libopenage/gamestate/api/patch.cpp +++ b/libopenage/gamestate/api/patch.cpp @@ -2,6 +2,14 @@ #include "patch.h" +#include +#include +#include +#include + +#include + +#include "datastructure/constexpr_map.h" #include "gamestate/api/definitions.h" diff --git a/libopenage/gamestate/api/player_setup.cpp b/libopenage/gamestate/api/player_setup.cpp index 956662a374..4d01cf327d 100644 --- a/libopenage/gamestate/api/player_setup.cpp +++ b/libopenage/gamestate/api/player_setup.cpp @@ -2,6 +2,13 @@ #include "player_setup.h" +#include +#include +#include +#include + +#include + namespace openage::gamestate::api { diff --git a/libopenage/gamestate/api/player_setup.h b/libopenage/gamestate/api/player_setup.h index b4bbe4c7dc..f3e23fbc81 100644 --- a/libopenage/gamestate/api/player_setup.h +++ b/libopenage/gamestate/api/player_setup.h @@ -2,6 +2,8 @@ #pragma once +#include + #include diff --git a/libopenage/gamestate/api/property.cpp b/libopenage/gamestate/api/property.cpp index cbd12c4da1..fb4458dd5b 100644 --- a/libopenage/gamestate/api/property.cpp +++ b/libopenage/gamestate/api/property.cpp @@ -2,6 +2,13 @@ #include "property.h" +#include +#include +#include +#include + +#include + namespace openage::gamestate::api { diff --git a/libopenage/gamestate/api/property.h b/libopenage/gamestate/api/property.h index e3346ab635..702abd2088 100644 --- a/libopenage/gamestate/api/property.h +++ b/libopenage/gamestate/api/property.h @@ -2,6 +2,8 @@ #pragma once +#include + #include diff --git a/libopenage/gamestate/api/sound.cpp b/libopenage/gamestate/api/sound.cpp index e978842c93..0af5fafcf4 100644 --- a/libopenage/gamestate/api/sound.cpp +++ b/libopenage/gamestate/api/sound.cpp @@ -2,6 +2,10 @@ #include "sound.h" +#include + +#include + #include "gamestate/api/util.h" diff --git a/libopenage/gamestate/api/sound.h b/libopenage/gamestate/api/sound.h index 6237ac3812..c45fc7c397 100644 --- a/libopenage/gamestate/api/sound.h +++ b/libopenage/gamestate/api/sound.h @@ -2,6 +2,9 @@ #pragma once +#include +#include + #include diff --git a/libopenage/gamestate/api/util.cpp b/libopenage/gamestate/api/util.cpp index 907befcb73..7e59ebf9bd 100644 --- a/libopenage/gamestate/api/util.cpp +++ b/libopenage/gamestate/api/util.cpp @@ -2,9 +2,13 @@ #include "util.h" -#include "error/error.h" - #include +#include + +#include + +#include "error/error.h" +#include "log/message.h" namespace openage::gamestate::api { diff --git a/libopenage/gamestate/api/util.h b/libopenage/gamestate/api/util.h index 297705830a..cad829a205 100644 --- a/libopenage/gamestate/api/util.h +++ b/libopenage/gamestate/api/util.h @@ -2,6 +2,8 @@ #pragma once +#include + #include diff --git a/libopenage/gamestate/component/api/idle.cpp b/libopenage/gamestate/component/api/idle.cpp index 4d80e9ecff..1292fbadaf 100644 --- a/libopenage/gamestate/component/api/idle.cpp +++ b/libopenage/gamestate/component/api/idle.cpp @@ -6,7 +6,7 @@ namespace openage::gamestate::component { -inline component_t Idle::get_type() const { +component_t Idle::get_type() const { return component_t::IDLE; } diff --git a/libopenage/gamestate/component/api/idle.h b/libopenage/gamestate/component/api/idle.h index cf13a1c40c..f9d42e5330 100644 --- a/libopenage/gamestate/component/api/idle.h +++ b/libopenage/gamestate/component/api/idle.h @@ -3,6 +3,7 @@ #pragma once #include "gamestate/component/api_component.h" +#include "gamestate/component/types.h" namespace openage::gamestate::component { diff --git a/libopenage/gamestate/component/api/live.cpp b/libopenage/gamestate/component/api/live.cpp index 068500e029..01fafde5ea 100644 --- a/libopenage/gamestate/component/api/live.cpp +++ b/libopenage/gamestate/component/api/live.cpp @@ -2,22 +2,27 @@ #include "live.h" +#include + +#include "curve/discrete.h" +#include "curve/iterator.h" +#include "curve/map_filter_iterator.h" #include "gamestate/component/types.h" namespace openage::gamestate::component { -inline component_t Live::get_type() const { +component_t Live::get_type() const { return component_t::LIVE; } -void Live::add_attribute(const curve::time_t &time, +void Live::add_attribute(const time::time_t &time, const nyan::fqon_t &attribute, std::shared_ptr> starting_values) { this->attribute_values.insert(time, attribute, starting_values); } -void Live::set_attribute(const curve::time_t &time, +void Live::set_attribute(const time::time_t &time, const nyan::fqon_t &attribute, int64_t value) { auto attribute_value = this->attribute_values.at(time, attribute); diff --git a/libopenage/gamestate/component/api/live.h b/libopenage/gamestate/component/api/live.h index 300df6e1b1..dd3d8cb0a0 100644 --- a/libopenage/gamestate/component/api/live.h +++ b/libopenage/gamestate/component/api/live.h @@ -2,11 +2,16 @@ #pragma once +#include +#include + #include #include "curve/map.h" -#include "curve/segmented.h" #include "gamestate/component/api_component.h" +#include "gamestate/component/types.h" +#include "time/time.h" + namespace openage::gamestate::component { class Live : public APIComponent { @@ -22,7 +27,7 @@ class Live : public APIComponent { * @param attribute Attribute identifier (fqon of the nyan object). * @param starting_values Attribute values at the time of addition. */ - void add_attribute(const curve::time_t &time, + void add_attribute(const time::time_t &time, const nyan::fqon_t &attribute, std::shared_ptr> starting_values); @@ -33,7 +38,7 @@ class Live : public APIComponent { * @param attribute Attribute identifier (fqon of the nyan object). * @param value New attribute value. */ - void set_attribute(const curve::time_t &time, + void set_attribute(const time::time_t &time, const nyan::fqon_t &attribute, int64_t value); diff --git a/libopenage/gamestate/component/api/move.cpp b/libopenage/gamestate/component/api/move.cpp index aa9ac73daf..4abd1b5c3e 100644 --- a/libopenage/gamestate/component/api/move.cpp +++ b/libopenage/gamestate/component/api/move.cpp @@ -7,7 +7,7 @@ namespace openage::gamestate::component { -inline component_t Move::get_type() const { +component_t Move::get_type() const { return component_t::MOVE; } diff --git a/libopenage/gamestate/component/api/move.h b/libopenage/gamestate/component/api/move.h index 77bc538f05..1cc6d65cf7 100644 --- a/libopenage/gamestate/component/api/move.h +++ b/libopenage/gamestate/component/api/move.h @@ -3,6 +3,8 @@ #pragma once #include "gamestate/component/api_component.h" +#include "gamestate/component/types.h" + namespace openage::gamestate::component { diff --git a/libopenage/gamestate/component/api/turn.h b/libopenage/gamestate/component/api/turn.h index ef84bbf20c..881bb05de9 100644 --- a/libopenage/gamestate/component/api/turn.h +++ b/libopenage/gamestate/component/api/turn.h @@ -5,6 +5,8 @@ #include #include "gamestate/component/api_component.h" +#include "gamestate/component/types.h" + namespace openage::gamestate::component { diff --git a/libopenage/gamestate/component/api_component.cpp b/libopenage/gamestate/component/api_component.cpp index f8cb9e44b7..e61ccabfae 100644 --- a/libopenage/gamestate/component/api_component.cpp +++ b/libopenage/gamestate/component/api_component.cpp @@ -2,11 +2,12 @@ #include "api_component.h" + namespace openage::gamestate::component { APIComponent::APIComponent(const std::shared_ptr &loop, nyan::Object &ability, - const time_t &creation_time, + const time::time_t &creation_time, const bool enabled) : ability{ability}, enabled(loop, 0) { diff --git a/libopenage/gamestate/component/api_component.h b/libopenage/gamestate/component/api_component.h index af0681fa24..e994103c5e 100644 --- a/libopenage/gamestate/component/api_component.h +++ b/libopenage/gamestate/component/api_component.h @@ -2,10 +2,14 @@ #pragma once +#include + #include #include "curve/discrete.h" #include "gamestate/component/base_component.h" +#include "time/time.h" + namespace openage { @@ -31,7 +35,7 @@ class APIComponent : public Component { */ APIComponent(const std::shared_ptr &loop, nyan::Object &ability, - const time_t &creation_time, + const time::time_t &creation_time, bool enabled = true); /** diff --git a/libopenage/gamestate/component/internal/activity.cpp b/libopenage/gamestate/component/internal/activity.cpp index 4d284a390d..540ad1e532 100644 --- a/libopenage/gamestate/component/internal/activity.cpp +++ b/libopenage/gamestate/component/internal/activity.cpp @@ -2,7 +2,9 @@ #include "activity.h" +#include "event/event.h" #include "gamestate/activity/activity.h" +#include "gamestate/component/internal/activity.h" namespace openage::gamestate::component { @@ -21,16 +23,16 @@ const std::shared_ptr &Activity::get_start_activity() const return this->start_activity; } -const std::shared_ptr Activity::get_node(const curve::time_t &time) const { +const std::shared_ptr Activity::get_node(const time::time_t &time) const { return this->node.get(time); } -void Activity::set_node(const curve::time_t &time, +void Activity::set_node(const time::time_t &time, const std::shared_ptr &node) { this->node.set_last(time, node); } -void Activity::init(const curve::time_t &time) { +void Activity::init(const time::time_t &time) { this->set_node(time, this->start_activity->get_start()); } @@ -38,7 +40,7 @@ void Activity::add_event(const std::shared_ptr &event) { this->scheduled_events.push_back(event); } -void Activity::cancel_events(const curve::time_t &time) { +void Activity::cancel_events(const time::time_t &time) { for (auto &event : this->scheduled_events) { event->cancel(time); } diff --git a/libopenage/gamestate/component/internal/activity.h b/libopenage/gamestate/component/internal/activity.h index e3289f5226..a52a97bd57 100644 --- a/libopenage/gamestate/component/internal/activity.h +++ b/libopenage/gamestate/component/internal/activity.h @@ -7,6 +7,9 @@ #include "curve/discrete.h" #include "gamestate/component/internal_component.h" +#include "gamestate/component/types.h" +#include "time/time.h" + namespace openage { @@ -50,7 +53,7 @@ class Activity : public InternalComponent { * @param time Time at which the node is requested. * @return Current node in the flow graph. */ - const std::shared_ptr get_node(const curve::time_t &time) const; + const std::shared_ptr get_node(const time::time_t &time) const; /** * Sets the current node in the activity flow graph at a given time. @@ -58,7 +61,7 @@ class Activity : public InternalComponent { * @param time Time at which the node is set. * @param node Current node in the flow graph. */ - void set_node(const curve::time_t &time, + void set_node(const time::time_t &time, const std::shared_ptr &node); /** @@ -66,7 +69,7 @@ class Activity : public InternalComponent { * * @param time Time at which the node is set. */ - void init(const curve::time_t &time); + void init(const time::time_t &time); /** * Add a scheduled event that is waited for to progress in the node graph. @@ -80,7 +83,7 @@ class Activity : public InternalComponent { * * @param time Time at which the events are cancelled. */ - void cancel_events(const curve::time_t &time); + void cancel_events(const time::time_t &time); private: /** diff --git a/libopenage/gamestate/component/internal/command_queue.cpp b/libopenage/gamestate/component/internal/command_queue.cpp index 5e522d6ea8..6896f63cdf 100644 --- a/libopenage/gamestate/component/internal/command_queue.cpp +++ b/libopenage/gamestate/component/internal/command_queue.cpp @@ -2,6 +2,8 @@ #include "command_queue.h" +#include + #include "gamestate/component/types.h" @@ -15,7 +17,7 @@ inline component_t CommandQueue::get_type() const { return component_t::COMMANDQUEUE; } -void CommandQueue::add_command(const curve::time_t &time, +void CommandQueue::add_command(const time::time_t &time, const std::shared_ptr &command) { this->command_queue.insert(time, command); } @@ -24,7 +26,7 @@ const curve::Queue> &CommandQueue::get_queue() return this->command_queue; } -std::shared_ptr CommandQueue::pop_command(const curve::time_t &time) { +std::shared_ptr CommandQueue::pop_command(const time::time_t &time) { return this->command_queue.pop_front(time); } diff --git a/libopenage/gamestate/component/internal/command_queue.h b/libopenage/gamestate/component/internal/command_queue.h index 72594505de..6c16d5cbc7 100644 --- a/libopenage/gamestate/component/internal/command_queue.h +++ b/libopenage/gamestate/component/internal/command_queue.h @@ -2,9 +2,14 @@ #pragma once +#include + #include "curve/queue.h" #include "gamestate/component/internal/commands/base_command.h" #include "gamestate/component/internal_component.h" +#include "gamestate/component/types.h" +#include "time/time.h" + namespace openage { @@ -31,7 +36,7 @@ class CommandQueue : public InternalComponent { * @param time Time at which the command is added. * @param command New command. */ - void add_command(const curve::time_t &time, + void add_command(const time::time_t &time, const std::shared_ptr &command); /** @@ -48,7 +53,7 @@ class CommandQueue : public InternalComponent { * * @return Command in the front of the queue or nullptr if the queue is empty. */ - std::shared_ptr pop_command(const curve::time_t &time); + std::shared_ptr pop_command(const time::time_t &time); private: /** diff --git a/libopenage/gamestate/component/internal/commands/custom.h b/libopenage/gamestate/component/internal/commands/custom.h index 5e8764b17a..2cc8a6d910 100644 --- a/libopenage/gamestate/component/internal/commands/custom.h +++ b/libopenage/gamestate/component/internal/commands/custom.h @@ -5,6 +5,7 @@ #include #include "gamestate/component/internal/commands/base_command.h" +#include "gamestate/component/internal/commands/types.h" namespace openage::gamestate::component::command { diff --git a/libopenage/gamestate/component/internal/commands/idle.h b/libopenage/gamestate/component/internal/commands/idle.h index c0fb2d6ca2..9870ad1ce5 100644 --- a/libopenage/gamestate/component/internal/commands/idle.h +++ b/libopenage/gamestate/component/internal/commands/idle.h @@ -3,6 +3,7 @@ #pragma once #include "gamestate/component/internal/commands/base_command.h" +#include "gamestate/component/internal/commands/types.h" namespace openage::gamestate::component::command { diff --git a/libopenage/gamestate/component/internal/commands/move.h b/libopenage/gamestate/component/internal/commands/move.h index 713e1ebe55..0516dddb46 100644 --- a/libopenage/gamestate/component/internal/commands/move.h +++ b/libopenage/gamestate/component/internal/commands/move.h @@ -4,6 +4,7 @@ #include "coord/phys.h" #include "gamestate/component/internal/commands/base_command.h" +#include "gamestate/component/internal/commands/types.h" namespace openage::gamestate::component::command { diff --git a/libopenage/gamestate/component/internal/ownership.cpp b/libopenage/gamestate/component/internal/ownership.cpp index 249f7c88a6..5fcfd3c007 100644 --- a/libopenage/gamestate/component/internal/ownership.cpp +++ b/libopenage/gamestate/component/internal/ownership.cpp @@ -9,7 +9,7 @@ namespace openage::gamestate::component { Ownership::Ownership(const std::shared_ptr &loop, const ownership_id_t owner_id, - const curve::time_t &creation_time) : + const time::time_t &creation_time) : owner(loop, 0) { this->owner.set_last(creation_time, owner_id); } @@ -22,7 +22,7 @@ inline component_t Ownership::get_type() const { return component_t::OWNERSHIP; } -void Ownership::set_owner(const curve::time_t &time, const ownership_id_t owner_id) { +void Ownership::set_owner(const time::time_t &time, const ownership_id_t owner_id) { this->owner.set_last(time, owner_id); } diff --git a/libopenage/gamestate/component/internal/ownership.h b/libopenage/gamestate/component/internal/ownership.h index 2e671a97ca..b28448a557 100644 --- a/libopenage/gamestate/component/internal/ownership.h +++ b/libopenage/gamestate/component/internal/ownership.h @@ -2,10 +2,21 @@ #pragma once +#include +#include + #include "curve/discrete.h" #include "gamestate/component/internal_component.h" +#include "gamestate/component/types.h" +#include "time/time.h" + + +namespace openage { +namespace event { +class EventLoop; +} -namespace openage::gamestate::component { +namespace gamestate::component { using ownership_id_t = uint64_t; @@ -20,7 +31,7 @@ class Ownership : public InternalComponent { */ Ownership(const std::shared_ptr &loop, const ownership_id_t owner_id, - const curve::time_t &creation_time); + const time::time_t &creation_time); /** * Creates an Ownership component. @@ -37,7 +48,7 @@ class Ownership : public InternalComponent { * @param time Time at which the owner ID is set. * @param owner_id New owner ID. */ - void set_owner(const curve::time_t &time, const ownership_id_t owner_id); + void set_owner(const time::time_t &time, const ownership_id_t owner_id); /** * Get the owner IDs over time. @@ -53,4 +64,5 @@ class Ownership : public InternalComponent { curve::Discrete owner; }; -} // namespace openage::gamestate::component +} // namespace gamestate::component +} // namespace openage diff --git a/libopenage/gamestate/component/internal/position.cpp b/libopenage/gamestate/component/internal/position.cpp index 78a58552c2..61611382cf 100644 --- a/libopenage/gamestate/component/internal/position.cpp +++ b/libopenage/gamestate/component/internal/position.cpp @@ -4,12 +4,13 @@ #include "gamestate/component/types.h" #include "gamestate/definitions.h" +#include "util/fixed_point.h" namespace openage::gamestate::component { Position::Position(const std::shared_ptr &loop, const coord::phys3 &initial_pos, - const curve::time_t &creation_time) : + const time::time_t &creation_time) : position(loop, 0, "", nullptr, WORLD_ORIGIN), angle(loop, 0) { this->position.set_insert(creation_time, initial_pos); @@ -49,7 +50,7 @@ const curve::Continuous &Position::get_positions() const { return this->position; } -void Position::set_position(const curve::time_t &time, const coord::phys3 &pos) { +void Position::set_position(const time::time_t &time, const coord::phys3 &pos) { this->position.set_last(time, pos); } @@ -57,7 +58,7 @@ const curve::Segmented &Position::get_angles() const { return this->angle; } -void Position::set_angle(const curve::time_t &time, const coord::phys_angle_t &angle) { +void Position::set_angle(const time::time_t &time, const coord::phys_angle_t &angle) { auto old_angle = this->angle.get(time); this->angle.set_insert_jump(time, old_angle, angle); } diff --git a/libopenage/gamestate/component/internal/position.h b/libopenage/gamestate/component/internal/position.h index 1d2e6bde1a..af0502fbae 100644 --- a/libopenage/gamestate/component/internal/position.h +++ b/libopenage/gamestate/component/internal/position.h @@ -2,15 +2,23 @@ #pragma once +#include #include #include "coord/phys.h" #include "curve/continuous.h" #include "curve/segmented.h" #include "gamestate/component/internal_component.h" -#include "util/fixed_point.h" +#include "gamestate/component/types.h" +#include "time/time.h" -namespace openage::gamestate::component { + +namespace openage { +namespace event { +class EventLoop; +} + +namespace gamestate::component { class Position : public InternalComponent { public: @@ -23,7 +31,7 @@ class Position : public InternalComponent { */ Position(const std::shared_ptr &loop, const coord::phys3 &initial_pos, - const curve::time_t &creation_time); + const time::time_t &creation_time); /** * Create a Position component. @@ -49,7 +57,7 @@ class Position : public InternalComponent { * @param time Time at which the position is set. * @param pos New position. */ - void set_position(const curve::time_t &time, const coord::phys3 &pos); + void set_position(const time::time_t &time, const coord::phys3 &pos); /** * Get the directions in degrees over time. @@ -66,7 +74,7 @@ class Position : public InternalComponent { * @param time Time at which the angle is set. * @param angle New angle. */ - void set_angle(const curve::time_t &time, const coord::phys_angle_t &angle); + void set_angle(const time::time_t &time, const coord::phys_angle_t &angle); private: /** @@ -78,9 +86,12 @@ class Position : public InternalComponent { * Angle the entity is facing over time. * * Represents degrees in the range [0, 360). At angle 0, the entity is facing - * towards the camera. + * towards the camera (direction vector {x, y} = {-1, 1}). + * + * Rotation is clockwise, so at 90 degrees the entity is facing left. */ curve::Segmented angle; }; -} // namespace openage::gamestate::component +} // namespace gamestate::component +} // namespace openage diff --git a/libopenage/gamestate/entity_factory.cpp b/libopenage/gamestate/entity_factory.cpp index d0d57e2529..f6aa7f4fc9 100644 --- a/libopenage/gamestate/entity_factory.cpp +++ b/libopenage/gamestate/entity_factory.cpp @@ -2,7 +2,17 @@ #include "entity_factory.h" -#include "event/state.h" +#include +#include +#include +#include +#include + +#include "error/error.h" + +#include "curve/discrete.h" +#include "curve/queue.h" +#include "event/event_loop.h" #include "gamestate/activity/activity.h" #include "gamestate/activity/end_node.h" #include "gamestate/activity/event_node.h" @@ -17,10 +27,16 @@ #include "gamestate/component/internal/command_queue.h" #include "gamestate/component/internal/ownership.h" #include "gamestate/component/internal/position.h" +#include "gamestate/component/types.h" #include "gamestate/game_entity.h" #include "gamestate/game_state.h" #include "gamestate/manager.h" +#include "gamestate/system/types.h" +#include "log/message.h" #include "renderer/render_factory.h" +#include "time/time.h" +#include "util/fixed_point.h" + namespace openage::gamestate { @@ -49,11 +65,11 @@ namespace openage::gamestate { std::shared_ptr create_test_activity() { auto start = std::make_shared(0); auto idle = std::make_shared(1, "Idle"); - auto condition_moveable = std::make_shared(2); - auto wait_for_command = std::make_shared(3); - auto condition_command = std::make_shared(4); + auto condition_moveable = std::make_shared(2); + auto wait_for_command = std::make_shared(3); + auto condition_command = std::make_shared(4); auto move = std::make_shared(5, "Move"); - auto wait_for_move = std::make_shared(6); + auto wait_for_move = std::make_shared(6); auto end = std::make_shared(7); start->add_output(idle); @@ -63,7 +79,7 @@ std::shared_ptr create_test_activity() { condition_moveable->add_output(wait_for_command); condition_moveable->add_output(end); - condition_moveable->set_condition_func([&](const curve::time_t & /* time */, + condition_moveable->set_condition_func([&](const time::time_t & /* time */, const std::shared_ptr &entity) { if (entity->has_component(component::component_t::MOVE)) { return 3; // wait_for_command->get_id(); @@ -73,7 +89,7 @@ std::shared_ptr create_test_activity() { }); wait_for_command->add_output(move); - wait_for_command->set_primer_func([](const curve::time_t & /* time */, + wait_for_command->set_primer_func([](const time::time_t & /* time */, const std::shared_ptr &entity, const std::shared_ptr &loop, const std::shared_ptr &state) { @@ -81,7 +97,7 @@ std::shared_ptr create_test_activity() { entity->get_manager(), state, // event is not executed until a command is available - std::numeric_limits::max()); + std::numeric_limits::max()); auto entity_queue = std::dynamic_pointer_cast( entity->get_component(component::component_t::COMMANDQUEUE)); auto &queue = const_cast> &>(entity_queue->get_queue()); @@ -89,7 +105,7 @@ std::shared_ptr create_test_activity() { return activity::event_store_t{ev}; }); - wait_for_command->set_next_func([](const curve::time_t &time, + wait_for_command->set_next_func([](const time::time_t &time, const std::shared_ptr &entity, const std::shared_ptr &, const std::shared_ptr &) { @@ -114,7 +130,7 @@ std::shared_ptr create_test_activity() { wait_for_move->add_output(idle); wait_for_move->add_output(condition_command); wait_for_move->add_output(end); - wait_for_move->set_primer_func([](const curve::time_t &time, + wait_for_move->set_primer_func([](const time::time_t &time, const std::shared_ptr &entity, const std::shared_ptr &loop, const std::shared_ptr &state) { @@ -125,7 +141,7 @@ std::shared_ptr create_test_activity() { return activity::event_store_t{ev}; }); - wait_for_move->set_next_func([&](const curve::time_t &, + wait_for_move->set_next_func([&](const time::time_t &, const std::shared_ptr &, const std::shared_ptr &, const std::shared_ptr &) { @@ -206,7 +222,7 @@ void EntityFactory::init_components(const std::shared_ptradd_attribute(std::numeric_limits::min(), + live->add_attribute(std::numeric_limits::min(), attribute.get_name(), std::make_shared>(loop, 0, diff --git a/libopenage/gamestate/entity_factory.h b/libopenage/gamestate/entity_factory.h index 075f275603..3960a08e53 100644 --- a/libopenage/gamestate/entity_factory.h +++ b/libopenage/gamestate/entity_factory.h @@ -7,9 +7,9 @@ #include -#include "coord/phys.h" #include "gamestate/types.h" + namespace openage { namespace event { @@ -69,9 +69,9 @@ class EntityFactory { * @param nyan_entity fqon of the GameEntity data in the nyan database. */ void init_components(const std::shared_ptr &loop, - const std::shared_ptr &state, - const std::shared_ptr &entity, - const nyan::fqon_t &nyan_entity); + const std::shared_ptr &state, + const std::shared_ptr &entity, + const nyan::fqon_t &nyan_entity); /** * Get a unique ID for creating a game entity. diff --git a/libopenage/gamestate/event/process_command.cpp b/libopenage/gamestate/event/process_command.cpp index cbae35328f..4783fe89c8 100644 --- a/libopenage/gamestate/event/process_command.cpp +++ b/libopenage/gamestate/event/process_command.cpp @@ -18,15 +18,15 @@ void ProcessCommandHandler::setup_event(const std::shared_ptr &target, const std::shared_ptr & /* state */, - const curve::time_t &time, + const time::time_t &time, const param_map & /* params */) { auto mgr = std::dynamic_pointer_cast(target); mgr->run_activity_system(time); } -curve::time_t ProcessCommandHandler::predict_invoke_time(const std::shared_ptr & /* target */, +time::time_t ProcessCommandHandler::predict_invoke_time(const std::shared_ptr & /* target */, const std::shared_ptr & /* state */, - const curve::time_t &at) { + const time::time_t &at) { return at; } diff --git a/libopenage/gamestate/event/process_command.h b/libopenage/gamestate/event/process_command.h index 0e0914f1e5..8b940dd616 100644 --- a/libopenage/gamestate/event/process_command.h +++ b/libopenage/gamestate/event/process_command.h @@ -2,8 +2,11 @@ #pragma once -#include "event/evententity.h" +#include + #include "event/eventhandler.h" +#include "time/time.h" + namespace openage { @@ -30,12 +33,12 @@ class ProcessCommandHandler : public openage::event::OnceEventHandler { void invoke(openage::event::EventLoop &loop, const std::shared_ptr &target, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) override; - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &state, - const curve::time_t &at) override; + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &state, + const time::time_t &at) override; }; diff --git a/libopenage/gamestate/event/send_command.cpp b/libopenage/gamestate/event/send_command.cpp index 9325977504..8530d6340d 100644 --- a/libopenage/gamestate/event/send_command.cpp +++ b/libopenage/gamestate/event/send_command.cpp @@ -2,13 +2,29 @@ #include "send_command.h" +#include + +#include "coord/phys.h" #include "gamestate/component/internal/command_queue.h" #include "gamestate/component/internal/commands/idle.h" #include "gamestate/component/internal/commands/move.h" +#include "gamestate/component/types.h" #include "gamestate/game_entity.h" #include "gamestate/game_state.h" +#include "gamestate/types.h" + + +namespace openage::gamestate { +namespace component { +class CommandQueue; + +namespace command { +class IdleCommand; +class MoveCommand; +} // namespace command +} // namespace component -namespace openage::gamestate::event { +namespace event { Commander::Commander(const std::shared_ptr &loop) : openage::event::EventEntity{loop} { @@ -35,7 +51,7 @@ void SendCommandHandler::setup_event(const std::shared_ptr & /* target */, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) { auto gstate = std::dynamic_pointer_cast(state); @@ -64,10 +80,11 @@ void SendCommandHandler::invoke(openage::event::EventLoop & /* loop */, } } -curve::time_t SendCommandHandler::predict_invoke_time(const std::shared_ptr & /* target */, - const std::shared_ptr & /* state */, - const curve::time_t &at) { +time::time_t SendCommandHandler::predict_invoke_time(const std::shared_ptr & /* target */, + const std::shared_ptr & /* state */, + const time::time_t &at) { return at; } -} // namespace openage::gamestate::event +} // namespace event +} // namespace openage::gamestate diff --git a/libopenage/gamestate/event/send_command.h b/libopenage/gamestate/event/send_command.h index cb49a91cfb..75d59a8b05 100644 --- a/libopenage/gamestate/event/send_command.h +++ b/libopenage/gamestate/event/send_command.h @@ -2,15 +2,19 @@ #pragma once +#include +#include +#include + #include "event/evententity.h" #include "event/eventhandler.h" + namespace openage { namespace event { class EventLoop; class Event; -class EventEntity; class State; } // namespace event @@ -40,12 +44,12 @@ class SendCommandHandler : public openage::event::OnceEventHandler { void invoke(openage::event::EventLoop &loop, const std::shared_ptr &target, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) override; - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &state, - const curve::time_t &at) override; + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &state, + const time::time_t &at) override; }; } // namespace gamestate::event diff --git a/libopenage/gamestate/event/spawn_entity.cpp b/libopenage/gamestate/event/spawn_entity.cpp index c293e995e0..5389cf775c 100644 --- a/libopenage/gamestate/event/spawn_entity.cpp +++ b/libopenage/gamestate/event/spawn_entity.cpp @@ -2,16 +2,24 @@ #include "spawn_entity.h" +#include +#include +#include + +#include + #include "coord/phys.h" #include "gamestate/component/internal/activity.h" #include "gamestate/component/internal/command_queue.h" #include "gamestate/component/internal/ownership.h" #include "gamestate/component/internal/position.h" +#include "gamestate/component/types.h" #include "gamestate/definitions.h" #include "gamestate/entity_factory.h" #include "gamestate/game_entity.h" #include "gamestate/game_state.h" #include "gamestate/manager.h" +#include "gamestate/types.h" // TODO: Testing #include "assets/mod_manager.h" @@ -68,7 +76,7 @@ void SpawnEntityHandler::setup_event(const std::shared_ptr & /* target */, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) { auto gstate = std::dynamic_pointer_cast(state); @@ -134,9 +142,9 @@ void SpawnEntityHandler::invoke(openage::event::EventLoop & /* loop */, gstate->add_game_entity(entity); } -curve::time_t SpawnEntityHandler::predict_invoke_time(const std::shared_ptr & /* target */, - const std::shared_ptr & /* state */, - const curve::time_t &at) { +time::time_t SpawnEntityHandler::predict_invoke_time(const std::shared_ptr & /* target */, + const std::shared_ptr & /* state */, + const time::time_t &at) { return at; } diff --git a/libopenage/gamestate/event/spawn_entity.h b/libopenage/gamestate/event/spawn_entity.h index 617e2ace1b..12f99378b3 100644 --- a/libopenage/gamestate/event/spawn_entity.h +++ b/libopenage/gamestate/event/spawn_entity.h @@ -2,15 +2,20 @@ #pragma once +#include +#include +#include + #include "event/evententity.h" #include "event/eventhandler.h" +#include "time/time.h" + namespace openage { namespace event { class EventLoop; class Event; -class EventEntity; class State; } // namespace event @@ -62,7 +67,7 @@ class SpawnEntityHandler : public openage::event::OnceEventHandler { void invoke(openage::event::EventLoop &loop, const std::shared_ptr &target, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) override; /** @@ -81,9 +86,9 @@ class SpawnEntityHandler : public openage::event::OnceEventHandler { * then dependencies may not be resolved perfectly anymore * (if other events have already been calculated before that). */ - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &state, - const curve::time_t &at) override; + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &state, + const time::time_t &at) override; private: /** diff --git a/libopenage/gamestate/event/wait.cpp b/libopenage/gamestate/event/wait.cpp index 8c8894644b..2d067086fa 100644 --- a/libopenage/gamestate/event/wait.cpp +++ b/libopenage/gamestate/event/wait.cpp @@ -18,15 +18,15 @@ void WaitHandler::setup_event(const std::shared_ptr & /* void WaitHandler::invoke(openage::event::EventLoop & /* loop */, const std::shared_ptr &target, const std::shared_ptr & /* state */, - const curve::time_t &time, + const time::time_t &time, const param_map & /* params */) { auto mgr = std::dynamic_pointer_cast(target); mgr->run_activity_system(time); } -curve::time_t WaitHandler::predict_invoke_time(const std::shared_ptr & /* target */, +time::time_t WaitHandler::predict_invoke_time(const std::shared_ptr & /* target */, const std::shared_ptr & /* state */, - const curve::time_t &at) { + const time::time_t &at) { return at; } diff --git a/libopenage/gamestate/event/wait.h b/libopenage/gamestate/event/wait.h index 221b73adaf..2c0d9732f2 100644 --- a/libopenage/gamestate/event/wait.h +++ b/libopenage/gamestate/event/wait.h @@ -2,8 +2,11 @@ #pragma once -#include "event/evententity.h" +#include + #include "event/eventhandler.h" +#include "time/time.h" + namespace openage { @@ -30,12 +33,12 @@ class WaitHandler : public openage::event::OnceEventHandler { void invoke(openage::event::EventLoop &loop, const std::shared_ptr &target, const std::shared_ptr &state, - const curve::time_t &time, + const time::time_t &time, const param_map ¶ms) override; - curve::time_t predict_invoke_time(const std::shared_ptr &target, - const std::shared_ptr &state, - const curve::time_t &at) override; + time::time_t predict_invoke_time(const std::shared_ptr &target, + const std::shared_ptr &state, + const time::time_t &at) override; }; } // namespace gamestate::event } // namespace openage diff --git a/libopenage/gamestate/game.cpp b/libopenage/gamestate/game.cpp index 957f2767e8..b496ae7e1e 100644 --- a/libopenage/gamestate/game.cpp +++ b/libopenage/gamestate/game.cpp @@ -2,13 +2,20 @@ #include "game.h" -#include -#include +#include + +#include + +#include "log/log.h" +#include "log/message.h" #include "assets/mod_manager.h" -#include "event/time_loop.h" +#include "assets/modpack.h" #include "gamestate/game_state.h" #include "gamestate/universe.h" +#include "util/path.h" +#include "util/strings.h" + namespace openage::gamestate { diff --git a/libopenage/gamestate/game.h b/libopenage/gamestate/game.h index b5849e8c8d..9c9eb1def4 100644 --- a/libopenage/gamestate/game.h +++ b/libopenage/gamestate/game.h @@ -3,8 +3,7 @@ #pragma once #include - -#include "util/path.h" +#include namespace nyan { class Database; @@ -24,6 +23,10 @@ namespace renderer { class RenderFactory; } +namespace util { +class Path; +} + namespace gamestate { class GameState; class Universe; diff --git a/libopenage/gamestate/game_entity.cpp b/libopenage/gamestate/game_entity.cpp index 3ece4f3644..e8b7a9e086 100644 --- a/libopenage/gamestate/game_entity.cpp +++ b/libopenage/gamestate/game_entity.cpp @@ -56,7 +56,7 @@ bool GameEntity::has_component(component::component_t type) { return this->components.contains(type); } -void GameEntity::render_update(const curve::time_t &time, +void GameEntity::render_update(const time::time_t &time, const std::string &animation_path) { if (this->render_entity != nullptr) { const auto &pos = dynamic_pointer_cast( diff --git a/libopenage/gamestate/game_entity.h b/libopenage/gamestate/game_entity.h index a28011d235..a79f167e7f 100644 --- a/libopenage/gamestate/game_entity.h +++ b/libopenage/gamestate/game_entity.h @@ -3,12 +3,13 @@ #pragma once #include +#include #include -#include "coord/phys.h" -#include "curve/curve.h" #include "gamestate/component/types.h" #include "gamestate/types.h" +#include "time/time.h" + namespace openage { @@ -104,7 +105,7 @@ class GameEntity { * @param time Simulation time of the update. * @param animation_path Animation path used at \p time. */ - void render_update(const curve::time_t &time, + void render_update(const time::time_t &time, const std::string &animation_path); protected: diff --git a/libopenage/gamestate/game_state.cpp b/libopenage/gamestate/game_state.cpp index b39c8c7ab3..759b638840 100644 --- a/libopenage/gamestate/game_state.cpp +++ b/libopenage/gamestate/game_state.cpp @@ -2,10 +2,14 @@ #include "game_state.h" -#include +#include + +#include "error/error.h" +#include "log/log.h" #include "gamestate/game_entity.h" + namespace openage::gamestate { GameState::GameState(const std::shared_ptr &db, diff --git a/libopenage/gamestate/game_state.h b/libopenage/gamestate/game_state.h index 8ea365a9e3..c091303548 100644 --- a/libopenage/gamestate/game_state.h +++ b/libopenage/gamestate/game_state.h @@ -2,11 +2,13 @@ #pragma once +#include #include #include "event/state.h" #include "gamestate/types.h" + namespace nyan { class Database; class View; @@ -18,6 +20,10 @@ namespace assets { class ModManager; } +namespace event { +class EventLoop; +} + namespace gamestate { class GameEntity; diff --git a/libopenage/gamestate/manager.cpp b/libopenage/gamestate/manager.cpp index 9952beccc5..9c8f6c1899 100644 --- a/libopenage/gamestate/manager.cpp +++ b/libopenage/gamestate/manager.cpp @@ -3,9 +3,9 @@ #include "manager.h" #include "log/log.h" +#include "log/message.h" #include "gamestate/component/internal/command_queue.h" -#include "gamestate/component/types.h" #include "gamestate/game_entity.h" #include "gamestate/system/activity.h" @@ -20,7 +20,7 @@ GameEntityManager::GameEntityManager(const std::shared_ptrgame_entity->get_id()); system::Activity::advance(this->game_entity, time, this->loop, this->state); } diff --git a/libopenage/gamestate/manager.h b/libopenage/gamestate/manager.h index c36d2958b4..6131c94bd2 100644 --- a/libopenage/gamestate/manager.h +++ b/libopenage/gamestate/manager.h @@ -2,12 +2,20 @@ #pragma once +#include #include +#include #include "event/evententity.h" +#include "time/time.h" -namespace openage::gamestate { +namespace openage { +namespace event { +class EventLoop; +} // namespace event + +namespace gamestate { class GameState; class GameEntity; @@ -18,7 +26,7 @@ class GameEntityManager : public openage::event::EventEntity { const std::shared_ptr &game_entity); ~GameEntityManager() = default; - void run_activity_system(const curve::time_t &time); + void run_activity_system(const time::time_t &time); size_t id() const override; std::string idstr() const override; @@ -31,4 +39,5 @@ class GameEntityManager : public openage::event::EventEntity { std::shared_ptr game_entity; }; -} // namespace openage::gamestate +} // namespace gamestate +} // namespace openage diff --git a/libopenage/gamestate/simulation.cpp b/libopenage/gamestate/simulation.cpp index 7de933255a..1c045548bc 100644 --- a/libopenage/gamestate/simulation.cpp +++ b/libopenage/gamestate/simulation.cpp @@ -2,16 +2,15 @@ #include "simulation.h" -#include "event/clock.h" -#include "event/event_loop.h" -#include "event/time_loop.h" - #include "assets/mod_manager.h" +#include "event/event_loop.h" #include "gamestate/entity_factory.h" #include "gamestate/event/process_command.h" #include "gamestate/event/send_command.h" #include "gamestate/event/spawn_entity.h" #include "gamestate/event/wait.h" +#include "time/clock.h" +#include "time/time_loop.h" // TODO #include "gamestate/game.h" @@ -21,7 +20,7 @@ namespace openage::gamestate { GameSimulation::GameSimulation(const util::Path &root_dir, const std::shared_ptr &cvar_manager, - const std::shared_ptr time_loop) : + const std::shared_ptr time_loop) : running{false}, root_dir{root_dir}, cvar_manager{cvar_manager}, diff --git a/libopenage/gamestate/simulation.h b/libopenage/gamestate/simulation.h index f2a922aa84..aab81c524e 100644 --- a/libopenage/gamestate/simulation.h +++ b/libopenage/gamestate/simulation.h @@ -18,13 +18,16 @@ class CVarManager; namespace event { class EventLoop; -class TimeLoop; } // namespace event namespace renderer { class RenderFactory; } +namespace time { +class TimeLoop; +} // namespace time + namespace gamestate { class EntityFactory; class Game; @@ -50,7 +53,7 @@ class GameSimulation final { */ GameSimulation(const util::Path &root_dir, const std::shared_ptr &cvar_manager, - const std::shared_ptr time_loop); + const std::shared_ptr time_loop); // game simulation should not be copied or moved GameSimulation(const GameSimulation ©) = delete; @@ -163,7 +166,7 @@ class GameSimulation final { /** * Time loop for getting the current simulation time and changing speed. */ - std::shared_ptr time_loop; + std::shared_ptr time_loop; /** * Event loop for processing events in the game. diff --git a/libopenage/gamestate/system/activity.cpp b/libopenage/gamestate/system/activity.cpp index cd6f0eccc3..240b5c7c50 100644 --- a/libopenage/gamestate/system/activity.cpp +++ b/libopenage/gamestate/system/activity.cpp @@ -2,26 +2,33 @@ #include "activity.h" -#include "log/log.h" +#include +#include +#include + +#include "error/error.h" +#include "log/message.h" -#include "gamestate/activity/activity.h" #include "gamestate/activity/event_node.h" +#include "gamestate/activity/node.h" #include "gamestate/activity/start_node.h" #include "gamestate/activity/task_node.h" #include "gamestate/activity/task_system_node.h" +#include "gamestate/activity/types.h" #include "gamestate/activity/xor_node.h" #include "gamestate/component/internal/activity.h" +#include "gamestate/component/types.h" #include "gamestate/game_entity.h" - #include "gamestate/system/idle.h" #include "gamestate/system/move.h" +#include "util/fixed_point.h" namespace openage::gamestate::system { void Activity::advance(const std::shared_ptr &entity, - const curve::time_t &start_time, + const time::time_t &start_time, const std::shared_ptr &loop, const std::shared_ptr &state) { auto activity_component = std::dynamic_pointer_cast( @@ -34,10 +41,10 @@ void Activity::advance(const std::shared_ptr &entity, } // TODO: this check should be moved to a more general pre-processing section - if (current_node->get_type() == activity::node_t::EVENT_GATEWAY) { + if (current_node->get_type() == activity::node_t::XOR_EVENT_GATE) { // returning to a event gateway means that the event has been triggered // move to the next node here - auto node = std::static_pointer_cast(current_node); + auto node = std::static_pointer_cast(current_node); auto event_next = node->get_next_func(); auto next_id = event_next(start_time, entity, loop, state); current_node = node->next(next_id); @@ -46,7 +53,7 @@ void Activity::advance(const std::shared_ptr &entity, activity_component->cancel_events(start_time); } - curve::time_t event_wait_time = 0; + time::time_t event_wait_time = 0; auto stop = false; while (not stop) { switch (current_node->get_type()) { @@ -59,8 +66,8 @@ void Activity::advance(const std::shared_ptr &entity, // TODO: if activities are nested, advance to parent activity stop = true; } break; - case activity::node_t::TASK: { - auto node = std::static_pointer_cast(current_node); + case activity::node_t::TASK_CUSTOM: { + auto node = std::static_pointer_cast(current_node); auto task = node->get_task_func(); task(start_time, entity); auto next_id = node->get_next(); @@ -73,14 +80,14 @@ void Activity::advance(const std::shared_ptr &entity, auto next_id = node->get_next(); current_node = node->next(next_id); } break; - case activity::node_t::XOR_GATEWAY: { - auto node = std::static_pointer_cast(current_node); + case activity::node_t::XOR_GATE: { + auto node = std::static_pointer_cast(current_node); auto condition = node->get_condition_func(); auto next_id = condition(start_time, entity); current_node = node->next(next_id); } break; - case activity::node_t::EVENT_GATEWAY: { - auto node = std::static_pointer_cast(current_node); + case activity::node_t::XOR_EVENT_GATE: { + auto node = std::static_pointer_cast(current_node); auto event_primer = node->get_primer_func(); auto evs = event_primer(start_time + event_wait_time, entity, loop, state); for (auto &ev : evs) { @@ -100,9 +107,9 @@ void Activity::advance(const std::shared_ptr &entity, activity_component->set_node(start_time, current_node); } -const curve::time_t Activity::handle_subsystem(const std::shared_ptr &entity, - const curve::time_t &start_time, - system_id_t system_id) { +const time::time_t Activity::handle_subsystem(const std::shared_ptr &entity, + const time::time_t &start_time, + system_id_t system_id) { switch (system_id) { case system_id_t::IDLE: return Idle::idle(entity, start_time); @@ -117,7 +124,7 @@ const curve::time_t Activity::handle_subsystem(const std::shared_ptr(system_id)}; } - return curve::time_t::from_int(0); + return time::time_t::from_int(0); } diff --git a/libopenage/gamestate/system/activity.h b/libopenage/gamestate/system/activity.h index 16696bbed6..d5283fceca 100644 --- a/libopenage/gamestate/system/activity.h +++ b/libopenage/gamestate/system/activity.h @@ -4,7 +4,7 @@ #include -#include "curve/curve.h" +#include "time/time.h" #include "gamestate/system/types.h" @@ -29,7 +29,7 @@ class Activity { * @param start_time Start time of change. */ static void advance(const std::shared_ptr &entity, - const curve::time_t &start_time, + const time::time_t &start_time, const std::shared_ptr &loop, const std::shared_ptr &state); @@ -43,8 +43,8 @@ class Activity { * * @return Runtime of the change in simulation time. */ - static const curve::time_t handle_subsystem(const std::shared_ptr &entity, - const curve::time_t &start_time, + static const time::time_t handle_subsystem(const std::shared_ptr &entity, + const time::time_t &start_time, system_id_t system_id); }; diff --git a/libopenage/gamestate/system/idle.cpp b/libopenage/gamestate/system/idle.cpp index a7bc126953..3db9f5cb5f 100644 --- a/libopenage/gamestate/system/idle.cpp +++ b/libopenage/gamestate/system/idle.cpp @@ -2,19 +2,25 @@ #include "idle.h" +#include + +#include "error/error.h" #include "log/log.h" +#include "log/message.h" #include "gamestate/api/ability.h" #include "gamestate/api/animation.h" #include "gamestate/api/property.h" +#include "gamestate/api/types.h" #include "gamestate/component/api/idle.h" +#include "gamestate/component/types.h" #include "gamestate/game_entity.h" namespace openage::gamestate::system { -const curve::time_t Idle::idle(const std::shared_ptr &entity, - const curve::time_t &start_time) { +const time::time_t Idle::idle(const std::shared_ptr &entity, + const time::time_t &start_time) { if (not entity->has_component(component::component_t::IDLE)) [[unlikely]] { throw Error{ERR << "Entity " << entity->get_id() << " has no idle component."}; } @@ -34,7 +40,7 @@ const curve::time_t Idle::idle(const std::shared_ptr &ent // TODO: play sound - return curve::time_t::from_int(0); + return time::time_t::from_int(0); } } // namespace openage::gamestate::system diff --git a/libopenage/gamestate/system/idle.h b/libopenage/gamestate/system/idle.h index b1eaca3c53..8a9a6e6a9a 100644 --- a/libopenage/gamestate/system/idle.h +++ b/libopenage/gamestate/system/idle.h @@ -4,7 +4,7 @@ #include -#include "curve/curve.h" +#include "time/time.h" namespace openage::gamestate { @@ -25,8 +25,8 @@ class Idle { * * @return Runtime of the change in simulation time. */ - static const curve::time_t idle(const std::shared_ptr &entity, - const curve::time_t &start_time); + static const time::time_t idle(const std::shared_ptr &entity, + const time::time_t &start_time); }; } // namespace system diff --git a/libopenage/gamestate/system/move.cpp b/libopenage/gamestate/system/move.cpp index 6fab22daf1..3ebd02085b 100644 --- a/libopenage/gamestate/system/move.cpp +++ b/libopenage/gamestate/system/move.cpp @@ -2,22 +2,34 @@ #include "move.h" +#include +#include + +#include + #include "log/log.h" +#include "log/message.h" +#include "coord/phys.h" +#include "curve/continuous.h" +#include "curve/segmented.h" #include "gamestate/api/ability.h" #include "gamestate/api/animation.h" #include "gamestate/api/property.h" +#include "gamestate/api/types.h" #include "gamestate/component/api/move.h" #include "gamestate/component/api/turn.h" #include "gamestate/component/internal/command_queue.h" #include "gamestate/component/internal/commands/move.h" #include "gamestate/component/internal/position.h" +#include "gamestate/component/types.h" #include "gamestate/game_entity.h" +#include "util/fixed_point.h" namespace openage::gamestate::system { -const curve::time_t Move::move_command(const std::shared_ptr &entity, - const curve::time_t &start_time) { +const time::time_t Move::move_command(const std::shared_ptr &entity, + const time::time_t &start_time) { auto command_queue = std::dynamic_pointer_cast( entity->get_component(component::component_t::COMMANDQUEUE)); auto command = std::dynamic_pointer_cast( @@ -25,19 +37,19 @@ const curve::time_t Move::move_command(const std::shared_ptrget_target(), start_time); } -const curve::time_t Move::move_default(const std::shared_ptr &entity, - const coord::phys3 &destination, - const curve::time_t &start_time) { +const time::time_t Move::move_default(const std::shared_ptr &entity, + const coord::phys3 &destination, + const time::time_t &start_time) { if (not entity->has_component(component::component_t::MOVE)) [[unlikely]] { log::log(WARN << "Entity " << entity->get_id() << " has no move component."); - return curve::time_t::from_int(0); + return time::time_t::from_int(0); } auto turn_component = std::dynamic_pointer_cast( diff --git a/libopenage/gamestate/system/move.h b/libopenage/gamestate/system/move.h index 6bf63cb1ff..11d6a6fa5f 100644 --- a/libopenage/gamestate/system/move.h +++ b/libopenage/gamestate/system/move.h @@ -5,7 +5,7 @@ #include #include "coord/phys.h" -#include "curve/curve.h" +#include "time/time.h" namespace openage::gamestate { @@ -23,8 +23,8 @@ class Move { * * @return Runtime of the change in simulation time. */ - static const curve::time_t move_command(const std::shared_ptr &entity, - const curve::time_t &start_time); + static const time::time_t move_command(const std::shared_ptr &entity, + const time::time_t &start_time); /** * Move a game entity to a destination. @@ -35,9 +35,9 @@ class Move { * * @return Runtime of the change in simulation time. */ - static const curve::time_t move_default(const std::shared_ptr &entity, + static const time::time_t move_default(const std::shared_ptr &entity, const coord::phys3 &destination, - const curve::time_t &start_time); + const time::time_t &start_time); }; } // namespace system diff --git a/libopenage/gamestate/terrain.cpp b/libopenage/gamestate/terrain.cpp index 2564347eef..247b457251 100644 --- a/libopenage/gamestate/terrain.cpp +++ b/libopenage/gamestate/terrain.cpp @@ -2,6 +2,10 @@ #include "terrain.h" +#include +#include +#include + #include "renderer/stages/terrain/terrain_render_entity.h" namespace openage::gamestate { diff --git a/libopenage/gamestate/terrain.h b/libopenage/gamestate/terrain.h index 690ea3bd03..1e1aef9846 100644 --- a/libopenage/gamestate/terrain.h +++ b/libopenage/gamestate/terrain.h @@ -3,7 +3,7 @@ #pragma once #include -#include +#include #include #include "util/vector.h" diff --git a/libopenage/gamestate/world.cpp b/libopenage/gamestate/world.cpp index 85785e0a67..d47ce1ce0b 100644 --- a/libopenage/gamestate/world.cpp +++ b/libopenage/gamestate/world.cpp @@ -2,9 +2,8 @@ #include "world.h" -#include "log/log.h" - -#include +#include +#include #include "gamestate/game_entity.h" #include "gamestate/game_state.h" diff --git a/libopenage/gamestate/world.h b/libopenage/gamestate/world.h index 2ba27cfd02..2fd825143b 100644 --- a/libopenage/gamestate/world.h +++ b/libopenage/gamestate/world.h @@ -2,7 +2,8 @@ #pragma once -#include "util/path.h" +#include + namespace openage { @@ -11,7 +12,6 @@ class RenderFactory; } namespace gamestate { -class GameEntity; class GameState; /** diff --git a/libopenage/gui/guisys/private/gui_renderer_impl.h b/libopenage/gui/guisys/private/gui_renderer_impl.h index 8e6f6a17fb..31c1330eea 100644 --- a/libopenage/gui/guisys/private/gui_renderer_impl.h +++ b/libopenage/gui/guisys/private/gui_renderer_impl.h @@ -3,6 +3,10 @@ #pragma once #ifndef __APPLE__ +#ifdef _MSC_VER +#define NOMINMAX +#include +#endif //_MSC_VER #include #else // __APPLE__ #include diff --git a/libopenage/gui/integration/private/gui_log.cpp b/libopenage/gui/integration/private/gui_log.cpp index d4387b1147..481374f9de 100644 --- a/libopenage/gui/integration/private/gui_log.cpp +++ b/libopenage/gui/integration/private/gui_log.cpp @@ -1,10 +1,12 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "../../integration/private/gui_log.h" #include #include "../../../log/log.h" +#include "log/message.h" + namespace openage { namespace gui { @@ -36,9 +38,8 @@ void gui_log(QtMsgType type, const QMessageLogContext &context, const QString &m log::MessageBuilder builder{ context.file != nullptr ? context.file : "", static_cast(context.line), - context.function != nullptr ? context.function : "", - msg_lvl - }; + context.function != nullptr ? context.function : "", + msg_lvl}; // TODO: maybe it's not UTF-8 // TODO: Qt should become a LogSource @@ -48,4 +49,5 @@ void gui_log(QtMsgType type, const QMessageLogContext &context, const QString &m abort(); } -}} // namespace openage::gui +} // namespace gui +} // namespace openage diff --git a/libopenage/input/controller/game/controller.cpp b/libopenage/input/controller/game/controller.cpp index 29220d4430..d12f7e1135 100644 --- a/libopenage/input/controller/game/controller.cpp +++ b/libopenage/input/controller/game/controller.cpp @@ -2,10 +2,9 @@ #include "controller.h" -#include "event/clock.h" +#include "event/event_loop.h" #include "event/evententity.h" #include "event/state.h" -#include "event/time_loop.h" #include "gamestate/component/internal/commands/types.h" #include "gamestate/event/send_command.h" #include "gamestate/event/spawn_entity.h" @@ -13,6 +12,8 @@ #include "gamestate/game_state.h" #include "gamestate/simulation.h" #include "input/controller/game/binding_context.h" +#include "time/clock.h" +#include "time/time_loop.h" #include "coord/phys.h" @@ -85,7 +86,7 @@ bool Controller::process(const event_arguments &ev_args, const std::shared_ptr &ctx, - const std::shared_ptr &time_loop, + const std::shared_ptr &time_loop, const std::shared_ptr &simulation, const std::shared_ptr &camera) { binding_func_t create_entity_event{[&](const event_arguments &args, diff --git a/libopenage/input/controller/game/controller.h b/libopenage/input/controller/game/controller.h index 9c3f50700f..2ef4439087 100644 --- a/libopenage/input/controller/game/controller.h +++ b/libopenage/input/controller/game/controller.h @@ -11,14 +11,14 @@ namespace openage { -namespace event { -class TimeLoop; -} - namespace gamestate { class GameSimulation; } +namespace time { +class TimeLoop; +} + namespace input::game { class BindingContext; @@ -116,7 +116,7 @@ class Controller { * @param camera Active game camera. */ void setup_defaults(const std::shared_ptr &ctx, - const std::shared_ptr &time_loop, + const std::shared_ptr &time_loop, const std::shared_ptr &simulation, const std::shared_ptr &camera); diff --git a/libopenage/log/file_logsink.cpp b/libopenage/log/file_logsink.cpp index 340d50f7f0..53e309f9be 100644 --- a/libopenage/log/file_logsink.cpp +++ b/libopenage/log/file_logsink.cpp @@ -1,18 +1,19 @@ -// Copyright 2015-2020 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "file_logsink.h" -#include #include +#include -#include "message.h" -#include "logsource.h" +#include "log/level.h" +#include "log/logsource.h" +#include "log/message.h" +#include "util/enum.h" namespace openage::log { -FileSink::FileSink(const char *filename, bool append) - : +FileSink::FileSink(const char *filename, bool append) : outfile{filename, std::ios_base::out | (append ? std::ios_base::app : std::ios_base::trunc)} {} diff --git a/libopenage/log/file_logsink.h b/libopenage/log/file_logsink.h index a4cdd4c4d8..ab651d57e6 100644 --- a/libopenage/log/file_logsink.h +++ b/libopenage/log/file_logsink.h @@ -1,14 +1,15 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once -#include #include #include "logsink.h" namespace openage { namespace log { +class LogSource; +struct message; class FileSink : public LogSink { public: @@ -20,4 +21,5 @@ class FileSink : public LogSink { std::ofstream outfile; }; -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/level.h b/libopenage/log/level.h index 817311083c..ef7322ec63 100644 --- a/libopenage/log/level.h +++ b/libopenage/log/level.h @@ -1,8 +1,9 @@ -// Copyright 2015-2019 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once // pxd: from libopenage.util.enum cimport Enum, EnumValue +#include "../util/compiler.h" #include "../util/enum.h" @@ -48,26 +49,27 @@ struct OAAPI level : util::Enum { // initializes the level to an internal UNDEFINED value. level(); - #ifdef __MINGW32__ - // Do not try to optimize these out even if it seems they are not used. - // Namely MIN that is not used within the library. - #define NOOPTIMIZE __attribute__((__used__)) - #else - #define NOOPTIMIZE - #endif // _win32 +#ifdef __MINGW32__ +// Do not try to optimize these out even if it seems they are not used. +// Namely MIN that is not used within the library. +#define NOOPTIMIZE __attribute__((__used__)) +#else +#define NOOPTIMIZE +#endif // _win32 - static constexpr level_value MIN NOOPTIMIZE {{"min loglevel", -1000}, "5"}; + static constexpr level_value MIN NOOPTIMIZE{{"min loglevel", -1000}, "5"}; - static constexpr level_value spam NOOPTIMIZE {{"SPAM", -100}, ""}; - static constexpr level_value dbg NOOPTIMIZE {{"DBG", -20}, ""}; - static constexpr level_value info NOOPTIMIZE {{"INFO", 0}, ""}; - static constexpr level_value warn NOOPTIMIZE {{"WARN", 100}, "33"}; - static constexpr level_value err NOOPTIMIZE {{"ERR", 200}, "31;1"}; - static constexpr level_value crit NOOPTIMIZE {{"CRIT", 500}, "31;1;47"}; + static constexpr level_value spam NOOPTIMIZE{{"SPAM", -100}, ""}; + static constexpr level_value dbg NOOPTIMIZE{{"DBG", -20}, ""}; + static constexpr level_value info NOOPTIMIZE{{"INFO", 0}, ""}; + static constexpr level_value warn NOOPTIMIZE{{"WARN", 100}, "33"}; + static constexpr level_value err NOOPTIMIZE{{"ERR", 200}, "31;1"}; + static constexpr level_value crit NOOPTIMIZE{{"CRIT", 500}, "31;1;47"}; - static constexpr level_value MAX NOOPTIMIZE {{"max loglevel", 1000}, "5"}; + static constexpr level_value MAX NOOPTIMIZE{{"max loglevel", 1000}, "5"}; - #undef NOOPTIMIZE +#undef NOOPTIMIZE }; -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/log.cpp b/libopenage/log/log.cpp index 49d610bba3..fa2300d1e3 100644 --- a/libopenage/log/log.cpp +++ b/libopenage/log/log.cpp @@ -1,10 +1,10 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "log.h" -#include "message.h" -#include "named_logsource.h" -#include "stdout_logsink.h" +#include "log/named_logsource.h" +#include "log/stdout_logsink.h" + namespace openage { namespace log { @@ -20,4 +20,5 @@ void set_level(level lvl) { } -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/log.h b/libopenage/log/log.h index 936a7735ab..4fe103d420 100644 --- a/libopenage/log/log.h +++ b/libopenage/log/log.h @@ -1,10 +1,12 @@ -// Copyright 2015-2017 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once // pxd: from libopenage.log.level cimport level -#include "level.h" -#include "message.h" +#include "../util/compiler.h" +#include "./level.h" +#include "./message.h" + namespace openage { namespace log { @@ -27,4 +29,5 @@ void log(const message &msg); OAAPI void set_level(level lvl); -}} // openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/logsink.h b/libopenage/log/logsink.h index 3fef9b4a5f..6edfa7890c 100644 --- a/libopenage/log/logsink.h +++ b/libopenage/log/logsink.h @@ -1,14 +1,16 @@ -// Copyright 2015-2020 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once #include #include -#include "level.h" +#include "../util/compiler.h" +#include "./level.h" -namespace openage::log { +namespace openage::log { +struct message; /** * Abstract base for classes that - in one way or an other - print log messages. @@ -51,9 +53,9 @@ class OAAPI LogSinkList { public: static LogSinkList &instance(); - LogSinkList(LogSinkList const&) = delete; + LogSinkList(LogSinkList const &) = delete; - void operator=(LogSinkList const&) = delete; + void operator=(LogSinkList const &) = delete; void log(const message &msg, class LogSource *source) const; @@ -68,7 +70,7 @@ class OAAPI LogSinkList { private: LogSinkList(); - std::list sinks; + std::list sinks; mutable std::mutex sinks_mutex; diff --git a/libopenage/log/logsource.cpp b/libopenage/log/logsource.cpp index 4c7c9d90d8..e2491e89cd 100644 --- a/libopenage/log/logsource.cpp +++ b/libopenage/log/logsource.cpp @@ -1,18 +1,20 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "logsource.h" -#include "../util/compiler.h" +#include +#include + +#include "log/logsink.h" +#include "log/stdout_logsink.h" +#include "util/compiler.h" -#include "logsink.h" -#include "stdout_logsink.h" namespace openage { namespace log { -LogSource::LogSource() - : +LogSource::LogSource() : logger_id{LogSource::get_unique_logger_id()} {} @@ -33,4 +35,5 @@ size_t LogSource::get_unique_logger_id() { } -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/logsource.h b/libopenage/log/logsource.h index 21d793bdd0..fa0268ddf5 100644 --- a/libopenage/log/logsource.h +++ b/libopenage/log/logsource.h @@ -1,17 +1,21 @@ -// Copyright 2015-2017 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once +#include + // pxd: from libcpp.string cimport string #include // pxd: from libopenage.log.message cimport message #include "message.h" +#include "../util/compiler.h" + namespace openage { namespace log { - +struct message; /** * Any class that wants to provide .log() shall inherit from this. @@ -52,4 +56,5 @@ class OAAPI LogSource { }; -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/message.cpp b/libopenage/log/message.cpp index fd7e8616cb..f3be4c4068 100644 --- a/libopenage/log/message.cpp +++ b/libopenage/log/message.cpp @@ -1,14 +1,19 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "message.h" +#include #include +#include #include +#include + +#include "log/level.h" +#include "util/enum.h" +#include "util/stringformatter.h" +#include "util/thread_id.h" +#include "util/timing.h" -#include "../util/timing.h" -#include "../util/compiler.h" -#include "../util/thread_id.h" -#include "../util/strings.h" namespace openage { namespace log { @@ -35,20 +40,18 @@ void message::init_with_metadata_copy(const std::string &filename, const std::st MessageBuilder::MessageBuilder(const char *filename, unsigned lineno, const char *functionname, - level lvl) - : + level lvl) : StringFormatter{msg.text} { + this->msg.filename = filename; + this->msg.lineno = lineno; + this->msg.functionname = functionname; + this->msg.lvl = lvl; - this->msg.filename = filename; - this->msg.lineno = lineno; - this->msg.functionname = functionname; - this->msg.lvl = lvl; - - this->msg.init(); - } + this->msg.init(); +} -std::ostream &operator <<(std::ostream &os, const message &msg) { +std::ostream &operator<<(std::ostream &os, const message &msg) { os << "\x1b[" << msg.lvl->colorcode << "m" << std::setw(4) << msg.lvl->name << "\x1b[m "; os << msg.filename << ":" << msg.lineno << " "; os << "(" << msg.functionname; @@ -59,4 +62,5 @@ std::ostream &operator <<(std::ostream &os, const message &msg) { } -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/message.h b/libopenage/log/message.h index 194320355a..09b888a9ac 100644 --- a/libopenage/log/message.h +++ b/libopenage/log/message.h @@ -1,20 +1,25 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once +#include +#include + // pxd: from libc.stdint cimport int64_t #include // pxd: from libcpp.string cimport string #include -#include "config.h" +#include "../util/compiler.h" #include "../util/constexpr.h" #include "../util/stringformatter.h" +#include "config.h" #include "logsink.h" // pxd: from libopenage.log.level cimport level #include "level.h" + #if defined(__GNUC__) #define OPENAGE_FUNC_NAME __PRETTY_FUNCTION__ #elif defined(_MSC_VER) @@ -27,7 +32,9 @@ namespace openage { // forward-declaration for use in 'friend' declaration below. -namespace error { class Error; } +namespace error { +class Error; +} namespace log { @@ -107,7 +114,7 @@ struct OAAPI message { /** * prints message to a stream (with color codes and everything!) */ -std::ostream &operator <<(std::ostream &os, const message &msg); +std::ostream &operator<<(std::ostream &os, const message &msg); /** * Wrapper around a log message that allows appending to the message with operator <<. @@ -125,8 +132,7 @@ class OAAPI MessageBuilder : public util::StringFormatter { * @param functionname (fully qualified) function name (OPENAGE_FUNC_NAME). * @param lvl loglevel of the message. Also required for exception messages. */ - MessageBuilder(const char *filename, unsigned lineno, const char *functionname, - level lvl=level::info); + MessageBuilder(const char *filename, unsigned lineno, const char *functionname, level lvl = level::info); // auto-convert to message inline operator const message &() const { @@ -159,16 +165,16 @@ class OAAPI MessageBuilder : public util::StringFormatter { // for use with existing log::level objects #define MSG_LVLOBJ(LVLOBJ) \ ::openage::log::MessageBuilder( \ - ::openage::util::constexpr_::strip_prefix( \ - __FILE__, \ - ::openage::config::buildsystem_sourcefile_dir), \ - __LINE__, \ - OPENAGE_FUNC_NAME, \ - LVLOBJ) + ::openage::util::constexpr_::strip_prefix( \ + __FILE__, \ + ::openage::config::buildsystem_sourcefile_dir), \ + __LINE__, \ + OPENAGE_FUNC_NAME, \ + LVLOBJ) // for use with log::level literals (auto-prefixes full qualification) -#define MSG(LVL) MSG_LVLOBJ(::openage::log::level:: LVL) +#define MSG(LVL) MSG_LVLOBJ(::openage::log::level::LVL) // some convenience shorteners for MSG(...). @@ -180,4 +186,5 @@ class OAAPI MessageBuilder : public util::StringFormatter { #define CRIT MSG(crit) -}} // openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/named_logsource.h b/libopenage/log/named_logsource.h index fe5e980123..c1839bd0cc 100644 --- a/libopenage/log/named_logsource.h +++ b/libopenage/log/named_logsource.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once @@ -8,6 +8,8 @@ // pxd: from libopenage.log.logsource cimport LogSource #include "logsource.h" +#include "../util/compiler.h" + namespace openage { namespace log { @@ -37,4 +39,5 @@ class OAAPI NamedLogSource : public LogSource { NamedLogSource &general_source(); -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/stdout_logsink.cpp b/libopenage/log/stdout_logsink.cpp index 978bae1579..647af51c49 100644 --- a/libopenage/log/stdout_logsink.cpp +++ b/libopenage/log/stdout_logsink.cpp @@ -1,16 +1,22 @@ -// Copyright 2015-2019 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "stdout_logsink.h" -#include #include +#include +#include #ifdef _MSC_VER #define WIN32_LEAN_AND_MEAN #include #endif -#include "named_logsource.h" +#include "log/level.h" +#include "log/logsource.h" +#include "log/message.h" +#include "log/named_logsource.h" +#include "util/enum.h" + namespace openage::log { @@ -36,7 +42,7 @@ void enable_ansi_color_codes() { } -} +} // namespace StdOutSink::StdOutSink() { @@ -46,14 +52,19 @@ StdOutSink::StdOutSink() { void StdOutSink::output_log_message(const message &msg, LogSource *source) { // print log level (width 4) - std::cout << "\x1b[" << msg.lvl->colorcode << "m" << std::setw(4) << msg.lvl->name << "\x1b[m" " "; + std::cout << "\x1b[" << msg.lvl->colorcode << "m" << std::setw(4) << msg.lvl->name << "\x1b[m" + " "; if (msg.thread_id != 0) { - std::cout << "\x1b[32m" "[T" << msg.thread_id << "]\x1b[m "; + std::cout << "\x1b[32m" + "[T" + << msg.thread_id << "]\x1b[m "; } if (source != &general_source()) { - std::cout << "\x1b[36m" "[" << source->logsource_name() << "]\x1b[m "; + std::cout << "\x1b[36m" + "[" + << source->logsource_name() << "]\x1b[m "; } std::cout << msg.text << std::endl; diff --git a/libopenage/log/stdout_logsink.h b/libopenage/log/stdout_logsink.h index cdf8c22637..b27a76175f 100644 --- a/libopenage/log/stdout_logsink.h +++ b/libopenage/log/stdout_logsink.h @@ -1,4 +1,4 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once @@ -6,7 +6,8 @@ namespace openage { namespace log { - +class LogSource; +struct message; /** * Simple logsink that prints messages to stdout (via std::cout). @@ -14,6 +15,7 @@ namespace log { class StdOutSink : public LogSink { public: StdOutSink(); + private: void output_log_message(const message &msg, LogSource *source) override; }; @@ -26,4 +28,5 @@ class StdOutSink : public LogSink { StdOutSink &global_stdoutsink(); -}} // namespace openage::log +} // namespace log +} // namespace openage diff --git a/libopenage/log/test.cpp b/libopenage/log/test.cpp index ae28caf7a2..1d7be48d0b 100644 --- a/libopenage/log/test.cpp +++ b/libopenage/log/test.cpp @@ -1,15 +1,15 @@ -// Copyright 2014-2019 the openage authors. See copying.md for legal info. +// Copyright 2014-2023 the openage authors. See copying.md for legal info. #include -#include +#include #include -#include -#include "log.h" -#include "logsource.h" -#include "logsink.h" +#include "log/logsink.h" +#include "log/logsource.h" +#include "log/message.h" +#include "util/stringformatter.h" +#include "util/strings.h" -#include "../util/strings.h" namespace openage::log::tests { @@ -24,9 +24,9 @@ class TestLogSource : public LogSource { class TestLogSink : public LogSink { public: - explicit TestLogSink(std::ostream &os) - : + explicit TestLogSink(std::ostream &os) : os{os} {} + private: std::ostream &os; @@ -62,4 +62,4 @@ void demo() { t1.join(); } -} // openage::log::tests +} // namespace openage::log::tests diff --git a/libopenage/main.cpp b/libopenage/main.cpp index 40cb48873c..7c80689a25 100644 --- a/libopenage/main.cpp +++ b/libopenage/main.cpp @@ -2,33 +2,12 @@ #include "main.h" -#include -#include +#include #include "cvar/cvar.h" #include "engine/engine.h" -#include "event/time_loop.h" -#include "gamestate/simulation.h" -#include "log/log.h" -#include "presenter/presenter.h" #include "util/timer.h" -// TODO: Remove custom jthread definition when clang/libc++ finally supports it -#if __llvm__ -#if !__cpp_lib_jthread -namespace std { -class jthread : public thread { -public: - using thread::thread; // needed constructors - ~jthread() { - this->join(); - } -}; -} // namespace std -#endif -#endif - - namespace openage { /* diff --git a/libopenage/main.h b/libopenage/main.h index c45052fd0a..7eb3317711 100644 --- a/libopenage/main.h +++ b/libopenage/main.h @@ -12,6 +12,9 @@ // pxd: from libopenage.util.path cimport Path #include "util/path.h" +#include + +#include "util/compiler.h" namespace openage { diff --git a/libopenage/main/tests.cpp b/libopenage/main/tests.cpp index 9ec4d77227..20b7369a52 100644 --- a/libopenage/main/tests.cpp +++ b/libopenage/main/tests.cpp @@ -1,5 +1,7 @@ // Copyright 2018-2023 the openage authors. See copying.md for legal info. +#include "tests.h" + #include "tests/pong.h" #include "tests/presenter.h" diff --git a/libopenage/main/tests.h b/libopenage/main/tests.h index 20e7c6edbd..fa9d8e4aef 100644 --- a/libopenage/main/tests.h +++ b/libopenage/main/tests.h @@ -2,13 +2,19 @@ #pragma once +#include "../util/compiler.h" // pxd: from libopenage.util.path cimport Path -#include "../util/path.h" -namespace openage::main::tests { +namespace openage { +namespace util { +class Path; +} // namespace util + +namespace main::tests { // pxd: void engine_demo(int demo_id, Path path) except + OAAPI void engine_demo(int demo_id, const util::Path &path); -} // namespace openage::main::tests +} // namespace main::tests +} // namespace openage diff --git a/libopenage/main/tests/aicontroller.cpp b/libopenage/main/tests/aicontroller.cpp index 046669e478..63bd369267 100644 --- a/libopenage/main/tests/aicontroller.cpp +++ b/libopenage/main/tests/aicontroller.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2019 the openage authors. See copying.md for legal info. +// Copyright 2019-2023 the openage authors. See copying.md for legal info. #include "aicontroller.h" @@ -9,7 +9,7 @@ namespace openage::main::tests::pong { std::vector get_ai_inputs(const std::shared_ptr &player, const std::shared_ptr &ball, const std::shared_ptr> &area_size_curve, - const curve::time_t &now, + const time::time_t &now, bool right_player) { std::vector ret; @@ -22,7 +22,7 @@ std::vector get_ai_inputs(const std::shared_ptr &player, double area_width = area_size[0]; double area_height = area_size[1]; - curve::time_t hit_time; + time::time_t hit_time; util::Vector2d hit_pos; // calculate ball trajectory @@ -31,22 +31,22 @@ std::vector get_ai_inputs(const std::shared_ptr &player, // move panel to predicted hit position of panel wall while (true) { - curve::time_t ty_hit = 0, tx_hit = 0; + time::time_t ty_hit = 0, tx_hit = 0; if (speed[0] == 0) { - tx_hit = std::numeric_limits::max(); + tx_hit = std::numeric_limits::max(); } else if (speed[0] > 0) { - tx_hit = curve::time_t::from_double((area_width - ball_pos[0]) / speed[0]); + tx_hit = time::time_t::from_double((area_width - ball_pos[0]) / speed[0]); } else if (speed[0] < 0) { - tx_hit = curve::time_t::from_double(ball_pos[0] / -speed[0]); + tx_hit = time::time_t::from_double(ball_pos[0] / -speed[0]); } if (speed[1] == 0) { - ty_hit = std::numeric_limits::max(); + ty_hit = std::numeric_limits::max(); } else if (speed[1] > 0) { - ty_hit = curve::time_t::from_double((area_height - ball_pos[1]) / speed[1]); + ty_hit = time::time_t::from_double((area_height - ball_pos[1]) / speed[1]); } else if (speed[1] < 0) { - ty_hit = curve::time_t::from_double(ball_pos[1] / -speed[1]); + ty_hit = time::time_t::from_double(ball_pos[1] / -speed[1]); } // actual hit has lowest time: diff --git a/libopenage/main/tests/aicontroller.h b/libopenage/main/tests/aicontroller.h index ea8376fd2e..5066a75f3f 100644 --- a/libopenage/main/tests/aicontroller.h +++ b/libopenage/main/tests/aicontroller.h @@ -1,4 +1,4 @@ -// Copyright 2019-2019 the openage authors. See copying.md for legal info. +// Copyright 2019-2023 the openage authors. See copying.md for legal info. #pragma once @@ -11,7 +11,7 @@ std::vector get_ai_inputs( const std::shared_ptr &player, const std::shared_ptr &ball, const std::shared_ptr> &area_size, - const curve::time_t &now, + const time::time_t &now, bool right_player ); diff --git a/libopenage/main/tests/gamestate.cpp b/libopenage/main/tests/gamestate.cpp index cb5bdb647d..2c2257677b 100644 --- a/libopenage/main/tests/gamestate.cpp +++ b/libopenage/main/tests/gamestate.cpp @@ -54,7 +54,7 @@ std::string PongPlayer::idstr() const { } -void PongPlayer::child_changes(const curve::time_t &time) { +void PongPlayer::child_changes(const time::time_t &time) { this->changes(time); } @@ -87,7 +87,7 @@ std::string PongBall::idstr() const { } -void PongBall::child_changes(const curve::time_t &time) { +void PongBall::child_changes(const time::time_t &time) { this->changes(time); } diff --git a/libopenage/main/tests/gamestate.h b/libopenage/main/tests/gamestate.h index 4ff97e1947..f66fbf1614 100644 --- a/libopenage/main/tests/gamestate.h +++ b/libopenage/main/tests/gamestate.h @@ -57,7 +57,7 @@ class PongPlayer : public event::EventEntity { size_t _id; private: - void child_changes(const curve::time_t &time); + void child_changes(const time::time_t &time); }; @@ -72,7 +72,7 @@ class PongBall : public event::EventEntity { std::shared_ptr> position; private: - void child_changes(const curve::time_t &time); + void child_changes(const time::time_t &time); size_t _id; }; diff --git a/libopenage/main/tests/gui.cpp b/libopenage/main/tests/gui.cpp index 04f3728ce9..2ef0897e2a 100644 --- a/libopenage/main/tests/gui.cpp +++ b/libopenage/main/tests/gui.cpp @@ -188,7 +188,7 @@ void main() { } -void Gui::draw(const std::shared_ptr &state, const curve::time_t &now) { +void Gui::draw(const std::shared_ptr &state, const time::time_t &now) { constexpr float ball_size = 50.0f; constexpr float paddle_width = 20.0f; diff --git a/libopenage/main/tests/gui.h b/libopenage/main/tests/gui.h index 33763fb3f0..b817d55a27 100644 --- a/libopenage/main/tests/gui.h +++ b/libopenage/main/tests/gui.h @@ -6,7 +6,7 @@ #include #include -#include "../../curve/curve.h" +#include "../../time/time.h" #include "../../renderer/renderer.h" #include "../../renderer/opengl/window.h" @@ -24,7 +24,7 @@ class Gui { const std::vector &get_inputs(const std::shared_ptr &player); - void draw(const std::shared_ptr &state, const curve::time_t &now); + void draw(const std::shared_ptr &state, const time::time_t &now); const util::Vector2s &get_window_size() const; diff --git a/libopenage/main/tests/physics.cpp b/libopenage/main/tests/physics.cpp index e737e40a51..c37f9ae122 100644 --- a/libopenage/main/tests/physics.cpp +++ b/libopenage/main/tests/physics.cpp @@ -32,7 +32,7 @@ class BallReflectWall : public event::DependencyEventHandler { void invoke(event::EventLoop &, const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &now, + const time::time_t &now, const event::EventHandler::param_map &/*param*/) override { auto positioncurve = std::dynamic_pointer_cast>(target); @@ -52,14 +52,14 @@ class BallReflectWall : public event::DependencyEventHandler { return; } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[1] > 0) { - ty = curve::time_t::from_double( + ty = time::time_t::from_double( (screen_size[1] - pos[1]) / speed[1] ); } else if (speed[1] < 0) { - ty = curve::time_t::from_double( + ty = time::time_t::from_double( pos[1] / -speed[1] ); } @@ -67,9 +67,9 @@ class BallReflectWall : public event::DependencyEventHandler { state->ball->position->set_last(now + ty, pos + (speed * ty.to_double())); } - curve::time_t predict_invoke_time(const std::shared_ptr &target, + time::time_t predict_invoke_time(const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &now) override { + const time::time_t &now) override { auto positioncurve = std::dynamic_pointer_cast>(target); auto state = std::dynamic_pointer_cast(gstate); @@ -79,15 +79,15 @@ class BallReflectWall : public event::DependencyEventHandler { auto screen_size = state->area_size->get(now); if (speed[1] == 0) { - return std::numeric_limits::max(); + return std::numeric_limits::max(); } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[1] > 0) { - ty = curve::time_t::from_double((screen_size[1] - pos[1]) / speed[1]); + ty = time::time_t::from_double((screen_size[1] - pos[1]) / speed[1]); } else if (speed[1] < 0) { - ty = curve::time_t::from_double(pos[1] / -speed[1]); + ty = time::time_t::from_double(pos[1] / -speed[1]); } util::FString str; @@ -120,7 +120,7 @@ class BallReflectPanel : public event::DependencyEventHandler { void invoke(event::EventLoop &mgr, const std::shared_ptr &/*target*/, const std::shared_ptr &gstate, - const curve::time_t &now, + const time::time_t &now, const event::EventHandler::param_map &/*param*/) override { auto state = std::dynamic_pointer_cast(gstate); @@ -167,12 +167,12 @@ class BallReflectPanel : public event::DependencyEventHandler { state->ball->position->set_last(now, pos); } - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[0] > 0) { - ty = curve::time_t::from_double((screen_size[0] - pos[0]) / speed[0]); + ty = time::time_t::from_double((screen_size[0] - pos[0]) / speed[0]); } else if (speed[0] < 0) { - ty = curve::time_t::from_double(pos[0] / -speed[0]); + ty = time::time_t::from_double(pos[0] / -speed[0]); } auto hit_pos = pos + speed * ty.to_double(); @@ -200,9 +200,9 @@ class BallReflectPanel : public event::DependencyEventHandler { } } - curve::time_t predict_invoke_time(const std::shared_ptr &target, + time::time_t predict_invoke_time(const std::shared_ptr &target, const std::shared_ptr &gstate, - const curve::time_t &now) override { + const time::time_t &now) override { auto positioncurve = std::dynamic_pointer_cast>(target); auto state = std::dynamic_pointer_cast(gstate); @@ -212,15 +212,15 @@ class BallReflectPanel : public event::DependencyEventHandler { auto screen_size = state->area_size->get(now); if (speed[0] == 0) - return std::numeric_limits::max(); + return std::numeric_limits::max(); - curve::time_t ty = 0; + time::time_t ty = 0; if (speed[0] > 0) { - ty = curve::time_t::from_double((screen_size[0] - pos[0]) / speed[0]); + ty = time::time_t::from_double((screen_size[0] - pos[0]) / speed[0]); } else if (speed[0] < 0) { - ty = curve::time_t::from_double(pos[0] / -speed[0]); + ty = time::time_t::from_double(pos[0] / -speed[0]); } { @@ -256,7 +256,7 @@ class ResetGame : public event::OnceEventHandler { void invoke(event::EventLoop &/*mgr*/, const std::shared_ptr &/*target*/, const std::shared_ptr &gstate, - const curve::time_t &now, + const time::time_t &now, const event::EventHandler::param_map &/*param*/) override { auto state = std::dynamic_pointer_cast(gstate); @@ -305,32 +305,32 @@ class ResetGame : public event::OnceEventHandler { state->gui->log(str); } - curve::time_t ty = 0; + time::time_t ty = 0; // calculate the wall-hit-times if (init_speed[1] > 0) { - ty = curve::time_t::from_double((screen_size[1] - pos[1]) / init_speed[1]); + ty = time::time_t::from_double((screen_size[1] - pos[1]) / init_speed[1]); } else if (init_speed[1] < 0) { - ty = curve::time_t::from_double(pos[1] / -init_speed[1]); + ty = time::time_t::from_double(pos[1] / -init_speed[1]); } else { // currently never happens, but this would be a non-vertically-moving ball // fallback to calculating panel-hit-times if (init_speed[0] > 0) { - ty = curve::time_t::from_double((screen_size[0] - pos[0]) / init_speed[0]); + ty = time::time_t::from_double((screen_size[0] - pos[0]) / init_speed[0]); } else { - ty = curve::time_t::from_double(pos[0] / -init_speed[0]); + ty = time::time_t::from_double(pos[0] / -init_speed[0]); } } state->ball->position->set_last(now + ty, pos + init_speed * ty.to_double()); } - curve::time_t predict_invoke_time(const std::shared_ptr &/*target*/, + time::time_t predict_invoke_time(const std::shared_ptr &/*target*/, const std::shared_ptr &/*state*/, - const curve::time_t &old_time) override { + const time::time_t &old_time) override { return old_time; } }; @@ -338,7 +338,7 @@ class ResetGame : public event::OnceEventHandler { void Physics::init(const std::shared_ptr &state, const std::shared_ptr &loop, - const curve::time_t &now) { + const time::time_t &now) { loop->add_event_handler(std::make_shared()); loop->add_event_handler(std::make_shared()); @@ -354,7 +354,7 @@ void Physics::init(const std::shared_ptr &state, void Physics::reset(const std::shared_ptr &gstate, event::EventLoop &mgr, - const curve::time_t &now) { + const time::time_t &now) { auto state = std::dynamic_pointer_cast(gstate); mgr.create_event("demo.reset", state->ball->position, state, now); @@ -365,10 +365,10 @@ void Physics::process_input(const std::shared_ptr &state, const std::shared_ptr &player, const std::vector &events, const std::shared_ptr &mgr, - const curve::time_t &now) { + const time::time_t &now) { // seconds into the future - constexpr static auto predicted_movement_time = curve::time_t::from_double(5.0); + constexpr static auto predicted_movement_time = time::time_t::from_double(5.0); // pixels per second for paddle movement constexpr static double movement_speed = 350.0; @@ -415,7 +415,7 @@ void Physics::process_input(const std::shared_ptr &state, break; } - curve::time_t move_stop_guess = now + predicted_movement_time; + time::time_t move_stop_guess = now + predicted_movement_time; // change the position by integrating the speed curve. // TODO: add native integral to curves. diff --git a/libopenage/main/tests/physics.h b/libopenage/main/tests/physics.h index 143a20527f..b29f643376 100644 --- a/libopenage/main/tests/physics.h +++ b/libopenage/main/tests/physics.h @@ -3,7 +3,7 @@ #pragma once #include "gamestate.h" -#include "../../curve/curve.h" +#include "../../time/time.h" #include @@ -20,17 +20,17 @@ class Physics { public: static void init(const std::shared_ptr &, const std::shared_ptr &mgr, - const curve::time_t &); + const time::time_t &); void process_input(const std::shared_ptr &, const std::shared_ptr &, const std::vector &input, const std::shared_ptr &mgr, - const curve::time_t &now); + const time::time_t &now); static void reset(const std::shared_ptr &, event::EventLoop &mgr, - const curve::time_t &); + const time::time_t &); }; } // openage::main::tests::pong diff --git a/libopenage/main/tests/pong.cpp b/libopenage/main/tests/pong.cpp index 59c7941ce0..9cbc163fdb 100644 --- a/libopenage/main/tests/pong.cpp +++ b/libopenage/main/tests/pong.cpp @@ -62,7 +62,7 @@ void main(const util::Path &path) { log::log(INFO << "initializing new pong game..."); auto loop = std::make_shared(); - curve::time_t now = 0; + time::time_t now = 0; Physics phys; // the window size is fetched in here already, @@ -146,7 +146,7 @@ void main(const util::Path &path) { // microseconds per frame // 30fps = 1s/30 = 1000000us/30 per frame constexpr static std::chrono::microseconds per_frame = 33333us; - constexpr static curve::time_t per_frame_s = std::chrono::duration_cast(per_frame).count(); + constexpr static time::time_t per_frame_s = std::chrono::duration_cast(per_frame).count(); if (speed == timescale::NOSLEEP) { // increase the simulation loop time a bit diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index 9bb312e45a..b1b08a2731 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -7,7 +7,6 @@ #include #include -#include "event/time_loop.h" #include "gamestate/simulation.h" #include "input/controller/camera/binding_context.h" #include "input/controller/camera/controller.h" @@ -30,13 +29,14 @@ #include "renderer/stages/terrain/terrain_renderer.h" #include "renderer/stages/world/world_renderer.h" #include "renderer/window.h" +#include "time/time_loop.h" #include "util/path.h" namespace openage::presenter { Presenter::Presenter(const util::Path &root_dir, const std::shared_ptr &simulation, - const std::shared_ptr &time_loop) : + const std::shared_ptr &time_loop) : root_dir{root_dir}, render_passes{}, simulation{simulation}, @@ -80,7 +80,7 @@ void Presenter::set_simulation(const std::shared_ptr this->simulation->attach_renderer(render_factory); } -void Presenter::set_time_loop(const std::shared_ptr &time_loop) { +void Presenter::set_time_loop(const std::shared_ptr &time_loop) { this->time_loop = time_loop; } diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index 0e0a672586..70ff733d43 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -13,10 +13,6 @@ class GuiApplication; namespace openage { -namespace event { -class TimeLoop; -} - namespace gamestate { class GameSimulation; } @@ -25,6 +21,10 @@ namespace input { class InputManager; } +namespace time { +class TimeLoop; +} + namespace renderer { class RenderPass; class Renderer; @@ -76,7 +76,7 @@ class Presenter { */ Presenter(const util::Path &path, const std::shared_ptr &simulation = nullptr, - const std::shared_ptr &time_loop = nullptr); + const std::shared_ptr &time_loop = nullptr); ~Presenter() = default; @@ -97,7 +97,7 @@ class Presenter { * * @param time_loop Time loop. */ - void set_time_loop(const std::shared_ptr &time_loop); + void set_time_loop(const std::shared_ptr &time_loop); /** * Initialize the Qt application managing the graphical views. Required @@ -211,7 +211,7 @@ class Presenter { /** * Time loop. */ - std::shared_ptr time_loop; + std::shared_ptr time_loop; /** * Input manager. diff --git a/libopenage/renderer/animation.h b/libopenage/renderer/animation.h index 860f245a21..aa5e27f8cf 100644 --- a/libopenage/renderer/animation.h +++ b/libopenage/renderer/animation.h @@ -2,8 +2,6 @@ #pragma once -#include - #include "renderer/resources/animation/animation_info.h" namespace openage::renderer { diff --git a/libopenage/renderer/camera/camera.cpp b/libopenage/renderer/camera/camera.cpp index aeaf45ffb7..7956e9fa70 100644 --- a/libopenage/renderer/camera/camera.cpp +++ b/libopenage/renderer/camera/camera.cpp @@ -2,11 +2,17 @@ #include "camera.h" +#include #include +#include +#include +#include "coord/pixel.h" +#include "coord/scene.h" #include "renderer/renderer.h" #include "renderer/resources/buffer_info.h" + namespace openage::renderer::camera { Camera::Camera(const std::shared_ptr &renderer, diff --git a/libopenage/renderer/camera/camera.h b/libopenage/renderer/camera/camera.h index c5d75beb5b..d82254cf5e 100644 --- a/libopenage/renderer/camera/camera.h +++ b/libopenage/renderer/camera/camera.h @@ -2,6 +2,10 @@ #pragma once +#include +#include +#include + #include #include "coord/pixel.h" @@ -21,9 +25,9 @@ namespace camera { * pitch = -30 degrees */ static const Eigen::Vector3f cam_direction{ - -1 * (sqrt(6) / 4), + -1 * (std::sqrt(6.f) / 4), -0.5f, - -1 * (sqrt(6) / 4), + -1 * (std::sqrt(6.f) / 4), }; /** diff --git a/libopenage/renderer/demo/demo_3.cpp b/libopenage/renderer/demo/demo_3.cpp index 9b142d8f7a..449fc45769 100644 --- a/libopenage/renderer/demo/demo_3.cpp +++ b/libopenage/renderer/demo/demo_3.cpp @@ -5,7 +5,6 @@ #include #include -#include "event/clock.h" #include "renderer/camera/camera.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" #include "renderer/opengl/window.h" @@ -20,6 +19,7 @@ #include "renderer/stages/world/world_render_entity.h" #include "renderer/stages/world/world_renderer.h" #include "renderer/uniform_buffer.h" +#include "time/clock.h" namespace openage::renderer::tests { @@ -31,7 +31,7 @@ void renderer_demo_3(const util::Path &path) { // Clock required by world renderer for timing animation frames // (we never advance time in this demo though, so it has no significance) - auto clock = std::make_shared(); + auto clock = std::make_shared(); // Camera // our viewport into the game world diff --git a/libopenage/renderer/demo/demo_4.cpp b/libopenage/renderer/demo/demo_4.cpp index 300167e652..95cc709ccb 100644 --- a/libopenage/renderer/demo/demo_4.cpp +++ b/libopenage/renderer/demo/demo_4.cpp @@ -5,7 +5,6 @@ #include #include -#include "event/clock.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" #include "renderer/opengl/window.h" #include "renderer/resources/animation/angle_info.h" @@ -15,6 +14,7 @@ #include "renderer/resources/shader_source.h" #include "renderer/resources/texture_data.h" #include "renderer/shader_program.h" +#include "time/clock.h" namespace openage::renderer::tests { void renderer_demo_4(const util::Path &path) { @@ -24,7 +24,7 @@ void renderer_demo_4(const util::Path &path) { auto renderer = window.make_renderer(); /* Clock for timed display */ - auto clock = event::Clock(); + auto clock = time::Clock(); /* Controls whether animations are use "real" time for frame timings (if true) or the actual simulation time (if false). When simulation time is used, @@ -187,11 +187,11 @@ void renderer_demo_4(const util::Path &path) { switch (key) { case Qt::Key_Space: { - if (clock.get_state() == event::ClockState::RUNNING) { + if (clock.get_state() == time::ClockState::RUNNING) { clock.pause(); log::log(INFO << "Stopped simulation at " << clock.get_time() << " (real = " << clock.get_real_time() << ")"); } - else if (clock.get_state() == event::ClockState::PAUSED) { + else if (clock.get_state() == time::ClockState::PAUSED) { clock.resume(); log::log(INFO << "Resumed simulation at " << clock.get_time() << " (real = " << clock.get_real_time() << ")"); } diff --git a/libopenage/renderer/demo/tests.cpp b/libopenage/renderer/demo/tests.cpp index 5deb3efd4c..3de072267c 100644 --- a/libopenage/renderer/demo/tests.cpp +++ b/libopenage/renderer/demo/tests.cpp @@ -3,6 +3,8 @@ #include "tests.h" #include "log/log.h" +#include "log/message.h" + #include "renderer/demo/demo_0.h" #include "renderer/demo/demo_1.h" #include "renderer/demo/demo_2.h" @@ -10,6 +12,7 @@ #include "renderer/demo/demo_4.h" #include "renderer/demo/demo_5.h" + namespace openage::renderer::tests { void renderer_demo(int demo_id, const util::Path &path) { diff --git a/libopenage/renderer/demo/tests.h b/libopenage/renderer/demo/tests.h index 0de8596c05..05568ae8fe 100644 --- a/libopenage/renderer/demo/tests.h +++ b/libopenage/renderer/demo/tests.h @@ -4,12 +4,17 @@ #include "../../util/compiler.h" // pxd: from libopenage.util.path cimport Path -#include "../../util/path.h" -namespace openage::renderer::tests { +namespace openage { +namespace util { +class Path; +} // namespace util + +namespace renderer::tests { // pxd: void renderer_demo(int demo_id, Path path) except + OAAPI void renderer_demo(int demo_id, const util::Path &path); -} // namespace openage::renderer::tests +} // namespace renderer::tests +} // namespace openage diff --git a/libopenage/renderer/gui/integration/private/gui_log.cpp b/libopenage/renderer/gui/integration/private/gui_log.cpp index 2cd4cef01c..f2556d214f 100644 --- a/libopenage/renderer/gui/integration/private/gui_log.cpp +++ b/libopenage/renderer/gui/integration/private/gui_log.cpp @@ -1,10 +1,12 @@ -// Copyright 2015-2022 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "../../integration/private/gui_log.h" #include #include "log/log.h" +#include "log/message.h" + namespace openage::renderer::gui { @@ -35,9 +37,8 @@ void gui_log(QtMsgType type, const QMessageLogContext &context, const QString &m log::MessageBuilder builder{ context.file != nullptr ? context.file : "", static_cast(context.line), - context.function != nullptr ? context.function : "", - msg_lvl - }; + context.function != nullptr ? context.function : "", + msg_lvl}; // TODO: maybe it's not UTF-8 // TODO: Qt should become a LogSource diff --git a/libopenage/renderer/opengl/debug.cpp b/libopenage/renderer/opengl/debug.cpp index 93fc41a2da..65bcfb9365 100644 --- a/libopenage/renderer/opengl/debug.cpp +++ b/libopenage/renderer/opengl/debug.cpp @@ -5,6 +5,7 @@ #include #include "log/log.h" +#include "log/message.h" namespace openage::renderer::opengl { diff --git a/libopenage/renderer/render_factory.h b/libopenage/renderer/render_factory.h index 13f7b50304..84f2b6eb39 100644 --- a/libopenage/renderer/render_factory.h +++ b/libopenage/renderer/render_factory.h @@ -5,8 +5,6 @@ #include namespace openage::renderer { -class Renderer; - namespace terrain { class TerrainRenderer; class TerrainRenderEntity; diff --git a/libopenage/renderer/renderer.h b/libopenage/renderer/renderer.h index 6432d34b0a..8dec3dec2f 100644 --- a/libopenage/renderer/renderer.h +++ b/libopenage/renderer/renderer.h @@ -3,6 +3,8 @@ #pragma once #include +#include +#include #include diff --git a/libopenage/renderer/resources/animation/animation_info.h b/libopenage/renderer/resources/animation/animation_info.h index 3c8b666923..be53acb180 100644 --- a/libopenage/renderer/resources/animation/animation_info.h +++ b/libopenage/renderer/resources/animation/animation_info.h @@ -2,16 +2,16 @@ #pragma once +#include +#include #include #include "renderer/resources/animation/layer_info.h" -#include "renderer/resources/texture_info.h" -namespace openage::renderer { -class Texture2d; - -namespace resources { +namespace openage::renderer::resources { +class Texture2dInfo; +class Texture2dSubInfo; /** * Contains information about a 2D animation. The animation data can be @@ -96,5 +96,4 @@ class Animation2dInfo { std::vector layers; }; -} // namespace resources -} // namespace openage::renderer +} // namespace openage::renderer::resources diff --git a/libopenage/renderer/resources/animation/layer_info.cpp b/libopenage/renderer/resources/animation/layer_info.cpp index ed0b87c151..49c95104a4 100644 --- a/libopenage/renderer/resources/animation/layer_info.cpp +++ b/libopenage/renderer/resources/animation/layer_info.cpp @@ -3,9 +3,12 @@ #include "layer_info.h" #include +#include #include "renderer/resources/animation/angle_info.h" #include "renderer/resources/frame_timing.h" +#include "time/time.h" + namespace openage::renderer::resources { @@ -23,8 +26,8 @@ LayerInfo::LayerInfo(std::vector> &angles, if (this->angles.size() > 0) { // set frame timings by calculating when they appear in the animation sequence auto frame_count = this->angles[0]->get_frame_count(); - curve::time_t t = 0; - std::vector keyframes; + time::time_t t = 0; + std::vector keyframes; for (size_t i = 0; i < frame_count; ++i) { keyframes.push_back(t); t += this->time_per_frame; diff --git a/libopenage/renderer/resources/assets/asset_manager.cpp b/libopenage/renderer/resources/assets/asset_manager.cpp index 54952b6cc2..284b2d27fb 100644 --- a/libopenage/renderer/resources/assets/asset_manager.cpp +++ b/libopenage/renderer/resources/assets/asset_manager.cpp @@ -2,9 +2,10 @@ #include "asset_manager.h" +#include "error/error.h" #include "log/log.h" +#include "log/message.h" -#include "renderer/renderer.h" #include "renderer/resources/animation/animation_info.h" #include "renderer/resources/assets/cache.h" #include "renderer/resources/assets/texture_manager.h" @@ -18,9 +19,9 @@ #include "renderer/resources/terrain/blendpattern_info.h" #include "renderer/resources/terrain/blendtable_info.h" #include "renderer/resources/terrain/terrain_info.h" -#include "renderer/resources/texture_data.h" #include "renderer/resources/texture_info.h" + namespace openage::renderer::resources { AssetManager::AssetManager(const std::shared_ptr &renderer, diff --git a/libopenage/renderer/resources/assets/asset_manager.h b/libopenage/renderer/resources/assets/asset_manager.h index 0ce9706cef..0d45e473dd 100644 --- a/libopenage/renderer/resources/assets/asset_manager.h +++ b/libopenage/renderer/resources/assets/asset_manager.h @@ -5,10 +5,11 @@ #include #include #include -#include +#include #include "util/path.h" + namespace openage::renderer { class Renderer; diff --git a/libopenage/renderer/resources/assets/cache.cpp b/libopenage/renderer/resources/assets/cache.cpp index 6ace9b0a00..5ab4db4229 100644 --- a/libopenage/renderer/resources/assets/cache.cpp +++ b/libopenage/renderer/resources/assets/cache.cpp @@ -2,47 +2,44 @@ #include "cache.h" -#include "renderer/resources/animation/animation_info.h" -#include "renderer/resources/palette_info.h" -#include "renderer/resources/terrain/blendpattern_info.h" -#include "renderer/resources/terrain/blendtable_info.h" -#include "renderer/resources/terrain/terrain_info.h" +#include "util/path.h" + namespace openage::renderer::resources { const std::shared_ptr &AssetCache::get_animation(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_animations[flat_path]; + return this->loaded_animations.at(flat_path); } const std::shared_ptr &AssetCache::get_blpattern(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_blpatterns[flat_path]; + return this->loaded_blpatterns.at(flat_path); } const std::shared_ptr &AssetCache::get_bltable(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_bltables[flat_path]; + return this->loaded_bltables.at(flat_path); } const std::shared_ptr &AssetCache::get_palette(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_palettes[flat_path]; + return this->loaded_palettes.at(flat_path); } const std::shared_ptr &AssetCache::get_terrain(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_terrains[flat_path]; + return this->loaded_terrains.at(flat_path); } const std::shared_ptr &AssetCache::get_texture(const util::Path &path) { auto flat_path = path.resolve_native_path(); - return this->loaded_textures[flat_path]; + return this->loaded_textures.at(flat_path); } diff --git a/libopenage/renderer/resources/assets/cache.h b/libopenage/renderer/resources/assets/cache.h index c3cc9a3d66..504a02bfd2 100644 --- a/libopenage/renderer/resources/assets/cache.h +++ b/libopenage/renderer/resources/assets/cache.h @@ -6,11 +6,12 @@ #include #include -#include "util/path.h" -namespace openage::renderer { - -namespace resources { +namespace openage { +namespace util { +class Path; +} +namespace renderer::resources { class Animation2dInfo; class BlendPatternInfo; class BlendTableInfo; @@ -128,5 +129,5 @@ class AssetCache { texture_cache_t loaded_textures; }; -} // namespace resources -} // namespace openage::renderer +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/assets/texture_manager.cpp b/libopenage/renderer/resources/assets/texture_manager.cpp index cc22d63e31..5cf3b2db0c 100644 --- a/libopenage/renderer/resources/assets/texture_manager.cpp +++ b/libopenage/renderer/resources/assets/texture_manager.cpp @@ -3,9 +3,9 @@ #include "texture_manager.h" #include "renderer/renderer.h" -#include "renderer/resources/parser/parse_texture.h" #include "renderer/resources/texture_data.h" + namespace openage::renderer::resources { TextureManager::TextureManager(const std::shared_ptr &renderer) : diff --git a/libopenage/renderer/resources/assets/texture_manager.h b/libopenage/renderer/resources/assets/texture_manager.h index 20e30973bb..73c8318c6b 100644 --- a/libopenage/renderer/resources/assets/texture_manager.h +++ b/libopenage/renderer/resources/assets/texture_manager.h @@ -6,9 +6,11 @@ #include #include #include +#include #include "util/path.h" + namespace openage::renderer { class Renderer; class Texture2d; diff --git a/libopenage/renderer/resources/buffer_info.h b/libopenage/renderer/resources/buffer_info.h index 7bdee91752..b654c3090f 100644 --- a/libopenage/renderer/resources/buffer_info.h +++ b/libopenage/renderer/resources/buffer_info.h @@ -2,11 +2,15 @@ #pragma once +#include +#include #include +#include #include #include "datastructure/constexpr_map.h" + namespace openage::renderer::resources { /** diff --git a/libopenage/renderer/resources/frame_timing.cpp b/libopenage/renderer/resources/frame_timing.cpp index ec6abf6f1b..c29801827a 100644 --- a/libopenage/renderer/resources/frame_timing.cpp +++ b/libopenage/renderer/resources/frame_timing.cpp @@ -2,10 +2,18 @@ #include "frame_timing.h" +#include +#include + +#include "error/error.h" +#include "log/message.h" + +#include "util/fixed_point.h" + namespace openage::renderer::resources { -FrameTiming::FrameTiming(const curve::time_t &total_length, +FrameTiming::FrameTiming(const time::time_t &total_length, const std::vector &&keyframes) : keyframes{keyframes}, total_length{total_length} { @@ -14,11 +22,11 @@ FrameTiming::FrameTiming(const curve::time_t &total_length, } } -void FrameTiming::set_total_length(const curve::time_t &total_length) { +void FrameTiming::set_total_length(const time::time_t &total_length) { this->total_length = total_length; } -void FrameTiming::insert(const curve::time_t &time) { +void FrameTiming::insert(const time::time_t &time) { for (auto it = this->keyframes.begin(); it != this->keyframes.end(); ++it) { if (*it >= time) { this->keyframes.insert(it, time); @@ -27,18 +35,18 @@ void FrameTiming::insert(const curve::time_t &time) { } } -size_t FrameTiming::get_frame(const curve::time_t &time) const { +size_t FrameTiming::get_frame(const time::time_t &time) const { return search_frame(time); } -size_t FrameTiming::get_frame(const curve::time_t &time, const curve::time_t &start) const { - curve::time_t offset = time - start; +size_t FrameTiming::get_frame(const time::time_t &time, const time::time_t &start) const { + time::time_t offset = time - start; if (this->total_length == 0) { // modulo would fail here so return early return 0; } - curve::time_t mod = offset % this->total_length; + time::time_t mod = offset % this->total_length; return this->get_frame(mod); } @@ -46,7 +54,7 @@ size_t FrameTiming::size() const { return this->keyframes.size(); } -size_t FrameTiming::search_frame(const curve::time_t &time) const { +size_t FrameTiming::search_frame(const time::time_t &time) const { size_t left = 0; size_t right = this->keyframes.size(); size_t mid = 0; diff --git a/libopenage/renderer/resources/frame_timing.h b/libopenage/renderer/resources/frame_timing.h index 7ff5fcc2b9..c253501900 100644 --- a/libopenage/renderer/resources/frame_timing.h +++ b/libopenage/renderer/resources/frame_timing.h @@ -5,7 +5,7 @@ #include #include -#include "curve/curve.h" +#include "time/time.h" namespace openage::renderer::resources { @@ -17,7 +17,7 @@ namespace openage::renderer::resources { */ class FrameTiming { public: - using keyframe_t = curve::time_t; + using keyframe_t = time::time_t; /** * Create a new frame timing sequence. @@ -25,7 +25,7 @@ class FrameTiming { * @param total_length Total length of the sequence (in seconds). * @param keyframes Time of each frame (in seconds). Expected to be sorted. */ - FrameTiming(const curve::time_t &total_length, + FrameTiming(const time::time_t &total_length, const std::vector &&keyframes); ~FrameTiming() = default; @@ -35,7 +35,7 @@ class FrameTiming { * * @param total_length Total length of the sequence (in seconds). */ - void set_total_length(const curve::time_t &total_length); + void set_total_length(const time::time_t &total_length); /** * Insert a new keyframe into the sequence. @@ -46,7 +46,7 @@ class FrameTiming { * * @param time Time of the new keyframe (in seconds). */ - void insert(const curve::time_t &time); + void insert(const time::time_t &time); /** * Get the index of the frame in the sequence that should be displayed at the @@ -55,7 +55,7 @@ class FrameTiming { * @param time Time in the sequence (in seconds). * @return Frame index in the sequence. */ - size_t get_frame(const curve::time_t &time) const; + size_t get_frame(const time::time_t &time) const; /** * Get the index of the frame in the sequence that should be displayed at a specified @@ -71,7 +71,7 @@ class FrameTiming { * @param start Start time of the sequence (in seconds). * @return Frame index in the sequence. */ - size_t get_frame(const curve::time_t ¤t, const curve::time_t &start) const; + size_t get_frame(const time::time_t ¤t, const time::time_t &start) const; /** * Get the number of frames in the sequence. @@ -90,7 +90,7 @@ class FrameTiming { * @param time Time in the sequence (in seconds). * @return Frame index in the sequence. */ - size_t search_frame(const curve::time_t &time) const; + size_t search_frame(const time::time_t &time) const; /** * Time of each frame in the sequence relative to the sequence start (in seconds). @@ -100,7 +100,7 @@ class FrameTiming { /** * Total length of the sequence (in seconds). */ - curve::time_t total_length; + time::time_t total_length; }; } // namespace openage::renderer::resources diff --git a/libopenage/renderer/resources/mesh_data.cpp b/libopenage/renderer/resources/mesh_data.cpp index e7aed09a87..74fb72b629 100644 --- a/libopenage/renderer/resources/mesh_data.cpp +++ b/libopenage/renderer/resources/mesh_data.cpp @@ -4,10 +4,13 @@ #include #include +#include #include -#include "../../error/error.h" -#include "../../datastructure/constexpr_map.h" +#include "error/error.h" +#include "log/message.h" + +#include "datastructure/constexpr_map.h" namespace openage::renderer::resources { @@ -16,15 +19,13 @@ static constexpr auto vin_size = datastructure::create_const_map( std::make_pair(vertex_input_t::F32, 1), std::make_pair(vertex_input_t::V2F32, 2), std::make_pair(vertex_input_t::V3F32, 3), - std::make_pair(vertex_input_t::M3F32, 9) -); + std::make_pair(vertex_input_t::M3F32, 9)); size_t vertex_input_size(vertex_input_t in) { return vin_size.get(in); @@ -34,18 +35,13 @@ size_t vertex_input_count(vertex_input_t in) { return vin_count.get(in); } -VertexInputInfo::VertexInputInfo(std::vector inputs, vertex_layout_t layout, vertex_primitive_t primitive) - : inputs(std::move(inputs)) - , layout(layout) - , primitive(primitive) {} +VertexInputInfo::VertexInputInfo(std::vector inputs, vertex_layout_t layout, vertex_primitive_t primitive) : + inputs(std::move(inputs)), layout(layout), primitive(primitive) {} -VertexInputInfo::VertexInputInfo(std::vector inputs, vertex_layout_t layout, vertex_primitive_t primitive, index_t index_type) - : inputs(std::move(inputs)) - , layout(layout) - , primitive(primitive) - , index_type(index_type) {} +VertexInputInfo::VertexInputInfo(std::vector inputs, vertex_layout_t layout, vertex_primitive_t primitive, index_t index_type) : + inputs(std::move(inputs)), layout(layout), primitive(primitive), index_type(index_type) {} -void VertexInputInfo::add_shader_input_map(std::unordered_map&& in_map) { +void VertexInputInfo::add_shader_input_map(std::unordered_map &&in_map) { for (auto mapping : in_map) { if (mapping.first >= this->inputs.size()) [[unlikely]] { throw Error(MSG(err) << "A shader input mapping is out-of-range, exceeding the available number of attributes."); @@ -67,7 +63,7 @@ const std::vector &VertexInputInfo::get_inputs() const { return this->inputs; } -std::optional> const& VertexInputInfo::get_shader_input_map() const { +std::optional> const &VertexInputInfo::get_shader_input_map() const { return this->shader_input_map; } @@ -83,21 +79,18 @@ std::optional VertexInputInfo::get_index_type() const { return this->index_type; } -MeshData::MeshData(const util::Path &/*path*/) { +MeshData::MeshData(const util::Path & /*path*/) { // TODO implement mesh loaders throw "unimplemented lol"; } -MeshData::MeshData(std::vector&& verts, const VertexInputInfo &info) - : data(std::move(verts)) - , info(info) {} +MeshData::MeshData(std::vector &&verts, const VertexInputInfo &info) : + data(std::move(verts)), info(info) {} -MeshData::MeshData(std::vector &&verts, std::vector &&ids, const VertexInputInfo &info) - : data(std::move(verts)) - , ids(std::move(ids)) - , info(info) {} +MeshData::MeshData(std::vector &&verts, std::vector &&ids, const VertexInputInfo &info) : + data(std::move(verts)), ids(std::move(ids)), info(info) {} -std::vector const& MeshData::get_data() const { +std::vector const &MeshData::get_data() const { return this->data; } @@ -112,24 +105,12 @@ VertexInputInfo MeshData::get_info() const { /// Vertices of a quadrilateral filling the whole screen. /// Format: (pos, tex_coords) = (x, y, u, v) static constexpr const std::array QUAD_DATA_CENTERED = { - { - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f - } -}; + {-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f}}; /// Vertices of a quad from (0, 0) to (1, 1) /// Format: (pos, tex_coords) = (x, y, u, v) static constexpr const std::array QUAD_DATA_UNIT = { - { - 0.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 0.0f, 1.0f, 0.0f - } -}; + {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f}}; namespace { @@ -142,18 +123,17 @@ MeshData create_float_mesh(const std::array &src) { auto const data_size = size * sizeof(float); std::vector verts(data_size); - std::memcpy(verts.data(), reinterpret_cast(src.data()), data_size); + std::memcpy(verts.data(), reinterpret_cast(src.data()), data_size); - VertexInputInfo info { - { vertex_input_t::V2F32, vertex_input_t::V2F32 }, + VertexInputInfo info{ + {vertex_input_t::V2F32, vertex_input_t::V2F32}, vertex_layout_t::AOS, - vertex_primitive_t::TRIANGLE_STRIP - }; + vertex_primitive_t::TRIANGLE_STRIP}; return MeshData(std::move(verts), info); } -} // anon namespace +} // namespace MeshData MeshData::make_quad(bool centered) { @@ -167,31 +147,18 @@ MeshData MeshData::make_quad(bool centered) { MeshData MeshData::make_quad(float sidelength, bool centered) { - // 8 positions and 8 uv-coords. // store pos and uv as: (x, y, uvx, uvy) std::array positions; if (centered) { - float halfsidelength = sidelength/2; + float halfsidelength = sidelength / 2; positions = { - { - -halfsidelength, halfsidelength, 0.0f, 1.0f, - -halfsidelength, -halfsidelength, 0.0f, 0.0f, - halfsidelength, halfsidelength, 1.0f, 1.0f, - halfsidelength, -halfsidelength, 1.0f, 0.0f - } - }; + {-halfsidelength, halfsidelength, 0.0f, 1.0f, -halfsidelength, -halfsidelength, 0.0f, 0.0f, halfsidelength, halfsidelength, 1.0f, 1.0f, halfsidelength, -halfsidelength, 1.0f, 0.0f}}; } else { positions = { - { - 0.0f, sidelength, 0.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - sidelength, sidelength, 1.0f, 1.0f, - sidelength, 0.0f, 1.0f, 0.0f - } - }; + {0.0f, sidelength, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, sidelength, sidelength, 1.0f, 1.0f, sidelength, 0.0f, 1.0f, 0.0f}}; } return create_float_mesh(positions); @@ -204,26 +171,14 @@ MeshData MeshData::make_quad(float width, float height, bool centered) { std::array positions; if (centered) { - float halfwidth = width/2; - float halfheight = height/2; + float halfwidth = width / 2; + float halfheight = height / 2; positions = { - { - -halfwidth, halfheight, 0.0f, 1.0f, - -halfwidth, -halfheight, 0.0f, 0.0f, - halfwidth, halfheight, 1.0f, 1.0f, - halfwidth, -halfheight, 1.0f, 0.0f - } - }; + {-halfwidth, halfheight, 0.0f, 1.0f, -halfwidth, -halfheight, 0.0f, 0.0f, halfwidth, halfheight, 1.0f, 1.0f, halfwidth, -halfheight, 1.0f, 0.0f}}; } else { positions = { - { - 0.0f, height, 0.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - width, height, 1.0f, 1.0f, - width, 0.0f, 1.0f, 0.0f - } - }; + {0.0f, height, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, width, height, 1.0f, 1.0f, width, 0.0f, 1.0f, 0.0f}}; } return create_float_mesh(positions); diff --git a/libopenage/renderer/resources/mesh_data.h b/libopenage/renderer/resources/mesh_data.h index 5d1ce51f9e..1ad0d7a3f4 100644 --- a/libopenage/renderer/resources/mesh_data.h +++ b/libopenage/renderer/resources/mesh_data.h @@ -1,17 +1,18 @@ -// Copyright 2017-2019 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once -#include -#include #include #include #include - -#include "../../util/path.h" +#include +#include namespace openage { +namespace util { +class Path; +} namespace renderer { namespace resources { @@ -71,13 +72,13 @@ class VertexInputInfo { /// map. The map entries must have the format (index_in_vector, index_in_shader) and will /// overwrite the default mapping. If an entry for a given index in the vector is missing, /// that attribute and its data will be skipped. - void add_shader_input_map(std::unordered_map&&); + void add_shader_input_map(std::unordered_map &&); /// Returns the list of per-vertex inputs. const std::vector &get_inputs() const; /// Returns the shader input map or an empty optional if it's not present. - std::optional> const& get_shader_input_map() const; + std::optional> const &get_shader_input_map() const; /// Returns the layout of vertices in memory. vertex_layout_t get_layout() const; @@ -114,13 +115,13 @@ class VertexInputInfo { class MeshData { public: /// Tries to load the mesh data from the specified file. - explicit MeshData(const util::Path&); + explicit MeshData(const util::Path &); /// Initializes the mesh data to a custom unindexed vertex vector described by the given info. - MeshData(std::vector &&verts, const VertexInputInfo&); + MeshData(std::vector &&verts, const VertexInputInfo &); /// Initializes the mesh data to a custom indexed vertex vector described by the given info. - MeshData(std::vector &&verts, std::vector &&ids, const VertexInputInfo&); + MeshData(std::vector &&verts, std::vector &&ids, const VertexInputInfo &); /// Returns the raw vertex data. std::vector const &get_data() const; @@ -136,13 +137,13 @@ class MeshData { /// (0, 0) of this quad is at the quad center and it stretches from (-1, -1) to (1, 1) /// and uv=(0, 0) at bottom left (-> (-1, -1)) and uv=(1, 1) top right (at (1, 1)). /// When centered = false, the quad stretches from (0, 0) to (1, 1). - static MeshData make_quad(bool centered=true); + static MeshData make_quad(bool centered = true); /// Initialize the mesh data with given sidelength. Optionally place (0, 0) bottom left. - static MeshData make_quad(float sidelength, bool centered=true); + static MeshData make_quad(float sidelength, bool centered = true); /// Initialize the mesh data with given width and height. Optionally place (0, 0) bottom left. - static MeshData make_quad(float width, float height, bool centered=true); + static MeshData make_quad(float width, float height, bool centered = true); private: /// The raw vertex data. The size is an integer multiple of the size of a single vertex. @@ -159,4 +160,6 @@ class MeshData { std::optional info; }; -}}} +} // namespace resources +} // namespace renderer +} // namespace openage diff --git a/libopenage/renderer/resources/palette_info.h b/libopenage/renderer/resources/palette_info.h index ba5d17cf59..d147522feb 100644 --- a/libopenage/renderer/resources/palette_info.h +++ b/libopenage/renderer/resources/palette_info.h @@ -2,10 +2,13 @@ #pragma once +#include +#include #include #include + namespace openage::renderer::resources { /** diff --git a/libopenage/renderer/resources/parser/common.cpp b/libopenage/renderer/resources/parser/common.cpp index 3f30fa2f72..30fa97118c 100644 --- a/libopenage/renderer/resources/parser/common.cpp +++ b/libopenage/renderer/resources/parser/common.cpp @@ -2,6 +2,9 @@ #include "common.h" +#include + + namespace openage::renderer::resources::parser { size_t parse_version(const std::vector &args) { diff --git a/libopenage/renderer/resources/parser/parse_blendmask.cpp b/libopenage/renderer/resources/parser/parse_blendmask.cpp index 29c00b2f53..d7f6e4aa74 100644 --- a/libopenage/renderer/resources/parser/parse_blendmask.cpp +++ b/libopenage/renderer/resources/parser/parse_blendmask.cpp @@ -2,16 +2,27 @@ #include "parse_blendmask.h" +#include +#include #include +#include +#include +#include +#include +#include + +#include "log/message.h" #include "error/error.h" #include "renderer/resources/assets/cache.h" #include "renderer/resources/parser/common.h" #include "renderer/resources/parser/parse_texture.h" -#include "renderer/resources/texture_data.h" -#include "renderer/texture.h" +#include "renderer/resources/texture_info.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /** diff --git a/libopenage/renderer/resources/parser/parse_blendmask.h b/libopenage/renderer/resources/parser/parse_blendmask.h index 7c80cb5545..795401c13a 100644 --- a/libopenage/renderer/resources/parser/parse_blendmask.h +++ b/libopenage/renderer/resources/parser/parse_blendmask.h @@ -2,10 +2,17 @@ #pragma once +#include + #include "renderer/resources/terrain/blendpattern_info.h" -#include "util/path.h" -namespace openage::renderer::resources { + +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources { class AssetCache; namespace parser { @@ -22,4 +29,5 @@ BlendPatternInfo parse_blendmask_file(const util::Path &file, const std::shared_ptr &cache = nullptr); } // namespace parser -} // namespace openage::renderer::resources +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/parser/parse_blendtable.cpp b/libopenage/renderer/resources/parser/parse_blendtable.cpp index e7d033eeaf..c37579ce36 100644 --- a/libopenage/renderer/resources/parser/parse_blendtable.cpp +++ b/libopenage/renderer/resources/parser/parse_blendtable.cpp @@ -3,15 +3,24 @@ #include "parse_blendtable.h" #include +#include +#include +#include +#include #include "error/error.h" +#include "log/message.h" + #include "renderer/resources/assets/cache.h" #include "renderer/resources/parser/common.h" #include "renderer/resources/parser/parse_blendmask.h" #include "renderer/resources/terrain/blendpattern_info.h" #include "renderer/resources/terrain/blendtable_info.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /** diff --git a/libopenage/renderer/resources/parser/parse_blendtable.h b/libopenage/renderer/resources/parser/parse_blendtable.h index fb667101c0..d3e7ea2265 100644 --- a/libopenage/renderer/resources/parser/parse_blendtable.h +++ b/libopenage/renderer/resources/parser/parse_blendtable.h @@ -2,10 +2,18 @@ #pragma once +#include +#include +#include + #include "renderer/resources/terrain/blendtable_info.h" -#include "util/path.h" -namespace openage::renderer::resources { +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources { class AssetCache; namespace parser { @@ -32,4 +40,5 @@ BlendTableInfo parse_blendtable_file(const util::Path &file, const std::shared_ptr &cache = nullptr); } // namespace parser -} // namespace openage::renderer::resources +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/parser/parse_palette.cpp b/libopenage/renderer/resources/parser/parse_palette.cpp index d360a8976f..344466dd86 100644 --- a/libopenage/renderer/resources/parser/parse_palette.cpp +++ b/libopenage/renderer/resources/parser/parse_palette.cpp @@ -2,12 +2,24 @@ #include "parse_palette.h" +#include +#include #include +#include +#include +#include +#include +#include #include "error/error.h" +#include "log/message.h" + #include "renderer/resources/parser/common.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /** diff --git a/libopenage/renderer/resources/parser/parse_palette.h b/libopenage/renderer/resources/parser/parse_palette.h index 17c48c4e88..8b8112371a 100644 --- a/libopenage/renderer/resources/parser/parse_palette.h +++ b/libopenage/renderer/resources/parser/parse_palette.h @@ -3,9 +3,13 @@ #pragma once #include "renderer/resources/palette_info.h" -#include "util/path.h" -namespace openage::renderer::resources::parser { +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources::parser { /** * Parse an palette definition from a .opal format file. @@ -16,4 +20,5 @@ namespace openage::renderer::resources::parser { */ PaletteInfo parse_palette_file(const util::Path &file); -} // namespace openage::renderer::resources::parser +} // namespace renderer::resources::parser +} // namespace openage diff --git a/libopenage/renderer/resources/parser/parse_sprite.cpp b/libopenage/renderer/resources/parser/parse_sprite.cpp index 48c55f1046..2156cc8422 100644 --- a/libopenage/renderer/resources/parser/parse_sprite.cpp +++ b/libopenage/renderer/resources/parser/parse_sprite.cpp @@ -2,18 +2,29 @@ #include "parse_sprite.h" +#include #include +#include +#include +#include +#include +#include #include "error/error.h" +#include "log/message.h" + #include "renderer/resources/animation/angle_info.h" #include "renderer/resources/animation/frame_info.h" #include "renderer/resources/animation/layer_info.h" #include "renderer/resources/assets/cache.h" #include "renderer/resources/parser/common.h" #include "renderer/resources/parser/parse_texture.h" -#include "renderer/texture.h" +#include "renderer/resources/texture_info.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /** diff --git a/libopenage/renderer/resources/parser/parse_sprite.h b/libopenage/renderer/resources/parser/parse_sprite.h index 091778d134..b2021190b3 100644 --- a/libopenage/renderer/resources/parser/parse_sprite.h +++ b/libopenage/renderer/resources/parser/parse_sprite.h @@ -2,10 +2,19 @@ #pragma once -#include "renderer/animation.h" -#include "util/path.h" +#include +#include -namespace openage::renderer::resources { +#include "renderer/resources/animation/animation_info.h" +#include "renderer/resources/animation/layer_info.h" + + +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources { class AssetCache; namespace parser { @@ -47,5 +56,6 @@ struct FrameData { Animation2dInfo parse_sprite_file(const util::Path &file, const std::shared_ptr &cache = nullptr); -} // namespace resources::parser -} // namespace openage::renderer +} // namespace parser +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/parser/parse_terrain.cpp b/libopenage/renderer/resources/parser/parse_terrain.cpp index 1a0c65194f..cc7b2f4814 100644 --- a/libopenage/renderer/resources/parser/parse_terrain.cpp +++ b/libopenage/renderer/resources/parser/parse_terrain.cpp @@ -2,19 +2,30 @@ #include "parse_terrain.h" +#include +#include #include +#include +#include +#include +#include #include "error/error.h" +#include "log/message.h" + #include "renderer/resources/assets/cache.h" #include "renderer/resources/parser/common.h" #include "renderer/resources/parser/parse_blendtable.h" #include "renderer/resources/parser/parse_texture.h" +#include "renderer/resources/terrain/blendtable_info.h" #include "renderer/resources/terrain/frame_info.h" #include "renderer/resources/terrain/layer_info.h" -#include "renderer/resources/texture_data.h" -#include "renderer/texture.h" +#include "renderer/resources/texture_info.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /** diff --git a/libopenage/renderer/resources/parser/parse_terrain.h b/libopenage/renderer/resources/parser/parse_terrain.h index ab7b39fb5f..6aad27ce6e 100644 --- a/libopenage/renderer/resources/parser/parse_terrain.h +++ b/libopenage/renderer/resources/parser/parse_terrain.h @@ -2,12 +2,21 @@ #pragma once +#include +#include #include +#include +#include "renderer/resources/terrain/layer_info.h" #include "renderer/resources/terrain/terrain_info.h" -#include "util/path.h" -namespace openage::renderer::resources { + +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources { class AssetCache; namespace parser { @@ -51,4 +60,5 @@ TerrainInfo parse_terrain_file(const util::Path &file, const std::shared_ptr &cache = nullptr); } // namespace parser -} // namespace openage::renderer::resources +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/parser/parse_texture.cpp b/libopenage/renderer/resources/parser/parse_texture.cpp index 442691b2f4..7da91211f4 100644 --- a/libopenage/renderer/resources/parser/parse_texture.cpp +++ b/libopenage/renderer/resources/parser/parse_texture.cpp @@ -2,11 +2,25 @@ #include "parse_texture.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include "error/error.h" -#include "renderer/renderer.h" +#include "log/message.h" + #include "renderer/resources/parser/common.h" +#include "renderer/resources/texture_subinfo.h" +#include "util/file.h" +#include "util/path.h" #include "util/strings.h" + namespace openage::renderer::resources::parser { /// Tries to guess the alignment of image rows based on image parameters. Kinda diff --git a/libopenage/renderer/resources/parser/parse_texture.h b/libopenage/renderer/resources/parser/parse_texture.h index 52a6eb3640..3000ce3b47 100644 --- a/libopenage/renderer/resources/parser/parse_texture.h +++ b/libopenage/renderer/resources/parser/parse_texture.h @@ -2,14 +2,17 @@ #pragma once +#include + #include "renderer/resources/texture_info.h" -#include "util/path.h" -namespace openage::renderer { -class Renderer; -class Texture2d; -namespace resources::parser { +namespace openage { +namespace util { +class Path; +} + +namespace renderer::resources::parser { /** * Containers for the raw data. @@ -44,5 +47,5 @@ struct SubtextureData { */ Texture2dInfo parse_texture_file(const util::Path &file); -} // namespace resources::parser -} // namespace openage::renderer +} // namespace renderer::resources::parser +} // namespace openage diff --git a/libopenage/renderer/resources/shader_source.cpp b/libopenage/renderer/resources/shader_source.cpp index 0dcf38a39b..60e6b102e0 100644 --- a/libopenage/renderer/resources/shader_source.cpp +++ b/libopenage/renderer/resources/shader_source.cpp @@ -1,25 +1,24 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #include "shader_source.h" -#include "../../util/file.h" +#include + +#include "util/file.h" +#include "util/path.h" namespace openage { namespace renderer { namespace resources { -ShaderSource::ShaderSource(shader_lang_t lang, shader_stage_t stage, std::string &&code) - : lang(lang) - , stage(stage) - , code(std::move(code)) {} +ShaderSource::ShaderSource(shader_lang_t lang, shader_stage_t stage, std::string &&code) : + lang(lang), stage(stage), code(std::move(code)) {} -ShaderSource::ShaderSource(shader_lang_t lang, shader_stage_t stage, const util::Path& path) - : lang(lang) - , stage(stage) - , code(path.open().read()) {} +ShaderSource::ShaderSource(shader_lang_t lang, shader_stage_t stage, const util::Path &path) : + lang(lang), stage(stage), code(path.open().read()) {} -std::string const& ShaderSource::get_source() const { +std::string const &ShaderSource::get_source() const { return this->code; } @@ -31,4 +30,6 @@ shader_stage_t ShaderSource::get_stage() const { return this->stage; } -}}} // openage::renderer::resources +} // namespace resources +} // namespace renderer +} // namespace openage diff --git a/libopenage/renderer/resources/shader_source.h b/libopenage/renderer/resources/shader_source.h index 1008569d9e..1467a306bf 100644 --- a/libopenage/renderer/resources/shader_source.h +++ b/libopenage/renderer/resources/shader_source.h @@ -1,13 +1,14 @@ -// Copyright 2015-2018 the openage authors. See copying.md for legal info. +// Copyright 2015-2023 the openage authors. See copying.md for legal info. #pragma once #include -#include "../../util/path.h" - namespace openage { +namespace util { +class Path; +} namespace renderer { namespace resources { @@ -37,7 +38,7 @@ class ShaderSource { /// Returns a view of the shader source code. This might be text /// or binary data. - std::string const& get_source() const; + std::string const &get_source() const; /// Returns the language of this shader source. shader_lang_t get_lang() const; @@ -56,4 +57,6 @@ class ShaderSource { std::string code; }; -}}} // openage::renderer::resources +} // namespace resources +} // namespace renderer +} // namespace openage diff --git a/libopenage/renderer/resources/terrain/blendpattern_info.h b/libopenage/renderer/resources/terrain/blendpattern_info.h index a5d061a415..6e79b96483 100644 --- a/libopenage/renderer/resources/terrain/blendpattern_info.h +++ b/libopenage/renderer/resources/terrain/blendpattern_info.h @@ -3,12 +3,14 @@ #pragma once #include +#include #include +#include #include -#include "renderer/resources/texture_info.h" namespace openage::renderer::resources { +class Texture2dInfo; struct blending_mask { char directions; diff --git a/libopenage/renderer/resources/terrain/layer_info.cpp b/libopenage/renderer/resources/terrain/layer_info.cpp index aa13966b2c..a93df7ef44 100644 --- a/libopenage/renderer/resources/terrain/layer_info.cpp +++ b/libopenage/renderer/resources/terrain/layer_info.cpp @@ -2,7 +2,11 @@ #include "layer_info.h" +#include +#include + #include "renderer/resources/frame_timing.h" +#include "time/time.h" namespace openage::renderer::resources { @@ -20,8 +24,8 @@ TerrainLayerInfo::TerrainLayerInfo(const std::vectorframes.size(); - curve::time_t t = 0; - std::vector frame_timing; + time::time_t t = 0; + std::vector frame_timing; for (size_t i = 0; i < frame_count; ++i) { frame_timing.push_back(t); t += this->time_per_frame; diff --git a/libopenage/renderer/resources/terrain/layer_info.h b/libopenage/renderer/resources/terrain/layer_info.h index a730e63c05..92edbc0249 100644 --- a/libopenage/renderer/resources/terrain/layer_info.h +++ b/libopenage/renderer/resources/terrain/layer_info.h @@ -8,8 +8,6 @@ namespace openage::renderer::resources { - -class BlendTableInfo; class TerrainFrameInfo; class FrameTiming; diff --git a/libopenage/renderer/resources/terrain/terrain_info.cpp b/libopenage/renderer/resources/terrain/terrain_info.cpp index b08521b44d..724fd146db 100644 --- a/libopenage/renderer/resources/terrain/terrain_info.cpp +++ b/libopenage/renderer/resources/terrain/terrain_info.cpp @@ -2,6 +2,13 @@ #include "terrain_info.h" +#include +#include +#include + +#include "renderer/resources/terrain/layer_info.h" + + namespace openage::renderer::resources { TerrainInfo::TerrainInfo(const float scalefactor, diff --git a/libopenage/renderer/resources/terrain/terrain_info.h b/libopenage/renderer/resources/terrain/terrain_info.h index 76bc179d25..dda22c8e6b 100644 --- a/libopenage/renderer/resources/terrain/terrain_info.h +++ b/libopenage/renderer/resources/terrain/terrain_info.h @@ -2,12 +2,17 @@ #pragma once +#include +#include #include #include "renderer/resources/terrain/layer_info.h" -#include "renderer/resources/texture_info.h" + namespace openage::renderer::resources { +class BlendTableInfo; +class Texture2dInfo; + /** * Contains information about a 2D terrain texture. diff --git a/libopenage/renderer/resources/texture_data.cpp b/libopenage/renderer/resources/texture_data.cpp index 15965dc88c..0e765b61d7 100644 --- a/libopenage/renderer/resources/texture_data.cpp +++ b/libopenage/renderer/resources/texture_data.cpp @@ -2,11 +2,18 @@ #include "texture_data.h" +#include +#include +#include +#include + #include -#include "../../error/error.h" -#include "../../log/log.h" -#include "../../util/csv.h" +#include "error/error.h" +#include "log/log.h" +#include "renderer/resources/texture_info.h" +#include "renderer/resources/texture_subinfo.h" +#include "util/path.h" namespace openage::renderer::resources { diff --git a/libopenage/renderer/resources/texture_data.h b/libopenage/renderer/resources/texture_data.h index 0b0f296c2b..0107959d36 100644 --- a/libopenage/renderer/resources/texture_data.h +++ b/libopenage/renderer/resources/texture_data.h @@ -2,15 +2,22 @@ #pragma once +#include #include -#include +#include #include -#include "../../util/path.h" +#include "error/error.h" +#include "log/message.h" + #include "texture_info.h" -namespace openage::renderer::resources { +namespace openage { +namespace util { +class Path; +} +namespace renderer::resources { /// Stores 2D texture data in a CPU-accessible byte buffer. Provides methods for loading from /// and storing onto disk, as well as sending to and receiving from graphics hardware. @@ -70,4 +77,5 @@ class Texture2dData { std::vector data; }; -} // namespace openage::renderer::resources +} // namespace renderer::resources +} // namespace openage diff --git a/libopenage/renderer/resources/texture_info.cpp b/libopenage/renderer/resources/texture_info.cpp index 6a65cf729f..dfe3c573e7 100644 --- a/libopenage/renderer/resources/texture_info.cpp +++ b/libopenage/renderer/resources/texture_info.cpp @@ -2,6 +2,11 @@ #include "texture_info.h" +#include + +#include "error/error.h" +#include "log/message.h" + namespace openage::renderer::resources { diff --git a/libopenage/renderer/resources/texture_info.h b/libopenage/renderer/resources/texture_info.h index 4f706bb517..f51f34ed73 100644 --- a/libopenage/renderer/resources/texture_info.h +++ b/libopenage/renderer/resources/texture_info.h @@ -2,12 +2,13 @@ #pragma once +#include #include #include +#include +#include #include -#include - #include "datastructure/constexpr_map.h" #include "renderer/resources/texture_subinfo.h" #include "util/path.h" diff --git a/libopenage/renderer/shader_program.h b/libopenage/renderer/shader_program.h index 912b736f8d..594f66dbc6 100644 --- a/libopenage/renderer/shader_program.h +++ b/libopenage/renderer/shader_program.h @@ -2,10 +2,10 @@ #pragma once +#include #include #include #include -#include #include @@ -15,7 +15,6 @@ namespace openage { namespace renderer { - class Texture2d; class UniformBuffer; diff --git a/libopenage/renderer/stages/camera/manager.h b/libopenage/renderer/stages/camera/manager.h index cddd8dc1ff..342b4bd8ef 100644 --- a/libopenage/renderer/stages/camera/manager.h +++ b/libopenage/renderer/stages/camera/manager.h @@ -4,10 +4,8 @@ #include -#include namespace openage::renderer { -class Renderer; class UniformBufferInput; namespace camera { diff --git a/libopenage/renderer/stages/terrain/terrain_mesh.cpp b/libopenage/renderer/stages/terrain/terrain_mesh.cpp index 3e00f126cc..1085e315d4 100644 --- a/libopenage/renderer/stages/terrain/terrain_mesh.cpp +++ b/libopenage/renderer/stages/terrain/terrain_mesh.cpp @@ -2,9 +2,14 @@ #include "terrain_mesh.h" +#include +#include +#include + #include "renderer/resources/assets/asset_manager.h" #include "renderer/resources/assets/texture_manager.h" #include "renderer/resources/terrain/terrain_info.h" +#include "renderer/resources/texture_info.h" #include "renderer/uniform_input.h" @@ -54,7 +59,7 @@ void TerrainRenderMesh::set_terrain_path(const curve::Discrete &ter })); } -void TerrainRenderMesh::update_uniforms(const curve::time_t &time) { +void TerrainRenderMesh::update_uniforms(const time::time_t &time) { // TODO: Only update uniforms that changed since last update if (this->uniforms == nullptr) [[unlikely]] { return; diff --git a/libopenage/renderer/stages/terrain/terrain_mesh.h b/libopenage/renderer/stages/terrain/terrain_mesh.h index 3e81d4d7eb..a571007204 100644 --- a/libopenage/renderer/stages/terrain/terrain_mesh.h +++ b/libopenage/renderer/stages/terrain/terrain_mesh.h @@ -3,18 +3,16 @@ #pragma once #include -#include -#include +#include #include #include "curve/discrete.h" #include "renderer/resources/mesh_data.h" +#include "time/time.h" + namespace openage::renderer { -class Geometry; -class Renderer; -class Texture2d; class UniformInput; namespace resources { @@ -23,7 +21,6 @@ class TerrainInfo; } // namespace resources namespace terrain { -class TerrainRenderEntity; /** * Drawable chunk of terrain with a single texture. @@ -94,7 +91,7 @@ class TerrainRenderMesh { * * @param time Current simulation time. */ - void update_uniforms(const curve::time_t &time = 0.0); + void update_uniforms(const time::time_t &time = 0.0); /** * Check whether a new renderable needs to be created for this mesh. diff --git a/libopenage/renderer/stages/terrain/terrain_model.cpp b/libopenage/renderer/stages/terrain/terrain_model.cpp index 24991eae4c..d663b19dae 100644 --- a/libopenage/renderer/stages/terrain/terrain_model.cpp +++ b/libopenage/renderer/stages/terrain/terrain_model.cpp @@ -2,13 +2,21 @@ #include "terrain_model.h" -#include "renderer/camera/camera.h" +#include +#include +#include +#include + +#include + +#include "coord/scene.h" #include "renderer/resources/assets/asset_manager.h" -#include "renderer/resources/assets/texture_manager.h" -#include "renderer/resources/terrain/terrain_info.h" +#include "renderer/resources/mesh_data.h" #include "renderer/stages/terrain/terrain_mesh.h" #include "renderer/stages/terrain/terrain_render_entity.h" -#include "renderer/uniform_input.h" +#include "util/fixed_point.h" +#include "util/vector.h" + namespace openage::renderer::terrain { @@ -43,7 +51,7 @@ void TerrainRenderModel::fetch_updates() { this->render_entity->clear_changed_flag(); } -void TerrainRenderModel::update_uniforms(const curve::time_t &time) { +void TerrainRenderModel::update_uniforms(const time::time_t &time) { for (auto &mesh : this->meshes) { mesh->update_uniforms(time); } diff --git a/libopenage/renderer/stages/terrain/terrain_model.h b/libopenage/renderer/stages/terrain/terrain_model.h index dcf4e123c3..4a1ec15aed 100644 --- a/libopenage/renderer/stages/terrain/terrain_model.h +++ b/libopenage/renderer/stages/terrain/terrain_model.h @@ -3,10 +3,10 @@ #pragma once #include +#include -#include +#include "time/time.h" -#include "curve/discrete.h" namespace openage::renderer { @@ -55,7 +55,7 @@ class TerrainRenderModel { * * @param time Current simulation time. */ - void update_uniforms(const curve::time_t &time = 0.0); + void update_uniforms(const time::time_t &time = 0.0); /** * Get the meshes composing the terrain. diff --git a/libopenage/renderer/stages/terrain/terrain_render_entity.cpp b/libopenage/renderer/stages/terrain/terrain_render_entity.cpp index 3aae26644e..a142461cb0 100644 --- a/libopenage/renderer/stages/terrain/terrain_render_entity.cpp +++ b/libopenage/renderer/stages/terrain/terrain_render_entity.cpp @@ -2,9 +2,10 @@ #include "terrain_render_entity.h" -#include "renderer/renderer.h" -#include "renderer/resources/texture_data.h" -#include "renderer/texture.h" +#include +#include +#include + namespace openage::renderer::terrain { @@ -18,7 +19,7 @@ TerrainRenderEntity::TerrainRenderEntity() : void TerrainRenderEntity::update(util::Vector2s size, std::vector height_map, const std::string terrain_path, - const curve::time_t time) { + const time::time_t time) { std::unique_lock lock{this->mutex}; // increase by 1 in every dimension because height_map diff --git a/libopenage/renderer/stages/terrain/terrain_render_entity.h b/libopenage/renderer/stages/terrain/terrain_render_entity.h index 3081fc711c..2d074e2590 100644 --- a/libopenage/renderer/stages/terrain/terrain_render_entity.h +++ b/libopenage/renderer/stages/terrain/terrain_render_entity.h @@ -4,12 +4,15 @@ #include #include +#include #include #include "coord/scene.h" #include "curve/discrete.h" +#include "time/time.h" #include "util/vector.h" + namespace openage::renderer { namespace terrain { @@ -31,7 +34,7 @@ class TerrainRenderEntity { void update(util::Vector2s size, std::vector height_map, const std::string terrain_path, - const curve::time_t time = 0.0); + const time::time_t time = 0.0); /** * Get the vertices of the terrain. diff --git a/libopenage/renderer/stages/terrain/terrain_renderer.cpp b/libopenage/renderer/stages/terrain/terrain_renderer.cpp index 573bcc06f1..1b8b2e7a7c 100644 --- a/libopenage/renderer/stages/terrain/terrain_renderer.cpp +++ b/libopenage/renderer/stages/terrain/terrain_renderer.cpp @@ -2,8 +2,6 @@ #include "terrain_renderer.h" - -#include "event/clock.h" #include "renderer/camera/camera.h" #include "renderer/opengl/context.h" #include "renderer/renderer.h" @@ -13,6 +11,8 @@ #include "renderer/stages/terrain/terrain_mesh.h" #include "renderer/stages/terrain/terrain_model.h" #include "renderer/window.h" +#include "time/clock.h" + namespace openage::renderer::terrain { @@ -21,7 +21,7 @@ TerrainRenderer::TerrainRenderer(const std::shared_ptr &window, const std::shared_ptr &camera, const util::Path &shaderdir, const std::shared_ptr &asset_manager, - const std::shared_ptr &clock) : + const std::shared_ptr &clock) : renderer{renderer}, camera{camera}, render_entity{nullptr}, diff --git a/libopenage/renderer/stages/terrain/terrain_renderer.h b/libopenage/renderer/stages/terrain/terrain_renderer.h index 5941cfece0..286567c34a 100644 --- a/libopenage/renderer/stages/terrain/terrain_renderer.h +++ b/libopenage/renderer/stages/terrain/terrain_renderer.h @@ -8,7 +8,8 @@ #include "util/path.h" namespace openage { -namespace event { + +namespace time { class Clock; } @@ -42,7 +43,7 @@ class TerrainRenderer { const std::shared_ptr &camera, const util::Path &shaderdir, const std::shared_ptr &asset_manager, - const std::shared_ptr &clock); + const std::shared_ptr &clock); ~TerrainRenderer() = default; /** @@ -121,7 +122,7 @@ class TerrainRenderer { /** * Simulation clock for timing animations. */ - std::shared_ptr clock; + std::shared_ptr clock; /** * Output texture. diff --git a/libopenage/renderer/stages/world/world_object.cpp b/libopenage/renderer/stages/world/world_object.cpp index 44c49fae0e..918578b4f0 100644 --- a/libopenage/renderer/stages/world/world_object.cpp +++ b/libopenage/renderer/stages/world/world_object.cpp @@ -2,6 +2,12 @@ #include "world_object.h" +#include +#include +#include +#include +#include + #include #include "renderer/camera/camera.h" @@ -9,13 +15,17 @@ #include "renderer/resources/animation/angle_info.h" #include "renderer/resources/animation/animation_info.h" #include "renderer/resources/animation/frame_info.h" +#include "renderer/resources/animation/layer_info.h" #include "renderer/resources/assets/asset_manager.h" #include "renderer/resources/assets/texture_manager.h" #include "renderer/resources/frame_timing.h" #include "renderer/resources/mesh_data.h" -#include "renderer/resources/texture_data.h" +#include "renderer/resources/texture_info.h" +#include "renderer/resources/texture_subinfo.h" #include "renderer/stages/world/world_render_entity.h" #include "renderer/uniform_input.h" +#include "util/fixed_point.h" +#include "util/vector.h" namespace openage::renderer::world { @@ -43,7 +53,7 @@ void WorldObject::set_camera(const std::shared_ptr &ca this->camera = camera; } -void WorldObject::fetch_updates(const curve::time_t &time) { +void WorldObject::fetch_updates(const time::time_t &time) { if (not this->render_entity->is_changed()) { // exit early because there is nothing to do return; @@ -72,7 +82,7 @@ void WorldObject::fetch_updates(const curve::time_t &time) { this->last_update = time; } -void WorldObject::update_uniforms(const curve::time_t &time) { +void WorldObject::update_uniforms(const time::time_t &time) { // TODO: Only update uniforms that changed since last update if (this->uniforms == nullptr) [[unlikely]] { return; diff --git a/libopenage/renderer/stages/world/world_object.h b/libopenage/renderer/stages/world/world_object.h index 5a87254f86..9c08cddad5 100644 --- a/libopenage/renderer/stages/world/world_object.h +++ b/libopenage/renderer/stages/world/world_object.h @@ -2,16 +2,18 @@ #pragma once +#include +#include #include - -#include +#include #include "coord/scene.h" #include "curve/continuous.h" -#include "curve/curve.h" #include "curve/discrete.h" #include "curve/segmented.h" #include "renderer/resources/mesh_data.h" +#include "time/time.h" + namespace openage::renderer { class UniformInput; @@ -52,14 +54,14 @@ class WorldObject { * * @param time Current simulation time. */ - void fetch_updates(const curve::time_t &time = 0.0); + void fetch_updates(const time::time_t &time = 0.0); /** * Update the uniforms of the renderable associated with this object. * * @param time Current simulation time. */ - void update_uniforms(const curve::time_t &time = 0.0); + void update_uniforms(const time::time_t &time = 0.0); /** * Get the ID of the corresponding game entity. @@ -168,7 +170,7 @@ class WorldObject { /** * Time of the last update call. */ - curve::time_t last_update; + time::time_t last_update; }; } // namespace world } // namespace openage::renderer diff --git a/libopenage/renderer/stages/world/world_render_entity.cpp b/libopenage/renderer/stages/world/world_render_entity.cpp index 3ddf7b8953..8cba90ca40 100644 --- a/libopenage/renderer/stages/world/world_render_entity.cpp +++ b/libopenage/renderer/stages/world/world_render_entity.cpp @@ -2,8 +2,12 @@ #include "world_render_entity.h" +#include +#include + #include "renderer/definitions.h" + namespace openage::renderer::world { WorldRenderEntity::WorldRenderEntity() : @@ -19,7 +23,7 @@ void WorldRenderEntity::update(const uint32_t ref_id, const curve::Continuous &position, const curve::Segmented &angle, const std::string animation_path, - const curve::time_t time) { + const time::time_t time) { std::unique_lock lock{this->mutex}; this->ref_id = ref_id; @@ -40,7 +44,7 @@ void WorldRenderEntity::update(const uint32_t ref_id, void WorldRenderEntity::update(const uint32_t ref_id, const coord::phys3 position, const std::string animation_path, - const curve::time_t time) { + const time::time_t time) { std::unique_lock lock{this->mutex}; this->ref_id = ref_id; @@ -74,7 +78,7 @@ const curve::Discrete &WorldRenderEntity::get_animation_path() { return this->animation_path; } -curve::time_t WorldRenderEntity::get_update_time() { +time::time_t WorldRenderEntity::get_update_time() { std::shared_lock lock{this->mutex}; return this->last_update; diff --git a/libopenage/renderer/stages/world/world_render_entity.h b/libopenage/renderer/stages/world/world_render_entity.h index 25e040fa32..ae656da20d 100644 --- a/libopenage/renderer/stages/world/world_render_entity.h +++ b/libopenage/renderer/stages/world/world_render_entity.h @@ -2,16 +2,20 @@ #pragma once -#include +#include +#include #include +#include + +#include #include "coord/phys.h" #include "coord/scene.h" #include "curve/continuous.h" -#include "curve/curve.h" #include "curve/discrete.h" #include "curve/segmented.h" -#include "util/path.h" +#include "time/time.h" + namespace openage::renderer::world { @@ -33,7 +37,7 @@ class WorldRenderEntity { const curve::Continuous &position, const curve::Segmented &angle, const std::string animation_path, - const curve::time_t time = 0.0); + const time::time_t time = 0.0); /** * Thus function is for DEBUGGING and should not be used. @@ -48,7 +52,7 @@ class WorldRenderEntity { void update(const uint32_t ref_id, const coord::phys3 position, const std::string animation_path, - const curve::time_t time = 0.0); + const time::time_t time = 0.0); /** * Get the ID of the corresponding game entity. @@ -83,7 +87,7 @@ class WorldRenderEntity { * * @return Time of last update. */ - curve::time_t get_update_time(); + time::time_t get_update_time(); /** * Check whether the render entity has received new updates from the @@ -129,7 +133,7 @@ class WorldRenderEntity { /** * Time of the last update call. */ - curve::time_t last_update; + time::time_t last_update; /** * Mutex for protecting threaded access. diff --git a/libopenage/renderer/stages/world/world_renderer.cpp b/libopenage/renderer/stages/world/world_renderer.cpp index 478ae74ba1..5882ef83d8 100644 --- a/libopenage/renderer/stages/world/world_renderer.cpp +++ b/libopenage/renderer/stages/world/world_renderer.cpp @@ -2,7 +2,6 @@ #include "world_renderer.h" -#include "event/clock.h" #include "renderer/camera/camera.h" #include "renderer/opengl/context.h" #include "renderer/resources/assets/asset_manager.h" @@ -12,6 +11,8 @@ #include "renderer/stages/world/world_object.h" #include "renderer/texture.h" #include "renderer/window.h" +#include "time/clock.h" + namespace openage::renderer::world { @@ -20,7 +21,7 @@ WorldRenderer::WorldRenderer(const std::shared_ptr &window, const std::shared_ptr &camera, const util::Path &shaderdir, const std::shared_ptr &asset_manager, - const std::shared_ptr clock) : + const std::shared_ptr clock) : renderer{renderer}, camera{camera}, asset_manager{asset_manager}, diff --git a/libopenage/renderer/stages/world/world_renderer.h b/libopenage/renderer/stages/world/world_renderer.h index b20eaa3771..0dc7195ebe 100644 --- a/libopenage/renderer/stages/world/world_renderer.h +++ b/libopenage/renderer/stages/world/world_renderer.h @@ -10,7 +10,7 @@ namespace openage { -namespace event { +namespace time { class Clock; } @@ -44,7 +44,7 @@ class WorldRenderer { const std::shared_ptr &camera, const util::Path &shaderdir, const std::shared_ptr &asset_manager, - const std::shared_ptr clock); + const std::shared_ptr clock); ~WorldRenderer() = default; /** @@ -122,7 +122,7 @@ class WorldRenderer { /** * Simulation clock for timing animations. */ - std::shared_ptr clock; + std::shared_ptr clock; /** * Default geometry for every world object. diff --git a/libopenage/renderer/texture_array.h b/libopenage/renderer/texture_array.h index 491be5f4d5..ccc19df0a9 100644 --- a/libopenage/renderer/texture_array.h +++ b/libopenage/renderer/texture_array.h @@ -1,8 +1,11 @@ -// Copyright 2018-2018 the openage authors. See copying.md for legal info. +// Copyright 2018-2023 the openage authors. See copying.md for legal info. #pragma once -#include "resources/texture_data.h" +#include + +#include "renderer/resources/texture_data.h" +#include "renderer/resources/texture_info.h" namespace openage { @@ -16,19 +19,20 @@ class Texture2dArray { virtual ~Texture2dArray(); /// Returns information about the layer format. - resources::Texture2dInfo const& get_info() const; + resources::Texture2dInfo const &get_info() const; /// Uploads the given texture data into the specified layer. `layer` must /// be strictly less than the size of the array and the data format must /// match the format this array was originally created with. - virtual void upload(size_t layer, resources::Texture2dData const&) = 0; + virtual void upload(size_t layer, resources::Texture2dData const &) = 0; protected: /// Constructs the base class. - Texture2dArray(const resources::Texture2dInfo&); + Texture2dArray(const resources::Texture2dInfo &); /// Information about the size, format, etc. of every layer in this array. resources::Texture2dInfo layer_info; }; -}} // openage::renderer +} // namespace renderer +} // namespace openage diff --git a/libopenage/renderer/uniform_buffer.h b/libopenage/renderer/uniform_buffer.h index dc642b7040..2ba5790127 100644 --- a/libopenage/renderer/uniform_buffer.h +++ b/libopenage/renderer/uniform_buffer.h @@ -2,15 +2,17 @@ #pragma once +#include #include #include #include "renderer/uniform_input.h" -namespace openage::renderer { +namespace openage::renderer { class Texture2d; +class UniformBufferInput; class UniformBuffer : public std::enable_shared_from_this { friend UniformBufferInput; diff --git a/libopenage/renderer/uniform_input.h b/libopenage/renderer/uniform_input.h index 8a52fc3e6e..85b197e4fa 100644 --- a/libopenage/renderer/uniform_input.h +++ b/libopenage/renderer/uniform_input.h @@ -1,17 +1,18 @@ // Copyright 2019-2023 the openage authors. See copying.md for legal info. - #pragma once +#include #include #include -#include "../error/error.h" +#include "error/error.h" +#include "log/message.h" +#include "util/compiler.h" namespace openage::renderer { - class ShaderProgram; class Texture2d; class UniformBuffer; diff --git a/libopenage/renderer/util.cpp b/libopenage/renderer/util.cpp index d9c5fcfe1d..3cb3995790 100644 --- a/libopenage/renderer/util.cpp +++ b/libopenage/renderer/util.cpp @@ -1,22 +1,19 @@ -// Copyright 2018-2019 the openage authors. See copying.md for legal info. - +// Copyright 2018-2023 the openage authors. See copying.md for legal info. #include "util.h" +#include + namespace openage::renderer::util { -Eigen::Matrix4d ortho_matrix_d(double left, double right, - double bottom, double top, - double near, double far) { +Eigen::Matrix4d ortho_matrix_d(double left, double right, double bottom, double top, double near, double far) { return ortho_matrix(left, right, bottom, top, near, far); } -Eigen::Matrix4f ortho_matrix_f(float left, float right, - float bottom, float top, - float near, float far) { +Eigen::Matrix4f ortho_matrix_f(float left, float right, float bottom, float top, float near, float far) { return ortho_matrix(left, right, bottom, top, near, far); } -} // openage::renderer::util +} // namespace openage::renderer::util diff --git a/libopenage/renderer/window_event_handler.cpp b/libopenage/renderer/window_event_handler.cpp index 52cd317aae..8f83ff3eaf 100644 --- a/libopenage/renderer/window_event_handler.cpp +++ b/libopenage/renderer/window_event_handler.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2022 the openage authors. See copying.md for legal info. +// Copyright 2022-2023 the openage authors. See copying.md for legal info. #include "window_event_handler.h" @@ -10,7 +10,7 @@ namespace openage::renderer { -bool WindowEventHandler::eventFilter(QObject *obj, QEvent *event) { +bool WindowEventHandler::eventFilter(QObject * /* obj */, QEvent *event) { auto add_to_queue = [this, event]() { this->event_queue.push_back(std::shared_ptr(event->clone())); }; diff --git a/libopenage/time/CMakeLists.txt b/libopenage/time/CMakeLists.txt new file mode 100644 index 0000000000..2a9475a66d --- /dev/null +++ b/libopenage/time/CMakeLists.txt @@ -0,0 +1,5 @@ +add_sources(libopenage + clock.cpp + time.cpp + time_loop.cpp +) diff --git a/libopenage/event/clock.cpp b/libopenage/time/clock.cpp similarity index 96% rename from libopenage/event/clock.cpp rename to libopenage/time/clock.cpp index 1bf368e870..ca4bf7e7db 100644 --- a/libopenage/event/clock.cpp +++ b/libopenage/time/clock.cpp @@ -7,7 +7,7 @@ #include "log/log.h" -namespace openage::event { +namespace openage::time { Clock::Clock() : state{ClockState::INIT}, @@ -50,14 +50,14 @@ void Clock::update_time() { } } -curve::time_t Clock::get_time() { +time::time_t Clock::get_time() { std::shared_lock lock{this->mutex}; // convert time unit from milliseconds to seconds return this->sim_time / 1000; } -curve::time_t Clock::get_real_time() { +time::time_t Clock::get_real_time() { std::shared_lock lock{this->mutex}; // convert time unit from milliseconds to seconds @@ -126,4 +126,4 @@ void Clock::resume() { << this->sim_real_time << "ms (real)"); } -} // namespace openage::event +} // namespace openage::time diff --git a/libopenage/event/clock.h b/libopenage/time/clock.h similarity index 93% rename from libopenage/event/clock.h rename to libopenage/time/clock.h index f58c6d3d16..1021f599cd 100644 --- a/libopenage/event/clock.h +++ b/libopenage/time/clock.h @@ -5,9 +5,10 @@ #include #include -#include "curve/curve.h" +#include "time/time.h" -namespace openage::event { + +namespace openage::time { using simclock_t = std::chrono::steady_clock; using timepoint_t = std::chrono::time_point; @@ -54,7 +55,7 @@ class Clock { * * @return Time passed (in seconds). */ - curve::time_t get_time(); + time::time_t get_time(); /** * Get the current simulation time without speed adjustments. @@ -64,7 +65,7 @@ class Clock { * * @return Time passed (in seconds). */ - curve::time_t get_real_time(); + time::time_t get_real_time(); /** * Get the current speed of the clock. @@ -135,13 +136,13 @@ class Clock { /** * Stores how much time has passed inside the simulation (in milliseconds). */ - curve::time_t sim_time; + time::time_t sim_time; /** * Stores how much time has passed inside the simulation (in milliseconds) * _without_ speed adjustments (i.e. it acts as if speed = 1.0). */ - curve::time_t sim_real_time; + time::time_t sim_real_time; /** * Mutex for protecting threaded access. @@ -149,4 +150,4 @@ class Clock { std::shared_mutex mutex; }; -} // namespace openage::event +} // namespace openage::time diff --git a/libopenage/time/time.cpp b/libopenage/time/time.cpp new file mode 100644 index 0000000000..a9e1d4edb2 --- /dev/null +++ b/libopenage/time/time.cpp @@ -0,0 +1,10 @@ +// Copyright 2017-2023 the openage authors. See copying.md for legal info. + +#include "time.h" + + +namespace openage::time { + +// This file is intended to be empty + +} // namespace openage::time diff --git a/libopenage/curve/curve.h b/libopenage/time/time.h similarity index 58% rename from libopenage/curve/curve.h rename to libopenage/time/time.h index 381ce727b3..a6851f679c 100644 --- a/libopenage/curve/curve.h +++ b/libopenage/time/time.h @@ -1,13 +1,13 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2023 the openage authors. See copying.md for legal info. #pragma once #include -#include "../util/fixed_point.h" +#include "util/fixed_point.h" -namespace openage::curve { +namespace openage::time { /** * Defines the type that is used as time index. @@ -15,4 +15,4 @@ namespace openage::curve { */ using time_t = util::FixedPoint; -} // openage::curve +} // namespace openage::time diff --git a/libopenage/event/time_loop.cpp b/libopenage/time/time_loop.cpp similarity index 91% rename from libopenage/event/time_loop.cpp rename to libopenage/time/time_loop.cpp index 6b50e63d19..ffc7fd6efd 100644 --- a/libopenage/event/time_loop.cpp +++ b/libopenage/time/time_loop.cpp @@ -4,10 +4,11 @@ #include -#include "event/clock.h" #include "log/log.h" +#include "time/clock.h" -namespace openage::event { + +namespace openage::time { TimeLoop::TimeLoop() : running{false}, @@ -51,4 +52,4 @@ const std::shared_ptr TimeLoop::get_clock() { return this->clock; } -} // namespace openage::event +} // namespace openage::time diff --git a/libopenage/event/time_loop.h b/libopenage/time/time_loop.h similarity index 89% rename from libopenage/event/time_loop.h rename to libopenage/time/time_loop.h index a5b990cb2b..0611b5b30e 100644 --- a/libopenage/event/time_loop.h +++ b/libopenage/time/time_loop.h @@ -5,13 +5,12 @@ #include #include -namespace openage { -namespace event { +namespace openage::time { class Clock; /** - * Manage event loop and clock. + * Manage and update internal time via a clock. */ class TimeLoop { public: @@ -68,5 +67,4 @@ class TimeLoop { }; -} // namespace event -} // namespace openage +} // namespace openage::time diff --git a/openage/convert/entity_object/export/formats/modpack_info.py b/openage/convert/entity_object/export/formats/modpack_info.py index 143a261f81..1a6017ce4e 100644 --- a/openage/convert/entity_object/export/formats/modpack_info.py +++ b/openage/convert/entity_object/export/formats/modpack_info.py @@ -10,7 +10,7 @@ from ..data_definition import DataDefinition -FILE_VERSION = "1" +FILE_VERSION = "2" class ModpackInfo(DataDefinition): @@ -25,6 +25,7 @@ def __init__(self, targetdir: str, filename: str): # Info self.packagename: str = None self.version: str = None + self.versionstr: str = None self.extra_info: dict[str, str] = {} # Assets @@ -153,6 +154,7 @@ def set_info( self, packagename: str, version: str, + versionstr: str = None, repo: str = None, alias: str = None, title: str = None, @@ -166,8 +168,10 @@ def set_info( :param packagename: Name of the modpack. :type packagename: str - :param version: Version number. + :param version: Internal version number. Must have semver format. :type version: str + :param versionstr: Human-readable version number. + :type versionstr: str :param repo: Name of the repo where the package is hosted. :type repo: str :param alias: Alias of the modpack. @@ -186,6 +190,9 @@ def set_info( self.packagename = packagename self.version = version + if versionstr: + self.extra_info["versionstr"] = versionstr + if repo: self.extra_info["repo"] = repo diff --git a/openage/convert/processor/conversion/aoc/modpack_subprocessor.py b/openage/convert/processor/conversion/aoc/modpack_subprocessor.py index cd365d1a51..8d54d68fed 100644 --- a/openage/convert/processor/conversion/aoc/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/aoc/modpack_subprocessor.py @@ -44,7 +44,7 @@ def _get_aoe2_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("aoe2_base", "1.0c", repo="openage") + mod_def.set_info("aoe2_base", "0.5", versionstr="1.0c", repo="openage") mod_def.add_include("data/**") diff --git a/openage/convert/processor/conversion/de2/modpack_subprocessor.py b/openage/convert/processor/conversion/de2/modpack_subprocessor.py index 13c20cca53..22d9d220e2 100644 --- a/openage/convert/processor/conversion/de2/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/de2/modpack_subprocessor.py @@ -40,7 +40,7 @@ def _get_aoe2_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("de2_base", "1.0c", repo="openage") + mod_def.set_info("de2_base", "0.5", versionstr="1.0c", repo="openage") mod_def.add_include("data/**") diff --git a/openage/convert/processor/conversion/hd/modpack_subprocessor.py b/openage/convert/processor/conversion/hd/modpack_subprocessor.py index e491660107..50e77ba711 100644 --- a/openage/convert/processor/conversion/hd/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/hd/modpack_subprocessor.py @@ -40,7 +40,7 @@ def _get_aoe2_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("hd_base", "5.8", repo="openage") + mod_def.set_info("hd_base", "0.5", versionstr="5.8", repo="openage") mod_def.add_include("data/**") diff --git a/openage/convert/processor/conversion/ror/modpack_subprocessor.py b/openage/convert/processor/conversion/ror/modpack_subprocessor.py index 0269f7da92..dfe485b003 100644 --- a/openage/convert/processor/conversion/ror/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/ror/modpack_subprocessor.py @@ -41,7 +41,7 @@ def _get_aoe1_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("aoe1_base", "1.0a", repo="openage") + mod_def.set_info("aoe1_base", "0.5", versionstr="1.0a", repo="openage") mod_def.add_include("data/**") diff --git a/openage/convert/processor/conversion/swgbcc/modpack_subprocessor.py b/openage/convert/processor/conversion/swgbcc/modpack_subprocessor.py index bc50d080c7..cef278f9eb 100644 --- a/openage/convert/processor/conversion/swgbcc/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/swgbcc/modpack_subprocessor.py @@ -40,7 +40,7 @@ def _get_swgb_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("swgb_base", "1.1-gog4", repo="openage") + mod_def.set_info("swgb_base", "0.5", versionstr="1.1-gog4", repo="openage") mod_def.add_include("data/**")