From d7bed0fa7305b254b32b1779277acd3fbebe3618 Mon Sep 17 00:00:00 2001 From: chrisbell Date: Tue, 16 Sep 2025 22:26:49 -0500 Subject: [PATCH] init --- .editorconfig | 4 ++ .gitattributes | 2 + .gitignore | 3 ++ icon.svg | 1 + icon.svg.import | 43 +++++++++++++++ project.godot | 21 ++++++++ scenes/main.tscn | 95 +++++++++++++++++++++++++++++++++ scripts/main.gd | 127 ++++++++++++++++++++++++++++++++++++++++++++ scripts/main.gd.uid | 1 + 9 files changed, 297 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 icon.svg create mode 100644 icon.svg.import create mode 100644 project.godot create mode 100644 scenes/main.tscn create mode 100644 scripts/main.gd create mode 100644 scripts/main.gd.uid diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..c6bbb7d --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..affec0c --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmb3k4y6h1xd0" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..b759d34 --- /dev/null +++ b/project.godot @@ -0,0 +1,21 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="AABGG" +run/main_scene="uid://dgnxuejg2n1xb" +config/features=PackedStringArray("4.5", "GL Compatibility") +config/icon="res://icon.svg" + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" diff --git a/scenes/main.tscn b/scenes/main.tscn new file mode 100644 index 0000000..d55c1dd --- /dev/null +++ b/scenes/main.tscn @@ -0,0 +1,95 @@ +[gd_scene load_steps=2 format=3 uid="uid://dgnxuejg2n1xb"] + +[ext_resource type="Script" uid="uid://b8xlgs6663g2b" path="res://scripts/main.gd" id="1_o5qli"] + +[node name="Main" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_o5qli") + +[node name="Panel" type="Panel" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HFlowContainer" type="HBoxContainer" parent="Panel/VBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 + +[node name="Artist" type="LineEdit" parent="Panel/VBoxContainer/HFlowContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Demon Hunter" +placeholder_text = "Artist" + +[node name="Album" type="LineEdit" parent="Panel/VBoxContainer/HFlowContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "War" +placeholder_text = "Album" + +[node name="Button" type="Button" parent="Panel/VBoxContainer/HFlowContainer"] +layout_mode = 2 +text = "Search" + +[node name="ScrollContainer" type="ScrollContainer" parent="Panel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ImageContainer" type="HFlowContainer" parent="Panel/VBoxContainer/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer"] +layout_mode = 2 + +[node name="StatusBar" type="TextEdit" parent="Panel/VBoxContainer/HBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Status..." +editable = false +wrap_mode = 1 + +[node name="CreateCollageButton" type="Button" parent="Panel/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Create Collage" + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[node name="ImageHttpRequest" type="HTTPRequest" parent="."] + +[node name="CollagePopupPanel" type="PopupPanel" parent="."] +oversampling_override = 1.0 +initial_position = 4 + +[node name="TextureRect" type="TextureRect" parent="CollagePopupPanel"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 4.0 +offset_top = 4.0 +offset_right = -4.0 +offset_bottom = -4.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 diff --git a/scripts/main.gd b/scripts/main.gd new file mode 100644 index 0000000..0fe380f --- /dev/null +++ b/scripts/main.gd @@ -0,0 +1,127 @@ +extends Control + +@onready var artist_input: LineEdit = $Panel/VBoxContainer/HFlowContainer/Artist +@onready var album_input: LineEdit = $Panel/VBoxContainer/HFlowContainer/Album +@onready var search_button: Button = $Panel/VBoxContainer/HFlowContainer/Button +@onready var output: TextEdit = $Panel/VBoxContainer/HBoxContainer/StatusBar +@onready var http_request: HTTPRequest = $HTTPRequest +@onready var http_image_request: HTTPRequest = $ImageHttpRequest +@onready var collage_popup_panel: PopupPanel = $CollagePopupPanel +@onready var create_collage_button: Button = $Panel/VBoxContainer/HBoxContainer/CreateCollageButton + + +var _image_array: Array[ImageTexture] = [] + +func _ready() -> void: + http_request.request_completed.connect(_on_http_request_completed) + search_button.pressed.connect(_on_search) + + http_image_request.request_completed.connect(_on_http_image_request_completed) + + create_collage_button.pressed.connect(_on_create_collage) + + +func _on_create_collage(): + var w = 1920 + var h = 1080 + var collage: ImageTexture = create_collage(w, h, false) + var img = collage.get_image() + var save_path = "user://saved_image.png" + var error: Error = img.save_png(save_path) + + if error == OK: + print("Image saved successfully to: " + save_path) + else: + print("Error saving image: " + str(error)) + #collage_popup_panel.get_node("TextureRect").texture = collage + #collage_popup_panel.size = Vector2(w, h) + #collage_popup_panel.show() + + +func _on_http_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + if result == HTTPRequest.RESULT_SUCCESS: + var json_data = JSON.parse_string(body.get_string_from_utf8()) as Dictionary + if json_data: + var data_arr: Array = json_data["data"] + var album: Dictionary = data_arr[0] + var cover_url: String = album["cover_big"] + output.text = str(cover_url) + http_image_request.request(cover_url) + else: + output.text = "Failed to parse JSON" + else: + output.text = str("HTTP Request failed with result: ", result, " and code: ", response_code) + + +# https://api.deezer.com/search/album?q=Demon%20Hunter%20War +func _on_search() -> void: + var artist = artist_input.text.replace(" ", "%20") + var album = album_input.text.replace(" ", "%20") + if artist == "" or album == "": return + + var url = str("https://api.deezer.com/search/album?q=",artist,"%20",album) + http_request.request(url) + + +func _on_http_image_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + if result == HTTPRequest.RESULT_SUCCESS: + var img = Image.new() + var err = img.load_jpg_from_buffer(body) + if err == OK: + var tex = ImageTexture.new() + tex = ImageTexture.create_from_image(img) + var new_tex_rect_node: TextureRect = TextureRect.new() + $Panel/VBoxContainer/ScrollContainer/ImageContainer.add_child(new_tex_rect_node) + new_tex_rect_node.texture = tex + _image_array.append(tex) + else: + output.text = str("Error loading image: ", err) + else: + output.text = str("HTTP Request failed with result: ", result, " and code: ", response_code) + + +func create_collage(w: int, h: int, fail_if_not_even: bool) -> ImageTexture: + var tile_w := 500 + var tile_h := 500 + + # Compute how many tiles we need to cover the area + var cols:int = ceil(w / tile_w) + var rows:int = ceil(h / tile_h) + var total_needed:int = cols * rows + + if fail_if_not_even and _image_array.size() < total_needed: + push_error("Not enough images to fill collage") + return null + + var shuffled := _image_array.duplicate() + shuffled.shuffle() + while shuffled.size() < total_needed: + shuffled.append_array(shuffled) + + # Actual cell size for each tile + var cell_w := w / cols + var cell_h := h / rows + + # Create the collage image with black background + var collage := Image.create(w, h, false, Image.FORMAT_RGBA8) + collage.fill(Color.BLACK) + + var idx := 0 + for row in rows: + for col in cols: + if idx >= shuffled.size(): + break + var tex: ImageTexture = shuffled[idx] + var img: Image = tex.get_image() + if img.get_format() != collage.get_format(): + img.convert(collage.get_format()) + + # Resize to fit the cell exactly (aspect ratio is fine to distort slightly) + img.resize(cell_w, cell_h) + + collage.blit_rect(img, Rect2i(Vector2i(0, 0), Vector2i(cell_w, cell_h)), + Vector2i(col * cell_w, row * cell_h)) + + idx += 1 + + return ImageTexture.create_from_image(collage) diff --git a/scripts/main.gd.uid b/scripts/main.gd.uid new file mode 100644 index 0000000..8a1321c --- /dev/null +++ b/scripts/main.gd.uid @@ -0,0 +1 @@ +uid://b8xlgs6663g2b