Simple file manager for loading, resizing
This commit is contained in:
		| @ -29,6 +29,7 @@ loadCart :: proc(target: ^Cart, filename: cstring) -> CartLoadError { | ||||
| 		return CartLoadError.Wrong_Size | ||||
| 	} | ||||
| 	target.texture = rl.LoadTextureFromImage(target.image) | ||||
| 	rl.SetTextureFilter(target.texture, .POINT) | ||||
| 	target.loaded = true | ||||
| 	return CartLoadError.None | ||||
| } | ||||
|  | ||||
							
								
								
									
										136
									
								
								guimode.odin
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								guimode.odin
									
									
									
									
									
								
							| @ -5,11 +5,12 @@ import rl "vendor:raylib" | ||||
| import "core:fmt" | ||||
| import "core:strings" | ||||
| import "core:slice" | ||||
| import "core:bytes" | ||||
| import "core:os" | ||||
|  | ||||
|  | ||||
| W :: 400 | ||||
| H :: 300 | ||||
| W :: 640 | ||||
| H :: 480 | ||||
|  | ||||
| width : int = W | ||||
| height : int = H | ||||
| @ -23,17 +24,31 @@ fileNameBuffer : [FILENAME_MAX]byte | ||||
| fileNameString := cstring(&fileNameBuffer[0]) | ||||
| editMode := false | ||||
|  | ||||
| fileListScrolling : i32 = 0 | ||||
| fileListActive : i32 = -1 | ||||
| fileListFocus : i32 = -1 | ||||
|  | ||||
| fileList : rl.FilePathList | ||||
|  | ||||
|  | ||||
| State :: enum { | ||||
| 	CartsInput, | ||||
| 	Export, | ||||
| 	GotError, | ||||
| 	Exported | ||||
| 	Exported, | ||||
| 	FileSelect | ||||
| } | ||||
|  | ||||
| GraphicsMode :: proc() { | ||||
| 	files = slice.into_dynamic(filesBuf[:]) | ||||
| 	cart := Cart{} | ||||
| 	target := Cart{} | ||||
| 	fileListTarget : ^Cart | ||||
|  | ||||
| 	DefaultName :string : "output.p8.png" | ||||
| 	for char, i in DefaultName { | ||||
| 		fileNameBuffer[i] = auto_cast char | ||||
| 	} | ||||
|  | ||||
| 	errorMessages := map[CartLoadError]cstring { | ||||
| 		.None = "", | ||||
| @ -44,15 +59,15 @@ GraphicsMode :: proc() { | ||||
| 	defer delete(errorMessages) | ||||
| 	currentError := CartLoadError.None | ||||
| 	 | ||||
| 	rl.SetConfigFlags({rl.ConfigFlag.WINDOW_RESIZABLE}) | ||||
| 	rl.SetConfigFlags({.WINDOW_RESIZABLE, .INTERLACED_HINT}) | ||||
| 	rl.InitWindow(W, H, "PicoRepico") | ||||
| 	rl.SetTargetFPS(60) | ||||
|  | ||||
| 	//fontData := #load("font.ttf") | ||||
| 	//font := rl.LoadFontFromMemory(".ttf", raw_data(fontData), auto_cast len(fontData), 8, nil, 0) | ||||
| 	font := rl.LoadFontEx("font.ttf", 32, nil, 0) | ||||
| 	rl.GuiSetFont(font) | ||||
| 	rl.GuiSetStyle(auto_cast rl.GuiControl.DEFAULT, auto_cast rl.GuiControlProperty.BORDER_COLOR_NORMAL, i32(rl.ColorToInt(rl.Color{211, 2, 255, 255}))) | ||||
| 	//font := rl.LoadFontEx("font.ttf", 32, nil, 0) | ||||
| 	//rl.GuiSetFont(font) | ||||
| 	//rl.GuiSetStyle(auto_cast rl.GuiControl.DEFAULT, auto_cast rl.GuiControlProperty.BORDER_COLOR_NORMAL, i32(rl.ColorToInt(rl.Color{211, 2, 255, 255}))) | ||||
|  | ||||
| 	hw : f32 = auto_cast width / 2 | ||||
| 	hh : f32 = auto_cast height / 2 | ||||
| @ -67,7 +82,7 @@ GraphicsMode :: proc() { | ||||
| 		hw = auto_cast width / 2 | ||||
| 		hh = auto_cast height / 2 | ||||
|  | ||||
| 		#partial switch state { | ||||
| 		switch state { | ||||
| 		case .CartsInput: { | ||||
| 			mouse := rl.GetMousePosition() | ||||
| 			if rl.IsFileDropped() { | ||||
| @ -93,18 +108,24 @@ GraphicsMode :: proc() { | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			zoom = 1 | ||||
| 			if width >= 640 && height > 450 { | ||||
| 				zoom = 2 | ||||
| 			} | ||||
|  | ||||
| 			buttonCartRect := rl.Rectangle{ | ||||
| 				x = hw - CART_WIDTH - 20, | ||||
| 				x = hw - CART_WIDTH * f32(zoom) - 5, | ||||
| 				y = 8, | ||||
| 				width = CART_WIDTH, | ||||
| 				height = CART_HEIGHT, | ||||
| 				width = CART_WIDTH * f32(zoom), | ||||
| 				height = CART_HEIGHT * f32(zoom), | ||||
| 			} | ||||
| 			buttonTargetRect := rl.Rectangle{ | ||||
| 				x = hw + 20, | ||||
| 				x = hw + 5, | ||||
| 				y = 8, | ||||
| 				width = CART_WIDTH, | ||||
| 				height = CART_HEIGHT, | ||||
| 				width = CART_WIDTH * f32(zoom), | ||||
| 				height = CART_HEIGHT * f32(zoom), | ||||
| 			} | ||||
| 			cartRect := rl.Rectangle{0, 0, CART_WIDTH, CART_HEIGHT} | ||||
| 			convertButtonRect := rl.Rectangle{ | ||||
| 				x = hw - 40, | ||||
| 				y = auto_cast height - 38, | ||||
| @ -114,20 +135,32 @@ GraphicsMode :: proc() { | ||||
|  | ||||
| 			rl.BeginDrawing() | ||||
| 			rl.GuiDummyRec(rl.Rectangle{0, 0, auto_cast width, auto_cast height}, "") | ||||
| 			rl.GuiButton(buttonCartRect, "Place here cart") | ||||
| 			rl.GuiButton(buttonTargetRect, "Place here target") | ||||
| 			 | ||||
| 			if rl.GuiButton(buttonCartRect, "Drag original\ncart here") { | ||||
| 				fileListTarget = &cart | ||||
| 				cd(".") | ||||
| 				state = .FileSelect | ||||
| 			} | ||||
| 			if cart.loaded { | ||||
| 				rl.DrawTexture(cart.texture, auto_cast buttonCartRect.x, auto_cast buttonCartRect.y, rl.WHITE) | ||||
| 				rl.DrawTexturePro(cart.texture, cartRect, buttonCartRect, {0, 0}, 0, rl.WHITE) | ||||
| 			} | ||||
| 			if rl.GuiButton(buttonTargetRect, "Drag target\nshell here") { | ||||
| 				fileListTarget = &target | ||||
| 				cd(".") | ||||
| 				state = .FileSelect | ||||
| 			} | ||||
| 			if target.loaded { | ||||
| 				rl.DrawTexture(target.texture, auto_cast buttonTargetRect.x, auto_cast buttonTargetRect.y, rl.WHITE) | ||||
| 				rl.DrawTexturePro(target.texture, cartRect, buttonTargetRect, {0, 0}, 0, rl.WHITE) | ||||
| 			} | ||||
| 			if !(cart.loaded && target.loaded) { rl.GuiDisable() } | ||||
| 			if rl.GuiButton(convertButtonRect, "CONVERT!") { | ||||
| 				state = .Export | ||||
| 			} | ||||
| 			rl.GuiEnable() | ||||
|  | ||||
| 			if rl.GuiLabelButton(rl.Rectangle{auto_cast width-60, auto_cast height-20, 60, 20}, "by Nefrace") { | ||||
| 				rl.OpenURL("https://nefrace.itch.io") | ||||
| 			} | ||||
| 		} | ||||
| 		case .Export: { | ||||
| 			res := rl.GuiTextInputBox(rl.Rectangle{hw - 100, 60, 200, 100}, "Input filename for result", "", "ok;cancel", fileNameString, FILENAME_MAX, nil) | ||||
| @ -151,8 +184,35 @@ GraphicsMode :: proc() { | ||||
| 				state = .CartsInput | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 		case .FileSelect: { | ||||
| 			rl.GuiPanel(rl.Rectangle{4, 4, auto_cast width - 8, auto_cast height - 8}, "Select a file") | ||||
| 			if rl.GuiButton(rl.Rectangle{auto_cast width - 26, 8, 16, 16}, "#128#") { | ||||
| 				state = .CartsInput | ||||
| 			} | ||||
| 			if rl.GuiButton(rl.Rectangle{8, 30, 50, 22}, "Open") { | ||||
| 				if fileListActive == -1 {break} | ||||
| 				if rl.DirectoryExists(files[fileListActive]) { | ||||
| 					cd(files[fileListActive]) | ||||
| 					break | ||||
| 				} | ||||
| 				if rl.GetFileExtension(files[fileListActive]) != ".png" { | ||||
| 					fmt.println("not a png") | ||||
| 					break | ||||
| 				} | ||||
| 				currentError = loadCart(fileListTarget, files[fileListActive]) | ||||
| 				if currentError != .None { | ||||
| 					state = .GotError | ||||
| 				} | ||||
| 				state = .CartsInput | ||||
|  | ||||
| 			} | ||||
| 			if rl.GuiButton(rl.Rectangle{60, 30, 50, 22}, "Up") { | ||||
| 				cd("..") | ||||
| 			} | ||||
| 			rl.GuiSetStyle(auto_cast rl.GuiControl.LISTVIEW, auto_cast rl.GuiControlProperty.TEXT_ALIGNMENT, auto_cast rl.GuiTextAlignment.TEXT_ALIGN_LEFT) | ||||
| 			res := rl.GuiListViewEx(rl.Rectangle{8, 54, auto_cast width - 16, auto_cast height - 62}, filesPtr, auto_cast filesCount, &fileListScrolling, &fileListActive, &fileListFocus) | ||||
| 		} | ||||
| 		} | ||||
| 		 | ||||
| 		rl.EndDrawing() | ||||
| 	} | ||||
| @ -161,3 +221,41 @@ GraphicsMode :: proc() { | ||||
| 	unloadCart(&target) | ||||
| } | ||||
|  | ||||
| filesBuf : [1024*8]cstring | ||||
| files : [dynamic]cstring | ||||
| filesPtr : [^]cstring | ||||
| filesCount : i32 = 0 | ||||
|  | ||||
| cd :: proc(dir: cstring) -> (result: bool) { | ||||
| 	result = rl.ChangeDirectory(dir) | ||||
| 	rl.UnloadDirectoryFiles(fileList) | ||||
| 	clear(&files) | ||||
| 	fileList = rl.LoadDirectoryFiles(".") | ||||
|  | ||||
| 	for fname in fileList.paths[:fileList.count] { | ||||
| 		if rl.DirectoryExists(fname) || rl.GetFileExtension(fname) == ".png" { | ||||
| 			append(&files, fname) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	slice.sort_by(files[:], proc(i,j:cstring) -> bool { | ||||
| 		a := string(i) | ||||
| 		b := string(j) | ||||
| 		adir := rl.DirectoryExists(i) | ||||
| 		bdir := rl.DirectoryExists(j) | ||||
| 		if (adir && bdir) || (!adir && !bdir) { | ||||
| 			return strings.compare(a, b) == -1 | ||||
| 		} | ||||
| 		return adir && !bdir | ||||
| 	}) | ||||
|  | ||||
| 	filesPtr = raw_data(files) | ||||
| 	filesCount = auto_cast len(files) | ||||
|  | ||||
|  | ||||
| //	slice.sort_by_cmp(fileList.paths[:fileList.count], strings.compare()) | ||||
| 	fileListScrolling = 0 | ||||
| 	fileListActive = -1 | ||||
| 	fileListFocus = -1 | ||||
| 	return | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user