From a20ea5744d4de531f6cc05bb074c1020ab4c3065 Mon Sep 17 00:00:00 2001 From: nnicdao Date: Tue, 2 Dec 2025 00:26:41 -0800 Subject: [PATCH 1/7] Add new prebuilt spacecraft "Solvalot-1" --- bin/OSPData/adera/solvalot.png | Bin 0 -> 23670 bytes bin/OSPData/adera/solvalot.sturdy.bin | Bin 0 -> 47448 bytes bin/OSPData/adera/solvalot.sturdy.gltf | 230 +++++++++++++++++++ src/adera_app/features/vehicles_prebuilt.cpp | 99 ++++++++ src/adera_app/features/vehicles_prebuilt.h | 3 +- src/testapp/main.cpp | 5 +- src/testapp/scenarios.cpp | 4 +- 7 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 bin/OSPData/adera/solvalot.png create mode 100644 bin/OSPData/adera/solvalot.sturdy.bin create mode 100644 bin/OSPData/adera/solvalot.sturdy.gltf diff --git a/bin/OSPData/adera/solvalot.png b/bin/OSPData/adera/solvalot.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff6c93547ae27526bb75def50b751fe58bd8329 GIT binary patch literal 23670 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 literal 0 HcmV?d00001 diff --git a/bin/OSPData/adera/solvalot.sturdy.bin b/bin/OSPData/adera/solvalot.sturdy.bin new file mode 100644 index 0000000000000000000000000000000000000000..510ab29c219c00c99763ab54ab40c65b444d9618 GIT binary patch literal 47448 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 F{eSZ@eyRWf literal 0 HcmV?d00001 diff --git a/bin/OSPData/adera/solvalot.sturdy.gltf b/bin/OSPData/adera/solvalot.sturdy.gltf new file mode 100644 index 00000000..3698f6b6 --- /dev/null +++ b/bin/OSPData/adera/solvalot.sturdy.gltf @@ -0,0 +1,230 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.5.49", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 5 + ] + } + ], + "nodes":[ + { + "extras":{ + "shape":"cube", + "massdry":1000.0 + }, + "name":"col_fusalage", + "scale":[ + 0.886086642742157, + 2.495450973510742, + 6.2181172370910645 + ], + "translation":[ + 0, + 0.0039101243019104, + 0.9583339095115662 + ] + }, + { + "extras":{ + "shape":"cube", + "massdry":1000.0 + }, + "name":"col_left", + "rotation":[ + 0.017452405765652657, + 0, + 0, + 0.9998477101325989 + ], + "scale":[ + 0.6479361057281494, + 2.646085262298584, + 2.323085308074951 + ], + "translation":[ + 5.002408027648926, + 0.1590890884399414, + -3.7140254974365234 + ] + }, + { + "extras":{ + "shape":"cube", + "massdry":1000.0 + }, + "name":"col_right", + "rotation":[ + 0.017452405765652657, + 0, + 0, + 0.9998477101325989 + ], + "scale":[ + 0.6479361057281494, + 2.646085262298584, + 2.323085308074951 + ], + "translation":[ + -5.002409934997559, + 0.1590890884399414, + -3.7140254974365234 + ] + }, + { + "extras":{ + "shape":"cube", + "massdry":1000.0 + }, + "name":"col_wings", + "scale":[ + 4.787597179412842, + 0.3123275935649872, + 3.603761672973633 + ], + "translation":[ + 0, + 0.0039101243019104, + -2.002084732055664 + ] + }, + { + "mesh":0, + "name":"solvalot" + }, + { + "children":[ + 0, + 1, + 2, + 3, + 4 + ], + "extras":{ + "massdry":10.0 + }, + "name":"part_solvalot1" + } + ], + "materials":[ + { + "doubleSided":true, + "name":"solvalot-material", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":0 + }, + "metallicFactor":0, + "roughnessFactor":0.5 + } + } + ], + "meshes":[ + { + "name":"Cube", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"solvalot", + "uri":"solvalot.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1335, + "max":[ + 5.2794013023376465, + 2.8245668411254883, + 7.075264930725098 + ], + "min":[ + -5.2794013023376465, + -2.377899408340454, + -6.056069374084473 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1335, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1335, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2364, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":16020, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":16020, + "byteOffset":16020, + "target":34962 + }, + { + "buffer":0, + "byteLength":10680, + "byteOffset":32040, + "target":34962 + }, + { + "buffer":0, + "byteLength":4728, + "byteOffset":42720, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":47448, + "uri":"solvalot.sturdy.bin" + } + ] +} diff --git a/src/adera_app/features/vehicles_prebuilt.cpp b/src/adera_app/features/vehicles_prebuilt.cpp index fe437a84..340d0863 100644 --- a/src/adera_app/features/vehicles_prebuilt.cpp +++ b/src/adera_app/features/vehicles_prebuilt.cpp @@ -114,6 +114,31 @@ static void add_rcs_block(VehicleBuilder& rFB, VehicleBuilder::WeldVec_t& rWeldT rWeldTo.push_back({ nozzleB, nozzleTfB }); } +static void add_rcs_mirrored(VehicleBuilder& rFB, VehicleBuilder::WeldVec_t& rWeldTo, RCSInputs const& inputs, float thrustMul, Vector3 pos, Quaternion rot) +{ + auto const [ nozzleA, nozzleB ] = rFB.create_parts<2>(); + rFB.set_prefabs({ + { nozzleA, "phLinRCS" }, + { nozzleB, "phLinRCS" } + }); + + constexpr Vector3 mirrorX = Vector3{-1.0f, 1.0f, 1.0f}; + + // sort of just guessed, and this happened to work + Quaternion const rotMirrored{rot.vector() * mirrorX, -rot.scalar() }; + + Matrix4 const nozzleTfA = quick_transform(pos, rot); + Matrix4 const nozzleTfB = quick_transform(pos * mirrorX, rotMirrored); + + + add_rcs_machines(rFB, inputs, nozzleA, thrustMul, nozzleTfA); + add_rcs_machines(rFB, inputs, nozzleB, thrustMul, nozzleTfB); + + rWeldTo.push_back({ nozzleA, nozzleTfA }); + rWeldTo.push_back({ nozzleB, nozzleTfB }); +} + + FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( FeatureBuilder &rFB, Implement testVhcls, @@ -212,6 +237,80 @@ FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( } + // Build "Solvalot-1" + { + VehicleBuilder vbuilder{&rResources}; + VehicleBuilder::WeldVec_t toWeld; + + auto const [ fusalage, engineA, engineB ] = vbuilder.create_parts<3>(); + vbuilder.set_prefabs({ + { fusalage, "solvalot1" }, + { engineA, "phEngine" }, + { engineB, "phEngine" }, + }); + + toWeld.push_back( {fusalage, quick_transform({ 0.0f, 0.0f, 0.0f}, {})} ); + toWeld.push_back( {engineA, quick_transform({ 0.0f, -0.12f, -3.76f}, {} )} ); + toWeld.push_back( {engineB, quick_transform({ 0.0f, 1.1f, -3.70f}, Quaternion::rotation(17.8_degf, {1.0f, 0.0f, 0.0f}))} ); + namespace ports_magicrocket = adera::ports_magicrocket; + namespace ports_userctrl = adera::ports_userctrl; + + auto const [ pitch, yaw, roll, throttle, thrustMul ] = vbuilder.create_nodes<5>(gc_ntSigFloat); + + auto &rFloatValues = vbuilder.node_values< SignalValues_t >(gc_ntSigFloat); + rFloatValues[thrustMul] = 120000.0f; + + vbuilder.create_machine(fusalage, gc_mtUserCtrl, { + { ports_userctrl::gc_throttleOut, throttle }, + { ports_userctrl::gc_pitchOut, pitch }, + { ports_userctrl::gc_yawOut, yaw }, + { ports_userctrl::gc_rollOut, roll } + } ); + + vbuilder.create_machine(engineA, gc_mtMagicRocket, { + { ports_magicrocket::gc_throttleIn, throttle }, + { ports_magicrocket::gc_multiplierIn, thrustMul } + } ); + + vbuilder.create_machine(engineB, gc_mtMagicRocket, { + { ports_magicrocket::gc_throttleIn, throttle }, + { ports_magicrocket::gc_multiplierIn, thrustMul } + } ); + + + RCSInputs rcsInputs{pitch, yaw, roll}; + + // for roll + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 12000.0f, Vector3{4.952f, -0.351f, -1.492f}, Quaternion::rotation(90.0_degf, {1.0f, 0.0f, 0.0f})); + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 12000.0f, Vector3{4.952f, -0.827f, -1.492f}, Quaternion::rotation(-90.0_degf, {1.0f, 0.0f, 0.0f})); + + // for pitch + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 5000.0f, Vector3{0.506f, 0.545f, 3.412f}, Quaternion::rotation(90.0_degf, {1.0f, 0.0f, 0.0f})); + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 5000.0f, Vector3{0.506f, -1.441f, 3.412f}, Quaternion::rotation(-90.0_degf, {1.0f, 0.0f, 0.0f})); + + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 4000.0f, Vector3{0.5061700940132141, + -1.4411895275115967, + -3.2911040782928467}, Quaternion::rotation(-90.0_degf, {1.0f, 0.0f, 0.0f})); + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 4000.0f, Vector3{0.5061700940132141f, + 2.2311899662017822f, + -3.2911040782928467f}, Quaternion::rotation(90.0_degf, {1.0f, 0.0f, 0.0f})); + + + // for yaw + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 15000.0f, Vector3{0.6308508515357971, + -0.6648790836334229, + 4.920871734619141}, Quaternion::rotation(-90.0_degf, {0.0f, 1.0f, 0.0f})); + add_rcs_mirrored(vbuilder, toWeld, rcsInputs, 15000.0f, Vector3{ 5.238207817077637, + -0.6648790836334229, + -5.217004776000977}, Quaternion::rotation(-90.0_degf, {0.0f, 1.0f, 0.0f})); + + + vbuilder.weld(toWeld); + + rPrebuiltVehicles[gc_pbvSolvalot1] = std::make_unique(std::move(vbuilder.finalize_release())); + } + + // Put more prebuilt vehicles here! diff --git a/src/adera_app/features/vehicles_prebuilt.h b/src/adera_app/features/vehicles_prebuilt.h index 5061e58f..32ccf42c 100644 --- a/src/adera_app/features/vehicles_prebuilt.h +++ b/src/adera_app/features/vehicles_prebuilt.h @@ -46,7 +46,8 @@ struct PrebuiltVehicles : osp::KeyedVec< PrebuiltVhId, std::unique_ptr (vhclSpawnVB.di.vehicleSpawnVB); auto &rPrebuiltVehicles = args.rFW.data_get (testVhcls.di.prebuiltVehicles); - for (int i = 0; i < 10; ++i) + for (int i = 0; i < 2; ++i) { rVehicleSpawn.spawnRequest.push_back( { @@ -458,7 +458,7 @@ static ScenarioMap_t make_scenarios() .velocity = {0.0, 0.0f, 50.0f * float(i)}, .rotation = {} }); - rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); + rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSolvalot1].get()); } }}); From d535b66056eb1a6fcc96aecf253813d2e263ab54 Mon Sep 17 00:00:00 2001 From: nnicdao Date: Thu, 25 Dec 2025 04:31:32 -0800 Subject: [PATCH 2/7] Refactor link and machines to use Strong Id types --- src/adera/activescene/VehicleBuilder.cpp | 40 +++++++++-------- src/adera/activescene/VehicleBuilder.h | 15 ++++--- src/adera/activescene/vehicles_vb_fn.h | 2 +- src/adera/machines/links.h | 43 +++++++++---------- src/adera_app/features/jolt.cpp | 2 +- src/adera_app/features/vehicles.cpp | 38 ++++++++--------- src/adera_app/features/vehicles_machines.cpp | 15 ++++--- src/osp/link/machines.cpp | 24 +++++------ src/osp/link/machines.h | 45 ++++++++++---------- src/osp/link/signal.h | 39 +++++------------ 10 files changed, 125 insertions(+), 138 deletions(-) diff --git a/src/adera/activescene/VehicleBuilder.cpp b/src/adera/activescene/VehicleBuilder.cpp index 66d4bd02..b97c4b2b 100644 --- a/src/adera/activescene/VehicleBuilder.cpp +++ b/src/adera/activescene/VehicleBuilder.cpp @@ -118,7 +118,7 @@ osp::link::MachAnyId VehicleBuilder::create_machine(PartId const part, auto &rData = m_data.value(); osp::link::PerMachType &rPerMachType = rData.m_machines.perType[machType]; - MachTypeId const mach = rData.m_machines.ids.create(); + MachAnyId const mach = rData.m_machines.ids.create(); std::size_t const capacity = rData.m_machines.ids.capacity(); rData.m_machines.machTypes.resize(capacity); @@ -130,7 +130,7 @@ osp::link::MachAnyId VehicleBuilder::create_machine(PartId const part, rPerNodeType.m_machToNodeCustom.ids_reserve(capacity); } - MachTypeId const local = rPerMachType.localIds.create(); + MachLocalId const local = rPerMachType.localIds.create(); rPerMachType.localToAny.resize(rPerMachType.localIds.capacity()); rData.m_machines.machTypes[mach] = machType; @@ -152,13 +152,14 @@ void VehicleBuilder::connect(MachAnyId const mach, std::initializer_list nodePortMax(rData.m_nodePerType.size(), 0); for (Connection const& connect : connections) { - int &rPortMax = nodePortMax[connect.m_port.type]; - rPortMax = std::max(rPortMax, connect.m_port.port + 1); + int &rPortMax = nodePortMax[connect.m_port.type.value]; + rPortMax = std::max(rPortMax, connect.m_port.port.value + 1); } - for (NodeTypeId nodeType = 0; std::size_t(nodeType) < rData.m_nodePerType.size(); ++nodeType) + for (std::size_t nodeTypeInt = 0; nodeTypeInt < rData.m_nodePerType.size(); ++nodeTypeInt) { - int const portMax = nodePortMax[nodeType]; + NodeTypeId const nodeType = NodeTypeId::from_index(nodeTypeInt); + int const portMax = nodePortMax[nodeType.value]; PerNodeType &rPerNodeType = rData.m_nodePerType[nodeType]; if (portMax != 0) { @@ -167,19 +168,20 @@ void VehicleBuilder::connect(MachAnyId const mach, std::initializer_list const portSpan = rPerNodeType.machToNode[mach]; + rPerNodeType.machToNode.emplace(mach.value, portMax); + lgrn::Span const portSpan = rPerNodeType.machToNode[mach.value]; std::fill(std::begin(portSpan), std::end(portSpan), lgrn::id_null()); - rPerNodeType.m_machToNodeCustom.emplace(mach, portMax); - lgrn::Span const customSpan = rPerNodeType.m_machToNodeCustom[mach]; + rPerNodeType.m_machToNodeCustom.emplace(mach.value, portMax); + lgrn::Span const customSpan = rPerNodeType.m_machToNodeCustom[mach.value]; std::fill(std::begin(customSpan), std::end(customSpan), 0); for (Connection const& connect : connections) { if (connect.m_port.type == nodeType) { - customSpan[connect.m_port.port] = connect.m_port.custom; - portSpan[connect.m_port.port] = connect.m_node; + customSpan[connect.m_port.port.value] = connect.m_port.custom; + portSpan[connect.m_port.port.value] = connect.m_node; + rPerNodeType.m_nodeConnectCount[connect.m_node] ++; rPerNodeType.m_connectCountTotal ++; } @@ -195,24 +197,26 @@ using osp::link::JuncCustom; VehicleData VehicleBuilder::finalize_release() { auto &rData = m_data.value(); - for (NodeTypeId nodeType = 0; std::size_t(nodeType) < rData.m_nodePerType.size(); ++nodeType) + for (std::uint16_t nodeTypeInt = 0; nodeTypeInt < rData.m_nodePerType.size(); ++nodeTypeInt) { + NodeTypeId const nodeType{nodeTypeInt}; + PerNodeType &rPerNodeType = rData.m_nodePerType[nodeType]; // reserve node-to-machine partitions rPerNodeType.nodeToMach.data_reserve(rPerNodeType.m_connectCountTotal); for (NodeId node : rPerNodeType.nodeIds) { - rPerNodeType.nodeToMach.emplace(node, rPerNodeType.m_nodeConnectCount[node]); - lgrn::Span junction = rPerNodeType.nodeToMach[node]; + rPerNodeType.nodeToMach.emplace(node.value, rPerNodeType.m_nodeConnectCount[node]); + lgrn::Span junction = rPerNodeType.nodeToMach[node.value]; std::fill(std::begin(junction), std::end(junction), Junction{}); } // assign node-to-machine for (MachAnyId const mach : rData.m_machines.ids) { - lgrn::Span portSpan = rPerNodeType.machToNode[mach]; - lgrn::Span customSpan = rPerNodeType.m_machToNodeCustom[mach]; + lgrn::Span portSpan = rPerNodeType.machToNode[mach.value]; + lgrn::Span customSpan = rPerNodeType.m_machToNodeCustom[mach.value]; for (int i = 0; i < portSpan.size(); ++i) { @@ -223,7 +227,7 @@ VehicleData VehicleBuilder::finalize_release() continue; } - lgrn::Span const juncSpan = rPerNodeType.nodeToMach[node]; + lgrn::Span const juncSpan = rPerNodeType.nodeToMach[node.value]; // find empty spot // should always succeed, as they were reserved a few lines ago diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index 3b893e2f..792b210b 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -56,19 +56,19 @@ struct StructureLink struct PerNodeType : osp::link::Nodes { - using MachToNodeCustom_t = lgrn::IntArrayMultiMap; + // MachAnyId -> JuncCustom[] + using MachToNodeCustom_t = lgrn::IntArrayMultiMap; MachToNodeCustom_t m_machToNodeCustom; // parallel with m_machToNode entt::any m_nodeValues; - std::vector m_nodeConnectCount; + osp::KeyedVec m_nodeConnectCount; int m_connectCountTotal{0}; }; struct VehicleData { - using MachToNodeCustom_t = lgrn::IntArrayMultiMap; + // MachAnyId -> JuncCustom[] + using MachToNodeCustom_t = lgrn::IntArrayMultiMap; using MapPartToMachines_t = osp::active::ACtxParts::MapPartToMachines_t; VehicleData() = default; @@ -84,9 +84,9 @@ struct VehicleData lgrn::IntArrayMultiMap m_weldToParts; osp::link::Machines m_machines; - std::vector m_machToPart; + osp::KeyedVec m_machToPart; - std::vector m_nodePerType; + osp::KeyedVec m_nodePerType; }; /** @@ -95,6 +95,7 @@ struct VehicleData class VehicleBuilder { using MachAnyId = osp::link::MachAnyId; + using MachLocalId = osp::link::MachLocalId; using MachTypeId = osp::link::MachTypeId; using NodeId = osp::link::NodeId; using NodeTypeId = osp::link::NodeTypeId; diff --git a/src/adera/activescene/vehicles_vb_fn.h b/src/adera/activescene/vehicles_vb_fn.h index 1f2efbe2..49592723 100644 --- a/src/adera/activescene/vehicles_vb_fn.h +++ b/src/adera/activescene/vehicles_vb_fn.h @@ -63,7 +63,7 @@ struct ACtxVehicleSpawnVB std::vector remapWelds; osp::KeyedVec remapWeldOffsets; - std::vector machtypeCount; + osp::KeyedVec machtypeCount; std::vector remapMachs; osp::KeyedVec remapMachOffsets; diff --git a/src/adera/machines/links.h b/src/adera/machines/links.h index 557c0020..a2df5c48 100644 --- a/src/adera/machines/links.h +++ b/src/adera/machines/links.h @@ -33,9 +33,8 @@ namespace adera { using osp::link::PortEntry; -using osp::link::gc_ntSigFloat; -using osp::link::gc_sigIn; -using osp::link::gc_sigOut; +using osp::link::sigfloat_input; +using osp::link::sigfloat_output; inline osp::link::MachTypeId const gc_mtUserCtrl = osp::link::MachTypeReg_t::create(); inline osp::link::MachTypeId const gc_mtMagicRocket = osp::link::MachTypeReg_t::create(); @@ -45,33 +44,33 @@ constexpr osp::Vector3 gc_rocketForward{0.0f, 0.0f, 1.0f}; namespace ports_userctrl { -PortEntry const gc_throttleOut { gc_ntSigFloat, 0, gc_sigOut }; -PortEntry const gc_pitchOut { gc_ntSigFloat, 1, gc_sigOut }; -PortEntry const gc_yawOut { gc_ntSigFloat, 2, gc_sigOut }; -PortEntry const gc_rollOut { gc_ntSigFloat, 3, gc_sigOut }; +PortEntry const gc_throttleOut = sigfloat_output(0); +PortEntry const gc_pitchOut = sigfloat_output(1); +PortEntry const gc_yawOut = sigfloat_output(2); +PortEntry const gc_rollOut = sigfloat_output(3); } namespace ports_magicrocket { -PortEntry const gc_throttleIn { gc_ntSigFloat, 0, gc_sigIn }; -PortEntry const gc_multiplierIn { gc_ntSigFloat, 1, gc_sigIn }; +PortEntry const gc_throttleIn = sigfloat_input(0); +PortEntry const gc_multiplierIn = sigfloat_input(1); } namespace ports_rcsdriver { -PortEntry const gc_posXIn { gc_ntSigFloat, 0, gc_sigIn }; -PortEntry const gc_posYIn { gc_ntSigFloat, 1, gc_sigIn }; -PortEntry const gc_posZIn { gc_ntSigFloat, 2, gc_sigIn }; -PortEntry const gc_dirXIn { gc_ntSigFloat, 3, gc_sigIn }; -PortEntry const gc_dirYIn { gc_ntSigFloat, 4, gc_sigIn }; -PortEntry const gc_dirZIn { gc_ntSigFloat, 5, gc_sigIn }; -PortEntry const gc_cmdLinXIn { gc_ntSigFloat, 6, gc_sigIn }; -PortEntry const gc_cmdLinYIn { gc_ntSigFloat, 7, gc_sigIn }; -PortEntry const gc_cmdLinZIn { gc_ntSigFloat, 8, gc_sigIn }; -PortEntry const gc_cmdAngXIn { gc_ntSigFloat, 9, gc_sigIn }; -PortEntry const gc_cmdAngYIn { gc_ntSigFloat, 10, gc_sigIn }; -PortEntry const gc_cmdAngZIn { gc_ntSigFloat, 11, gc_sigIn }; -PortEntry const gc_throttleOut { gc_ntSigFloat, 12, gc_sigOut }; +PortEntry const gc_posXIn = sigfloat_input(0); +PortEntry const gc_posYIn = sigfloat_input(1); +PortEntry const gc_posZIn = sigfloat_input(2); +PortEntry const gc_dirXIn = sigfloat_input(3); +PortEntry const gc_dirYIn = sigfloat_input(4); +PortEntry const gc_dirZIn = sigfloat_input(5); +PortEntry const gc_cmdLinXIn = sigfloat_input(6); +PortEntry const gc_cmdLinYIn = sigfloat_input(7); +PortEntry const gc_cmdLinZIn = sigfloat_input(8); +PortEntry const gc_cmdAngXIn = sigfloat_input(9); +PortEntry const gc_cmdAngYIn = sigfloat_input(10); +PortEntry const gc_cmdAngZIn = sigfloat_input(11); +PortEntry const gc_throttleOut = sigfloat_output(12); } float thruster_influence(osp::Vector3 pos, osp::Vector3 dir, osp::Vector3 cmdLin, osp::Vector3 cmdAng) noexcept; diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index 4ebb64a9..442f61bf 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -555,7 +555,7 @@ static void assign_weld_rockets( } MachAnyId const mach = machtypeRocket.localToAny[pair.local]; - auto const& portSpan = rFloatNodes.machToNode[mach]; + auto const& portSpan = rFloatNodes.machToNode[mach.value]; NodeId const throttleIn = connected_node(portSpan, gc_throttleIn.port); NodeId const multiplierIn = connected_node(portSpan, gc_multiplierIn.port); diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index 82d072b2..8e1ae224 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -243,9 +243,10 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( remapMachTotal += bounds; machTotal += srcMachines.ids.size(); - for (MachTypeId type = 0; type < MachTypeReg_t::largest(); ++type) + for (std::uint16_t typeInt = 0; typeInt < MachTypeReg_t::largest(); ++typeInt) { - rVSVB.machtypeCount[type] += srcMachines.perType[type].localIds.size(); + MachTypeId const typeId{typeInt}; + rVSVB.machtypeCount[typeId] += srcMachines.perType[typeId].localIds.size(); } } @@ -280,7 +281,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( ++itDstMachIds; // Populate map for "VehicleBuilder MachAnyId -> ACtxParts MachAnyId" - rVSVB.remapMachs[remapMachOffset + srcMach] = dstMach; + rVSVB.remapMachs[remapMachOffset + srcMach.value] = dstMach; // Create ACtxParts MachLocalIds // MachLocalIds don't need a remap, since they can be obtained @@ -327,7 +328,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( // Update rScnParts machine->part map for (MachAnyId const srcMach : pVData->m_machines.ids) { - MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach]; + MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach.value]; PartId const srcPart = pVData->m_machToPart[srcMach]; PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart]; @@ -349,7 +350,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( MachinePair const& srcPair = srcPairs[i]; MachinePair& rDstPair = dstPairs[i]; MachAnyId const srcMach = pVData->m_machines.perType[srcPair.type].localToAny[srcPair.local]; - MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach]; + MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach.value]; MachTypeId const dstType = srcPair.type; MachLocalId const dstLocal = rLinks.machines.machToLocal[dstMach]; @@ -399,16 +400,17 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( auto machRemap = arrayView(std::as_const(rVSVB.remapMachs)).exceptPrefix(rVSVB.remapMachOffsets[vhId]); - for (NodeTypeId nodeType = 0; nodeType < NodeTypeReg_t::largest(); ++nodeType) + for (std::uint16_t nodeTypeInt = 0; nodeTypeInt < NodeTypeReg_t::largest(); ++nodeTypeInt) { + NodeTypeId const nodeType{nodeTypeInt}; PerNodeType const &rSrcNodeType = pVData->m_nodePerType[nodeType]; std::size_t const remapSize = rSrcNodeType.nodeIds.capacity(); auto nodeRemapOut = arrayView(rVSVB.remapNodes).sliceSize(nodeRemapUsed, remapSize); - remapNodeOffsets2d[vhId.value][nodeType] = nodeRemapUsed; + remapNodeOffsets2d[vhId.value][nodeTypeInt] = nodeRemapUsed; nodeRemapUsed += remapSize; copy_nodes(rSrcNodeType, pVData->m_machines, machRemap, - rLinks.nodePerType[nodeType], rLinks.machines, nodeRemapOut); + rLinks.nodePerType[NodeTypeId{nodeTypeInt}], rLinks.machines, nodeRemapOut); } } }); @@ -463,12 +465,12 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( PerNodeType const& srcFloatNodes = pVData->m_nodePerType[gc_ntSigFloat]; entt::any const& srcFloatValuesAny = srcFloatNodes.m_nodeValues; auto const& srcFloatValues = entt::any_cast< SignalValues_t >(srcFloatValuesAny); - std::size_t const nodeRemapOffset = remapNodeOffsets2d[vhId.value][gc_ntSigFloat]; + std::size_t const nodeRemapOffset = remapNodeOffsets2d[vhId.value][gc_ntSigFloat.value]; auto const nodeRemap = arrayView(rVSVB.remapNodes).exceptPrefix(nodeRemapOffset); for (NodeId const srcNode : srcFloatNodes.nodeIds) { - NodeId const dstNode = nodeRemap[srcNode]; + NodeId const dstNode = nodeRemap[srcNode.value]; rSigValFloat[dstNode] = srcFloatValues[srcNode]; } } @@ -535,16 +537,14 @@ FeatureDef const ftrSignalsFloat = feature_def("SignalsFloat", [] ( } rUpdMach.machTypesDirty.clear(); - // Sees which nodes changed, and writes into rUpdMach set dirty which MACHINES - // must be updated next - update_signal_nodes( - rSigUpdFloat.nodeDirty, - rFloatNodes.nodeToMach, - rLinks.machines, - arrayView(rSigUpdFloat.nodeNewValues), - rSigValFloat, - rUpdMach); + // Apply new node values and notify connected inputs + for (NodeId const nodeId : rSigUpdFloat.nodeDirty) + { + rSigValFloat[nodeId] = rSigUpdFloat.nodeNewValues[nodeId]; + notify_connected_inputs(nodeId, rFloatNodes.nodeToMach, rUpdMach); + } rSigUpdFloat.nodeDirty.clear(); + rSigUpdFloat.dirty = false; // Run tasks needed to update machine types that are dirty diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index b361c2ae..5381f57f 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -149,7 +149,7 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI PartId const part = rScnParts.machineToPart[anyId]; ActiveEnt const partEnt = rScnParts.partToActive[part]; - auto const& portSpan = floats.machToNode[anyId]; + auto const& portSpan = floats.machToNode[anyId.value]; NodeId const throttleIn = connected_node(portSpan, ports_magicrocket::gc_throttleIn.port); NodeId const multiplierIn = connected_node(portSpan, ports_magicrocket::gc_multiplierIn.port); @@ -212,7 +212,7 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI DrawEnt const drawEnt = rThrustIndicator.rktToDrawEnt[pair.local]; MachAnyId const anyId = rockets.localToAny[pair.local]; - auto const& portSpan = floats.machToNode[anyId]; + auto const& portSpan = floats.machToNode[anyId.value]; NodeId const throttleIn = connected_node(portSpan, ports_magicrocket::gc_throttleIn.port); NodeId const multiplierIn = connected_node(portSpan, ports_magicrocket::gc_multiplierIn.port); @@ -268,7 +268,7 @@ FeatureDef const ftrMachRCSDriver = feature_def("RCSDriver", [] ( for (MachLocalId const local : rUpdMach.localDirty[gc_mtRcsDriver]) { MachAnyId const mach = rRockets.localToAny[local]; - auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach]}; + auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach.value]}; NodeId const thrNode = connected_node(portSpan, ports_rcsdriver::gc_throttleOut.port); if (thrNode == lgrn::id_null()) @@ -383,9 +383,10 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( // Select a UsrCtrl machine when pressing the switch button if (rUserInput.button_state(rVhControls.btnSwitch).m_triggered) { - ++rVhControls.selectedUsrCtrl; + ++rVhControls.selectedUsrCtrl.value; bool found = false; - for (MachLocalId local = rVhControls.selectedUsrCtrl; local < rUsrCtrl.localIds.capacity(); ++local) + auto const capacity = std::uint32_t(rUsrCtrl.localIds.capacity()); + for (MachLocalId local = rVhControls.selectedUsrCtrl; local.value < capacity; ++local.value) { if (rUsrCtrl.localIds.exists(local)) { @@ -402,7 +403,7 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( } else { - OSP_LOG_INFO("Selected User Control: {}", rVhControls.selectedUsrCtrl); + OSP_LOG_INFO("Selected User Control: {}", rVhControls.selectedUsrCtrl.value); } } }); @@ -440,7 +441,7 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( PerMachType &rUsrCtrl = rLinks.machines.perType[gc_mtUserCtrl]; MachAnyId const mach = rUsrCtrl.localToAny[rVC.selectedUsrCtrl]; - auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach]}; + auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach.value]}; bool changed = false; auto const write_control = [&rSigValFloat, &rSigUpdFloat, &changed, portSpan] (PortEntry const& entry, float write, bool replace = true, float min = 0.0f, float max = 1.0f) diff --git a/src/osp/link/machines.cpp b/src/osp/link/machines.cpp index 696354e8..e8a63c94 100644 --- a/src/osp/link/machines.cpp +++ b/src/osp/link/machines.cpp @@ -41,7 +41,7 @@ void copy_nodes( for (NodeId const srcNode : rSrcNodes.nodeIds) { NodeId const dstNode = rDstNodes.nodeIds.create(); - remapNode[srcNode] = dstNode; + remapNode[srcNode.value] = dstNode; } // Copy node-to-machine connections @@ -50,17 +50,17 @@ void copy_nodes( + rSrcNodes.nodeToMach.data_size()); for (NodeId const srcNode : rSrcNodes.nodeIds) { - NodeId const dstNode = remapNode[srcNode]; - Span srcJunction = rSrcNodes.nodeToMach[srcNode]; - rDstNodes.nodeToMach.emplace(dstNode, srcJunction.size()); - Span dstJuncton = rDstNodes.nodeToMach[dstNode]; + NodeId const dstNode = remapNode[srcNode.value]; + Span srcJunction = rSrcNodes.nodeToMach[srcNode.value]; + rDstNodes.nodeToMach.emplace(dstNode.value, srcJunction.size()); + Span dstJuncton = rDstNodes.nodeToMach[dstNode.value]; auto dstJuncIt = std::begin(dstJuncton); for (Junction const& srcJunc : srcJunction) { MachTypeId const machType = srcJunc.type; MachAnyId const srcMach = rSrcMach.perType[machType].localToAny[srcJunc.local]; - MachAnyId const dstMach = remapMach[srcMach]; + MachAnyId const dstMach = remapMach[srcMach.value]; MachLocalId const dstLocal = rDstMach.machToLocal[dstMach]; dstJuncIt->local = dstLocal; @@ -77,18 +77,18 @@ void copy_nodes( + rSrcNodes.machToNode.data_size()); for (MachAnyId const srcMach : rSrcMach.ids) { - if (rSrcNodes.machToNode.contains(srcMach)) + if (rSrcNodes.machToNode.contains(srcMach.value)) { - Span srcPorts = rSrcNodes.machToNode[srcMach]; - MachAnyId const dstMach = remapMach[srcMach]; - rDstNodes.machToNode.emplace(dstMach, srcPorts.size()); - Span dstPorts = rDstNodes.machToNode[dstMach]; + Span srcPorts = rSrcNodes.machToNode[srcMach.value]; + MachAnyId const dstMach = remapMach[srcMach.value]; + rDstNodes.machToNode.emplace(dstMach.value, srcPorts.size()); + Span dstPorts = rDstNodes.machToNode[dstMach.value]; auto dstPortIt = std::begin(dstPorts); for (NodeId const srcNode : srcPorts) { *dstPortIt = (srcNode != lgrn::id_null()) - ? remapNode[srcNode] + ? remapNode[srcNode.value] : lgrn::id_null(); std::advance(dstPortIt, 1); diff --git a/src/osp/link/machines.h b/src/osp/link/machines.h index 86d4ddd9..89e7219a 100644 --- a/src/osp/link/machines.h +++ b/src/osp/link/machines.h @@ -28,7 +28,7 @@ #include "../core/copymove_macros.h" #include "../core/global_id.h" #include "../core/keyed_vector.h" - +#include "../core/strong_id.h" #include #include @@ -41,16 +41,16 @@ namespace osp::link { -using MachTypeId = uint16_t; -using MachAnyId = uint32_t; -using MachLocalId = uint32_t; +using MachTypeId = osp::StrongId< std::uint16_t, struct DummyForMachTypeId >; +using MachAnyId = osp::StrongId< std::uint32_t, struct DummyForMachAnyId >; +using MachLocalId = osp::StrongId< std::uint32_t, struct DummyForMachLocalId >; -using NodeTypeId = uint16_t; -using NodeId = uint32_t; +using NodeTypeId = osp::StrongId< std::uint16_t, struct DummyForNodeTypeId >; +using NodeId = osp::StrongId< std::uint32_t, struct DummyForNodeId >; -using PortId = uint16_t; -using JunctionId = uint16_t; -using JuncCustom = uint16_t; +using PortId = osp::StrongId< std::uint16_t, struct DummyForPortId >; +using JunctionId = osp::StrongId< std::uint16_t, struct DummyForJunctionId >; +using JuncCustom = std::uint16_t; using MachTypeReg_t = GlobalIdReg; using NodeTypeReg_t = GlobalIdReg; @@ -62,8 +62,8 @@ inline NodeTypeId const gc_ntSigFloat = NodeTypeReg_t::create(); */ struct PerMachType { - lgrn::IdRegistryStl localIds; - std::vector localToAny; + lgrn::IdRegistryStl localIds; + osp::KeyedVec localToAny; }; /** @@ -71,12 +71,12 @@ struct PerMachType */ struct Machines { - lgrn::IdRegistryStl ids; + lgrn::IdRegistryStl ids; - std::vector machTypes; - std::vector machToLocal; + osp::KeyedVec machTypes; + osp::KeyedVec machToLocal; - std::vector perType; + osp::KeyedVec perType; }; struct MachineUpdater @@ -91,14 +91,14 @@ struct MachineUpdater struct MachinePair { - MachLocalId local {lgrn::id_null()}; - MachTypeId type {lgrn::id_null()}; + MachLocalId local; + MachTypeId type; }; struct Junction { - MachLocalId local {lgrn::id_null()}; - MachTypeId type {lgrn::id_null()}; + MachLocalId local; + MachTypeId type; JuncCustom custom {0}; }; @@ -109,8 +109,8 @@ struct Nodes { // reminder: IntArrayMultiMap is kind of like an // std::vector< std::vector<...> > but more memory efficient - using NodeToMach_t = lgrn::IntArrayMultiMap; - using MachToNode_t = lgrn::IntArrayMultiMap; + using NodeToMach_t = lgrn::IntArrayMultiMap; + using MachToNode_t = lgrn::IntArrayMultiMap; lgrn::IdRegistryStl nodeIds; @@ -132,7 +132,7 @@ struct PortEntry inline NodeId connected_node(lgrn::Span portSpan, PortId port) noexcept { - return (portSpan.size() > port) ? portSpan[port] : lgrn::id_null(); + return (portSpan.size() > port.value) ? portSpan[port.value] : NodeId{}; } void copy_machines( @@ -148,5 +148,4 @@ void copy_nodes( Machines &rDstMach, ArrayView remapNodeOut); - } // namespace osp::wire diff --git a/src/osp/link/signal.h b/src/osp/link/signal.h index 39249faf..131de67a 100644 --- a/src/osp/link/signal.h +++ b/src/osp/link/signal.h @@ -32,8 +32,11 @@ namespace osp::link constexpr JuncCustom gc_sigIn = 0; constexpr JuncCustom gc_sigOut = 1; +constexpr PortEntry sigfloat_input(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigIn}; } +constexpr PortEntry sigfloat_output(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigOut}; } + template -using SignalValues_t = std::vector; +using SignalValues_t = osp::KeyedVec; template struct UpdateNodes @@ -51,39 +54,19 @@ struct UpdateNodes } }; -template -bool update_signal_nodes( - RANGE_T const& toUpdate, - Nodes::NodeToMach_t const& nodeToMach, - Machines const& machines, - ArrayView newValues, - ArrayView currentValues, - MachineUpdater& rUpdMach) +inline void notify_connected_inputs(NodeId const nodeId, Nodes::NodeToMach_t const& nodeToMach, MachineUpdater& rUpdMach) { - bool somethingNotified = false; - - for (uint32_t const node : toUpdate) + for (Junction junc : nodeToMach[nodeId.value]) { - // Apply node value changes - currentValues[node] = newValues[node]; - - // Notify connected inputs - for (Junction junc : nodeToMach[node]) + if (junc.custom == gc_sigIn) { - if (junc.custom == gc_sigIn) - { - somethingNotified = true; + // A machine of type "junc.m_type" has new values to read + rUpdMach.machTypesDirty.insert(junc.type); - // A machine of type "junc.m_type" has new values to read - rUpdMach.machTypesDirty.insert(junc.type); - - // Specify using local Id on which machine needs to update - rUpdMach.localDirty[junc.type].insert(junc.local); - } + // Specify using local Id on which machine needs to update + rUpdMach.localDirty[junc.type].insert(junc.local); } } - - return somethingNotified; } } // namespace osp::wire From f7a7de183705d7c39809b12f523abcc317caa556 Mon Sep 17 00:00:00 2001 From: nnicdao Date: Sat, 27 Dec 2025 16:46:42 -0800 Subject: [PATCH 3/7] Refactor PartIds and WeldIds to use Strong Id types --- src/adera/activescene/VehicleBuilder.cpp | 12 +++++------ src/adera/activescene/VehicleBuilder.h | 11 +++++----- src/adera/activescene/vehicles_vb_fn.cpp | 18 ++++++++-------- src/adera/activescene/vehicles_vb_fn.h | 2 +- src/adera_app/features/jolt.cpp | 8 +++---- src/adera_app/features/vehicles.cpp | 10 ++++----- src/adera_app/features/vehicles_machines.cpp | 2 +- src/osp/activescene/vehicles.h | 22 ++++++++------------ src/osp/link/machines.h | 4 ++-- 9 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/adera/activescene/VehicleBuilder.cpp b/src/adera/activescene/VehicleBuilder.cpp index b97c4b2b..6d117a57 100644 --- a/src/adera/activescene/VehicleBuilder.cpp +++ b/src/adera/activescene/VehicleBuilder.cpp @@ -71,13 +71,13 @@ WeldId VehicleBuilder::weld(osp::ArrayView toWeld) WeldId const weld = m_data->m_weldIds.create(); m_data->m_weldToParts.ids_reserve(m_data->m_weldIds.capacity()); - PartId *pPartInWeld = m_data->m_weldToParts.emplace(weld, toWeld.size()); + PartId *pPartInWeld = m_data->m_weldToParts.emplace(weld.value, toWeld.size()); for (PartToWeld const& set : toWeld) { - m_data->m_partTransformWeld[set.m_part] = set.m_transform; + m_data->m_partTransformWeld[set.m_part.value] = set.m_transform; - m_data->m_partToWeld[set.m_part] = weld; + m_data->m_partToWeld[set.m_part.value] = weld; (*pPartInWeld) = set.m_part; std::advance(pPartInWeld, 1); } @@ -255,7 +255,7 @@ VehicleData VehicleBuilder::finalize_release() rData.m_partToMachines.data_reserve(rData.m_machines.ids.capacity()); for (PartId const part : rData.m_partIds) { - rData.m_partToMachines.emplace(part, m_partMachCount[part]); + rData.m_partToMachines.emplace(part.value, m_partMachCount[part.value]); } // Assign part-to-machine partitions @@ -264,11 +264,11 @@ VehicleData VehicleBuilder::finalize_release() MachLocalId const local = rData.m_machines.machToLocal[mach]; MachTypeId const type = rData.m_machines.machTypes[mach]; PartId const part = rData.m_machToPart[mach]; - auto const machines = lgrn::Span{rData.m_partToMachines[part]}; + auto const machines = lgrn::Span{rData.m_partToMachines[part.value]}; // Reuse machine count to track how many are currently added. // By the end, these should all be zero - auto &rPartMachCount = m_partMachCount[part]; + auto &rPartMachCount = m_partMachCount[part.value]; assert(rPartMachCount != 0); -- rPartMachCount; diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index 792b210b..05dd4a6b 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -25,9 +25,10 @@ #pragma once #include +#include +#include #include #include -#include #include @@ -56,8 +57,7 @@ struct StructureLink struct PerNodeType : osp::link::Nodes { - // MachAnyId -> JuncCustom[] - using MachToNodeCustom_t = lgrn::IntArrayMultiMap; + using MachToNodeCustom_t = lgrn::IntArrayMultiMap; MachToNodeCustom_t m_machToNodeCustom; // parallel with m_machToNode entt::any m_nodeValues; @@ -67,9 +67,8 @@ struct PerNodeType : osp::link::Nodes struct VehicleData { - // MachAnyId -> JuncCustom[] - using MachToNodeCustom_t = lgrn::IntArrayMultiMap; using MapPartToMachines_t = osp::active::ACtxParts::MapPartToMachines_t; + using MapWeldToParts_t = lgrn::IntArrayMultiMap; VehicleData() = default; OSP_MOVE_ONLY_CTOR(VehicleData); @@ -81,7 +80,7 @@ struct VehicleData MapPartToMachines_t m_partToMachines; lgrn::IdRegistryStl m_weldIds; - lgrn::IntArrayMultiMap m_weldToParts; + MapWeldToParts_t m_weldToParts; osp::link::Machines m_machines; osp::KeyedVec m_machToPart; diff --git a/src/adera/activescene/vehicles_vb_fn.cpp b/src/adera/activescene/vehicles_vb_fn.cpp index ed31a38b..894b6337 100644 --- a/src/adera/activescene/vehicles_vb_fn.cpp +++ b/src/adera/activescene/vehicles_vb_fn.cpp @@ -130,7 +130,7 @@ void SysVehicleSpawnVB::create_parts_and_welds(ACtxVehicleSpawn& rVehicleSpawn, ++itDstPartIds; // Populate map for "VehicleBuilder PartId -> ACtxParts PartId" - rVSVB.remapParts[remapPartOffset + srcPart] = dstPart; + rVSVB.remapParts[remapPartOffset + srcPart.value] = dstPart; } for (WeldId const srcWeld : pVData->m_weldIds) @@ -140,17 +140,17 @@ void SysVehicleSpawnVB::create_parts_and_welds(ACtxVehicleSpawn& rVehicleSpawn, // Populate map for "VehicleBuilder WeldId -> ACtxParts WeldId" // rVehicleSpawnVB.remapWelds - rVSVB.remapWelds[remapWeldOffset + srcWeld] = dstWeld; + rVSVB.remapWelds[remapWeldOffset + srcWeld.value] = dstWeld; // Use remaps to connect ACtxParts WeldIds and PartIds // rScnParts.m_partToWeld and rScnParts.m_weldToParts - auto const srcWeldPartSpan = pVData->m_weldToParts[srcWeld]; - WeldId *pDstWeldPartOut = rScnParts.weldToParts.emplace(dstWeld, srcWeldPartSpan.size()); + auto const srcWeldPartSpan = pVData->m_weldToParts[srcWeld.value]; + PartId *pDstWeldPartOut = rScnParts.weldToParts.emplace(dstWeld.value, srcWeldPartSpan.size()); for (PartId const srcPart : srcWeldPartSpan) { - PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart]; + PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart.value]; (*pDstWeldPartOut) = dstPart; std::advance(pDstWeldPartOut, 1); @@ -180,13 +180,13 @@ void SysVehicleSpawnVB::request_prefabs(ACtxVehicleSpawn& rVehicleSpawn, ACtxVeh } // Copy Part data from VehicleBuilder to scene - for (uint32_t srcPart : pVData->m_partIds) + for (PartId srcPart : pVData->m_partIds) { PartId const dstPart = *itDstPartIds; ++itDstPartIds; - PrefabPair const& prefabPairSrc = pVData->m_partPrefabs[srcPart]; - rScnParts.partTransformWeld[dstPart] = pVData->m_partTransformWeld[srcPart]; + PrefabPair const& prefabPairSrc = pVData->m_partPrefabs[srcPart.value]; + rScnParts.partTransformWeld[dstPart] = pVData->m_partTransformWeld[srcPart.value]; // Add Prefab and Part init events (*itPrefabOut) = rPrefabs.spawnRequest.size(); @@ -195,7 +195,7 @@ void SysVehicleSpawnVB::request_prefabs(ACtxVehicleSpawn& rVehicleSpawn, ACtxVeh rPrefabs.spawnRequest.push_back(TmpPrefabRequest{ .m_importerRes = prefabPairSrc.m_importer, .m_prefabId = prefabPairSrc.m_prefabId, - .m_pTransform = &pVData->m_partTransformWeld[srcPart] + .m_pTransform = &pVData->m_partTransformWeld[srcPart.value] }); } } diff --git a/src/adera/activescene/vehicles_vb_fn.h b/src/adera/activescene/vehicles_vb_fn.h index 49592723..a2e6aca6 100644 --- a/src/adera/activescene/vehicles_vb_fn.h +++ b/src/adera/activescene/vehicles_vb_fn.h @@ -60,7 +60,7 @@ struct ACtxVehicleSpawnVB std::vector remapParts; osp::KeyedVec remapPartOffsets; - std::vector remapWelds; + std::vector remapWelds; osp::KeyedVec remapWeldOffsets; osp::KeyedVec machtypeCount; diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index 442f61bf..8b5760d6 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -355,7 +355,7 @@ FeatureDef const ftrVehicleSpawnJolt = feature_def("VehicleSpawnJolt", [] ( { // Count parts in this weld first std::size_t entCount = 0; - for (PartId const part : rScnParts.weldToParts[weld]) + for (PartId const part : rScnParts.weldToParts[weld.value]) { SpPartId const newPart = rVehicleSpawn.partToSpawned[part]; uint32_t const prefabInit = rVehicleSpawn.spawnedPrefabs[newPart]; @@ -369,7 +369,7 @@ FeatureDef const ftrVehicleSpawnJolt = feature_def("VehicleSpawnJolt", [] ( SubtreeBuilder bldRoot = SysSceneGraph::add_descendants(rBasic.m_scnGraph, entCount + 1); SubtreeBuilder bldWeld = bldRoot.add_child(weldEnt, entCount); - for (PartId const part : rScnParts.weldToParts[weld]) + for (PartId const part : rScnParts.weldToParts[weld.value]) { SpPartId const newPart = rVehicleSpawn.partToSpawned[part]; uint32_t const prefabInit = rVehicleSpawn.spawnedPrefabs[newPart]; @@ -542,12 +542,12 @@ static void assign_weld_rockets( // Each weld consists of multiple parts, iterate them all. Note that each part has their own // individual transforms, so math is needed to calculate stuff with thrust direction and // center-of-mass. - for (PartId const part : rScnParts.weldToParts[weld]) + for (PartId const part : rScnParts.weldToParts[weld.value]) { auto const sizeBefore = rRocketsFoundTemp.size(); // Each part contains Machines, some of which may be rockets. - for (MachinePair const pair : rScnParts.partToMachines[part]) + for (MachinePair const pair : rScnParts.partToMachines[part.value]) { if (pair.type != gc_mtMagicRocket) { diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index 8e1ae224..45dc07a2 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -330,7 +330,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( { MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach.value]; PartId const srcPart = pVData->m_machToPart[srcMach]; - PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart]; + PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart.value]; rScnParts.machineToPart[dstMach] = dstPart; } @@ -338,12 +338,12 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( // Update rScnParts part->machine multimap for (PartId const srcPart : pVData->m_partIds) { - PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart]; + PartId const dstPart = rVSVB.remapParts[remapPartOffset + srcPart.value]; - auto const& srcPairs = pVData->m_partToMachines[srcPart]; + auto const& srcPairs = pVData->m_partToMachines[srcPart.value]; - rScnParts.partToMachines.emplace(dstPart, srcPairs.size()); - auto dstPairs = rScnParts.partToMachines[dstPart]; + rScnParts.partToMachines.emplace(dstPart.value, srcPairs.size()); + auto dstPairs = rScnParts.partToMachines[dstPart.value]; for (int i = 0; i < srcPairs.size(); ++i) { diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index 5381f57f..9f191d2f 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -205,7 +205,7 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI PartId const part = rScnParts.activeToPart[ent]; ActiveEnt const partEnt = rScnParts.partToActive[part]; - for (MachinePair const pair : rScnParts.partToMachines[part]) + for (MachinePair const pair : rScnParts.partToMachines[part.value]) { if (pair.type == gc_mtMagicRocket) { diff --git a/src/osp/activescene/vehicles.h b/src/osp/activescene/vehicles.h index 6a913c45..54010386 100644 --- a/src/osp/activescene/vehicles.h +++ b/src/osp/activescene/vehicles.h @@ -26,22 +26,18 @@ #include "active_ent.h" -#include "../core/array_view.h" #include "../core/keyed_vector.h" #include "../core/math_types.h" #include "../link/machines.h" -#include "../vehicles/prefabs.h" #include #include -#include - namespace osp::active { -using PartId = uint32_t; -using WeldId = uint32_t; +using PartId = osp::StrongId; +using WeldId = osp::StrongId; struct ACtxLinks { @@ -53,17 +49,17 @@ struct ACtxLinks struct ACtxParts { - using MapPartToMachines_t = lgrn::IntArrayMultiMap; + using MapPartToMachines_t = lgrn::IntArrayMultiMap; + using MapWeldToPart_t = lgrn::IntArrayMultiMap; lgrn::IdRegistryStl partIds; - //KeyedVec partPrefabs; KeyedVec partTransformWeld; ///< Part's transform relative to the weld it's part of std::vector partDirty; lgrn::IdRegistryStl weldIds; std::vector weldDirty; - lgrn::IntArrayMultiMap weldToParts; + MapWeldToPart_t weldToParts; KeyedVec partToWeld; MapPartToMachines_t partToMachines; @@ -76,10 +72,10 @@ struct ACtxParts }; -using SpVehicleId = StrongId; -using SpPartId = StrongId; -using SpWeldId = StrongId; -using SpMachAnyId = StrongId; +using SpVehicleId = StrongId; +using SpPartId = StrongId; +using SpWeldId = StrongId; +using SpMachAnyId = StrongId; struct ACtxVehicleSpawn { diff --git a/src/osp/link/machines.h b/src/osp/link/machines.h index 89e7219a..63b26519 100644 --- a/src/osp/link/machines.h +++ b/src/osp/link/machines.h @@ -109,8 +109,8 @@ struct Nodes { // reminder: IntArrayMultiMap is kind of like an // std::vector< std::vector<...> > but more memory efficient - using NodeToMach_t = lgrn::IntArrayMultiMap; - using MachToNode_t = lgrn::IntArrayMultiMap; + using NodeToMach_t = lgrn::IntArrayMultiMap; + using MachToNode_t = lgrn::IntArrayMultiMap; lgrn::IdRegistryStl nodeIds; From 8cd41f5b04fe7b9e373a85cc5f0ce309663e6383 Mon Sep 17 00:00:00 2001 From: nnicdao Date: Sun, 28 Dec 2025 22:36:07 -0800 Subject: [PATCH 4/7] Add 'GlobalLinkInfo' --- src/adera/activescene/VehicleBuilder.h | 7 +- src/adera/activescene/vehicles_vb_fn.h | 5 +- src/adera/machines/links.cpp | 3 - src/adera/machines/links.h | 6 +- src/adera_app/features/jolt.cpp | 6 +- src/adera_app/features/vehicles.cpp | 41 +++++----- src/adera_app/features/vehicles_machines.cpp | 18 ++--- src/osp/activescene/vehicles.h | 4 +- src/osp/link/machines.cpp | 18 +++-- src/osp/link/machines.h | 85 ++++++++++++++------ src/osp/link/signal.h | 11 ++- 11 files changed, 129 insertions(+), 75 deletions(-) diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index 05dd4a6b..031ca96b 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -55,7 +55,7 @@ struct StructureLink PartId m_less; }; -struct PerNodeType : osp::link::Nodes +struct PerNodeType : osp::link::NodeConnections { using MachToNodeCustom_t = lgrn::IntArrayMultiMap; @@ -113,9 +113,10 @@ class VehicleBuilder VehicleBuilder(osp::Resources *pResources) : m_pResources{pResources} { + auto const& info = osp::link::GlobalLinkInfo::instance(); auto &rData = m_data.emplace(); - rData.m_machines.perType.resize(osp::link::MachTypeReg_t::size()); - rData.m_nodePerType.resize(osp::link::NodeTypeReg_t::size()); + rData.m_machines.perType.resize(info.machtypeIds.capacity()); + rData.m_nodePerType.resize(info.nodetypeIds.capacity()); index_prefabs(); }; diff --git a/src/adera/activescene/vehicles_vb_fn.h b/src/adera/activescene/vehicles_vb_fn.h index a2e6aca6..4260c21b 100644 --- a/src/adera/activescene/vehicles_vb_fn.h +++ b/src/adera/activescene/vehicles_vb_fn.h @@ -46,13 +46,13 @@ struct ACtxVehicleSpawnVB inline Corrade::Containers::StridedArrayView2D remap_node_offsets_2d() noexcept { return {Corrade::Containers::arrayView(remapNodeOffsets.data(), remapNodeOffsets.size()), - {dataVB.size(), osp::link::NodeTypeReg_t::size()}}; + {dataVB.size(), remapNodeOffsetStride}}; } inline Corrade::Containers::StridedArrayView2D remap_node_offsets_2d() const noexcept { return {Corrade::Containers::arrayView(remapNodeOffsets.data(), remapNodeOffsets.size()), - {dataVB.size(), osp::link::NodeTypeReg_t::size()}}; + {dataVB.size(), remapNodeOffsetStride}}; } osp::KeyedVec dataVB; @@ -71,6 +71,7 @@ struct ACtxVehicleSpawnVB // An offset can exist for each pair of [New Vehicle, Node Type] std::vector remapNodes; osp::KeyedVec remapNodeOffsets; + std::size_t remapNodeOffsetStride; }; class SysVehicleSpawnVB diff --git a/src/adera/machines/links.cpp b/src/adera/machines/links.cpp index eb5fd6e2..c59f314c 100644 --- a/src/adera/machines/links.cpp +++ b/src/adera/machines/links.cpp @@ -26,9 +26,6 @@ using namespace osp; -using osp::link::MachTypeReg_t; -using osp::link::MachTypeId; - namespace adera { diff --git a/src/adera/machines/links.h b/src/adera/machines/links.h index a2df5c48..a830b79e 100644 --- a/src/adera/machines/links.h +++ b/src/adera/machines/links.h @@ -36,9 +36,9 @@ using osp::link::PortEntry; using osp::link::sigfloat_input; using osp::link::sigfloat_output; -inline osp::link::MachTypeId const gc_mtUserCtrl = osp::link::MachTypeReg_t::create(); -inline osp::link::MachTypeId const gc_mtMagicRocket = osp::link::MachTypeReg_t::create(); -inline osp::link::MachTypeId const gc_mtRcsDriver = osp::link::MachTypeReg_t::create(); +inline osp::link::MachTypeId const gc_mtUserCtrl = osp::link::GlobalLinkInfo::instance().create_machtype(); +inline osp::link::MachTypeId const gc_mtMagicRocket = osp::link::GlobalLinkInfo::instance().create_machtype(); +inline osp::link::MachTypeId const gc_mtRcsDriver = osp::link::GlobalLinkInfo::instance().create_machtype(); constexpr osp::Vector3 gc_rocketForward{0.0f, 0.0f, 1.0f}; diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index 8b5760d6..4bbd7c69 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -521,7 +521,7 @@ static void assign_weld_rockets( ACtxParts const &rScnParts, ACtxJoltWorld &rJolt, ACtxRocketsJolt &rRocketsJolt, - Nodes const &rFloatNodes, + NodeConnections const &rFloatNodes, PerMachType const &machtypeRocket, std::vector &rRocketsFoundTemp) { @@ -694,8 +694,8 @@ FeatureDef const ftrRocketThrustJolt = feature_def("RocketThrustJolt", [] ( { using adera::gc_mtMagicRocket; - Nodes const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - PerMachType const &machtypeRocket = rLinks.machines.perType[gc_mtMagicRocket]; + NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + PerMachType const &machtypeRocket = rLinks.machines.perType[gc_mtMagicRocket]; rRocketsJolt.m_bodyRockets.ids_reserve(rJolt.m_bodyIds.size()); rRocketsJolt.m_bodyRockets.data_reserve(rLinks.machines.perType[gc_mtMagicRocket].localIds.capacity()); diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index 45dc07a2..06ea4a5f 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -87,11 +87,11 @@ FeatureDef const ftrParts = feature_def("Parts", [] ( auto &rScnParts = rFB.data_emplace< ACtxParts > (parts.di.scnParts); // Resize containers to fit all existing MachTypeIds and NodeTypeIds - // These Global IDs are dynamically initialized just as the program starts - rUpdMach.machTypesDirty.resize(MachTypeReg_t::size()); - rUpdMach.localDirty .resize(MachTypeReg_t::size()); - rLinks.machines.perType.resize(MachTypeReg_t::size()); - rLinks.nodePerType .resize(NodeTypeReg_t::size()); + std::size_t const machTypeIdCapacity = GlobalLinkInfo::instance().machtypeIds.capacity(); + rUpdMach.machTypesDirty.resize(machTypeIdCapacity); + rUpdMach.localDirty .resize(machTypeIdCapacity); + rLinks.machines.perType.resize(machTypeIdCapacity); + rLinks.nodePerType .resize(machTypeIdCapacity); rFB.task() .name ("Clear Part dirty vectors after use") @@ -188,7 +188,9 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( rFB.pipeline(vhclSpawnVB.pl.remapMachs) .parent(mainApp.loopblks.mainLoop); rFB.pipeline(vhclSpawnVB.pl.remapNodes) .parent(mainApp.loopblks.mainLoop); - rFB.data_emplace< ACtxVehicleSpawnVB >(vhclSpawnVB.di.vehicleSpawnVB); + auto& rVehicleSpawnVB = rFB.data_emplace< ACtxVehicleSpawnVB >(vhclSpawnVB.di.vehicleSpawnVB); + + rVehicleSpawnVB.machtypeCount.resize(GlobalLinkInfo::instance().machtypeIds.capacity()); rFB.task() .name ("Create PartIds and WeldIds for vehicles to spawn from VehicleData") @@ -217,13 +219,14 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( std::size_t const newVehicleCount = rVehicleSpawn.new_vehicle_count(); ACtxVehicleSpawnVB &rVSVB = rVehicleSpawnVB; + GlobalLinkInfo const& linkInfo = GlobalLinkInfo::instance(); + // Count total machines, and calculate offsets for remaps. std::size_t machTotal = 0; std::size_t remapMachTotal = 0; - rVSVB.machtypeCount.clear(); - rVSVB.machtypeCount.resize(MachTypeReg_t::size(), 0); + std::fill(rVSVB.machtypeCount.begin(), rVSVB.machtypeCount.end(), 0); rVSVB.remapMachOffsets.resize(newVehicleCount); @@ -243,9 +246,8 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( remapMachTotal += bounds; machTotal += srcMachines.ids.size(); - for (std::uint16_t typeInt = 0; typeInt < MachTypeReg_t::largest(); ++typeInt) + for (MachTypeId const typeId : linkInfo.machtypeIds) { - MachTypeId const typeId{typeInt}; rVSVB.machtypeCount[typeId] += srcMachines.perType[typeId].localIds.size(); } } @@ -370,7 +372,11 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( std::size_t const newVehicleCount = rVehicleSpawn.new_vehicle_count(); ACtxVehicleSpawnVB &rVSVB = rVehicleSpawnVB; - rVSVB.remapNodeOffsets.resize(newVehicleCount * NodeTypeReg_t::size()); + GlobalLinkInfo const& linkInfo = GlobalLinkInfo::instance(); + + rVSVB.remapNodeOffsetStride = GlobalLinkInfo::instance().nodetypeIds.capacity(); + rVSVB.remapNodeOffsets.resize(newVehicleCount * rVSVB.remapNodeOffsetStride); + auto remapNodeOffsets2d = rVSVB.remap_node_offsets_2d(); // Add up bounds needed for all nodes of every type for remaps @@ -400,17 +406,16 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( auto machRemap = arrayView(std::as_const(rVSVB.remapMachs)).exceptPrefix(rVSVB.remapMachOffsets[vhId]); - for (std::uint16_t nodeTypeInt = 0; nodeTypeInt < NodeTypeReg_t::largest(); ++nodeTypeInt) + for (NodeTypeId const nodeType : linkInfo.nodetypeIds) { - NodeTypeId const nodeType{nodeTypeInt}; PerNodeType const &rSrcNodeType = pVData->m_nodePerType[nodeType]; std::size_t const remapSize = rSrcNodeType.nodeIds.capacity(); auto nodeRemapOut = arrayView(rVSVB.remapNodes).sliceSize(nodeRemapUsed, remapSize); - remapNodeOffsets2d[vhId.value][nodeTypeInt] = nodeRemapUsed; + remapNodeOffsets2d[vhId.value][nodeType.value] = nodeRemapUsed; nodeRemapUsed += remapSize; copy_nodes(rSrcNodeType, pVData->m_machines, machRemap, - rLinks.nodePerType[NodeTypeId{nodeTypeInt}], rLinks.machines, nodeRemapOut); + rLinks.nodePerType[nodeType], rLinks.machines, nodeRemapOut); } } }); @@ -444,8 +449,8 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( .args ({ vhclSpawn.di.vehicleSpawn, vhclSpawnVB.di.vehicleSpawnVB, parts.di.scnParts, links.di.links, sigFloat.di.sigValFloat, sigFloat.di.sigUpdFloat}) .func ([] (ACtxVehicleSpawn& rVehicleSpawn, ACtxVehicleSpawnVB const& rVehicleSpawnVB, ACtxParts& rScnParts, ACtxLinks &rLinks, SignalValues_t& rSigValFloat, UpdateNodes& rSigUpdFloat) noexcept { - Nodes const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - std::size_t const maxNodes = rFloatNodes.nodeIds.capacity(); + NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + std::size_t const maxNodes = rFloatNodes.nodeIds.capacity(); rSigUpdFloat.nodeNewValues.resize(maxNodes); rSigUpdFloat.nodeDirty.resize(maxNodes); rSigValFloat.resize(maxNodes); @@ -526,7 +531,7 @@ FeatureDef const ftrSignalsFloat = feature_def("SignalsFloat", [] ( return; // Not dirty, nothing to do } - Nodes const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; // NOTE: The various use of reset() clear entire bit arrays, which may or may // not be expensive. They likely optimize to memset diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index 9f191d2f..f2f1f180 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -137,9 +137,9 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI .args ({ comScn.di.basic, scnRender.di.scnRender, comScn.di.drawing, comScn.di.drawingRes, parts.di.scnParts, links.di.links, sigFloat.di.sigValFloat, rktIndicate.di.indicator}) .func([] (ACtxBasic& rBasic, ACtxSceneRender &rScnRender, ACtxDrawing& rDrawing, ACtxDrawingRes const& rDrawingRes, ACtxParts const& rScnParts, ACtxLinks const& rLinks, SignalValues_t const& rSigValFloat, ThrustIndicator& rIndicator) noexcept { - Material &rMat = rScnRender.m_materials[rIndicator.material]; - PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; - Nodes const &floats = rLinks.nodePerType[gc_ntSigFloat]; + Material &rMat = rScnRender.m_materials[rIndicator.material]; + PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; + NodeConnections const &floats = rLinks.nodePerType[gc_ntSigFloat]; for (MachLocalId const localId : rockets.localIds) { @@ -199,8 +199,8 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI auto &rLinks = *static_cast< ACtxLinks* > (data[2]); auto &rSigValFloat = *static_cast< SignalValues_t* > (data[3]); - PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; - Nodes const &floats = rLinks.nodePerType[gc_ntSigFloat]; + PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; + NodeConnections const &floats = rLinks.nodePerType[gc_ntSigFloat]; PartId const part = rScnParts.activeToPart[ent]; ActiveEnt const partEnt = rScnParts.partToActive[part]; @@ -262,8 +262,8 @@ FeatureDef const ftrMachRCSDriver = feature_def("RCSDriver", [] ( .args ({ links.di.links, links.di.updMach, sigFloat.di.sigValFloat, sigFloat.di.sigUpdFloat}) .func ([] (ACtxLinks& rLinks, MachineUpdater& rUpdMach, SignalValues_t& rSigValFloat, UpdateNodes& rSigUpdFloat) noexcept { - Nodes const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - PerMachType &rRockets = rLinks.machines.perType[gc_mtRcsDriver]; + NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + PerMachType &rRockets = rLinks.machines.perType[gc_mtRcsDriver]; for (MachLocalId const local : rUpdMach.localDirty[gc_mtRcsDriver]) { @@ -425,8 +425,8 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( return; // No vehicle selected } - Nodes const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - float const thrRate = deltaTimeIn; + NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + float const thrRate = deltaTimeIn; float const thrChange = held(rVC.btnThrMore, thrRate) - held(rVC.btnThrLess, thrRate) diff --git a/src/osp/activescene/vehicles.h b/src/osp/activescene/vehicles.h index 54010386..65bee5a2 100644 --- a/src/osp/activescene/vehicles.h +++ b/src/osp/activescene/vehicles.h @@ -43,8 +43,8 @@ struct ACtxLinks { ACtxLinks() = default; OSP_MOVE_ONLY_CTOR_ASSIGN(ACtxLinks); - link::Machines machines; - KeyedVec nodePerType; + link::Machines machines; + KeyedVec nodePerType; }; struct ACtxParts diff --git a/src/osp/link/machines.cpp b/src/osp/link/machines.cpp index e8a63c94..84166c20 100644 --- a/src/osp/link/machines.cpp +++ b/src/osp/link/machines.cpp @@ -27,13 +27,19 @@ namespace osp::link { +GlobalLinkInfo& GlobalLinkInfo::instance() +{ + static GlobalLinkInfo info; + return info; +} + void copy_nodes( - Nodes const &rSrcNodes, - Machines const &rSrcMach, - Corrade::Containers::ArrayView remapMach, - Nodes &rDstNodes, - Machines &rDstMach, - Corrade::Containers::ArrayView remapNode) + NodeConnections const &rSrcNodes, + Machines const &rSrcMach, + Corrade::Containers::ArrayView remapMach, + NodeConnections &rDstNodes, + Machines &rDstMach, + Corrade::Containers::ArrayView remapNode) { using lgrn::Span; diff --git a/src/osp/link/machines.h b/src/osp/link/machines.h index 63b26519..94030b24 100644 --- a/src/osp/link/machines.h +++ b/src/osp/link/machines.h @@ -37,25 +37,61 @@ #include #include +#include + namespace osp::link { -using MachTypeId = osp::StrongId< std::uint16_t, struct DummyForMachTypeId >; -using MachAnyId = osp::StrongId< std::uint32_t, struct DummyForMachAnyId >; -using MachLocalId = osp::StrongId< std::uint32_t, struct DummyForMachLocalId >; +using MachTypeId = osp::StrongId< std::uint16_t, struct DummyForMachTypeId >; +using MachAnyId = osp::StrongId< std::uint32_t, struct DummyForMachAnyId >; +using MachLocalId = osp::StrongId< std::uint32_t, struct DummyForMachLocalId >; + +using NodeTypeId = osp::StrongId< std::uint16_t, struct DummyForNodeTypeId >; +using TransmitModeId = osp::StrongId< std::uint16_t, struct DummyForTransmitModeId >; +using NodeId = osp::StrongId< std::uint32_t, struct DummyForNodeId >; + +using PortId = osp::StrongId< std::uint16_t, struct DummyForPortId >; +using JunctionId = osp::StrongId< std::uint16_t, struct DummyForJunctionId >; +using JuncCustom = std::uint16_t; + +struct NodeTypeInfo +{ + TransmitModeId transmitMode; + std::size_t nodeDataSize; +}; + +struct GlobalLinkInfo +{ + // TODO: maybe put some private or more encapsulation stuff here; just made this work for now -using NodeTypeId = osp::StrongId< std::uint16_t, struct DummyForNodeTypeId >; -using NodeId = osp::StrongId< std::uint32_t, struct DummyForNodeId >; + static GlobalLinkInfo& instance(); + + MachTypeId create_machtype() { return machtypeIds.create(); }; + + TransmitModeId create_transmitmode() { return transmitmodeIds.create(); }; + + NodeTypeId create_nodetype(NodeTypeInfo info) + { + NodeTypeId const id = nodetypeIds.create(); + infoOfNodetype.resize(nodetypeIds.capacity()); + infoOfNodetype[id] = info; + return id; + } + + osp::KeyedVec infoOfNodetype; + + lgrn::IdRegistryStl machtypeIds; + lgrn::IdRegistryStl transmitmodeIds; + lgrn::IdRegistryStl nodetypeIds; +}; + +// Not yet used, for example only +inline TransmitModeId const gc_tmStructure = GlobalLinkInfo::instance().transmitmodeIds.create(); +inline TransmitModeId const gc_tmSimpleFluid = GlobalLinkInfo::instance().transmitmodeIds.create(); -using PortId = osp::StrongId< std::uint16_t, struct DummyForPortId >; -using JunctionId = osp::StrongId< std::uint16_t, struct DummyForJunctionId >; -using JuncCustom = std::uint16_t; -using MachTypeReg_t = GlobalIdReg; -using NodeTypeReg_t = GlobalIdReg; -inline NodeTypeId const gc_ntSigFloat = NodeTypeReg_t::create(); /** * @brief Keeps track of Machines of a certain type that exists @@ -85,7 +121,6 @@ struct MachineUpdater lgrn::IdSetStl machTypesDirty; - // [MachTypeId][MachLocalId] osp::KeyedVec> localDirty; }; @@ -103,9 +138,9 @@ struct Junction }; /** - * @brief Connects Machines together with intermediate Nodes + * @brief Connects machines together */ -struct Nodes +struct NodeConnections { // reminder: IntArrayMultiMap is kind of like an // std::vector< std::vector<...> > but more memory efficient @@ -123,6 +158,11 @@ struct Nodes MachToNode_t machToNode; }; +struct NodeValues +{ + std::vector data; +}; + struct PortEntry { NodeTypeId type; @@ -135,17 +175,12 @@ inline NodeId connected_node(lgrn::Span portSpan, PortId port) noe return (portSpan.size() > port.value) ? portSpan[port.value] : NodeId{}; } -void copy_machines( - Machines const &rSrc, - Machines &rDst, - ArrayView remapMachOut); - void copy_nodes( - Nodes const &rSrcNodes, - Machines const &rSrcMach, - ArrayView remapMach, - Nodes &rDstNodes, - Machines &rDstMach, - ArrayView remapNodeOut); + NodeConnections const &rSrcNodes, + Machines const &rSrcMach, + ArrayView remapMach, + NodeConnections &rDstNodes, + Machines &rDstMach, + ArrayView remapNodeOut); } // namespace osp::wire diff --git a/src/osp/link/signal.h b/src/osp/link/signal.h index 131de67a..ab28b64d 100644 --- a/src/osp/link/signal.h +++ b/src/osp/link/signal.h @@ -29,6 +29,15 @@ namespace osp::link { + +inline TransmitModeId const gc_tmLogicSignal = GlobalLinkInfo::instance().create_transmitmode(); + +inline NodeTypeId const gc_ntSigFloat = GlobalLinkInfo::instance().create_nodetype(NodeTypeInfo{ + .transmitMode = gc_tmLogicSignal, .nodeDataSize = sizeof(float) +}); + + + constexpr JuncCustom gc_sigIn = 0; constexpr JuncCustom gc_sigOut = 1; @@ -54,7 +63,7 @@ struct UpdateNodes } }; -inline void notify_connected_inputs(NodeId const nodeId, Nodes::NodeToMach_t const& nodeToMach, MachineUpdater& rUpdMach) +inline void notify_connected_inputs(NodeId const nodeId, NodeConnections::NodeToMach_t const& nodeToMach, MachineUpdater& rUpdMach) { for (Junction junc : nodeToMach[nodeId.value]) { From 28b9ecc7788f9618d495e270a13ff664a80dde4c Mon Sep 17 00:00:00 2001 From: nnicdao Date: Tue, 30 Dec 2025 21:58:26 -0800 Subject: [PATCH 5/7] Rename src/osp/link/machines.* to src/osp/link/link.* and move src/adera/machine/links.* to src/adera --- src/adera/activescene/VehicleBuilder.h | 2 +- src/adera/{machines => }/links.cpp | 0 src/adera/{machines => }/links.h | 2 +- src/adera_app/features/jolt.cpp | 2 +- src/adera_app/features/vehicles.cpp | 2 +- src/adera_app/features/vehicles_machines.cpp | 2 +- src/adera_app/features/vehicles_prebuilt.cpp | 2 +- src/gdextension/sessions/godot.cpp | 2 +- src/osp/activescene/vehicles.h | 2 +- src/osp/link/{machines.cpp => link.cpp} | 2 +- src/osp/link/{machines.h => link.h} | 0 src/osp/link/signal.h | 2 +- src/testapp/features/magnum.cpp | 2 +- src/testapp/scenarios.cpp | 15 +++++++++++++-- 14 files changed, 24 insertions(+), 13 deletions(-) rename src/adera/{machines => }/links.cpp (100%) rename src/adera/{machines => }/links.h (96%) rename src/osp/link/{machines.cpp => link.cpp} (99%) rename src/osp/link/{machines.h => link.h} (100%) diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index 031ca96b..bff784df 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/src/adera/machines/links.cpp b/src/adera/links.cpp similarity index 100% rename from src/adera/machines/links.cpp rename to src/adera/links.cpp diff --git a/src/adera/machines/links.h b/src/adera/links.h similarity index 96% rename from src/adera/machines/links.h rename to src/adera/links.h index a830b79e..af188eec 100644 --- a/src/adera/machines/links.h +++ b/src/adera/links.h @@ -26,7 +26,7 @@ #include -#include +#include #include namespace adera diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index 4bbd7c69..b290c4ef 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #include diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index 06ea4a5f..2111659b 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index f2f1f180..066672c1 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/adera_app/features/vehicles_prebuilt.cpp b/src/adera_app/features/vehicles_prebuilt.cpp index 340d0863..b66d0448 100644 --- a/src/adera_app/features/vehicles_prebuilt.cpp +++ b/src/adera_app/features/vehicles_prebuilt.cpp @@ -26,7 +26,7 @@ #include "../feature_interfaces.h" -#include +#include #include diff --git a/src/gdextension/sessions/godot.cpp b/src/gdextension/sessions/godot.cpp index 0c02b3be..61042fd6 100644 --- a/src/gdextension/sessions/godot.cpp +++ b/src/gdextension/sessions/godot.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include diff --git a/src/osp/activescene/vehicles.h b/src/osp/activescene/vehicles.h index 65bee5a2..13fa4b98 100644 --- a/src/osp/activescene/vehicles.h +++ b/src/osp/activescene/vehicles.h @@ -28,7 +28,7 @@ #include "../core/keyed_vector.h" #include "../core/math_types.h" -#include "../link/machines.h" +#include "../link/link.h" #include #include diff --git a/src/osp/link/machines.cpp b/src/osp/link/link.cpp similarity index 99% rename from src/osp/link/machines.cpp rename to src/osp/link/link.cpp index 84166c20..091ddb11 100644 --- a/src/osp/link/machines.cpp +++ b/src/osp/link/link.cpp @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "machines.h" +#include "link.h" namespace osp::link { diff --git a/src/osp/link/machines.h b/src/osp/link/link.h similarity index 100% rename from src/osp/link/machines.h rename to src/osp/link/link.h diff --git a/src/osp/link/signal.h b/src/osp/link/signal.h index ab28b64d..457df8cb 100644 --- a/src/osp/link/signal.h +++ b/src/osp/link/signal.h @@ -24,7 +24,7 @@ */ #pragma once -#include "machines.h" +#include "link.h" namespace osp::link { diff --git a/src/testapp/features/magnum.cpp b/src/testapp/features/magnum.cpp index ca08a734..5cf3b560 100644 --- a/src/testapp/features/magnum.cpp +++ b/src/testapp/features/magnum.cpp @@ -29,7 +29,7 @@ #include -#include +#include #include #include #include diff --git a/src/testapp/scenarios.cpp b/src/testapp/scenarios.cpp index 95f22945..e5b355cb 100644 --- a/src/testapp/scenarios.cpp +++ b/src/testapp/scenarios.cpp @@ -454,12 +454,23 @@ static ScenarioMap_t make_scenarios() { rVehicleSpawn.spawnRequest.push_back( { - .position = {float(i - 2) * 8.0f, 30.0f, 10.0f}, - .velocity = {0.0, 0.0f, 50.0f * float(i)}, + .position = {float(i - 2) * 15.0f, 30.0f, 10.0f}, + .velocity = {0.0, 0.0f, 0.0f}, .rotation = {} }); rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSolvalot1].get()); } + + for (int i = 0; i < 2; ++i) + { + rVehicleSpawn.spawnRequest.push_back( + { + .position = {float(i - 2) * 15.0f, 0.0f, 10.0f}, + .velocity = {0.0, 0.0f, 0.0f}, + .rotation = {} + }); + rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); + } }}); return scenarioMap; From cf999c8eab6f81b294929eeb0e8ee13218b918fa Mon Sep 17 00:00:00 2001 From: nnicdao Date: Sat, 31 Jan 2026 14:15:50 -0800 Subject: [PATCH 6/7] Rework link nodes WIP and break everything --- src/adera/activescene/VehicleBuilder.cpp | 54 +++---- src/adera/activescene/VehicleBuilder.h | 34 ++--- src/adera/activescene/vehicles_vb_fn.cpp | 3 + src/adera/activescene/vehicles_vb_fn.h | 3 + src/adera_app/features/jolt.cpp | 10 +- src/adera_app/features/vehicles.cpp | 48 ++++--- src/adera_app/features/vehicles_machines.cpp | 39 +++-- src/osp/activescene/vehicles.h | 14 +- src/osp/core/keyed_vector.h | 2 + src/osp/link/link.cpp | 16 +-- src/osp/link/link.h | 142 +++++++++++++------ src/osp/link/signal.h | 2 +- 12 files changed, 211 insertions(+), 156 deletions(-) diff --git a/src/adera/activescene/VehicleBuilder.cpp b/src/adera/activescene/VehicleBuilder.cpp index 6d117a57..28872d9b 100644 --- a/src/adera/activescene/VehicleBuilder.cpp +++ b/src/adera/activescene/VehicleBuilder.cpp @@ -31,6 +31,8 @@ namespace adera { +#if 0 + using osp::restypes::gc_importer; VehicleBuilder::~VehicleBuilder() @@ -116,26 +118,25 @@ osp::link::MachAnyId VehicleBuilder::create_machine(PartId const part, std::initializer_list const& connections) { auto &rData = m_data.value(); - osp::link::PerMachType &rPerMachType = rData.m_machines.perType[machType]; + osp::link::MachType &rPerMachType = rData.m_links.machtype[machType]; - MachAnyId const mach = rData.m_machines.ids.create(); + MachAnyId const mach = rData.m_links.machIds.create(); - std::size_t const capacity = rData.m_machines.ids.capacity(); - rData.m_machines.machTypes.resize(capacity); - rData.m_machines.machToLocal.resize(capacity); - rData.m_machToPart.resize(capacity); - for (PerNodeType &rPerNodeType : rData.m_nodePerType) + std::size_t const capacity = rData.m_links.machIds.capacity(); + rData.m_links.machTypeOf .resize(capacity); + rData.m_links.machlocalidOf .resize(capacity); + rData.m_machToPart .resize(capacity); + for (osp::link::NodeType &rPerNodeType : rData.m_links.nodetype) { rPerNodeType.machToNode.ids_reserve(capacity); - rPerNodeType.m_machToNodeCustom.ids_reserve(capacity); } MachLocalId const local = rPerMachType.localIds.create(); - rPerMachType.localToAny.resize(rPerMachType.localIds.capacity()); + rPerMachType.machanyIdOf.resize(rPerMachType.localIds.capacity()); - rData.m_machines.machTypes[mach] = machType; - rData.m_machines.machToLocal[mach] = local; - rPerMachType.localToAny[local] = mach; + rData.m_links.machTypeOf[mach] = machType; + rData.m_links.machlocalidOf[mach] = local; + rPerMachType.machanyIdOf[local] = mach; m_partMachCount[std::size_t(part)] ++; rData.m_machToPart[mach] = part; @@ -147,20 +148,21 @@ osp::link::MachAnyId VehicleBuilder::create_machine(PartId const part, void VehicleBuilder::connect(MachAnyId const mach, std::initializer_list const& connections) { + auto const& linkInfo = osp::link::GlobalLinkInfo::instance(); + // get max port count for each node type auto &rData = m_data.value(); - std::vector nodePortMax(rData.m_nodePerType.size(), 0); + osp::KeyedVec portSizeRequired(linkInfo.nodetypeIds.capacity(), 0); for (Connection const& connect : connections) { - int &rPortMax = nodePortMax[connect.m_port.type.value]; + int &rPortMax = portSizeRequired[connect.m_port.type]; rPortMax = std::max(rPortMax, connect.m_port.port.value + 1); } - for (std::size_t nodeTypeInt = 0; nodeTypeInt < rData.m_nodePerType.size(); ++nodeTypeInt) + for (NodeTypeId const nodeType : linkInfo.nodetypeIds) { - NodeTypeId const nodeType = NodeTypeId::from_index(nodeTypeInt); - int const portMax = nodePortMax[nodeType.value]; - PerNodeType &rPerNodeType = rData.m_nodePerType[nodeType]; + int const portMax = portSizeRequired[nodeType]; + osp::link::NodeType &rPerNodeType = rData.m_links.nodetype[nodeType]; if (portMax != 0) { // reallocate each time :) @@ -213,7 +215,7 @@ VehicleData VehicleBuilder::finalize_release() } // assign node-to-machine - for (MachAnyId const mach : rData.m_machines.ids) + for (MachAnyId const mach : rData.m_machines.machIds) { lgrn::Span portSpan = rPerNodeType.machToNode[mach.value]; lgrn::Span customSpan = rPerNodeType.m_machToNodeCustom[mach.value]; @@ -239,8 +241,8 @@ VehicleData VehicleBuilder::finalize_release() }); assert(found != std::end(juncSpan)); - MachTypeId const type = rData.m_machines.machTypes[mach]; - MachLocalId const local = rData.m_machines.machToLocal[mach]; + MachTypeId const type = rData.m_machines.machTypeOf[mach]; + MachLocalId const local = rData.m_machines.machlocalidOf[mach]; found->local = local; found->type = type; @@ -252,17 +254,17 @@ VehicleData VehicleBuilder::finalize_release() // Reserve part-to-machine partitions using osp::link::MachinePair; rData.m_partToMachines.ids_reserve(rData.m_partIds.capacity()); - rData.m_partToMachines.data_reserve(rData.m_machines.ids.capacity()); + rData.m_partToMachines.data_reserve(rData.m_machines.machIds.capacity()); for (PartId const part : rData.m_partIds) { rData.m_partToMachines.emplace(part.value, m_partMachCount[part.value]); } // Assign part-to-machine partitions - for (MachAnyId const mach : rData.m_machines.ids) + for (MachAnyId const mach : rData.m_machines.machIds) { - MachLocalId const local = rData.m_machines.machToLocal[mach]; - MachTypeId const type = rData.m_machines.machTypes[mach]; + MachLocalId const local = rData.m_machines.machlocalidOf[mach]; + MachTypeId const type = rData.m_machines.machTypeOf[mach]; PartId const part = rData.m_machToPart[mach]; auto const machines = lgrn::Span{rData.m_partToMachines[part.value]}; @@ -286,4 +288,6 @@ VehicleData VehicleBuilder::finalize_release() return dataOut; } +#endif + } // namespace adera diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index bff784df..4fa78f91 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -45,6 +45,8 @@ namespace adera { +#if 0 + using osp::active::PartId; using osp::active::WeldId; @@ -55,16 +57,6 @@ struct StructureLink PartId m_less; }; -struct PerNodeType : osp::link::NodeConnections -{ - using MachToNodeCustom_t = lgrn::IntArrayMultiMap; - - MachToNodeCustom_t m_machToNodeCustom; // parallel with m_machToNode - entt::any m_nodeValues; - osp::KeyedVec m_nodeConnectCount; - int m_connectCountTotal{0}; -}; - struct VehicleData { using MapPartToMachines_t = osp::active::ACtxParts::MapPartToMachines_t; @@ -82,10 +74,9 @@ struct VehicleData lgrn::IdRegistryStl m_weldIds; MapWeldToParts_t m_weldToParts; - osp::link::Machines m_machines; - osp::KeyedVec m_machToPart; + osp::link::Links m_links; - osp::KeyedVec m_nodePerType; + osp::KeyedVec m_machToPart; }; /** @@ -115,8 +106,8 @@ class VehicleBuilder { auto const& info = osp::link::GlobalLinkInfo::instance(); auto &rData = m_data.emplace(); - rData.m_machines.perType.resize(info.machtypeIds.capacity()); - rData.m_nodePerType.resize(info.nodetypeIds.capacity()); + rData.m_links.machtype.resize(info.machtypeIds.capacity()); + rData.m_links.nodetype.resize(info.nodetypeIds.capacity()); index_prefabs(); }; @@ -152,7 +143,7 @@ class VehicleBuilder std::size_t node_capacity(NodeTypeId nodeType) const { - return m_data->m_nodePerType[nodeType].nodeIds.capacity(); + return m_data->m_links.nodetype[nodeType].capacity; } struct Connection @@ -204,12 +195,11 @@ std::array VehicleBuilder::create_nodes(NodeTypeId const n { std::array out; - PerNodeType &rPerNodeType = m_data->m_nodePerType[nodeType]; + osp::link::NodeType &rNodeType = m_data->m_links.nodetype[nodeType]; - rPerNodeType.nodeIds.create(std::begin(out), std::end(out)); - std::size_t const capacity = rPerNodeType.nodeIds.capacity(); - rPerNodeType.nodeToMach.ids_reserve(rPerNodeType.nodeIds.capacity()); - rPerNodeType.m_nodeConnectCount.resize(capacity, 0); + rNodeType.nodeIds.create(std::begin(out), std::end(out)); + std::size_t const capacity = rNodeType.nodeIds.capacity(); + rNodeType.nodeToMach.ids_reserve(rNodeType.nodeIds.capacity()); return out; } @@ -231,4 +221,6 @@ VALUES_T& VehicleBuilder::node_values(NodeTypeId nodeType) return rValues; } +#endif + } // namespace adera diff --git a/src/adera/activescene/vehicles_vb_fn.cpp b/src/adera/activescene/vehicles_vb_fn.cpp index 894b6337..8a348a62 100644 --- a/src/adera/activescene/vehicles_vb_fn.cpp +++ b/src/adera/activescene/vehicles_vb_fn.cpp @@ -32,6 +32,8 @@ using namespace osp::active; namespace adera { +#if 0 + void SysVehicleSpawnVB::create_parts_and_welds(ACtxVehicleSpawn& rVehicleSpawn, ACtxVehicleSpawnVB& rVehicleSpawnVB, ACtxParts& rScnParts) { std::size_t const newVehicleCount = rVehicleSpawn.new_vehicle_count(); @@ -201,5 +203,6 @@ void SysVehicleSpawnVB::request_prefabs(ACtxVehicleSpawn& rVehicleSpawn, ACtxVeh } } +#endif } // namespace adera diff --git a/src/adera/activescene/vehicles_vb_fn.h b/src/adera/activescene/vehicles_vb_fn.h index 4260c21b..8b954c2f 100644 --- a/src/adera/activescene/vehicles_vb_fn.h +++ b/src/adera/activescene/vehicles_vb_fn.h @@ -32,6 +32,8 @@ namespace adera { +#if 0 + struct ACtxVehicleSpawnVB { using SpVehicleId = osp::active::SpVehicleId; @@ -86,5 +88,6 @@ class SysVehicleSpawnVB static void request_prefabs(ACtxVehicleSpawn& rVehicleSpawn, ACtxVehicleSpawnVB const& rVehicleSpawnVB, ACtxParts& rScnParts, ACtxPrefabs& rPrefabs, Resources& rResources); }; +#endif } // namespace adera diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index b290c4ef..3ad29adc 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -521,8 +521,8 @@ static void assign_weld_rockets( ACtxParts const &rScnParts, ACtxJoltWorld &rJolt, ACtxRocketsJolt &rRocketsJolt, - NodeConnections const &rFloatNodes, - PerMachType const &machtypeRocket, + NodeType const &rFloatNodes, + MachType const &machtypeRocket, std::vector &rRocketsFoundTemp) { using adera::gc_mtMagicRocket; @@ -554,7 +554,7 @@ static void assign_weld_rockets( continue; // This machine is not a rocket } - MachAnyId const mach = machtypeRocket.localToAny[pair.local]; + MachAnyId const mach = machtypeRocket.machanyIdOf[pair.local]; auto const& portSpan = rFloatNodes.machToNode[mach.value]; NodeId const throttleIn = connected_node(portSpan, gc_throttleIn.port); NodeId const multiplierIn = connected_node(portSpan, gc_multiplierIn.port); @@ -694,8 +694,8 @@ FeatureDef const ftrRocketThrustJolt = feature_def("RocketThrustJolt", [] ( { using adera::gc_mtMagicRocket; - NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - PerMachType const &machtypeRocket = rLinks.machines.perType[gc_mtMagicRocket]; + NodeType const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + MachType const &machtypeRocket = rLinks.machines.perType[gc_mtMagicRocket]; rRocketsJolt.m_bodyRockets.ids_reserve(rJolt.m_bodyIds.size()); rRocketsJolt.m_bodyRockets.data_reserve(rLinks.machines.perType[gc_mtMagicRocket].localIds.capacity()); diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index 2111659b..e7f69251 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -82,16 +82,20 @@ FeatureDef const ftrParts = feature_def("Parts", [] ( rFB.pipeline(parts.pl.mapPartActive) .parent(mainApp.loopblks.mainLoop); rFB.pipeline(parts.pl.mapWeldActive) .parent(mainApp.loopblks.mainLoop); - auto &rLinks = rFB.data_emplace< ACtxLinks > (links.di.links); + auto &rLinks = rFB.data_emplace< Links > (links.di.links); auto &rUpdMach = rFB.data_emplace< MachineUpdater > (links.di.updMach); auto &rScnParts = rFB.data_emplace< ACtxParts > (parts.di.scnParts); // Resize containers to fit all existing MachTypeIds and NodeTypeIds - std::size_t const machTypeIdCapacity = GlobalLinkInfo::instance().machtypeIds.capacity(); + GlobalLinkInfo const& linkInfo = GlobalLinkInfo::instance(); + + std::size_t const machTypeIdCapacity = linkInfo.machtypeIds.capacity(); rUpdMach.machTypesDirty.resize(machTypeIdCapacity); rUpdMach.localDirty .resize(machTypeIdCapacity); - rLinks.machines.perType.resize(machTypeIdCapacity); - rLinks.nodePerType .resize(machTypeIdCapacity); + rLinks .machtype .resize(machTypeIdCapacity); + + std::size_t const nodeTypeIdCapacity = linkInfo.nodetypeIds.capacity(); + rLinks.nodetype.resize(nodeTypeIdCapacity); rFB.task() .name ("Clear Part dirty vectors after use") @@ -239,12 +243,12 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( } Machines const &srcMachines = pVData->m_machines; - std::size_t const bounds = srcMachines.ids.capacity(); + std::size_t const bounds = srcMachines.machIds.capacity(); rVSVB.remapMachOffsets[vhId] = remapMachTotal; remapMachTotal += bounds; - machTotal += srcMachines.ids.size(); + machTotal += srcMachines.machIds.size(); for (MachTypeId const typeId : linkInfo.machtypeIds) { @@ -258,10 +262,10 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( // Create ACtxParts MachAny/LocalIDs and populate remaps // MachAnyIDs created here - rLinks.machines.ids.create(rVehicleSpawn.spawnedMachs.begin(), - rVehicleSpawn.spawnedMachs.end()); + rLinks.machines.machIds.create(rVehicleSpawn.spawnedMachs.begin(), + rVehicleSpawn.spawnedMachs.end()); - rLinks.machines.machToLocal.resize(rLinks.machines.ids.capacity()); + rLinks.machines.machlocalidOf.resize(rLinks.machines.machIds.capacity()); auto itDstMachIds = rVehicleSpawn.spawnedMachs.cbegin(); @@ -277,7 +281,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( std::size_t const remapMachOffset = rVSVB.remapMachOffsets[vhId]; - for (MachAnyId const srcMach : srcMachines.ids) + for (MachAnyId const srcMach : srcMachines.machIds) { MachAnyId const dstMach = *itDstMachIds; ++itDstMachIds; @@ -291,14 +295,14 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( // TODO: This can be optimized later, where all local IDs are // created at once with ids.create(first, last), and make // resize(..) called once per type too - MachTypeId const type = srcMachines.machTypes[srcMach]; - PerMachType& rDstPerType = rLinks.machines.perType[type]; + MachTypeId const type = srcMachines.machTypeOf[srcMach]; + MachType& rDstPerType = rLinks.machines.perType[type]; MachLocalId const dstLocal = rDstPerType.localIds.create(); - rDstPerType.localToAny.resize(rDstPerType.localIds.capacity()); + rDstPerType.machanyIdOf.resize(rDstPerType.localIds.capacity()); - rDstPerType.localToAny[dstLocal] = dstMach; - rLinks.machines.machToLocal[dstMach] = dstLocal; + rDstPerType.machanyIdOf[dstLocal] = dstMach; + rLinks.machines.machlocalidOf[dstMach] = dstLocal; } } }); @@ -320,15 +324,15 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( continue; } - rScnParts.machineToPart.resize(rLinks.machines.ids.capacity()); + rScnParts.machineToPart.resize(rLinks.machines.machIds.capacity()); rScnParts.partToMachines.ids_reserve(rScnParts.partIds.capacity()); - rScnParts.partToMachines.data_reserve(rLinks.machines.ids.capacity()); + rScnParts.partToMachines.data_reserve(rLinks.machines.machIds.capacity()); std::size_t const remapMachOffset = rVSVB.remapMachOffsets[vhId]; std::size_t const remapPartOffset = rVSVB.remapPartOffsets[vhId]; // Update rScnParts machine->part map - for (MachAnyId const srcMach : pVData->m_machines.ids) + for (MachAnyId const srcMach : pVData->m_machines.machIds) { MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach.value]; PartId const srcPart = pVData->m_machToPart[srcMach]; @@ -351,10 +355,10 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( { MachinePair const& srcPair = srcPairs[i]; MachinePair& rDstPair = dstPairs[i]; - MachAnyId const srcMach = pVData->m_machines.perType[srcPair.type].localToAny[srcPair.local]; + MachAnyId const srcMach = pVData->m_machines.perType[srcPair.type].machanyIdOf[srcPair.local]; MachAnyId const dstMach = rVSVB.remapMachs[remapMachOffset + srcMach.value]; MachTypeId const dstType = srcPair.type; - MachLocalId const dstLocal = rLinks.machines.machToLocal[dstMach]; + MachLocalId const dstLocal = rLinks.machines.machlocalidOf[dstMach]; rDstPair = { .local = dstLocal, .type = dstType }; } @@ -449,7 +453,7 @@ FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( .args ({ vhclSpawn.di.vehicleSpawn, vhclSpawnVB.di.vehicleSpawnVB, parts.di.scnParts, links.di.links, sigFloat.di.sigValFloat, sigFloat.di.sigUpdFloat}) .func ([] (ACtxVehicleSpawn& rVehicleSpawn, ACtxVehicleSpawnVB const& rVehicleSpawnVB, ACtxParts& rScnParts, ACtxLinks &rLinks, SignalValues_t& rSigValFloat, UpdateNodes& rSigUpdFloat) noexcept { - NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + NodeType const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; std::size_t const maxNodes = rFloatNodes.nodeIds.capacity(); rSigUpdFloat.nodeNewValues.resize(maxNodes); rSigUpdFloat.nodeDirty.resize(maxNodes); @@ -531,7 +535,7 @@ FeatureDef const ftrSignalsFloat = feature_def("SignalsFloat", [] ( return; // Not dirty, nothing to do } - NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + NodeType const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; // NOTE: The various use of reset() clear entire bit arrays, which may or may // not be expensive. They likely optimize to memset diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index 066672c1..94967a63 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -104,7 +104,6 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI auto &rDrawTfObservers = rFB.data_get< DrawTfObservers >(scnRender.di.drawTfObservers); auto &rScnParts = rFB.data_get< ACtxParts > (parts.di.scnParts); auto &rLinks = rFB.data_get< ACtxLinks > (links.di.links); - auto &rSigValFloat = rFB.data_get< SignalValues_t > (sigFloat.di.sigValFloat); auto &rThrustIndicator = rFB.data_emplace(rktIndicate.di.indicator); rThrustIndicator.material = material; @@ -117,7 +116,7 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI .args ({ scnRender.di.scnRender, parts.di.scnParts, links.di.links, rktIndicate.di.indicator}) .func([] (ACtxSceneRender &rScnRender, ACtxParts const& rScnParts, ACtxLinks const& rLinks, ThrustIndicator& rIndicator) noexcept { - PerMachType const& rockets = rLinks.machines.perType[gc_mtMagicRocket]; + MachType const& rockets = rLinks.machines.perType[gc_mtMagicRocket]; rIndicator.rktToDrawEnt.resize(rockets.localIds.capacity()); @@ -138,14 +137,14 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI .func([] (ACtxBasic& rBasic, ACtxSceneRender &rScnRender, ACtxDrawing& rDrawing, ACtxDrawingRes const& rDrawingRes, ACtxParts const& rScnParts, ACtxLinks const& rLinks, SignalValues_t const& rSigValFloat, ThrustIndicator& rIndicator) noexcept { Material &rMat = rScnRender.m_materials[rIndicator.material]; - PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; - NodeConnections const &floats = rLinks.nodePerType[gc_ntSigFloat]; + MachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; + NodeType const &floats = rLinks.nodePerType[gc_ntSigFloat]; for (MachLocalId const localId : rockets.localIds) { DrawEnt const drawEnt = rIndicator.rktToDrawEnt[localId]; - MachAnyId const anyId = rockets.localToAny[localId]; + MachAnyId const anyId = rockets.machanyIdOf[localId]; PartId const part = rScnParts.machineToPart[anyId]; ActiveEnt const partEnt = rScnParts.partToActive[part]; @@ -199,8 +198,8 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI auto &rLinks = *static_cast< ACtxLinks* > (data[2]); auto &rSigValFloat = *static_cast< SignalValues_t* > (data[3]); - PerMachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; - NodeConnections const &floats = rLinks.nodePerType[gc_ntSigFloat]; + MachType const &rockets = rLinks.machines.perType[gc_mtMagicRocket]; + NodeType const &floats = rLinks.nodePerType[gc_ntSigFloat]; PartId const part = rScnParts.activeToPart[ent]; ActiveEnt const partEnt = rScnParts.partToActive[part]; @@ -210,7 +209,7 @@ FeatureDef const ftrMagicRocketThrustIndicator = feature_def("MagicRocketThrustI if (pair.type == gc_mtMagicRocket) { DrawEnt const drawEnt = rThrustIndicator.rktToDrawEnt[pair.local]; - MachAnyId const anyId = rockets.localToAny[pair.local]; + MachAnyId const anyId = rockets.machanyIdOf[pair.local]; auto const& portSpan = floats.machToNode[anyId.value]; NodeId const throttleIn = connected_node(portSpan, ports_magicrocket::gc_throttleIn.port); @@ -262,12 +261,12 @@ FeatureDef const ftrMachRCSDriver = feature_def("RCSDriver", [] ( .args ({ links.di.links, links.di.updMach, sigFloat.di.sigValFloat, sigFloat.di.sigUpdFloat}) .func ([] (ACtxLinks& rLinks, MachineUpdater& rUpdMach, SignalValues_t& rSigValFloat, UpdateNodes& rSigUpdFloat) noexcept { - NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; - PerMachType &rRockets = rLinks.machines.perType[gc_mtRcsDriver]; + NodeType const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + MachType &rRockets = rLinks.machines.perType[gc_mtRcsDriver]; for (MachLocalId const local : rUpdMach.localDirty[gc_mtRcsDriver]) { - MachAnyId const mach = rRockets.localToAny[local]; + MachAnyId const mach = rRockets.machanyIdOf[local]; auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach.value]}; NodeId const thrNode = connected_node(portSpan, ports_rcsdriver::gc_throttleOut.port); @@ -378,7 +377,7 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( .args ({ parts.di.scnParts, links.di.links, windowApp.di.userInput, vhclCtrl.di.vhControls}) .func ([] (ACtxParts& rScnParts, ACtxLinks& rLinks, input::UserInputHandler const &rUserInput, VehicleControls &rVhControls) noexcept { - PerMachType &rUsrCtrl = rLinks.machines.perType[gc_mtUserCtrl]; + MachType &rUsrCtrl = rLinks.machines.perType[gc_mtUserCtrl]; // Select a UsrCtrl machine when pressing the switch button if (rUserInput.button_state(rVhControls.btnSwitch).m_triggered) @@ -425,7 +424,7 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( return; // No vehicle selected } - NodeConnections const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; + NodeType const &rFloatNodes = rLinks.nodePerType[gc_ntSigFloat]; float const thrRate = deltaTimeIn; float const thrChange @@ -439,8 +438,8 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( held(rVC.btnRollRt, 1.0f) - held(rVC.btnRollLf, 1.0f) }; - PerMachType &rUsrCtrl = rLinks.machines.perType[gc_mtUserCtrl]; - MachAnyId const mach = rUsrCtrl.localToAny[rVC.selectedUsrCtrl]; + MachType &rUsrCtrl = rLinks.machines.perType[gc_mtUserCtrl]; + MachAnyId const mach = rUsrCtrl.machanyIdOf[rVC.selectedUsrCtrl]; auto const portSpan = lgrn::Span{rFloatNodes.machToNode[mach.value]}; bool changed = false; @@ -487,11 +486,11 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( // Obtain associated ActiveEnt // MachLocalId -> MachAnyId -> PartId -> RigidGroup -> ActiveEnt - PerMachType const& rUsrCtrls = rLinks.machines.perType.at(adera::gc_mtUserCtrl); - MachAnyId const selectedMach = rUsrCtrls.localToAny .at(rVhControls.selectedUsrCtrl); - PartId const selectedPart = rScnParts.machineToPart .at(selectedMach); - WeldId const weld = rScnParts.partToWeld .at(selectedPart); - ActiveEnt const selectedEnt = rScnParts.weldToActive .at(weld); + MachType const& rUsrCtrls = rLinks.machines.perType.at(adera::gc_mtUserCtrl); + MachAnyId const selectedMach = rUsrCtrls.machanyIdOf .at(rVhControls.selectedUsrCtrl); + PartId const selectedPart = rScnParts.machineToPart .at(selectedMach); + WeldId const weld = rScnParts.partToWeld .at(selectedPart); + ActiveEnt const selectedEnt = rScnParts.weldToActive .at(weld); if (rBasic.m_transform.contains(selectedEnt)) { diff --git a/src/osp/activescene/vehicles.h b/src/osp/activescene/vehicles.h index 13fa4b98..226d74b0 100644 --- a/src/osp/activescene/vehicles.h +++ b/src/osp/activescene/vehicles.h @@ -39,13 +39,13 @@ namespace osp::active using PartId = osp::StrongId; using WeldId = osp::StrongId; -struct ACtxLinks -{ - ACtxLinks() = default; - OSP_MOVE_ONLY_CTOR_ASSIGN(ACtxLinks); - link::Machines machines; - KeyedVec nodePerType; -}; +//struct ACtxLinks +//{ +// ACtxLinks() = default; +// OSP_MOVE_ONLY_CTOR_ASSIGN(ACtxLinks); +// link::Machines machines; +// KeyedVec nodePerType; +//}; struct ACtxParts { diff --git a/src/osp/core/keyed_vector.h b/src/osp/core/keyed_vector.h index de374b4b..ec1c69dd 100644 --- a/src/osp/core/keyed_vector.h +++ b/src/osp/core/keyed_vector.h @@ -55,6 +55,8 @@ class KeyedVec : public std::vector using difference_type = typename vector_t::difference_type; using size_type = typename vector_t::size_type; + using vector_t::vector_t; + constexpr vector_t& base() noexcept { return *this; } constexpr vector_t const& base() const noexcept { return *this; } diff --git a/src/osp/link/link.cpp b/src/osp/link/link.cpp index 091ddb11..0c18c611 100644 --- a/src/osp/link/link.cpp +++ b/src/osp/link/link.cpp @@ -34,11 +34,11 @@ GlobalLinkInfo& GlobalLinkInfo::instance() } void copy_nodes( - NodeConnections const &rSrcNodes, - Machines const &rSrcMach, + NodeType const &rSrcNodes, + Links const &rSrcMach, Corrade::Containers::ArrayView remapMach, - NodeConnections &rDstNodes, - Machines &rDstMach, + NodeType &rDstNodes, + Links &rDstMach, Corrade::Containers::ArrayView remapNode) { using lgrn::Span; @@ -65,9 +65,9 @@ void copy_nodes( for (Junction const& srcJunc : srcJunction) { MachTypeId const machType = srcJunc.type; - MachAnyId const srcMach = rSrcMach.perType[machType].localToAny[srcJunc.local]; + MachAnyId const srcMach = rSrcMach.machtype[machType].machanyIdOf[srcJunc.local]; MachAnyId const dstMach = remapMach[srcMach.value]; - MachLocalId const dstLocal = rDstMach.machToLocal[dstMach]; + MachLocalId const dstLocal = rDstMach.machlocalidOf[dstMach]; dstJuncIt->local = dstLocal; dstJuncIt->type = machType; @@ -78,10 +78,10 @@ void copy_nodes( } // copy mach-to-node connections - rDstNodes.machToNode.ids_reserve(rDstMach.ids.capacity()); + rDstNodes.machToNode.ids_reserve(rDstMach.machIds.capacity()); rDstNodes.machToNode.data_reserve(rDstNodes.machToNode.data_size() + rSrcNodes.machToNode.data_size()); - for (MachAnyId const srcMach : rSrcMach.ids) + for (MachAnyId const srcMach : rSrcMach.machIds) { if (rSrcNodes.machToNode.contains(srcMach.value)) { diff --git a/src/osp/link/link.h b/src/osp/link/link.h index 94030b24..ed90bbf2 100644 --- a/src/osp/link/link.h +++ b/src/osp/link/link.h @@ -87,47 +87,17 @@ struct GlobalLinkInfo }; // Not yet used, for example only -inline TransmitModeId const gc_tmStructure = GlobalLinkInfo::instance().transmitmodeIds.create(); -inline TransmitModeId const gc_tmSimpleFluid = GlobalLinkInfo::instance().transmitmodeIds.create(); - - +inline TransmitModeId const gc_tmStructure = GlobalLinkInfo::instance().create_transmitmode(); +inline TransmitModeId const gc_tmSimpleFluid = GlobalLinkInfo::instance().create_transmitmode(); /** * @brief Keeps track of Machines of a certain type that exists */ -struct PerMachType +struct MachType { lgrn::IdRegistryStl localIds; - osp::KeyedVec localToAny; -}; - -/** - * @brief Keeps track of all Machines that exist and what type they are - */ -struct Machines -{ - lgrn::IdRegistryStl ids; - - osp::KeyedVec machTypes; - osp::KeyedVec machToLocal; - - osp::KeyedVec perType; -}; - -struct MachineUpdater -{ - alignas(64) std::atomic requestMachineUpdateLoop {false}; - - lgrn::IdSetStl machTypesDirty; - - osp::KeyedVec> localDirty; -}; - -struct MachinePair -{ - MachLocalId local; - MachTypeId type; + osp::KeyedVec machanyIdOf; }; struct Junction @@ -137,30 +107,53 @@ struct Junction JuncCustom custom {0}; }; -/** - * @brief Connects machines together - */ -struct NodeConnections +struct NodeType { + static constexpr std::size_t smc_blockSize = 64; + static constexpr std::size_t smc_blockAlign = 64; + struct alignas(smc_blockAlign) Block + { + std::byte data[smc_blockAlign]; + }; + // reminder: IntArrayMultiMap is kind of like an // std::vector< std::vector<...> > but more memory efficient using NodeToMach_t = lgrn::IntArrayMultiMap; using MachToNode_t = lgrn::IntArrayMultiMap; - lgrn::IdRegistryStl nodeIds; + lgrn::IdRegistryStl nodeIds; // Node-to-Machine connections // [NodeId][JunctionIndex] -> Junction (type, MachLocalId, custom int) - NodeToMach_t nodeToMach; + NodeToMach_t nodeToMach; // Corresponding Machine-to-Node connections // [MachAnyId][PortIndex] -> NodeId - MachToNode_t machToNode; + MachToNode_t machToNode; + + std::size_t stride; // copy of NodeTypeInfo::nodeDataSize + std::vector data; + std::size_t capacity; +}; + +struct Links +{ + lgrn::IdRegistryStl machIds; + + osp::KeyedVec machTypeOf; + osp::KeyedVec machlocalidOf; + + osp::KeyedVec machtype; + osp::KeyedVec nodetype; }; -struct NodeValues +/** + * @brief Machine Local and type ID. Equivalent to a MachAnyId + */ +struct MachinePair { - std::vector data; + MachLocalId local; + MachTypeId type; }; struct PortEntry @@ -170,17 +163,72 @@ struct PortEntry JuncCustom custom; }; +using RequestMachId = osp::StrongId< std::uint32_t, struct DummyForRequestMachId >; +using RequestNodeId = osp::StrongId< std::uint32_t, struct DummyForRequestNodeId >; + +struct RequestMachine +{ + MachTypeId type; +}; + +struct RequestNode +{ + NodeTypeId type; +}; + +struct RequestConnect +{ + NodeId node; + NodeTypeId nodeType; +}; + +// what is the first thing we should make? +// each part should just be a machine? +// make a machine for 'part' +// 'named part' system that acts like template. +// u spawn a part, then update the craft for it to generate wire connections and stuff +// change a part on the fly. +// make a machine called 'part' +// make a node data type + +// when iterating parts, + +// 1. make part registry system so we know what part things are lol +// * +// 2. make a 'part' machine type + +// extendable +// add part, it's a machine +// + +// outputs: model and link + +struct PartType +{ + +}; + + +struct MachineUpdater +{ + alignas(64) std::atomic requestMachineUpdateLoop {false}; + + lgrn::IdSetStl machTypesDirty; + + osp::KeyedVec> localDirty; +}; + inline NodeId connected_node(lgrn::Span portSpan, PortId port) noexcept { return (portSpan.size() > port.value) ? portSpan[port.value] : NodeId{}; } void copy_nodes( - NodeConnections const &rSrcNodes, - Machines const &rSrcMach, + NodeType const &rSrcNodes, + Links const &rSrcMach, ArrayView remapMach, - NodeConnections &rDstNodes, - Machines &rDstMach, + NodeType &rDstNodes, + Links &rDstMach, ArrayView remapNodeOut); } // namespace osp::wire diff --git a/src/osp/link/signal.h b/src/osp/link/signal.h index 457df8cb..a323c84c 100644 --- a/src/osp/link/signal.h +++ b/src/osp/link/signal.h @@ -63,7 +63,7 @@ struct UpdateNodes } }; -inline void notify_connected_inputs(NodeId const nodeId, NodeConnections::NodeToMach_t const& nodeToMach, MachineUpdater& rUpdMach) +inline void notify_connected_inputs(NodeId const nodeId, NodeType::NodeToMach_t const& nodeToMach, MachineUpdater& rUpdMach) { for (Junction junc : nodeToMach[nodeId.value]) { From 73b9d36a8a97d0a57152ab2818ab99ccd0309488 Mon Sep 17 00:00:00 2001 From: nnicdao Date: Sat, 14 Feb 2026 16:07:41 -0800 Subject: [PATCH 7/7] Disable vehicles and progress on WIP new vehicle builder --- src/adera/activescene/VehicleBuilder.cpp | 22 +++++++++ src/adera/activescene/VehicleBuilder.h | 49 ++++++++++++++++++++ src/adera_app/features/jolt.cpp | 6 +++ src/adera_app/features/vehicles.cpp | 11 +++++ src/adera_app/features/vehicles.h | 8 +++- src/adera_app/features/vehicles_machines.cpp | 3 ++ src/adera_app/features/vehicles_prebuilt.cpp | 31 +++++++++++-- src/adera_app/features/vehicles_prebuilt.h | 10 ++-- src/gdextension/scenarios.cpp | 3 +- src/osp/core/strong_id.h | 1 + src/osp/link/link.cpp | 8 ++-- src/osp/link/link.h | 42 +++++++---------- src/osp/link/signal.h | 8 ++-- src/testapp/scenarios.cpp | 44 ++++++++++-------- src/testapp/scenarios_magnum.cpp | 6 +-- 15 files changed, 185 insertions(+), 67 deletions(-) diff --git a/src/adera/activescene/VehicleBuilder.cpp b/src/adera/activescene/VehicleBuilder.cpp index 28872d9b..e8f3d2ff 100644 --- a/src/adera/activescene/VehicleBuilder.cpp +++ b/src/adera/activescene/VehicleBuilder.cpp @@ -24,13 +24,35 @@ */ #include "VehicleBuilder.h" +#include + +#include +#include + #include #include #include +using namespace osp::fw; + namespace adera { +struct VehicleBuilderImpl +{ + ContextId main; + Framework fw; + osp::exec::SinglethreadFWExecutor exec; +}; + + +VehicleBuilder::VehicleBuilder(Framework fw, ContextId ctx) + : m_impl{std::make_unique(ctx, std::move(fw), osp::exec::SinglethreadFWExecutor{})} +{ } + +VehicleBuilder::~VehicleBuilder() = default; + + #if 0 using osp::restypes::gc_importer; diff --git a/src/adera/activescene/VehicleBuilder.h b/src/adera/activescene/VehicleBuilder.h index 4fa78f91..ebdcf597 100644 --- a/src/adera/activescene/VehicleBuilder.h +++ b/src/adera/activescene/VehicleBuilder.h @@ -24,6 +24,8 @@ */ #pragma once +#include + #include #include #include @@ -45,6 +47,53 @@ namespace adera { +struct VehicleBuilderImpl; + +class VehicleBuilder +{ +public: + + VehicleBuilder(osp::fw::Framework fw, osp::fw::ContextId ctx); + ~VehicleBuilder(); + + struct Connection + { + osp::link::PortEntry m_port; + osp::link::NodeId m_node; + }; + + template + [[nodiscard]] std::array create_nodes(osp::link::NodeTypeId nodeType); + + osp::link::MachAnyId create_machine(osp::link::MachTypeId machType, std::initializer_list const& connections); + + void connect(osp::link::MachAnyId mach, std::initializer_list const& connections); + + void update(); + + osp::link::Links& links(); + +private: + + std::unique_ptr m_impl; +}; + + +template +std::array VehicleBuilder::create_nodes(osp::link::NodeTypeId const nodeType) +{ + std::array out; + + osp::link::NodeType &rNodeType = *links().nodetype[nodeType]; + + rNodeType.nodeIds.create(std::begin(out), std::end(out)); + std::size_t const capacity = rNodeType.nodeIds.capacity(); + rNodeType.nodeToMach.ids_reserve(rNodeType.nodeIds.capacity()); + + return out; +} + + #if 0 using osp::active::PartId; diff --git a/src/adera_app/features/jolt.cpp b/src/adera_app/features/jolt.cpp index 3ad29adc..b7db8688 100644 --- a/src/adera_app/features/jolt.cpp +++ b/src/adera_app/features/jolt.cpp @@ -615,6 +615,8 @@ static void assign_weld_rockets( } } +#if 0 + struct RocketThrustUserData { ACtxRocketsJolt const &rRocketsJolt; @@ -727,6 +729,9 @@ FeatureDef const ftrRocketThrustJolt = feature_def("RocketThrustJolt", [] ( rRocketsJolt.factorIndex = static_cast(index); }); // ftrRocketThrustJolt +#endif + + struct ACtxTerrainJolt { BodyId bodyId; @@ -738,6 +743,7 @@ struct ACtxTerrainJolt std::vector positions; }; + FeatureDef const ftrTerrainJolt = feature_def("ftrTerrainJolt", [] ( FeatureBuilder &rFB, Implement terrainJolt, diff --git a/src/adera_app/features/vehicles.cpp b/src/adera_app/features/vehicles.cpp index e7f69251..56f394ef 100644 --- a/src/adera_app/features/vehicles.cpp +++ b/src/adera_app/features/vehicles.cpp @@ -52,6 +52,13 @@ using namespace Magnum::Math::Literals; namespace adera { +FeatureDef const ftrLinks = feature_def("Links", [] ( + FeatureBuilder &rFB, + Implement links, + DependOn cleanup) +{ + auto &rLinks = rFB.data_emplace< Links > (links.di.links); +}); FeatureDef const ftrParts = feature_def("Parts", [] ( FeatureBuilder &rFB, @@ -174,6 +181,8 @@ FeatureDef const ftrVehicleSpawn = feature_def("VehicleSpawn", [] ( }); // ftrVehicleSpawn +#if 0 + FeatureDef const ftrVehicleSpawnVBData = feature_def("VehicleSpawnVBData", [] ( FeatureBuilder &rFB, Implement vhclSpawnVB, @@ -569,5 +578,7 @@ FeatureDef const ftrSignalsFloat = feature_def("SignalsFloat", [] ( }); }); // ftrSignalsFloat +#endif + } // namespace adera diff --git a/src/adera_app/features/vehicles.h b/src/adera_app/features/vehicles.h index ba99a7b2..873dd470 100644 --- a/src/adera_app/features/vehicles.h +++ b/src/adera_app/features/vehicles.h @@ -29,8 +29,14 @@ namespace adera { + +/** + * @brief TODO + */ +extern osp::fw::FeatureDef const ftrLinks; + /** - * @brief Support for Parts, Machines, and Links + * @brief TODO */ extern osp::fw::FeatureDef const ftrParts; diff --git a/src/adera_app/features/vehicles_machines.cpp b/src/adera_app/features/vehicles_machines.cpp index 94967a63..2c0fffd4 100644 --- a/src/adera_app/features/vehicles_machines.cpp +++ b/src/adera_app/features/vehicles_machines.cpp @@ -52,6 +52,8 @@ using namespace osp; namespace adera { +#if 0 + FeatureDef const ftrMachMagicRockets = feature_def("MachMagicRockets", [] ( FeatureBuilder &rFB, DependOn scn, @@ -506,6 +508,7 @@ FeatureDef const ftrVehicleControl = feature_def("VehicleControl", [] ( }); // ftrVehicleControl +#endif } // namespace adera diff --git a/src/adera_app/features/vehicles_prebuilt.cpp b/src/adera_app/features/vehicles_prebuilt.cpp index b66d0448..555b3569 100644 --- a/src/adera_app/features/vehicles_prebuilt.cpp +++ b/src/adera_app/features/vehicles_prebuilt.cpp @@ -23,6 +23,8 @@ * SOFTWARE. */ #include "vehicles_prebuilt.h" +#include "vehicles.h" + #include "../feature_interfaces.h" @@ -56,6 +58,7 @@ struct RCSInputs NodeId m_roll {lgrn::id_null()}; }; +/* static void add_rcs_machines(VehicleBuilder& rFB, RCSInputs const& inputs, PartId part, float thrustMul, Matrix4 const& tf) { namespace ports_rcsdriver = adera::ports_rcsdriver; @@ -137,7 +140,7 @@ static void add_rcs_mirrored(VehicleBuilder& rFB, VehicleBuilder::WeldVec_t& rWe rWeldTo.push_back({ nozzleA, nozzleTfA }); rWeldTo.push_back({ nozzleB, nozzleTfB }); } - +*/ FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( FeatureBuilder &rFB, @@ -148,11 +151,30 @@ FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( { auto &rResources = rFB.data_get(mainApp.di.resources); - auto &rPrebuiltVehicles = rFB.data_emplace(testVhcls.di.prebuiltVehicles); - rPrebuiltVehicles.resize(PrebuiltVhIdReg_t::size()); + //auto &rPrebuiltVehicles = rFB.data_emplace(testVhcls.di.prebuiltVehicles); + //rPrebuiltVehicles.resize(PrebuiltVhIdReg_t::size()); using namespace adera; + + Framework fw; + + // Contexts adds a way to separate major sections of the Framework. + // Feature Interfaces are added per-context. A context can't have two of the same + // implementations of a Feature Interface. If we were to add two aquariums that are logically + // separated and can run in parallel, we can use two contexts. + ContextId const ctx = fw.m_contextIds.create(); + + ContextBuilder cb{ctx, {}, fw}; + cb.add_feature(ftrLinks); + ContextBuilder::finalize(std::move(cb)); + + VehicleBuilder vb(std::move(fw), ctx); + + + + /* +asdf // Build "PartVehicle" { VehicleBuilder vbuilder{&rResources}; @@ -309,10 +331,12 @@ FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( rPrebuiltVehicles[gc_pbvSolvalot1] = std::make_unique(std::move(vbuilder.finalize_release())); } +*/ // Put more prebuilt vehicles here! + /* rFB.task() .name ("Clean up prebuilt vehicles") @@ -332,6 +356,7 @@ FeatureDef const ftrPrebuiltVehicles = feature_def("PrebuiltVehicles", [] ( } rPrebuildVehicles.clear(); }); +*/ }); // setup_prebuilt_vehicles diff --git a/src/adera_app/features/vehicles_prebuilt.h b/src/adera_app/features/vehicles_prebuilt.h index 32ccf42c..6526fa82 100644 --- a/src/adera_app/features/vehicles_prebuilt.h +++ b/src/adera_app/features/vehicles_prebuilt.h @@ -40,11 +40,11 @@ namespace adera using PrebuiltVhId = osp::StrongId; using PrebuiltVhIdReg_t = osp::GlobalIdReg; -struct PrebuiltVehicles : osp::KeyedVec< PrebuiltVhId, std::unique_ptr > -{ - PrebuiltVehicles() = default; - OSP_MOVE_ONLY_CTOR_ASSIGN(PrebuiltVehicles); -}; +// struct PrebuiltVehicles : osp::KeyedVec< PrebuiltVhId, std::unique_ptr > +// { +// PrebuiltVehicles() = default; +// OSP_MOVE_ONLY_CTOR_ASSIGN(PrebuiltVehicles); +// }; inline PrebuiltVhId const gc_pbvSimpleCommandServiceModule = PrebuiltVhIdReg_t::create(); inline PrebuiltVhId const gc_pbvSolvalot1 = PrebuiltVhIdReg_t::create(); diff --git a/src/gdextension/scenarios.cpp b/src/gdextension/scenarios.cpp index 7caa3e1d..87884d94 100644 --- a/src/gdextension/scenarios.cpp +++ b/src/gdextension/scenarios.cpp @@ -155,6 +155,7 @@ static ScenarioMap_t make_scenarios() add_floor(rFW, sceneCtx, pkg, 4); +#if 0 auto vhclSpawn = rFW.get_interface(sceneCtx); auto vhclSpawnVB = rFW.get_interface(sceneCtx); auto testVhcls = rFW.get_interface(sceneCtx); @@ -173,7 +174,7 @@ static ScenarioMap_t make_scenarios() }); rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); } - +#endif }}); return scenarioMap; diff --git a/src/osp/core/strong_id.h b/src/osp/core/strong_id.h index 4b5452f9..e252106f 100644 --- a/src/osp/core/strong_id.h +++ b/src/osp/core/strong_id.h @@ -45,6 +45,7 @@ namespace osp template struct StrongId { + using int_t = INT_T; using entity_type = INT_T; // Name used for entt compatibility constexpr StrongId() noexcept = default; diff --git a/src/osp/link/link.cpp b/src/osp/link/link.cpp index 0c18c611..b8222b6b 100644 --- a/src/osp/link/link.cpp +++ b/src/osp/link/link.cpp @@ -64,13 +64,13 @@ void copy_nodes( auto dstJuncIt = std::begin(dstJuncton); for (Junction const& srcJunc : srcJunction) { - MachTypeId const machType = srcJunc.type; - MachAnyId const srcMach = rSrcMach.machtype[machType].machanyIdOf[srcJunc.local]; + MachTypeId const machType = MachTypeId{srcJunc.type}; + MachAnyId const srcMach = rSrcMach.machtype[machType].machanyIdOf[MachLocalId{srcJunc.local}]; MachAnyId const dstMach = remapMach[srcMach.value]; MachLocalId const dstLocal = rDstMach.machlocalidOf[dstMach]; - dstJuncIt->local = dstLocal; - dstJuncIt->type = machType; + dstJuncIt->local = dstLocal.value; + dstJuncIt->type = machType.value; dstJuncIt->custom = srcJunc.custom; std::advance(dstJuncIt, 1); diff --git a/src/osp/link/link.h b/src/osp/link/link.h index ed90bbf2..45461b93 100644 --- a/src/osp/link/link.h +++ b/src/osp/link/link.h @@ -102,13 +102,20 @@ struct MachType struct Junction { - MachLocalId local; - MachTypeId type; - JuncCustom custom {0}; + MachLocalId::int_t local; + MachTypeId::int_t type; + JuncCustom custom {0}; }; struct NodeType { + NodeType() = default; + OSP_MOVE_ONLY_CTOR(NodeType); +// NodeType(NodeType const& copy) = delete; +// NodeType(NodeType&& move) = delete; +// NodeType& operator= (NodeType const& copy) = delete; +// NodeType& operator= (NodeType&& move) = delete; + static constexpr std::size_t smc_blockSize = 64; static constexpr std::size_t smc_blockAlign = 64; struct alignas(smc_blockAlign) Block @@ -118,8 +125,8 @@ struct NodeType // reminder: IntArrayMultiMap is kind of like an // std::vector< std::vector<...> > but more memory efficient - using NodeToMach_t = lgrn::IntArrayMultiMap; - using MachToNode_t = lgrn::IntArrayMultiMap; + using NodeToMach_t = lgrn::IntArrayMultiMap; + using MachToNode_t = lgrn::IntArrayMultiMap; lgrn::IdRegistryStl nodeIds; @@ -138,13 +145,16 @@ struct NodeType struct Links { + Links() = default; + OSP_MOVE_ONLY_CTOR_ASSIGN(Links); + lgrn::IdRegistryStl machIds; osp::KeyedVec machTypeOf; osp::KeyedVec machlocalidOf; osp::KeyedVec machtype; - osp::KeyedVec nodetype; + osp::KeyedVec< NodeTypeId, std::unique_ptr > nodetype; }; /** @@ -182,26 +192,6 @@ struct RequestConnect NodeTypeId nodeType; }; -// what is the first thing we should make? -// each part should just be a machine? -// make a machine for 'part' -// 'named part' system that acts like template. -// u spawn a part, then update the craft for it to generate wire connections and stuff -// change a part on the fly. -// make a machine called 'part' -// make a node data type - -// when iterating parts, - -// 1. make part registry system so we know what part things are lol -// * -// 2. make a 'part' machine type - -// extendable -// add part, it's a machine -// - -// outputs: model and link struct PartType { diff --git a/src/osp/link/signal.h b/src/osp/link/signal.h index a323c84c..0d638bf5 100644 --- a/src/osp/link/signal.h +++ b/src/osp/link/signal.h @@ -41,8 +41,8 @@ inline NodeTypeId const gc_ntSigFloat = GlobalLinkInfo::instance().create_nodety constexpr JuncCustom gc_sigIn = 0; constexpr JuncCustom gc_sigOut = 1; -constexpr PortEntry sigfloat_input(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigIn}; } -constexpr PortEntry sigfloat_output(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigOut}; } +inline PortEntry sigfloat_input(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigIn}; } +inline PortEntry sigfloat_output(std::uint16_t portId) { return PortEntry{gc_ntSigFloat, PortId{portId}, gc_sigOut}; } template using SignalValues_t = osp::KeyedVec; @@ -70,10 +70,10 @@ inline void notify_connected_inputs(NodeId const nodeId, NodeType::NodeToMach_t if (junc.custom == gc_sigIn) { // A machine of type "junc.m_type" has new values to read - rUpdMach.machTypesDirty.insert(junc.type); + rUpdMach.machTypesDirty.insert(MachTypeId{junc.type}); // Specify using local Id on which machine needs to update - rUpdMach.localDirty[junc.type].insert(junc.local); + rUpdMach.localDirty[MachTypeId{junc.type}].insert(MachLocalId{junc.local}); } } } diff --git a/src/testapp/scenarios.cpp b/src/testapp/scenarios.cpp index e5b355cb..1701720f 100644 --- a/src/testapp/scenarios.cpp +++ b/src/testapp/scenarios.cpp @@ -178,29 +178,30 @@ static ScenarioMap_t make_scenarios() sceneCB.add_feature(ftrBounds); sceneCB.add_feature(ftrPrefabs); - sceneCB.add_feature(ftrParts); - sceneCB.add_feature(ftrSignalsFloat); - sceneCB.add_feature(ftrVehicleSpawn); - sceneCB.add_feature(ftrVehicleSpawnVBData); - sceneCB.add_feature(ftrPrebuiltVehicles); +// sceneCB.add_feature(ftrParts); +// sceneCB.add_feature(ftrSignalsFloat); +// sceneCB.add_feature(ftrVehicleSpawn); +// sceneCB.add_feature(ftrVehicleSpawnVBData); +// sceneCB.add_feature(ftrPrebuiltVehicles); - sceneCB.add_feature(ftrMachMagicRockets); - sceneCB.add_feature(ftrMachRCSDriver); +// sceneCB.add_feature(ftrMachMagicRockets); +// sceneCB.add_feature(ftrMachRCSDriver); sceneCB.add_feature(ftrJolt); sceneCB.add_feature(ftrJoltConstAccel); sceneCB.add_feature(ftrPhysicsShapesJolt); - sceneCB.add_feature(ftrVehicleSpawnJolt); - sceneCB.add_feature(ftrRocketThrustJolt); +// sceneCB.add_feature(ftrVehicleSpawnJolt); +// sceneCB.add_feature(ftrRocketThrustJolt); ContextBuilder::finalize(std::move(sceneCB)); ospjolt::ForceFactors_t const gravity = add_constant_acceleration(sc_gravityForce, args.rFW, sceneCtx); set_phys_shape_factors (gravity, args.rFW, sceneCtx); - set_vehicle_default_factors(gravity, args.rFW, sceneCtx); +// set_vehicle_default_factors(gravity, args.rFW, sceneCtx); add_floor(args.rFW, sceneCtx, args.defaultPkg, 4); +#if 0 auto vhclSpawn = args.rFW.get_interface(sceneCtx); auto vhclSpawnVB = args.rFW.get_interface(sceneCtx); auto testVhcls = args.rFW.get_interface(sceneCtx); @@ -219,6 +220,7 @@ static ScenarioMap_t make_scenarios() }); rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); } +#endif }}); @@ -414,20 +416,20 @@ static ScenarioMap_t make_scenarios() sceneCB.add_feature(ftrBounds); sceneCB.add_feature(ftrPrefabs); - sceneCB.add_feature(ftrParts); - sceneCB.add_feature(ftrSignalsFloat); - sceneCB.add_feature(ftrVehicleSpawn); - sceneCB.add_feature(ftrVehicleSpawnVBData); - sceneCB.add_feature(ftrPrebuiltVehicles); +// sceneCB.add_feature(ftrParts); +// sceneCB.add_feature(ftrSignalsFloat); +// sceneCB.add_feature(ftrVehicleSpawn); +// sceneCB.add_feature(ftrVehicleSpawnVBData); +// sceneCB.add_feature(ftrPrebuiltVehicles); - sceneCB.add_feature(ftrMachMagicRockets); - sceneCB.add_feature(ftrMachRCSDriver); +// sceneCB.add_feature(ftrMachMagicRockets); +// sceneCB.add_feature(ftrMachRCSDriver); sceneCB.add_feature(ftrJolt); sceneCB.add_feature(ftrJoltConstAccel); sceneCB.add_feature(ftrPhysicsShapesJolt); - sceneCB.add_feature(ftrVehicleSpawnJolt); - sceneCB.add_feature(ftrRocketThrustJolt); +// sceneCB.add_feature(ftrVehicleSpawnJolt); +// sceneCB.add_feature(ftrRocketThrustJolt); sceneCB.add_feature(ftrTerrainJolt); @@ -438,10 +440,11 @@ static ScenarioMap_t make_scenarios() ospjolt::ForceFactors_t const gravity = add_constant_acceleration(sc_gravityForce, args.rFW, sceneCtx); set_phys_shape_factors(gravity, args.rFW, sceneCtx); - set_vehicle_default_factors(gravity, args.rFW, sceneCtx); +// set_vehicle_default_factors(gravity, args.rFW, sceneCtx); //add_floor(args.rFW, sceneCtx, args.defaultPkg, 4); +#if 0 auto vhclSpawn = args.rFW.get_interface(sceneCtx); auto vhclSpawnVB = args.rFW.get_interface(sceneCtx); auto testVhcls = args.rFW.get_interface(sceneCtx); @@ -471,6 +474,7 @@ static ScenarioMap_t make_scenarios() }); rVehicleSpawnVB.dataVB.push_back(rPrebuiltVehicles[gc_pbvSimpleCommandServiceModule].get()); } +#endif }}); return scenarioMap; diff --git a/src/testapp/scenarios_magnum.cpp b/src/testapp/scenarios_magnum.cpp index ddb2ce97..25ee1afc 100644 --- a/src/testapp/scenarios_magnum.cpp +++ b/src/testapp/scenarios_magnum.cpp @@ -148,8 +148,8 @@ ContextId make_scene_renderer(Framework &rFW, PkgId defaultPkg, ContextId mainCo if (rFW.get_interface_id(sceneCtx).has_value()) { - scnRdrCB.add_feature(ftrVehicleSpawnDraw); - scnRdrCB.add_feature(ftrVehicleControl); +// scnRdrCB.add_feature(ftrVehicleSpawnDraw); +// scnRdrCB.add_feature(ftrVehicleControl); } else { @@ -158,7 +158,7 @@ ContextId make_scene_renderer(Framework &rFW, PkgId defaultPkg, ContextId mainCo if (rFW.get_interface_id(sceneCtx).has_value()) { - scnRdrCB.add_feature(ftrMagicRocketThrustIndicator, TplPkgIdMaterialId{ defaultPkg, matFlat }); +// scnRdrCB.add_feature(ftrMagicRocketThrustIndicator, TplPkgIdMaterialId{ defaultPkg, matFlat }); } if ( ! scnRdrCB.has_error() && rFW.get_interface_id(sceneCtx).has_value() )