================================== Important ================================== If you want participate in engine development you must follow this rules. Otherwise your pull request will be guaranteed rejected. =============================================================================== =================================== Common ==================================== 1. About structure and naming of folders and files. a) All folders names are lower-case. Words are separated by "_". Never use upper-case characters. b) You can create subfolders and files only in "src/examples/", "src/plugins/", "include/" and "resources/examples/" folders. Project files also could be created in "build//examples/" or "build//plugins/" folders if needed. If you need to create folder in some other place (for example for the new tool) you must contact the project leader to discuss folder location with him. c) All *.txt files must be named in CamelCase style. d) All resource and other miscellaneous files are named in lower-case with "_" word separator. e) All examples "src/examples/" and common "src/common" source files are named in lower-case with "_" word separator. f) All engine and plugin sources are named in CamelCase style. Solutions and projects are named in CamelCase as well. The only exceptions are some engine headers like "DGLE_Types.h", "DGLE_CoreRenderer.h", "DGLE_EXT.h", etc. This exception spreads only upon system headers started with "DGLE". g) All binaries are named in CamelCase style. ==================================== C++ ====================================== 1. Use only "#pragma once" to solve include collisions of headers, never use other methods. Exception is made only for engine and plugins headers. 2. Functions and methods naming. a) All functions and public methods are named in CamelCase style. b) All private class methods begins with symbol "_". 3. Naming of classes, structures, types and enums. a) All class names begins with symbol "C" followed by CamelCase styled name ex. "CMyGame". b) Rules for structs and typedefs are the same as for classes except the first symbol is "T". c) Enums have upper-case names with symbol "_" as word separator. First two symbols of the name must be "E_". Enum elements also have upper-case names with symbol "_" as word separator. First characters of the element name must be concatenation of first characters of every word of the enum name. First element value of the enum must be set. See example below for clear understanding. enum E_BATCH_MODE { BM_AUTO = 0, BM_DISABLED, BM_ENABLED, BM_ENABLED_UPDATE_EVERY_TICK }; 4. Variables naming rules. a) Global variables, public class members and function arguments are named in lowerCamelCase style. Example: bool isGameStarted; b) Private class members are named as public but first character is "_". Example: bool _isGameStarted; c) Local variables must have lower-case names with "_" as separator. Example: bool is_game_started; Note: For bools first word better to be a verb like "do", "is", "has" and so on... or prefix "b" (see below). 5. Variables prefixes and data types. a) We use Hungarian Notation especially for pointers and strings. It is highly recommended to use this notation almost everywhere in project. There are type and special prefixes. Prefixes could be combined. See tables and code sample at the bottom of the file for better understanding. /----------------------\ | Type | Prefix | ------------------------ | int | i | | unsigned | u | | signed | s | | long int | i32 | | short int | i16 | | long long | i64 | | float | f | | double | d | | char/byte | bt | | bool | b | | char | c | | char | i8 | | wchar | wc | | class | cl | | * | p | | enum | e | | struct | st | | std::string | str | | std::vector | vec | | & | r | | array | a | | typedef | t | \----------------------/ Note: Prefixes "a", "r" and "p" must go first in any prefix combination. /--------------------\ | Special prefixes | ---------------------- | const | c_ | | static | s_ | | volatile | v_ | | mutable | m_ | | extern | e_ | \--------------------/ Note: Special prefixes must not be used with functions or methods parametrs. Special prefixes are prior to common prefixes and must go first in any prefix combination. b) Project uses its own data types becuse they are platform independent. And you must use them too. You could find all of them in the "include/cpp/DGLE_Types.h". Here is most common types: /-------------------------------------------------------\ | short int | int16 | | long int | int32 | | signed char | int8 | | wchar_t | wchar | | unsigned short int | uint | | unsigned short int | uint16 | | unsigned long int | uint32 | | unsigned char | uint8 | | unsigned char | uchar | | signed long long | int64 | | unsigned long long | uint64 | | window descriptor | TWinHandle | | color descriptor | TColor4 | | two component vector | TPoint2 or TVec2 | | three component vector | TPoint3 or TVec3 | | rectangle discriptor | TRectF | | common 4X4 matrix | TMatrix or TMat4 | | ....................... | ................... | \-------------------------------------------------------/ 6. Comments and auto documentation. a) Every header or cpp file of engine or plugin must starts with this header: /** \author < your full name > aka < your nickname > \date < last major modification date dd.mm.yyyy > (c)Korotkov Andrey This file is a part of DGLE project and is distributed under the terms of the GNU Lesser General Public License. See "DGLE.h" for more details. */ It is not necessary to paste this header into examples, tools or your custom plugins, only in core project source code. b) All source code in "include/" folder must be commented the way to be later auto documented by doxygen. See engine headers as the example. c) Use only english language in comments. 7. Macroses naming rule is simple. Use upper-case characters separated by "_". 8. a) It's recommended to use spaces around "(", ")", "[", "]", "+", "–", "*", "/", "=", "+=", "-=", "*=", "/=", "|=", "&=", "==", "!=", "&", "&&", "|", "||", "^", "<", ">", "?", ":", "if", "for", "while". In functions calls "(" and ")" as well as unar "+", "–", "*", "&" should NOT be separated by spaces. Note: Some exceptions for this rule could be done for templates. b) One tab is equal to four spaces. 9. Write constant safe code. Use "const" not only for constant variables but also for constant class methods, references and pointers. It's often better to use "mutable" but leave class method constant. 10. In classes private members must go first, then goes private methods and then goes all public methods. Try not to use public members and friend classes. 11. If you are not shure that you have done right, don't be afraid, feel free to contact developers by e-mail hello@dglengine.org but before, please, think a little bit and try to make right decision concerning the style and principles of code around. ===================================== C# ====================================== By default you should use rules from C++ section, but there are some important exceptions! 1. All classes, class metods, enums, structures and functions must be named in CamelCase style. 2. All global and local variables as well as class members must be named in lowerCamelCase style. 3. Try not to use Hungarian Notation it is obsolete for modern programming languages. Note that C# file names are commonly CamelCase by default and there is no need to rename them. Also note that engine C# assemblies have the same code style as C++, we do so not to confuse engine users. =============================== Code Samples ================================== Here are code samples written according to described rules. =============================================================================== ==================================== C++ ====================================== Global variables or public members. uint32 ui32Value; const int c_iValue = 10; uint8 *pui8Data1, *pbtData2, *pData3; CMyClass clMy1, *pclMy2, *pMy3; char acName1[10], *pcName2; Function or method parametrs. void Foo(const TMyStruct &rValue); void Foo(CMyClass *&prClass); Local variables. int32 i32_data_offset, offset; float af_verts[3], verts[3]; IMyInterface *pcl_my_interface, *p_my_int, *my; uint8 *p_ui8_data1, *p_data1; ----------------- | MyGame.h | ----------------- #pragma once #include "DGLE.h" using namespace DGLE; #define GAME_SPEED 10 E_GAME_STATES { GS_STAGE_1 = 0, GS_STAGE_2 }; class CCoolGame { static const uint _sc_uiMaxLives; TVec2 _stPlayerPos; float _someValue; bool _bIsGameStarted; void _Update(double dDeltaTime); public: E_GAME_STATES eGameState; CCoolGame(uint uiGameSpeed); bool StartGame(); bool IsGameStarted() const; void SetPlayerPos(const TVec2 &pos); }; bool InitGame(const char *pcArguments, uint uiArgsCount); ----------------- | MyGame.cpp | ----------------- #include "MyGame.h" const uint c_someMagicValue = 10; CCoolGame::CCoolGame(uint uiGameSpeed): _s_c_uiMaxLives(c_someMagicValue), _bIsGameStarted(false), eGameState(GS_STAGE_1) { _someValue = float(rand() % 100); } CCoolGame::_Update(double dDeltaTime) { //ToDo: Insert code here } bool CCoolGame::StartGame() { eGameState = GS_STAGE_1; _bIsGameStarted = true; _stPlayerPos = TVec2(float(rand()%640), float(rand()%480)); return true; } bool CCoolGame::IsGameStarted() const { return _bIsGameStarted; } void CCoolGame::SetPlayerPos(const TVec2 &pos) { _stPlayerPos = pos; } CCoolGame clGameOne(GAME_SPEED), *pGameTwo = NULL; bool InitGame(const char *pcArguments, uint uiArgsCount) { int16 i16_my_magic_number = 44; bool is_game_started = false; if (i16_my_magic_number == rand() % 88) is_game_started = clGameOne.StartGame(); return is_game_started; }