Open an issue at GitHub issue tracker. Before doing that, ensure the bug was not already reported or fixed in master
branch. Describe a problem and, if necessary, provide minimal code needed to reproduce it.
Open a new GitHub pull request with your patch. Provide a description of the problem and solution. Follow our code style.
New code should at least:
- work under Windows and POSIX systems and provide platform-agnostic API
- support x64 targets
- use Vulkan as graphics API
- use SDL as hardware API
- use sily or it's sister-libraries (i.e sily-terminal) for game math and some of I/O operations when possible. If there is no required operation please open an issue or create a pull request
- follow our code style
- not violate copyright/licensing. When adapting third-party code, make sure that it is compatible with GNU GPL 3.0.
Adding new external dependencies should be avoided as much as possible.
master
branch is a development branch for the next release. When release is ready, master
branch will be pushed into release
branch and release will be made from it.
Raylight mostly follows D style. Essential rules are the following:
- Use spaces instead of tabs. Each indentation level is 4 spaces
- There's always a space after control statements (
if
,while
,for
, etc...) - Opening curly bracket should be on a same line
- Functions and variables should be in
camelCase
- Classes, structs and enums should be in
PascalCase
- Module names should be in lowercase
if () else if ()
can be split asif () else\n if ()
- If method or function is used as property parenthesis can be dropped
- Prefer explicitly importing methods instead of importing whole module when only several methods from this module are needed. Exception is when imported module declares only one thing (i.e vector and aliases for it)
- Also prefer explicitly importing sub-modules. I.e
import std.algorithm.searching;
instead ofimport std.algorithm;
- Imports are ordered separated by single space. First normal, then static and finally public:
- std
- core
- bindbc
- erupted
- sily
- other libraries
- raylight
- Preferred order of declarations for classes or structs is:
- Public properties and one-line setters/getters
- Private properties
- Constructors
- Public methods
- Private methods
- Name prefixes are:
public static const int normalProperty
)_
- for private/protected properties (private int _privateProperty
)s_
- for private/protected static properties (private static int s_staticInt
)t_
- for private/protected thread static properties (private shared int t_staticInt
)_
- as postfix when name is a keyword (bool bool_
)
- Function signature preferred to be in order:
- attributes (@property)
- visibility (public, private...),
public
can be dropped since everything is default public - isStatic (static)
- misc
- isOverride (override)
- type qualifiers and type (int, bool...)
- name and params
- attributes (const, nothrow, pure, @nogc, @safe)
- i.e
@property private static override int myMethod(int* ptr) @safe @nogc nothrow {}
- Interfaces must be prefixed with
I
, i.e.IEntity
- When declaring properties, methods, etc... visibility modifier can be dropped in favor of global visibility modifier, i.e
private:
. This type of declaration is valid but should be avoided since it's considered implicit- Example:
class MyClass { public: int myPublicInt; string myPublicString; private: int myPrivateInt; public: int myPublicIntMethod() {} ... }
- Always describe symbols with ddoc unless name is self-descriptive (for properties)
- Avoid exceptions at all costs. Prefer status return checks and if needed to return nullable use
std.typecons: Nullable;
or if needed to return multiple values consider putting then in custom struct
Example of how a module would look like when adhering to those rules:
/++
Custom raylight module.
Currently an example of style to use in raylight engine source
code.
+/
module raylight.custom;
import std.stdio: stdout, stdin, writeln;
import core.stdc: FILE;
import bindbc.sdl;
import bindbc.erupted;
import sily.vector;
import sily.terminal: isatty;
import raylight.logger;
import raylight.render.engine;
static import bindbc.loader;
public import sily.matrix;
/// Prints if std is a tty
void funcName() {
if (stdout.isatty) {
trace("STDOUT is a tty");
} else
if (stdin.isatty) {
trace("STDIN is a tty");
} else {
trace("None are tty")
}
}
/// CustomStruct isCustom type enum
enum CustomEnum {
enumKey1,
enumKey2
}
/// Structure to do custom things for raylight
struct CustomStruct {
/// Is custom struct
CustomEnum isCustom;
/// Struct index
static int index;
private int _privateIndex;
private shared bool t_isInit;
/// Returns private name
@property string getName() const {
return privateName();
}
/// Ditto
private string privateName() const {
return "my private name";
}
}