How to get acces to file in the same folder of the game (Godot engine) - godot

So i wanted to load external file in my godot game but I can't find any answer. I want to load file (sound, image, ...) in the same folder of the game (.exe).
By the way I can always do it directly include all the file in the engine but it's more easy to modify the external file than file in the editor

You can use OS.get_executable_path() to get the path of the executable. Except, it will give you the path to the Godot executable if you are running from the editor.
You can check if your code is running from the editor with OS.has_feature("standalone").
And of course, you don't really want the path to the executable, but to the folder it is in. So we use get_base_dir.
Like this:
if OS.has_feature("standalone"):
var folder := OS.get_executable_path().get_base_dir()
Also be aware of OS.get_user_data_dir() which gives you an appropriate folder for your game depending on the operating system (there is also where the "logs" folder will be). Plus OS.get_user_data_dir() will work even when running form the editor, and it gives you a folder path directly.
Then we can either build a path to another file in the same folder:
if OS.has_feature("standalone"):
var path := OS.get_executable_path().get_base_dir()
var file_name := folder.plus_file("my_file.png")
Or we can enumerate files:
if OS.has_feature("standalone"):
var path := OS.get_executable_path().get_base_dir()
var dir = Directory.new()
if dir.open(path) == OK:
dir.list_dir_begin()
var file_name:String = dir.get_next()
while file_name != "":
if not dir.current_is_dir():
if file_name.get_extension() == "png":
print("Found file: " + file_name)
file_name = dir.get_next()
else:
print("An error occurred when trying to access the path.")
Now, you want to load them. Except load et.al. won't work because they are not resources in your project.
You can read the contents of a file into a buffer like this:
var file := File.new()
file.open(file_name, File.READ)
var buffer := file.get_buffer(file.get_len())
file.close()
Then from the buffer you can create an Image like this:
var my_image := Image.new()
my_image.load_png_from_buffer(buffer)
If you happen to need a Texture you can do this:
var my_texture := ImageTexture.new()
my_texture.create_from_image(my_image)
I'll also mention that you can set the flags of the Texture.
And for sound…
I will point you to GDScriptAudioImport because, sadly, it is not as straightforward.
And as you can imagine anything else you want to load from external files will different code to support it.
By the way I can always do it directly include all the file in the engine but it's more easy to modify the external file than file in the editor
You can always edit files in the project folder with any other external software and when you switch back to Godot it will detect the changes and re-import. So you don't need to modify anything within Godot.
And for any other software modifying files in the project folder should not be any harder than modifying files located elsewhere.

Related

I need to copy files from appdata/local to C drive and overwrite them each time the program is run

I use a program which, sadly corrupts some saved files at random times. To be helpful (although I am a novice at this) I am trying to make a Python program to basically backup those file from the AppData/local directory and put them in a folder on C. I need this program to overwrite the previously copied files each time it is run.
I need to generalize the AppData/local because each person who uses this program would, in theory, have a different user directory preceding the AppData folder.
I've tried running some of my own attempts at a solution.
I will post the results.
# Imports
import shutil
import os
import distutils
from distutils import dir_util
# Paths
# os.makedirs("C:/RevSaves-Backup")
path = '%LOCALAPPDATA%/Remnant'
backup_path = "C:/RevSaves-Backup"
# Procedures
print("The Very Basic Remnant Save Backup Utility")
print(" ")
print("Backing up the save source:")
print(path)
print(" ")
print("It is recommended you run this at regular intervals \nto ensure you have the latest saves up to date.")
distutils.dir_util.copy_tree(path, backup_path)
print("Backup completed.")
When I execute this via command prompt or PowerShell, I get the following message:
Traceback (most recent call last):
File "RevSaveBkUp.py", line 28, in
distutils.dir_util.copy_tree(path, backup_path)
File "C:\Users\candr\AppData\Local\Programs\Python\Python37-32\lib\distutils\dir_util.py", line 124, in copy_tree
"cannot copy tree '%s': not a directory" % src)
distutils.errors.DistutilsFileError: cannot copy tree '%LOCALAPPDATA%/Remnant': not a directory
I am having trouble "targeting" the system-specific local AppData folder.
After a lot of reading, I made the following solution if anyone else is trying to do something similar. I do not know if this is the "best" or "right" way of doing things, however.
Here is how I targeted the AppData Local folder regardless of the user logged in:
path = os.path.join(os.path.expanduser('~'), 'AppData', 'Local')
Some explanations for anyone who is new like me:
os.path.join basically connects folders together in the path. For example, using the above code, join would "connect" AppData to Local and the "User Folder" (referenced in the code as '~'). The output would look like this: C:\Users\your_username\AppData\Local
os.path.expanduser defines the user in question. For example, "~" targets the current user logged in. It goes inside the () because this is how you tell "your code" who, to target. If you wanted a specific user (if you had more than one) you could possibly use os.path.expanduser('Jane') I believe.
Keeping the notes above in reference, this method allowed me to define the variables I needed to and use them for the copy above, where I could not normally use the AppData directory as I wanted.
This was done by using the following code as an example:
path = os.path.join(os.path.expanduser('~'), 'AppData', 'Local')
backup_path = "C:/MyBackupFolder"
Finally we executed the copy with this:
distutils.dir_util.copy_tree(path, backup_path)
The above copied The AppData information I needed to the backup folder.
I hope this helps everyone learn as I did, it came in quite handy.

