Show discovered mission markers in the handheld atlas

This commit is contained in:
2026-10-15 16:53:21 +02:00
parent a2106cfa26
commit 07c4d70de5
6 changed files with 80 additions and 16 deletions
+39
View File
@@ -0,0 +1,39 @@
"""Execute the actual atlas page preparation; widget operations are doubled."""
from policy_harness import ROOT, body, run
p=ROOT/'addons/core/Scripts/Game/ERR/30_Map/ERRM_AtlasPresentation.c'
prepare=body(p,'void Prepare(').replace('Vector(', 'vector(').replace('Widget mapWidget','Widget* mapWidget').replace('Widget objectives','Widget* objectives')
for name in ['ERRM_PaperPages','Math','FrameSlot']:prepare=prepare.replace(name+'.',name+'::')
for name in ['m_Root','objectives']:prepare=prepare.replace(name+'.',name+'->')
run(r'''
#include <cassert>
#include <algorithm>
#include <string>
struct vector{float v[3]={0,0,0};vector(){}vector(float x,float y,float z):v{x,y,z}{}float&operator[](int i){return v[i];}};
struct Widget{float x=0,y=0,w=744,h=1024;int z=0;bool visible=true;Widget*map=nullptr,*overlay=nullptr;Widget*FindAnyWidget(std::string n){return n=="MapWidget"?map:overlay;}void SetVisible(bool b){visible=b;}void SetZOrder(int n){z=n;}};
struct FrameSlot{static void SetPos(Widget*w,float x,float y){w->x=x;w->y=y;}static void SetSize(Widget*w,float x,float y){w->w=x;w->h=y;}};
struct Math{static float Min(float a,float b){return std::min(a,b);}static float Max(float a,float b){return std::max(a,b);}};
struct ERRM_PaperPages{static constexpr int COVER=16777215,OVERVIEW=16777214,REGION=16777216;static bool IsRegion(int page){return page>=REGION;}
// Page geometry is independently implemented by PaperPages; this test targets
// marker visibility and alignment, including non-square regional bounds.
static void RegionBounds(int,int,int,vector,float,vector&lo,vector&hi){lo=vector(.2,0,.3);hi=vector(.7,0,.9);}
};
struct Atlas{Widget*m_Root;float m_X=0,m_Y=0,m_Width=0,m_Height=0;
'''+prepare+r'''
};
int main(){
Widget root,map,overlay;root.map=&map;root.overlay=&overlay;Atlas a{&root};
for(int page:{ERRM_PaperPages::COVER,ERRM_PaperPages::OVERVIEW,ERRM_PaperPages::REGION,ERRM_PaperPages::REGION+4,0,4097}){
for(vector size:{vector(12800,0,12800),vector(24000,0,12000),vector(8000,0,16000)}){
a.Prepare(page,size,.5,8,6);
assert(overlay.visible==(page!=ERRM_PaperPages::COVER));assert(overlay.z>10);
assert(overlay.x==map.x&&overlay.y==map.y&&overlay.w==map.w&&overlay.h==map.h);
assert(overlay.x>=0&&overlay.y>=0&&overlay.x+overlay.w<=744&&overlay.y+overlay.h<=1024);
}
}
root.overlay=nullptr;a.Prepare(0,vector(12800,0,12800),.5,8,6);
}
''')
layout=ROOT/'addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout'
assert 'Anchor 0 0 0 0' in body(layout,'Name "ERR_ObjectiveOverlay"')
assert 'Clipping True' in layout.read_text()
print('PASS: actual atlas preparation shows disclosed markers on overview, regional and detail sheets; cover hidden; overlay matches map rectangle above print for square/wide/tall terrains')
+7 -5
View File
@@ -92,7 +92,7 @@ run(r'''
#include <cmath>
#include <string>
using string=std::string;using vector=std::array<float,3>;
struct Widget{Widget*parent=nullptr,*container=nullptr,*overlay=nullptr,*text=nullptr,*image=nullptr;vector placed={0,0,0};float sx=0,sy=0,width=36,height=36;bool visible=true;virtual ~Widget()=default;Widget*GetParent(){return parent;}Widget*FindAnyWidget(string n){if(n=="UIIconsContainer")return container;if(n=="ERR_ObjectiveOverlay")return overlay;if(n=="ObjectiveText")return text;if(n=="Image")return image;return nullptr;}bool IsVisible(){return visible;}void GetScreenPos(float&x,float&y){x=sx;y=sy;}void GetScreenSize(float&w,float&h){w=width;h=height;}};
struct Widget{Widget*parent=nullptr,*container=nullptr,*overlay=nullptr,*text=nullptr,*image=nullptr;vector placed={0,0,0};float sx=0,sy=0,width=36,height=36;bool visible=true;virtual ~Widget()=default;Widget*GetParent(){return parent;}Widget*FindAnyWidget(string n){if(n=="UIIconsContainer")return container;if(n=="ERR_ObjectiveOverlay")return overlay;if(n=="ObjectiveText")return text;if(n=="Image")return image;return nullptr;}int GetZOrder(){return 20;}bool IsVisible(){return visible;}void GetScreenPos(float&x,float&y){x=sx;y=sy;}void GetScreenSize(float&w,float&h){w=width;h=height;}};
struct TextWidget:Widget{string label;static TextWidget*Cast(Widget*w){return dynamic_cast<TextWidget*>(w);}string GetText(){return label;}};
struct ImageWidget:Widget{static ImageWidget*Cast(Widget*w){return dynamic_cast<ImageWidget*>(w);}void GetImageSize(int,int&w,int&h){w=64;h=64;}};
struct ERR_ObjectiveMapElement{vector pos;vector GetPos(){return pos;}};
@@ -163,16 +163,18 @@ assert 'GetOrigin() + "1037.25 0 1063.75"' in s
print('PASS: actual long-warning phases retain visible label through1500ms checkpoint then restore radio before close; synthetic marker separated from unmoved player')
# Actual Center method offsets the pan target, not the disclosed data or input.
center=body(p,'protected void Center(').replace('protected ','').replace('m_Marker.','m_Marker->').replace('m_Map.','m_Map->')
center=body(p,'protected void Center(').replace('Math.Min','std::min').replace('GetMapWidget().','GetMapWidget()->').replace('Math.Min','std::min').replace('std::min(100, width * 0.25)', 'std::min(100.f, width * 0.25f)').replace('protected ','').replace('m_Marker.','m_Marker->').replace('m_Map.','m_Map->')
run(r'''
#include <cassert>
#include <cmath>
#include <initializer_list>
#include <algorithm>
struct Canvas{float width=500;void GetScreenSize(float&w,float&h){w=width;h=500;}};
struct Marker{int x=6250,y=7250;void GetWorldPos(int p[2]){p[0]=x;p[1]=y;}};
struct Map{float zoom=0,x=0,y=0,duration=0;int calls=0;void ZoomPanSmooth(float z,float px,float py,float t){zoom=z;x=px;y=py;duration=t;calls++;}};
struct Map{Canvas canvas;Canvas*GetMapWidget(){return &canvas;}float zoom=0,x=0,y=0,duration=0;int calls=0;void ZoomPanSmooth(float z,float px,float py,float t){zoom=z;x=px;y=py;duration=t;calls++;}};
struct Probe{Marker*m_Marker;Map*m_Map;
'''+center+r'''
};
int main(){Marker marker;Map map;Probe p{&marker,&map};for(float zoom:{0.3f,0.6f}){p.Center(zoom);assert(map.zoom==zoom&&map.y==7250&&std::abs(map.duration-0.1f)<0.001f);assert(std::abs((marker.x-map.x)*zoom+100.0f)<0.01f);assert(marker.x==6250&&marker.y==7250);}assert(map.calls==2);}
int main(){Marker marker;Map map;Probe p{&marker,&map};for(float zoom:{0.3f,0.6f}){p.Center(zoom);assert(map.zoom==zoom&&map.y==7250&&std::abs(map.duration-0.1f)<0.001f);assert(std::abs((marker.x-map.x)*zoom+100.0f)<0.01f);assert(marker.x==6250&&marker.y==7250);}assert(map.calls==2);map.canvas.width=124;p.Center(.3f);assert(std::abs((map.x-marker.x)*.3f-31)<.01f);}
''')
print('PASS: actual Center places marker100screenpx left of pan center at both fixture zooms without altering disclosed coordinates')
print('PASS: actual Center keeps marker offset within large and small native viewports at both fixture zooms without altering disclosed coordinates')