1

EDIT: Figured THIS part out, but see 2nd post below for another question.

(a little backstory here, skip ahead for the TLDR :) )

I'm currently trying to write a few scripts for Blender to help improve the level creation workflow for a game that I play (Natural Selection 2). Currently, to move geometry from the level editor to Blender, I have to 1) Save a file from the editor as an .obj 2) import obj into blender, and make my changes. Then I 3) export to the game's level format using an exporter script I wrote, and 4) re-open the file in a new instance of the editor. 5) copy the level data from the new instance. 6) paste into the main level file. This is quite a pain to do, and quite clearly discourages even using the tool at all but for major edits. My idea for an improved workflow: 1) Copy data to clipboard in editor 2) Run importer script in Blender to load data. 3) Run exporter script in blender to save data. 4) Paste back into original file. This not only cuts out two whole steps in the tedious process, but also eliminates the need for extra files cluttering up my desktop. Currently though, I haven't found a way to read in clipboard data from the Windows clipboard into Blender... at least not without having to go through some really elaborate installation steps (eg install python 3.1, install pywin32, move x,y,z to the blender directory, uninstall python 3.1... etc...)

TLDR

I need help finding a way to write/read BINARY data to/from the clipboard in Blender. I'm not concerned about cross-platform capability -- the game tools are Windows only.

Ideally -- though obviously beggars can't be choosers here -- the solution would not make it too difficult to install the script for the layman. I'm (hopefully) not the only person who is going to be using this, so I'd like to keep the installation instructions as simple as possible. If there's a solution available in the python standard library, that'd be awesome!

Things I've looked at already/am looking at now

Pyperclip -- plaintext ONLY. I need to be able to read BINARY data off the clipboard.

pywin32 -- Kept getting missing DLL file errors, so I'm sure I'm doing something wrong. Need to take another stab at this, but the steps I had to take were pretty involved (see last sentence above TLDR section :) )

TKinter -- didn't read too far into this one as it seemed to only read plain-text.

ctypes -- actually just discovered this in the process of writing this post. Looks scary as hell, but I'll give it a shot.

BeigeAlert
  • 197
  • 1
  • 11

2 Answers2

2

Okay I finally got this working. Here's the code for those interested:

from ctypes import *
from binascii import hexlify

kernel32 = windll.kernel32
user32 = windll.user32

user32.OpenClipboard(0)

CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")

if user32.IsClipboardFormatAvailable(CF_SPARK):
    data = user32.GetClipboardData(CF_SPARK)
    size = kernel32.GlobalSize(data)
    data_locked = kernel32.GlobalLock(data)
    text = string_at(data_locked,size)
    kernel32.GlobalUnlock(data)
else:
    print('No spark data in clipboard!')
user32.CloseClipboard()
BeigeAlert
  • 197
  • 1
  • 11
0

Welp... this is a new record for me (posting a question and almost immediately finding an answer).

For those interested, I found this: How do I read text from the (windows) clipboard from python?

It's exactly what I'm after... sort of. I used that code as a jumping-off point.

Instead of CF_TEXT = 1

I used CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")

Here's where I got that function name from: http://msdn.microsoft.com/en-us/library/windows/desktop/ms649049(v=vs.85).aspx

The 'W' is there because for whatever reason, Blender doesn't see the plain-old "RegisterClipboardFormat" function, you have to use "...FormatW" or "...FormatA". Not sure why that is. If somebody knows, I'd love to hear about it! :)

Anyways, haven't gotten it actually working yet: still need to find a way to break this "data" object up into bytes so I can actually work with it, but that shouldn't be too hard.

Scratch that, it's giving me quite a bit of difficulty.

Here's my code

from ctypes import *
from binascii import hexlify

kernel32 = windll.kernel32
user32 = windll.user32

user32.OpenClipboard(0)

CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")

if user32.IsClipboardFormatAvailable(CF_SPARK):
    data = user32.GetClipboardData(CF_SPARK)
    data_locked = kernel32.GlobalLock(data)
    print(data_locked)
    text = c_char_p(data_locked)
    print(text)
    print(hexlify(text))
    kernel32.GlobalUnlock(data_locked)
else:
    print('No spark data in clipboard!')
user32.CloseClipboard()

There aren't any errors, but the output is wrong. The line print(hexlify(text)) yields b'e0cb0c1100000000', when I should be getting something that's 946 bytes long, the first 4 of which should be 01 00 00 00. (Here's the clipboard data, saved out from InsideClipboard as a .bin file: https://www.dropbox.com/s/bf8yhi1h5z5xvzv/testLevel.bin?dl=1 )

Community
  • 1
  • 1
BeigeAlert
  • 197
  • 1
  • 11