Checkpoint 3: deliver playable samples and complete native authoring workflows

This commit is contained in:
Emil
2026-09-18 04:29:41 +03:00
parent fad5eb4e55
commit d834cfad67
92 changed files with 8335 additions and 353 deletions
+1
View File
@@ -9,6 +9,7 @@
namespace faset::authoring {
Json make_scene(std::string name, int dimension = 3);
Json default_simulation_settings();
Json make_entity(const SchemaRegistry& schemas, std::string name, const std::string& parent = "");
void validate_scene(const Json& scene, const SchemaRegistry& schemas);
+2
View File
@@ -20,6 +20,8 @@ class EditorUI {
void select_document(const std::string& document);
const std::string& selected_entity() const;
void select_entity(const std::string& entity);
bool project_switch_requested() const;
void set_project_switch_enabled(bool enabled);
private:
struct Impl;
+2
View File
@@ -23,6 +23,8 @@ class StdioTransport {
bool closed() const noexcept {
return closed_;
}
// Write failure closes this transport; a disconnected client never exits
// the Editor process. A GUI can continue after closed() becomes true.
void send(const Json& message);
private:
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <faset/ui/ui.hpp>
#include <optional>
namespace faset::editor {
struct ProjectSelection {
std::filesystem::path path;
std::string name;
int dimension = 3;
bool create = false;
};
// Records only existing, valid projects. Call after successful Session setup.
void remember_project(const std::filesystem::path& project);
class ProjectLauncher {
public:
ProjectLauncher(render::Renderer&, const std::filesystem::path& engine_root,
const std::filesystem::path& initial_project = {},
const std::filesystem::path& recent_store = {});
~ProjectLauncher();
void frame(const std::vector<render::Event>&);
const render::Snapshot& snapshot() const;
ui::Context& widgets();
const std::optional<ProjectSelection>& selection() const;
bool cancelled() const;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
std::optional<ProjectSelection>
run_project_launcher(const std::filesystem::path& engine_root,
const std::filesystem::path& initial_project = {},
std::uint64_t max_frames = 0, const std::filesystem::path& capture = {});
} // namespace faset::editor
+6
View File
@@ -46,6 +46,8 @@ class Session {
void register_commands();
Json assets_list() const;
Json jobs() const;
std::string source_signature() const;
Json schema_status() const;
Json job(const std::string& id) const;
void load_schema(const std::filesystem::path& path);
void launch_player(Json scene, const std::filesystem::path& executable);
@@ -65,5 +67,9 @@ class Session {
std::string pending_play_job_;
Json pending_play_scene_;
std::unique_ptr<PluginManager> plugins_;
std::map<std::string, std::string> submitted_sources_;
std::string schema_source_signature_;
bool schema_loaded_ = false;
std::string schema_error_;
};
} // namespace faset::editor
+5
View File
@@ -24,6 +24,11 @@ class SceneView {
SceneView& operator=(const SceneView&) = delete;
render::Snapshot build(const nlohmann::json& flatSceneOrRuntimeSnapshot, float aspect,
CameraSettings camera = {});
// Append box outlines from explicitly supplied physics poses/settings. The
// Player supplies current simulation poses, independent of visual interpolation.
// Supports the initial root-only Box2D/Box3D adapters; does not change the camera.
void appendPhysicsDebug(render::Snapshot&, const nlohmann::json& physicsScene,
float thickness = 0.025f) const;
void clearCache();
const std::vector<std::string>& diagnostics() const;
+10 -1
View File
@@ -79,11 +79,16 @@ struct Snapshot {
std::vector<Quad> ui_quads;
std::vector<Text> ui_text;
};
// CPU-only validation used before publishing a game or creating Vulkan pipelines.
void validate_shader_bundle(const std::filesystem::path& directory);
struct RendererConfig {
std::uint32_t width{1280}, height{720};
std::string title{"Faset Engine"};
bool headless{false};
bool validation{true};
// Optional isolated shader bundle, useful for editor preview and shader reload tests.
std::filesystem::path shader_directory;
};
struct Event {
enum class Type {
@@ -110,8 +115,12 @@ struct Event {
};
struct FrameStats {
std::uint64_t frame{};
bool validation_enabled{};
// Live VkDeviceMemory allocation sizes, including alignment; excludes driver internals.
std::uint64_t gpu_allocated_bytes{};
std::uint32_t texture_count{};
std::uint32_t vertices{}, draw_calls{}, culled_meshes{}, validation_errors{};
double cpu_ms{}, gpu_ms{};
double cpu_ms{}, gpu_ms{}, readback_cpu_ms{};
std::string device;
};
class Renderer {
+2
View File
@@ -118,6 +118,7 @@ struct Widget {
bool visible = true, enabled = true, selected = false, checked = false;
double value = 0, step = .01;
int precision = 3, indent = 0;
float font_size = 0; // Zero inherits the theme typography.
float scroll_y = 0, content_height = 0;
std::string error, tooltip;
Json drag_payload;
@@ -159,6 +160,7 @@ class Context {
const Theme& theme() const;
// Reloads declarative widget properties; matching IDs retain callbacks and
// edit state.
void validate_layout(const Json&) const;
void apply_layout(const Json&);
void layout(float drawable_width, float drawable_height, float dpi_scale = 1);
bool handle(const render::Event&);