# Contributing Guidelines This document outlines the conventions to follow when contributing to this project. ## Commit Policy ### Verify Build and Tests Before Committing Before preparing or proposing a commit, you **must** perform the following verifications to prevent regressions: 1. **MacOS / Linux (Native)**: * Build the project (debug or release). * Run the entire test suite (`ctest`). * Ensure all tests pass. 2. **Windows (Cross-Compilation)**: * If `mingw-w64` is installed on your system, you **must** also verify the Windows build. * Run `./scripts/build_win.sh`. * Ensure the build succeeds and produces the `demo64k_packed.exe` binary. * Check the size report to ensure no unexpected bloat. Refer to the "Testing" and "Windows Cross-Compilation" sections in `HOWTO.md` for detailed instructions. ### Format Code Before Committing All code **must** be formatted using `clang-format` before committing. This ensures a consistent coding style across the entire codebase. To format your code, run the following command from the project root: ```bash clang-format -i $(git ls-files | grep -E '\.(h|cc)$' | grep -vE '^(assets|archive|third_party)/') ``` Refer to the `.clang-format` file in the project root for the specific style rules. ### Ensure Newline at End of File All source files (`.h`, `.cc`, `.cpp`, etc.) must end with a newline character. This prevents "No newline at end of file" errors from linters and ensures consistent file handling. ### Source File Headers Every source file (`.h`, `.cc`) must begin with a concise 3-line comment header describing its purpose. Example: ```cpp // This file is part of the 64k demo project. // It implements the core audio synthesis engine. // This is not a user-facing header, but an internal one. ``` ### Function and method comments Functions and methods, especially if they are internal non user-facing, should at least have a 1-line comment describing what they do or their how/when they should be called. Except if they are just 1-line function or very very short, obvious ones. ### '#endif' directive The closing #endif directive must recall the corresponding opening #ifdef clause they are closing Example: ```cpp #ifdef MY_TAG ...some code #endif /* MY TAG */ ``` We must also prefer '#if defined(MY_QUITE_LONG_TAG)' over '#ifdef MY_QUITE_LONG_TAG' especially if there's a risk of having later something like: ```cpp #if defined(MY_TAG_1) && !defined(MY_TAG_2) ``` ### use and abuse 'const' directives Especially for local variable, use 'const' qualification as much as possible. As an example, don't use: ```cpp StructA variable_name = StructA(...); ``` but prefer instead: ```cpp const StructA variable_name = StructA(...); ``` if variable_name is not mutated afterward. Also: pass parameter as "const ref" as much as possible (```const Struct& param``` instead of pointers or non-const refs) ### put spaces around code and operators (cosmetics) Don't compact the code to much horizontally, and prefer adding extra spaces around code and operators. Example: ```cpp const bool v = my_variable && (my_function() / 3. > (1. / x)); const y = function_call(3, x, 2.); for (int x = 0; x < 24; ++x) { ... } ``` instead of ```cpp const bool v=my_variable&&my_function()/3.>(1./x); const y = function_call(3,x,2); for(int x=0;x<24;++x){ ... } ``` ### prefer prefixed incrementation over suffixed Use pre-incrementation: ```cpp ++x ``` instead of post-incrementation: ```cpp x++ ``` ### use extra () for boolean operations Even if they are not strictly needed due to operator precedence rules, prefer adding extra ()'s around tests for clarity, with parcimony. ### c++ cast don't use reinterpret_cast<>, static_cast<> or const_cast<>. ### pointer declaration prefer ```const T* name``` to ```const T *name```. ### 'auto' type Don't use 'auto' as type, unless for complex iterators or very complex types. ### don't use trailing whitespaces don't. ### no missing \newline at the end of file make sure each file has a final \n newline. ### c++ keyword indentation: The keyword 'public', 'protected', 'private' should be intended 1 character less than the methods. Example: ```cpp private: int field_; ``` instead of: ```cpp private: int field_; ``` ### vertical space keep the code compact vertically. That includes shader code, too. Use only one statement per line. ### finally Make sure everything is reflected in clang-format. ## Development Protocols ### Adding a New Visual Effect 1. **Implement**: Create or update a class in `src/gpu/demo_effects.cc` (and declare in `demo_effects.h`) that inherits from `Effect`. - Implement `init()` for one-time resource setup (e.g., using the asset system). - Implement `compute()` if you need GPU-side physics or state updates. - Implement `render()` to record WebGPU draw commands. 2. **Register**: Add an `EFFECT` entry to `assets/demo.seq` specifying the class name, start/end times, and any constructor arguments. 3. **Verify**: Build with `DEMO_ALL_OPTIONS=ON` and use `--seek` to test your effect at its specific timestamp.