From cd49ba8afc2a0a80dd285a26b5b1f0ce79b9f372 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Wed, 17 Jun 2020 19:11:20 +0200 Subject: [PATCH] list all artworks from res:// I cannot simply explore the res:// filesystem on Android. As a workaround, I create a static list of embedded artworks. --- src/FileList.gd | 32 ++++++++------- src/ImagePicker.gd | 16 +++++++- src/ImagePicker.tscn | 20 +++++++--- src/Main.tscn | 2 +- src/NewGamePanel.gd | 91 ++++++++++++++++++++----------------------- src/NewGamePanel.tscn | 21 ++-------- src/Taquin.gd | 28 +++++-------- src/Utils.gd | 9 +++++ 8 files changed, 112 insertions(+), 107 deletions(-) diff --git a/src/FileList.gd b/src/FileList.gd index d8dde55..fb33d46 100644 --- a/src/FileList.gd +++ b/src/FileList.gd @@ -1,23 +1,24 @@ extends ItemList signal file_selected(path) +signal texture_selected(texture) var _parent_display_name := "" var _sep := "/" var _dir := Directory.new() -export var root_dir: String = OS.get_system_dir(OS.SYSTEM_DIR_PICTURES) +export var root_dir: String export var walkable := false export var folder_texture: Texture = null export var parent_folder_texture: Texture = null -# Called when the node enters the scene tree for the first time. func _ready(): - if root_dir != null: + print_debug("root dir: ", root_dir) + if root_dir != null and not root_dir.empty(): populate(root_dir) func populate(dir: String) -> void: - print_debug(dir) + print_debug("populate ", dir) clear() if _dir.change_dir(dir) != OK: @@ -49,12 +50,17 @@ func populate(dir: String) -> void: sort_items_by_text() func _on_FileList_item_selected(index): - var item_text := get_item_text(index) - if item_text == _parent_display_name: - item_text = ".." - if _dir.dir_exists(item_text): - populate(item_text) - else: - var full_path = root_dir + _sep + item_text - print_debug(full_path) - emit_signal("file_selected", full_path) + emit_signal("texture_selected", get_item_icon(index)) + +# if root_dir == null or root_dir.empty(): +# emit_signal("texture_selected", get_item_icon(index)) +# return +# +# var item_text := get_item_text(index) +# if item_text == _parent_display_name: +# item_text = ".." +# if _dir.dir_exists(item_text): +# populate(item_text) +# else: +# var full_path = root_dir + _sep + item_text +# emit_signal("file_selected", full_path) diff --git a/src/ImagePicker.gd b/src/ImagePicker.gd index d8b1a13..0a251e9 100644 --- a/src/ImagePicker.gd +++ b/src/ImagePicker.gd @@ -3,11 +3,25 @@ class_name ImagePicker extends Panel signal file_selected(path) +signal texture_selected(texture) +signal canceled() + +var _fs_tab_index := 1 onready var fs_list := $VBoxContainer/TabContainer/Filesystem/FileList func _ready(): - fs_list.populate(OS.get_system_dir(OS.SYSTEM_DIR_PICTURES)) + # TODO: fix Android + if OS.get_name() == "Android": + $VBoxContainer/TabContainer.set_tab_disabled(_fs_tab_index, true) + else: + fs_list.populate(OS.get_system_dir(OS.SYSTEM_DIR_PICTURES)) func _on_FileList_file_selected(path): emit_signal("file_selected", path) + +func _on_FileList_texture_selected(texture): + emit_signal("texture_selected", texture) + +func _on_Cancel_pressed(): + emit_signal("canceled") diff --git a/src/ImagePicker.tscn b/src/ImagePicker.tscn index f3e650f..c1c65dc 100644 --- a/src/ImagePicker.tscn +++ b/src/ImagePicker.tscn @@ -1,7 +1,10 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://src/ImagePicker.gd" type="Script" id=1] [ext_resource path="res://src/FileList.tscn" type="PackedScene" id=2] +[ext_resource path="res://assets/artworks/hokusai.jpg" type="Texture" id=3] +[ext_resource path="res://assets/artworks/escher_convex_concave.jpg" type="Texture" id=4] +[ext_resource path="res://assets/artworks/escher_lizards.jpg" type="Texture" id=5] [node name="ImagePicker" type="Panel"] anchor_right = 1.0 @@ -29,7 +32,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="Taqin" type="Tabs" parent="VBoxContainer/TabContainer"] +[node name="App" type="Tabs" parent="VBoxContainer/TabContainer"] anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 8.0 @@ -38,7 +41,11 @@ margin_right = -8.0 margin_bottom = -8.0 rect_clip_content = true -[node name="FileList" parent="VBoxContainer/TabContainer/Taqin" instance=ExtResource( 2 )] +[node name="FileList" parent="VBoxContainer/TabContainer/App" instance=ExtResource( 2 )] +items = [ "", ExtResource( 4 ), false, "", ExtResource( 5 ), false, "", ExtResource( 3 ), false ] +root_dir = "" +folder_texture = null +parent_folder_texture = null [node name="Filesystem" type="Tabs" parent="VBoxContainer/TabContainer"] visible = false @@ -50,10 +57,10 @@ margin_right = -8.0 margin_bottom = -8.0 [node name="FileList" parent="VBoxContainer/TabContainer/Filesystem" instance=ExtResource( 2 )] -root_dir = "/home/fabs/Pictures" +root_dir = "" walkable = true -[node name="Button" type="Button" parent="VBoxContainer"] +[node name="Cancel" type="Button" parent="VBoxContainer"] margin_top = 520.0 margin_right = 1024.0 margin_bottom = 600.0 @@ -65,5 +72,6 @@ __meta__ = { } [connection signal="item_rect_changed" from="." to="." method="_on_ImagePicker_item_rect_changed"] [connection signal="resized" from="." to="." method="_on_ImagePicker_resized"] -[connection signal="file_selected" from="VBoxContainer/TabContainer/Taqin/FileList" to="." method="_on_FileList_file_selected"] +[connection signal="texture_selected" from="VBoxContainer/TabContainer/App/FileList" to="." method="_on_FileList_texture_selected"] [connection signal="file_selected" from="VBoxContainer/TabContainer/Filesystem/FileList" to="." method="_on_FileList_file_selected"] +[connection signal="pressed" from="VBoxContainer/Cancel" to="." method="_on_Cancel_pressed"] diff --git a/src/Main.tscn b/src/Main.tscn index d5af625..35511bf 100644 --- a/src/Main.tscn +++ b/src/Main.tscn @@ -75,7 +75,7 @@ rect_min_size = Vector2( 0, 70 ) text = "Hints" [node name="NewGamePanel" parent="." instance=ExtResource( 3 )] -rect_pivot_offset = Vector2( 203, 134 ) +rect_pivot_offset = Vector2( 4, 4 ) [connection signal="state_changed" from="GridContainer/Taquin" to="." method="_on_Taquin_state_changed"] [connection signal="pressed" from="GridContainer/VBoxContainer/New Game" to="." method="_on_New_game_pressed"] [connection signal="button_down" from="GridContainer/VBoxContainer/Hints" to="GridContainer/Taquin" method="_on_Hints_button_down"] diff --git a/src/NewGamePanel.gd b/src/NewGamePanel.gd index 2e8dd2f..a504a31 100644 --- a/src/NewGamePanel.gd +++ b/src/NewGamePanel.gd @@ -2,9 +2,10 @@ tool class_name NewGamePanel extends PopupPanel -signal start_triggered(config) +signal start_triggered(config, texture) const pref_path := "user://preferences.cfg" +const cached_artwork_path := "user://artwork.dat" const easy_columns := 3 const easy_rows := 3 @@ -15,19 +16,17 @@ const normal_iterations := 10 const hard_columns := 5 const hard_rows := 5 const hard_iterations := 30 -const default_artwork_path := "res://assets/hokusai.jpg" const Utils = preload("res://src/Utils.gd") export var window_scale_factor = 0.9 # how big the popup will be compared to screen +export var default_artwork_texture: Texture var preferences = ConfigFile.new() var fade_duration = 0.2 var fade_scale_factor = 0.9 var flip_duration = 0.4 -var _artwork_path: String = default_artwork_path - onready var popup = $"." onready var panel = $Panel onready var edit_panel = $EditPanel @@ -153,6 +152,15 @@ func _update_description(): desc.add_text("%d" % [iterations]) desc.pop() +func _set_artwork(tex: Texture) -> void: + preview.texture = tex + + var file = File.new() + if file.open(cached_artwork_path, File.WRITE) != OK: + assert(false) + file.store_var(tex.get_data(), true) + file.close() + # # Signals # @@ -180,12 +188,10 @@ func _on_Start_pressed(): preferences.set_value("game", "columns", columns_spinbox.value) preferences.set_value("game", "rows", rows_spinbox.value) preferences.set_value("game", "shuffle_iterations", iterations_spinbox.value) - - preferences.set_value("game", "artwork_path", _artwork_path) preferences.save(pref_path) - emit_signal("start_triggered", preferences) + emit_signal("start_triggered", preferences, preview.texture) fade_out() func _on_NewGamePanel_about_to_show(): @@ -201,9 +207,9 @@ func _on_NewGamePanel_about_to_show(): _update_description() - _artwork_path = preferences.get_value("game", "artwork_path", default_artwork_path) - print_debug("artwork path: ", _artwork_path) - preview.texture = Utils.load_texture_from_path(_artwork_path) + preview.texture = Utils.deserialize_texture(cached_artwork_path) + if preview.texture == null: + preview.texture = default_artwork_texture # $Panel/Start.grab_focus() fade_in() @@ -236,45 +242,32 @@ func _on_Custom_pressed(): func _on_LoadImage_pressed(): flip_over($ImagePicker) -# if OS.get_name() == "Android": -# $FileDialog.current_dir = "/storage/emulated/0/" -# $FileDialog.popup_centered(rect_size) -func _on_FileDialog_file_selected(path: String): - var texture := load(path) - if texture == null: - print_debug("Cannot load image from path: ", path) - return - preview.texture = texture - - var directory = Directory.new() - # TODO: remove previous artwork.png, artwork.jpg files - var cached_artwork_path := "user://artwork.%s" % [path.get_extension()] - var error = directory.copy(path, cached_artwork_path) - if error != OK: - print_debug("Cannot cache image") - _artwork_path = path - else: - _artwork_path = cached_artwork_path +#func _on_ImagePicker_file_selected(path): +# print_debug(path) +# var texture := load(path) +# if texture == null: +# print_debug("Cannot load image from path: ", path) +# return +# preview.texture = texture +# +# var file = File.new() +# file.store_var(texture) +# +# var directory = Directory.new() +# # TODO: remove previous artwork.png, artwork.jpg files +# var cached_artwork_path := "user://artwork.%s" % [path.get_extension()] +# var error = directory.copy(path, cached_artwork_path) +# if error != OK: +# print_debug("Cannot cache image") +# _artwork_path = path +# else: +# _artwork_path = cached_artwork_path +# flip_back($ImagePicker) -func _on_FileDialog_dir_selected(dir): - print_debug("dir selected") - -func _on_ImagePicker_file_selected(path): - print_debug(path) - var texture := load(path) - if texture == null: - print_debug("Cannot load image from path: ", path) - return - preview.texture = texture - - var directory = Directory.new() - # TODO: remove previous artwork.png, artwork.jpg files - var cached_artwork_path := "user://artwork.%s" % [path.get_extension()] - var error = directory.copy(path, cached_artwork_path) - if error != OK: - print_debug("Cannot cache image") - _artwork_path = path - else: - _artwork_path = cached_artwork_path +func _on_ImagePicker_canceled(): + flip_back($ImagePicker) + +func _on_ImagePicker_texture_selected(texture): + _set_artwork(texture) flip_back($ImagePicker) diff --git a/src/NewGamePanel.tscn b/src/NewGamePanel.tscn index 0ea1cea..b89404f 100644 --- a/src/NewGamePanel.tscn +++ b/src/NewGamePanel.tscn @@ -381,23 +381,9 @@ margin_left = 4.0 margin_top = 4.0 margin_right = -4.0 margin_bottom = -4.0 +rect_clip_content = true [node name="Tween" type="Tween" parent="."] - -[node name="FileDialog" type="FileDialog" parent="."] -margin_left = 4.0 -margin_top = 4.0 -margin_right = 1020.0 -margin_bottom = 596.0 -window_title = "Open a File" -mode = 0 -access = 2 -filters = PoolStringArray( "*.png ; PNG Images", "*.jpg, *.jpeg ; JPEG Images" ) -current_dir = "/home/fabs/Code/taqin" -current_path = "/home/fabs/Code/taqin/" -__meta__ = { -"_edit_use_anchors_": false -} [connection signal="about_to_show" from="." to="." method="_on_NewGamePanel_about_to_show"] [connection signal="pressed" from="Panel/VBoxContainer/Difficulty/Easy" to="." method="_on_Easy_pressed"] [connection signal="pressed" from="Panel/VBoxContainer/Difficulty/Normal" to="." method="_on_Normal_pressed"] @@ -408,6 +394,5 @@ __meta__ = { [connection signal="pressed" from="Panel/Cancel" to="." method="_on_Cancel_pressed"] [connection signal="pressed" from="EditPanel/Cancel" to="." method="_on_Edit_Cancel_pressed"] [connection signal="pressed" from="EditPanel/Save" to="." method="_on_Edit_Save_pressed"] -[connection signal="file_selected" from="ImagePicker" to="." method="_on_ImagePicker_file_selected"] -[connection signal="dir_selected" from="FileDialog" to="." method="_on_FileDialog_dir_selected"] -[connection signal="file_selected" from="FileDialog" to="." method="_on_FileDialog_file_selected"] +[connection signal="canceled" from="ImagePicker" to="." method="_on_ImagePicker_canceled"] +[connection signal="texture_selected" from="ImagePicker" to="." method="_on_ImagePicker_texture_selected"] diff --git a/src/Taquin.gd b/src/Taquin.gd index 60e487a..abcd996 100644 --- a/src/Taquin.gd +++ b/src/Taquin.gd @@ -52,7 +52,7 @@ var local_max_position := Vector2.ZERO var hint_active := false setget set_hint_active, get_hint_active -var _artwork_path := NewGamePanel.default_artwork_path +#var _artwork_path := NewGamePanel.default_artwork_path onready var hint_tween = $HintTween @@ -87,8 +87,7 @@ func _ready() -> void: if autoload_fresh_game: start_fresh() if artwork_texture == null: - print_debug("Load texture from: ", NewGamePanel.default_artwork_path) - artwork_texture = Utils.load_texture_from_path(NewGamePanel.default_artwork_path) + artwork_texture = NewGamePanel.default_artwork_texture new_game(NewGamePanel.normal_columns, NewGamePanel.normal_rows, NewGamePanel.normal_iterations, artwork_texture) func _unhandled_input(event): @@ -372,23 +371,19 @@ func save() -> Dictionary: "columns": columns, "pieces": serialized_pieces, "hidden_piece": serialized_pieces.size(), - "artwork_path": _artwork_path, +# "artwork_path": _artwork_path, } func load(saved_state) -> bool: print("load save state: ", saved_state) - if not saved_state.has_all(["rows", "columns", "pieces", "hidden_piece", "artwork_path"]): + if not saved_state.has_all(["rows", "columns", "pieces", "hidden_piece"]): assert(false, "Invalid save state") return false rows = saved_state["rows"] columns = saved_state["columns"] - - var texture := Utils.load_texture_from_path(saved_state["artwork_path"]) - if texture == null: - return false - artwork_texture = texture - _artwork_path = saved_state["artwork_path"] - print_debug("Load artwork from: ", _artwork_path) + + artwork_texture = Utils.deserialize_texture(NewGamePanel.cached_artwork_path) + assert(artwork_texture != null) init(saved_state["pieces"], saved_state["hidden_piece"], artwork_texture) return true @@ -498,20 +493,15 @@ func _on_AnimationPlayer_animation_finished(anim_name): "MovingPiece": commit_slide(true, true) -func _on_NewGamePanel_start_triggered(preferences): +func _on_NewGamePanel_start_triggered(preferences, texture): var difficulty_mode = preferences.get_value("game", "difficulty", "normal") print_debug("difficulty mode: ", difficulty_mode) var columns = preferences.get_value("game", "columns", NewGamePanel.normal_columns) var rows = preferences.get_value("game", "rows", NewGamePanel.normal_rows) var shuffle_iterations = preferences.get_value("game", "shuffle_iterations", NewGamePanel.normal_iterations) - var artwork_path = preferences.get_value("game", "artwork_path", NewGamePanel.default_artwork_path) - print_debug("new game triggered with artwork path: ", artwork_path) - artwork_texture = Utils.load_texture_from_path(artwork_path) - if artwork_path != null: - _artwork_path = artwork_path + artwork_texture = texture new_game(columns, rows, shuffle_iterations, artwork_texture) - func _on_Hints_button_down(): if not hint_active: show_hints() diff --git a/src/Utils.gd b/src/Utils.gd index 2452dc2..3ed47ec 100644 --- a/src/Utils.gd +++ b/src/Utils.gd @@ -7,3 +7,12 @@ static func load_texture_from_path(path: String) -> Texture: texture.create_from_image(img) return texture +static func deserialize_texture(path: String) -> Texture: + var file := File.new() + if file.open(path, File.READ) != OK: + return null + var img: Image = file.get_var(true) + file.close() + var img_tex = ImageTexture.new() + img_tex.create_from_image(img) + return img_tex