Code: Select all
; AZJIO (19.11.2023)
EnableExplicit
#Window = 0
;- Enumeration
Enumeration Gadget
	#cnvPalette
	#cnvScene
; 	#btnOpenLevel
	#btnSave
	#btnOpenImg
	#btnClear
	#Opt1
	#Opt2
	#Opt3
EndEnumeration
Declare hsb_to_rgb()
Declare rgb_to_hsb()
UseGIFImageDecoder()
UsePNGImageDecoder()
;- Global
Global tmp, i, j, y, x, Color, Type, ecnv, selectedColor, StyleBox
Global mxxOld, myyOld, pendown, delmode, mxx, myy
Global tmp$
Global ImagePlugin
Global Dim arr_rgb(2)
Global Dim arr_hsb(2)
Global w, h
Global ini$ = GetPathPart(ProgramFilename()) + "BallBrick.ini"
Global CELLSIZEW = 20
Global CELLSIZEH = 20
; #CELLSIZE
Global XXX = 24
Global YYY = 24
; Global Dim aIcon(XXX, YYY)
Global Dim aIcon(XXX, YYY)
Global AreaX = CELLSIZEW * XXX
Global AreaY = CELLSIZEH * YYY
Structure Bricks
	x.i
	y.i
	t.i
	c.i
