Open Emasoft opened 9 years ago
@Emasoft You seem to be very knowledgeable with SVGs and SMIL, so I hope you'll also give me some feedback on my work as I get closer to completion :wink:
@dalboris A hierarchy of layers is much the same to me, sounds good. Would multiple parents be a possibility with this system? I am familiar with the issues of multiple inheritance, and it could be difficult to display, but it's still a question worth asking.
@Emasoft Yes, thank you! For this specific shot I would just make the whole train one layer, without sublayers for individual cars, since indeed Z-ordering is fixed between layers, but not between strokes within a layer.
Basically, the issue is that "grouping" is useful for different reasons:
In theory, the hierarchy used for scene management might be different from the hierarchy for Z-ordering, different from the hierarchy used for cascading styling, and different from the transform hierarchy, since those concepts are orthogonal. But in practice, that's just too much of a hassle and some, if not all, of these hierarchies are shared, which makes for easier management and mental model of what's happening. But that comes with limitations, for instance you can't have different "entities" for each train's car, because scene management is merged with Z-ordering, which is unfortunate in this case.
In the short term, the concept of layer in VPaint would "group" (oops, sorry ;-) ) together scene management, Z-ordering, and transform hierarchy. In addition, there would be an independent Z-ordering system to deal with ordering within a layer (the current system, where ordering can be manually specified per-frame per-stroke).
In the long term, implementing orthogonal mechanisms to save/restore selections (possibly smart: i.e. if at a given frame, you split an edge into two edges, then saved selections containing the initial edge should now contain the two new edges instead), or to share style (the simplest being that each per-frame stroke may optionally store a pointer to a "named style" to use, instead of actual style data) are all options to consider. :-)
@scribblemaniac No, I do not consider multiple parents, which is indeed more likely to introduce more problems than it solves ;-)
"Smil falls as svg rises" http://alistapart.com/article/web-animation-past-present-and-future
Hi @scribblemaniac ! I'm going through the list of bugs / feature requests in preparation of VPaint 1.7 in the coming weeks. It might be a good idea to consider merging your work on importing SVG, so that it's not wasted work.
I know this was a long time ago, but would you consider it in a somewhat releasable state? It will still be tagged with "BETA" so it doesn't have to be perfect, but I see that the last commit is "Began refactoring for the g tag", so I wouldn't want to try merging something in a half-refactored state ;) Does it support <g>
tags at all right now? What happens if you try? (crash? ignore the <g>
tag and its children? Ignore the <g>
tag but not its children, and behave as if all children were outside the group?) I know I can try myself but you probably have better insight.
Cheers!
I'll take a second look at this. If memory serves me correctly, I did not get the <g>
tag working. It won't crash, but it probably won't render anything inside of <g>
tags. Ignoring them but not the children is not a good idea because their attributes affect all of their children so you could end up with elements in the wrong place, wrong color, etc.
You're right, very good point, especially the transform attribute of the group is super important.
Still doing a little work on the SVG export.
We're now a bit more compliant w.r.t. stroke/fill opacity, although we can't be 100% compliant because VPaint rendering model doesn't currently allow for per-group alpha compositing. So it's impossible to get the correct behavior for the second example of the bottom-row of:
https://www.w3.org/TR/SVG11/images/masking/opacity01.svg:
(top: Chrome; bottom: VPaint)
For future reference when implementing this in VGC, I've added a detailed comment in SvgPresentationAttributes::applyChildStyle(XmlStreamReader &xml)
VPaint now supports the transform attribute :-)
Here are some examples from https://www.w3.org/TR/SVG11/coords.html (with text converted to paths in Inkscape prior to importing in VPaint):
Good news: VPaint now also supports the CSS style-attribute way of setting stroke
, stroke-width
, fill
, opacity
, etc. This means that simple files (that is, not using gradients, patterns, dashes, markers, non-round stroke join/cap, symbols, clipping, masking, or embedded JPG/PNG images) generated by Inkscape should now be correctly imported by VPaint as it. :)
Any update on SVG/SMIL import and export?
Even a simple frame by frame SMIL animation would do:
<g id="frames60fps" style="display:inline">
<animate
attributeName="display"
fill="freeze"
repeatCount="indefinite"
dur="1.3s"
keyTimes="0;0.961;0.992;1"
values="none;inline;none;none" />
...
<g id="frame001" style="display:inline">
(...paste the svg frame as a group here...)
</g>
<g id="frame002" style="display:inline">
(...paste the svg frame as a group here...)
</g>
<g id="frame003" style="display:inline">
(...paste the svg frame as a group here...)
</g>
…
...
</g>
And for embedded/linked bitmap animations:
<svg version="1.1" baseProfile="tiny" id="svg-root"
width="100%" height="100%" viewBox="0 0 480 360"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="320" height="240" xlink:href="frame001.jpg">
<animate id='frame_001' attributeName='display' values='inline;none'
dur='0.01667s' fill='freeze' begin="0s" repeatCount="indefinite"/>
</image>
<image width="320" height="240" xlink:href="frame002.jpg">
<animate id='frame_002' attributeName='display' values='none;inline'
dur='0.01667s' fill='freeze' begin="0.01667s" repeatCount="indefinite" />
</image>
<image width="320" height="240" xlink:href="frame003.jpg">
<animate id='frame_003' attributeName='display' values='none;inline'
dur='0.01667s' fill='freeze' begin="0,03334s" repeatCount="indefinite" />
</image>
….
</svg>
Thanks @Emasoft for the examples! I haven't worked on that yet, and I don't think I will take the time to implement it in VPaint as I'm focusing on the dev of VGC Illustration/Animation. But yes, I would like to have such import/export in VGC, although I don't have a timeline for this yet.
I’ve found a very efficient way to encode frame by frame animations in SVG. Much better than the last code I posted above.
<svg version="1.1" baseProfile="tiny" id="svg-root"
width="100%" height="100%" viewBox="0 0 160 160"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>
SIMPLE FRAME BY FRAME ANIMATION
Coded by Emasoft
Example implementation of basic SVG frame-by-frame animation, for
educational purpouses. The frame based animation is easy to export.
No javascript or CSS, just pure SVG.
In this way the SVG format is used like an MPEG for vector animations.
This animation has only 3 frames:
Frame 01 = square
Frame 02 = circle
Frame 03 = triangle
This file is divided in two sections:
1) The Definitions (defs) : Here you need to put all frames and clipping paths.
All frames require an unique id. For example: frame0001, frame0002, etc.
All elements of a frame must be wrapped in a group with such id.
Objects written here are not displayed until the animation cycle instances them.
2) The Animation Scene (a group called "animation_scene") : Here you need to put
the elements on the scene. First the background rectangle (with or without a
clipping path), then the animated group of objects (called "animated_group").
The animation element needs the following parameters:
values : the id of the frames, with a leading # char and separated by a ; char.
The frames must be named in the exact order you need them to be displayed.
Also the first frame id must be indicated in the "use" element as the href
(example: xlink:href="#frame0001" ).
begin : the start time delay, in seconds (example: 0s).
repeatCount : this should set on "indefinite" if you want a looping animation.
Otherwise on "0" if you want the animation to stop at the last frame. Any other
number would be the number of repetitions of the entire sequence.
dur : the duration in seconds of each frame. For example: "1.0" means 1 frame
per second. For 60fps is "0.01667". For 24fps you have "0.04167" seconds.
(just divide 1 for the number of frames, i.e. 1/60=0.0166666.., aprox: "0.01667").
Gist: https://gist.github.com/Emasoft/e86b227d7acd5b21794a5af1a50126d6
</desc>
<defs>
<clipPath id="_clipPath_background">
<rect width="512" height="512"/>
</clipPath>
<g id="frame0001" style="display:inline">
<rect
style="fill:#edd154;fill-opacity:1;stroke:#3c352d;stroke-width:2;stroke-opacity:1;"
id="square"
width="100"
height="100"
x="30"
y="30">
</rect>
</g>
<g id="frame0002" style="display:inline">
<path
style="fill:#edd154;fill-opacity:1;stroke:#3c352d;stroke-width:2;stroke-opacity:1;"
id="circle"
d="m 125,80 a 45,45 0 1 1 -90,0 45,45 0 1 1 90,0 z">
</path>
</g>
<g id="frame0003" style="display:inline">
<path
style="fill:#edd154;fill-opacity:1;stroke:#3c352d;stroke-width:2;stroke-opacity:1;"
id="triangle"
d="M 105,105 47,89 89,46 105,105 z">
</path>
</g>
</defs>
<g id="animation_scene">
<g id="background" clip-path="url(#_clipPath_background)" style="transform: scale(3); transform-origin: center;">
<rect x="0" y="0" width="512" height="512" transform="matrix(1,0,0,1,0,0)" fill="rgb(90,145,240)"/>
</g>
<g id="animated_group">
<use width="160" height="160" xlink:href="url(#frame0001)">
<animate attributeName="xlink:href"
values="
#frame0001;
#frame0002;
#frame0003"
begin="0s" repeatCount="indefinite" dur="0.5s"/>
</use>
</g>
</g>
</svg>
GIST 1 : basic prototype 3 frames svg smil GIST 2 : basic walk cycle frame by frame svg smil GIST 3 : panther frame by frame animation svg smil GIST 4 : seagull frame by frame animation smil fbfsvg
CODEPEN 1 : basic prototype 3 frames svg CODEPEN 2 : basic walk cycle frame by frame in pure smil CODEPEN 3: panther and bird frame by frame animation in pure smil CODEPEN 4: seagull frame by frame animation smil fbfsvg
Wow, this is really going to change the way vector animations are done! But please support the SVG file format instead of limiting yourself to the VEC format. You need to make your application able to communicate with the world of graphic design. All you need is to save frames as SVG files or as SVG SMIL animations and to import vector images as keyframes. The SVG file format is an open standard widely used, and the accepted standard for vector images.
We need four options:
Please add support for SVG if you want your app to become popular and used in real world applications (from websites icon animations to cartoon movies).
P.S: You can also consider the option to integrate vpaint in Inkscape as a Plugin. It would be awesome. There are already some morphing plugins, but they are so primitive to be useless. Yours, instead, will make a true revolution, and people using Inkscape will start making SVG animations immediately and making your app very popular. Here is a proposal I made some time ago for a SVG animation plugin for Inkscape: