<br><br>

<div style="width: 100%;">
<img src="./logo/raster.png" width="128px" style="display: block; margin-left: auto; margin-right: auto;"/>
<h1 style="text-align: center; top:-1em;">fennec</h1>
<div style="text-align: center; top:-4em;">a free and open source game engine</div>
</div>

<br><br>

## Table of Contents

 1. [Introduction](#introduction)
    1. [Coding Standards](#coding-standards)
 2. [Building from Source](#building-from-source)
    1. [Building from Terminal](#building-from-terminal)
    2. [Building on Windows](#building-on-windows)
 3. [Running the Test Suite](#running-the-test-suite)
 4. [Usage](#usage)
 5. [Contribution](#contribution)
 6. [Documentation](./documentation.html)

<br>
<br>


<a id="introduction"></a>
## Introduction

&ensp; fennec is designed to be a general purpose, educational game engine. fennec  
may be used through the provided editor application, or as a standalone library to   
link against your application.



<br>

<a id="coding-standards"></a>
### Coding Standards

Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html).  
Some main areas where the engine strays from the GNU standard includes the following:

* [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
  fennec provides an implementation for X11, however it does not use the GTK toolkit.
- [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
  fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section.
* [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
  fennec follows most of the conventions in this section, however the build system used is CMake and not  
  Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.

<br>

fennec Standards:

 * As per the GNU standard, macros should be `SCREAMING_SNAKE_CASE`. Additionally, Macros should be preceded by `<APP_NAME>_`.  
   Macros that wrap C-Style functions may use normal `snake_case`.

 - Header Guards should be implemented using `#ifndef`, `#define`, and `#endif` for portability.  
   The naming convention for Header Guards is as follows: `<APP_NAME>_<DIRECTORY_PATH>_<FILE_NAME>_H`.  
   I.E. the engine file `fennec/lang/utility.h` has the Header Guard `FENNEC_LANG_UTILITY_H`.  

 * Helper Functions, in the case of classes, should be private.  
   In the case of global functions, helpers should be placed in a similarly named file in a subdirectory and namespace  
   called `detail`. Helper functions should be documented with C-Style comments, however it is not necessary to provide  
   Doxygen documentation.

 - **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate.<sup>[[1]](#f1)</sup>

 * Most behaviours should be type independent. Specifically interactions with the core systems of the engine.

<br><br>

<a id="f1"></a>
<sup>[1]</sup> Okay, I will elaborate. If we were to use the exception paradigm for all erroneous behaviour, we couldn't  
                     guarantee that the state will not be corrupted when an exception is thrown. The behaviour afterward is  
                     undefined because of this, and we also don't really know when, how, or where that exception will be handled.  
                     The assertion paradigm is better at handling this because you are defining erroneous behaviour in the code and how   
                     it is handled. In a debug build we can immediately halt the program, we don't care about the state afterward, only  
                     beforehand. Now for a release build, this is first and foremost a game engine, so we want to crash as gracefully as  
                     possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to  
                     be used, defining a hook in the private version of the function. This hook is used to clean up any state information  
                     within the engine and may be used to send immediate events to listeners so that outside functionality may decide  
                     how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon  
                     as the branch finishes, `abort()` will be called.
    

<br>

The C++ stdlib is reimplemented in the fennec engine. 
There are a few reasons for this:

 1. Standardize implementations across compilers
 2. Set proper naming conventions, i.e. `std::vector` &rarr; `fennec::dynarray`
 3. Optimize compilation times, binary size, and performance.
 4. Inject debugging information when necessary.
 5. Expose functionality in a readable manner for those interested in learning the
    intricacies of the implementation.

<br>


<a id="building-from-source"></a>
## Building from Source

&ensp; fennec uses the CMake build manager. The CMake build script provides several  
targets for building parts of the engine.

&ensp; Using an IDE will streamline the build process for you and add additional configuration  
options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode  
is also a viable IDE but involves some extra setup.

| Target                 | Description                                                                            |
|------------------------|----------------------------------------------------------------------------------------|
| fennec                 | The main engine target.                                                                |
| fennec-metaprogramming | Generate metaprogramming info for the fennec library. A dependency of the main engine. |
| fennecdocs             | Generate html documentation for the engine. Requires Doxygen.                          |
| fennecdocs-clean       | Cleans the generated html documentation files.                                         |
| fennec-test            | Test suite for verifying engine functionality.                                         |

<a id="dependencies"></a>

| Dependency        | Notes                                                                                                    |
|-------------------|----------------------------------------------------------------------------------------------------------|
| C/C++ Compiler    | GCC/G++ is the compiler that fennec is designed around, however, Clang, MSVC, and MinGW may also be used |
| CMake             | The build manager used by the engine                                                                     |
| A build system    | Any build system will work, however, `build.sh` uses Ninja by default.                                   |
| A memory debugger | Any memory debugger will work, however, `test.sh` uses Valgrind by default.                              |
| Doxygen           | Doxygen is required for building the documentation for fennec. This is an optional dependency            |
| Graphviz          | Graphviz is a required dependency for Doxygen                                                            |

<br>

<a id="building-from-terminal"></a>
### Building from Terminal

`build.sh` provides profiles for building the main engine. Run `./build.sh --help`
for more info.

&ensp; By default, the CMake generator used is Ninja, which requires Ninja to be installed. You can modify the  
build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).

<br>

<a id="building-on-windows"></a>
### Building on Windows

&ensp; The bash script can be run natively on Windows when WSL is enabled. You do not need to run the  
script in WSL, simply use the "bash" command in Command Prompt or PowerShell.  The script will require  
the build [dependencies](#dependencies) installed and configured to be available on the `PATH` environment variable.

Fore more details, [see this blog post](https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/) for Windows Build 14316.

Otherwise, follow the sequence of commands provided in the bash script.

```console
mkdir -p build/<profile>
cd ./build/<profile>
cmake -G Ninja -DCMAKE_BUILD_TYPE=<profile> -S ../.. -B .
cmake --build . --target fennec
```

The value of `<profile>` may be one of the following:

| Profile        | Description                                                                      |
|----------------|----------------------------------------------------------------------------------|
| Debug          | Build in debug mode, provides full debugging information to use with a debugger. |
| Release        | Build in release mode, provides full optimizations, eliminating debug info.      |
| RelWithDebInfo | Build in release mode with extra debug info, provides partial optimizations.     |
| MinSizeRel     | Build in release mode but optimizing for minimum binary size.                    |


<br>

&ensp; If you would like to use Visual Studio without CMake, you can use the build script to generate  
a Visual Studio project for the source. For a list of available Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)  
of the CMake docs. Running the following command will generate the Visual Studio project.

```commandline
cmake -G "Visual Studio 17 2022" -A x64
```

<br>
<br>

<a id="running-the-test-suite"></a>
## Running the Test Suite

`test.sh` provides profiles for building the test suite and executes them.

&ensp; By default, the program runs in debug mode and the first failed test will throw an assertion.  
Any tests that involve running as an application will spawn a subprocess with a window, and give  
a short description of the behaviour in the terminal. It will then have you confirm whether the  
information displayed is correct.

<br>
<br>

<a id="usage"></a>
## Usage


### Licensing

The following statement is not legal advice, nor is it legally binding, and nor does it change the terms of the license.

fennec is licensed under GPLv3. The primary reason for the choice of license is to dissuade corporations from modifying  
fennec and using it in a commercial manner. This of course does not bar them from using fennec commercially, however  
it will prevent them from being able to make the derivative work proprietary. You are free to use and redistribute  
fennec however you wish according to the terms of the license, which does not bar you from commercializing software  
based on fennec. 

I encourage those who wish to commercialize derivative works crowdfund rather than use a sales model. I also ask  
that you kindly support me as a developer, I will set up a Buy Me a Coffee link at some point.

GPLv3 is bound by fair use; here is the clause,  17 U.S. Code § 107:

```
107. Limitations on exclusive rights: Fair use

Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by 
reproduction in copies or phonorecords or by any other means specified by that section, for purposes such as criticism, 
comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an 
infringement of copyright. In determining whether the use made of a work in any particular case is a fair use the 
factors to be considered shall include—

 (1) the purpose and character of the use, including whether such use is of a commercial nature or is for nonprofit 
     educational purposes;
 (2) the nature of the copyrighted work;
 (3) the amount and substantiality of the portion used in relation to the copyrighted work as a whole; and
 (4) the effect of the use upon the potential market for or value of the copyrighted work.

The fact that a work is unpublished shall not itself bar a finding of fair use if such finding is made upon 
consideration of all the above factors.
```

If you have any questions or concerns, please seek legal council. If you believe someone else has violated the terms  
of this license, please contact me at [mslockbo@gmail.com](mailto:mslockbo@gmail.com).

<br>
<br>

<a id="contribution"></a>
## Contribution

There are some principles to keep in mind when contributing to fennec. 

 1. You must follow the [standards provided above](#coding-standards).
 2. Any changes must allow all projects to be forward compatible with newer engine versions.
