@name 14-segment sign maker
#@inputs String:string Master:entity 
#@inputs Scale Start Parent FX
#@inputs Colour:vector
@outputs String:string Master:entity 
@outputs Colour:vector Scale Start Parent FX
@persist Chardefs:table Defaultpos:array Holos:array 
@persist Spawning Index RemainingSpawns Nextburst Nextspawn
@persist String:string Master:entity Scale Start Parent FX
#by Magos Mechanicus
interval(1000)
runOnChat(1)
gSetGroup("Sign")
if(first()){
    if(gGetNum("Used")){
    Master=gGetEnt("Master")
    Scale=gGetNum("Scale")
    String=gGetStr("String")
    Parent=gGetNum("Parent")
    FX=gGetNum("FX")    
    Colour=gGetVec("Colour")
    }else{
    Master=entity() Scale=50 Parent=1 FX=1}
}
#if(!Master){Master=entity()}
if(!Scale){Scale=50}
Own=entity():owner()
Chat=Own:lastSaid()
K=chatClk()
Command="Sign"
Print="say"
Scale1="!s"
Parent1="!p"
FX1="!f"
Color="!c"
Break=" "
Get="<"
GO="run"
Reset="!x"
Brk=";"
HelpMe="help"
Setting="!set"
Printing=Chat:find(Print)
Com=Chat:find(Command)
Got=Chat:find(Get)
Go=Chat:find(GO)
Color1=Chat:find(Color)
Scale2=Chat:find(Scale1)
Parent2=Chat:find(Parent1)
FX2=Chat:find(FX1)
Reset1=Chat:find(Reset)
Help=Chat:find(HelpMe)
Settings=Chat:find(Setting)
if(K&Com){
    if(Settings){
        print("Parented?: "+Parent)
        print("Scale: "+Scale)
        print("Color: "+Colour)
        print("String: "+String)
        print("FX: "+FX)
        MasterA=array()
        MasterA[1,entity]=Master
    print("entity: "+MasterA:concat()) 
    }
    if(Help){
        Ch="Change "
        print("Commands:")
        print("Say: '"+Command+"' Then say:")
        print(Ch+"color: "+Color)
        print(Ch+"Scale: "+Scale1)
        print(Ch+"Entity: "+Get)
        print(Ch+"FX: "+FX1)
        print(Ch+"Parrented?: "+Parent1)
        print("Set string say: "+Print+Brk)
        print("To reset for another string: "+Reset)
        print("To start type: "+GO)
    }
    if(Reset1){
        gSetNum("Used",1)
        gSetNum("Parent",Parent)
        gSetNum("Scale",Scale)
        gSetNum("FX",FX)
        gSetVec("Colour",Colour)
        gSetEnt("Master",Master)
        gSetStr("String",String)
        reset()
        }
    if(Go){Start=1}
    if(Color1){
        Color2=Chat:explode(Break)
        R=Color2[3,string]:toNumber()
        G=Color2[4,string]:toNumber()
        B=Color2[5,string]:toNumber()
        Colour=vec(R,G,B)
        print("Color: "+Colour)
    }
    if(Parent2){Parent=Chat:explode(Break)[3,string]:toNumber()
        print("Parent: "+Parent)}
    if(FX2){FX=Chat:explode(Break)[3,string]:toNumber() 
        print("FX: "+FX)}
    if(Scale2){Scale=Chat:explode(Break)[3,string]:toNumber() 
        print("Scale: "+Scale)}
 if(Printing){String=Chat:explode(Brk)[2,string] print(String)}
if(Got){
    Master=Own:aimEntity() 
    MasterA=array()
    MasterA[1,entity]=Master
    print("entity: "+MasterA:concat())}
}else{Start=0}

#if(Start&~Start&Master&Scale){
if(Start&changed(Start)&Master&Scale){
    holoDeleteAll()
    Holos=array()
    Spawning=1 Index=0
    }

