// File: picker.agc
// Created: 20-04-25
type tPickerArrow
	id				as integer
	pos				as tPoint2D
	drag				as integer
endtype

type tPicker
	PickerWindowId	as integer
	Arrow			as tPickerArrow
	ValueID			as integer
	Shadow			as integer
	Light			as integer
	Init				as integer
	SwatchId			as integer
	Stp				as integer
	HSV				as tHSV
	rgb				as tRGB
	Cursor			as integer
	pos				as tPoint2D
endtype

global gPickerData	as tPicker


function		ColorPicker()	
	id	as integer
	hsv as tHSV
	rgb as tRGB
	
	if GetPointerPressed()
		id = GetSpriteHit(GetPointerX(), GetPointerY())
		select id
			case gPickerData.PickerWindowId
				rgb = PickColour(GetPointerX(), GetPointerY())
				hsv = RGB2HSV(rgb.r, rgb.g, rgb.b)
				SetHSV(hsv.h, hsv.s, hsv.v)	
				gPickerData.HSV = hsv			
				gPickerData.rgb = rgb				
			endcase
			case gPickerData.ValueID
				rgb = PickColour(GetPointerX(), GetPointerY())
				SetSpriteColor(gPickerData.SwatchID, rgb.r, rgb.g, rgb.b, 0xff)				
				SetSpritePositionByOffset(gPickerData.Arrow.id, GetSpriteX(gPickerData.Arrow.id), GetPointerY())		
				gPickerData.rgb = rgb		
			endcase
			case gPickerData.Arrow.id
				gPickerData.Arrow.Drag = TRUE
				gPickerData.Arrow.pos.x = GetPointerX()
				gPickerData.Arrow.pos.y = GetPointerY()				
			endcase
		endselect
	endif
	
	if GetPointerState() and gPickerData.Arrow.Drag = TRUE
		if GetPointerY() > GetSpriteY(gPickerData.ValueID) and GetPointerY() < ( GetSpriteY(gPickerData.ValueID) + GetSpriteHeight(gPickerData.ValueID) )
			rgb = PickColour(GetSpriteX(gPickerData.ValueID) + 2, GetPointerY())
			gPickerData.rgb = rgb			
			SetSpriteColor(gPickerData.SwatchID, rgb.r, rgb.g, rgb.b, 0xff)				
			SetSpritePositionByOffset(gPickerData.Arrow.id, GetSpriteX(gPickerData.Arrow.id), GetPointerY())
		endif		
	endif
	
endfunction gPickerData.rgb

function DeletePicker()
	gPickerData.PickerWindowId = DestroySprite(gPickerData.PickerWindowId)	
	gPickerData.SwatchId = DestroySprite(gPickerData.SwatchId)
	gPickerData.ValueID = DestroySprite(gPickerData.ValueID)	
	gPickerData.Cursor = DestroySprite(gPickerData.Cursor)			
	gPickerData.Arrow.id = DestroySprite(gPickerData.Arrow.id)	
	gPickerData.Init = 0
endfunction


function SetRGB(r as integer, g as integer, b as integer)
	hsv as tHSV
	x as integer
	y as integer
	
	hsv = RGB2HSV(r, g, b)
	
	x = hsv.h / 3 
	y = (1.0 - hsv.s) * 100.0
	
	x = GetWorldXFromSprite( gPickerData.PickerWindowId, x, y )
	y = GetWorldYFromSprite( gPickerData.PickerWindowId, x, y )
	
	SetHSV(hsv.h, hsv.s, hsv.v)
	gPickerData.rgb.r = r
	gPickerData.rgb.g = g
	gPickerData.rgb.b = b
endfunction	

function	SetHSV(h as float, s as float, v as float)
	c as float
	x as float
	y as float
	t as float
	rgb as tRGB
	
	x = h / 3 
	y = (1.0 - v) * 100.0
		
	x = GetWorldXFromSprite( gPickerData.PickerWindowId, x, y )
	y = GetWorldYFromSprite( gPickerData.PickerWindowId, x, y )
	
	c = HSV2RGB(h, s, v)
	
	SetSpritePosition(gPickerData.Cursor, x, y)
	
	CreateValueRamp(h, s, v)
	
	rgb = PickColour(GetSpriteX(gPickerData.ValueID) + 2, GetSpriteY(gPickerData.Arrow.id))
	SetSpriteColor(gPickerData.SwatchID, rgb.r, rgb.g, rgb.b, 0xff)	
		
	gPickerData.HSV = RGB2HSV(rgb.r, rgb.g, rgb.b)
endfunction

