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.
This commit is contained in:
Fabien Freling 2020-06-17 19:11:20 +02:00
parent e90eb40630
commit cd49ba8afc
8 changed files with 112 additions and 107 deletions

View file

@ -1,23 +1,24 @@
extends ItemList extends ItemList
signal file_selected(path) signal file_selected(path)
signal texture_selected(texture)
var _parent_display_name := "<parent directory>" var _parent_display_name := "<parent directory>"
var _sep := "/" var _sep := "/"
var _dir := Directory.new() 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 walkable := false
export var folder_texture: Texture = null export var folder_texture: Texture = null
export var parent_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(): func _ready():
if root_dir != null: print_debug("root dir: ", root_dir)
if root_dir != null and not root_dir.empty():
populate(root_dir) populate(root_dir)
func populate(dir: String) -> void: func populate(dir: String) -> void:
print_debug(dir) print_debug("populate ", dir)
clear() clear()
if _dir.change_dir(dir) != OK: if _dir.change_dir(dir) != OK:
@ -49,12 +50,17 @@ func populate(dir: String) -> void:
sort_items_by_text() sort_items_by_text()
func _on_FileList_item_selected(index): func _on_FileList_item_selected(index):
var item_text := get_item_text(index) emit_signal("texture_selected", get_item_icon(index))
if item_text == _parent_display_name:
item_text = ".." # if root_dir == null or root_dir.empty():
if _dir.dir_exists(item_text): # emit_signal("texture_selected", get_item_icon(index))
populate(item_text) # return
else: #
var full_path = root_dir + _sep + item_text # var item_text := get_item_text(index)
print_debug(full_path) # if item_text == _parent_display_name:
emit_signal("file_selected", full_path) # 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)

View file

@ -3,11 +3,25 @@ class_name ImagePicker
extends Panel extends Panel
signal file_selected(path) signal file_selected(path)
signal texture_selected(texture)
signal canceled()
var _fs_tab_index := 1
onready var fs_list := $VBoxContainer/TabContainer/Filesystem/FileList onready var fs_list := $VBoxContainer/TabContainer/Filesystem/FileList
func _ready(): 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): func _on_FileList_file_selected(path):
emit_signal("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")

View file

