diff options
author | Danny Holman <dholman@gymli.org> | 2024-10-25 01:49:29 -0500 |
---|---|---|
committer | Danny Holman <dholman@gymli.org> | 2024-10-25 01:49:29 -0500 |
commit | e38d94416f705aa4ddd32e1c51199b45b58d6093 (patch) | |
tree | 88f19d0f17aed3ff5004d28d7c4fa49e28ad08b8 /doc | |
parent | 28e27060274591fe13d5a1a226216fb01141e2f7 (diff) |
doc: add introductory documentation files
Add documentation files that act as the starting points for the rest of
the documentation and introduce a beginner to Rune.
Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'doc')
-rw-r--r-- | doc/coding-style.rst | 284 | ||||
-rw-r--r-- | doc/core/index.rst | 37 | ||||
-rw-r--r-- | doc/dev-process.rst | 43 | ||||
-rw-r--r-- | doc/index.rst | 46 | ||||
-rw-r--r-- | doc/introduction.rst | 43 | ||||
-rw-r--r-- | doc/submitting-patches.rst | 142 |
6 files changed, 595 insertions, 0 deletions
diff --git a/doc/coding-style.rst b/doc/coding-style.rst new file mode 100644 index 0000000..68c2240 --- /dev/null +++ b/doc/coding-style.rst @@ -0,0 +1,284 @@ +Rune Engine coding style +======================== + +This is a short document describing the preferred coding style for the Rune +Engine. This coding style is largely inspired by the Linux kernel coding style, +with some tweaks to make it friendly to modern editors. + +Indentation +----------- + +Tabs are 8 spaces, tab characters should not be used. This makes the code look +the same across editors and systems, and forces developers to simplify their +code wherever possible. Large indentations make each code block easier to +identify at a glance. + +.. code-block:: c + + int main(int argc, char* argv[]) { + if (rune_init(argc, argv) != 0) { + log_output(LOG_FATAL, "Error!"); + return -1; + } + + int running = 1; + while (running) { + // main loop + } + + rune_exit(); + } + +Branch statements should not be placed on the same line; it makes it look like +you have something to hide: + +.. code-block:: c + + if (condition) do_this; + do_something_always; + +Braces should be used on multiple statements: + +.. code-block:: c + + if (condition) { + do_this(); + do_that(); + } + +Assignments should be placed on their own lines. The coding style is very simple +and fancy expressions are frowned upon. + +Long lines +---------- + +The preferred limit on the length of a single line is 80 columns, however, some +exceptions are made based on readability. Otherwise, lines longer than 80 +columns should ideally be broken down into sensible chunks. A commonly used +technique is to align descendants to a function open parenthesis. However, +user-visible strings should *never* be broken as that breaks the ability to grep +for them. + +Braces and spaces +----------------- + +The opening brace should *always* be placed last on the same line and the +closing brace first on the following line. This applies to all functions and +statement blocks. If a statement is followed by a continuation, it is placed +right after the brace. This allows easy insertion and deletion of interposing +statements: + +.. code-block:: c + + int func(void) { + } + + switch (value) { + case 0: + break; + default: + return; + } + + if (x == 1) { + here(); + then_here(); + over_there_as_well(); + } else { + do_this(); + } + +An exception is when a single statement under a branch: no braces are required +unless one of the branches has multiple lines. In addition, braces should be +used on any loop that has more than a single statement. + +Spaces should be placed on each side of most binary and ternary operators, such +as the following: + +.. code-block:: c + + = + - < > * / % | & ^ <= >= == != ? : + +However, spaces should *not* be placed after unary operators, increment and +decrement operators and structure member access operators. + +Unnecessary whitespace at the end of lines or files is frowned upon. Some +editors with smart indentation will leave whitespace at the beginning of new +lines so you can start typing the next line right away. However, many editors +do not erase the whitespace should you choose not to continue typing. + +Git will warn about trailing whitespace, and can optionally strip it out for +you; however, if applying a series of patches, this may make later patches in +the series fail by changing context lines. + +Naming things +------------- + +Encoding the type into the function or variable name can become misleading at +best, or dead wrong at worst. The compiler already knows what type the object +in question is, and relaying this information to the programmer is unnecessary. +Furthermore, overly descriptive names for variables are frowned upon, unless the +description boosts readability. + +Local variables should be short and to the point. Loop counter should just be +called ``i``. Giving temporary and single-use variables long, descriptive names +is counterproductive and makes the code that much harder to read. + +Global variables should be avoided, but in cases where they *must* be used, they +should have a name that reflects their purpose and scope. For instance: + +.. code-block:: c + + int index_counter = 0; + vec3 clear_color = {0.0f, 0.0f, 0.0f, 1.0f}; + +Typedefs +-------- + +Typedefs should be avoided at the global or API level, as it can hide +information about a struct or pointer. Things such as ``type_t`` are prone to +create confusion and are heavily frowned upon. The rationale is that when a +programmer sees ``type_t var``, they have no context as to how the type needs +to be used. Instead, leave the backing type information in full view: + +.. code-block:: c + + struct type *var; + +The engine has already defined the standard C23 integer types for use in +engine code, so there is no need to do any kind of typedef. Even if the backing +type information is platform-dependant, a simple ``void*`` is almost always +preferable to creating a new type wholesale. + +Functions +--------- + +Functions should be short and (ideally) do one operation. They should fit on +no more than one or two 1080p screens, and any more than that is a sign the +function is too complex. Never be afraid to define a helper function local to +the function's translation unit. If a function is no more than five lines long, +it can be inlined for performance. Helper functions should be prefixed with an +underscore and marked ``static``, so that they aren't visible by the API. + +The number of local variables should not exceed five or six, and any more than +that is a good sign of an overly complex function. If you need more than that, +the function's design should be re-thought. Psychology says that the average +human brain can only hold between five and seven things in working memory, so +functions should be designed accordingly. In source files, functions should be +separated with a single blank line. In header files, any function made part of +the API should be marked with ``RAPI`` before the function signature. + +In function prototypes, the function name should be included with the type +information. This adds valuble information for the reader and makes function +arguments easier to track in debuggers. + +Commenting +---------- + +The engine uses doxygen-style comments for generating documentation. Outside of +this, comments should be used to explain the what and why of a piece of code. +Avoid putting comments inside a function body unless its a TODO or FIXME tag. +Generally, comments should be placed at the head of a function for documentation +purposes, especially engine API functions. + +.. code-block:: c + + /** + * \brief Example function + * \param[in] ex1 Example input + * \param[out] ex2 Example output + * \return Example return + */ + int example(int ex1, int *ex2); + +Structs should also be commented in a similar style: + +.. code-block:: c + + /** + * Example struct + */ + struct example { + int ID; ///< Identifier + struct member *m; ///< Example member + } + +Member doc comments should be tabbed over so that they are in the same column. + +Data structures +---------------- + +Data structures that have visibility outside the local thread should have a +reference count. The engine provides a reference accounting structure that is +thread-safe and works atomically. If you think your code will be visible outside +the current thread, don't hesitate to use it. It is better to be overly cautious +and use more memory than to take unnecessary risks with thread-global data. + +In addition, reference counting means the engine can avoid locking, and allows +multiple threads to access the data structure in parallel, or merely ensuring +the underlying data doesn't get taken away during a lock or other operation. + +A good rule of thumb is that if another thread can find your structure, and it +doesn't contain a reference count, it is almost always a bug. + +Macros and enums +---------------- + +All macros, enum values and constants should be capitalized. + +.. code-block:: c + + #define PI 3.1415926535 + + enum state { + STATE_READY, + STATE_UNREADY, + STATE_LOCKED + ... + } + + int GRAVITY = 9.8; + +Generally, inline functions are preferred to macros resembling functions, as +bugs in macros are much harder to track down and don't appear in a debugger. +Macros with multiple statements should be enclosed in a do-while block: + +.. code-block:: c + + #define MACRO(a, b, c) \ + do { \ + if (a == 5) \ + do_this(b, c); \ + } while(0) + +You should avoid macros that affect control flow, depend on having a local +variable with a magic name and macros that are used as l-values. Furthermore, +macros that have a more complex expression should be enclosed in parentheses. + +.. code-block:: c + + #define PI 3.14159265 + #define AREA(x) (PI * x * x) + +Macros should take into account common variable names, especially those +resembling functions. For instance: + +.. code-block:: c + + #define FOO(x) \ + ({ \ + typeof(x) ret; \ + }) + +Conditional compilation +----------------------- + +Wherever possible, the use of preprocessor conditionals should be relegated to +header files. If you need to define a different function (say, for a different +platform) it is best to define functions for each case and a stub for the final +else. + +References +---------- + +* `Linux kernel coding style <https://www.kernel.org/doc/html/v4.10/process/coding-style.html>`_ diff --git a/doc/core/index.rst b/doc/core/index.rst new file mode 100644 index 0000000..f0d8710 --- /dev/null +++ b/doc/core/index.rst @@ -0,0 +1,37 @@ +Core API reference +================== + +Initialization +-------------- + +.. doxygenfile:: init.h + +Error handling +-------------- + +.. doxygenfile:: abort.h + +Data structures +--------------- + +.. doxygenfile:: list.h + +Logging +------- + +.. doxygenfile:: logging.h + +Memory allocation +----------------- + +.. doxygenfile:: alloc.h + +Mod interface +------------- + +.. doxygenfile:: mod.h + +Multithreading +-------------- + +.. doxygenfile:: thread.h diff --git a/doc/dev-process.rst b/doc/dev-process.rst new file mode 100644 index 0000000..7484bf5 --- /dev/null +++ b/doc/dev-process.rst @@ -0,0 +1,43 @@ +Development process +=================== + +This document is intended to provide developers work with the development +community while minimizing frustration. While there are some technical +information here, the majority of this manual is process-oriented and does not +require deep understanding of the engine's APIs to understand. + +How to contribute +----------------- + +The Rune Engine is free and open source. Like any community-driven project, the +engine relies on volunteer contributions. If you are not a programmer, no need +to worry, as Rune requires many other roles as well. In fact, if you are a user +of the engine and enjoy its feature set, merely putting "Made with Rune" on your +game or application positively impacts the well-being of this project. Your +personal success makes the engine visible to other developers, growing the +community further. + +Technical contributions +----------------------- + +* Report bugs and other issues - As active users of the engine, you are much + better equipped to track down bugs and other issues more than anyone else. To + let the community know about your findings, visit the + `Flyspray instance <https://bugs.gymli.org/index.php?do=toplevel&project=3>`_. +* Test development versions - It is recommended to use the stable releases for + your projects, but you can help us test development releases, betas and + release candidates by running your project with them and checking what + problems this introduces or solves. +* Contribute engine code - The engine development is mainly coordinated on our + `mailing list <https://lists.gymli.org/rune-engine/new.html>`_. +* Review code contributions - All patches submitted to the mailing lists need to + be carefully reviewed before they can be merged into the mainline engine. The + maintainers are limited in number and how much work they can get done. You can + help them get a head start by participating in the code review process. +* Demo projects - The engine has a small selection of demo projects so new users + can quickly test new features or get familiar with the engine in the first + place. Help improve existing projects or write entirely new ones to be added + to the pool. +* Write documentation - The documentation is one of the most important parts of + the engine, and is often overlooked. If you have technical writing skills, + help with the engine documentation is always welcome. diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..b4dfb5a --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,46 @@ +.. Rune Game Engine documentation master file, created by + sphinx-quickstart on Wed Oct 16 23:36:04 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Rune Game Engine documentation +============================== + +Rune is a high-performance game engine written entirely in C and designed to +support Quake-style, "boomer" shooters. It is free and open source, and has both +2D and 3D capabilities. If you are new to this documentation, we recommend that +you read the `introduction page <introduction.html>`_ to get an overview of features and specs that +Rune has to offer. Please note that improvements to the documentation are +welcome; join the rune-engine mailing list at lists.gymli.org if you want to help +out. + +User-oriented documentation +--------------------------- + +The following manuals are written for game or application developers who are +trying to get the engine to work for their own applications or libraries. + +.. toctree:: + :maxdepth: 1 + + Introduction <introduction.rst> + List of features <feature-list.rst> + Core API <core/index.rst> + Network API <network/index.rst> + Rendering API <render/index.rst> + UI API <ui/index.rst> + Sound API <sound/index.rst> + Reporting issues <reporting-issues.rst> + +Working with upstream +--------------------- + +The guides for interacting with the engine's development community and getting +your work upstream. + +.. toctree:: + :maxdepth: 1 + + Development process <dev-process.rst> + Coding style <coding-style.rst> + Submitting patches <submitting-patches.rst> diff --git a/doc/introduction.rst b/doc/introduction.rst new file mode 100644 index 0000000..c2bba3b --- /dev/null +++ b/doc/introduction.rst @@ -0,0 +1,43 @@ +Introduction +============ + +Welcome to the official documentation of the Rune Engine, the free and open +source 2D and 3D game engine. This engine, being licensed under the terms of the +very liberal zlib license, allows game and application developers to create any +kind of game, for any platform and with no usage restriction whatsoever. +However, as the engine's focus is on Quake-style shooters, it may be more +difficult to create a different type of game (e.g., a top-down city builder) in +this engine. Developers are free to make their own modifications to Rune to +support their game and are encouraged to submit their changes to the mailing +lists. + +This page gives a broad overview of the engine and this documentation, so that +you know where to start if you are a beginner or where to look if you need more +information about a particular feature. + +Before you start +---------------- + +Please note that much of the engine is still under heavy development, and some +APIs have yet to be stabilized and documented. The ones listed in this +documentation have been stabilized and nothing should be removed or changed, +however, some functions may be added in the future should the need arise. + +About the Rune Engine +--------------------- + +A standard, "off the shelf" game engine is designed to provide a developer with +an IDE-like interface with an editor, a publication platform, scripting engine, +etc. Rune is designed to be just another library that a developer can use. There +is no editor outside of the one you provide yourself. The engine is designed to +stay out of the developer's way as much as possible, allowing the developer to +realize their vision without distractions and fluff. Rune is built on POSIX and +Unix principles and abstractions, so Linux and macOS developers should feel very +at home working with Rune. The engine considers Linux a first-class citizen, so +any code that calls engine APIs and primitives should run *unmodified* on a +Linux system, given the application developer is only using Rune APIs. + +Rune is completely free and open source under the permissive zlib license. No +strings attached and no royalities required. Users' games are theirs, down to +the last line of engine code. Rune's development is fully community-driven, +giving users the ability to shape the engine to meet their needs. diff --git a/doc/submitting-patches.rst b/doc/submitting-patches.rst new file mode 100644 index 0000000..002f7a4 --- /dev/null +++ b/doc/submitting-patches.rst @@ -0,0 +1,142 @@ +Submitting patches +================== + +If you have experience submitting patches to the Linux kernel or similar +projects, you are already familiar with the system Rune uses for +community-driven development. If not, this is the guide from which you should +begin. This manual provides a step by step guide on how to get your code into +the engine, as well as tips on increasing the odds your changes get merged into +the mainline release. + +Experience with ``git`` is expected and assumed, as the engine uses it for all +it version control needs. If you are unfamiliar with it, the documentation for +``git`` can be found at `this website <https://git-scm.com/doc>`_. + +Obtain a source tree +---------------------------- + +If you do not have a repository with the engine source, use ``git`` to download +one. Most of the time, you will want a mainline repository, which can be cloned +like so: + +.. code-block:: + + git clone git://git.gymli.org/dholman/rune-engine.git + +Describe your changes +--------------------- + +For any feature, bugfix or solution, there must have been a motivation behind +this change. Convince the reviewer that there is a problem worth fixing or a new +feature to be added, and make them believe its worth reading past the first few +lines of the commit message. + +Optimizations and the trade-offs that were made with them should be made clear +in the message. If you claim a performance increase, back it up with a numerical +figure. Describe the expected downsides of your optimization so that the +reviewer and the community at large can discuss its potential benefits and +costs. + +Patches should fix only a single problem or introduce a single feature. If the +changes you send do more than that, consider breaking them up into a series of +patches. + +When a patch is submitted, the full description and justification should be +included with it. It is on you to ensure the correct information is attached to +the patch or patch series. Maintainers are busy guys and are not obligated to +follow a URL to a pastebin to find the information about a patch. In other +words, the patch (series) should be self-contained. + +If you need to link to a mailing list archive, prefer to use the lists.gymli.org +service. To create the link, use the contents of the ``Message-ID`` header of +the message without the angle brackets. + +.. code-block:: + + Link: https://lists.gymli.org/rune-engine/104 + +Your changes should be in imperative mood and should follow the canonical patch +format. In other words, the patch should sound as though it is ordering the code +to change, rather than the developer merely describing his or her changes. This +makes commit messages shorter and easier to follow. Furthermore, the message +should be in plain English or a very close approximation as can be permitted +when discussing technical details. + +If you want to refer to a specific commit or issue, don't just include the hash +of the commit or the issue ID. The patch should contain at least a oneline +summary of the commit or issue. This makes code review flow much more smoothly +and allows the maintainers to know what you are referring to. The hash should at +least include the first twelve characters of the SHA-1 hash. This reduces the +chance of collisions even when the number of objects grows large. + +If a patch fixes a bug introduced in a previous commit or a bug tracker, the +'Fixes:' tag should be used with the first twelve characters of the SHA-1 hash, +or in the case of a public bug tracker, the 'Closes:' tag should be used with +the relevant link. + +.. code-block:: + + Closes: https://bugs.site.tld/issues/176 + Fixes: 123456789abc ("subsystem: file: example") + +Select the recipients for your patch +------------------------------------ + +You should always CC the appropriate maintainers and lists on any patch to code +they maintain. A good bet is to send it to the email attached to the +``git blame`` data and the main discussion list. If you cannot contact the +relevant maintainer for the subsystem you are working on, Danny Holman, being +the final arbiter of all changes accepted into the engine, serves as maintainer +of last resort. + +Formatting +---------- + +Danny and other engine developers need to be able to read and comment on the +changes you are submitting. If a maintainer cannot quote your changes using +standard, plain text tools, it is almost guaranteed to be ignored. For this +reason, all patches should be submitted by email "inline". By far, the easiest +way to do this is to use ``git send-email``. The documentation linked in the +opening paragraphs has a section dedicated to this tool. + +Furthermore, all patches should contain 'PATCH' in the subject line. This makes +actual patches distinguishable from other email discussions. The +``git send-mail`` tool will do this automatically. + +Sign your work +-------------- + +To facilitate copyright and to keep track of who submitted changes, all patches +should include a sign-off at the end of the commit message. This certifies you +wrote the patch or otherwise have the right to pass it on as open source. See +the ``dco.txt`` file for the exact requirements. + +When committing, ``git`` will do this automatically when you specify +``--signoff`` as part of the command flags. Alternatively, you can define an +alias in your ``.gitconfig`` file that will shorten ``git commit --signoff`` to +something similar to ``git cs``. + +Canonical patch format +---------------------- + +The canonical patch subject line is: + +.. code-block:: + + Subject: [PATCH 1/X] subsystem: summary phrase + +The body contains the following: + +* A ``from`` line specifying the patch author, followed by an empty line +* The body of the explanation, line wrapped at 75 columns, which will be copied + to the permanent changelog to describe this patch +* An empty line +* The ``Signed-off-by:`` lines, described above +* A marker line containing simply ``---`` +* Any additional comments not suitable for the changelog +* The actual patch (``diff`` output) + +References +---------- + +* `Linux kernel patch submission guide <https://www.kernel.org/doc/html/latest/process/submitting-patches.html>`_ |