クリップボードのSVGデータをBlenderのパスに変換するスクリプト

blenderではSVGのベクターデータをカーブとして読み込む機能があります
また、現行のPhotoshopではベクトルマスクのあるレイヤのコンテクストメニューから
テキストデータとしてクリップボードにコピーする機能があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/f1a872ae-7441-121a-45e2-63d6ab7b84c0.png)
コピーしたものを　メモ帳にペーストするとこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/08f54fda-3956-9b9b-cf43-2cf053eba776.png)
このままSVGの拡張子で保存すれば　PhotoshopからBlenderへ　塗りを含めたベクトルデータとして渡せます

ただ、個人的に業務で使う頻度が増え　いちいち一時ファイルを作るのも面倒になったために
クリップボードから直接カーブを作成するスクリプトを作ってみました

:::note
現在業務で使っているのがBlender3.3なのでBlender3.3の内容になります
試しに3.6で使ってみたところ　引用したコードに僅かな違いがあり動かない様子だったのでご注意を
:::
## 既存アドオンのライブラリを利用する
とはいっても　既存のアドオンの機能で完全に動いているので書き直しは無駄です
アドオンフォルダにある io_curve_svg のコードを読んでみます。
このアドオンは__init__.pyにGUIまわりの操作が書かれていて
import_svg.py のload_svg関数の実行をしているようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/aeb0ca52-11dd-f597-d19b-b018753edfce.png)
また読み込み処理の大まかな部分はSVGGeometryContainerを継承したSVGLoaderクラスで行っていて
xml.dom.minidom.parse(filepath) でファイルで指定したデータのXMLデータをパースすることで
SVGのデータを取得しているようです。

まずはこの部分をコピペして　既存アドオンのライブラリを利用するスクリプトをテストしてみます

```testimport.py
# 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() でテキストデータから行うようにして整理するだけです
```SVGcurve_from_clipboard.py
# 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)
```
少しだけシンプルな動作にしました　何かの参考になれば幸いです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/71214bf0-3fc4-2120-53fa-3b58c650ea13.png)