if(Spawning){
    #Remaining spawns tracking
    Curtime=curtime()
    if(Curtime >= Nextspawn){
        Nextspawn=Curtime+1
        if(Curtime >= Nextburst){
            RemainingSpawns=30
            Nextburst=Curtime+10
        }elseif(RemainingSpawns<10){
            RemainingSpawns=10}
    }
    Nextburst=Curtime+10
    
    #If we have the spawns to spare:
    Decoded=Chardefs[String:upper():index(Index+1), string]
    if(Decoded:replace("0",""):length() <= RemainingSpawns){
            Index++
            Origin=Master:toWorld( vec( 0,3*(Index-String:length()/2)*Scale,5+Master:boxSize():z() ) )
            Frame=matrix(Master)*Scale Roll=Master:angles():pitch()
            Find=Decoded:find("1")
            while(Find){
                #Spawn and track
                Holoindex=Holos:count()+1
                holoCreate(Holoindex)
                Holos[Holoindex, vector2] = vec2(Find, Index) 
                RemainingSpawns--
                Matrix=Defaultpos[Find,matrix]
                
                #Positioning/orientation
                holoPos(Holoindex,Origin + Frame*Matrix:column(1))
                holoAng(Holoindex,(Frame*Matrix:column(2)):toAngle():setRoll(Roll))
                holoScaleUnits(Holoindex,Matrix:column(3)*Scale)
                
                #Rendering/parenting
                holoShadow(Holoindex,0)
                holoColor(Holoindex,Colour,255)
                if(Parent){holoParent(Holoindex,Master)}
                if(FX){holoRenderFX(Holoindex,3)
                    holoColor(Holoindex,Colour,200)}
                
                Find=Decoded:find("1",Find+1)
                }
            timer("Spawning",10)
        }
        else{timer("Waittospawn",1001)}

    if(Index==String:length()){Spawning=0}
}

if(first()){
     #Local definitions for positions, directions and scales of different segments
    Hscale=vec(2,0.25,0.25)
    Half=vec(Hscale:x()/2,0.25,0.25)
    Small=vec(2.1,0.2,0.2)
    Angle=67.5
    Temp=matrix(vec(0,0,4),vec(0,1,0),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,1,3),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,1,1),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0,0),vec(0,1,0),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,-1,1),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,-1,3),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,-0.5,2),vec(0,1,0),Half)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0.5,2),vec(0,1,0),Half)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0,1),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0,3),vec(0,0,1),Hscale)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,-0.5,3),vec(0,cos(Angle),-sin(Angle)),Small)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0.5,3),vec(0,cos(Angle),sin(Angle)),Small)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,-0.5,1),vec(0,cos(Angle),sin(Angle)),Small)
    Defaultpos:pushMatrix(Temp)
    Temp=matrix(vec(0,0.5,1),vec(0,cos(Angle),-sin(Angle)),Small)
    Defaultpos:pushMatrix(Temp)
    
    #Character definitions
    #Characters follow the ABCDEF of the Wire 7-seg indicator
#but the F is split into two consecutive segments, counting from the left.
#Then follows the middle vertical segments, counting from the bottom and 
#then the crossbars, counting clockwise from the top left.
    #Each character's definition is indexed by the character itself
    Chardefs:setString("0","11111100000000")
    Chardefs:setString("1","01100000000000")
    Chardefs:setString("2","11011011000000")
    Chardefs:setString("3","11110011000000")
    Chardefs:setString("4","01100111000000")
    Chardefs:setString("5","10110111000000")
    Chardefs:setString("6","10111111000000")
    Chardefs:setString("7","11100000000000")
    Chardefs:setString("8","11111111000000")
    Chardefs:setString("9","11110111000000")
    Chardefs:setString("A","11101111000000")
    Chardefs:setString("B","11110001110000")
    Chardefs:setString("C","10011100000000")
    Chardefs:setString("D","11110000110000")
    Chardefs:setString("E","10011111000000")
    Chardefs:setString("F","10001111000000")
    Chardefs:setString("G","10111101000000")
    Chardefs:setString("H","01101111000000")
    Chardefs:setString("I","00000000110000")
    Chardefs:setString("J","01111000000000")
    Chardefs:setString("K","00001110000101") 
    Chardefs:setString("L","00011100000000")
    Chardefs:setString("M","01101100001100") 
    Chardefs:setString("N","01101100001001") 
    Chardefs:setString("O","11111100000000")
    Chardefs:setString("P","11001111000000")
    Chardefs:setString("Q","11111100000001")
    Chardefs:setString("R","11001111000001")
    Chardefs:setString("S","10110111000000")
    Chardefs:setString("T","10000000110000")
    Chardefs:setString("U","01111100000000")
    Chardefs:setString("V","00001100000110") 
    Chardefs:setString("W","01101100000011") 
    Chardefs:setString("X","00000000001111") 
    Chardefs:setString("Y","00000000101100")
    Chardefs:setString("Z","10010000000110")
    Chardefs:setString(" ","00000000000000") 
    Chardefs:setString("-","00000011000000")
    Chardefs:setString("'","00000000000100")
    
    RemainingSpawns=30 Nextspawn=Nextburst=curtime() 
    }
