Tooling
This commit is contained in:
@@ -133,6 +133,7 @@ agree. A row is added to a spec and here in the same pull request as the emit ca
|
||||
| Stats | `status_applied`, `status_blocked`, `status_removed` |
|
||||
| Combat | `enemy_spawned`, `enemy_killed`, `ability_used`, `player_damaged`, `player_downed`, `player_revived`, `player_died`, `party_wiped`, `grief_action` |
|
||||
| Crafting | `substance_processed`, `piece_shaped`, `piece_enchanted`, `item_assembled`, `assembly_rejected`, `activity_completed`, `characteristic_discovered`, `weapon_equipped` |
|
||||
| World | `world_map_opened` (layer, metres_per_pixel, opened_by) |
|
||||
| Technical | `perf_sample`, `error_logged`, `net_correction` (count of visible movement corrections per 30 s, from `p.NetShowCorrections`) |
|
||||
|
||||
### The rows that carry weight
|
||||
|
||||
@@ -161,12 +161,80 @@ Hooks now, content later; none of the later work touches a widget.
|
||||
| Rebinding | prompts read the live binding | the rows ship in step 3 through engine settings |
|
||||
| Hold-to-confirm | on irreversible verbs already | an option to extend it to every verb |
|
||||
|
||||
## The world map
|
||||
|
||||
```
|
||||
[DECIDED] The map is a picture of the world with a linear transform on it. There is no capture. (D-73)
|
||||
```
|
||||
|
||||
`L_World` is a whole planet map imported with no crop (`RawContent/World/Region.json`), so the art and the ground
|
||||
are the same rectangle at two scales and the whole projection is one multiply and one add per axis. Everything
|
||||
else about a map view falls out of that and most of it is absence: no scene capture, no render target, no minimap
|
||||
actor, no per-tile bookkeeping. A capture would also be *wrong* rather than merely expensive — the level is
|
||||
world-partitioned, so a capture only ever sees the streamed-in region, and a map is exactly the thing that must
|
||||
show ground nobody is standing on.
|
||||
|
||||
```
|
||||
Source/SaltyCore/World/
|
||||
└── WorldMapProjection.h // pure: world cm <-> 0..1 across the art, the seam, distance on the ground
|
||||
|
||||
Source/Salty/World/
|
||||
├── WorldMapDefinition.h // UPrimaryDataAsset: the projection, the layers, which level it is a map of
|
||||
└── WorldMapSubsystem.h // world subsystem: finds the definition, holds the markers, emits the event
|
||||
|
||||
Source/Salty/UI/
|
||||
├── SWorldMap.h // the map itself: drawing, panning, zooming, markers, scale bar
|
||||
└── WorldMapWidget.h // UWidget wrapping it, so a Blueprint can drop one into a screen
|
||||
|
||||
Source/SaltyEditor/WorldMap/
|
||||
└── WorldMapTab.h // the same SWorldMap in a dockable tab; a click moves the viewport camera
|
||||
```
|
||||
|
||||
**Why Slate and not a `UUserWidget`.** The map has two hosts with nothing else in common, and the editor tab has
|
||||
no `UWorld` at all — anything that needed one to exist could not be shared, and a second implementation is where
|
||||
two maps quietly start disagreeing about where things are. `UWorldMapWidget` is the UMG wrapper; `WBP_WorldMap`
|
||||
is what owns the frame around it, which is the usual C++/Blueprint line.
|
||||
|
||||
**Markers are registered, never searched for.** An actor that wants to be on the map adds one in `BeginPlay` and
|
||||
removes it in `EndPlay`. The local player's own body is deliberately not a registered marker: it moves every
|
||||
frame, and a registry entry rewritten every frame is a registry being used as a variable. It is queried each
|
||||
paint instead, through `GetLocalPlayerMarker`, which also means it is drawn last and can never end up hidden
|
||||
under a waypoint that happens to be on top of it.
|
||||
|
||||
**Following is sticky in both directions.** The map opens centred on the player and tracks them. Panning by hand
|
||||
turns the follow off, because a map that snaps back the moment you let go cannot be read — and because that
|
||||
would otherwise be a one-way door, a left double-click (or `bs.WorldMapFollow`) goes back to the player and
|
||||
resumes it. `FocusOnWorld` deliberately does *not* re-arm the follow: a "go here" jump and a "go back to me"
|
||||
are different intents and only one of them means "and keep up".
|
||||
|
||||
**The art is data.** `RawContent/World/MapArt/layers.json` says which planet images become layers; `Tools/MapArt`
|
||||
renders them (including the derived shaded-relief layer) and `Scripts/Authoring/create_world_map.py` imports them
|
||||
and writes the definition. The projection is copied out of `Region.json` rather than typed, because a map that
|
||||
disagrees with the landscape about how big the world is is the one bug here that still looks like a plausible map.
|
||||
|
||||
**The key is a debug bind, deliberately.** `M` opens the map and `N` cycles its layers, both `DebugExecBindings`
|
||||
in `Config/DefaultInput.ini` pointing at the `bs.*` commands. That is the engine's own mechanism for putting a
|
||||
key on a console command: development builds only, no Input Action, no mapping context, no asset. It is the
|
||||
right shape *because* it is not the input map — step 3 designs that, and a map key invented here would be a
|
||||
guess at an `Input.*` action that step has to live with. When the map gets a HUD it gets a real action and
|
||||
those two lines go away.
|
||||
|
||||
**Not yet:** there is no HUD, so the only ways in are that key, the console and the editor tab. It does
|
||||
not read the theme asset either, because there is not one yet; its colours are local and will move to `UUITheme`
|
||||
when that lands. Overlay marks — the towns, roads and forests `overlay.json` already carries in world metres —
|
||||
are not drawn; they transfer by the same normalised coordinates and are the obvious next thing.
|
||||
|
||||
## Telemetry
|
||||
|
||||
`settings_changed` with `setting_id` as the dotted path (`camera.fov.first_person`, `input.bindings.interact`) and
|
||||
the new value. Nothing else: prompt visibility and menu opens are high frequency and low value, and
|
||||
`prop_interacted` already answers whether players find things.
|
||||
|
||||
`world_map_opened` with the layer, the zoom in ground metres per pixel and what opened it. One event, because
|
||||
opening the map is the act worth counting and which layer and how far in say what a person wanted from it.
|
||||
Every way of opening it goes through `UWorldMapSubsystem::NoteMapOpened`, so the count is of maps opened and not
|
||||
of the ways of opening them.
|
||||
|
||||
## Open questions
|
||||
|
||||
- **Q1. World-space widget legibility.** A `UWidgetComponent` at bench distance in both camera modes has to be
|
||||
|
||||
Reference in New Issue
Block a user