24#include <fmt/format.h>
43 uint8_t r =
color[0] * 255.0f;
44 uint8_t g =
color[1] * 255.0f;
45 uint8_t
b =
color[2] * 255.0f;
46 return fmt::format(
"#{:02X}{:02X}{:02X}", r, g,
b);
51 const float stroke_opacity,
58 node.append_attribute(
"stroke").set_value(stroke_hex.c_str());
59 node.append_attribute(
"stroke-opacity").set_value(stroke_color.
a * stroke_opacity);
61 node.append_attribute(
"fill").set_value(
"none");
62 node.append_attribute(
"stroke-linecap").set_value(round_cap ?
"round" :
"square");
67 const float layer_opacity)
73 node.append_attribute(
"fill").set_value(stroke_hex.c_str());
74 node.append_attribute(
"stroke").set_value(
"none");
75 node.append_attribute(
"fill-opacity").set_value(fill_color.
a * layer_opacity);
83 const float thickness,
84 const std::string &hexcolor)
86 pugi::xml_node rect_node = node.append_child(
"rect");
87 rect_node.append_attribute(
"x").set_value(
x);
88 rect_node.append_attribute(
"y").set_value(
y);
89 rect_node.append_attribute(
"width").set_value(width);
90 rect_node.append_attribute(
"height").set_value(height);
91 rect_node.append_attribute(
"fill").set_value(
"none");
92 if (thickness > 0.0f) {
93 rect_node.append_attribute(
"stroke").set_value(hexcolor.c_str());
94 rect_node.append_attribute(
"stroke-width").set_value(thickness);
101 std::string get_node_uuid_string();
127 std::optional<float> width);
128 pugi::xml_node
write_path(pugi::xml_node node,
136std::string SVGExporter::get_node_uuid_string()
138 std::string
id = fmt::format(
".uuid_{:#x}", this->_node_uuid++);
144 this->_node_uuid = 0;
148 const int frame_number = scene.
r.
cfra;
162 const int orig_frame = scene.
r.
cfra;
167 if (selection_only) {
174 frames,
GrainSize(1024), memory, [&](
const int frame_number) {
192 pugi::xml_node frames_group_node = main_node.append_child(
"g");
193 frames_group_node.append_attribute(
"id").set_value(
"blender_frames");
194 frames_group_node.append_attribute(
"display").set_value(
"none");
196 const int frame_count = frames.
size();
200 scene.
r.
cfra = frame_number;
207 scene.
r.
cfra = orig_frame;
224 std::string frametxt =
"blender_frame." + std::to_string(frame_number);
238 pugi::xml_node clip_node = node.append_child(
"clipPath");
239 clip_node.append_attribute(
"id").set_value(
240 (
"clip-path." + std::to_string(frame_number)).c_str());
245 pugi::xml_node frame_node = node.append_child(
"g");
246 frame_node.append_attribute(
"id").set_value(
frame_name(frame_number).c_str());
250 frame_node.append_attribute(
"clip-path")
251 .set_value((
"url(#clip-path." + std::to_string(frame_number) +
")").c_str());
255 const Object *ob = info.object;
257 pugi::xml_node ob_node = frame_node.append_child(
"g");
260 SNPRINTF(obtxt,
"blender_object.%s.%d", ob->
id.
name + 2, frame_number);
261 std::string object_id = std::string(obtxt) + this->get_node_uuid_string();
262 ob_node.append_attribute(
"id").set_value(object_id.c_str());
270 if (!layer->is_visible()) {
273 const Drawing *drawing = grease_pencil_eval->get_drawing_at(*layer, frame_number);
274 if (drawing ==
nullptr) {
279 pugi::xml_node layer_node = ob_node.append_child(
"g");
280 std::string layer_node_id =
"layer." + layer->name() + this->get_node_uuid_string();
281 layer_node.append_attribute(
"id").set_value(layer_node_id.c_str());
287 {CURVE_TYPE_CATMULL_ROM, CURVE_TYPE_BEZIER, CURVE_TYPE_NURBS}))
320 const std::optional<float> width,
321 const bool round_cap,
322 const bool is_outline) {
324 pugi::xml_node element_node =
write_path(layer_node, layer_to_world, positions, cyclic);
331 layer_node, layer_to_world, positions, cyclic, width);
348 pugi::xml_node decl =
main_doc_.prepend_child(pugi::node_declaration);
349 decl.append_attribute(
"version") =
"1.0";
350 decl.append_attribute(
"encoding") =
"UTF-8";
352 pugi::xml_node comment =
main_doc_.append_child(pugi::node_comment);
353 std::string txt = std::string(
" Generator: Blender, ") +
svg_exporter_name +
" - " +
355 comment.set_value(txt.c_str());
357 pugi::xml_node doctype =
main_doc_.append_child(pugi::node_doctype);
359 "svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
360 "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"");
365 pugi::xml_node main_node =
main_doc_.append_child(
"svg");
366 main_node.append_attribute(
"version").set_value(
"1.1");
367 main_node.append_attribute(
"x").set_value(
"0px");
368 main_node.append_attribute(
"y").set_value(
"0px");
369 main_node.append_attribute(
"xmlns").set_value(
"http://www.w3.org/2000/svg");
371 std::string width, height;
382 main_node.append_attribute(
"width").set_value((width +
"px").c_str());
383 main_node.append_attribute(
"height").set_value((height +
"px").c_str());
384 std::string viewbox =
"0 0 " + width +
" " + height;
385 main_node.append_attribute(
"viewBox").set_value(viewbox.c_str());
392 const float duration)
394 pugi::xml_node use_node = parent_node.append_child(
"use");
395 use_node.append_attribute(
"id").set_value(
"blender_animation");
397 use_node.append_attribute(
"href").set_value(href_text.c_str());
399 pugi::xml_node animate_node = use_node.append_child(
"animate");
400 animate_node.append_attribute(
"id").set_value(
"frame-by-frame_animation");
401 animate_node.append_attribute(
"attributeName").set_value(
"href");
403 std::string duration_text = std::to_string(duration) +
"s";
404 animate_node.append_attribute(
"dur").set_value(duration_text.c_str());
405 animate_node.append_attribute(
"repeatCount").set_value(
"indefinite");
407 std::string animated_frame_ids = [&]() {
408 std::string frame_ids_text =
"";
410 std::string frame_url_entry =
"#" +
frame_name(frame) +
";";
411 frame_ids_text.append(frame_url_entry);
413 return frame_ids_text;
416 animate_node.append_attribute(
"values").set_value(animated_frame_ids.c_str());
425 pugi::xml_node element_node = node.append_child(
"polygon");
435 txt.append(std::to_string(screen_co.x) +
"," +
439 txt.append(std::to_string(screen_co.x) +
"," +
444 element_node.append_attribute(
"points").set_value(txt.c_str());
453 const std::optional<float> width)
455 pugi::xml_node element_node = node.append_child(cyclic ?
"polygon" :
"polyline");
458 element_node.append_attribute(
"stroke-width").set_value(*width);
469 txt.append(std::to_string(screen_co.x) +
"," +
473 txt.append(std::to_string(screen_co.x) +
"," +
478 element_node.append_attribute(
"points").set_value(txt.c_str());
488 pugi::xml_node element_node = node.append_child(
"path");
490 std::string txt =
"M";
498 txt.append(std::to_string(screen_co.x) +
"," +
502 txt.append(std::to_string(screen_co.x) +
"," +
511 element_node.append_attribute(
"d").set_value(txt.c_str());
522 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(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 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)
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)
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)
CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves, const IndexMask &selection, const ResampleCurvesOutputAttributeIDs &output_ids={})
@ 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)