Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
87 lines
9.8 KiB
Python
87 lines
9.8 KiB
Python
"""Execute candidate hierarchy adapter; native slot regeneration/rendering unqualified."""
|
|
from policy_harness import ROOT, body, run
|
|
P=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c'
|
|
def cpp(s):
|
|
s=s.replace('protected ', '').replace('override ', '').replace('ref ', '')
|
|
for t in ('Widget','ERR_GameMode','GridLayoutWidget','ERR_InventoryGridPlacement'):
|
|
for n in ('widget','child','w','mode','root','grid','named','placement','previousHost','host'):
|
|
s=s.replace(t+' '+n+'(',t+'* '+n+'(').replace(t+' '+n+')',t+'* '+n+')').replace(t+' '+n+' =',t+'* '+n+' =')
|
|
s=s.replace('GridLayoutWidget.Cast(', 'dynamic_cast<GridLayoutWidget*>(').replace('VerticalLayoutWidget.Cast(', 'dynamic_cast<VerticalLayoutWidget*>(')
|
|
for n in ('widget','child','w','mode','root','grid','named','placement','previousHost','host','m_ERRStorageLayoutRoot','m_ERRStorageLayoutGrid','m_ERRStorageLayoutHost','m_MenuHandler'):
|
|
s=s.replace(n+'.',n+'->')
|
|
for n in ('ERR_GameMode','SCR_InventoryMenuUI','WidgetType','WidgetFlags','GridSlot','AlignableSlot','LayoutHorizontalAlign','LayoutVerticalAlign'):
|
|
s=s.replace(n+'.',n+'::')
|
|
s=s.replace('GetGame().','GetGame()->').replace('GetWorkspace().','GetWorkspace()->')
|
|
s=s.replace('null','nullptr').replace('bool created;', 'bool created = false;')
|
|
return s.replace('super.', 'Native::')
|
|
placement='\n'.join(cpp(body(P,k)) for k in ('bool Capture(', 'bool Apply('))
|
|
prepare=cpp(body(P,'bool ERR_PrepareStorageLayout('))
|
|
attach=cpp(body(P,'override void HandlerAttached('))
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
using string=std::string;
|
|
namespace LayoutHorizontalAlign{enum{Left,Center,Right,Stretch};}
|
|
namespace LayoutVerticalAlign{enum{Top,Center,Bottom,Stretch};}
|
|
namespace WidgetType{const int VerticalLayoutWidgetTypeID=7;}
|
|
namespace WidgetFlags{const int VISIBLE=1;}
|
|
struct Widget {virtual ~Widget(){}Widget* parent=nullptr;std::vector<Widget*> children;string name;bool removed=false,refuseAdd=false;int row=0,col=0,rows=1,cols=1,h=0,v=0;float l=0,t=0,r=0,b=0;int handlers=0;
|
|
Widget* GetParent(){return parent;}Widget* GetChildren(){return children.empty()?nullptr:children[0];}string GetName(){return name;}void SetName(string n){name=n;}
|
|
void AddChild(Widget* child){if(refuseAdd)return;if(child->parent){auto& a=child->parent->children;a.erase(std::remove(a.begin(),a.end(),child),a.end());}child->parent=this;children.push_back(child);child->row=child->col=0;child->rows=child->cols=1;child->l=child->t=child->r=child->b=0;child->h=child->v=0;}
|
|
Widget* FindAnyWidget(string n){if(name==n)return this;for(auto c:children)if(auto result=c->FindAnyWidget(n))return result;return nullptr;}
|
|
void RemoveFromHierarchy(){removed=true;if(parent){auto& a=parent->children;a.erase(std::remove(a.begin(),a.end(),this),a.end());}parent=nullptr;}
|
|
};
|
|
struct GridLayoutWidget:Widget{};struct VerticalLayoutWidget:Widget{};
|
|
namespace GridSlot {void Check(Widget* w){assert(w&&dynamic_cast<GridLayoutWidget*>(w->parent));}int GetRow(Widget*w){Check(w);return w->row;}int GetColumn(Widget*w){Check(w);return w->col;}int GetRowSpan(Widget*w){Check(w);return w->rows;}int GetColumnSpan(Widget*w){Check(w);return w->cols;}void SetRow(Widget*w,int n){Check(w);w->row=n;}void SetColumn(Widget*w,int n){Check(w);w->col=n;}void SetRowSpan(Widget*w,int n){Check(w);w->rows=n;}void SetColumnSpan(Widget*w,int n){Check(w);w->cols=n;}}
|
|
namespace AlignableSlot {int GetHorizontalAlign(Widget*w){return w->h;}int GetVerticalAlign(Widget*w){return w->v;}void GetPadding(Widget*w,float&l,float&t,float&r,float&b){l=w->l;t=w->t;r=w->r;b=w->b;}void SetHorizontalAlign(Widget*w,int n){w->h=n;}void SetVerticalAlign(Widget*w,int n){w->v=n;}void SetPadding(Widget*w,float l,float t,float r,float b){w->l=l;w->t=t;w->r=r;w->b=b;}}
|
|
struct Workspace {int creates=0;bool fail=false,wrongType=false,refuseAdd=false;Widget* last=nullptr;Widget* CreateWidget(int type,int flags,void*,int,Widget* parent){assert(type==7&&flags==1);creates++;if(fail)return nullptr;Widget* host=wrongType?new Widget:new VerticalLayoutWidget;parent->AddChild(host);host->refuseAdd=refuseAdd;last=host;return host;}};
|
|
struct ERR_GameMode {static ERR_GameMode* current;bool active=true;int world=1;static ERR_GameMode* Get(){return current;}bool Active(){return active;}int GetWorld(){return world;}};ERR_GameMode* ERR_GameMode::current=nullptr;
|
|
struct Game {Workspace workspace;bool menu=true;int world=1;Workspace* GetWorkspace(){return &workspace;}bool GetMenuManager(){return menu;}int GetWorld(){return world;}} game;Game* GetGame(){return &game;}
|
|
struct ERR_InventoryGridPlacement {int m_Row=0,m_Column=0,m_RowSpan=0,m_ColumnSpan=0,m_Horizontal=0,m_Vertical=0;float m_Left=0,m_Top=0,m_Right=0,m_Bottom=0;
|
|
'''+placement+r'''
|
|
};
|
|
struct SCR_InventoryMenuUI {static SCR_InventoryMenuUI* current;Widget* root=nullptr;Widget* m_ERRStorageLayoutRoot=nullptr;GridLayoutWidget* m_ERRStorageLayoutGrid=nullptr;VerticalLayoutWidget* m_ERRStorageLayoutHost=nullptr;bool m_ERRStorageLayoutBound=false;static SCR_InventoryMenuUI* GetInventoryMenu(){return current;}Widget* GetRootWidget(){return root;}
|
|
'''+prepare+r'''
|
|
};SCR_InventoryMenuUI* SCR_InventoryMenuUI::current=nullptr;
|
|
struct Native {int calls=0,baseInit=0,refresh=0,invalidLayoutCalls=0;void HandlerAttached(Widget* w){calls++;baseInit++;if(!w||!dynamic_cast<VerticalLayoutWidget*>(w->parent))invalidLayoutCalls+=2;refresh++;}};
|
|
struct Handler:Native {SCR_InventoryMenuUI* m_MenuHandler=nullptr;
|
|
'''+attach+r'''
|
|
};
|
|
struct Fixture {ERR_GameMode mode;Widget root,child;GridLayoutWidget grid;SCR_InventoryMenuUI menu;Handler handler;
|
|
Fixture(){game={};ERR_GameMode::current=&mode;SCR_InventoryMenuUI::current=&menu;menu.root=&root;grid.name="StoragesListSlot";root.AddChild(&grid);child.name="Frame0";grid.AddChild(&child);child.row=2;child.col=3;child.rows=4;child.cols=5;child.l=1;child.t=2;child.r=3;child.b=4;child.h=2;child.v=1;handler.m_MenuHandler=&menu;}
|
|
void attach(){handler.HandlerAttached(&child);assert(handler.calls==1&&handler.baseInit==1&&handler.refresh==1);}
|
|
};
|
|
int main(){
|
|
{Fixture f;f.attach();auto host=f.menu.m_ERRStorageLayoutHost;assert(host&&host->parent==&f.grid&&f.child.parent==host&&game.workspace.creates==1&&f.handler.invalidLayoutCalls==0);assert(host->row==2&&host->col==3&&host->rows==4&&host->cols==5&&host->l==1&&host->t==2&&host->r==3&&host->b==4&&host->h==2&&host->v==1);assert(f.child.l==0&&f.child.t==0&&f.child.r==0&&f.child.b==0&&f.child.h==3&&f.child.v==3);
|
|
// Native refresh removes the old root; the same menu reuses its empty host.
|
|
f.child.RemoveFromHierarchy();Widget next;next.name="Frame0";f.grid.AddChild(&next);Handler second;second.m_MenuHandler=&f.menu;second.HandlerAttached(&next);assert(second.calls==1&&second.baseInit==1&&second.refresh==1&&second.invalidLayoutCalls==0&&game.workspace.creates==1&&next.parent==host&&f.grid.children.size()==1);
|
|
}
|
|
for(int fault=0;fault<8;fault++){Fixture f;SCR_InventoryMenuUI other;Widget foreignRoot;GridLayoutWidget foreignGrid;
|
|
if(fault==0)ERR_GameMode::current=nullptr;
|
|
if(fault==1)f.mode.active=false;
|
|
if(fault==2)game.world=2;
|
|
if(fault==3)SCR_InventoryMenuUI::current=&other;
|
|
if(fault==4)f.handler.m_MenuHandler=&other;
|
|
if(fault==5)f.child.name="Different";
|
|
if(fault==6)f.menu.root=&foreignRoot;
|
|
if(fault==7){foreignGrid.name="OtherGrid";foreignGrid.AddChild(&f.child);}
|
|
f.attach();assert(game.workspace.creates==0&&!f.menu.m_ERRStorageLayoutBound&&f.handler.invalidLayoutCalls==2);
|
|
}
|
|
{Fixture f;Widget named;named.name="ERR_InventoryStorageLayout";f.grid.AddChild(&named);f.attach();assert(game.workspace.creates==0&&f.child.parent==&f.grid&&!named.removed);}
|
|
for(int fault=0;fault<3;fault++){Fixture f;game.workspace.fail=fault==0;game.workspace.wrongType=fault==1;game.workspace.refuseAdd=fault==2;f.attach();assert(f.child.parent==&f.grid&&!f.menu.m_ERRStorageLayoutHost&&!f.menu.m_ERRStorageLayoutBound&&f.handler.invalidLayoutCalls==2);assert(f.child.row==2&&f.child.col==3&&f.child.l==1);if(game.workspace.last)assert(game.workspace.last->removed);}
|
|
{Fixture f;f.attach();auto host=f.menu.m_ERRStorageLayoutHost;f.child.RemoveFromHierarchy();Widget foreign;host->AddChild(&foreign);Widget next;next.name="Frame0";f.grid.AddChild(&next);assert(!f.menu.ERR_PrepareStorageLayout(&next));assert(next.parent==&f.grid&&foreign.parent==host&&game.workspace.creates==1);}
|
|
{Fixture f;f.attach();auto host=f.menu.m_ERRStorageLayoutHost;f.child.RemoveFromHierarchy();host->row=7;host->l=9;host->refuseAdd=true;Widget next;next.name="Frame0";f.grid.AddChild(&next);next.row=6;next.l=8;assert(!f.menu.ERR_PrepareStorageLayout(&next));assert(next.parent==&f.grid&&next.row==6&&next.l==8&&host->row==7&&host->l==9&&game.workspace.creates==1);}
|
|
{Fixture f;f.attach();f.child.RemoveFromHierarchy();Widget replacementRoot;replacementRoot.AddChild(&f.grid);f.menu.root=&replacementRoot;Widget next;next.name="Frame0";f.grid.AddChild(&next);assert(!f.menu.ERR_PrepareStorageLayout(&next));assert(game.workspace.creates==1&&next.parent==&f.grid);}
|
|
{Fixture f;f.attach();auto host=f.menu.m_ERRStorageLayoutHost;f.child.RemoveFromHierarchy();host->RemoveFromHierarchy();f.menu.m_ERRStorageLayoutHost=nullptr;Widget next;next.name="Frame0";f.grid.AddChild(&next);assert(!f.menu.ERR_PrepareStorageLayout(&next));assert(game.workspace.creates==1);}
|
|
{ERR_InventoryGridPlacement p;Widget child;assert(!p.Capture(&child)&&!p.Apply(&child));}
|
|
}
|
|
''')
|
|
s=P.read_text();handler=body(P,'override void HandlerAttached(')
|
|
assert handler.count('super.HandlerAttached(w)')==1
|
|
assert 'return' not in handler
|
|
for forbidden in ('Init(', 'RefreshList(', 'SetFillWeight(', 'SetSizeMode(', 'CallLater(', 'RemoveHandler(', 'CreateWidgets(', 'OpenMenu('):assert forbidden not in s,forbidden
|
|
assert 'class SCR_InventoryStorageBaseUI' not in s
|
|
print('PASS: actual inventory adapter scope, grid placement, sole compatible host, refresh reuse, rollback, foreign hierarchy refusal and exactly-once native delegation; native compatibility pending')
|