feat: derive resource visuals from state
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# Jajce Resource States 05
|
||||
|
||||
Captured: 2026-07-17
|
||||
|
||||
## Files
|
||||
|
||||
- [full resources](jajce_resource_states_05_full.png)
|
||||
- [low resources](jajce_resource_states_05_low.png)
|
||||
- [depleted resources](jajce_resource_states_05_depleted.png)
|
||||
- `world/resource_nodes/ResourceAmountVisual.gd`
|
||||
- `world/jajce/HarvestableTreePresentation.tscn`
|
||||
- `tests/jajce_resource_presentation_state_test.gd`
|
||||
|
||||
The three images use the same 1280×720 cross-river camera, daylight value,
|
||||
warmup, and Metal renderer. Debug labels are hidden. The lower-left berry patch
|
||||
and right-hand harvestable tree are shown at their authored full amounts, at
|
||||
40%/50% respectively, and at zero.
|
||||
|
||||
## Amount-derived visual language
|
||||
|
||||
`ResourceAmountVisual` finds its owning `ResourceNode` and derives one of three
|
||||
tiers from `amount_remaining / initial_amount`:
|
||||
|
||||
- full keeps all five berry leaf clumps, eight berries, and four tree canopies;
|
||||
- low keeps three leaf clumps, four berries, and two tree canopies; and
|
||||
- depleted keeps a two-leaf fruitless remnant and replaces the tree with a
|
||||
low-poly stump and warm cut face.
|
||||
|
||||
The threshold is deliberately simple and readable: a positive source at or
|
||||
below half amount is low. The berry keeps using two bounded MultiMeshes, so
|
||||
thinning changes only `visible_instance_count`; it does not create or destroy
|
||||
nodes during play. The tree wrapper reuses the existing wind-reactive standing
|
||||
tree and toggles authored crown/stump parts.
|
||||
|
||||
## Authority and restore proof
|
||||
|
||||
`ResourceStateRecord` remains the only amount authority. `ResourceNode` now
|
||||
emits its existing `amount_changed` presentation signal when authoritative
|
||||
state is rebound, including restore. The visual contract listens to that signal
|
||||
and also refreshes once after scene readiness, covering either bind order.
|
||||
|
||||
The focused scenario performs two real player harvests on
|
||||
`berry_bush_river_02` and two real NPC gather completions on
|
||||
`tree_river_resource_01`, checks the low presentation and NPC wood inventory,
|
||||
then fully depletes both through those same production paths. It restores low
|
||||
and depleted snapshots in turn and verifies the presentation is reconstructed.
|
||||
The resource records contain no visual, visibility, tier, or stump fields.
|
||||
|
||||
The capture tool's optional amount overrides also construct and bind ordinary
|
||||
`ResourceStateRecord`s. They do not directly manipulate visual children, so
|
||||
the review images exercise the same runtime contract as gameplay.
|
||||
|
||||
## Next slice
|
||||
|
||||
Apply this contract to the existing `tree_forest_grove_01` and
|
||||
`tree_forest_grove_02` stable IDs in one bounded forest-edge cluster. Decorative
|
||||
canopy and understory should stay presentation-only while the two finite trees
|
||||
remain reachable, discoverable, depletable, and restore correctly.
|
||||
|
||||
## Capture commands
|
||||
|
||||
```bash
|
||||
HOME="$PWD/logs/quality/godot_profile" \
|
||||
APPDATA="$PWD/logs/quality/godot_profile" \
|
||||
LOCALAPPDATA="$PWD/logs/quality/godot_profile" \
|
||||
/Applications/Godot.app/Contents/MacOS/Godot \
|
||||
--path "$PWD" --script res://tools/capture_jajce_lookdev.gd -- \
|
||||
--scene=res://world/jajce/JajceResourceStateLookdev.tscn \
|
||||
--output=res://docs/baselines/jajce_resource_states_05_full.png \
|
||||
--hide-resource-labels
|
||||
```
|
||||
|
||||
For the low frame, append:
|
||||
|
||||
```text
|
||||
--resource-amount=berry_bush_river_02:2
|
||||
--resource-amount=tree_river_resource_01:4
|
||||
```
|
||||
|
||||
For the depleted frame, use the same arguments with both amounts set to `0`.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 429 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnusf1uofgeam"
|
||||
path="res://.godot/imported/jajce_resource_states_05_depleted.png-4da1f8d2357fb72267bc5e3167868d55.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://docs/baselines/jajce_resource_states_05_depleted.png"
|
||||
dest_files=["res://.godot/imported/jajce_resource_states_05_depleted.png-4da1f8d2357fb72267bc5e3167868d55.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 430 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c6fr86t0glm1p"
|
||||
path="res://.godot/imported/jajce_resource_states_05_full.png-b7555dd39fe62146f66c1e731a0813d3.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://docs/baselines/jajce_resource_states_05_full.png"
|
||||
dest_files=["res://.godot/imported/jajce_resource_states_05_full.png-b7555dd39fe62146f66c1e731a0813d3.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 428 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://lerebtc2de5v"
|
||||
path="res://.godot/imported/jajce_resource_states_05_low.png-ca9e13189ad1a8dc22e32380ddf38b2f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://docs/baselines/jajce_resource_states_05_low.png"
|
||||
dest_files=["res://.godot/imported/jajce_resource_states_05_low.png-ca9e13189ad1a8dc22e32380ddf38b2f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
Reference in New Issue
Block a user