# Orbit

## [202](https://github.com/MoONSHO7/Orbit/tree/202) (2026-03-02)
[Full Changelog](https://github.com/MoONSHO7/Orbit/compare/201...202) [Previous Releases](https://github.com/MoONSHO7/Orbit/releases)

- Ddd (#39)  
    * DDD Sprint 1: Extract Color System from WidgetLogic  
    - Created Core/Color/ReactionColorResolver.lua (reaction color classification)  
    - Created Core/Color/ClassColorResolver.lua (class/unit color with preview fallbacks)  
    - Created Core/Color/ColorCurveEngine.lua (curve sampling, interpolation, native conversion)  
    - Converted WidgetLogic.lua to facade for all color methods (925->723 LOC)  
    - Updated Orbit.toc load order (Color files before WidgetLogic)  
    - Zero consumer API changes: all WL:Method() signatures preserved  
    * DDD Sprint 2: Decompose Icons.lua into focused skinning modules  
    - Created Core/Skins/IconLayout.lua (grid layout math + geometry calculation)  
    - Created Core/Skins/IconMonitor.lua (ticker-based icon count monitoring)  
    - Created Core/Skins/ActionButtonSkinning.lua (action bar button skinning/stripping)  
    - Rewrote Icons.lua as facade + core skinning (959->215 LOC)  
    - Updated Skins.xml load order  
    - Zero consumer API changes: all Orbit.Skin.Icons:Method() preserved  
    * DDD Sprint 3: Extract SchemaBuilder from WidgetLogic  
    - Created Core/Engine/SchemaBuilder.lua (18 Add*Settings methods, 12 onChange factories, 2 tab helpers)  
    - Defined previously-missing ApplyAndSync helper (was undefined in original code)  
    - Reduced WidgetLogic.lua to pure 45-line facade (925->45 LOC, -95%)  
    - Updated Orbit.toc load order  
    - Zero consumer API changes: all WL:Method() signatures preserved  
    * DDD Sprint 4: Decompose AuraMixin into focused modules  
    - Created Core/Mixins/AuraLayout.lua (grid, linear, smart layout + positioning)  
    - Created Core/Mixins/PandemicGlow.lua (glow application, OnUpdate controller, cleanup)  
    - Created Core/Mixins/AuraPreview.lua (edit-mode preview icon + private aura rendering)  
    - Rewrote AuraMixin.lua as facade + core icon setup (696->200 LOC)  
    - Updated Mixins.xml load order  
    - Zero consumer API changes: all Mixin:Method() calls preserved  
    * DDD Sprint 5A: Move Shared Kernel + Infrastructure files  
    - Created Core/Shared/ (Constants.lua, Media.lua)  
    - Created Core/Infrastructure/ (EventBus, Async, Pixel, TickMixin, KeybindSystem, CombatManager, Animation)  
    - Removed Services.xml (inlined into .toc)  
    - Removed CombatManager from Managers.xml  
    - All .toc/.xml paths validated  
    * DDD Sprint 5B: Move Plugin Framework files  
    - Created Core/Plugin/ (Registry, PluginMixin, NativeBarMixin, OOCFadeMixin, DefaultProfile, ProfileManager)  
    - Updated .toc with Plugin section  
    - Removed plugin entries from Mixins.xml and Managers.xml  
    - All paths validated  
    * DDD Sprint 5C: Move Config UI files  
    - Created Core/Config/ (ConfigLayout, SchemaBuilder, ConfigRenderer, Widgets/, OrbitSettingsDialog, OrbitOptionsPanel, OrbitOptionsButton)  
    - Updated .toc with Config UI section  
    - All paths validated  
    * DDD Sprint 5D: Move Canvas + UnitDisplay + Skinning + CanvasUI  
    - Created Core/Canvas/ (NativeFrame, EditMode, PositionManager, MountedVisibility, Frame/, Handle/, Preview/)  
    - Created Core/UnitDisplay/ (UnitButton/, UnitFrameMixin, CastBarMixin, AuraMixin, AuraLayout, PandemicGlow, AuraPreview, StatusIconMixin, AggroIndicatorMixin, ResourceBarMixin, UnitDisplay.xml)  
    - Created Core/Skinning/ (all Skins/ files + VisualsExtendedMixin)  
    - Created Core/CanvasUI/ (all CanvasMode UI files + ComponentSettings)  
    - Complete .toc rewrite with DDD-aligned paths  
    - Removed old Mixins.xml, Managers.xml (directories now empty)  
    - All .toc/.xml paths validated  
    * DDD Sprint 5E: Cleanup stale files and empty directories  
    - Removed Managers.xml, Mixins.xml (no longer referenced)  
    - Moved UnitButton.lua from Engine/ to UnitDisplay/ (fixes XML relative path)  
    - Engine/ reduced to Engine.lua + WidgetLogic.lua facade only  
    - All .toc/.xml paths validated  
    * DDD Sprint 6: BossFrame CastBar extraction  
    - Created BossFrameCastBar.lua (~170 LOC) extracting cast bar creation, hooks, positioning, color resolution  
    - Rewrote BossFrame.lua to delegate cast bar logic via Orbit.BossFrameCastBar  
    - Updated Orbit\_BossFrames.toc load order  
    - BossFrame.lua reduced from 989 to ~280 LOC of unique logic  
    * DDD Sprint 7: ActionBars decomposition  
    - Created ActionBarsText.lua (~110 LOC) - text component positioning  
    - Created ActionBarsContainer.lua (~120 LOC) - container factory + vehicle exit + button reparenting  
    - Created ActionBarsPreview.lua (~85 LOC) - canvas mode preview creation  
    - Rewrote ActionBars.lua as orchestrator with facade delegates  
    - Updated Orbit\_ActionBars.toc load order  
    * DDD Sprint 8: Dialog decomposition  
    - Created DialogActions.lua extracting Apply, Cancel, ResetPositions (~330 LOC)  
    - Dialog.lua reduced from 996 to ~660 LOC  
    - Updated CanvasMode.xml load order  
    * DDD Sprint 9: Remove all facades, migrate plugins to direct modules  
    - Deleted WidgetLogic.lua facade (45 LOC)  
    - Migrated 40+ files from OrbitEngine.WidgetLogic to direct modules:  
      - Color methods -> OrbitEngine.ColorCurve  
      - Schema methods -> OrbitEngine.SchemaBuilder  
      - Reaction colors -> OrbitEngine.ReactionColor  
    - Migrated Icons.lua facade delegates:  
      - ApplyActionButtonCustom -> Orbit.Skin.ActionButtonSkin:Apply  
      - ApplyManualLayout -> Orbit.Skin.IconLayout:ApplyManualLayout  
    - Migrated AuraMixin.lua facade delegates:  
      - LayoutAurasGrid -> Orbit.AuraLayout:LayoutGrid  
      - ShowPreviewAuraIcons -> Orbit.AuraPreview:ShowIcons  
      - ApplyPandemicGlow -> Orbit.PandemicGlow:Apply  
    - Stripped facade delegate methods from Icons.lua and AuraMixin.lua  
    - Updated Engine.lua type annotations  
    - Removed WidgetLogic.lua from Orbit.toc  
    * Audit fixes: delete stale dirs, fix UnitFrameMixin divider format  
    - Deleted empty Skins/ and UI/CanvasMode/ directories (remnants of DDD migration)  
    - Fixed 12 short dividers in UnitFrameMixin.lua to include trailing dashes  
    * DDD Sprint 10: Extract settings + tooltip parsing, add shared SB:MakePluginOnChange  
    - NEW: PartyFrameSettings.lua (60 LOC) - extracted from PartyFrame.lua (-144 LOC)  
    - NEW: RaidFrameSettings.lua (55 LOC) - extracted from RaidFrame.lua (-143 LOC)  
    - NEW: TrackedTooltipParser.lua (92 LOC) - extracted from TrackedAbilities.lua (-102 LOC)  
    - Added SB:MakePluginOnChange to SchemaBuilder.lua for shared plugin settings pattern  
    - Updated 3 TOC files for correct load order  
    - Net reduction: ~139 LOC from god-files, 0 duplicated makeOnChange helpers  
    * fix: remove DDD violations - facades, core-plugin coupling, defensive nil-guards  
    - Remove ComponentEdit facade alias, rename all refs to CanvasMode (11 files)  
    - Decouple UnitFrameMixin from Orbit\_PlayerFrame (configurable inheritPlugin)  
    - Decouple ProfileManager from Orbit\_CooldownViewer (refreshPriority flag)  
    - Decouple API.lua from Cooldown Manager name (capability check)  
    - Strip all defensive nil-guards for OOCFadeMixin (guaranteed by TOC load order)  
    - Strip all defensive nil-guards for MountedVisibility (guaranteed by TOC load order)  
    - Fix dead-code double-return in ActionBars/Container GetVisibilityDriver  
    - Fix closure indentation bugs in PlayerFrame, PlayerPower, PlayerPetFrame  
    * fix: strip defensive nil-chains for TOC-guaranteed modules  
    - Remove all OrbitEngine.X and OrbitEngine.X: inline nil-chains  
    - Remove all Orbit.Engine.X and Orbit.Engine.X: inline nil-chains  
    - Unwrap all if OrbitEngine.X then multi-line guard blocks  
    - Modules guaranteed by TOC load order: Pixel, EditMode, CanvasMode,  
      ComponentDrag, FrameSelection, FrameAnchor, SmartGuides,  
      SelectionTooltip, CanvasComponentSettings, systems (Registry)  
    - 37+ files modified across Core and Plugins  
    * fix: DRY borderSize fallback + extract magic numbers  
    P2: Add Pixel:DefaultBorderSize(scale) to eliminate 22 duplicated  
    patterns across 20 files  
    P3: Extract magic numbers to file-top constants:  
    - RaidFrame: STATUS\_ICON\_SIZE, ROLE\_ICON\_SIZE  
    - BossFrameCastBar: CAST\_BAR\_WIDTH, CAST\_BAR\_HEIGHT, CAST\_BAR\_ICON\_SIZE  
    * refactor: decompose PlayerResources.lua by resource bar type  
    Extract rendering logic into two focused modules:  
    - ContinuousBarRenderer.lua: handles Stagger, Soul Fragments, Ebon  
      Might, Mana, Maelstrom Weapon (status bar + tick marks)  
    - DiscreteBarRenderer.lua: handles Combo Points, Runes, Essence, Chi,  
      Arcane Charges, Holy Power, Soul Shards (button grid + charged overlays)  
    PlayerResources.lua reduced from 1229 to 650 LOC. It retains plugin  
    registration, lifecycle, settings application, spacer positioning, and  
    delegates all rendering to the appropriate renderer module.  
    TOC updated to load renderers before PlayerResources.lua.  
    * fix: strip 9 remaining TOC-guaranteed nil-guards  
    Remove defensive guards for modules guaranteed by TOC load order:  
    - EventBus (7 sites): Pixel, PluginMixin, UnitButtonCore,  
      PlayerResources, CombatTimer, KeybindSystem, ProfileManager  
    - CombatManager (1 site): OOCFadeMixin  
    - Animation (1 site): OOCFadeMixin  
    Legitimate guards retained: DispelIndicatorMixin (optional),  
    SettingsDialog/OptionsPanel (forward refs), Profile in Init (timing)  
    * refactor: decompose TrackedCharges.lua by responsibility  
    Extract layout/skinning and canvas preview into dedicated modules:  
    - ChargeBarLayout.lua (~160 LOC): button building, layout sizing,  
      button skinning, text positioning, tick marks  
    - ChargeBarCanvasPreview.lua (~115 LOC): canvas mode preview closure  
    TrackedCharges.lua reduced from 1019 to 752 LOC. Retains lifecycle,  
    frame creation, spawn/despawn, drag-drop, update logic, seed  
    visibility, cursor/recharge watchers.  
    TOC updated to load new modules before TrackedCharges.lua.  
    * Rename component drag files, fix aura height compensation bug  
    - Rename ComponentDrag.lua -> ComponentRegistry.lua (reflects true purpose: component registration and position restoration)  
    - Rename DragComponent.lua -> CanvasModeDrag.lua (clarifies this is Canvas Mode's drag handler)  
    - Update Frame.xml and CanvasMode.xml load entries  
    - Fix OrbitOptionsPanel.lua Core->Plugin violation (Orbit\_Portal -> EventBus)  
    - Fix aura container height compensation bug in PositionUtils.lua: guard on justifyH ~= CENTER to prevent compHalfH pixel error when selfAnchor is CENTER-based  
    * DDD refactoring: extract shared group frame modules, decompose TrackedAbilities/TrackedCharges, refine component positioning  
    * feat: aura clickthrough, HealerAuraRegistry, raid buff container, pandemic glow fix, resource auras, action bar flash fix, addons menu organization, remove legacy player options, healthstone cooldown fix, cast bar & frame texture fixes  
    * refactor: architecture overhaul + live toggle system + group frame improvements  
    # Architecture  
    - Rename Canvas/ -> EditMode/ for Blizzard edit mode integration  
    - Rename CanvasUI/ -> CanvasMode/ for intra-frame component editor  
    - Flatten component files into CanvasMode/ (ComponentEdit, ComponentHandle,  
      ComponentHelpers, ComponentRegistry, SmartGuides, OverrideUtils)  
    - Rename Frame.lua -> EditFrame.lua, update XML bundle references  
    - Decouple EditFrame from CanvasMode: use late-bound Engine.CanvasMode  
      lookups instead of cached module reference  
    - Add new readme.md for EditMode/ and CanvasMode/ directories  
    - Update Orbit.toc load order for new directory structure  
    - Update Core/readme.md dependency graph  
    # New: CONTRIBUTE.md  
    - Comprehensive contributor guide: project overview, three-system data flow,  
      architecture diagrams, directory structure, code standards, plugin lifecycle,  
      common patterns, preview parity rules, submission checklist  
    # New: What's New Window (WhatsNew.lua)  
    - Changelog popup shown once per account after each update  
    - Scrollable entries, Discord invite dialog, ESC/combat hide  
    - Auto-show on PLAYER\_LOGIN (skips if version already read)  
    - /orbit whatsnew slash command added to OrbitOptionsPanel  
    # Live Toggle Plugin System  
    - Core/Init.lua: liveToggle flag, \_initialized tracking, IsLiveToggle(),  
      LiveTogglePlugin() (enable/disable without reload), RegisterBlizzardHider()  
    - Core/Init.lua: IsBlizzardHidden/SetBlizzardHidden for tri-state support  
    - Core/Init.lua: Apply blizzard hiders on PLAYER\_LOGIN  
    - PluginMixin: OnCanvasApply() single entry point for canvas mode apply  
    - ProfileManager: HideBlizzardFrames persisted per-profile, diffed on switch,  
      live-toggle clean plugins, reload prompt for dirty ones, copy/flush support  
    - PluginManager: Tri-state checkbox UI (off/on/hide-blizzard), live-toggle  
      detection, tooltip descriptions, skip reload for clean toggles  
    - 12 plugins marked liveToggle=true: CombatTimer, Performance, PlayerPower,  
      PlayerResources, TargetPower, TargetBuffs, TargetDebuffs, TargetCastBar,  
      FocusPower, FocusBuffs, FocusDebuffs, FocusCastBar  
    - Blizzard hiders registered: FocusFrame, MenuBar, BagBar  
    # ComponentSettings Refactoring  
    - Compose() helper builds schemas from reusable control presets  
    - STATIC\_TEXT, DYNAMIC\_TEXT, TEXT\_NO\_COLOR, AURA\_GRID, PANDEMIC\_GLOW presets  
    - Per-control plugin = true flag replaces pluginSettings/pluginSettingKeys  
    - Unified override loading: saved -> existing -> plugin -> pending  
    - GetControlDef() lookup, ApplyPluginPreview() dispatches by component type  
    - IconFrame uses IconSize slider instead of Scale  
    # Canvas Mode Improvements  
    - OverrideUtils: ApplyIconSizeOverride() for pixel-snapped icon resizing  
    - IconFrameCreator: load saved IconSize from overrides on creation  
    - AuraCreator: use shared AuraSpacing constant, apply SkinBorder on icons  
    - ComponentSettings.ApplyStyle: separate IconSize handler with border re-skin  
    - Dialog: remove SaveOriginalPositions (cancel no longer deep-copies)  
    - DialogActions: Apply calls OnCanvasApply(), Cancel simplified  
    # Group Frame Unification (Party + Raid)  
    - ApplyFrameStyle(): shared styling for live and preview frames (size, border,  
      texture, text, component positions, icon positions, overrides)  
    - GroupCanvasRegistration: PrepareIcons() and ShowCanvasModeIcons() extract  
      duplicated party/raid canvas mode logic into shared methods  
    - AuraPreview.ShowFrameAuras() reduces boilerplate in preview aura rendering  
    - Both plugins: ApplySettings delegates to ApplyFrameStyle + live-only updates  
    # Healer Aura System  
    - HealerAuraRegistry: add Mark of the Wild, rebuild on PLAYER\_SPECIALIZATION\_CHANGED  
    - HealerAuraRegistry: AllRaidBuffIds lookup, safe specIndex guard  
    - Filter healer auras with HELPFUL|PLAYER (only player-applied buffs)  
    - Guard UpdateSpellAuraIcon/UpdateMissingRaidBuffs against preview/canvas mode  
    - Hide missing raid buff indicator when target is dead (UnitIsDeadOrGhost)  
    - Missing raid buff alpha tied to UnitInRange  
    - Stale raid buff container detection (replace if missing \_raidIcons)  
    - Expose container.Icon for canvas mode detection  
    - GetComponentIconSize() reads IconSize override for healer aura sizing  
    - Continuous color curve sampling via HealerCurveOnUpdate (swipe + timer text)  
    - Dynamic remainingPercent passed to BuildSkinSettings for swipe color curves  
    # Aura System Fixes  
    - AuraMixin: reorder skin application before cooldown to fix swipe color  
    - AuraMixin: apply swipeColor from skinSettings  
    - AuraMixin: EnableMouse(false) on Cooldown and Overlay frames  
    - AuraMixin: invalidate Skin.Icons.regionCache before re-skinning  
    - AuraMixin: SetPassThroughButtons instead of SetMouseClickEnabled (fixes tooltip interaction)  
    - AuraMixin: use SetUnitBuffByAuraInstanceID/SetUnitDebuffByAuraInstanceID  
      for correct tooltip display (replaces deprecated SetUnitAura)  
    - AuraMixin: EnsureAuraButton renamed to EnsureAuraIcon  
    - Shared aura skin constants (Constants.Aura.SkinWithTimer/SkinNoTimer)  
    - AuraLayout: use shared AuraSpacing constant  
    - PrivateAuraMixin: disable countdown frame/numbers, always recreate anchors  
    - PrivateAuraAnchor changed from Button to Frame  
    # Cooldown Manager  
    - TrackedUpdater: prefer item cooldown for trinkets/items, fall back to spell CD  
    - TrackedUpdater: handle active-phase detection for item cooldowns  
    - TrackedUpdater: match item spell casts in RegisterSpellCastWatcher  
    - CooldownLayout: color curves run every frame (no OOC throttle for curves)  
    # Unit Frame Fixes  
    - VisualsExtendedMixin: accept overrideLevel for PLAYER\_LEVEL\_UP event  
    - TargetFrame, FocusFrame: register PLAYER\_LEVEL\_UP, pass new level  
    - PlayerFrame: pass newLevel arg from PLAYER\_LEVEL\_UP  
    - GroupFrameMixin.UpdateInRange: handle missing unit (set alpha 0)  
    - BossFrame/BossFramePreview: use StatusIconMixin:ApplyMarkerSprite  
    - ConfigRenderer: footer width from frame:GetWidth() instead of constant  
    - MountedVisibility: skip hide when canvas mode is active  
    # Constants  
    - GroupFrames.AuraSpacing = 1  
    - Aura.SkinWithTimer and Aura.SkinNoTimer shared skin tables  
    # Misc  
    - StatusIconMixin: ApplyMarkerSprite() extracted for reuse  
    - tmp\_old\_target\_debuffs.lua: backup of old standalone target debuffs plugin  
    * Small Edits  
    * CDM perf, powerbar height, talking head tri-state, PAA cleanup  
    Cooldown Manager:  
    - Restrict color curve polling to BuffIcon-only (remove Essential/Utility)  
    - Remove unused GetDurationObject; ApplyTimerColor uses aura duration directly  
    - Simplify OnUpdate: BuffIcon curve runs every frame, other systems desat-only  
    - Remove OOC color throttle (no longer needed with BuffIcon-only scope)  
    - Enforce singleColorMode on Timer canvas for non-BuffIcon systems  
    - Fix curve threshold: allow single-pin curves (#pins == 0 means no curve)  
    Party/Raid Frames:  
    - Add PowerBarHeight slider (5-30%) to Party and Raid settings  
    - Thread powerBarRatio through Helpers:UpdateFrameLayout  
    Talking Head:  
    - Add tri-state checkbox (enable orbit / disable orbit / disable both)  
    - Register Blizzard hider for Talking Head frame  
    PAA Preview:  
    - Hide private aura preview icons on HidePreview (Party + Raid)  
    - Remove unconditional PrivateAuraAnchor:Show() from GroupCanvasRegistration  
    - Fix canvas mode detection: check container before iterating frames  
    Default Profile:  
    - Add HealerAura1-7 and RaidBuff to Party/Raid default component lists  
    Docs:  
    - Fix dependency graph direction in CONTRIBUTE.md and Core/readme.md  
    - Expand EditMode, UnitDisplay, and UnitFrames readmes with file details  
    Cleanup:  
    - Delete tmp\_old\_target\_debuffs.lua  
    - Remove TrackedUpdater:ApplyTimerTextColor (dead code)  
    * Whats New Update  