skate3recomp-multiplayer/src/skate3_app_common.h
MiTHRAL 36b5169e27 ghost multiplayer: cloth on ghosts + player nameplates
Phase 4:

- Cloth: remote ghosts now wear this player's cloth garments (tee/pants).
  The local player's rigid character.cloth_ropa items (CPU-sim deformed
  root-local VB) are cloned per ghost and drawn with the REMOTE entity world
  from the pose, so each ghost is draped in its own root frame. No mesh or
  cloth data is transmitted; the shader already applies item.world to the
  rigid cloth path (zero blend weights). Sim-inactive (skinned) garments and
  garments not near the local body are skipped.

- Nameplates: display names ride the wire. JOIN carries a display name
  (skate3_ghost_name cvar, default the OS user name); the relay stores it
  per client and echoes {session_id, name} pairs in the HELLO roster
  (RosterEntry). Clients re-JOIN every 5 s so the roster/names stay current
  as members join and leave. A GhostNameplateOverlay (always registered,
  draws only while enabled) projects each ghost's entity origin +1.75 m
  through the published camera and draws a colored name label above it.

  Uses skate3::native_scene::GetPublishedCamera (new thread-safe snapshot of
  the published view-proj/cam) so the UI thread can project world points.

- GhostDialog gains a display-name field. Protocol version bumped to 3.
2026-08-26 21:17:43 -04:00

70 lines
2.1 KiB
C++

#pragma once
#include "generated/skate3_init.h"
#include <atomic>
#include <filesystem>
#include <functional>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <rex/rex_app.h>
#include <rex/ui/overlay/simple_settings_overlay.h>
#include "skate3_native_debug_dialog.h"
#include "skate3_native_ghost_dialog.h"
namespace rex::ui {
class ImGuiDrawer;
}
class Skate3BaseApp : public rex::ReXApp {
public:
using rex::ReXApp::ReXApp;
~Skate3BaseApp() override;
protected:
std::optional<rex::PathConfig> OnFinalizePaths(
const rex::PathConfig& defaults,
std::function<void(rex::PathConfig)> resume) override;
void OnConfigurePaths(rex::PathConfig& paths) override;
void OnConfigureFonts(ImFontAtlas* atlas) override;
void OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) override;
void OnPostSetup() override;
void OnShutdown() override;
private:
void InstallRecipeOverlay();
void InstallBigDeviceAliases();
void InstallDlcPackages();
void ToggleSimpleSettings();
void ToggleNativeDebug();
void ToggleGhost();
void ApplySettingsCursorMode();
void ApplyGameplayCursorMode();
void RestartGame();
void SaveDrawFingerprintLog();
void LogUserMarker();
void LogDebugMarker();
void ApplySelectedProfileToRuntime();
static bool IsRecipeNameChar(char c);
static std::set<std::string> DiscoverRecipeAliases(
const std::filesystem::path& content_root);
static bool CreateOverlayDirectory(const std::filesystem::path& overlay_root,
std::string_view guest_path);
std::filesystem::path config_path_;
std::filesystem::path user_settings_path_;
std::filesystem::path profiles_path_;
std::unique_ptr<rex::ui::SimpleSettingsDialog> simple_settings_dialog_;
std::unique_ptr<skate3::NativeDebugDialog> native_debug_dialog_;
std::unique_ptr<skate3::GhostDialog> ghost_dialog_;
std::unique_ptr<skate3::GhostNameplateOverlay> ghost_nameplate_overlay_;
std::unique_ptr<skate3::RenderModeIndicator> render_mode_indicator_;
bool recipe_overlay_installed_ = false;
bool big_device_aliases_installed_ = false;
std::atomic<uint32_t> debug_marker_count_{0};
};