rakugoteam/Rakugo-Dialogue-System

Audio and images don't work after exporting a project with Rakugo

MRSEEO opened this issue · 23 comments

I have a code that plays music and displays image in Rakugo script file.
In godot editor it works really well, but in the export version of that project it doesn't work...

I have a code that plays music and displays image in Rakugo script file. In godot editor it works really well, but in the export version of that project it doesn't work...

I see this is quite simple to fix, by default godot doesn't include files that is don't recognize, with include *.rk files.
To fix this follow this steps: https://rakugoteam.github.io/rakugo-docs/export/

@MRSEEO this worked for you ⬆️ ?

@MRSEEO this worked for you ⬆️ ?

Sorry for late response. Unfortunately, no... Rakugo .rk script works well, text displays as intented, but audio doesn't want to play and images also don't want to work. But in Godot Editor audio and images works well

@MRSEEO This is very unusual, can say me 2 things:

  • where are those audio and image files, are they inside your Godot project ?
  • can you paste this code that that plays music and displays image in Rakugo script file ?

@MRSEEO This is very unusual, can say me 2 things:

  • where are those audio and image files, are they inside your Godot project ?
  • can you paste this code that that plays music and displays image in Rakugo script file ?

Yes, they are inside

func _ready():

  var id_regex = "([a-zA-Z0-9_]+ ?)+"

  Rakugo.parser_add_regex_at_runtime("show", "^show (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("hide", "^hide (?<id>%s)" %  id_regex )

  Rakugo.parser_add_regex_at_runtime("play", "^play (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("stop", "^stop (?<id>%s)" %  id_regex )


  Rakugo.connect("parser_unhandled_regex", self, "_on_parser_unhandled_regex")
  Rakugo.connect("say", self, "_on_say")
  Rakugo.connect("step", self, "_on_step")
  Rakugo.connect("ask", self, "_on_ask")
  Rakugo.connect("menu", self, "_on_menu")

  Rakugo.parse_and_execute_script(file_path)

func _on_parser_unhandled_regex(key:String, result:RegExMatch):
	var ids = result.get_string("id").split(" ")

	
	match(key):
		"show":
			###Color
			for i in ids:
				if i == "color":
					find_node("color").color = ColorN(ids[1])
					find_node("color").visible = true
				
			###Background
				if i == "bg":
					var name_num = ResourcesDefine.bg.get('name').find(str(ids[1]))
					var path_to_file = ResourcesDefine.bg.get('path')[name_num]
					
					find_node("bg").texture = load(path_to_file)
					find_node("bg").visible = true
			
		"hide":
			var layers = ['color', 'bg', 'sprite']
			for i in layers.size():
				if ids[0].begins_with(str(layers[i])):
					ids[0] = layers[i]
			
			
			find_node(ids[0]).visible = false


		"play":
			for i in ids:
			###Play music
				if i == "music":
					var name_num = ResourcesDefine.music.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.music.get('path')[name_num]
					
					if "fadein" in ids:
						Audio.play_music(path_to_file, true, float(ids[3]))
						
					else:
						Audio.play_music(path_to_file, false, 0)
						
			###Play sound
				if i == "sound":
					var name_num = ResourcesDefine.sound.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.sound.get('path')[name_num]
					
					Audio.play_sound(path_to_file)
						
						
		"stop":
			for i in ids:
				
				if i == "music":
					if "fadeout" in ids:
						Audio.stop_music(true, float(ids[2]))
					
					else:
						Audio.stop_music(false, 0)

It's a custom code for parser.

In .rk script i just do this:

play music menu fadein 3

Az "Music test"

stop music fadeout 5

Az "Sound test"

play sound click

@theludovyc do you have any idea why this ⬆️ doesn't work ?

@MRSEEO two more questions:

  1. can you try using $"path/to/node" or get_node("path/to/node") instead of find_node("node_name") ?
  2. could your run exported project using terminal, so we can see if they are any bugs ?
  3. when you export you have a project_name.pck, I hope you don't remove it, as this is where all game resources are ?

Hello :) !

@MRSEEO What is ResourcesDefine and how it works ?

Do you try to play audio or change background without using it ?

@theludovyc do you have any idea why this ⬆️ doesn't work ?

@MRSEEO two more questions:

  1. can you try using $"path/to/node" or get_node("path/to/node") instead of find_node("node_name") ?
  2. could your run exported project using terminal, so we can see if they are any bugs ?
  3. when you export you have a project_name.pck, I hope you don't remove it, as this is where all game resources are ?

Hello :) !

