How do i include svg files?

Godot Version

4.51

Question

How do I include svg files in my project for access as svg files. If I simply add the files and try to access them through res instead of getting an svg I get a raster image. Is loading from the filesystem the only option ?

svg files will always be rasterized. Godot does not support vector graphics. You can re-import them as DPITexture which will automatically rasterize them when their size changes.

To do this select the svg file in the FileSystem dock and go to the Import dock and choose DPITexture in the Import As: dropdown.

I don’t want to use the svg files in a node or any UI elements, they are not for display. I need the svgs to be able to generate output files based on UI selections.

So I would like them to be treated like txt files or other non image files.

You’re going to need to very very specific about what you’re planning to do if you want an answer to that. There are all sorts of things you can do with an svg file once it is loaded. However describing what you are trying to do also might allow us to give you alternatives to reach your end goal.

1 Like

I have code that takes a list of input svgs and combines them into a larger svg, placing each input svg based on position, rotation etc. I have a UI that configures these properties, and provides a preview of the output. This works (thanks mrcdk).

Now I have to figure out how to include the source svg files in the project so that they can be accessed as svgs so that they can be combined.

If it’s working for you great. Read the documentation on DPITexture, which was introduced recently, which @mrcdk mentioned. Just keep in mind it may not have everything you want. In which case you’ll have to drop to C++ and roll your own version of Godot.

You can also look into Control nodes and using them to scale your textures.

I meant the UI was working using the filesystem to load the svgs from absolute paths that are not part of the project.

Which is why I was hoping to figure out how to include the svg files that are the source files in the project itself. I guess I though maybe there was a way other than using the filesystem to do it.

Edit:

I just tried the FileAccess object to get the svg file reference from the resources. If I then use the file reference with GetAsText it seems to be what I needed. Sample code in case it helps anyone.

string relativePath = "packs/S7d31msP/textures/objects/bridge/bridge_chair.svg";

if (FileAccess.FileExists("res://" + relativePath))
{
    using var file = FileAccess.Open("res://" + relativePath, FileAccess.ModeFlags.Read);
    string content = file.GetAsText();
    GD.Print(content);
}

Thanks for the help.

Worth noting if you export your project that file may not exist, change it’s import settings to “Keep File” otherwise it will be packed into a compressed raster texture and named differently. Not sure the scope of your project though if this is a tool then you’re fine!

1 Like

Oh I didn’t know that. I was hoping I could use the svgs as raster images in the preview but then have access to the base svg file for creating the ouput file instead of having to have duplicates of each svg one for the preview window, and one for generating output.

However it would be impractical to have to adjust the hundreds of files to adjust the import settings.

Secondly in the import settings I have to choose either import as texture2d or keep as is, there is no option for both.

I guess I’ll just have to have duplicate files for each resource or something.

Edit:

How much overhead if instead of duplicating things I just use Image.Load() to load the image from the file system, and the use ImageTexture.CreateFromImage() at runtime for creating the raster images on the fly?

Have you tried exporting this project yet? I believe you will find your code breaks when you export because everything gets remapped. In which case you have to add .remap to the end of the filename.

I’m gonna go back to, I don’t know what you’re doing, but it feels as if you are going the hard way around. It might helped if you showed us a screenshot of what you’re doing and explained what output file you are trying to create. It’s still unclear why you want to keep the contents of the svg file itself not as an image.

I want to keep the svg files because the output file is a dynamic svg file which contains multiple individual svgs combined. As I have explained multiple times.

I have a ui to set some properties , when an object is configured I click add, I add it to the preview panel (not efficient - currently just working out proof of concept) by creating a texture rectangle placing it at the x,y coordinates in the above properties. This image is the same as the svg only currently what I am doing is I have png generated files- these are in the project and they are used as textures to display each object in the UI.

However when all objects have been added and the preview looks good, I click the save button which creates a new svg, and adds the specified source svgs at the position, with a rotation specified in the properties. It also replaces certain colors with custom colors if required.

So to create the output svg I need the source svgs to be available as svgs. I also need to display the source svgs in UI as well for generating a preview thus the need for two versions currently.

Overhead depends on the SVG, it should be slightly quicker than the time it takes the editor to import the same SVG.

