blenderではSVGのベクターデータをカーブとして読み込む機能があります
また、現行のPhotoshopではベクトルマスクのあるレイヤのコンテクストメニューから
テキストデータとしてクリップボードにコピーする機能があります
コピーしたものを メモ帳にペーストするとこんな感じです。
このままSVGの拡張子で保存すれば PhotoshopからBlenderへ 塗りを含めたベクトルデータとして渡せます
ただ、個人的に業務で使う頻度が増え いちいち一時ファイルを作るのも面倒になったために
クリップボードから直接カーブを作成するスクリプトを作ってみました
現在業務で使っているのがBlender3.3なのでBlender3.3の内容になります
試しに3.6で使ってみたところ 引用したコードに僅かな違いがあり動かない様子だったのでご注意を
既存アドオンのライブラリを利用する
とはいっても 既存のアドオンの機能で完全に動いているので書き直しは無駄です
アドオンフォルダにある io_curve_svg のコードを読んでみます。
このアドオンは__init__.pyにGUIまわりの操作が書かれていて
import_svg.py のload_svg関数の実行をしているようです
また読み込み処理の大まかな部分はSVGGeometryContainerを継承したSVGLoaderクラスで行っていて
xml.dom.minidom.parse(filepath) でファイルで指定したデータのXMLデータをパースすることで
SVGのデータを取得しているようです。
まずはこの部分をコピペして 既存アドオンのライブラリを利用するスクリプトをテストしてみます
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
import xml.dom.minidom
from mathutils import Vector, Matrix
from io_curve_svg.import_svg import SVGGeometryContainer
class SVGLoader(SVGGeometryContainer):
"""
SVG file loader
"""
def getTransformMatrix(self):
"""
Get matrix created from "transform" attribute
"""
# SVG document doesn't support transform specification
# it can't even hold attributes
return None
def __init__(self, context, filepath, do_colormanage):
"""
Initialize SVG loader
"""
import os
svg_name = os.path.basename(filepath)
scene = context.scene
collection = bpy.data.collections.new(name=svg_name)
scene.collection.children.link(collection)
node = xml.dom.minidom.parse(filepath)
m = Matrix()
m = m @ Matrix.Scale(1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((1.0, 0.0, 0.0)))
m = m @ Matrix.Scale(-1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((0.0, 1.0, 0.0)))
rect = (0, 0)
self._context = {'defines': {},
'transform': [],
'rects': [rect],
'rect': rect,
'matrix': m,
'materials': {},
'styles': [None],
'style': None,
'do_colormanage': do_colormanage,
'collection': collection}
super().__init__(node, self._context)
def load_svg(context, filepath, do_colormanage):
"""
Load specified SVG file
"""
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
loader = SVGLoader(context, filepath, do_colormanage)
loader.parse()
loader.createGeom(False)
context = bpy.context
do_colormanage = context.scene.display_settings.display_device != 'NONE'
# デスクトップにあるtest.svgを読み込む
import os
desktop_dir = os.path.expanduser('~/Desktop')
filepath = os.path.join(desktop_dir,'test.svg')
load_svg(context, filepath, do_colormanage)
コード内にファイルパス直書きで とりあえずの動作が確認できました
クリップボードからの読み込み
これを今回の目的のクリップボードからの読み込みに書き直してみます
とはいっても クリップボードのテキストを取得する bpy.context.window_manager.clipboard を使って
XMLのパースをxml.dom.minidom.parseString() でテキストデータから行うようにして整理するだけです
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
import xml.dom.minidom
from mathutils import Vector, Matrix
from io_curve_svg.import_svg import SVGGeometryContainer
class SVGLoaderClipboard(SVGGeometryContainer):
"""
SVG file loader
"""
def getTransformMatrix(self):
"""
Get matrix created from "transform" attribute
"""
# SVG document doesn't support transform specification
# it can't even hold attributes
return None
def __init__(self, context, SVGstring, do_colormanage):
"""
Initialize SVG loader
"""
collection = context.scene.collection
node = xml.dom.minidom.parseString(SVGstring, parser=None)
m = Matrix()
m = m @ Matrix.Scale(1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((1.0, 0.0, 0.0)))
m = m @ Matrix.Scale(-1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((0.0, 1.0, 0.0)))
rect = (0, 0)
self._context = {'defines': {},
'transform': [],
'rects': [rect],
'rect': rect,
'matrix': m,
'materials': {},
'styles': [None],
'style': None,
'do_colormanage': do_colormanage,
'collection': collection}
super().__init__(node, self._context)
context = bpy.context
do_colormanage = context.scene.display_settings.display_device != 'NONE'
# クリップボードのテキストを取得
SVGstring = bpy.context.window_manager.clipboard
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
if SVGstring:
loader = SVGLoaderClipboard(context, SVGstring, do_colormanage)
loader.parse()
loader.createGeom(False)