From 7adbafe16f334a30f64082df45038be54d6872a7 Mon Sep 17 00:00:00 2001 From: Swartz27 Date: Wed, 24 Sep 2014 12:27:14 -0400 Subject: [PATCH 1/4] Updated Readme.me to redirect to new Git location. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0ea43fb0fd7..32d3827e869 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,6 @@ This repository contains the Stalker: Call of Pripyat source code version 1.6.02 It is a place to share ideas on what to implement, gather people that want to work on the engine, and work on the source code. + +Update 9/24/2014: The VS2008 COP source will continue to be available here, +however this project now has a new home at: https://github.com/OpenXRay From 154b29ae43e87e9cbb99a4f14803b59172ceb988 Mon Sep 17 00:00:00 2001 From: Andrew Davies Date: Wed, 24 Sep 2014 12:51:57 -0700 Subject: [PATCH 2/4] Added BSD-Style license. --- License.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 License.txt diff --git a/License.txt b/License.txt new file mode 100644 index 00000000000..825753ffa11 --- /dev/null +++ b/License.txt @@ -0,0 +1,23 @@ +All source code included with this distribution, unless declared otherwise, +is commercial GSC Game World proprietary code. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither binary nor source code redistributions may be used for any +commercial purposes. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. From 7f0a45f5cb78581ed985ff0e82c13bad68d839a4 Mon Sep 17 00:00:00 2001 From: Andrew Davies Date: Wed, 24 Sep 2014 13:01:54 -0700 Subject: [PATCH 3/4] Minor commit. Making sure gitconfig is set up properly. --- Proposed engine changes.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Proposed engine changes.txt b/Proposed engine changes.txt index f76a10f4e84..5d6da51a8b2 100644 --- a/Proposed engine changes.txt +++ b/Proposed engine changes.txt @@ -8,7 +8,7 @@ Note: Source for COP released! Will update this with source asap. 2) Multi-thread the engine for up to 4 cores 3) Solve stuttering problem (likely due to LuaJit. Solution would be to upgrade it to newest version and then rewrite all the lua files to conform - with it) + with it). 4) Solve problem with COP sometimes not loading correctly upon launch on some systems as well as not always exiting properly and still running as a background task. @@ -40,7 +40,7 @@ Note: Source for COP released! Will update this with source asap. 18) Grass draw distance console command - * 19) Re-enable fov and hud_fov console commands - * 20) Re-enable grass shadows - * -21) Add Instanced Tessellation for DX9&10: +21) Add Instanced Tessellation for DX9&10: http://developer.download.nvidia.com/SDK/10.5/Samples/InstancedTessellation.zip SDK @@ -60,7 +60,7 @@ Weapon related changes The new AK-12 fires 3 shots at 1,000rpm. I'm not adding an AK-12, just giving an example). 2) Make pistols more useful somehow. Maybe make a "quick pistol" key or - something. + something. 3) Different reload sounds for reloading empty vs reloading full - * 4) Add anm_reload_empty to weapons that don't have one - * 5) Animation for misfires - * From db5d0debff0e9c431c5ebd76d8a41698b8364f87 Mon Sep 17 00:00:00 2001 From: Andrew Davies Date: Wed, 24 Sep 2014 13:11:00 -0700 Subject: [PATCH 4/4] Added coding/commiting convention files to doc/procedures/ --- doc/procedures/commit_coding.txt | 24 + doc/procedures/cpp_code.txt | 886 +++++++++++++++++++++++++++++++ 2 files changed, 910 insertions(+) create mode 100644 doc/procedures/commit_coding.txt create mode 100644 doc/procedures/cpp_code.txt diff --git a/doc/procedures/commit_coding.txt b/doc/procedures/commit_coding.txt new file mode 100644 index 00000000000..ddfbb678eaa --- /dev/null +++ b/doc/procedures/commit_coding.txt @@ -0,0 +1,24 @@ +TITLE: Commit message conventions + +The format of commit message should be a short description of what you did. +After the description, the bug ID, review ID or anything else. + +The commit log should not contain the obvious. If you change file Foo.cpp: + + BAD: + "Fix bug in Foo.cpp" + BAD: + "Fix #45" + BAD: + "Commit Foo.cpp" + GOOD: + "Fix buffer overflow (close #45)." + +The above does not mean that when you do a complex change do not write a +description of what you did, on the contrary. When a long description is +needed do add as much as needed to explain the change, just do not add +meaningless information (committing Foo.cpp etc.) + +It is advisable to split complex commits to several smaller commits if +possible. If you see that your commit massage contain more then one topic, you +probably can and should split the commit into a few unrelated commits. diff --git a/doc/procedures/cpp_code.txt b/doc/procedures/cpp_code.txt new file mode 100644 index 00000000000..3ec16f18052 --- /dev/null +++ b/doc/procedures/cpp_code.txt @@ -0,0 +1,886 @@ +TITLE: C++ Coding Conventions +STATUS: WORK IN PROGRESS + +--------------------- + +Shift width (indentation) is 4 spaces. +Line size is 120 columns. +Indentation is always one shift-width (4): + BAD + GatherInfo(expression, description, arg0, arg1, file, line, + function, assertionInfo); + + GOOD + GatherInfo(expression, description, arg0, arg1, file, line, + function, assertionInfo); + +Open and close brackets of a section should be on the same level: + BAD + if (lastErr == ERROR_SUCCESS) { + *buffer = 0; + return; + } + + GOOD + if (lastErr == ERROR_SUCCESS) + { + *buffer = 0; + return; + } + +When breaking up a long line, it should continue with one shift-width for +indentation: + BAD + if (lineLength > 1 && (screenSize.Vertical < bufferSize.Vertical + || explicitLines)) + { + printf("this is a test section that will show how to handle " + "long lines, such as %s which is %d lines long", + "this", 2); + SetWindowText( hWnd, + "Button Name" ); + } + GOOD + if (lineLength > 1 && (screenSize.Vertical < bufferSize.Vertical + || explicitLines)) + { + printf("this is a test section that will show how to handle " + "long lines, such as %s which is %d lines long", "this", 2); + SetWindowText(hWnd, "Button Name"); + } + +if/for/while statement that takes more than one line should always have +brackets same thing goes when the then/loop part is more than one line: + BAD + if (!ErrorAfterDialog) + MessageBox(NULL, "Fatal error occured\n\n" + "Press OK to abort program execution", "Fatal error", + MB_OK | MB_ICONERROR | MB_SYSTEMMODAL); + GOOD + if (!ErrorAfterDialog) + { + MessageBox(NULL, "Fatal error occured\n\n" + "Press OK to abort program execution", "Fatal error", + MB_OK | MB_ICONERROR | MB_SYSTEMMODAL); + } + +Function prototypes should be spaced like function calls: + BAD + void xrDebug::Backend(const char* reason, + const char* expression, + const char* arg0, + const char* arg1, + const char* file, + int line, + const char* function, + bool& ignoreAlways); + { + // function code + } + BAD + static void Backend(const char* reason, const char* expression, const + char* arg0, const char* arg1, const char* file, int line, const char* + function, bool& ignoreAlways); + GOOD + // declaration + static void Backend(const char* reason, const char* expression, + const char* arg0, const char* arg1, const char* file, int line, + const char* function, bool& ignoreAlways); + + // implementation + void xrDebug::Backend(const char* reason, const char* expression, + const char* arg0, const char* arg1, const char* file, int line, + const char* function, bool& ignoreAlways) + { + // function code + } + + // if you need to comment parameters + void xrDebug::Backend( + const char* reason, // error reason + const char* expression, // failed expression + const char* arg0, // first argument + const char* arg1, // second argument + const char* file, + int line, + const char* function, + bool& ignoreAlways) // ignore errors of this type + { + // function code + } + +switch statements should have the case on the same level, no space before ':'. +if the case is one line, then one space after ':': + BAD + switch (vendor) + { + case Vendor::Intel: + ... + case Vendor::AMD: + ... + } + GOOD + switch (vendor) + { + case Vendor::Intel: + ... + case Vendor::AMD: + ... + } + GOOD + switch (controlId) + { + case IDC_TOGGLESTATS: + app->drawStats = !app->drawStats; + break; + case IDC_RESETCAMERA: + app->ResetCamera(); + break; + case IDC_LIGHT_SIZE: + { + auto r = hud->GetSlider(IDC_LIGHT_SIZE)->GetValue() * 0.01f; + app->spotLightObj->SetLightRadius(r); + break; + } + } + GOOD + switch (vendorId) + { + case 0x756e6547: vendor = Vendor::Intel; break; + case 0x68747541: vendor = Vendor::AMD; break; + default: vendor = Vendor::Unknown; break; + } + +No space between function name and opening brackets, +no space between opening brackets and first parameter, +one space after comma: + BAD + Msg ("hello %s\n", "world"); + Msg( "hello world\n" ); + Msg("hello world\n","world"); + GOOD + Msg("hello world\n", "world"); + +One space after reserved words before the opening parenthesis: + BAD + if(OnDialog) + GOOD + if (OnDialog) + +'then' part of if statement should be in a separete line. +Reason: allows to debug the if and see when it is run. + BAD + if (OnDialog) OnDialog(true); + GOOD + if (OnDialog) + OnDialog(true); + +else if statements should be on the same level at the starting if +Reason: this is similar to switch statement. + BAD + if (!strcmp(argv[1],"--help")) PrintUsage(); + else if (!strcmp(argv[1], "--run")) { + RunApplication(); + PrintResults(); + } else PrintError(); + GOOD: + if (!strcmp(argv[1], "--help")) + PrintUsage(); + else if (!strcmp(argv[1], "--run")) + { + RunApplication(); + PrintResults(); + } + else + PrintError(); + +return statements should not have parentheses and should not have a space +after them: + BAD + return (0); + GOOD + return 0; + BAD + return ; + GOOD + return; + +Don't use unneeded parentheses in expressions: + BAD + if ((a != b) || (c != d)) + ... + GOOD + if (a != b || c != d) + ... + +Don't call return at the end of a function returning void: + BAD + void foo() + { + bar(); + return; + } + GOOD + void foo() + { + bar(); + } + +Don't separate code sections with more than one blank line. + +class/struct/enum definitions, initializations should open { at the next line: + BAD + struct Size { + int Width; + int Height; + }; + GOOD + struct Size + { + int Width; + int Height; + }; + BAD + Size size = { + 16, + 42 + }; + GOOD + Size size = + { + 16, + 42 + }; + GOOD (initialization fits in a single line) + Size size = {16, 42}; + +Prefer C++ comments to C comments: + GOOD + /* draw overlay statistics */ + DrawStats(); + GOOD (better) + // draw overlay statistics + DrawStats(); + +Comments should be aligned as the code they comment, or one space after +the end of line: + BAD + /* + * draw overlay statistics + */ + DrawStats(); + BAD + // + // draw overlay statistics + // + DrawStats(); + GOOD + /* draw overlay statistics */ + DrawStats(); + GOOD (better) + // draw overlay statistics + DrawStats(); + GOOD + DrawStats(); // draw overlay statistics + +Comments which occupy more than one line should adhere to the following +guidline: + BAD + // + // last render stage: draw overlay engine performance statistics + // (input, render, sound, ai, physics) + // + DrawStats(); + GOOD + // last render stage: draw overlay engine performance statistics + // (input, render, sound, ai, physics) + DrawStats(); + +Common sense should come into play when deciding whether to use for or while +loops: + BAD + int i = 0; + while (i < 10) + { + i++; + ... + } + GOOD + for (int i = 0; i < 10; i++) + ... + BAD + for (ptr = ptr->next; ptr; ptr = ptr->next) + ... + GOOD + while ((ptr = ptr->next)) + ... + +In for and while loops without a statement, statement separator should be in +the same line. + BAD + for(i = 0; Test(i); i++) + ; + GOOD + for (i = 0; Test(i); i++); + +Put one space before and after an assignment: + BAD + int a=0; + x= x+1; + capacity*=2; + GOOD + int a = 0; + x = x+1; + capacity *= 2; + +Don't put a space before a statement separator, put one after it: + BAD + for (i = 0 ;i < 10 ;i--, j *= 2) ; + GOOD + for (i = 0; i < 10; i--, j *= 2); + +Don't put a space after increment and decrement. Increment after the value, +not before. + BAD + i --; + ++j; + GOOD + i--; + j++; + +Don't increment, set or change value of variable inside a function call: + BAD + CalcXY(i++, 2); + BAD + SetX(i = 3); + GOOD (if i is not a global) + CalcXY(i, 2); + i++; + GOOD (if i is a global that CalcXY() uses) + i++; + CalcXY(i-1, 2); + GOOD + if (i++) + a[i++] = 4; + GOOD (if i is not a global) + i = 3; + SetX(i); + +In for loops, when there is a function that gets the next element, it should +be done once (inside the step condition): + BAD: + for (int i = 0, ch = GetChar(); ch == '\r'; ch = GetChar(), i++) + HandleResult(ch); + GOOD: + for (int i = 0; (ch = GetChar()) == '\r'; i++) + HandleResult(ch); + +When assigning in a truth value (if/for/while) - use brackets. This eliminates +compilation warnings: + BAD: + for (int i = 0; ch = GetChar(); i++) + HandleResult(ch); + if (x = ComputeNum()) + return x; + GOOD: + for (int i = 0; (ch = GetChar()); i++) + HandleResult(ch); + if ((x = ComputeNum())) + return x; + +In string initialization and null termination, you must use 0: + BAD: + string[0] = '\0'; + if (string[3] == '\0') + { + } + + GOOD: + string[0] = 0; + if (string[3] == 0) + { + } + +Naming conventions: +- Do choose easily readable identifier names. For example, a variable named + horizontalAlignment is more readable in English than alignmentHorizontal. +- Do not use underscores. +- Do not use Hungarian notation except in two cases: + - UI-related code, i.e. btnOpen, lblMessage, chkRecursive, cbGameType + - Interface classes: IClient, IGameLevel, IGamePersistent, etc + +Casing styles: +- class/struct/enum: PascalCase + - Math primitives can be in lowercase: vector2f, angle3f, matrix44f +- Public members: PascalCase + - Math primitives can use lowercase: vector2f.x, angle3f.yaw, matrix44f.m03 +- Private members: camelCase +- Local variables: camelCase +- Global variables: PascalCase +- Namespaces: PascalCase + +Checking function return values: +Functions that return bool or a pointer will be checked without +comparing, if they return true or false. + BAD + if (strstr(args, " -h") != nullptr) + PrintHelp(); + GOOD + if (strstr(args, " -h")) + PrintHelp(); + BAD + if (IsUpdateRequired() == true) + Update(); + GOOD + if (IsUpdateRequired()) + Update(); + BAD + cl = GetClient(id); + if (cl == nullptr) + return nullptr; + GOOD + cl = GetClient(id); + if (!cl) + return nullptr; + BAD + cl = GetClient(id); + if (cl != nullptr) + Disconnect(cl); + GOOD + cl = GetClient(id); + if (cl) + Disconnect(cl); + +When allocating a structure on stack, use = {0} unstead of memset: + BAD + ShaderParams params; + memset(¶ms, sizeof(params), 0); + GOOD + ShaderParams params = {0}; + +When possible, prefer inline functions to macros: + BAD + #define RAD2DEG(angle) ((angle)*180/PI) + GOOD + template + T RadiansToDegrees(T angle) + { + return angle * 180 / PI; + } + +Macro names should normally be all upper case, with normal spacing as rest of +code: + BAD + #define RAD2DEG( angle ) ((angle)*180/PI) + #define RAD2DEG(angle) \ + ((angle) * 180 / PI) + GOOD + #define RAD2DEG(angle) ((angle)*180/PI) + GOOD + #define RAD2DEG(angle) \ + ((angle)*180/PI) + +Macros that are more than one statement long should be encapsulated by +do-while(false). This enables using them inside if-else statements: + Example usage: + if (condition) + DO_A_AND_B; + else + DoSomethingElse(); + BAD + #define DO_THIS_AND_THAT() \ + { \ + DoThis(); \ + DoThat(); \ + } + GOOD + #define DO_THIS_AND_THAT() \ + do { \ + DoThis(); \ + DoThat(); \ + } while (false) + +Don't use forward declarations unless they are necessary. Instead, change the +order so the caller is below the callee. + BAD + void Callee(); + void Caller() + { + Callee(); + } + void Callee() + { + } + GOOD + void Callee() + { + } + void Caller() + { + Callee(); + } + +Prefer data types from Common.hpp over OS specific data types: + BAD + BYTE b; + DWORD w; + GOOD + byte b; + uint32 w; + +At the beginning of a file add inclusion protection. Don't use include guards. +Instead, use #pragma once - it's less prone to making mistakes and it is less +code to type. Though it's not a part of the standard, it's well supported +across compilers. + BAD + #ifndef _XRAY_HPP_ + #define _XRAY_HPP_ + + // The XRay.hpp content comes here + + #endif // _XRAY_HPP_ + GOOD + #pragma once + + // The XRay.hpp content comes here + +Files should terminate with an empty line: + BAD + int main() + { + return 0; + } + GOOD + int main() + { + return 0; + } + + +COMPLEX #if sections should adhere to the following guideline: + BAD + #ifndef NO_SINGLE + Msg("* Found new patch: %s", versionName); + #ifdef DOWNLOAD_UPDATES + #ifdef DOWNLOAD_UPDATES_GATHER_STATS + DownloadStats stats; + DownloadUpdate(downloadUrl, stats); + stats.Dump(); + #else + DownloadUpdate(downloadUrl); + #endif + #endif + #endif + BAD + #ifndef NO_SINGLE + Msg("* Found new patch: %s", versionName); + # ifdef DOWNLOAD_UPDATES + # ifdef DOWNLOAD_UPDATES_GATHER_STATS + DownloadStats stats; + DownloadUpdate(downloadUrl, stats); + stats.Dump(); + # else + DownloadUpdate(downloadUrl); + # endif + # endif + #endif + GOOD + #ifndef NO_SINGLE + Msg("* Found new patch: %s", versionName); + #ifdef DOWNLOAD_UPDATES + #ifdef DOWNLOAD_UPDATES_GATHER_STATS + DownloadStats stats; + DownloadUpdate(downloadUrl, stats); + stats.Dump(); + #else + DownloadUpdate(downloadUrl); + #endif + #endif + #endif + +SIMPLE #if sections should not be indented: + GOOD + #ifndef DEBUG + #ifdef _DEBUG + #define DEBUG + #endif + #ifdef MIXED + #define DEBUG + #endif + #endif + BAD + #ifndef DEBUG + #ifdef _DEBUG + #define DEBUG + #endif + #ifdef MIXED + #define DEBUG + #endif + #endif + GOOD + void Sleep(int milliseconds) + { + #ifdef WINDOWS + ::Sleep(milliseconds); + #else + ::sleep(milliseconds); + #endif + } + BAD + void Sleep(int milliseconds) + { + #ifdef WINDOWS + ::Sleep(milliseconds); + #else + ::sleep(milliseconds); + #endif + } + +After #endif you can put a comment telling to what if it belongs if there is +a large gap between the #if and its corresponding #endif. + BAD + #ifdef _EDITOR + VerifyPath(path); + #endif // _EDITOR + GOOD + #ifdef _EDITOR + VerifyPath(path); + #endif + GOOD + #ifdef _EDITOR + // Lots of editor related code, that you really have to scroll down + // to see all of it. + #endif // _EDITOR + +Only use the defined() macro when you have a complex expression. If you find +that you do need to use the defined() macro for more than one flag, see if +that flags can be grouped under another one new flag: + BAD + #ifndef DEDICATED_SERVER + #ifdef CONFIG_SHOW_LOGO_WINDOW + DestroyWindow(logoWindow); + #endif + #endif + BAD + #if defined(CONFIG_SHOW_LOGO_WINDOW) + DestroyWindow(logoWindow); + #endif + GOOD + #ifdef CONFIG_SHOW_LOGO_WINDOW + DestroyWindow(logoWindow); + #endif + GOOD (since you really need both flags) + #if !defined(DEDICATED_SERVER) && defined(CONFIG_SHOW_LOGO_WINDOW) + DestroyWindow(logoWindow); + #endif + +Use using instead of typedef: + BAD + typedef void (*FunctionType)(double); + typedef Vector3 vector3f; + GOOD + using FunctionType = void (*)(double); + using vector3f = Vector3; + +Use strongly typed enums instead of plain C enums: + BAD + enum CmdStatus + { + CmdStatusOk, + CmdStatusInProgress, + CmdStatusFailed, + }; + GOOD + enum class CmdStatus + { + Ok, + InProgress, + Failed, + }; + +Enums that can be serialized should have values assigned: + BAD + enum class CmdStatus + { + Ok = 1, + InProgress, + Failed, + }; + GOOD + enum class CmdStatus + { + Ok = 1, + InProgress = 2, + Failed = 3, + }; + +Every enum line have to be comma terminated - this makes the enum extensible. +Only separate the last line, if it is meant to never be surpassed. + BAD + enum class CmdType + { + Reset = 1, + Load = 2, + Save = 3 + }; + GOOD + enum class CmdType + { + Reset = 1, + Load = 2, + Save = 3, + }; + GOOD + enum class CmdType + { + Reset = 1, + Load = 2, + Save = 3, + Invalid = 0xFF + }; + +Put the pointer and reference before the identifier: + BAD + IClient *GetServerClient(); + void BanAddress(const IPAddress &ip); + GOOD + IClient* GetServerClient(); + void BanAddress(const IPAddress& ip); + +Operator delete also handles nullptr, so no need for 'if ()' before it: + BAD (if str can be null): + if (str) + delete str; + GOOD: + delete str; + +Constant strings longer than one line should be closed on each line by a quote +and opened again on the next line. Words should have the space after them on +the same line. + BAD + Log("Hello world, this is a long string that we want to print and \ +is more than 80 chars long so we need to split it"); + BAD + Log("Hello world, this is a long string that we want to print" + " and is more than 80 chars long so we need to split it"); + GOOD + Log("Hello world, this is a long string that we want to print " + "and is more than 80 chars long so we need to split it"); + +Functions that accept zero parameters should be defined without void: + BAD + IClient* GetServerClient(void); + GOOD + IClient* GetServerClient(); + +Trivial + - * / expressions should not have spaces around them: + BAD + Foo(a + b); + GOOD + Foo(a+b); + BAD + Foo(2 * (a + b)); + GOOD + Foo(2*(a+b)); + BAD + Foo((a + b) / (1000 * 1000)); + GOOD + Foo((a+b)/(1000*1000)); + BAD + Foo((Min(aMin, bMin)+Max(aMax, bMax))*(width*Pow(a, p))/(1000*1000)); + GOOD + Foo((Min(aMin, bMin)+Max(aMax, bMax)) * (width*Pow(a, p)) / (1000*1000)); + +Dont put empty lines between code inside functions. If you want to separate +code fragments, put a comment line. + BAD + for (auto& item : items) + storage.push_back(item); + + if (storage.size() == 0) + Log("! ERROR: No items found"); + GOOD + for (auto& item : items) + storage.push_back(item); + // check if there's no items + if (storage.size() == 0) + Log("! ERROR: No items found"); + +Module Foo in Engine/Bar/Foo.cpp & Foo.hpp. +All files should follow this exact example. +Unless using precompiled headers, #include "Common.hpp" must be first in +the *.cpp file to make sure the features configuration affect all the rest of +the files. If using precompiled headers, #include "Common.hpp" must be first +in the precompiled header file (e.g. stdafx.hpp) and must not be included in +*.cpp file. +Header files must be self contained, i.e. they must be able to compile +without relying on another include line to come before them. +Therefore #include "Foo.hpp" must be immediately after to make sure Foo.hpp +compiles standalone without any dependency on includes before it. + GOOD + Foo.hpp template + ------------------------------ + #pragma once + #include "Common.hpp" + ... Put here minimal includes required by Foo.hpp ... + + ... Put here your declarations ... + + Foo.cpp template + ------------------------------ + #include "Common.hpp" + #include "Foo.hpp" + ... Put here minimal includes required by Foo.cpp ... + + ... Put here your code ... + + GOOD (using precompiled headers) + stdafx.hpp template + ------------------------------ + #pragma once + #include "Common.hpp" + ... Put here additional includes ... + + Foo.hpp template + ------------------------------ + #pragma once + #include "Common.hpp" + ... Put here minimal includes required by Foo.hpp ... + + ... Put here your declarations ... + + Foo.cpp template + ------------------------------ + #include "stdafx.hpp" + #include "Foo.hpp" + ... Put here minimal includes required by Foo.cpp ... + + ... Put here your code ... + +Use #include "Foo.hpp" for headers in the same directory as the source +including them. +Use #include "PathToFoo/Foo.hpp" for headers in other directories, where +PathToFoo is relative to root engine directory. +Use #include for external system files. + BAD + #include + #include + #include "IReader.hpp" + #include "algorithm" + GOOD + #include "Common.hpp" + #include "xrCore.hpp" // we are in Engine/xrCore directory + #include "IO/IReader.hpp" // from Engine/xrCore/IO/IReader.hpp + #include + +Comments of XXX should be : . Multiple names should be +separated with a '/': + BAD + XXX: dima: optimize this case + XXX alexmx: RENDER check if already loaded + XXX alexmx: oles: move to common + GOOD + XXX: optimize this case + XXX dima: optimize this case + XXX alexmx RENDER: check if already loaded + XXX alexmx/oles: move to common