@name 3D Holo Drag N Snap Movement
@inputs 
@outputs [Ent1 Ent2]:entity [Local1 Local2]:vector Paused Divisions Mode
@persist [H O E]:entity Idx Cid:array Distance
@model 

if( dupefinished() ){ reset() }

if( first() )
{
    runOnTick(1)
    runOnChat(1)
    runOnLast(1)
    propSpawnEffect(0)
    
    O = owner()
    E = entity():isWeldedTo() ?: entity()
    
    function number getID( N )
    {
        Idx+=N
        return Idx
    }
    function number clipIt( N:number, [V1 V2]:vector )
    {
        Cid[N,number] = Cid[N,number] + 1
        holoClipEnabled( N, Cid[N,number], 1 )
        holoClip( N, Cid[N,number], V1, V2, 0 )
    }
    #clipIt( getID(0), vec(), vec(0,0,1) )
    
    H = holoCreate( getID(1), E:toWorld(vec(0,0,0)), vec(1) / 12, E:toWorld(ang(0,0,0)), hsv2rgb(0,1,0.5) )
    holoModel( getID(0), "hq_sphere" )
    holoParent( getID(0), E )
    
    holoCreate( getID(1), E:toWorld(vec(0,0,0)), vec(1,1,2) / 12, E:toWorld(ang(0,0,0)), vec(0,255,0) )
    holoModel( getID(0), "hq_cylinder" )
    holoParent( getID(0), E )
    
    holoCreate( getID(1), E:toWorld(vec(0,0,0)), vec(0.75) / 12, E:toWorld(ang(0,0,0)), hsv2rgb(200,1,0.5) )
    holoModel( getID(0), "hq_cylinder" )
    holoParent( getID(0), E )
    
    Divisions = 2
    
    Mode = 1
}

if( !Paused )
{
    Use = O:keyUse()
    Ae = O:aimEntity()
    
    if( Ae )
    {
        local Box = Ae:aabbSize() / Divisions
        local Local = Ae:toLocal( O:aimPos() )
        local Pos = round( Local / Box ) * Box
        
        holoPos( 1, Ae:toWorld(Pos) )
        holoPos( 3, O:aimPos() )
        
        if( Use )
        {
            Ent2 = Ae
            Local2 = Ent2:toLocal(H:pos())
                
            local V1 = Ent1:toWorld(Local1)
            local V2 = Ent2:toWorld(Local2)
            local Dir = V2 - V1
            holoPos( 2, mix( V1, V2, 0.5 ) )
            holoAng( 2, Dir:toAngle() + ang(90,0,0) )
            holoScale( 2, vec(0.5,0.5,Dir:length()) / 12 )
        }
    }
    
    if( changed(Ae) )
    {
        holoAlpha( 1, Ae:isValid() * 255 )
        holoAlpha( 3, Ae:isValid() * 255 )
    }
    
    if( changed(Use) )
    {
        if( Use )
        {
            if( !Ent1 )
            {
                Ent1 = Ae
                Local1 = Ent1:toLocal(H:pos())
                holoAlpha( 2, 255 )
            }
        }
        else
        {
            if( Mode == 1 )
            {
                #local Local = toLocal( Ent1:toLocal(Local1), ang(), Ent2:toWorld(Local2), Ent1:angles() )
                local Local = toLocal( Ent1:toWorld(Local1), ang(), Ent2:toWorld(Local2), Ent1:angles() )
                if( O:keySprint() )
                {
                    P = propSpawn( Ent1:model(), Ent1:toWorld( -Local ), Ent1:angles(), 1 )
                }
                else
                {
                    Ent1:setPos( Ent1:toWorld( -Local ) )
                }
            }
            else
            {
                Distance = Ent1:toWorld(Local1):distance( Ent2:toWorld(Local2) )
                print( _HUD_PRINTCENTER, "Distance: \n" + Distance )
                hint( "Distance: \n" + Distance, 20 )
            }
            Ent1 = Ent2 = noentity()
            holoAlpha( 2, 0 )
        }
    }
}

Pause = O:keyUse() & O:keyAttack2()

if( changed(Pause) & Pause )
{
    Paused = !Paused
    print( _HUD_PRINTCENTER, Paused ? "Paused" : "Unpaused" )
}

if( chatClk(O) )
{
    local Lsx = O:lastSaid():lower():explode(" ")
    
    switch( Lsx[1,string] )
    {
        default,
        break
        
        case "done",
            hideChat(1)
            selfDestruct()
        break
        
        case "d",
            hideChat(1)
            Divisions = max( 1, Lsx[2,string]:toNumber() )
        break
        
        case "measure",
            Mode = 2
            holoColor( 2, hsv2rgb(60,1,1) )
            holoColor( 1, hsv2rgb(120,1,1) )
            hideChat(1)
        break
        
        case "move",
            Mode = 1
            holoColor( 1, hsv2rgb(0,1,0.5) )
            holoColor( 2, hsv2rgb(120,1,1) )
            hideChat(1)
        break
    }
}

if( last() )
{
    holoDeleteAll()
}
