Juliean said:
As I said, the reflection is completely independant of ECS or what else, I even use it in the OOP-based gameplay-framework that sits on top of the ECS.
I knew you would do better than the ‘bad’ example i tried to make ; )
But out of interest, how are you declaring/handling property-types in your system? Since it sounds like you don't have any type-system attached to it, do you just use immediate-mode gui calls for the different types?
You don't want to see what i'm doing.
Every data member in the configuration can be bool, int, float … float4. I use a union over float[4], and if it's actually just a bool the other memory is wasted.
And i add each data member manually with a code line per member. The code line gives extra info in parameters, e.g. default value; if i want a slider or just a number for GUI; or if the given description string should be used to extract names of a drop down menu instead of a tool tip.
There is nothing elegant or clever to expect.
Usually i do all this ‘declaration’ work in a function called CreateConfig(), which is called once, typically at application startup, e.g. from constructors. At the end of said function it loads itself from file, and if the configuration object is destroyed it saves its settings. This way changes i do on the running app are preserved for the next startup. And if i decide to add new data members, i do so by adding code in CreateConfig(), but the saved file is still compatible to be loaded and will contain the new stuff next time.
The GUI is created by iterating all data members in order, using flags and min/max numbers etc. if it was given on creation. Mostly defaults are fine, so not too much work on tweaking GUI.
Here the creation function for the screenshot i've used above as example.
I could not create this automatically in such compact way, as it's settings affect many underlying systems of the editor. The amount of needed code is pretty much the same that i would need to make GUI elements anyway.
Downside is the extra parameters to achieve certain things like sliders or drop downs. If i need that, i always need to search for examples in older code.
But it's not too messy : )
void MakeConfig ()
{
config = Configuration("EditorApplication", "configs\\", 0, true);//false);//
config.BeginScope ("Startup:", 0);
config.SetParamI ("background threads", 15);
config.SetParamString ("prefabDirectory", "c:\\dev\\data\\prefabs\\");
config.SetParamString ("load staticMesh", "sponza8k", 0, true);
config.SetParamString ("load staticMesh", "Armadillo_input", 0, true);
config.SetParamString ("load staticMesh", "sphere", 0, true);
config.SetParamString ("load staticMesh", "botijo", 0, true);
config.SetParamFN ("activeRegion.minmax[0]", std::array<float,3>{-100.f, -100.0f, -100.0f}.data(), 3);
config.SetParamFN ("activeRegion.minmax[1]", std::array<float,3>{100.f, 100.f, 100.f}.data(), 3);
config.SetParamB ("start background processing at startup", 0);
config.SetParamB ("procedural fluid scene at startup", 1);
config.SetParamB ("fluid from file at startup", 1);
config.SetParamB ("fluid to scene at startup", 0);
config.SetParamB ("hm from file at startup", 0);
config.SetParamString ("fluidPreset", "brain mountains");
config.SetParamB ("open fluidSim.GUI", 1);
config.SetParamB ("open heightSim.GUI", 0);
config.SetParamB ("open DebugSurfaceEffects", 0);
config.SetParamB ("open DebugMeshing", 0);
config.SetParamB ("open DebugSDF", 0);
config.EndScope ();
config.BeginScope ("EditorApplication::MainLoop()", 1);
config.SetParamB ("do UserInput", 1);
config.SetParamB ("do TreeView", 1);
config.SetParamB ("vis editorScene", 1);
config.BeginScope ("vis volumeScene", 1);
config.SetParamB ("vis IsoSurf", 0);
config.SetParamB ("vis Mesh", 0);
config.SetParamB ("vis Crossfield", 0);
config.SetParamB ("vis Wavefield", 0);
config.SetParamB ("vis Remesh", 0);
config.SetParamB ("vis Stitch", 0);
config.SetParamI ("CellLevel", 1);
config.SetParamB ("updateFocus", 1);
config.SetParamF ("focusRadius", 5.3f);
config.SetParamF ("focusDist", 2.f);
config.EndScope ();
config.EndScope ();
config.BeginScope ("EditorApplication.editorScene", 1); // own config?
config.SetParamI ("vis> maxObjects", 30000, 1.0f, 0, 1000000, Configuration::GUI_IS_SLIDER);//scope path?
config.SetParamB ("vis> content", 0);
config.SetParamB ("vis> nodes", 0);
config.SetParamB ("vis> both", 0);
config.SetParamB ("vis> skipNonLayerNodes", 0);
config.SetParamB ("vis> content meshes", 0);
config.SetParamB ("vis> content wireframe", 0);
config.SetParamB ("vis> node transform", 1);
config.SetParamB ("vis> node BBox", 1);
config.SetParamB ("vis> node verbose", 1);
config.EndScope ();
config.LoadFromFile("", 0);
}