diff --git a/mai83A8.tmp b/mai83A8.tmp new file mode 100644 index 0000000..3174011 --- /dev/null +++ b/mai83A8.tmp @@ -0,0 +1,291 @@ +[gd_scene load_steps=5 format=3 uid="uid://cefaf32sglsey"] + +[ext_resource type="Script" path="res://main.gd" id="1_ksdsl"] + +[sub_resource type="Animation" id="Animation_ise3b"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Panel/HBoxContainer/ProfilePanel:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Panel/HBoxContainer/ProfilePanel:size_flags_stretch_ratio") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Panel/HBoxContainer/ProfilePanel:modulate") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 0)] +} + +[sub_resource type="Animation" id="Animation_m3lq2"] +resource_name = "switch_profile_view" +length = 0.15 +step = 0.05 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Panel/HBoxContainer/ProfilePanel:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.05, 0.15), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 1, +"values": [false, true, true] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Panel/HBoxContainer/ProfilePanel:size_flags_stretch_ratio") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0.05, 0.15), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 1.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Panel/HBoxContainer/ProfilePanel:modulate") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.05, 0.15), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 0), Color(1, 1, 1, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_s7q63"] +_data = { +"RESET": SubResource("Animation_ise3b"), +"switch_profile_view": SubResource("Animation_m3lq2") +} + +[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 +script = ExtResource("1_ksdsl") + +[node name="Anim" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_s7q63") +} + +[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="HBoxContainer" type="HBoxContainer" parent="Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VSeparator" type="VSeparator" parent="Panel/HBoxContainer"] +self_modulate = Color(1, 1, 1, 0) +layout_mode = 2 + +[node name="Cont" type="VBoxContainer" parent="Panel/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HSeparator" type="HSeparator" parent="Panel/HBoxContainer/Cont"] +self_modulate = Color(1, 1, 1, 0) +layout_mode = 2 + +[node name="GameTab" type="HBoxContainer" parent="Panel/HBoxContainer/Cont"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 + +[node name="GameIcon" type="TextureRect" parent="Panel/HBoxContainer/Cont/GameTab"] +unique_name_in_owner = true +custom_minimum_size = Vector2(64, 0) +layout_mode = 2 +expand_mode = 3 +stretch_mode = 4 + +[node name="GameName" type="Label" parent="Panel/HBoxContainer/Cont/GameTab"] +unique_name_in_owner = true +layout_mode = 2 +text = "Selected Game Name" + +[node name="VSeparator" type="VSeparator" parent="Panel/HBoxContainer/Cont/GameTab"] +self_modulate = Color(1, 1, 1, 0) +custom_minimum_size = Vector2(64, 0) +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Panel/HBoxContainer/Cont/GameTab"] +layout_mode = 2 +alignment = 1 + +[node name="ProfileAdd" type="Button" parent="Panel/HBoxContainer/Cont/GameTab/VBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +text = "Add profile" + +[node name="VSeparator2" type="VSeparator" parent="Panel/HBoxContainer/Cont/GameTab"] +self_modulate = Color(1, 1, 1, 0) +custom_minimum_size = Vector2(16, 0) +layout_mode = 2 + +[node name="VBoxContainer2" type="VBoxContainer" parent="Panel/HBoxContainer/Cont/GameTab"] +layout_mode = 2 +alignment = 1 + +[node name="GameClose" type="Button" parent="Panel/HBoxContainer/Cont/GameTab/VBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +text = "Return" + +[node name="Games" type="ItemList" parent="Panel/HBoxContainer/Cont"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 4.0 +auto_height = true +max_columns = 8 +same_column_width = true +icon_mode = 0 + +[node name="Profiles" type="ItemList" parent="Panel/HBoxContainer/Cont"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 4.0 +auto_height = true +max_columns = 8 +same_column_width = true +icon_mode = 0 + +[node name="HSeparator3" type="HSeparator" parent="Panel/HBoxContainer/Cont"] +self_modulate = Color(1, 1, 1, 0) +layout_mode = 2 + +[node name="VSeparator2" type="VSeparator" parent="Panel/HBoxContainer"] +self_modulate = Color(1, 1, 1, 0) +layout_mode = 2 + +[node name="ProfilePanel" type="VBoxContainer" parent="Panel/HBoxContainer"] +unique_name_in_owner = true +visible = false +modulate = Color(1, 1, 1, 0) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.0 + +[node name="ProfileIcon" type="TextureRect" parent="Panel/HBoxContainer/ProfilePanel"] +unique_name_in_owner = true +custom_minimum_size = Vector2(96, 96) +layout_mode = 2 +expand_mode = 3 +stretch_mode = 4 + +[node name="ProfileName" type="Label" parent="Panel/HBoxContainer/ProfilePanel"] +unique_name_in_owner = true +layout_mode = 2 +text = "Profile Name" + +[node name="ProfileDesc" type="Label" parent="Panel/HBoxContainer/ProfilePanel"] +unique_name_in_owner = true +layout_mode = 2 +text = "Profile Desc" + +[node name="ProfileOptions" type="HBoxContainer" parent="Panel/HBoxContainer/ProfilePanel"] +custom_minimum_size = Vector2(0, 32) +layout_mode = 2 + +[node name="ProfileLaunch" type="Button" parent="Panel/HBoxContainer/ProfilePanel/ProfileOptions"] +unique_name_in_owner = true +layout_mode = 2 +text = "Launch" + +[node name="ProfileEdit" type="Button" parent="Panel/HBoxContainer/ProfilePanel/ProfileOptions"] +unique_name_in_owner = true +layout_mode = 2 +text = "Edit" + +[node name="ProfileDelete" type="Button" parent="Panel/HBoxContainer/ProfilePanel/ProfileOptions"] +unique_name_in_owner = true +layout_mode = 2 +text = "Delete" + +[node name="ProfileOpenFolder" type="Button" parent="Panel/HBoxContainer/ProfilePanel/ProfileOptions"] +unique_name_in_owner = true +layout_mode = 2 +text = "Open Folder" + +[node name="ProfileAddPanel" type="VBoxContainer" parent="Panel/HBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.0 + +[node name="ProfileIcon" type="TextureRect" parent="Panel/HBoxContainer/ProfileAddPanel"] +custom_minimum_size = Vector2(96, 96) +layout_mode = 2 +expand_mode = 3 +stretch_mode = 4 + +[node name="ProfileName" type="Label" parent="Panel/HBoxContainer/ProfileAddPanel"] +layout_mode = 2 +text = "Profile Name" + +[node name="ProfileDesc" type="Label" parent="Panel/HBoxContainer/ProfileAddPanel"] +layout_mode = 2 +text = "Profile Desc" + +[node name="ProfileOptions" type="HBoxContainer" parent="Panel/HBoxContainer/ProfileAddPanel"] +custom_minimum_size = Vector2(0, 32) +layout_mode = 2 + +[node name="Save" type="Button" parent="Panel/HBoxContainer/ProfileAddPanel/ProfileOptions"] +layout_mode = 2 +text = "Launch" + +[node name="Cancel" type="Button" parent="Panel/HBoxContainer/ProfileAddPanel/ProfileOptions"] +layout_mode = 2 +text = "Edit" + +[node name="HTTPRequest" type="HTTPRequest" parent="."] +use_threads = true diff --git a/main.gd b/main.gd index b664d64..1b8fbc0 100644 --- a/main.gd +++ b/main.gd @@ -15,21 +15,30 @@ func _ready(): %Games.item_activated.connect(on_item_activated.bind("games")) %Profiles.item_activated.connect(on_item_activated.bind("profiles")) %ProfileAdd.pressed.connect(_add_new_profile) + %ProfileLaunch.pressed.connect(_launch_profile) if games.size()==1: - select_game(games[0]) + select_game(games.keys()[0]) %GameClose.visible=false elif games.size()>1: load_games() %GameClose.pressed.connect(_return_to_list) + else: + PathHelper.create_game_folder("DummyGame") + PathHelper.create_profile_folder("DummyGame","BaseProfile") + + + lua.bind_libraries(["base", "coroutine", "debug", "table", "string", "math", "io", "os", "utf8", "package"]) + lua.push_variant("create_process", LuaFuncs._create_process) + lua.push_variant("download_file", LuaFuncs.download_file) + lua.push_variant("message", "Hello lua!") func register_games(): for gm in DirAccess.get_directories_at(PathHelper.data_path): var cfg := PathHelper.get_game_config(gm) var dt = { "name":cfg.get_value("Data","game_name","Dummy"), - "image":cfg.get_value("Data","game_icon_path","icon.svg"), - "profiles":[] + "image":cfg.get_value("Data","game_icon_path","icon.svg") } games[gm]=dt print("Registered games") @@ -70,8 +79,13 @@ func load_games(): func load_profiles(): - profiles["profile1"]={"name":"profile1","image":"res://icon.svg","profiles":[]} - profiles["profile2"]={"name":"profile2","image":"res://icon.svg","profiles":[]} + for pf in DirAccess.get_directories_at(PathHelper.data_path): + var cfg := PathHelper.get_profile_config(selected_game,pf) + var dt = { + "name":cfg.get_value("Data","profile_name","Dummy"), + "image":cfg.get_value("Data","profile_icon_path","icon.svg") + } + profiles[pf]=dt print("Registered games") func select_profile(key:String): @@ -123,3 +137,19 @@ func _return_to_list(): func _add_new_profile(): pass + +var lua: LuaAPI = LuaAPI.new() +func _launch_profile(): + # Most methods return a LuaError in case of an error + var err: LuaError = lua.do_file(PathHelper.data_path+PathHelper.game+"/game.lua") + if err is LuaError: + print("ERROR %d: %s" % [err.type, err.message]) + return + + var ret = lua.call_function("launch_profile", [ + PathHelper.data_path+PathHelper.game+"/", + PathHelper.data_path+PathHelper.game+"/profiles/"+selected_profile+"/" + ]) + if ret is LuaError: + print("ERROR %d: %s" % [ret.type, ret.message]) + return diff --git a/main.tscn b/main.tscn index 3174011..ba9dc29 100644 --- a/main.tscn +++ b/main.tscn @@ -254,38 +254,5 @@ unique_name_in_owner = true layout_mode = 2 text = "Open Folder" -[node name="ProfileAddPanel" type="VBoxContainer" parent="Panel/HBoxContainer"] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_stretch_ratio = 0.0 - -[node name="ProfileIcon" type="TextureRect" parent="Panel/HBoxContainer/ProfileAddPanel"] -custom_minimum_size = Vector2(96, 96) -layout_mode = 2 -expand_mode = 3 -stretch_mode = 4 - -[node name="ProfileName" type="Label" parent="Panel/HBoxContainer/ProfileAddPanel"] -layout_mode = 2 -text = "Profile Name" - -[node name="ProfileDesc" type="Label" parent="Panel/HBoxContainer/ProfileAddPanel"] -layout_mode = 2 -text = "Profile Desc" - -[node name="ProfileOptions" type="HBoxContainer" parent="Panel/HBoxContainer/ProfileAddPanel"] -custom_minimum_size = Vector2(0, 32) -layout_mode = 2 - -[node name="Save" type="Button" parent="Panel/HBoxContainer/ProfileAddPanel/ProfileOptions"] -layout_mode = 2 -text = "Launch" - -[node name="Cancel" type="Button" parent="Panel/HBoxContainer/ProfileAddPanel/ProfileOptions"] -layout_mode = 2 -text = "Edit" - [node name="HTTPRequest" type="HTTPRequest" parent="."] use_threads = true diff --git a/project.godot b/project.godot index 93d5ede..9b43812 100644 --- a/project.godot +++ b/project.godot @@ -20,3 +20,4 @@ config/icon="res://icon.svg" [autoload] PathHelper="*res://utils/PathHelper.gd" +LuaFuncs="*res://utils/lua_funcs.gd" diff --git a/utils/PathHelper.gd b/utils/PathHelper.gd index a57ec66..f68e34b 100644 --- a/utils/PathHelper.gd +++ b/utils/PathHelper.gd @@ -7,6 +7,8 @@ func _ready(): if OS.has_feature("release"): base_path=OS.get_executable_path().path_join("data") data_path=base_path+"data/" + if !DirAccess.dir_exists_absolute(data_path): + DirAccess.make_dir_recursive_absolute(data_path) func game_exists(game)->bool: return DirAccess.dir_exists_absolute(base_path+game) @@ -15,30 +17,67 @@ func game_config_exists(game)->bool: if !game_exists(game): return false - return DirAccess.dir_exists_absolute(base_path+game+"/config.cfg") + return DirAccess.dir_exists_absolute(data_path+game+"/config.cfg") func create_game_folder(game): - DirAccess.make_dir_recursive_absolute(base_path+game+"/profiles") + DirAccess.make_dir_recursive_absolute(data_path+game+"/profiles") var file := ConfigFile.new() file.set_value("Data","game_name","Dummy") file.set_value("Data","game_icon_path","icon.svg") - file.save(base_path+game+"/config.cfg") + file.save(data_path+game+"/config.cfg") + + var script := FileAccess.open(data_path+game+"/game.lua",FileAccess.WRITE) + script.store_string( + """ +function get_launch_cmd() + return "echo Hello gdScript!" +end +""" + ) func get_game_config(game)->ConfigFile: var file := ConfigFile.new() if !game_config_exists(game): file.set_value("Data","game_name","Dummy") file.set_value("Data","game_icon_path","icon.svg") - file.save(base_path+game+"/config.cfg") + file.save(data_path+game+"/config.cfg") return file - file.load(base_path+game+"/config.cfg") + file.load(data_path+game+"/config.cfg") return file func game_script_exists(game)->bool: if !game_exists(game): return false - return DirAccess.dir_exists_absolute(base_path+game+"/game.lua") + return DirAccess.dir_exists_absolute(data_path+game+"/game.lua") +func profile_exists(game,profile)->bool: + if !game_exists(game): + return false + return DirAccess.dir_exists_absolute(data_path+game+"/profiles/"+profile) + +func profile_config_exists(game,profile)->bool: + if !game_exists(game): + return false + + return DirAccess.dir_exists_absolute(data_path+game+"/profiles/"+profile+"/config.cfg") + +func create_profile_folder(game,profile): + DirAccess.make_dir_recursive_absolute(data_path+game+"/profiles/"+profile+"/profiles") + + var file := ConfigFile.new() + file.set_value("Data","game_name","Dummy") + file.set_value("Data","game_icon_path","icon.svg") + file.save(data_path+game+"/profiles/"+profile+"/config.cfg") + +func get_profile_config(game,profile)->ConfigFile: + var file := ConfigFile.new() + if !game_config_exists(game): + file.set_value("Data","profile_name","Dummy") + file.set_value("Data","profile_icon_path","icon.svg") + file.save(data_path+game+"/profiles/"+profile+"/config.cfg") + return file + file.load(data_path+game+"/profiles/"+profile+"/config.cfg") + return file diff --git a/utils/lua_funcs.gd b/utils/lua_funcs.gd new file mode 100644 index 0000000..ad210b4 --- /dev/null +++ b/utils/lua_funcs.gd @@ -0,0 +1,15 @@ +extends Node + + +func _execute(cmd:String,args:Array): + OS.execute(cmd,args) + +func _create_process(cmd:String,args:=[],console:=false): + OS.create_process(cmd,args,console) + +func download_file(url,download_file): + var request = HTTPRequest.new() + request.download_file=download_file + request.use_threads=true + request.request(url) + await request.request_completed