BroadcastPlanSlider.cs

A Sandbox UI slider panel for the match broadcast plan. Drags or clicks set team tempo or mentality in tenths, draws ten step markers and a thumb, and commits the value on release.

using System;
using Sandbox;
using Sandbox.UI;
using Socer;

public sealed class BroadcastPlanSlider : Panel
{
    public MatchController Game {get;set;}
    public bool Tempo {get;set;}
    readonly Panel[] steps=new Panel[10];
    readonly Panel thumb;
    bool dragging;
    MatchSimulation gestureMatch;
    void HoldOpen(bool on)
    {
        for(var panel=Parent;panel!=null;panel=panel.Parent)
            if(panel.HasClass("match-console")){panel.SetClass("adjusting",on);break;}
    }
    public BroadcastPlanSlider()
    {
        AddClass("plan-slider");
        var track=Add.Panel("plan-slider-track");
        for(int i=0;i<10;i++)steps[i]=track.Add.Panel("plan-slider-step");
        thumb=Add.Panel("plan-slider-thumb");
    }
    public float Value=>Game==null?.5f:Tempo?Game.Match.TeamTempo[0]:Game.Match.TeamMentality[0];
    public void SetFraction(float value,bool commit=false)
    {
        if(Game==null)return;
        value=MathF.Round(Math.Clamp(value,0,1)*10)/10;
        Game.SetBroadcastPlan(Tempo?value:Game.Match.TeamTempo[0],Tempo?Game.Match.TeamMentality[0]:value,commit);
    }
    void Pick()=>SetFraction(MousePosition.x/Math.Max(1,Box.Rect.Width));
    protected override void OnMouseDown(MousePanelEvent e)
    {
        base.OnMouseDown(e);
        if(e.MouseButton!=MouseButtons.Left || Game==null)return;
        gestureMatch=Game.Match;dragging=true;HoldOpen(true);
        // Pressed panels already receive release. OS capture locks the cursor
        // and makes a regular slider jump back to its starting point.
        if(HasMouseCapture)SetMouseCapture(false);
        Pick();
    }
    protected override void OnMouseUp(MousePanelEvent e)
    {
        base.OnMouseUp(e);
        if(e.MouseButton!=MouseButtons.Left || !dragging)return;
        if(gestureMatch==Game?.Match){Pick();SetFraction(Value,true);}
        dragging=false;HoldOpen(false);
        if(HasMouseCapture)SetMouseCapture(false);
    }
    public override void Tick()
    {
        base.Tick();
        if(Game==null)return;
        if(dragging && gestureMatch!=Game.Match){dragging=false;HoldOpen(false);}
        if(dragging)Pick();
        for(int i=0;i<10;i++)steps[i].SetClass("filled",i<Value*10);
        thumb.Style.Left=Length.Percent(Value*100);
    }
    public override void OnDeleted()
    {
        if(dragging && gestureMatch==Game?.Match)SetFraction(Value,true);
        HoldOpen(false);
        if(HasMouseCapture)SetMouseCapture(false);
        base.OnDeleted();
    }
}