function PickColour(x as float, y as float)
	id as integer
	m as integer
	c as tRGB
	
	render()
	id = GetImage(x, y, x+1, y+1)
	m = CreateMemblockFromImage(id)
	
	c.r = getmemblockbyte(m,12)
	c.g = getmemblockbyte(m,13)
	c.b = getmemblockbyte(m,14)
	
	DeleteImage(id)
	DeleteMemblock(m)
endfunction c

function	ColorPickerInit(xx as integer, yy as integer)
	hue	as float
	sat	as float
	lum	as float
	c	as integer
	id	as integer
	x 	as float
	y 	as float
	i	as integer
	t	as float
	w	as tPoint2D
	
	if gPickerData.Init = 0
		gPickerData.Shadow = 0x40
		gPickerData.Light = 0xc0
		gPickerData.Init = 1		
	endif

	gPickerData.Pos.x = xx
	gPickerData.Pos.y = yy
		
	stp as float : stp = 3.0
	
	if gPickerData.Arrow.id = 0
		ColorPickerArrow()
	endif	
	
	ClearScreen()
	c = 0xffffffff
	DrawBox(0, 0, (360 / stp) + 2, 102, c, c, c, c, 1)
	Render()
	
	id = GetImage(0, 0, (360 / stp) + 2, 16)
	gPickerData.SwatchID = CreateSprite(id)
	c = HSV2RGB(0.01, 1.0, 1.0)
	SetSpriteColor(gPickerData.SwatchID, GetColorRed(c), GetColorGreen(c), GetColorBlue(c), 0xff)
		
	ClearScreen()	
	gPickerData.HSV.h = 0.1
	gPickerData.HSV.v = 1
	
	lum = 0.8
	
	for hue=0 to 360.0 step stp
		for sat=100 to 0 step -1
			c = HSV2RGB(hue, 1, (sat * 0.01))
			x = (hue / stp) + 1
			y = (100 - sat) + 1
			drawbox(x, y, x+1, y+1, c, c, c, c, 1)		
		next
	next	
		
	drawline(  0, 101, (360 / stp) + 1, 101, gPickerData.Light,  gPickerData.Light,  gPickerData.Light)	
	drawline(  0,   0,  0, 101, gPickerData.Shadow, gPickerData.Shadow, gPickerData.Shadow)
	drawline((360 / stp) +1,   0, (360 / stp) +1, 101, gPickerData.Light,  gPickerData.Light,  gPickerData.Light)
	drawline(  0,   0,  (360 / stp) + 1, 0, gPickerData.Shadow, gPickerData.Shadow, gPickerData.Shadow)
	
	Render()
	id = GetImage(0, 0, (360 / stp) + 2, 102)
	gPickerData.PickerWindowId = CreateSprite(id)
	SetSpritePosition(gPickerData.PickerWindowId, xx, yy)		
	SetSpriteOffset(gPickerData.PickerWindowId, 0, 0)	
	SetSpritePosition(gPickerData.SwatchId, xx, yy + GetSpriteHeight(gPickerData.PickerWindowId) + 8)

	ClearScreen()		
	DrawBox(0, 0, 4, 4, 0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff, 0)	
	Render()
	id = GetImage(0, 0, 5, 5)
	gPickerData.Cursor = CreateSprite(id)
	
	CreateValueRamp(0.01, 1, 1)
	SetSpritePositionByOffset(gPickerData.Arrow.id, GetSpriteX(gPickerData.ValueID) + 19, GetSpriteY(gPickerData.ValueID) + GetSpriteHeight(gPickerData.ValueID) * 0.5)
	
endfunction id


function CreateValueRamp(hue as float, sat as float, value as float)
	c as float
	t as float
	id as integer
	
	ClearScreen()
	
	drawline(  0,   0, 17,   0, gPickerData.Shadow, gPickerData.Shadow, gPickerData.Shadow)	
	drawline( 17,   0, 17, 101, gPickerData.Light,  gPickerData.Light,  gPickerData.Light)	
	drawline( 17, 101,  0, 101, gPickerData.Light,  gPickerData.Light,  gPickerData.Light)
	drawline(  0, 101,  0,   0, gPickerData.Shadow, gPickerData.Shadow, gPickerData.Shadow)
	
	c = 0xffffffff
	t = HSV2RGB(hue, sat, value)
	drawbox(1, 1, 16, 50, c, c, t, t, 1)
	c = HSV2RGB(hue, sat, value)
	t = 0xff000000
	drawbox(1, 51, 16, 100, c, c, t, t, 1)	

	if gPickerData.ValueID > 0
		DeleteSprite(gPickerData.ValueID)
		DeleteImage(gPickerData.ValueID)
	endif
	
	Render()
	id = GetImage(0, 0, 18, 102)
	gPickerData.ValueID = CreateSprite(id)
	SetSpritePosition(gPickerData.ValueID, GetSpriteX(gPickerData.PickerWindowId) + GetSpriteWidth(gPickerData.PickerWindowId) + 8, gPickerData.Pos.y)					
	
	