@ -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/ImagePicker.gd" type="Script" id=1]
[ext_resource path="res://src/FileList.tscn" type="PackedScene" id=2] [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"] [node name="ImagePicker" type="Panel"]
anchor_right = 1.0 anchor_right = 1.0
@ -29,7 +32,7 @@ __meta__ = {
"_edit_use_anchors_": false "_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_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_left = 8.0 margin_left = 8.0
@ -38,7 +41,11 @@ margin_right = -8.0
margin_bottom = -8.0 margin_bottom = -8.0
rect_clip_content = true 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"] [node name="Filesystem" type="Tabs" parent="VBoxContainer/TabContainer"]
visible = false visible = false
@ -50,10 +57,10 @@ margin_right = -8.0
margin_bottom = -8.0 margin_bottom = -8.0
[node name="FileList" parent="VBoxContainer/TabContainer/Filesystem" instance=ExtResource( 2 )] [node name="FileList" parent="VBoxContainer/TabContainer/Filesystem" instance=ExtResource( 2 )]
root_dir = "/home/fabs/Pictures" root_dir = ""
walkable = true walkable = true
[node name="Button" type="Button" parent="VBoxContainer"] [node name="Cancel" type="Button" parent="VBoxContainer"]
margin_top = 520.0 margin_top = 520.0
margin_right = 1024.0 margin_right = 1024.0
margin_bottom = 600.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="item_rect_changed" from="." to="." method="_on_ImagePicker_item_rect_changed"]
[connection signal="resized" from="." to="." method="_on_ImagePicker_resized"] [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="file_selected" from="VBoxContainer/TabContainer/Filesystem/FileList" to="." method="_on_FileList_file_selected"]
[connection signal="pressed" from="VBoxContainer/Cancel" to="." method="_on_Cancel_pressed"]

View file

@ -75,7 +75,7 @@ rect_min_size = Vector2( 0, 70 )
text = "Hints" text = "Hints"
[node name="NewGamePanel" parent="." instance=ExtResource( 3 )] [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="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="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"] [connection signal="button_down" from="GridContainer/VBoxContainer/Hints" to="GridContainer/Taquin" method="_on_Hints_button_down"]

View file

@ -2,9 +2,10 @@ tool
class_name NewGamePanel class_name NewGamePanel
extends PopupPanel extends PopupPanel
signal start_triggered(config) signal start_triggered(config, texture)
const pref_path := "user://preferences.cfg" const pref_path := "user://preferences.cfg"
const cached_artwork_path := "user://artwork.dat"
const easy_columns := 3 const easy_columns := 3
const easy_rows := 3 const easy_rows := 3
@ -15,19 +16,17 @@ const normal_iterations := 10
const hard_columns := 5 const hard_columns := 5
const hard_rows := 5 const hard_rows := 5
const hard_iterations := 30 const hard_iterations := 30
const default_artwork_path := "res://assets/hokusai.jpg"
const Utils = preload("res://src/Utils.gd") 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 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 preferences = ConfigFile.new()
var fade_duration = 0.2 var fade_duration = 0.2
var fade_scale_factor = 0.9 var fade_scale_factor = 0.9
var flip_duration = 0.4 var flip_duration = 0.4
var _artwork_path: String = default_artwork_path
onready var popup = $"." onready var popup = $"."
onready var panel = $Panel onready var panel = $Panel
onready var edit_panel = $EditPanel onready var edit_panel = $EditPanel
@ -153,6 +152,15 @@ func _update_description():
desc.add_text("%d" % [iterations]) desc.add_text("%d" % [iterations])
desc.pop() 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 # Signals
# #
@ -180,12 +188,10 @@ func _on_Start_pressed():
preferences.set_value("game", "columns", columns_spinbox.value) preferences.set_value("game", "columns", columns_spinbox.value)
preferences.set_value("game", "rows", rows_spinbox.value) preferences.set_value("game", "rows", rows_spinbox.value)
preferences.set_value("game", "shuffle_iterations", iterations_spinbox.value) preferences.set_value("game", "shuffle_iterations", iterations_spinbox.value)
preferences.set_value("game", "artwork_path", _artwork_path)
preferences.save(pref_path) preferences.save(pref_path)
emit_signal("start_triggered", preferences) emit_signal("start_triggered", preferences, preview.texture)
fade_out() fade_out()
func _on_NewGamePanel_about_to_show(): func _on_NewGamePanel_about_to_show():
@ -201,9 +207,9 @@ func _on_NewGamePanel_about_to_show():
_update_description() _update_description()
_artwork_path = preferences.get_value("game", "artwork_path", default_artwork_path) preview.texture = Utils.deserialize_texture(cached_artwork_path)
print_debug("artwork path: ", _artwork_path) if preview.texture == null:
preview.texture = Utils.load_texture_from_path(_artwork_path) preview.texture = default_artwork_texture
# $Panel/Start.grab_focus() # $Panel/Start.grab_focus()
fade_in() fade_in()
@ -236,45 +242,32 @@ func _on_Custom_pressed():
func _on_LoadImage_pressed(): func _on_LoadImage_pressed():
flip_over($ImagePicker) 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): #func _on_ImagePicker_file_selected(path):
var texture := load(path) # print_debug(path)
if texture == null: # var texture := load(path)
print_debug("Cannot load image from path: ", path) # if texture == null:
return # print_debug("Cannot load image from path: ", path)
preview.texture = texture # return
# preview.texture = texture
var directory = Directory.new() #
# TODO: remove previous artwork.png, artwork.jpg files # var file = File.new()
var cached_artwork_path := "user://artwork.%s" % [path.get_extension()] # file.store_var(texture)
var error = directory.copy(path, cached_artwork_path) #
if error != OK: # var directory = Directory.new()
print_debug("Cannot cache image") # # TODO: remove previous artwork.png, artwork.jpg files
_artwork_path = path # var cached_artwork_path := "user://artwork.%s" % [path.get_extension()]
else: # var error = directory.copy(path, cached_artwork_path)
_artwork_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): func _on_ImagePicker_canceled():
print_debug("dir selected") flip_back($ImagePicker)
func _on_ImagePicker_file_selected(path): func _on_ImagePicker_texture_selected(texture):
print_debug(path) _set_artwork(texture)
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
flip_back($ImagePicker) flip_back($ImagePicker)

View file

