TheOpenSpaceProgram / osp-magnum

A spaceship game
https://www.openspaceprogram.org/
MIT License
216 stars 32 forks source link

Add `framework`, based on testapp #298

Closed Capital-Asterisk closed 2 months ago

Capital-Asterisk commented 3 months ago

Heavily addresses #288, most info on these new changes are here.

This can allow the GDExtension application (#294) to not need to depend on testapp.

Capital-Asterisk commented 3 months ago

almost 10,000 line changes and rising :whale: :bird:...

I wrote a little unit test / tutorial that shows the important parts of using the new framework: https://github.com/TheOpenSpaceProgram/osp-magnum/blob/5e8a0b5d3cae3aca5412ff0d90814ac481721763/test/framework/main.cpp

A ton of grunt work required to rewrite all the setup_* 'Session' functions into 'Features'. This gets rid of a bunch of macros and janky stuff and shrinks down the code a tiny bit:

Before and after for 'bounds' (click to expand) **Before:** ```cpp // Header 1 #define TESTAPP_DATA_BOUNDS 2, \ idBounds, idOutOfBounds struct PlBounds { PipelineDef boundsSet {"boundsSet"}; PipelineDef outOfBounds {"outOfBounds"}; }; // Header 2 osp::Session setup_bounds( osp::TopTaskBuilder& rBuilder, osp::ArrayView topData, osp::Session const& scene, osp::Session const& commonScene, osp::Session const& physShapes); // Source Session setup_bounds( TopTaskBuilder& rBuilder, ArrayView const topData, Session const& scene, Session const& commonScene, Session const& physShapes) { OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); OSP_DECLARE_GET_DATA_IDS(physShapes, TESTAPP_DATA_PHYS_SHAPES); auto const tgScn = scene .get_pipelines(); auto const tgCS = commonScene .get_pipelines(); auto const tgShSp = physShapes .get_pipelines(); Session out; OSP_DECLARE_CREATE_DATA_IDS(out, topData, TESTAPP_DATA_BOUNDS); auto const tgBnds = out.create_pipelines(rBuilder); rBuilder.pipeline(tgBnds.boundsSet) .parent(tgScn.update); rBuilder.pipeline(tgBnds.outOfBounds) .parent(tgScn.update); top_emplace< ActiveEntSet_t > (topData, idBounds); top_emplace< ActiveEntVec_t > (topData, idOutOfBounds); rBuilder.task() .name ("Check for out-of-bounds entities") .run_on ({tgScn.update(Run)}) .sync_with ({tgCS.transform(Ready), tgBnds.boundsSet(Ready), tgBnds.outOfBounds(Modify__)}) .push_to (out.m_tasks) .args ({ idBasic, idBounds, idOutOfBounds }) .func([] (ACtxBasic const& rBasic, ActiveEntSet_t const& rBounds, ActiveEntVec_t& rOutOfBounds) noexcept { ... ``` **After:** ```cpp // Header 1 struct FIBounds { struct DataIds { DataId bounds; DataId outOfBounds; }; struct Pipelines { PipelineDef boundsSet {"boundsSet"}; PipelineDef outOfBounds {"outOfBounds"}; }; }; // Header 2 extern osp::fw::FeatureDef const ftrBounds; // Source FeatureDef const ftrBounds = feature_def("Bounds", [] ( FeatureBuilder &rFB, Implement bounds, DependOn scn, DependOn comScn, DependOn physShapes) { rFB.pipeline(bounds.pl.boundsSet) .parent(scn.pl.update); rFB.pipeline(bounds.pl.outOfBounds) .parent(scn.pl.update); rFB.data_emplace< ActiveEntSet_t > (bounds.di.bounds); rFB.data_emplace< ActiveEntVec_t > (bounds.di.outOfBounds); rFB.task() .name ("Check for out-of-bounds entities") .run_on ({scn.pl.update(Run)}) .sync_with ({comScn.pl.transform(Ready), bounds.pl.boundsSet(Ready), bounds.pl.outOfBounds(Modify__)}) .args ({ comScn.di.basic, bounds.di.bounds, bounds.di.outOfBounds }) .func([] (ACtxBasic const &rBasic, ActiveEntSet_t const &rBounds, ActiveEntVec_t &rOutOfBounds) noexcept { ...