endfunction


////////////////////////
// HSV to RGB
function HSV2RGB( h as float, s as float, v as float)
	t as float
	r as float
	g as float
	b as float
	i as integer
	p as float
	q as float
	c as integer
	f as float
	
	h = fClamp(h, 0.0, 360.0) / 60.0
	s = fClamp(s, 0.0, 1.0)
	v = fClamp(v, 0.0, 1.0)
	
	i = floor(h)
	f = h - i

	p = v * (1.0 - s)
	q = v * (1.0 - s * f)
	t = v * (1.0 - s * (1.0 - f) )

	select i
		case 0 : r = v : g = t : b = p : endcase
		case 1 : r = q : g = v : b = p : endcase
		case 2 : r = p : g = v : b = t : endcase
		case 3 : r = p : g = q : b = v : endcase
		case 4 : r = t : g = p : b = v : endcase
		case 5 : r = v : g = p : b = q : endcase
	endselect

	r = fClamp(r, 0.0, 1.0) * 255
	g = fClamp(g, 0.0, 1.0) * 255
	b = fClamp(b, 0.0, 1.0) * 255
	c = MakeColor(r, g, b)
endfunction c

function ColorPickerArrow()
	s as string[]
	i as integer
	f as integer
	
	s.fromJSON('[ "89","50","4e","47","0d","0a","1a","0a","00","00","00","0d","49","48","44","52","00","00","00","08","00","00","00","08","08","06","00","00","00","c4","0f","be","8b","00","00","00","45","49","44","41","54","18","95","75","8e","c1","11","80","30","0c","c3","ac","2c","02","2b","e4","b2","40","37","81","51","ba","79","78","95","47","c1","fa","4a","77","36","32","64","e6","01","4c","ac","80","5b","92","70","62","81","13","8b","88","88","21","69","b8","2f","ef","44","55","5d","dd","3d","81","f3","37","70","e1","27","d8","c3","07","34","e0","14","32","ff","74","71","bf","00","00","00","00","49","45","4e","44","ae","42","60","82" ]')
	
	f = OpenToWrite("arrow.png")
	
	i = s.length
	
	for i=0 to s.length
		WriteByte(f, val(s[i], 16))
	next
	
	CloseFile(f)
	
	gPickerData.Arrow.id = CreateSprite(LoadImage("arrow.png"))	
	
	SetSpriteOffset(gPickerData.Arrow.id, 0, GetSpriteHeight(gPickerData.Arrow.id) * 0.5)
endfunction
		
function RGB2HSV( r as float, g as float, b as float)
	min as float
	max as float
	delta as float
	hsv as tHSV
	
    min = fMin3( r, g, b )
    max = fMax3( r, g, b )
    HSV.v = max / 255
    delta = max - min
     
    if max = 0 
        HSV.h = 0 : HSV.s = 0: HSV.v = 0: exitfunction HSV
    endif
    if (max=255) and (min=255) 
        HSV.h = 0 : HSV.s = 0: HSV.v = 1: exitfunction HSV
    endif
 
    HSV.s = delta/max
     
    select max
        case r: HSV.h = (g-b)/delta: endcase
        case g: HSV.h = 2 + (b-r)/delta: endcase
        case b: HSV.h = 4 + (r-g)/delta: endcase
    endselect
     
    HSV.h = fWrap(HSV.h*60, 0.0, 360.0)
     
endfunction HSV

////////////////////////
// Make Colour
function CreateColor( r as float, g as float, b as float, a as float )
    ret as tRGB
    ret.r = r
    ret.g = g
    ret.b = b
endfunction ret
 
////////////////////////
// WRAP
function fWrap( value as float, first as float, last as float )
	newvalue as float
    if value < first
        newValue = last - (first - value)
        exitfunction newValue
    endif
    if value > last
        newValue = first + (value - last)
        exitfunction newValue
    endif
endfunction value
 
////////////////////////
// MAX
function fMax3( a as float, b as float, c as float)
    if (a>b) and (a>c) then exitfunction a
    if b>c then exitfunction b
endfunction c
 
////////////////////////
// MIN
function fMin3( a as float, b as float, c as float )
    if (a<b) and (a<c) then exitfunction a
    if b<c then exitfunction b
endfunction c
 
////////////////////////
// CLAMP
function fClamp( v as float, minv as float, maxv as float)
    if v > maxv then exitfunction maxv
    if v < minv then exitfunction minv
endfunction v
