Choose a rendering system by the surface you need to control, then give the view one owner for creation, input, refresh, and destruction.

Choose the smallest suitable UI system

Requirement Recommended approach
Decorate an existing modern HTML-based screen Inject an owned child view and scoped CSS or JavaScript.
Independent floating modern panel Create a panel-sized Gameface view inside a window owned by the current context.
Simple native HUD text, markers, or drag handles Use the classic GUI layer with resetters and explicit input ownership.
Modify a specific legacy control Integrate with that view system instead of covering it with an unrelated overlay.

Shared ownership rules

  • Create the surface only in its applicable account, battle, mode, and view context.
  • Keep one refresh loop and one drag loop per overlay.
  • Bind input only while interaction is needed.
  • Clamp restored positions after resolution or scale changes.
  • Destroy the view, resetters, callbacks, observers, and handlers during context exit.

Centralize visibility decisions

A lobby overlay can exist while it should not be visible. Compute visibility from every relevant state in one side-effect-free function.

def visibility_reason():
    if not settings.enabled:
        return 'disabled'
    if not lifecycle_active:
        return 'inactive_context'
    if current_vehicle() is None:
        return 'no_vehicle'
    if preview_vehicle() is not None:
        return 'preview_active'
    if not route_is_allowed():
        return 'blocked_route'
    if incompatible_window_is_open():
        return 'blocked_window'
    return None

def refresh_visibility():
    reason = visibility_reason()
    view.setVisible(reason is None)
    diagnostics.set_block_reason(reason)

Input and dragging

  • Use stable screen or engine cursor coordinates while moving a native window.
  • A moving window changes window-local mouse coordinates, which can cause drag feedback and jitter.
  • Save position after drag completion rather than on every frame.
  • Recover from lost mouse-up by also checking current button state during the drag callback.

Continue by surface

Gameface Modding

Resource maps, native-view injection, standalone Wulf panels, model bridges, DOM readiness, sizing, scaling, input, and diagnostics.

Identify the active UI owner

Use source location as a first clue: controllers under gui/Scaleform usually feed classic Flash surfaces, while controllers under gui/impl usually belong to Wulf or Gameface. A legacy battle alias may survive after the active implementation migrated, so trace the current controller and consumer before selecting a technology.

See Tooling, Assets & Packaging for a practical ownership checklist.