mewpurpur / godsvg Goto Github PK
View Code? Open in Web Editor NEWAn application in early development for creating simple vector graphics. Built in Godot.
Home Page: https://godsvg.com
License: MIT License
An application in early development for creating simple vector graphics. Built in Godot.
Home Page: https://godsvg.com
License: MIT License
The button is disabled, but it shouldn't be.
GodSVG is going to stick to the SVG basics and not support most of the SVG elements and attributes out there. This means that imported SVGs are often going to have undetected tags. A basic Import Error Window would work the following way:
In the future, ways to correct the SVG could be implemented (e.g. expanding style attributes), but for an initial implementation this is not necessary.
resizing the view cause the shape to move most likely because of imprecision
https://github.com/MewPurPur/GodSVG/assets/66184050/2744d236-db28-4b6d-bd9a-64daae52c60e
When an absolute S command follows an absolute C or S command, the contour drawn is incorrect.
Problem 1: Viewbox is automatically coupled at the beginning.
Problem 2: Changing values is only possible from the code editor.
Problem 3: Certain shape contours (elliptical arcs) are fudged.
The path editor is a complex widget that's kind of dysfunctional at the moment. I want to untangle the mess now and make the LineEdit with the value editable.
The path editor, like all attribute editors, will hold a value
variable that would be tied to changes to the main SVGData resource, which will allow it to communicate its changes externally. get modified externally. But this one is peculiar.
value
here is the quirky string, but to have a clean way to edit the individual commands this string represents, we need some way to represent it as an array of objects. This is already done.commands
property that would need to be synchronized with the value
. This array is then used to populate the path editor with command editors.This means that the following infrastructure is required:
But let's look at it closely... There are the following four ways this value could be edited, and they need kind of contradictory side effects.
value
-> Generate new path commands -> Rebuild inspector without autogenerating new value
value
value
without rebuilding the inspectorvalue
, rebuilding the inspector is acceptableSo the value
should change after all of these operations, but sometimes it should rebuild the inspector, and sometimes not.
Currently, changes that happen externally change the value
variable, whose setter adjusts the property editor if needed. Normally this is not a problem, but here, changed value
might mean that the path editor needs to be completely rebuilt (e.g. if you paste a pathdata into the CodeEdit with completely different commands). But this would be in the setter, so the whole path editor would need to be rebuilt every time the value changes, even from internal changes. This is actually undesired - if you click off from one number field into another - which should be common - you'd not be able to select it, because just then the path editor would rebuild.
There are some hacks that could fix this, but what I'm thinking of right now is to, instead of a full rebuild, do a check on the existing command editors and whether they are consistent with the path data being used for the rebuild. If there is an inconsistency in the numbers or flags, simply adjust them; and if there's an inconsistency in the commands, strip out the remaining command editors and rebuild the rest. This would have less overhead and avoid the aforementioned problem.
Dragged handles are also a challenge, right now they hold two SVGAttributes to be forced as their X and Y. I'm planning to make it so the generic handle is a base class, and there are two types of handles that inherit it - a NonPathHandle and a PathHandle. The NonPathHandle will be the current one, while the PathHandle will take in a single SVGPathAttribute and the index of the command it is to represent.
Since the path logic will be essentially split in two places, I will have a ParsedPathData class with static functions for parsing from a pathdata string to an array of path command objects, and in the opposite direction. The path editor will use them, and also the handles to know how to actually set the value they are to edit.
This should be a solid path infrastructure, hopefully nothing goes wrong. Tomorrow is gonna be fun for sure.
Use Godot's UndoRedo to make actions reversible. Add Ctrl+Z
as a shortcut; for Redo, allow both Ctrl+Y
and Ctrl+Shift+Z
. For an initial implementation, the whole SVG's state can be saved after each action, rebuilding all global definitions and tag editors in the process.
Interestingly, the code editor's own UndoRedo already works quite decently. But it considers every adjustment as an action, even if you're just holding a spinner arrow or dragging a handle.
Turns out, high zoom levels in Image.load_svg
cause extreme performance penalties, to the point where even a 16x16 texture causes lag spikes at the highest zoom levels.
I have no idea how to fix this right now, although #103 did improve the situation slightly by turning the contours texture into draw commands which cause less slowdown in the worst case and can also be optimized without sacrificing quality.
For this one, something different would be needed. Maybe constantly redrawing the SVG as you scroll around in the viewport, so a smaller section is drawn? (I fear this will cause stutters so maybe I'll have to think harder.
An initial implementation should have the following:
Would be great to also implement some kind of visual for how the gradient looks.
SVGs are really taxing on performance, so this should reduce the overhead of changing the SVG and zooming in/out by at least a little bit (probably by something like 40%).
This will also fix how these outlines aren't drawn outside the texture even if they stretch a little out.
Care should be taken to not draw a lot of lines out of bounds (like if you put x=999999 y=999999 as a curve end point in a path) as this might freeze the app if it's not done with care.
Clicking on a path command parameter editors after just editing a path command in not selecting it.
Can probably be fixed by making it so the path command editors are only rebuilt fully when there is a change in the command layout.
https://github.com/MewPurPur/GodSVG/assets/66184050/0a64b6d7-4c83-4c7f-b398-7eb80ac58cc1
5. when switching too much the viewbox it makes it distort :
I just cloned, imported it from the Project List and opened the project. Then without making any changes, I get this error:
Invalid get index 'window_mode' (on base: 'null instance')
and its stopping in the "_enter_tree()" at like 45.
I want to try to use this, but I'm stuck here.
Just writing out what's on my mind right now, as I try to figure out a good infrastructure that would allow to make SVG elements and attributes configurable from multiple places.
This post might be edited a few times as I rethink things.
The core idea is that the SVG singleton will hold data, which will be the defacto way to manipulate anything about the SVG. This data will be independently able to be manipulated by:
As before, there will be:
This is a rough simplification. So, these RefCounteds should also emit specific signals when they are changed.
value_changed()
attribute. SVGTag would be subscribed to this and emit attribute_changed()
itself.attribute_changed()
signal for now. SVGData will be subscribed to this signal and emit attribute_changed()
itself.attribute_changed()
signal as explained. It will also have resized()
, tag_deleted()
, tag_added()
, tag_moved()
, and tags_changed_unknown()
signals.TODO: What about individual path commands in a path definition?
TODO: How to signal information about which specific things updated?
The "Display" TextureRect will be subscribed to all SVGData signals with its queue_svg_update()
function, always updating the SVG when something changes.
Talking: When I make it editable, I plan to make it so after every edit, the text is checked for being a valid svg string. If it is, then gather from it all the values needed to make up a width, a height (I'll address viewBox later), and an array of SVGTags, and assign all that to the existing SVGData. This will emit the tags_changed_unknown()
and resized()
signals.
Listening: It will listen to all SVGData signals and use tags_to_string()
to translate the data. But if it's currently being edited, it won't change its text. Unlike other ways to edit the SVG, we don't want to change the text to a standard generated one while the user is editing it.
They will be handled in a TextureRect overlaid on top of the SVG.
Talking: Each handle will hold a reference to its the relevant SVGAttributes in the svg data: one for its x-pos, and one for its y-pos. While a handle is being dragged, it will use its X and Y position to update these two attributes.
Listening: All SVGData signals except for tag_moved()
will be listened to. They will trigger a full rebuild of the handles, except for attribute_changed()
which will search for the appropriate handle and update its x or y position.
TODO: What about individual path commands in a path definition?
Talking: Each tag editor will hold a reference to its relevant SVGTag in the SVGData, and likewise each of the fields will hold a reference to its relevant SVGAttribute. The signals that will be emitted on each possible action are pretty self-explanatory.
Listening: All SVGData signals except for resized()
will be listened to. tags_changed_unknown()
will trigger a full rebuild, while the others will only change the relevant parts.
TODO: How to find which tag editor or attribute editor corresponds to a certain tag? Iterating and checking?
People have different preferences between zooming up/down to zoom in/out. I think we should accommodate that with a setting in GlobalSettings that's checked against when using the mouse scrollwheel.
This list will be kept up-to-date.
Self-explanatory.
A "Move" button on each tag, which should use drag-and-drop to be moved around.
All shape-related SVG tags should draw their own controls in the editor, for example, the ellipse
tag should have a control for the center and for its two radii. There could also be an option for hiding them to see the clean SVG image, as well as to drag them around and update the corresponding SVG tag itself, but this isn't needed for the initial implementation.
Stroke and fill-related properties should be hidden when stroke
or fill
is set to none.
Use Godot's UndoRedo to make actions reversible. Add Ctrl+Z as a shortcut; for Redo, allow both Ctrl+Y and Ctrl+Shift+Z. For an initial implementation, the whole SVG's state can be saved after each action, rebuilding all global definitions and tag editors in the process.
No implementation details on my mind yet, but @ajreckof seems to have something on mind.
Using touchpad gestures should zoom in such a way that the cursor becomes the center.
No implementation details on my mind yet. Feedback welcome.
Enhancements and bugfixes are always welcome, even if not on the list.
set application setting application/run/low_processor_mode
to true. Hence the screen is not redrawn if nothing changes visually ,this Godot feature is meant for applications
This would be in each individual path command and look exactly like the current dropdown menu. When you pick a command, it gets auto-inserted after the current one (The current dropdown menu might actually become kinda obsolete after this?)
For a start, it can be two arrows to make the tag move one step up or down. This is not so hard to anymore since the CodeEdit is now editable, but it would still be nice to have this functionality. I think the most challenging part here is figuring out a universal UI/UX that doesn't take too much space.
Viewbox is automatically coupled at the beginning, changing the viewbox and corrupting SVGs a lot of the time.
Viewbox also doesn't automatically decouple when you change the viewbox from the code editor.
Self-explanatory, GodSVG needs a good app icon. I'm thinking of keeping the blue flame, maybe even having some subtle reminiscence of Godot in its overall shape. I don't think the handle is necessary, or the eyes. The eyes are cute though, I'll try to keep them when/if I wind up making the design!
Zooming should keep the viewport's center, or make the mouse position the new center if mousewheel is used.
Steps to reproduce:
M
)A
)This freezes GodSVG for me on Ubuntu 22, Godot v4.1 rc1, and Godot is not leaving any trace. I have tried to patch it, but couldn't.
This is because I'm checking against get_global_rect()
. Ideally, I'd be using mouse_entered
and mouse_exited
, but for some reason this doesn't seem to work.
Commands that aren't allowed should be grayed out rather than removed.
Path Commands should be individually selectable. The selection should be mutually exclusive with tag selections (i.e. if you select a path command, you can't Ctrl+Click to select tags too, and vice versa). The selected path tag would highlight the handle in the display viewport and . Hovering should also have the usual indication.
The fix for #112 didn't address the situation for tangents.
Tangents should be drawn at the bottom too, with multiline instead.
The git clone example code lists the wrong repo
This would be a pre-requisite for future work on minifying inputs and optimizing SVGs. But long before work on that begins, it's going to just be a nice quality of life thing.
This is so that you don't have to zoom in or out very far depending on the svg size, and that the percentage display between the zoom buttons indicates how far its been zoomed relatively to its size.
A possible way of doing this would be to look at the specified viewBox (I believe this is how its called) inside the svg and work with that.
It's an abomination. I should look into whether it can just use the default OS file manager.
If not, it still needs better theming - but it's really hard to work with the Godot node, so I hope I don't have to fix everything myself.
Cubic Bezier curves should draw two lines from each point to its in/out control, while quadratic Bezier curves should draw from both points to their single control. The lines should be smaller than normal contours. There should be handles for:
Handles should probably have a draw_mode
enum, that would be used to discern between normal handles and Bezier controls.
The minimum requirement to call this implemented would be to:
Selecting a path tag is equivalent to selecting all of its path commands.
This will help with finding where a tag's handles are.
Caused by #72. I'm working on this already.
Make things like sqrt(2)
, 2 + 5.6
, 2,5
neatly evaluated in number fields. Godot's EditorSpinSlider has a really good system for this, I wonder if I can replicate it.
Would be nice if related properties had a way to be grouped together, just visually, to reduce horizontal space and signify that they are related. The best example would be coordinates with X and Y components, as well as colors and their opacity attribute.
The draw calls are executed in order of the path commands. But that's wrong; instead, each color (selected/hovered/default) should have its lines/polylines saved in arrays for normal/selected/hovered and drawn at the end, first all normal ones, then all selected ones, then all hovered ones.
For a start, we could draw these as separate polylines, but ultimately it'll be a good idea to try to connect together lines into polylines as much as possible.
I haven't investigated why yet, but paths very often have misplaced handles. This is tied to the Close Path command (z
) and I'm assuming the problem is that it's not accounted for by the handles after in locate_start_points()
of PathCommandArray.
Fixing this is high-priority and should be relatively straightforward.
Editing path data causes everything to rebuild.
This is very challenging. Paths have several ways they can be edited.
value
-> Generate new path commands -> Rebuild inspector without autogenerating new value
value
value
without rebuilding the inspectorBut...
value
has a setter that propagates the change to other parts of the codebase. It's also the thing that can be changed by other parts of the codebase.How do I get out of this conundrum? I don't know, but it's a very high priority bugfix.
Allow to duplicate tags from the same menu where the Move Up / Move Down options are. The deletion button can also be moved there to free up space (and not have a destructive operation easily available)
The svg is missing the namespace which is needed for any app to render the svg. This is the xlmns
parameter in the svg tag.
The repository currently doesn't seem to contain any license. Could you add one, please? See Choose a License for more information 🙂
The reason is probably that an input function somewhere doesn't catch the mouse input actions.
Should be an easy fix.
Arcs and Curves are just too wide, when they stretch wider than the inspector, they can mess up the UI.
Yet, I feel like what needs to be done here is come up with a smaller widget for editing XY pairs of values. (#54)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.