@ -381,23 +381,9 @@ margin_left = 4.0
margin_top = 4.0 margin_top = 4.0
margin_right = -4.0 margin_right = -4.0
margin_bottom = -4.0 margin_bottom = -4.0
rect_clip_content = true
[node name="Tween" type="Tween" parent="."] [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="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/Easy" to="." method="_on_Easy_pressed"]
[connection signal="pressed" from="Panel/VBoxContainer/Difficulty/Normal" to="." method="_on_Normal_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="Panel/Cancel" to="." method="_on_Cancel_pressed"]
[connection signal="pressed" from="EditPanel/Cancel" to="." method="_on_Edit_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="pressed" from="EditPanel/Save" to="." method="_on_Edit_Save_pressed"]
[connection signal="file_selected" from="ImagePicker" to="." method="_on_ImagePicker_file_selected"] [connection signal="canceled" from="ImagePicker" to="." method="_on_ImagePicker_canceled"]
[connection signal="dir_selected" from="FileDialog" to="." method="_on_FileDialog_dir_selected"] [connection signal="texture_selected" from="ImagePicker" to="." method="_on_ImagePicker_texture_selected"]
[connection signal="file_selected" from="FileDialog" to="." method="_on_FileDialog_file_selected"]

View file

@ -52,7 +52,7 @@ var local_max_position := Vector2.ZERO
var hint_active := false setget set_hint_active, get_hint_active 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 onready var hint_tween = $HintTween
@ -87,8 +87,7 @@ func _ready() -> void:
if autoload_fresh_game: if autoload_fresh_game:
start_fresh() start_fresh()
if artwork_texture == null: if artwork_texture == null:
print_debug("Load texture from: ", NewGamePanel.default_artwork_path) artwork_texture = NewGamePanel.default_artwork_texture
artwork_texture = Utils.load_texture_from_path(NewGamePanel.default_artwork_path)
new_game(NewGamePanel.normal_columns, NewGamePanel.normal_rows, NewGamePanel.normal_iterations, artwork_texture) new_game(NewGamePanel.normal_columns, NewGamePanel.normal_rows, NewGamePanel.normal_iterations, artwork_texture)
func _unhandled_input(event): func _unhandled_input(event):
@ -372,23 +371,19 @@ func save() -> Dictionary:
"columns": columns, "columns": columns,
"pieces": serialized_pieces, "pieces": serialized_pieces,
"hidden_piece": serialized_pieces.size(), "hidden_piece": serialized_pieces.size(),
"artwork_path": _artwork_path, # "artwork_path": _artwork_path,
} }
func load(saved_state) -> bool: func load(saved_state) -> bool:
print("load save state: ", saved_state) 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") assert(false, "Invalid save state")
return false return false
rows = saved_state["rows"] rows = saved_state["rows"]
columns = saved_state["columns"] columns = saved_state["columns"]
var texture := Utils.load_texture_from_path(saved_state["artwork_path"]) artwork_texture = Utils.deserialize_texture(NewGamePanel.cached_artwork_path)
if texture == null: assert(artwork_texture != null)
return false
artwork_texture = texture
_artwork_path = saved_state["artwork_path"]
print_debug("Load artwork from: ", _artwork_path)
init(saved_state["pieces"], saved_state["hidden_piece"], artwork_texture) init(saved_state["pieces"], saved_state["hidden_piece"], artwork_texture)
return true return true
@ -498,20 +493,15 @@ func _on_AnimationPlayer_animation_finished(anim_name):
"MovingPiece": "MovingPiece":
commit_slide(true, true) 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") var difficulty_mode = preferences.get_value("game", "difficulty", "normal")
print_debug("difficulty mode: ", difficulty_mode) print_debug("difficulty mode: ", difficulty_mode)
var columns = preferences.get_value("game", "columns", NewGamePanel.normal_columns) var columns = preferences.get_value("game", "columns", NewGamePanel.normal_columns)
var rows = preferences.get_value("game", "rows", NewGamePanel.normal_rows) var rows = preferences.get_value("game", "rows", NewGamePanel.normal_rows)
var shuffle_iterations = preferences.get_value("game", "shuffle_iterations", NewGamePanel.normal_iterations) 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) artwork_texture = texture
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
new_game(columns, rows, shuffle_iterations, artwork_texture) new_game(columns, rows, shuffle_iterations, artwork_texture)
func _on_Hints_button_down(): func _on_Hints_button_down():
if not hint_active: if not hint_active:
show_hints() show_hints()

View file

@ -7,3 +7,12 @@ static func load_texture_from_path(path: String) -> Texture:
texture.create_from_image(img) texture.create_from_image(img)
return texture 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