@MRSEEO What is ResourcesDefine and how it works ?

Do you try to play audio or change background without using it ?

ResourcesDefine it's a script, that checks music and image folders and puts every file in an array.

EDIT: I tried to play audio without using it, but nothing changed...

Wow, i didn't know about opening the game in cmd... I found a bug
изображение_2023-03-10_180552657

Edit: 1. Yes, i tried it - it doesn't help.
3. Of course .pck file is included in export.

@MRSEEO From what I see in this cmd screenshot is clear that you have configured export in why that exclude
addons/file-editor from your project and that make your project broken, can you post a screenshot of your export settings ?

@MRSEEO From what I see in this cmd screenshot is clear that you have configured export in why that exclude addons/file-editor from your project and that make your project broken, can you post a screenshot of your export settings ?

изображение_2023-03-10_190145810

I turned off a file-editor, but anyway it doesn't help. I think problem is in "SCRIPT ERROR: Invalid get index '-1' (on base: 'Array')". It appears, when code should to play music or open image

@MRSEEO Sorry I didn't make it clear I wanted to check your Resources tab in Export settings.

I think problem is in "SCRIPT ERROR: Invalid get index '-1' (on base: 'Array')". It appears, when code should to play music or open image

Probably you are right, is this a gameplay.gds file that is metioned in this errors ?

