25#include <fmt/format.h>
44 uint8_t r =
color[0] * 255.0f;
45 uint8_t g =
color[1] * 255.0f;
46 uint8_t
b =
color[2] * 255.0f;
47 return fmt::format(
"#{:02X}{:02X}{:02X}", r, g,
b);
52 const float stroke_opacity,
59 node.append_attribute(
"stroke").set_value(stroke_hex.c_str());
60 node.append_attribute(
"stroke-opacity").set_value(stroke_color.
a * stroke_opacity);
62 node.append_attribute(
"fill").set_value(
"none");
63 node.append_attribute(
"stroke-linecap").set_value(round_cap ?
"round" :
"square");
68 const float layer_opacity)
74 node.append_attribute(
"fill").set_value(stroke_hex.c_str());
75 node.append_attribute(
"stroke").set_value(
"none");
76 node.append_attribute(
"fill-opacity").set_value(fill_color.
a * layer_opacity);
84 const float thickness,
85 const std::string &hexcolor)
87 pugi::xml_node rect_node = node.append_child(
"rect");
88 rect_node.append_attribute(
"x").set_value(
x);
89 rect_node.append_attribute(
"y").set_value(
y);
90 rect_node.append_attribute(
"width").set_value(width);
91 rect_node.append_attribute(
"height").set_value(height);
92 rect_node.append_attribute(
"fill").set_value(
"none");
93 if (thickness > 0.0f) {
94 rect_node.append_attribute(
"stroke").set_value(hexcolor.c_str());
95 rect_node.append_attribute(
"stroke-width").set_value(thickness);
102 std::string get_node_uuid_string();
128 std::optional<float> width);
129 pugi::xml_node
write_path(pugi::xml_node node,
143std::string SVGExporter::get_node_uuid_string()
145 std::string
id = fmt::format(
".uuid_{:#x}", this->_node_uuid++);
151 this->_node_uuid = 0;
155 const int frame_number = scene.
r.
cfra;
169 const int orig_frame = scene.
r.
cfra;
174 if (selection_only) {
181 frames,
GrainSize(1024), memory, [&](
const int frame_number) {
199 pugi::xml_node frames_group_node = main_node.append_child(
"g");
200 frames_group_node.append_attribute(
"id").set_value(
"blender_frames");
201 frames_group_node.append_attribute(
"display").set_value(
"none");
203 const int frame_count = frames.
size();
207 scene.
r.
cfra = frame_number;
214 scene.
r.
cfra = orig_frame;
231 std::string frametxt =
"blender_frame." + std::to_string(frame_number);
245 pugi::xml_node clip_node = node.append_child(
"clipPath");
246 clip_node.append_attribute(
"id").set_value(
247 (
"clip-path." + std::to_string(frame_number)).c_str());
252 pugi::xml_node frame_node = node.append_child(
"g");
253 frame_node.append_attribute(
"id").set_value(
frame_name(frame_number).c_str());
257 frame_node.append_attribute(
"clip-path")
258 .set_value((
"url(#clip-path." + std::to_string(frame_number) +
")").c_str());
262 const Object *ob = info.object;
264 pugi::xml_node ob_node = frame_node.append_child(
"g");
268 std::string object_id = std::string(obtxt) + this->get_node_uuid_string();
269 ob_node.append_attribute(
"id").set_value(object_id.c_str());
277 if (!layer->is_visible()) {
280 const Drawing *drawing = grease_pencil_eval->get_drawing_at(*layer, frame_number);
281 if (drawing ==
nullptr) {
286 pugi::xml_node layer_node = ob_node.append_child(
"g");
287 std::string layer_node_id =
"layer." + layer->name() + this->get_node_uuid_string();
288 layer_node.append_attribute(
"id").set_value(layer_node_id.c_str());
298 options.convert_bezier_handles_to_poly_points =
false;
299 options.convert_bezier_handles_to_catmull_rom_points =
false;
300 options.keep_bezier_shape_as_nurbs =
true;
301 options.keep_catmull_rom_shape_as_nurbs =
true;
332 const std::optional<float> width,
333 const bool round_cap,
334 const bool is_outline) {
336 pugi::xml_node element_node =
write_path(layer_node, layer_to_world, positions, cyclic);
340 pugi::xml_node element_node;
343 layer_node, layer_to_world, positions, positions_left, positions_right, cyclic);
348 element_node =
write_polyline(layer_node, layer_to_world, positions, cyclic, width);
366 pugi::xml_node decl =
main_doc_.prepend_child(pugi::node_declaration);
367 decl.append_attribute(
"version") =
"1.0";
368 decl.append_attribute(
"encoding") =
"UTF-8";
370 pugi::xml_node comment =
main_doc_.append_child(pugi::node_comment);
371 std::string txt = std::string(
" Generator: Blender, ") +
svg_exporter_name +
" - " +
373 comment.set_value(txt.c_str());
375 pugi::xml_node doctype =
main_doc_.append_child(pugi::node_doctype);
377 "svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
378 "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"");
383 pugi::xml_node main_node =
main_doc_.append_child(
"svg");
384 main_node.append_attribute(
"version").set_value(
"1.1");
385 main_node.append_attribute(
"x").set_value(
"0px");
386 main_node.append_attribute(
"y").set_value(
"0px");
387 main_node.append_attribute(
"xmlns").set_value(
"http://www.w3.org/2000/svg");
389 std::string width, height;
400 main_node.append_attribute(
"width").set_value((width +
"px").c_str());
401 main_node.append_attribute(
"height").set_value((height +
"px").c_str());
402 std::string viewbox =
"0 0 " + width +
" " + height;
403 main_node.append_attribute(
"viewBox").set_value(viewbox.c_str());
410 const float duration)
412 pugi::xml_node use_node = parent_node.append_child(
"use");
413 use_node.append_attribute(
"id").set_value(
"blender_animation");
415 use_node.append_attribute(
"href").set_value(href_text.c_str());
417 pugi::xml_node animate_node = use_node.append_child(
"animate");
418 animate_node.append_attribute(
"id").set_value(
"frame-by-frame_animation");
419 animate_node.append_attribute(
"attributeName").set_value(
"href");
421 std::string duration_text = std::to_string(duration) +
"s";
422 animate_node.append_attribute(
"dur").set_value(duration_text.c_str());
423 animate_node.append_attribute(
"repeatCount").set_value(
"indefinite");
425 std::string animated_frame_ids = [&]() {
426 std::string frame_ids_text =
"";
428 std::string frame_url_entry =
"#" +
frame_name(frame) +
";";
429 frame_ids_text.append(frame_url_entry);
431 return frame_ids_text;
434 animate_node.append_attribute(
"values").set_value(animated_frame_ids.c_str());
443 pugi::xml_node element_node = node.append_child(
"polygon");
456 element_node.append_attribute(
"points").set_value(txt.c_str());
465 const std::optional<float> width)
467 pugi::xml_node element_node = node.append_child(cyclic ?
"polygon" :
"polyline");
470 element_node.append_attribute(
"stroke-width").set_value(*width);
484 element_node.append_attribute(
"points").set_value(txt.c_str());
494 pugi::xml_node element_node = node.append_child(
"path");
496 std::string txt =
"M";
511 element_node.append_attribute(
"d").set_value(txt.c_str());
523 pugi::xml_node element_node = node.append_child(
"path");
525 std::string txt =
"M";
537 if (
i != positions.
size() - 2) {
563 element_node.append_attribute(
"d").set_value(txt.c_str());
574 std::wstring wstr(filepath_16);
Low-level operations for curves.
Low-level operations for grease pencil.
bool BKE_scene_camera_switch_update(Scene *scene)
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
#define BLI_assert_unreachable()
void BLI_kdtree_nd_ free(KDTree *tree)
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
#define SNPRINTF_UTF8(dst, format,...)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
Object is a sort of wrapper for general info.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
unsigned long long int uint64_t
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
constexpr IndexRange drop_back(int64_t n) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr const char * c_str() const
IndexRange curves_range() const
bool has_curve_with_type(CurveType type) const
IndexMask indices_for_curve_type(CurveType type, IndexMaskMemory &memory) const
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_topology_changed()
float4x4 to_world_space(const Object &object) const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
GreasePencilExporter(const IOContext &context, const ExportParams ¶ms)
std::string coord_to_svg_string(const float2 &screen_co) const
blender::Bounds< float2 > screen_rect_
std::optional< float4x4 > camera_persmat_
const ExportParams params_
blender::Bounds< float2 > camera_rect_
void prepare_render_params(Scene &scene, int frame_number)
void foreach_stroke_in_layer(const Object &object, const bke::greasepencil::Layer &layer, const bke::greasepencil::Drawing &drawing, WriteStrokeFn stroke_fn)
Vector< ObjectInfo > retrieve_objects() const
bool is_selected_frame(const GreasePencil &grease_pencil, int frame_number) const
float2 project_to_screen(const float4x4 &transform, const float3 &position) const
GreasePencilExporter(const IOContext &context, const ExportParams ¶ms)
pugi::xml_node write_polygon(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions)
void export_grease_pencil_layer(pugi::xml_node node, const Object &object, const bke::greasepencil::Layer &layer, const bke::greasepencil::Drawing &drawing)
pugi::xml_document main_doc_
void export_grease_pencil_objects(pugi::xml_node node, int frame_number)
pugi::xml_node write_bezier_path(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions, Span< float3 > positions_left, Span< float3 > positions_right, bool cyclic)
void write_document_header()
pugi::xml_node write_main_node()
pugi::xml_node write_animation_node(pugi::xml_node parent_node, IndexMask frames, float duration)
bool write_to_file(StringRefNull filepath)
ExportStatus export_scene(Scene &scene, StringRefNull filepath)
pugi::xml_node write_path(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions, bool cyclic)
pugi::xml_node write_polyline(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions, bool cyclic, std::optional< float > width)
CCL_NAMESPACE_BEGIN struct Options options
bke::CurvesGeometry convert_curves(const bke::CurvesGeometry &src_curves, const IndexMask &selection, CurveType dst_type, const bke::AttributeFilter &attribute_filter, const ConvertCurvesOptions &options={})
@ InvalidActiveObjectType
static std::string rgb_to_hexstr(const float color[3])
static void write_fill_color_attribute(pugi::xml_node node, const ColorGeometry4f &fill_color, const float layer_opacity)
constexpr const char * svg_exporter_name
static void write_rect(pugi::xml_node node, const float x, const float y, const float width, const float height, const float thickness, const std::string &hexcolor)
ExportStatus export_svg(const IOContext &context, const ExportParams ¶ms, Scene &scene, StringRefNull filepath)
static std::string frame_name(int frame_number)
static void write_stroke_color_attribute(pugi::xml_node node, const ColorGeometry4f &stroke_color, const float stroke_opacity, const bool round_cap)
constexpr const char * svg_exporter_version
MatBase< float, 4, 4 > float4x4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)