diff --git a/.gitignore b/.gitignore index 5fefad3..4bde3cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target *.jpg !background.jpg +.godot diff --git a/Cargo.lock b/Cargo.lock index a78c59d..063adf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "approx" version = "0.5.1" @@ -166,6 +175,24 @@ dependencies = [ "toml", ] +[[package]] +name = "gdextension-api" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f2fc05d781fbc1da92d13480d464b2bf66b2e8cf230746f3a9ded3eb9bf6de" + +[[package]] +name = "gensym" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "uuid", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -174,7 +201,18 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -187,6 +225,95 @@ dependencies = [ "weezl", ] +[[package]] +name = "glam" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" + +[[package]] +name = "godot" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246203d267e0523aa8877e7d5145fa34a5bbdb1a5c8e135f4dacbdeb074c1fc9" +dependencies = [ + "godot-core", + "godot-macros", +] + +[[package]] +name = "godot-bindings" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b664d294f99139f828b76b6e9955aa1b7455cc03fac08917b57a4578d22489e7" +dependencies = [ + "gdextension-api", +] + +[[package]] +name = "godot-cell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28ee918b831ef1c455283b96d8527d0ddee556363c757fc18e01c75935bf7fb8" + +[[package]] +name = "godot-codegen" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e6d5d3f836cdc4487de17f3422f7b25c3f95a11472132f8e8ef698dd907cd4" +dependencies = [ + "godot-bindings", + "heck", + "nanoserde", + "proc-macro2", + "quote", + "regex", +] + +[[package]] +name = "godot-core" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96dbdc7c65fb4a2dc58b66c2bb91f2b092f55afa42d2ffd509fa454f123f3e51" +dependencies = [ + "glam", + "godot-bindings", + "godot-cell", + "godot-codegen", + "godot-ffi", +] + +[[package]] +name = "godot-ffi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4a1f0d0c8c1443ba8732f011a532ae35793e276567e2fcd90a8ef9c09d90c9" +dependencies = [ + "gensym", + "godot-bindings", + "godot-codegen", + "libc", + "paste", +] + +[[package]] +name = "godot-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff936aabcda6b8bcba69a4367938369e41bcdf17601f07ddda153947a481a0f0" +dependencies = [ + "godot-bindings", + "proc-macro2", + "quote", + "venial", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "image" version = "0.23.14" @@ -239,7 +366,9 @@ dependencies = [ name = "instinct" version = "0.1.0" dependencies = [ + "godot", "image 0.25.5", + "lazy_static", "photon-rs", ] @@ -325,6 +454,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nanoserde" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de9cf844ab1e25a0353525bd74cb889843a6215fa4a0d156fd446f4857a1b99" +dependencies = [ + "nanoserde-derive", +] + +[[package]] +name = "nanoserde-derive" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204" + [[package]] name = "node-sys" version = "0.4.2" @@ -457,6 +601,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "perlin2d" version = "0.2.6" @@ -579,7 +729,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", "libc", "rand_chacha", "rand_core 0.5.1", @@ -611,7 +761,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", ] [[package]] @@ -644,6 +794,35 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rulinalg" version = "0.4.2" @@ -702,18 +881,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -923,6 +1102,25 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "venial" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6816bc32f30bf8dd1b3adb04de8406c7bf187d2f923bd9e4c0b99365d012613f" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "version_check" version = "0.9.5" @@ -935,6 +1133,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.78" diff --git a/Cargo.toml b/Cargo.toml index 665b1a0..4179c81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,10 +3,18 @@ name = "instinct" version = "0.1.0" edition = "2021" -[[bin]] -name = "cli" -src = "src/main.rs" +[lib] +# name = "instinct" +crate-type = ["cdylib"] + + +# [[bin]] +# name = "cli" + + [dependencies] +godot = { version = "0.1.3", features = ["experimental-threads"] } image = { version = "0.25.5", features = ["jpeg"], default-features = false } +lazy_static = "1.5.0" photon-rs = "0.3.2" diff --git a/PhotoProcessing.gdextension b/PhotoProcessing.gdextension new file mode 100644 index 0000000..b388890 --- /dev/null +++ b/PhotoProcessing.gdextension @@ -0,0 +1,8 @@ +[configuration] +entry_symbol = "gdext_rust_init" +compatibility_minimum = 4.3 +reloadable = true + +[libraries] +macos.debug.arm64 = "res://target/debug/libinstinct.dylib" +macos.release.arm64 = "res://target/release/libinstinct.dylib" diff --git a/background.jpg b/background.jpg deleted file mode 100644 index da8ea65..0000000 Binary files a/background.jpg and /dev/null differ diff --git a/godot/App.gd b/godot/App.gd new file mode 100644 index 0000000..b8390cb --- /dev/null +++ b/godot/App.gd @@ -0,0 +1,110 @@ +extends Control + + +@onready +var template = $Printer/PictureLayer/Template + +signal done_loading_picture(picture) +signal done_processing_photo(photo) + +var files_being_processed = 0 + +func _ready(): + get_viewport().files_dropped.connect( + func(files): + var thread = Thread.new() + thread.start(on_files_dropped.bind(files), Thread.PRIORITY_LOW) + $PhotoProcess.process_files(files) + ) + + $PhotoProcess.done_with_photo.connect( + func(photo): + var thread = Thread.new() + thread.start(print_out.bind(photo), Thread.PRIORITY_LOW) + ) + + done_loading_picture.connect(animate_picture) + done_processing_photo.connect(animate_printing_out) + + template.get_parent().remove_child(template) + + +func on_files_dropped(files): + var index = 0 + for path in files: + var image = Image.load_from_file(path) + var texture = ImageTexture.create_from_image(image) + + var picture = template.duplicate() + picture.get_node('Texture').texture = texture + picture.global_position = Vector2(randf_range(-300, 300), -300) * 2.0 + picture.rotation = randf() * TAU * randf_range(1, 3) + call_deferred('emit_signal', 'done_loading_picture', picture, index) + index += 1 + + +func animate_picture(picture, index): + $Printer/PictureLayer.add_child(picture) + await get_tree().create_timer(index).timeout + var tween = create_tween().set_parallel() + var time = 1.0 + randf() + tween.tween_property( + picture, + 'rotation', + .0, + time + ) + + tween.tween_property( + picture, + 'global_position', + $Printer/Back/AnimationTarget.global_position, + time + ) + + tween.chain().tween_property( + picture, + 'global_position', + $Printer/Back/AnimationTarget.global_position + Vector2.DOWN * 100, + 1.0 + ) + + tween.play() + await tween.finished + files_being_processed += 1 + + +func print_out(photo): + var image = Image.load_from_file(photo) + var texture = ImageTexture.create_from_image(image) + + var picture = template.duplicate() + picture.get_node('Texture').texture = texture + call_deferred('emit_signal', 'done_processing_photo', picture) + + +func animate_printing_out(picture): + $Printer/PictureOutLayer.add_child(picture) + files_being_processed -= 1 + + picture.global_position = $Printer/Back/AnimationTarget.global_position + Vector2.DOWN * 100 + picture.rotation = .0 + + var tween = create_tween() + var time = 3.0 + randf() + + tween.tween_property( + picture, + 'global_position', + $Printer/Back/AnimationTarget.global_position + Vector2.DOWN * 200, + time + ) + + tween.play() + + +func _process(_delta): + if files_being_processed > 0: + $Printer/Front.rotation = sin(Time.get_ticks_msec()) * .025 + else: + $Printer/Front.rotation = .0 diff --git a/godot/App.tscn b/godot/App.tscn new file mode 100644 index 0000000..75d852a --- /dev/null +++ b/godot/App.tscn @@ -0,0 +1,278 @@ +[gd_scene load_steps=7 format=3 uid="uid://dxtriafl731dx"] + +[ext_resource type="Script" path="res://godot/App.gd" id="1_mppeb"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5uavs"] +bg_color = Color(0.2, 0.058, 0.058, 1) +corner_radius_top_left = 32 +corner_radius_top_right = 32 +corner_radius_bottom_right = 16 +corner_radius_bottom_left = 16 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5u4ls"] +bg_color = Color(0.2, 0.058, 0.058, 1) +corner_radius_bottom_right = 16 +corner_radius_bottom_left = 16 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_c0w2o"] +bg_color = Color(0.6, 0.174, 0.174, 1) +corner_radius_top_left = 32 +corner_radius_top_right = 32 +corner_radius_bottom_right = 16 +corner_radius_bottom_left = 16 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kj77j"] +bg_color = Color(0.87665, 0.8633, 0.89, 1) +corner_radius_top_left = 100 +corner_radius_top_right = 100 +corner_radius_bottom_right = 100 +corner_radius_bottom_left = 100 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7puhn"] +bg_color = Color(0.43, 0.1247, 0.1247, 1) +corner_radius_top_left = 32 +corner_radius_top_right = 32 + +[node name="App" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("1_mppeb") + +[node name="PhotoProcess" type="PhotoProcess" parent="."] + +[node name="Poloroid" type="Control" parent="."] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Background" type="ColorRect" parent="Poloroid"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.99, 0.9504, 0.9504, 1) + +[node name="Black" type="ColorRect" parent="Poloroid"] +layout_mode = 1 +anchors_preset = -1 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 52.0 +offset_top = 52.0 +offset_right = -52.0 +offset_bottom = -96.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.08, 0.0768, 0.0768, 1) +metadata/_edit_use_anchors_ = true + +[node name="StatusText" type="RichTextLabel" parent="Poloroid"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -200.0 +offset_top = -69.0 +offset_right = 200.0 +offset_bottom = 66.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/normal_font_size = 32 +bbcode_enabled = true +text = "[center]Drop in your photos to get started 🫓 🌁 + [/center]" +fit_content = true + +[node name="Printer" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Background" type="ColorRect" parent="Printer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.82, 0.7872, 0.7872, 1) + +[node name="StatusText" type="RichTextLabel" parent="Printer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -200.0 +offset_top = 121.0 +offset_right = 200.0 +offset_bottom = 256.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_colors/default_color = Color(0, 0, 0, 1) +theme_override_font_sizes/normal_font_size = 32 +bbcode_enabled = true +text = "[center]Drop in your photos to get started 🫓 🌁 + [/center]" +fit_content = true + +[node name="Back" type="Panel" parent="Printer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -100.0 +offset_top = -178.0 +offset_right = 100.0 +offset_bottom = -29.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_5uavs") + +[node name="AnimationTarget" type="Control" parent="Printer/Back"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -0.5 +offset_top = -0.5 +offset_right = 0.5 +offset_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="PictureLayer" type="Control" parent="Printer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Template" type="Control" parent="Printer/PictureLayer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -165.0 +offset_top = -437.0 +offset_right = -164.0 +offset_bottom = -436.0 +grow_horizontal = 2 +grow_vertical = 2 +pivot_offset = Vector2(85, 95) + +[node name="Texture" type="TextureRect" parent="Printer/PictureLayer/Template"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -85.5 +offset_top = -73.0 +offset_right = 85.5 +offset_bottom = 73.0 +grow_horizontal = 2 +grow_vertical = 2 +pivot_offset = Vector2(85, 95) +expand_mode = 1 +stretch_mode = 5 + +[node name="Exit" type="Panel" parent="Printer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -100.0 +offset_top = 50.0 +offset_right = 100.0 +offset_bottom = 96.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_5u4ls") + +[node name="PictureOutLayer" type="Control" parent="Printer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Front" type="Panel" parent="Printer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -170.0 +offset_top = -98.0 +offset_right = 170.0 +offset_bottom = 51.0 +grow_horizontal = 2 +grow_vertical = 2 +pivot_offset = Vector2(171, 75) +theme_override_styles/panel = SubResource("StyleBoxFlat_c0w2o") + +[node name="Button" type="Panel" parent="Printer/Front"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = 129.0 +offset_top = -55.5 +offset_right = 149.0 +offset_bottom = -35.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_kj77j") + +[node name="Mouth" type="Panel" parent="Printer/Front"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -100.0 +offset_top = 51.5 +offset_right = 100.0 +offset_bottom = 74.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_7puhn") diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..cd7d08f --- /dev/null +++ b/project.godot @@ -0,0 +1,24 @@ +; 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] + +run/main_scene="res://godot/App.tscn" +config/features=PackedStringArray("4.3") +boot_splash/bg_color=Color(0.988235, 0.94902, 0.94902, 1) +boot_splash/show_image=false + +[display] + +window/size/viewport_width=500 +window/size/viewport_height=500 +window/size/resizable=false +window/size/always_on_top=true +window/size/extend_to_title=true diff --git a/src/bin/cli.rs b/src/bin/cli.rs deleted file mode 100644 index abcb977..0000000 --- a/src/bin/cli.rs +++ /dev/null @@ -1,33 +0,0 @@ -use instinct::{process_image, save_image}; -use std::thread; - -fn main() { - let mut files = std::env::args().collect::>(); - files.remove(0); - println!("\nšŸ“ø Starting instinct processing ✨"); - - let mut threads = vec![]; - for file in files { - threads.push(thread::spawn(move || { - let path = std::path::Path::new(&file); - println!("šŸŽžļø Processing {:?}", path.file_name().unwrap()); - let image = process_image(path); - let mut new_file_path = std::path::PathBuf::from(path); - new_file_path.set_file_name(format!( - "{} - instagram compatible.jpg", - path.file_name() - .unwrap() - .to_str() - .unwrap() - .replace(".jpg", "") - )); - - save_image(image, new_file_path.to_str().unwrap()); - println!("šŸ–¼ļø done w/ file, wrote to: {new_file_path:#?}"); - })); - } - - for handle in threads { - handle.join().unwrap(); - } -} diff --git a/src/lib.rs b/src/lib.rs index f733d5e..e40039d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,12 +14,19 @@ use photon_rs::{ // TODO: Add option for 4:5 export and 1:1 export pub fn process_image(path: &std::path::Path) -> PhotonImage { - let mut image = open_image(path.to_str().unwrap()).unwrap(); + let mut image = open_image(path.to_str().expect("to parse path to string")) + .expect("to open image with Photon"); + println!("opened image"); let padding = 36; let intended_size_in_frame = 1080 - padding; - let mut background = open_image("background.jpg").unwrap(); + let mut background = PhotonImage::new_from_byteslice({ + let mut image = + Image::create(1080, 1080, false, Format::RGB8).expect("to be able to create an image"); + image.fill(Color::WHITE); + image.save_jpg_to_buffer().to_vec() + }); let width = image.get_width(); let height = image.get_height(); @@ -69,8 +76,6 @@ pub fn process_image(path: &std::path::Path) -> PhotonImage { ); } - // save_image(background, "result.jpg").unwrap(); - // println!("done!"); background } @@ -80,14 +85,98 @@ pub fn save_image(image: PhotonImage, path: &str) { let width = image.get_width(); let height = image.get_height(); - let buffer = ImageBuffer::from_vec(width, height, raw_pixels).unwrap(); + println!("attempting to make image buffer"); + let buffer = ImageBuffer::from_vec(width, height, raw_pixels) + .expect("to be able to build an image buffer"); let image = ImageRgba8(buffer).into_rgb8(); - let file = std::fs::File::create(path).unwrap(); + println!("attempting to save to {path:#?}"); + let file = std::fs::File::create(path).expect("to able to create a file"); let ref mut buff = BufWriter::new(file); let mut encoder = JpegEncoder::new_with_quality(buff, 100); encoder .encode(&image.as_bytes(), width, height, Rgb8) - .unwrap(); + .expect("to encode the JPEG to a file"); + println!("saved to {path:#?}"); +} + +use godot::{ + engine::{image::Format, Image}, + prelude::*, +}; + +struct PhotoProcessingExtension; + +#[gdextension] +unsafe impl ExtensionLibrary for PhotoProcessingExtension {} + +#[derive(GodotClass)] +#[class(base=Node)] +struct PhotoProcess { + base: Base, +} + +#[godot_api] +impl INode for PhotoProcess { + fn init(base: Base) -> Self { + Self { base } + } +} + +#[godot_api] +impl PhotoProcess { + #[signal] + fn done_with_photo(path: GString); + + #[func] + fn process_files(&mut self, files: PackedStringArray) { + godot_print!("attempting to process files: {files:#?}! ✨"); + let mut threads = vec![]; + let instance_id = self.base().instance_id(); + + for file in files.to_vec() { + godot_print!("attempting to process file: {file:#?}! šŸ¤”"); + let file = file.to_string().clone(); + + threads.push(std::thread::spawn(move || { + let path = std::path::Path::new(&file); + println!( + "šŸŽžļø Processing {:?}", + path.file_name().expect("to turn path into a filename") + ); + let image = process_image(path); + println!("Done processing!"); + let mut new_file_path = std::path::PathBuf::from(path); + new_file_path.set_file_name(format!( + "{} - instagram compatible.jpg", + path.file_name() + .expect("to get path filename") + .to_str() + .expect("to convert filename to string") + .replace(".jpg", "") + )); + + save_image( + image, + new_file_path + .to_str() + .expect("to turn new_path into a string"), + ); + + Gd::::from_instance_id(instance_id).call_deferred( + "emit_signal".into(), + &[ + Variant::from("done_with_photo"), + Variant::from(new_file_path.to_str().unwrap()), + ], + ); + println!("šŸ–¼ļø done w/ file, wrote to: {new_file_path:#?}"); + })); + } + + // for handle in threads { + // handle.join().expect("to join threads"); + // } + } }