@@ -45,9 +45,10 @@ Plain text and binary files
4545Godot's :ref: `class_FileAccess ` class provides methods to access files on the
4646filesystem for reading and writing:
4747
48- ::
48+ .. tabs ::
49+ .. code-tab :: gdscript
4950
50- func save_file(content):
51+ func save_file(content):
5152 var file = FileAccess.open("/path/to/file.txt", FileAccess.WRITE)
5253 file.store_string(content)
5354
@@ -56,6 +57,21 @@ filesystem for reading and writing:
5657 var content = file.get_as_text()
5758 return content
5859
60+ .. code-tab :: csharp
61+
62+ private void SaveFile(string content)
63+ {
64+ using var file = FileAccess.Open("/Path/To/File.txt", FileAccess.ModeFlags.Write);
65+ file.StoreString(content);
66+ }
67+
68+ private string LoadFile()
69+ {
70+ using var file = FileAccess.Open("/Path/To/File.txt", FileAccess.ModeFlags.Read);
71+ string content = file.GetAsText();
72+ return content;
73+ }
74+
5975To handle custom binary formats (such as loading file formats not supported by
6076Godot), :ref: `class_FileAccess ` provides several methods to read/write integers,
6177floats, strings and more. These FileAccess methods have names that start with
@@ -116,7 +132,8 @@ increase performance by reducing I/O utilization.
116132Example of loading an image and displaying it in a :ref: `class_TextureRect ` node
117133(which requires conversion to :ref: `class_ImageTexture `):
118134
119- ::
135+ .. tabs ::
136+ .. code-tab :: gdscript
120137
121138 # Load an image of any format supported by Godot from the filesystem.
122139 var image = Image.load_from_file(path)
@@ -131,6 +148,21 @@ Example of loading an image and displaying it in a :ref:`class_TextureRect` node
131148 # Save the converted ImageTexture to a PNG image.
132149 $TextureRect.texture.get_image().save_png("/path/to/file.png")
133150
151+ .. code-tab :: csharp
152+
153+ // Load an image of any format supported by Godot from the filesystem.
154+ var image = Image.LoadFromFile(path);
155+ // Optionally, generate mipmaps if displaying the texture on a 3D surface
156+ // so that the texture doesn't look grainy when viewed at a distance.
157+ // image.GenerateMipmaps();
158+ GetNode<TextureRect>("TextureRect").Texture = ImageTexture.CreateFromImage(image);
159+
160+ // Save the loaded Image to a PNG image.
161+ image.SavePng("/Path/To/File.png");
162+
163+ // Save the converted ImageTexture to a PNG image.
164+ GetNode<TextureRect>("TextureRect").Texture.GetImage().SavePng("/Path/To/File.png");
165+
134166.. _doc_runtime_file_loading_and_saving_audio_video_files :
135167
136168Audio/video files
@@ -143,13 +175,19 @@ load correctly as audio files in Godot.
143175
144176Example of loading an Ogg Vorbis audio file in an :ref: `class_AudioStreamPlayer ` node:
145177
146- ::
178+ .. tabs ::
179+ .. code-tab :: gdscript
147180
148181 $AudioStreamPlayer.stream = AudioStreamOggVorbis.load_from_file(path)
149182
183+ .. code-tab :: csharp
184+
185+ GetNode<AudioStreamPlayer>("AudioStreamPlayer").Stream = AudioStreamOggVorbis.LoadFromFile(path);
186+
150187Example of loading an Ogg Theora video file in a :ref: `class_VideoStreamPlayer ` node:
151188
152- ::
189+ .. tabs ::
190+ .. code-tab :: gdscript
153191
154192 var video_stream_theora = VideoStreamTheora.new()
155193 # File extension is ignored, so it is possible to load Ogg Theora videos
@@ -161,6 +199,18 @@ Example of loading an Ogg Theora video file in a :ref:`class_VideoStreamPlayer`
161199 # before this property is set, so call `play() ` after setting `stream `.
162200 $VideoStreamPlayer.play()
163201
202+ .. code-tab :: csharp
203+
204+ var videoStreamTheora = new VideoStreamTheora();
205+ // File extension is ignored, so it is possible to load Ogg Theora videos
206+ // that have an `.ogg ` extension this way.
207+ videoStreamTheora.File = "/Path/To/File.ogv";
208+ GetNode<VideoStreamPlayer>("VideoStreamPlayer").Stream = videoStreamTheora;
209+
210+ // VideoStreamPlayer's Autoplay property won't work if the stream is empty
211+ // before this property is set, so call `Play() ` after setting `Stream `.
212+ GetNode<VideoStreamPlayer>("VideoStreamPlayer").Play();
213+
164214.. note ::
165215
166216 Godot doesn't support runtime loading of MP3 or WAV files yet. Until this is
@@ -185,7 +235,8 @@ as it's faster to write and smaller, but the text format is easier to debug.
185235
186236Example of loading a glTF scene and appending its root node to the scene:
187237
188- ::
238+ .. tabs ::
239+ .. code-tab :: gdscript
189240
190241 # Load an existing glTF scene.
191242 # GLTFState is used by GLTFDocument to store the loaded scene's state.
@@ -209,6 +260,34 @@ Example of loading a glTF scene and appending its root node to the scene:
209260 # `GLTFDocument.generate_buffer() ` is also available for saving to memory.
210261 gltf_document_save.write_to_filesystem(gltf_state_save, path)
211262
263+ .. code-tab :: csharp
264+
265+ // Load an existing glTF scene.
266+ // GLTFState is used by GLTFDocument to store the loaded scene's state.
267+ // GLTFDocument is the class that handles actually loading glTF data into a Godot node tree,
268+ // which means it supports glTF features such as lights and cameras.
269+ var gltfDocumentLoad = new GltfDocument();
270+ var gltfStateLoad = new GltfState();
271+ var error = gltfDocumentLoad.AppendFromFile("/Path/To/File.gltf", gltfStateLoad);
272+ if (error == Error.Ok)
273+ {
274+ var gltfSceneRootNode = gltfDocumentLoad.GenerateScene(gltfStateLoad);
275+ AddChild(gltfSceneRootNode);
276+ }
277+ else
278+ {
279+ GD.PrintErr($"Couldn't load glTF scene (error code: {error}).");
280+ }
281+
282+ // Save a new glTF scene.
283+ var gltfDocumentSave = new GltfDocument();
284+ var gltfStateSave = new GltfState();
285+ gltfDocumentSave.AppendFromScene(gltfSceneRootNode, gltfStateSave);
286+ // The file extension in the output `path ` (`.gltf ` or `.glb `) determines
287+ // whether the output uses text or binary format.
288+ // `GltfDocument.GenerateBuffer() ` is also available for saving to memory.
289+ gltfDocumentSave.WriteToFilesystem(gltfStateSave, path);
290+
212291.. note ::
213292
214293 When loading a glTF scene, a *base path * must be set so that external
@@ -240,7 +319,8 @@ Godot's support for :ref:`doc_using_fonts_system_fonts`.
240319Example of loading a font file automatically according to its file extension,
241320then adding it as a theme override to a :ref: `class_Label ` node:
242321
243- ::
322+ .. tabs ::
323+ .. code-tab :: gdscript
244324
245325 var path = "/path/to/font.ttf"
246326 var path_lower = path.to_lower()
@@ -263,6 +343,37 @@ then adding it as a theme override to a :ref:`class_Label` node:
263343 # If font was loaded successfully, add it as a theme override.
264344 $Label.add_theme_font_override("font", font_file)
265345
346+ .. code-tab :: csharp
347+
348+ string path = "/Path/To/Font.ttf";
349+ var fontFile = new FontFile();
350+
351+ if (
352+ path.EndsWith(".ttf", StringComparison.OrdinalIgnoreCase)
353+ || path.EndsWith(".otf", StringComparison.OrdinalIgnoreCase)
354+ || path.EndsWith(".woff", StringComparison.OrdinalIgnoreCase)
355+ || path.EndsWith(".woff2", StringComparison.OrdinalIgnoreCase)
356+ || path.EndsWith(".pfb", StringComparison.OrdinalIgnoreCase)
357+ || path.EndsWith(".pfm", StringComparison.OrdinalIgnoreCase)
358+ )
359+ {
360+ fontFile.LoadDynamicFont(path);
361+ }
362+ else if (path.EndsWith(".fnt", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".font", StringComparison.OrdinalIgnoreCase))
363+ {
364+ fontFile.LoadBitmapFont(path);
365+ }
366+ else
367+ {
368+ GD.PrintErr("Invalid font file format.");
369+ }
370+
371+ if (!fontFile.Data.IsEmpty())
372+ {
373+ // If font was loaded successfully, add it as a theme override.
374+ GetNode<Label>("Label").AddThemeFontOverride("font", fontFile);
375+ }
376+
266377ZIP archives
267378------------
268379
@@ -285,7 +396,8 @@ through the Godot editor to generate PCK/ZIP files.
285396Example that lists files in a ZIP archive in an :ref: `class_ItemList ` node,
286397then writes contents read from it to a new ZIP archive (essentially duplicating the archive):
287398
288- ::
399+ .. tabs ::
400+ .. code-tab :: gdscript
289401
290402 # Load an existing ZIP archive.
291403 var zip_reader = ZIPReader.new()
@@ -312,3 +424,37 @@ then writes contents read from it to a new ZIP archive (essentially duplicating
312424 zip_packer.close_file()
313425
314426 zip_packer.close()
427+
428+ .. code-tab :: csharp
429+
430+ // Load an existing ZIP archive.
431+ var zipReader = new ZipReader();
432+ zipReader.Open(path);
433+ string[] files = zipReader.GetFiles();
434+ // The list of files isn't sorted by default. Sort it for more consistent processing.
435+ Array.Sort(files);
436+ foreach (string file in files)
437+ {
438+ GetNode<ItemList>("ItemList").AddItem(file);
439+ // Make folders disabled in the list.
440+ GetNode<ItemList>("ItemList").SetItemDisabled(-1, file.EndsWith('/'));
441+ }
442+
443+ // Save a new ZIP archive.
444+ var zipPacker = new ZipPacker();
445+ var error = zipPacker.Open(path);
446+ if (error != Error.Ok)
447+ {
448+ GD.PrintErr($"Couldn't open path for saving ZIP archive (error code: {error}).");
449+ return;
450+ }
451+
452+ // Reuse the above ZIPReader instance to read files from an existing ZIP archive.
453+ foreach (string file in zipReader.GetFiles())
454+ {
455+ zipPacker.StartFile(file);
456+ zipPacker.WriteFile(zipReader.ReadFile(file));
457+ zipPacker.CloseFile();
458+ }
459+
460+ zipPacker.Close();
0 commit comments