How to open a binary file in my case .nii file using node.js

I want to open a binary file, or at least when I try to open this with the vscode editor, is say that, can't be opened, because is a binary file.
Can someone explain to me what I can do in order to open this type of files and read the content?
About the .nii file format. is a NIFTI1 and used on medical visualization like MRI.
What I trying to do is to read this file at the lowest level and then make some computations.
I will like to use Node.js for this, not any Python or C++.
More details about the file format can be found here.
https://nifti.nimh.nih.gov/
I don't know about how VScode handle binary file but for exemple with Atom (or with another text editor like vi), you can open and view the content of a binary file. This is not very usefull however as the content is not particularly human readable, except maybe some metadata at the top of the file.
$ vim yourniifile.nii
Anyway, it's all depends on what you want to do with that file, which "computation" you're planned to apply to it, and how you will use it after that.
Luckily, there are some npm packages that can help you with the task of reading and processing that kind of file, like nifti-reader-js or nifti-js, for exemple:
const fs = require('fs');
const niftijs = require('nifti-js');
let rawData = fs.readFileSync('yourniifile.nii');
let data = niftijs.parse(rawData);
console.log(data);

How can i make 'text' to 'downloadable url'?

I make chrome extension, which download some files from website.
i want write some log with txt file, because my program has some error and i want save error to txt file.
but i can't find how to do it.
someone say it's impossible.
i try to search, some questions say just 'app' can do it, but extension can't.
if i want this functions, i must change my program to web app? but i don't know anything about that...
'download file' is possible, download is write file to filesystem.
i think, 'write text file' is so easy work then download image and sound files....
why not??? what's diffrent??
i see many questions, blog and document, but i cant know clearly.
*to sum up
I want make some text to downloadable file. If i can get downloadable file and it's url, everything is perfect.
i see this extension, i think i can do it. but i don't know how to do it.
please teach me how do it!
https://chrome.google.com/webstore/detail/save-text-to-file/mkepenkbhepjelljcfiooignmpfgochi/related
This is what I understand from your question that you want to write some text into .txt file and it should be automatically downloaded for your users. For that, here I am writing code in JavaScript which will surely helps you.
var fileText = "Your content which you want to save in file";
var fileBlob = new Blob([fileText], {
type: 'text/plain'
});
var fileUrl = URL.createObjectURL(fileBlob);
var fileName = 'mytextfile.txt';
var fileOptions = {
filename: fileName,
url: fileUrl,
conflictAction: 'uniquify'
};
fileOptions.saveAs = true;
It will automatically download mytextfile.txt file with your given contents. You can implement this logic in your chrome extension as per your way.

Why is this code not printing the directory contents?

I am a Python newbie and need to create a script that will do parse some files and put them into a SQL db. So I am trying to create smaller scripts that do what I want, then combine them into a larger script.
To that end, I am trying run this code:
import os
fileList = []
testDir = "/home/me/somedir/dir1/test"
for i in os.listdir(testDir):
if os.path.isfile(i):
fileList.append(i)
for fileName in fileList:
print(fileName)
When I look at the output, I do not see any files listed. I tried the path without quotes and got stack errors. So searching showed I need the double quotes.
Where did I go wrong?
I found this code that works fine:
import os
in_path = "/home/me/dir/"
for dir_path, subdir_list, file_list in os.walk(in_path):
for fname in file_list:
full_path = os.path.join(dir_path, fname)
print(full_path)
I can use full_path to do my next step.
If anyone has any performance tips, feel free to share them. Or point me in the right direction.
that is because you're most likely ejecuting your script from a folder outside your testdir, os.path.isfile need the full path name of the file so it can check is that is a lile or not (os.listdir return the names), if the full path is not provide then it will check is there is a file with the given name in the same folder from which the script is executed, to fix this you need to give the full path name of that file, you can do it with os.path.join like this
for name in os.listdir(testDir):
if os.path.isfile( os.path.join(testDir,name) ):
fileList.append(name)
or if you also want the full path
for name in os.listdir(testDir):
path = os.path.join(testDir,name)
if os.path.isfile(path):
fileList.append(path)

Automatically create folder of same name on file creation

Is there any way for me to set up sublime to automatically create a folder of the same name when I create certain files.
I create landing pages that all have a lp_ prefix to the filename, I would like to watch for when a file with this name is created and then automatically create a folder of the same name in another directory (for css and images).
Would this be possible with a plugin or something like Grunt?
Example:
Create file: lp_test.php
Automate Folder Creation: /lp/lp_test/
You can make a plugin that extends EventListener and overrides (for example) on_post_save_async. You can use this simple example as base:
import sublime, sublime_plugin, os
# We extend event listener
class ExampleCommand(sublime_plugin.EventListener):
# This method is called every time a file is saved (not only the first time is saved)
def on_post_save_async(self, view):
variables = view.window().extract_variables()
fileBaseName = variables['file_base_name'] # File name without extension
path = 'C:/desiredPath/css/' + fileBaseName
if fileBaseName.startswith('lp_') and not os.path.exists(path):
os.mkdir(path)
EDIT: changed on_post_save to on_post_save_async as it runs in a different thread and does not block the application. Thanks MattDMo for commenting it and for adding python highlighting.

Resources