51 lines
2.8 KiB
C++
51 lines
2.8 KiB
C++
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
module Basic.DebugCommands;
|
||
|
|
import std;
|
||
|
|
import Crafter.Debug;
|
||
|
|
import Basic.World;
|
||
|
|
namespace Debug = Crafter::Debug;
|
||
|
|
|
||
|
|
namespace Basic {
|
||
|
|
struct SpawnArgs {
|
||
|
|
Debug::Required<float> y;
|
||
|
|
float x = 0;
|
||
|
|
float vy = 0;
|
||
|
|
float radius = 0.1f;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct BallArgs {
|
||
|
|
Debug::Required<std::int32_t> id;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
void Basic::RegisterDebug(World& world) {
|
||
|
|
// Commands run on the main thread, between ticks, so they touch the
|
||
|
|
// world as the simulation does.
|
||
|
|
Debug::Command("World_Spawn", "Drop a ball from height y (m), moving at vy (m/s, up is positive); returns its id.",
|
||
|
|
[&world](const SpawnArgs& args) -> Debug::Result<std::int32_t> {
|
||
|
|
if (args.radius <= 0) return Debug::Error{ "BadRadius", "radius must be above 0" };
|
||
|
|
if (*args.y - args.radius <= world.floor.top) {
|
||
|
|
return Debug::Error{ "BelowFloor", std::format("y must clear the floor's top ({} m) by the radius", world.floor.top) };
|
||
|
|
}
|
||
|
|
return world.Spawn(args.x, *args.y, args.vy, args.radius);
|
||
|
|
});
|
||
|
|
Debug::Command("World_Reset", "Remove every ball and drop the scene's five again.", [&world] { world.Reset(); });
|
||
|
|
Debug::Command("World_Clear", "Remove every ball.", [&world] { world.Clear(); });
|
||
|
|
Debug::Command("Ball_Get", "One ball's position, velocity and state.", [&world](const BallArgs& args) -> Debug::Result<Ball> {
|
||
|
|
if (const Ball* ball = world.Find(*args.id)) return *ball;
|
||
|
|
return Debug::Error{ "NoBall", std::format("no ball {}; `get balls` lists them", *args.id) };
|
||
|
|
});
|
||
|
|
|
||
|
|
Debug::Watch("physics.gravity", world.physics.gravity, { .min = -50, .max = 0, .help = "m/s^2" });
|
||
|
|
Debug::Watch("physics.restitution", world.physics.restitution, { .min = 0, .max = 1, .help = "share of speed kept by a bounce" });
|
||
|
|
Debug::Watch("physics.substeps", world.physics.substeps, { .min = 1, .max = 16, .help = "collision checks per tick" });
|
||
|
|
Debug::Watch("floor.top", world.floor.top, { .help = "m" });
|
||
|
|
Debug::Watch("floor.thickness", world.floor.thickness, { .min = 0.01, .max = 10, .help = "m" });
|
||
|
|
Debug::Watch("world.time", [&world] { return world.Time(); }, { .help = "simulated seconds since the last reset" });
|
||
|
|
Debug::Watch("world.count", [&world] { return world.Balls().size(); }, { .help = "balls in the scene" });
|
||
|
|
Debug::Watch("world.lost", [&world] { return world.Lost(); }, { .help = "balls below the floor" });
|
||
|
|
Debug::Watch("world.fastest", [&world] { return world.Fastest(); }, { .help = "m/s, last tick" });
|
||
|
|
Debug::Watch("balls", [&world] { return std::vector<Ball>(world.Balls().begin(), world.Balls().end()); });
|
||
|
|
}
|