Repair every bundle that renders pink on macOS: overlays, deployment zones, silhouettes, ID tokens and the miniatures - #16
Open
ironsquadronfr-hub wants to merge 17 commits into
Conversation
…nothing renders pink on macOS The three link tables the mod spawns its projector tools from still named the original bundles, which ship no Metal variant: on macOS the shader is missing at load and the tool renders solid pink. Every URL here now names the bi-platform rebuild of the same bundle -- same prefabs, same geometry, same shader source, recompiled for both graphics APIs. Windows reads the same variant it always did. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dles too
Same defect as the previous commit, reached by a different route. These
bundles are not spawned through the overlay module, so the substitution
table cannot see them: the URLs are written straight into the mod's own
controllers and object JSON. Swapped in place instead.
Twenty-three bundles, all confirmed shipping only [4, 15] -- Direct3D 9 and
11, no Metal -- and all replaced by a rebuild that is byte for byte the one
validated in game:
* 8 deployment zones and the 3x3 masking projector
(BucketheadBits/Projector/Deployment, SETUP_CONTROLLER and
GAME_CONTROLLER). These paint at the start of every single game, so
they are the most visible of the lot.
* 3 silhouettes (BucketheadBits/Silhouette), the SIL button on
Unit_Leader, POI_Token and BombCarts.
* 10 unit ID tokens (BucketheadBits/Tokens/Lambert Channel Mask).
* the shelf hologram (BucketheadBits/Logo/Fast Hologram).
31 URL occurrences across 16 files, nothing else touched. These are plain
URL swaps rather than a lookup table because the mod writes them inline;
repointing them at Steam later is the same one-line-per-entry edit.
… on macOS The last group, and the one that matters most: the unit models themselves. 82 bundles, referenced from contrib/cards/**/minis[].bundle and official.json. They were checked rather than assumed. Every one of the 82 was downloaded from its published URL and its shaders read out of the typetree: 82 out of 82 ship platforms [4, 15] only, Direct3D 9 and 11, no Metal. 66 carry BucketheadBits/Units/Color Replacer, the rest add Glow Geometry and Rim Glow Geometry Shield, and three carry Particles/Standard Unlit -- a stock Unity name, but baked into the bundle without a Metal variant like the others, so it breaks the same way. None of them is a Custom Model with a stock TTS material; those carry no shader at all and are unaffected. 265 URL occurrences across 11 files. Each replacement is byte for byte the bundle validated in the local TTS cache. The 61 MB of rebuilds are hosted on the fork rather than committed here, so this commit stays a text diff you can actually read. They are all under mod/data/isq-metal-rebuilds on the isq-qol branch. With this, no bundle without a Metal variant is referenced anywhere in the repository any more.
Its spawn entry in official.json carries a diffuse that is 404 on every Steam CDN, while the mesh next to it is fine. A Custom Model whose texture fails to load renders pink, which is very likely part of what your Mac tester reported alongside the shader problem -- and this half would show on Windows too, on any cold cache. The replacement is not invented: it is the diffuse the mod's own Graffiti Token object already uses, same mesh, 42 KB of JPEG that answers today. Both copies of official.json carried the dead one.
Correcting the previous commit, which was aimed at the wrong token. Fourteen entries in official.json share one disc mesh -- Bane, Complete the Mission, Condition, Graffiti, Incognito, Objective, Operative, Proton Charge, Shield, Smoke, Victory, Wheel Mode -- and I read the dead diffuse as belonging to the graffiti token because it sat next to that mesh. It is the operative token's, and the previous commit would have made operative markers show graffiti art. The right texture was in the mod already: Operative_Marker_Tokens.125746.json carries the same mesh with a diffuse that answers, 162 KB of JPEG. Both copies of official.json now use it, and the graffiti token keeps its own.
…g notched bases On every base with notches the template's collider overlapped the base at spawn; the template is locked, so the physics engine pushed the miniature back instead, up to 0.73 mm on epic bases. The retuned bundle moves the collider's tip from -35.62 to -33.50 mm, leaving 1.3 to 2.1 mm of clearance on every base. The visual mesh is untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The published materials render speeds 1 and 2 nearly identical (white and a 0.745 grey). The retuned shared bundles paint them white, dark grey and red, so the chosen speed reads at a glance. Purely cosmetic: the published bundles with only the material color changed. Drop this commit if you prefer the original look. The colorTint fields next to the bundle links are decorative -- the tint never reaches these bundles' materials -- so they are aligned with the baked colors and commented as such, and the duplicated speed 1 sharedBundle line is dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Toggling the overlays walks the table and called clearRangeRulersOriginal and clearCohesionRulerOriginal on objects holding a ruler -- names no object script defines: every toggle threw a Lua error on each such token (reported on the token, so the caller's pcall never surfaced it) and the vanilla ruler was left on the table. The cleanup now calls the functions that exist -- clearRangeRulers, which every ruler-holding family gets from !/RangeRulers, and the models' clearCohesionRuler -- and resets the ruler button flags the wipe leaves stale in either direction (rangeOn on tokens, isqRangeOn on bomb carts, rulerOn on order tokens), plus the hover hotkey's toggle identity in the Global scope, so the next press always starts fresh. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing calls it -- the order token's cohesion button does its own deterministic toggle with rulerOn, which is what this function was written for -- and its body still calls clearCohesionRulerOriginal and spawnCohesionRulerOriginal by name on the fig, names no fig script defines: whoever wired it up later would inherit the silent-pcall bug the overlay-toggle fix just removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The table-wide overlay mode lived only in a Lua global: every load -- and every Ctrl+Z, which replays Global's startup with the snapshot's state -- silently flipped the table back to the mod's original overlays. The mode now rides in the save blob next to the chess clock and welcome dialog states, and load imposes it rather than toggling, the same rule that fixed those two. Saves from before the key keep today's default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gCohesionTrigger was their only consumer and is gone; the range pair stays, macModeToggle and the hover path still route through it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Order Token wires the two spawned templates to each other and to the unit through setVar/setTable -- volatile script state that no save ever carries. After a save, a load or an undo (which reloads the whole mod), the copies still stand on the table but templateA/templateB/basePos are nil: picking one up spams turnToCursor/positionTemplate errors and every physics contact spams onCollisionStay. A fresh spawn is wired within its first frame, a reloaded copy never is, so each copy now waits a second after load and removes itself if the wiring never came. Upstream bug, every platform, unrelated to the overlay module. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An assigned order token copies the selected unit's unitData into its script globals for its own movement math, so the overlay hover hotkeys took it for a unit and drew range bands or a cohesion ruler around the token itself. Gate hovered objects on what they are instead: range draws for unit figures (leaders carry miniGUIDs, minis carry leaderGUID), tokens that declare a rangeKey (POI, objective, condition, Bane, mission, smoke) and bomb carts (script-global baseSize); cohesion draws for unit figures only, which is what vanilla already enforces through its unitData check on every token. The vanilla path is left as it was. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ironsquadronfr-hub
force-pushed
the
isq-metal-rebuilds
branch
from
August 18, 2026 02:20
58baa58 to
8baa23a
Compare
Author
|
Heads-up: rebased on current
Nothing changes in what we are asking: your test on Mac + Windows, then the Steam UGC upload when you are happy. |
With slow or absent connectivity the vanilla XML is not up yet when the toggle button builds itself: getXmlTable returns nothing and pushing the empty result back logged "<UI.setXmlTable>: table was null" in Global. Nothing to edit into means nothing to do -- and the initial build now retries until the XML is there instead of firing once and missing the menu. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same volatility as the movement templates one commit back, other family: the only reference to the vanilla maxMoveTemplate ring (and to our overlay registry's projectors) lives in script state no save carries, so a ring that made it into a save can never be cleared again after a load or an undo. The Global's own load sweep already handles this for rulers -- standbyTokens, last call of onload, destroys "Cohesion Ruler" and "Range Ruler" by name -- but "Maximum Move" was missing from its list. Add it there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From a four-angle cleanup review of the series; no behavior change: - macModeToggle: hoist the flag list out of the per-object loop, drop the pcall around setVar on an object whose getVar was just read bare, and fold the three getVar existence checks under one guard. - IsqBridge: one shared isqVar probe instead of the pcall-around-getVar idiom written out three times; drop a nil-guard the pcalls already cover. - Model Template B: point at Model Template A's zombie-guard comment instead of repeating it verbatim. - IsqOverlays: the ISQ_ASSETS comment claimed a single repoint site, which the in-place URL swaps made false; say what repointing actually takes and why the literals are deliberate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ironsquadronfr-hub
force-pushed
the
isq-metal-rebuilds
branch
from
August 18, 2026 09:17
c453945 to
ed83bc5
Compare
The three SIL comments claimed silhouetteState is saved with the game; it is not -- Unit_Leader and BombCarts already reset it on every load, and silhouettes are attachments TTS never carries into a save, so a load always starts with none up and the state false. Say so, and give the POI token the same explicit reset its two siblings have (it relied on nil being falsy). No behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the pink your Mac tester is seeing. It is not a link issue and it is not his cache.
What it is
Range, Cohesion and Movement all spawn Custom AssetBundles built around the
BucketheadBits/Projectorshaders, and those were compiled without a Metal variant. I pulled the published bundles down from the mod's own URLs just now and read the platform list out of each shader:halfcohesion_27mm[4, 15]projector_bomb_cart[4, 15]projector_tokenrangetwo[4, 15]movement_27mm_speed1[4, 15]projector_27mm[4, 15]projector_27mm_isq_v6(ours, as a control)[4, 14]4is Direct3D 9,15is Direct3D 11,14is Metal. The file downloads fine — it is 8 to 13 KB, it opens, the shader is in there. It was simply never compiled for macOS. Your Windows box reads variant15, which exists; a Mac has nothing to read, so Unity falls back to its error material and paints the projector pink. A Windows player with a completely cold cache would see exactly what you see.What confirms it
His own report is the proof, once you look at what works. Range renders for him, cohesion does not. Our overlay module covers all eight base sizes for range, but only 100/120/150mm and the oblongs for cohesion — 27, 50 and 70mm fall back to the mod's bundles. Everything pink is a mod bundle, everything that renders is one of ours. No exceptions, including the max movement templates and the bomb cart and graffiti buttons he named.
What this does
One defect, three routes to it. 145 bundles now load a repaired, bi-platform rebuild, built from the mod's own prefabs and shader source and recompiled for both graphics APIs. Every replacement is byte for byte what has been validated in game. Windows reads the same variant it always did — that is the half of the test I cannot run, so it is the half worth your attention, and the section on what else changed is where to start.
40 in your own data files — Movement, Range and Cohesion, swapped where they live:
MovementLinks,RangeRulerLinks,CohesionLinks. (An earlier version of this PR routed these through a lookup table in our module; plain URL swaps in your files are easier to read, revertible entry by entry, and behave identically for every player.)23 more written straight into your files — never resolved through the link tables. Swapped in place, 31 occurrences across 16 files:
Projector/DeploymentSETUP_CONTROLLER,GAME_CONTROLLERSilhouetteUnit_Leader,POI_Token,BombCartsTokens/Lambert Channel MaskLogo/Fast HologramShelfThe deployment zones matter most here: they paint at the start of every single game, so on a Mac that is pink before anyone has touched anything.
82 miniatures — the unit models, from
contrib/cards/**/minis[].bundleandofficial.json. 265 URL occurrences across 11 files. 66 carryBucketheadBits/Units/Color Replacer, the rest addGlow GeometryandRim Glow Geometry Shield, and three carryParticles/Standard Unlit— a stock Unity name, but baked into the bundle without a Metal variant like the others, so it breaks identically. None of them is a Custom Model with a stock TTS material; those carry no shader at all and are untouched.Nothing was assumed. Every bundle here was downloaded from its published URL and had its shaders read out of the typetree. The 82 miniatures came back 82 out of 82 on platforms
[4, 15]— Direct3D 9 and 11, no Metal. Same for the other 63. As a control, one of ours came back[4, 14].After this, no bundle without a Metal variant is referenced anywhere in the repository.
Where the files live, and the one thing to weigh
No binary lands in your repo — the whole PR is a text diff. The 63 small bundles sit under
mod/data/isq-overlay-assetsand the 82 miniatures (61 MB) undermod/data/isq-metal-rebuilds, both on the fork'sisq-qolbranch, same placeISQ_ASSETSalready resolves to.That is the honest cost of this PR: the mod pulls these bundles from a personal fork. I think it beats every Mac player seeing pink figures, but it is your call and I will not pretend it is free. Which is what the next section is about.
What else changed, besides the platform
I diffed every one of the 145 against the copy currently published — material properties and projector geometry, not just the shader — so this is measured rather than asserted.
116 of 145 are identical apart from the Metal variant. The other 29 fall into three groups, and only the first is a deliberate change:
18 movement bundles carry a fix for two upstream bugs in the Maximum Move footprint. Both are visible on Windows too, and they are the reason these came from a later build than the rest:
_BaseSizewas left at70on every base above large — the ring radius_ProjectorRadiushad been tuned per size, the base footprint had not, so they were all derived from the 70mm. Now set per base:100,120,150as appropriate. 15 bundles.BB_MovementProjectorplaces the footprint athalfBase / (_ProjectorRadius + halfBase)of the projector's extent, while that extent is_ProjectorRadius(checked:m_OrthographicSize == _ProjectorRadiuson all 24). The drawn radius was therefore always smaller than the base and changed with speed, sinceRchanges. A base footprint that grows when you move faster — reproduced in game. The three 27mm bundles compensate with_ProjectorRadiusnudged by0.087, which is the deployment offset the mod already applies intemplateInfo.deployMod.small.Happy to pull these out into their own PR if you would rather judge them separately — say the word.
One miniature drifted, unintentionally.
ig-100_magnagaurd_mathas_SwapOutlineat0.217where the published copy has0.348. That is a rebuild artefact, not a decision. Flagging it rather than quietly patching a bundle I cannot test; if you want the published value back it is a one-property edit.The remaining differences are properties the published materials never stored at all —
_BaseGap,_ArcCompress/_ArcSpacing, and the eighteenColor Replacerknobs on the threearc_*bundles. In every case the published material has no entry and the rebuilt one declares the shader's value. Rebuilding against the current shader writes out the full property set; nothing was retuned.How thoroughly this was checked
Our own inventory of the broken bundles dates from May, and the mod has moved since — several assets have been re-uploaded under new UGC entries that the inventory never knew about. So the final sweep ignored the inventory entirely and worked from the repository itself: every URL used in a bundle role, found by its field —
AssetbundleURL,minis[].bundle,sharedBundle. 190 unique bundle URLs.sharedBundleentries inStarWarsLegion.lua, the table bundle inTABLE.3a3ed9.jsonand the Infantry Support Platform — all re-uploads that replaced assets our old inventory had flagged.So the claim is not "we fixed the ones we knew about". It is: every bundle this repository loads has been downloaded and had its shaders read, and none of them is missing Metal any more.
No blind spots left, and one more thing found
I had listed
Sabine WrenandBlack Sun Enforcersas unreachable, because our old inventory has bundles for them that appear nowhere in the sources. Looking properly: they no longer use a bundle at all. Both now spawn frommesh+diffuse— plain Custom Models on stock TTS materials, which carry no shader and cannot be hit by this. Their URLs answer. Same story for the Infantry Support Platform. So there is nothing left unaccounted for.While sweeping every
meshanddiffusein the card data — 911 URLs — one dead link turned up in the official set, and it is worth your attention because it is not a shader problem:The operative token has a dead texture. Fourteen tokens share one disc mesh in
official.json— Bane, Complete the Mission, Condition, Graffiti, Incognito, Objective, Operative, Proton Charge, Shield, Smoke, Victory, Wheel Mode — and one of the fourteen, the operative marker, points at a diffuse no Steam CDN serves any more. A Custom Model whose texture fails to load renders pink, and unlike everything else in this PR this one would show on Windows too, on any cold cache.The right texture was already in the mod:
Operative_Marker_Tokens.125746.jsoncarries the same mesh with a diffuse that answers, 162 KB of JPEG. Both copies ofofficial.jsonnow use it.Two other dead-link problems I did not touch, so you know they exist:
templateInfo.templateMeshandtemplateInfo.templateColliderinStarWarsLegion.lua— the three physical movement template models and their colliders — are 404 everywhere, as is the Mud map's diffuse. Cold cache means pink movement templates, Windows included. These need re-uploading; I have nothing to point them at.contrib/cards/homebrew.jsonis largely gone: 368 of its 482 model and texture URLs are 404. That is community content whose uploads have expired, not mod assets, so I left it alone entirely — but if the homebrew spawner is meant to work, most of it currently cannot.What we would like to happen next
This is a workaround, not where it should end up. It serves the repaired bundles from our fork, which is fine for now and not fine forever. The sequence we are hoping for:
MovementLinks,RangeRulerLinksandCohesionLinksat the new URLs.No rush on our side, and no hard feelings if you would rather ship the workaround for a while — the Mac players stop seeing pink either way. But step 2 is the only thing that actually retires the bug for everyone, including anyone who never installs anything.
Separate bug, worth knowing about
While checking every URL in
mod/srcI found seven that are 404 on every Steam CDN, not just the deadcloud-3host:StarWarsLegion.lua:113—templateInfo.templateMesh, the three physical movement template modelsStarWarsLegion.lua:71-73—templateInfo.templateCollider, their three collidersCustom_Maps/Mud/BATTLEFIELD.526772.json:39— the Mud map'sDiffuseURLThose really are gone, and that one is a cache story: anyone with a cold cache gets pink movement templates, Windows included. You only don't see it because yours have been cached for years. Not fixed here — those assets need re-uploading.
Update, 18 Aug — the follow-up commits
The same branch now also carries, each in its own commit:
attempt to index a nil value(turnToCursor,positionTemplate,onCollisionStayspam). They now remove themselves when the wiring is gone. Upstream bug, every platform — to reproduce: start a move, save, reload, touch the template.standbyTokens, last call ofonload— already destroysCohesion RulerandRange Rulerby name;Maximum Movewas missing from its list and now joins it.unitDatain its script globals, so it passed for a unit and range bands or a cohesion ruler got drawn around the token itself. Range hover now draws for unit figures, range-bearing tokens (everything that declares arangeKey) and bomb carts; cohesion hover for unit figures only — which is what the vanilla path already enforces through itsunitDatacheck.isq-qol.The serving strategy also changed since the first push, as described above: the lookup table inside our module is gone, every repaired URL is swapped in place in the file where it lives, and no binary is committed in the PR.