aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2024-04-27 10:05:19 -0700
committerrtk0c <[email protected]>2025-08-16 11:34:41 -0700
commit9b2387dfe702bbadbdfde03fad8ba20daec127f8 (patch)
tree71daf487345822f8ba0c8f4aceb97280f7402e3d /docs
parent92a688093c801ac2b8cc9b74a42b5c850c8dd18e (diff)
Commit project notes
Diffstat (limited to 'docs')
-rw-r--r--docs/design.org4
-rw-r--r--docs/notes.org52
-rw-r--r--docs/todo.org101
3 files changed, 157 insertions, 0 deletions
diff --git a/docs/design.org b/docs/design.org
new file mode 100644
index 0000000..4a881b1
--- /dev/null
+++ b/docs/design.org
@@ -0,0 +1,4 @@
+* Game idea "Tethered"
+- Two players, each has a loop of ropes
+- One end of the rope is always attached to the player
+- The other end can be freely attached and detatched from things like anchors, pullies, or the other player
diff --git a/docs/notes.org b/docs/notes.org
new file mode 100644
index 0000000..38d7b1c
--- /dev/null
+++ b/docs/notes.org
@@ -0,0 +1,52 @@
+* General
+- Big level - =GameObject= streaming from disk
+ - How to solve in-editor/dev-env performance problems?
+- A number of common namespaces used throughout the projects
+ - =Utils= contains misc functions that are not attached to any class
+ - =Metadata= contains, well, metadata related things. Most of the functions in here have definitions created by [[*Codegen Design][codegen]] during compilation
+ - =Tags= contains various enums that need to be unscoped (=enum= instead of =enum class=) for simplicity of interop with libraries and/or use with arrays, but don't want to pollute the global namespace with.
+
+* Codegen Design
+This code generator assumes the source-header pair structure. For each header, there needs to be at least one corresponding =.cpp= file (translation unit) for codegen to work (by including the generated code at the bottom of the =.cpp= file). At the same time, if anything residing inside a =.cpp= needs code generation, those will also be placed at the =.inl= included.
+
+** Iteration 1
+- 2 kinds of files to deal with: an included file (headers) with no ODR restrictions, and TU files (can be included at most once, or directly compiled)
+ - Headers can be included in generated =.cpp= files
+ - Source can not be included; they must include the generated =.cpp= files
+- Referenced constructs can exist in both kinds of files
+- Dynamically link everything?
+
+** Iteration 2
+- "gh" = Generated Header
+- "gph" = Generated Pre-Header
+- "gs" = Generated Source
+- "gps" = Generated Pre-Source
+- "g" = General generated file, with any suffix (e.g. =.cpp= or =.hpp=)
+
+* =GameObject= Allocator Design
+- TODO
+
+* The General Engine Organization Plan
+游戏世界 <-> =GameObject= 之间的组织结构
+
+** Iteration 1
+- 分成几个逻辑上的子系统:physics, "rest"。
+- physics子系统
+ - 负责处理 =GameObject= 移动逻辑
+ - 数据直接储存在 =GameWorld= 里,lazily从实现了 =IPhysicsObject= 的 =GameObject= 里获取
+ - 例:多个地板对象提供的collision mesh会被汇总到 =GameWorld= 地下,由kinematics solver直接处理
+- "rest"子系统
+ - 就是剩下的一般 =GameObject= 逻辑,实现陷阱、玩家、门之类的逻辑
+ - 数据表现为 =GameObject= 和派生类的member variable、member function等
+
+*** 脑洞: =TerrainObject=
+把所有静止对象全部和到同个 =GameObject= 里,反正每个 =GameObject= 可以提供多个 =RenderObject= 而静止物体又不需要处理逻辑,直接一股脑丢给渲染器和物理引擎就可以了
+- 优点
+ - 降低 =GameObject= 个数
+- 缺点
+ - 模糊了 =GameObject= 的语义,它到底表现的是什么?
+ - 调试相对麻烦
+ - 需要单独为 =TerrainObject= 编写/维护一套编辑器
+
+** Iteration 2
+TODO
diff --git a/docs/todo.org b/docs/todo.org
new file mode 100644
index 0000000..4837594
--- /dev/null
+++ b/docs/todo.org
@@ -0,0 +1,101 @@
+* Epics
+** Epic: Level loading
+** Epic: Guizmo
+* Inbox
+** TODO upgrade ImGui to docking branch
+** TODO migraete to pcg-cpp for random number generation
+** TODO [[Epic: Guizmo]] specialized translate, rotate, and scale manipulators instead of the giant glob that exists as ImGuizmo::Manipulate() right now
+** DONE [[Epic: Level loading]] Level manager
+** TODO [[Epic: Level loading]] Level ser/deser system
+Options
+- Perhaps utilize the codegen?
+- boost.serialization style =OperateIOStream()= function?
+- Port IO system from CPLT
+End result: selected JSON based hand written serialization
+** TODO Switch to binary level format for faster loading and saving, also less RAM usage
+** DONE Fix "ill-formed, no diagnostic required" within codegen
+Currently enum metadata are provided through template specializations stored in =.cpp= file but not =.hpp= file. According to the standard, a specialization must appear before every instantiation, even if the template in question is just
+#+BEGIN_SRC c++
+template <>
+std::string_view GetterFunc();
+// ^^^ No definition/body provided here
+#+END_SRC
+** DONE Render options: wireframe
+** TODO Render options: debug coloring (random color for each triangle)
+** TODO Camera move between 2D and 3D mode easing
+** TODO Allocator/arena based ~GameObject~ memory management
+- 现在的系统管理内存分散在 =GameObject= 和 =GameWorld= 两个类之间,并且 =~GameObject()= 的行为没有很好的定义
+- ser/deser写起来很麻烦,内存全部得由 =LevelWrapper= 管理
+** TODO custom UI - port from p6503?
+Ongoing work in branch /main/ui-framework
+** TODO Port codegen to =libclang= :codegen:
+Or some other existing C++ parser library. Currently everything is hacked together to parse a very limited subset of the syntax (e.g. skipping templates) which breaks on quite a lot of classes in the project. It only works because the parser can skip them, and those unrecognized structures aren't using codegen.
+=libclang= will formalize all of this.
+** STRT Some kind of =basically_global.cpp= implementation :codegen:
+Probably a part of codegen, scan each file and store into the database. On generation, simply enumerate all the options and generate a DAG.
+Potentially throw error if a DAG cannot be formed (cyclic dependency)?
+#+BEGIN_SRC c++
+// Declares a global initializable target
+#define BASICALLY_GLOBAL(name)
+// Declare a initialization function for the last defined target
+// Options
+// - DEPENDS [name]...
+#define BASICALLY_GLOBAL_INIT(...)
+// Declare a destructor function for the last defiend target (invoked on shutdown, in opposite order of initialization)
+#define BASICALLY_GLOBAL_DEL()
+
+BASICALLY_GLOBAL(gApp) static App* gApp;
+
+BASICALLY_GLOBAL(gAssetStore) static AssetStore* gAssetStore;
+BASICALLY_GLOBAL_INIT(gAssetStore, DEPENDS gApp) {
+ gAssetStore = new AssetStore(gApp);
+}
+BASICALLY_GLOBAL_DEL(gAssetStore) {
+ delete gAssetStore;
+}
+
+BASICALLY_GLOBAL(gDirtyObjects) static std::vector<Object> gDirtyObjects;
+// NOTE: the parser will only check for macros at the beginning of the line
+BASICALLY_GLOBAL_INIT(gDirtyObjects, DEPENDS gApp gAssetStore) {
+ gDirtyObjects.push_back(gAssetStore->FindAsset(gApp->GetWorld()->assetId));
+}
+
+BASICALLY_GLOBAL(gSaves) static SaveStore* gSaves;
+BASICALLY_GLOBAL_DEL(gSaves) DELETE_PTR(gSaves) // Macros for shorthands!
+
+// There doesn't have to be a variable attached: the names are really just names for "targets" to generate an invocation DAG
+BASICALLY_GLOBAL(DummySequencerTarget);
+BASICALLY_GLOBAL_INIT(DummySequencerTarget, DEPENDS gDirtyObjects gAssetStore) {}
+
+// Initialize multiple global variables in one initializer
+BASICALLY_GLOBAL(gAppFlagEnableDebug) static int gAppFlagEnableDebug;
+// You can add comments between global items that share the same initializer
+BASICALLY_GLOBAL(gAppFlagProfiling) static int gAppFlagProfiling;
+
+// Or new lines
+// You can add anything between them
+static bool helepr() {
+ return false;
+}
+
+BASICALLY_GLOBAL(gAppFlagUserConfig) static int gAppFlagUserConfig;
+// Logic:
+// When parser sees BASICALLY_GLOBAL, they are added to a list
+// When the parser sees BASICALLY_GLOBAL_INIT or BASICALLY_GLOBAL_DEL, the initializer/deleter are assigned to the items in list
+// If right the BASICALLY_GLOBAL_INIT after is another BASICALLY_GLOBAL_DEL, the deleter will be assigned to the same list as well
+// If any other BASICALLY_GLOBAL is seen after an initializer/deleter, the list will be discarded
+
+// Update 2023-01-16: the above is ideally true, but we need to generate mangled names for the initializers and deleters AND allow the codegen to get them, so if it's purely stateful it's not going to work
+// Because:
+// - Option 1: use some kind of UNIQUE_NAME macro: not preditable, we can't gaurentee the codegen gets the same __COUNTER__ as the compiled file, which may use __COUNTER__ in some included file
+// - Option 2: generate a mangled name inside code. This won't work because a purely stateful mechanism has no way for BASICALLY_GLOBAL_INIT, etc. to lookup the last item
+// - The only potential solution here is to have a dedicated BASICALLY_GLOBAL_UNIQUE_NAME macro that has a custom counter, and restrict its usage to be only in .cpp files. But it's both fragile and difficult to work with, whereas simply adding the target name to BASICALLY_GLOBAL_INIT is simpler and more reliable.
+BASICALLY_GLOBAL_INIT(gAppFlagUserConfig, DEPENDS gApp DummySequencerTarget) {
+ // Allows flexibility: do anything as "initialization"
+ gAppFlagEnableDebug = gApp->FindArgument("debug").As<bool>();
+ gAppFlagProfiling = gApp->FindArgument("debug").As<bool>();
+ gAppFlagUserConfig = gApp->FindArgument("debug").As<bool>();
+}
+#+END_SRC
+
+** TODO