Import multiple rigged characters using the plug-in system


#1

Hi!
I am always having trouble importing and reusing rigged characters with bones and skeletons into other scenes so I tried to come up with a solution that so far worked for me so I decided to share it so that others can use and maybe improve it.

First thing you have to do is install the plug-in that will import the characters into your scene. I tweaked the original script that was used for the import of simple skeletons so that it works for rigged characters with bones. Dowload the add-character.rar file and extract it and copy the folder add-character into the plug-in folder of Synfig. On Windows that folder can be found in …Synfig/share/synfig/plugins. The add-character folder contains a python-file that is the actual plug-in, an uncompressed sif-file character.sif that is the actual file that will contain the rigged character you want to import (for now it only contains a dummy character) and an xml-file that holds the name of the plug-in and that points to the python-file. After you copied the plug-in in the right place it should appear in Synfig under Plug-Ins.

Next you want to make and rig the first character you want to import. Just make a character and rigg it with the skeleton layer and add some bones to it. Make sure that when you name your groups that you set (char) in front of it. So a group called Head will become (char) Head. A group called body will become (char) Body, Skeleton will become (char) Skeleton, etc. Now give your character a name and save it as a compressed sifz-file in a place where you usually save your characters.

Next you want to make your second charater and rigg it. Again use the (char) variable in front of every group. Give the character a name and save it.

Now open up a new file that will contain the scene that you want to compose. Leave the scene-file open and open the first character-file that you made. Save the first character as an uncompressed sif-file into the add-character plug-in folder and name it character.sif. Close the character-file and go back to the scene-file and under Plug-Ins click on Add character. The plug-in will import the first character and will add a number to each of the (char) variables depending on how much characters you already imported. Leave the scene-file open and open the second character that you created and also save that as an uncompressed sif-file into the same add-character plug-in folder again under the same name character.sif. That will overwrite the first character but since you also have a backup sifz-file of it that does not matter. Close the file of the second character and go back to your scene-file that was left open and under Plug-Ins click Add character again. The second character will import and the (char) variable will be set to two so that it is easy to spot the two imported characters in the layers panel.

You can now save the scene and start animating. If you want to change or edit either of the characters and or their skeletons I suggest that you open the original sifz-files of the characters and import them back into the scene after the changes are being made. I know this is a long post but it helped me out in more then one way. I will add the plug-in as a rar file and also include the final scene-file.
Link to youtube movie showing the basic steps: https://youtu.be/3nEoO_6wtfs
Greetz!
scene01.sifz (12.3 KB)
add-character.rar (4.15 KB)


#2

Possible to have a gui for selecting the project file ?

do you know about this tentative of initiating a synfigfu.py ?


#3

Sorry, do you mean like a project on github or someting? :confused:

Yes, I know about that. I use it a lot when I am extracting stills from storyboards to make animatics in Synfig.

edit: Just noticed that the link was to synfigfu.py, and not gimp2synfig. What is synfigfu.py exactly ? The start of a standard sif xml template usable in synfig plug-in scripts?
Greetz!


#4

gui --> Graphic User Interface :wink:

Yep … something like that … i should create a specific repository for that project if it’s interesting enough


#5

Hi!
Gui… aha! I see, lol. Nope. As I recall, but of course I can be wrong, the plug-in system in Synfig does not allow interaction with the user during execution. So in order to get a gui, you should turn the script into an executable file and run it externally. In itself that would not be a bad idea: a little program that asks you what to import into a scene (BG, overlays, rigged characters etc.) and then saves it all into a workable sif-file as a result.
Greetz!


#6

I don’t see any limitations in extra lib use …
Actually can’t test/confirm because a rare “Document not well-formed. Segmentation fault” when i try to execute any plugins… !

[code]from PyQt4 import QtGui

def create_window():
app = QtGui.QApplication(sys.argv)

w = QtGui.QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()[/code]

(don’t forget to install something like “python3-pyqt4” )


#7

Hi!

You are right. Your pyqt4 example defining a window worked. Cool. Did not know that. Tested on my backup laptop that runs Lubuntu and Synfig 1.02. I guess that the input goes thru pyqt4 commands as well? Have to look into that.
Greetz!


#8

Hi!
I have seem to have bumped into the limit of my Python skills. I am not a programmer so no surprises there. I have two scripts. One is the original synfig plugin that imports a rigged character and the second creates a giu in the form of a window with an input field that asks for the sif to be imported. The string given in the import field should replace the name ‘character.sif’ in the first script, but although the two scripts work separately I can’t seem to find a way to put them together and make them work as a whole. :confused:
Any suggestions? :mrgreen:
Greetz!

First plugin script

[code]#!/usr/bin/env python

import os
import sys
import codecs

def check_substring(data, substring):
s = “\n”.join(data);
if substring in s:
return True
return False

def process(filename):
def merge_defs():
defs = False
for l in template_contents:
if defs:
if not “” in l:
inputfile_f.write(l)
else:
break
elif “” in l:
defs = True

template_filename = os.path.join(os.path.dirname(sys.argv[0]), 'character.sif')
template_f = codecs.open(template_filename, 'r', encoding='utf-8')
template_contents = template_f.readlines()
template_f.close()

# Read the input file
inputfile_f = codecs.open(filename, 'r', encoding='utf-8')
inputfile_contents = inputfile_f.readlines()
inputfile_f.close()

# Now write results to the same file
inputfile_f = open(filename, 'w', encoding='utf-8')

num = 1
while check_substring(inputfile_contents, '(char%s' % num):
    num += 1

for i, line in enumerate(template_contents):
    template_contents[i] = line.replace('(char', '(char%s' % num)

defs_found = False
for line in inputfile_contents:
    if "</bones>" in line:
        defs_found = True
        merge_defs()
    if line == "</canvas>\n":
        if not defs_found:
            inputfile_f.write("<bones>\n")
            merge_defs()
            inputfile_f.write("</bones>\n")
        canvas = False
        for l in template_contents:
            if canvas:
                if not l == "</canvas>\n":
                    inputfile_f.write(l)
                else:
                    break
            elif "</bones>" in l:
                canvas = True
    inputfile_f.write(line)

inputfile_f.close()

if len(sys.argv) < 2:
sys.exit()
else:
process(sys.argv[1])[/code]

Second script with the gui:

[code]import sys
from PyQt4.QtCore import SIGNAL
from PyQt4.QtGui import QDialog, QApplication, QPushButton, QLineEdit, QFormLayout

class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        self.le = QLineEdit()
        

        self.pb = QPushButton()
        self.pb.setObjectName("connect")
        self.pb.setText("OK") 

        layout = QFormLayout()
        layout.addWidget(self.le)
        layout.addWidget(self.pb)

        self.setLayout(layout)
        self.connect(self.pb, SIGNAL("clicked()"),self.button_click)
        self.pb.clicked.connect(self.close)
        self.setWindowTitle("Enter sif")
        

    def button_click(self):
        
        shost = str (self.le.text())
        #print (shost)

app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
[/code]


#9

An idea to have only one script.

For example from script 2:

  • add a new Class AddCharacterPlugin with a AddCharacterPlugin::setcharacter(string filename) and AddCharacterPlugin::process() functions.
  • In Form.Buttonclicked you instantiate a AddCharacterPlugin you set the characher file , and then you process …
  • transform the script2 to a synfig plugin template (like script 1)

catch the idea ?


#10

Hi!
Thanks!
I get the idea. … now and try to implement it into practice…
Greetz!