You will have to import as Keep File or the “res://” paths will be renamed and imported. You mention the filesystem and a save button, do you intend to pick SVGs from the user-defined filesystem? Not from “res://”? Is this project a tool for editing SVGs? If so you should avoid “res://” in general, including the base load function (Image.load is fine and meant for runtime files) It may help to explain the full breadth of your project if you have further questions.

2 Likes

I realize this makes sense in your head as a full explanation, but it does not convey any new information. Some screenshots might help. In my mind, the only reason to do it this way is you have complex geometric pieces, say the 5 points of a star, that all intersect, and you need to keep all the edges aligned when resizing the screen.

But then I see this, and I think, why go through all that trouble for a rectangle?

This makes more sense. So you are creating some sort of art program?

This makes more sense. But now the question is, why do you want to save the files as SVGs?

I’m not sure if this is a big secret project you don’t want us to know about, or you’re just not used to asking for programming help, but like @getkeno just said, and I said before, it might help for you to pretend that we are not in your head reading your mind, and that telling us the whole scope of your project might help us help you.

Why does it matter why I want the final product to be a svg?

For the current thing I am working on this is the entire scope of the project. Generate an svg from source svgs that is basically a tile map in svg form.Nothing more, nothing less.

It’s just to display the preview I need raster images and to generate the final svg I need the svgs as an svg.

1 Like

If I use the filesystem, I would not include any of the svgs in the project but rather just reference them using absolute paths.

Have the user set a base path, and then just use relative paths based on the selected source path or something.

Because Godot does not have full support for SVGs.

And for the other reasons I already gave you multiple times.

Good luck.

The reason it’s svg is because I have a battlemap generator that use procedural generation to build a ship layout. It has hull definitions and rooms that contain objects and generates different layouts randomly and it expects the rooms to be in svg format.

These maps are then used in a web app which also expects the source to be svg.

However it’s all line art in black and white.

I now have nice objects to populate the rooms with as well as new walls and new hulls etc all done in color. Now I need an easy way to generate the maps for the rooms so that I can use them to generate much nicer looking maps and automate as much of the process as possible and tracking rooms as they get finished.

I decided to use Godot because it has a decent UI toolkit that is cross platform and intrinsic support for displaying images for creating a preview of the map.

Currently it works for my use case, but I was thinking if I can make it generic enough it might be useful to other people who need to combine svgs, like say you have to layout multiple plots and or graphs on a page.

Edit Update:

So I came up with something that works. I included the svg files as content in the C# project, and set them to be copied to the output folder. However when run in the editor or when debugging this content is directly in the same folder relative to the exe because the editor runs the project. When exported this content ends up in a folder starting with data, in this case the folder is called data_RoomMapper_linuxbsd_x86_64.

So I had to come up with a check to see if the project was in editor or exported:

var path = ProjectSettings.GlobalizePath("res://");
		
		if (path == String.Empty)
		{
			path = OS.GetExecutablePath().GetBaseDir();
			string searchPattern = "data*"; 
			string[] matchingDirectories = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
			
			if (matchingDirectories.Any())
			{
				GD.Print("A folder starting with 'data' exists.");
				// Optionally, get the first matching folder name
				string firstFolderName = Path.GetFileName(matchingDirectories.First());
				GD.Print($"First matching folder found: {firstFolderName}");
				path = Path.Join(path, firstFolderName) + "/";
			}
			else
			{
				GD.Print("No folder starting with 'data' was found.");
			}
			
		}
	
		GD.Print(path);
		resourceBasePath = path;

Then I just access the files with FileAccess:

setPath();
string relativePath = "packs/S7d31msP/textures/objects/bridge/bridge_electronics.svg";
bool found = FileAccess.FileExists(resourceBasePath + relativePath);

if (found)
{
    GD.Print("FOUND");
}

Everything is still duplicated but at least it I only have one set of svgs and they can all be maintained within the project.

Which leads me to a question, my code to find the data folder depends on the data folder to start with data, is this the case when exported for a different platform? Or even better is there a built in variable for getting this folder?

Thanks for all the help and suggestions they are appreciated.

1 Like