EndStructure
;- GUI
OpenWindow(#Window, 0, 0, AreaX + 110, AreaY + 4, "IconEditor", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
; SetWindowColor(#Window, 0)
OptionGadget(#Opt1, AreaX + 11, AreaY - 230, 98, 20, "Solid")
OptionGadget(#Opt2, AreaX + 11, AreaY - 210, 98, 20, "Box")
OptionGadget(#Opt3, AreaX + 11, AreaY - 190, 98, 20, "Round")
SetGadgetState(#Opt2, 1)
StyleBox = 1
; ButtonGadget(#btnOpenLevel, AreaX + 6, AreaY - 160, 100, 33 , "Level")
ButtonGadget(#btnClear, AreaX + 6, AreaY - 120, 100, 33 , "Clear")
ButtonGadget(#btnOpenImg, AreaX + 6, AreaY - 80, 100, 33 , "Open img")
ButtonGadget(#btnSave, AreaX + 6, AreaY - 40, 100, 33 , "Save")
; холст Сцена
CanvasGadget(#cnvScene, 0, 0, AreaX + 4, AreaY + 4, #PB_Canvas_Border)
If StartDrawing(CanvasOutput(#cnvScene))
	Box(0, 0, AreaX, AreaY, 0)
	StopDrawing()
EndIf
; холст Палитра
CanvasGadget(#cnvPalette, AreaX + 4, 0, 106 , AreaY - 248)
If StartDrawing(CanvasOutput(#cnvPalette))
	Box(0, 0, 110 , AreaY - 168 , $333333)
	; Спектр
	w = 100
	h = 10
	arr_hsb(1) = 100
	arr_hsb(2) = 100
	For i = 100 To 0 Step - 1
		Line(93, 150 - i, 10, 1, RGB(i * 2.5, i * 2.5, i * 2.5))
	Next
; 	For i=0 To 255
; 		Line(91, i, 10, 1, RGB(i, i, i))
; 	Next
	For j = 0 To 90
		arr_hsb(2) = 100 - j
		For i = 0 To w
			arr_hsb(0) = i * 360 / w
			hsb_to_rgb()
			Plot(j + 1, i + 50, RGB(arr_rgb(0), arr_rgb(1), arr_rgb(2)))
		Next
	Next
	selectedColor = $7DC4DF
; 	Box(0, 0, 110, 30, selectedColor)
	Box(27, 8, 32, 32, $FFFFFF)
	Box(28, 9, 30, 30, selectedColor)
	StopDrawing()
EndIf
;; init palette end
Procedure DrawPixel(selectedColor)
	Protected myy, mxx
	; преобразование в позицию квадратов x, y, чтобы сравнить являются ли квадраты на одной линии
	mxx = Int(GetGadgetAttribute(#cnvScene, #PB_Canvas_MouseX) / CELLSIZEW) * CELLSIZEW
	myy = Int(GetGadgetAttribute(#cnvScene, #PB_Canvas_MouseY) / CELLSIZEH) * CELLSIZEH
	If StartDrawing(CanvasOutput(#cnvScene))
		Select StyleBox
			Case 0
				Box(mxx, myy, CELLSIZEW, CELLSIZEH, selectedColor)
			Case 1
				Box(mxx, myy, CELLSIZEW - 1, CELLSIZEH - 1, selectedColor)
			Case 2
				RoundBox(mxx + 1, myy + 1, CELLSIZEW - 2, CELLSIZEH - 2, 2, 2, selectedColor)
		EndSelect
		StopDrawing()
	EndIf
EndProcedure
;- Loop
Repeat
	Select WaitWindowEvent():
		Case #PB_Event_CloseWindow
			CloseWindow(#Window)
			End
			;  $00FF99
;- Loop_Gadget
		Case #PB_Event_Gadget
			Select EventGadget()
				Case #Opt1
					; 					SetGadgetState(#Opt1, 1)
					StyleBox = 0
				Case #Opt2
; 					SetGadgetState(#Opt2, 1)
					StyleBox = 1
				Case #Opt3
; 					SetGadgetState(#Opt3, 1)
					StyleBox = 2
; 				Case #btnOpenLevel
; 					tmp$ = OpenFileRequester("Открыть уровень", GetCurrentDirectory(), "txt|*.txt", 0)
; 					If Asc(tmp$)
; 					EndIf
				Case #btnClear
					If StartDrawing(CanvasOutput(#cnvScene))
						Box(0, 0, AreaX, AreaY, 0)
						StopDrawing()
					EndIf
				Case #btnOpenImg
					tmp$ = OpenFileRequester("Open file", GetCurrentDirectory(), "img|*.bmp;*.png;*.gif;*.ico", 0)
					If Asc(tmp$)
						#Image = 0
						If LoadImage(#Image, tmp$)
							If StartDrawing(CanvasOutput(#cnvScene))
								If GetExtensionPart(tmp$) = "ico"
									XXX = ImageWidth(#Image)
									YYY = ImageHeight(#Image)
									; Debug XXX
									; Debug YYY
									Box(0, 0, XXX + 1, YYY + 1, $010203) ; стираем холст цветом, который задан как прозрачный
									Dim aIcon(XXX, YYY) ; пересоздаём массив, в отличии от ReDim Dim стирает данные, но они и не нужны.
									CELLSIZEW = AreaX / XXX
									CELLSIZEH = AreaY / YYY
								Else
									ResizeImage(#Image, XXX , YYY, #PB_Image_Smooth)
; 									ResizeImage(#Image, AreaX , AreaY, #PB_Image_Raw)
								EndIf
								SetWindowTitle(#Window, "IconEditor   (" + Str(XXX) + "x" + Str(YYY) + ")")
								DrawImage(ImageID(#Image), 0, 0)
								; 	считываем пиксели рисунка в массив
								For y = 0 To YYY - 1
									For x = 0 To XXX - 1
										tmp = Point(x, y)
; 										Debug tmp
										aIcon(x, y) = tmp
									Next
								Next
								Box(0, 0, AreaX, AreaY, $010203) ; стираем холст
								For y = 0 To YYY - 1
									For x = 0 To XXX - 1
										Select StyleBox
											Case 0
												Box(x * CELLSIZEW, y * CELLSIZEH, CELLSIZEW, CELLSIZEH, aIcon(x, y))
											Case 1
												Box(x * CELLSIZEW, y * CELLSIZEH, CELLSIZEW - 1, CELLSIZEH - 1, aIcon(x, y))
											Case 2
												RoundBox(x * CELLSIZEW + 1, y * CELLSIZEH + 1, CELLSIZEW - 2, CELLSIZEH - 2, 2, 2, aIcon(x, y))
										EndSelect
									Next
								Next
								StopDrawing()
							EndIf
							FreeImage(#Image)
						EndIf
					EndIf
				Case #btnSave
					If StartDrawing(CanvasOutput(#cnvScene))
						DrawingMode(#PB_2DDrawing_Transparent)
						For y = 1 To YYY
							For x = 1 To XXX
								tmp = Point(x * CELLSIZEW - CELLSIZEW / 2, y * CELLSIZEH - CELLSIZEH / 2)
								aIcon(x, y) = tmp
							Next
						Next
						StopDrawing()
						If CreateImage(#Image, XXX, YYY, 24, #PB_Image_Transparent)
; 						If CreateImage(#Image, XXX, YYY)
							If StartDrawing(ImageOutput(#Image))
								DrawingMode(#PB_2DDrawing_Transparent)
								For y = 1 To YYY
									For x = 1 To XXX
										If aIcon(x, y) <> $010203
											Plot(x - 1, y - 1, aIcon(x, y))
										EndIf
									Next
								Next
								StopDrawing()
								; tmp$ = SaveFileRequester("Выберите файл для сохранения", GetCurrentDirectory(), "img|*.bmp;*.png;*.gif;*.ico", 0)
								tmp$ = SaveFileRequester("Select file to save", GetCurrentDirectory(), "*.bmp|*.bmp|*.png|*.png", 0)
								If Asc(tmp$)
									Select GetExtensionPart(tmp$)
										Case "png"
											ImagePlugin = #PB_ImagePlugin_PNG
										Case "bmp"
											ImagePlugin = #PB_ImagePlugin_BMP
										Default
											tmp$ + ".bmp"
											ImagePlugin = #PB_ImagePlugin_BMP
									EndSelect
									; 									Debug tmp$
; 									выводим на холст палитры, всё нормально с изображением
; 									If StartDrawing(CanvasOutput(#cnvPalette))
; 										DrawImage(ImageID(#Image), 1, 1)
; 										StopDrawing()
; 									EndIf
									If SaveImage(#Image, tmp$, ImagePlugin)
										MessageRequester("File created", tmp$)
									Else
										MessageRequester("Error", "Failed to save file")
									EndIf
								EndIf
							EndIf
							FreeImage(#Image)
						EndIf
					EndIf
;- Canvas (event)
				Case #cnvPalette
					ecnv = EventType()
					Select ecnv
						Case #PB_EventType_MouseWheel
; 							Debug
							mxx = GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseX)
							myy = GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseY)
							If mxx > 0 And mxx < 92 And myy > 49 And myy < 151
								arr_hsb(1) + GetGadgetAttribute(#cnvPalette, #PB_Canvas_WheelDelta) * 5
								If arr_hsb(1) < 0
									arr_hsb(1) = 0
									Continue
								ElseIf arr_hsb(1) > 100
									arr_hsb(1) = 100
									Continue
								EndIf
								Debug arr_hsb(1)
								If StartDrawing(CanvasOutput(#cnvPalette))
									For j = 0 To 90
										arr_hsb(2) = 100 - j
										For i = 0 To w
											arr_hsb(0) = i * 360 / w
											hsb_to_rgb()
											Plot(j + 1, i + 50, RGB(arr_rgb(0), arr_rgb(1), arr_rgb(2)))
										Next
									Next
									StopDrawing()
								EndIf
							EndIf
						Case #PB_EventType_LeftClick
							mxx = GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseX)
							myy = GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseY)
; 							Debug mxx
; 							Debug myy
							If mxx > 0 And mxx < 92 And myy > 49 And myy < 151
								If StartDrawing(CanvasOutput(#cnvPalette))
									selectedColor = Point(GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseX), GetGadgetAttribute(#cnvPalette, #PB_Canvas_MouseY))
									Box(28, 9, 30, 30, selectedColor)
									StopDrawing()
								EndIf
							EndIf
							If mxx > 92 And mxx < 104 And myy > 49 And myy < 151
								arr_hsb(1) = 150 - myy
								; 								Debug arr_hsb(1)
								If StartDrawing(CanvasOutput(#cnvPalette))
									For j = 0 To 90
										arr_hsb(2) = 100 - j
										For i = 0 To w
											arr_hsb(0) = i * 360 / w
											hsb_to_rgb()
											Plot(j + 1, i + 50, RGB(arr_rgb(0), arr_rgb(1), arr_rgb(2)))
										Next
									Next
									StopDrawing()
								EndIf
							EndIf
					EndSelect
				Case #cnvScene
					ecnv = EventType()
					Select ecnv
						Case #PB_EventType_RightButtonDown
							delmode = 1
							DrawPixel(0)
							pendown = 1
						Case #PB_EventType_LeftButtonDown
							DrawPixel(selectedColor)
							pendown = 1
						Case #PB_EventType_LeftButtonUp, #PB_EventType_RightButtonUp
							pendown = 0
							delmode = 0
						Case #PB_EventType_MouseMove
							If pendown = 1
								; преобразование в позицию квадратов x, y, чтобы сравнить являются ли квадраты на одной линии
								mxx = Int(GetGadgetAttribute(#cnvScene, #PB_Canvas_MouseX) / CELLSIZEW) * CELLSIZEW
								myy = Int(GetGadgetAttribute(#cnvScene, #PB_Canvas_MouseY) / CELLSIZEH) * CELLSIZEH
								If mxxOld = mxx And myyOld = myy
									Continue
								Else
									mxxOld = mxx
									myyOld = myy
								EndIf
								If StartDrawing(CanvasOutput(#cnvScene))
									If delmode
										Select StyleBox
											Case 0
												Box(mxx, myy, CELLSIZEW, CELLSIZEH, 0)
											Case 1
												Box(mxx, myy, CELLSIZEW - 1, CELLSIZEH - 1, 0)
											Case 2
												RoundBox(mxx + 1, myy + 1, CELLSIZEW - 2, CELLSIZEH - 2, 2, 2, 0)
										EndSelect
									Else
										Select StyleBox
											Case 0
												Box(mxx, myy, CELLSIZEW, CELLSIZEH, selectedColor)
											Case 1
												Box(mxx, myy, CELLSIZEW - 1, CELLSIZEH - 1, selectedColor)
											Case 2
												RoundBox(mxx + 1, myy + 1, CELLSIZEW - 2, CELLSIZEH - 2, 2, 2, selectedColor)
										EndSelect
									EndIf
									StopDrawing()
								EndIf
							EndIf
					EndSelect
			EndSelect
	EndSelect
ForEver
; Procedure hsb_to_rgb(arr_hsb)
Procedure hsb_to_rgb()
	Protected sector
	Protected.f ff, pp, qq, tt
	Protected.f Dim af_rgb(2) ; создаём массивы в которых числа будут в диапазоне 0-1
	Protected.f Dim af_hsb(2)
	; Protected Dim arr_rgb(2)
	af_hsb(2) = arr_hsb(2) / 100
	If arr_hsb(1) = 0 ; если серый, то одно значение всем
		arr_rgb(0) = Round(af_hsb(2) * 255, #PB_Round_Nearest)
		arr_rgb(1) = arr_rgb(0)
		arr_rgb(2) = arr_rgb(0)
		; ProcedureReturn arr_rgb
	EndIf
	While arr_hsb(0) >= 360 ; если тон задан большим запредельным числом, то
		arr_hsb(0) - 360
	Wend
	af_hsb(1) = arr_hsb(1) / 100
	af_hsb(0) = arr_hsb(0) / 60
	; sector = Int(arr_hsb(0))
	sector = Round(af_hsb(0), #PB_Round_Down)
	ff = af_hsb(0) - sector
	pp = af_hsb(2) * (1 - af_hsb(1))
	qq = af_hsb(2) * (1 - af_hsb(1) * ff)
	tt = af_hsb(2) * (1 - af_hsb(1) * (1 - ff))
	Select sector
		Case 0
			af_rgb(0) = af_hsb(2)
			af_rgb(1) = tt
			af_rgb(2) = pp
		Case 1
			af_rgb(0) = qq
			af_rgb(1) = af_hsb(2)
			af_rgb(2) = pp
		Case 2
			af_rgb(0) = pp
			af_rgb(1) = af_hsb(2)
			af_rgb(2) = tt
		Case 3
			af_rgb(0) = pp
			af_rgb(1) = qq
			af_rgb(2) = af_hsb(2)
		Case 4
			af_rgb(0) = tt
			af_rgb(1) = pp
			af_rgb(2) = af_hsb(2)
		Default
			af_rgb(0) = af_hsb(2)
			af_rgb(1) = pp
			af_rgb(2) = qq
	EndSelect
	; RGB
	arr_rgb(0) = Round(af_rgb(0) * 255, #PB_Round_Nearest)
	arr_rgb(1) = Round(af_rgb(1) * 255, #PB_Round_Nearest)
	arr_rgb(2) = Round(af_rgb(2) * 255, #PB_Round_Nearest)
	; BGR
	; arr_rgb(2)=Round(af_rgb(0)*255, #PB_Round_Nearest)
	; arr_rgb(1)=Round(af_rgb(1)*255, #PB_Round_Nearest)
	; arr_rgb(0)=Round(af_rgb(2)*255, #PB_Round_Nearest)
	; ProcedureReturn arr_rgb
EndProcedure
Procedure rgb_to_hsb()
	Protected.f min, max
	If arr_rgb(0) <= arr_rgb(1)
		min = arr_rgb(0)
		max = arr_rgb(1)
	Else
		min = arr_rgb(1)
		max = arr_rgb(0)
	EndIf
	If min > arr_rgb(2)
		min = arr_rgb(2)
	EndIf
	If max < arr_rgb(2)
		max = arr_rgb(2)
	EndIf
	If max = min
		arr_hsb(0) = 0
	ElseIf max = arr_rgb(0)
		arr_hsb(0) = 60 * (arr_rgb(1) - arr_rgb(2)) / (max - min)
		If arr_rgb(1) < arr_rgb(2)
			arr_hsb(0) + 360
		EndIf
	ElseIf max = arr_rgb(1)
		arr_hsb(0) = 60 * (arr_rgb(2) - arr_rgb(0)) / (max - min) + 120
	ElseIf max = arr_rgb(2)
		arr_hsb(0) = 60 * (arr_rgb(0) - arr_rgb(1)) / (max - min) + 240
	EndIf
	If max = 0
		arr_hsb(1) = 0
	Else
		arr_hsb(1) = (1 - min / max) * 100
	EndIf
	arr_hsb(2) = max / 255 * 100
	arr_hsb(0) = Round(arr_hsb(0), #PB_Round_Nearest)
	arr_hsb(1) = Round(arr_hsb(1), #PB_Round_Nearest)
	arr_hsb(2) = Round(arr_hsb(2), #PB_Round_Nearest)
	; ProcedureReturn arr_hsb
EndProcedure