func _ready():

  var id_regex = "([a-zA-Z0-9_]+ ?)+"

  Rakugo.parser_add_regex_at_runtime("show", "^show (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("hide", "^hide (?<id>%s)" %  id_regex )

  Rakugo.parser_add_regex_at_runtime("play", "^play (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("stop", "^stop (?<id>%s)" %  id_regex )


  Rakugo.connect("parser_unhandled_regex", self, "_on_parser_unhandled_regex")
  Rakugo.connect("say", self, "_on_say")
  Rakugo.connect("step", self, "_on_step")
  Rakugo.connect("ask", self, "_on_ask")
  Rakugo.connect("menu", self, "_on_menu")

  Rakugo.parse_and_execute_script(file_path)

func _on_parser_unhandled_regex(key:String, result:RegExMatch):
	var ids = result.get_string("id").split(" ")

	
	match(key):
		"show":
			###Color
			for i in ids:
				if i == "color":
					find_node("color").color = ColorN(ids[1])
					find_node("color").visible = true
				
			###Background
				if i == "bg":
					var name_num = ResourcesDefine.bg.get('name').find(str(ids[1]))
					var path_to_file = ResourcesDefine.bg.get('path')[name_num]
					
					find_node("bg").texture = load(path_to_file)
					find_node("bg").visible = true
			
		"hide":
			var layers = ['color', 'bg', 'sprite']
			for i in layers.size():
				if ids[0].begins_with(str(layers[i])):
					ids[0] = layers[i]
			
			
			find_node(ids[0]).visible = false


		"play":
			for i in ids:
			###Play music
				if i == "music":
					var name_num = ResourcesDefine.music.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.music.get('path')[name_num]
					
					if "fadein" in ids:
						Audio.play_music(path_to_file, true, float(ids[3]))
						
					else:
						Audio.play_music(path_to_file, false, 0)
						
			###Play sound
				if i == "sound":
					var name_num = ResourcesDefine.sound.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.sound.get('path')[name_num]
					
					Audio.play_sound(path_to_file)
						
						
		"stop":
			for i in ids:
				
				if i == "music":
					if "fadeout" in ids:
						Audio.stop_music(true, float(ids[2]))
					
					else:
						Audio.stop_music(false, 0)

Tip if you tape gdscript after "```" ten it will be higlighten
O I see you wrong indexs in your code you have a lot of ids[1] and first item in array is not `1`, but `0`.
Try to change `ids[1]` to `ids[0]`, `ids[2]` to `ids[1]` and `ids[3]` to `ids[2]`, and then give it a try.

@MRSEEO Sorry I didn't make it clear I wanted to check your Resources tab in Export settings.

I think problem is in "SCRIPT ERROR: Invalid get index '-1' (on base: 'Array')". It appears, when code should to play music or open image

Probably you are right, is this a gameplay.gds file that is metioned in this errors ?

func _ready():

  var id_regex = "([a-zA-Z0-9_]+ ?)+"

  Rakugo.parser_add_regex_at_runtime("show", "^show (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("hide", "^hide (?<id>%s)" %  id_regex )

  Rakugo.parser_add_regex_at_runtime("play", "^play (?<id>%s)" %  id_regex )
  Rakugo.parser_add_regex_at_runtime("stop", "^stop (?<id>%s)" %  id_regex )


  Rakugo.connect("parser_unhandled_regex", self, "_on_parser_unhandled_regex")
  Rakugo.connect("say", self, "_on_say")
  Rakugo.connect("step", self, "_on_step")
  Rakugo.connect("ask", self, "_on_ask")
  Rakugo.connect("menu", self, "_on_menu")

  Rakugo.parse_and_execute_script(file_path)

func _on_parser_unhandled_regex(key:String, result:RegExMatch):
	var ids = result.get_string("id").split(" ")

	
	match(key):
		"show":
			###Color
			for i in ids:
				if i == "color":
					find_node("color").color = ColorN(ids[1])
					find_node("color").visible = true
				
			###Background
				if i == "bg":
					var name_num = ResourcesDefine.bg.get('name').find(str(ids[1]))
					var path_to_file = ResourcesDefine.bg.get('path')[name_num]
					
					find_node("bg").texture = load(path_to_file)
					find_node("bg").visible = true
			
		"hide":
			var layers = ['color', 'bg', 'sprite']
			for i in layers.size():
				if ids[0].begins_with(str(layers[i])):
					ids[0] = layers[i]
			
			
			find_node(ids[0]).visible = false


		"play":
			for i in ids:
			###Play music
				if i == "music":
					var name_num = ResourcesDefine.music.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.music.get('path')[name_num]
					
					if "fadein" in ids:
						Audio.play_music(path_to_file, true, float(ids[3]))
						
					else:
						Audio.play_music(path_to_file, false, 0)
						
			###Play sound
				if i == "sound":
					var name_num = ResourcesDefine.sound.get('name').find(ids[1])
					var path_to_file = ResourcesDefine.sound.get('path')[name_num]
					
					Audio.play_sound(path_to_file)
						
						
		"stop":
			for i in ids:
				
				if i == "music":
					if "fadeout" in ids:
						Audio.stop_music(true, float(ids[2]))
					
					else:
						Audio.stop_music(false, 0)

Tip if you tape gdscript after "```" ten it will be higlighten O I see you wrong indexs in your code you have a lot of ids[1] and first item in array is not `1`, but `0`. Try to change `ids[1]` to `ids[0]`, `ids[2]` to `ids[1]` and `ids[3]` to `ids[2]`, and then give it a try.

I found what cause that bug. It's a ResourcesDefine, it doesn't work as intented and i don't know why. I add it to AutoLoad but it doesn't want to add files to array...

ResourcesDefine code:

extends Node

###IMAGES
var bg = {
	"name": [],
	"path": []
}

var sprites = {
	"name": [],
	"path": []
}


###MUSIC AND SOUNDS
var music = {
	"name": [],
	"path": []
}

var sound = {
	"name": [],
	"path": []
}

var loaded_images = []
var loaded_audio = []

func _ready():
	define_images(bg, "res://images/backgrounds/")
	define_images(sprites, "res://images/sprites/")

	define_audio(music, "res://audio/music/")
	define_audio(sound, "res://audio/sounds/")

	#for i in bg['path']:
		

func define_images(type, path):
	var dir = Directory.new()
	
	if dir.open(path) == OK:
		dir.list_dir_begin()
		var file_name = dir.get_next()
		
		while file_name != "" and !file_name.ends_with(".import"):
			var formats = [".png", ".jpg"]
				
			if ".jpg" or ".png" in file_name:
				#Preloading.
				loaded_images.append(load(path + "/" + file_name))
				
				
				type["path"].push_back(path+file_name)
				
				for i in formats:
					file_name = file_name.trim_suffix(i)
				
				type["name"].push_back(file_name)


			file_name = dir.get_next()
			#print(loaded_images)
			
	else:
		push_error("Images error")




func define_audio(type, path):
	var dir = Directory.new()
	
	if dir.open(path) == OK:
		dir.list_dir_begin()
		var file_name = dir.get_next()
		
		while file_name != "" and !file_name.ends_with(".import"):
			var formats = [".ogg", ".wav", ".mp3"]
				
			if ".ogg" or ".wav" or ".mp3" in file_name:
				#Preloading.
				loaded_audio.append(load(path + file_name))
				#print("music: " + str(loaded_audio))
				
				
				type["path"].push_back(path+file_name)
				
				for i in formats:
					file_name = file_name.trim_suffix(i)
				
				type["name"].push_back(file_name)
				
				
			file_name = dir.get_next()
			#print(type)
			
	else:
		push_error("Sounds error")

@MRSEEO what does the debugger say when you execute define_images step by step ?

Do you know class String contain a func get_extension() ? I think it can help to simplify your code.

I also wondering about if you use load() on purpose in your script (not ResourcesDefine) line 37 ?

@MRSEEO I have 2 question:

  1. Is this intended that you don't add "/" in path ?
loaded_images.append(load(path + "/" + file_name))				
type["path"].push_back(path+file_name)
  1. Could you try use preload() instead of load() ?

@MRSEEO what does the debugger say when you execute define_images step by step ?

Do you know class String contain a func get_extension() ? I think it can help to simplify your code.

I also wondering about if you use load() on purpose in your script (not ResourcesDefine) line 37 ?

@MRSEEO I have 2 question:

  1. Is this intended that you don't add "/" in path ?
loaded_images.append(load(path + "/" + file_name))				
type["path"].push_back(path+file_name)
  1. Could you try use preload() instead of load() ?

When i use load("path_to_file"), it works well.

Looks like .png(or .jpg) files works only in Godot Editor. After export code can't find any .png or .jpg files, with audio situation is same. Code can find only .import files...

I tested this. In Editor code prints every file, city.png and city.png.import, but in export version on cmd prints only .import files.

And i don't know what to do with it...

@MRSEEO Can you check if in Export Resources tab you have it set in the same way ?
image
If yes then try to Filters to export non-resource files/folders
add *.png, *.jpg, *.ogg, *.wav, *.mp3 to force incluing them in exported project.

@MRSEEO Can you check if in Export Resources tab you have it set in the same way ? image
If yes then try to Filters to export non-resource files/folders add *.png, *.jpg, *.ogg, *.wav, *.mp3 to force incluing them in exported project.

изображение_2023-03-11_163534233
And it doesn't help at all... Maybe i should load these .import files? Sorry for non-Rakugo problem topic

And it doesn't help at all... Maybe i should load these .import files? Sorry for non-Rakugo problem topic

@MRSEEO No problem we like to help you.
I did some diging and it seams that you need to load those files from res://.import/ directory,
godotengine/godot#38489 (comment) :

not an error at all.
the wav file will never be found in res:// irregardless of what you do or what platform you're on.
the actual imported and converted sound file would be in import/

as an example. the Icon.png is not stored in the exported .pck. It would be pointless, because the real, imported and converted texture file, is present in import/. When you load() a resource the path is remapped to those internally imported files.

So you need to change your script so it don't search those files at run time,
but to make it be saved as part of scene that already keeps all this paths,
Change it beginning this way:

tool
# I added `tool` keyword so we can run it in editor
extends Node

# this will be checkbox that we use as button to load our rescources
export var load_resources := false setget _load_resources

# I added `export` keyword so it will be saved as part of scene
###IMAGES
export var bg = {
	"name": [],
	"path": []
}

export var sprites = {
	"name": [],
	"path": []
}


###MUSIC AND SOUNDS
export var music = {
	"name": [],
	"path": []
}

export var sound = {
	"name": [],
	"path": []
}

export var loaded_images = []
export var loaded_audio = []

func _load_resources(v : bool): #instead of _ready() func
	define_images(bg, "res://images/backgrounds/")
	define_images(sprites, "res://images/sprites/")

	define_audio(music, "res://audio/music/")
	define_audio(sound, "res://audio/sounds/")

	#for i in bg['path']:

After that to save your database of resurces you need to add this script as root in new empty scene.
Then check the Load Resources checkbox in its inspector - this should run _load_resources() func.
Now that you need to save this scene. From now you will need to run this when ever you add or remove resource from game. After change ResourcesDefine autoload/singleton so it points to this new scene.
Now exported should work.

@MRSEEO did my solution above helped you or you found other solution ?

@MRSEEO did my solution above helped you or you found other solution ?

sorry for late response. this code just makes my godot 3.5 freeze until i revert my code back...

edit: i heard about ResourcePreloader in Godot. I don't know how to use it, but it can helps?..
And i thought that my mistake is load resources paths, not resources itself. But i don't know how to load resources in that way, that i can use them by it's name

sorry for late response. this code just makes my godot 3.5 freeze until i revert my code back...

Sorry about this my bad I didn't have project on witch I could test it. so maybe I made mistakie in it.

edit: i heard about ResourcePreloader in Godot. I don't know how to use it, but it can helps?..
And i thought that my mistake is load resources paths, not resources itself. But i don't know how to load resources in that way, that i can use them by it's name

As I mentioned before godotengine/godot#38489 (comment) godot does not provide searching for not compiled files in an already compiled game.

So just using ResourcePreloader or it simplifed from preload() probably wan't help you.
What need is that you need to have this database of files already saved before game export.
@theludovyc any idea how @MRSEEO can automate this ?

Other thing you can make it to add all backgrounds, sprites, music and sound to one scene as nodes that are parented to Nodes called in like a folders and use this scene as foundation for other scenes.
And to main root of this scene add script that is similar to your ResourcesDefine, but it don't load and add this resources to scenes, but show/hide or play them.

Another thing you can do is to just don't export game just bundle game with godot editor exe as godot editor is already an engine to run you can then add *.sh (linux/mac) and *.bat (windows) script that just do:

#!/bin/bash
./godot_executable_name project.godot

It is remind me an old project I do. With same intention to load images. Look at https://github.com/theludovyc/Godot_Islanders/blob/master/Script/Load.gd, the load icons part. And when I do export, is not work like I want. I no take time to resolve it for now.

@MRSEEO ask on godot official discord or maybe you can find a solution on google. I am sorry to can not help you more.

It is remind me an old project I do. With same intention to load images. Look at https://github.com/theludovyc/Godot_Islanders/blob/master/Script/Load.gd, the load icons part. And when I do export, is not work like I want. I no take time to resolve it for now.

@MRSEEO ask on godot official discord or maybe you can find a solution on google. I am sorry to can not help you more.

I don't know why, but for me even without export load() didn't work at all, but ResurceLoader.load() is working,
but I didn't finish yet example inspired by this issue, so I didn't test it exported.