Add civilian traffic variants, farm tractors and UI scaling; record Workshop 0.0.143
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -65,7 +65,9 @@ class MenuSourceTests(unittest.TestCase):
|
||||
for key in ('PositionX', 'PositionY', 'SizeX', 'SizeY')]
|
||||
nav = json.loads((builder.SOURCE / 'navigation.json').read_text())
|
||||
pages = {p['key']: p for p in nav['pages']}
|
||||
panel_width, panel_height = rect('Panel')[2:]
|
||||
panel = re.search(r'Name "PanelSize" ([^{}]+)', layout)[1]
|
||||
panel_width = int(re.search(r'\bWidthOverride (\d+)', panel)[1])
|
||||
panel_height = int(re.search(r'\bHeightOverride (\d+)', panel)[1])
|
||||
previous_right = 0
|
||||
for group in nav['groups']:
|
||||
x, y, width, height = rect('Main_' + group['name'])
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Execute panel-only scaling with viewport and DPI boundaries."""
|
||||
from policy_harness import ROOT, body, run
|
||||
source=body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenuView.c','static void FitPanel(')
|
||||
source=source.replace('Widget root','Widget* root').replace('ScaleWidget scale = ScaleWidget.Cast(root.FindAnyWidget("PanelScale"));','ScaleWidget* scale = root->FindAnyWidget("PanelScale");')
|
||||
source=source.replace('GetGame().','GetGame()->').replace('GetWorkspace().','GetWorkspace()->').replace('root.','root->').replace('scale.','scale->').replace('Math.','Math::')
|
||||
run(r'''
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
struct ScaleWidget {float scale=1;int writes=0;float GetScale(){return scale;}void SetScale(float v){scale=v;writes++;}};
|
||||
struct Widget {float width=1920,height=1080;ScaleWidget panel;bool present=true;ScaleWidget* FindAnyWidget(const char*){return present?&panel:nullptr;}void GetScreenSize(float& w,float& h){w=width;h=height;}};
|
||||
struct Workspace {float factor=1;float DPIScale(float x){return x*factor;}} workspace;
|
||||
struct Game {Workspace* GetWorkspace(){return &workspace;}} game;
|
||||
Game* GetGame(){return &game;}
|
||||
namespace Math {float Min(float a,float b){return std::min(a,b);}float AbsFloat(float v){return std::abs(v);}}
|
||||
'''+source+r'''
|
||||
int main(){
|
||||
Widget root;FitPanel(nullptr);FitPanel(&root);assert(root.panel.scale==1 && root.panel.writes==0);
|
||||
for(float dpi:{.75f,1.f,1.25f,1.5f,2.f}) {
|
||||
workspace.factor=dpi;FitPanel(&root);
|
||||
assert(root.panel.scale<=1 && root.panel.scale>0);
|
||||
assert(1220*dpi*root.panel.scale<=root.width*.96f+.1f);
|
||||
assert(760*dpi*root.panel.scale<=root.height*.96f+.1f);
|
||||
int writes=root.panel.writes;FitPanel(&root);assert(root.panel.writes==writes);
|
||||
assert(workspace.factor==dpi);
|
||||
}
|
||||
root.width=800;root.height=600;FitPanel(&root);
|
||||
assert(1220*workspace.factor*root.panel.scale<=768.1f);
|
||||
root.width=3840;root.height=2160;workspace.factor=1;FitPanel(&root);assert(root.panel.scale==1);
|
||||
root.height=0;int writes=root.panel.writes;FitPanel(&root);assert(root.panel.writes==writes);
|
||||
root.present=false;FitPanel(&root);assert(root.panel.writes==writes);
|
||||
}
|
||||
''')
|
||||
print('PASS: panel fits narrow/large-DPI viewports, restores requested size, avoids repeated writes and preserves user DPI')
|
||||
@@ -36,7 +36,7 @@ namespace ERR_CivilianTrafficRules{
|
||||
bool CleanupDue(float now,float since){return since>=0&&now-since>=60000;}
|
||||
}
|
||||
struct SCR_GarbageSystem{static SCR_GarbageSystem* GetByEntityWorld(IEntity*){static SCR_GarbageSystem g;return &g;}void UpdateBlacklist(IEntity*,bool){}};
|
||||
struct SiteData{bool Consumed=false;};
|
||||
struct SiteData{bool Consumed=false;bool Farm=false;};
|
||||
struct ERR_ParkedVehicle{IEntity* Entity=nullptr;SiteData* Site=nullptr;Vec Origin;float HiddenSince=-1;};
|
||||
struct Mode{int owned=0;void Own(IEntity*){owned++;}};
|
||||
struct Service{
|
||||
@@ -46,7 +46,7 @@ struct Service{
|
||||
Array<ERR_ParkedVehicle*> m_Parked;Array<Vec> views;Array<IEntity*> actors;
|
||||
bool Running(){return running;}float Now(){return clock;}
|
||||
bool Observers(Array<Vec>& o,Array<IEntity*>& a){o=views;a=actors;return known;}
|
||||
bool Hidden(Vec,Vec,Array<IEntity*>& a,IEntity* e){hiddenCalls++;return e->hidden;}
|
||||
bool Hidden(Vec,Vec,Array<IEntity*>& a,IEntity* e,bool farm){hiddenCalls++;return e->hidden;}
|
||||
void Discover(Array<Vec>&,float){discovers++;}void Plan(Array<Vec>&,Array<IEntity*>&,float){plans++;}
|
||||
void Pending(Array<Vec>&,Array<IEntity*>&){pending++;}
|
||||
''' + methods.replace('m_Pending = nullptr','m_Pending = 0') + r'''
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"""Run production garage filtering and vehicle-fit rules against unsafe inputs."""
|
||||
from policy_harness import ROOT, body, run
|
||||
p = ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_GarageVehicles.c'
|
||||
rules = '\n'.join(body(p, s) for s in ('static bool Garage(', 'static bool Envelope(', 'static bool Yard(', 'static vector YardOffset('))
|
||||
rules = '\n'.join(body(p, s) for s in ('static bool Garage(', 'static bool Envelope(', 'static bool Yard(', 'static bool Farm(', 'static bool FarmEnvelope(', 'static vector YardOffset('))
|
||||
rules += '\n' + body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ParkedCarCatalog.c', 'static bool Candidate(')
|
||||
rules += '\n' + body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ParkedCarCatalog.c', 'static bool MovingCandidate(')
|
||||
rules = rules.replace('vector ', 'Vec ').replace('ERR_ForceRules.', 'ERR_ForceRules::')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
@@ -32,12 +33,26 @@ int main(){
|
||||
assert(!Yard("Prefabs/Structures/Houses/Village/House_Village_E_1I06/House_Village_E_1I06_base.et"));
|
||||
assert(!Yard("Prefabs/Structures/Houses/Village/House_Village_E_1I06/Dst/House_Village_E_1I06_ruin.et"));
|
||||
assert(!Yard("Prefabs/Structures/Houses/Village/House_Village_E_1I06/Furniture/House_Village_E_1I06_furniture_01.et"));
|
||||
assert(Farm("Prefabs/Structures/Agriculture/Barn/Barn_E_01/Barn_E_01_white.et"));
|
||||
assert(Farm("Prefabs/Structures/Agriculture/CowShed/CowShed_E_01/CowShed_E_01_short.et"));
|
||||
assert(!Farm("Prefabs/Structures/Agriculture/Barn/Barn_E_01/Dst/Barn_E_01_Ruin.et"));
|
||||
assert(!Farm("Prefabs/Structures/Agriculture/Barn/Barn_E_01/Barn_E_01_Base.et"));
|
||||
assert(!Farm("Prefabs/Structures/Agriculture/Barn/Barn_E_01/Furniture/Barn_E_01_furniture_01.et"));
|
||||
assert(FarmEnvelope({{-1.4,-0.2,-2.9}},{{1.4,3,2.9}}));
|
||||
assert(!FarmEnvelope({{-1.5,0,-2}},{{1,3,2}}));
|
||||
assert(!FarmEnvelope({{-1,0,-2}},{{1,3.2,2}}));
|
||||
assert(!FarmEnvelope({{-1,0,-3}},{{1,3,2}}));
|
||||
assert(!FarmEnvelope({{-1,0,-2}},{{1,NAN,2}}));
|
||||
Vec low={{-4,-1,-6}},high={{6,8,8}};
|
||||
assert(YardOffset(low,high,0)[0]==-7 && YardOffset(low,high,0)[2]==1);
|
||||
assert(YardOffset(low,high,1)[0]==9 && YardOffset(low,high,1)[1]==0);
|
||||
assert(YardOffset(low,high,2)[2]==-9 && YardOffset(low,high,2)[0]==1);
|
||||
assert(YardOffset(low,high,3)[2]==11);
|
||||
assert(YardOffset(low,high,0,4)[0]==-8 && YardOffset(low,high,3,4)[2]==12);
|
||||
assert(Candidate("{GUID}Prefabs/Vehicles/Wheeled/T601/T601_blue_twoTone.et",false));
|
||||
assert(!MovingCandidate("{GUID}Prefabs/Vehicles/Wheeled/T601/T601_blue_twoTone.et"));
|
||||
assert(MovingCandidate("{GUID}Prefabs/Vehicles/Wheeled/V2101/V2101_lightBlue.et"));
|
||||
assert(!MovingCandidate("Prefabs/Vehicles/Wheeled/S105/S105_rally_08.et"));
|
||||
assert(Candidate("Prefabs/Vehicles/Wheeled/V2101/V2101_lightBlue.et",false));
|
||||
assert(Candidate("Prefabs/Vehicles/Wheeled/S105/S105_rally_08.et",true));
|
||||
assert(!Candidate("Prefabs/Vehicles/Wheeled/S105/S105_rally_08.et",false));
|
||||
@@ -75,13 +90,13 @@ struct Vec {float v[3];float operator[](int i)const{return v[i];}
|
||||
Vec operator+(Vec b)const{return {{v[0]+b[0],v[1]+b[1],v[2]+b[2]}};}
|
||||
Vec operator*(float n)const{return {{v[0]*n,v[1]*n,v[2]*n}};}};
|
||||
bool worldAvailable=true,managerAvailable=true,hasRoad=true,wetEdge=false;
|
||||
float roadDistance=20,edgeHeight=0;
|
||||
float roadDistance=20,edgeHeight=0,waterBoundary=2;
|
||||
struct BaseRoad{float width=10;float GetWidth(){return width;}} roadInstance;
|
||||
struct Roads{void GetClosestRoad(Vec,BaseRoad*& road,float& distance,bool){road=hasRoad?&roadInstance:nullptr;distance=roadDistance;}} roads;
|
||||
struct SCR_AIWorld{Roads* GetRoadNetworkManager(){return managerAvailable?&roads:nullptr;}} nativeWorld;
|
||||
namespace ERR_ForceRules{bool Finite(float n){return std::isfinite(n);}}
|
||||
namespace SCR_TerrainHelper{float GetTerrainY(Vec p){return p[0]>.5f?edgeHeight:0;}}
|
||||
namespace ERR_Actors{bool DryGround(Vec p){return !(wetEdge&&p[2]>2)&&std::isfinite(SCR_TerrainHelper::GetTerrainY(p));}}
|
||||
namespace ERR_Actors{bool DryGround(Vec p){return !(wetEdge&&p[2]>waterBoundary)&&std::isfinite(SCR_TerrainHelper::GetTerrainY(p));}}
|
||||
namespace Math{float AbsFloat(float n){return std::abs(n);}}
|
||||
''' + ground + r'''
|
||||
int main(){Vec p={{0,0,0}},matrix[4]={{{1,0,0}},{{0,1,0}},{{0,0,1}},{{0,0,0}}};
|
||||
@@ -90,7 +105,7 @@ int main(){Vec p={{0,0,0}},matrix[4]={{{1,0,0}},{{0,1,0}},{{0,0,1}},{{0,0,0}}};
|
||||
hasRoad=false;assert(YardGround(p,matrix));hasRoad=true;
|
||||
worldAvailable=false;assert(!YardGround(p,matrix));worldAvailable=true;
|
||||
managerAvailable=false;assert(!YardGround(p,matrix));managerAvailable=true;
|
||||
wetEdge=true;assert(!YardGround(p,matrix));wetEdge=false;
|
||||
wetEdge=true;assert(!YardGround(p,matrix));waterBoundary=2.75f;assert(YardGround(p,matrix)&&!YardGround(p,matrix,true));wetEdge=false;
|
||||
edgeHeight=.19f;assert(!YardGround(p,matrix));edgeHeight=.17f;assert(YardGround(p,matrix));
|
||||
edgeHeight=NAN;assert(!YardGround(p,matrix));edgeHeight=0;
|
||||
roadDistance=NAN;assert(!YardGround(p,matrix));
|
||||
|
||||
Reference in New Issue
Block a user