<inkscape-extension> <_name>PF Editor</_name> <id>org.pf.inkscape.plugins.pf_plugin</id> <dependency type="executable" location="extensions">pf_plugin.py</dependency> <dependency type="executable" location="extensions">inkex.py</dependency> <param name="layer_name" type="string" _gui_text="Layer name">Game objects</param> <param name="obj_name" type="string" _gui_text="Object name">Object1</param> <param name="obj_width" type="int" _gui-text="Width" min="10" max="12000">30</param> <param name="obj_height" type="int" _gui-text="Height" min="10" max="12000">30</param> <param name="obj_radius" type="int" _gui-text="Radius" min="10" max="12000">30</param> <param name="obj_posX" type="int" _gui-text="PosX" min="0" max="12000">30</param> <param name="obj_posY" type="int" _gui-text="PosY" min="0" max="12000">30</param> <param name="obj_density" type="float" _gui-text="Density" min="0" max="1">0.5</param> <param name="obj_friction" type="float" _gui-text="Friction" min="0" max="1">0.5</param> <param name="obj_restitution" type="float" _gui-text="Restitution" min="0" max="1">0.5</param> <param name="obj_isSensor" type="boolean" _gui-text="Sensor body">false</param> <param name="obj_isRotable" type="boolean" _gui-text="Rotable body">false</param> <param name="obj_type" type="enum" _gui-text="Object type"> <_item value="SQUARE">Square</_item> <_item value="CIRCLE">Circle</_item> </param> <param name="obj_d_type" type="enum" _gui-text="Static/Dynamic"> <_item value="STATIC">Static</_item> <_item value="DYNAMIC">Dynamic</_item> </param> <param name="obj_hasImage" type="boolean" _gui-text="Has image">false</param> <effect> <object-type>all</object-type> <effects-menu> <submenu _name="PF Plugins"/> </effects-menu> </effect> <script> <command reldir="extensions" interpreter="python">pf_plugin.py</command> </script> </inkscape-extension>
pf_plugin.py, inkex.py
lines pf_plugin.py, inkex.py
set the dependencies for the module - in fact, that will be loaded. The <param name="obj_d_type" type="enum" _gui-text="Static/Dynamic">
has an enum property inside - a drop-down list is specified externally. When you click on OK, all parameters go to the input to the Python script, the current value on the drop-down list is also a parameter. The value of param name must match the parameters declared as included in the Python script. Oh yeah, visually in the plugin you can create tabs - I tried it, it did not work for me. import sys sys.path.append('/usr/share/inkscape/extensions') import inkex class PFEditor(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.OptionParser.add_option('--layer_name', action='store', type='string', dest='layer_name', default='Game objects', help='Layer name which objects append to') self.OptionParser.add_option('--obj_name', action='store', type='string', dest='obj_name', default='Object', help='Object name') self.OptionParser.add_option('--obj_width', action='store', type='int', dest='obj_width', default=30, help='Object width') self.OptionParser.add_option('--obj_height', action='store', type='int', dest='obj_height', default=30, help='Object height') self.OptionParser.add_option('--obj_radius', action='store', type='int', dest='obj_radius', default=30, help='Object radius') self.OptionParser.add_option('--obj_posX', action='store', type='int', dest='obj_posX', default=30, help='PosX') self.OptionParser.add_option('--obj_posY', action='store', type='int', dest='obj_posY', default=30, help='PosY') self.OptionParser.add_option('--obj_type', action='store', type='string', dest='obj_type', default='SQUARE', help='Object type') self.OptionParser.add_option('--obj_d_type', action='store', type='string', dest='obj_d_type', default='STATIC', help='Static/Dynamic') self.OptionParser.add_option('--obj_density', action='store', type='float', dest='obj_density', default=0.5, help='Density') self.OptionParser.add_option('--obj_friction', action='store', type='float', dest='obj_friction', default=0.5, help='Friction') self.OptionParser.add_option('--obj_restitution', action='store', type='float', dest='obj_restitution', default=0.5, help='Restitution') self.OptionParser.add_option('--obj_isSensor', action='store', type='inkbool', dest='obj_isSensor', default=False, help='Sensor body') self.OptionParser.add_option('--obj_isRotable', action='store', type='inkbool', dest='obj_isRotable', default=True, help='Rotable body') self.OptionParser.add_option('--obj_hasImage', action='store', type='inkbool', dest='obj_hasImage', default=False, help='Body has image') def pfbTypes(self, x): return { 'STATIC' : '#00ff00', 'DYNAMIC' : '#ff0000', 'SQUARE' : 'SQUARE', 'CIRCLE' : 'CIRCLE' }.get(x, 0) def pfbType_SVG(self, x): return { 'SQUARE' : 'rect', 'CIRCLE' : 'circle' }.get(x, 'rect') def concat_style(self, style): # @NoSelf style_str = '' for stl in style: style_str += stl + ':' + style[stl] + ';' style_str = style_str[:-1] return style_str def generate_object(self, w, h, r, x, y, density, friction, restitution, isSensor, isRotable, parent, type, d_type, name, hasImage): # @NoSelf style = { 'fill' : self.pfbTypes(d_type), 'fill-rule' :'evenodd', 'stroke' :'000000', 'stroke-width' :'0px', 'stroke-linecap' :'butt', 'stroke-linejoin' :'miter', 'stroke-opacity' :'0' } attribs = { 'type' : type, 'd_type' : d_type, 'height' : str(h), 'width' : str(w), 'density' : str(density), 'friction' : str(friction), 'restitution' : str(restitution), 'isSensor' : str(isSensor).lower(), 'isRotable' : str(isRotable).lower(), 'hasImage' : str(hasImage).lower(), 'name' : name, 'style' : self.concat_style(style), } if d_type == 'DYNAMIC': attribs['isDynamic'] = 'true' else: attribs['isDynamic'] = 'false' if type == 'SQUARE' : attribs['x'] = str(x); attribs['y'] = str(y); if type == 'CIRCLE' : attribs['cx'] = str(x); attribs['cy'] = str(y); attribs['r'] = str(r); obj = inkex.etree.SubElement(parent, inkex.addNS(self.pfbType_SVG(type), 'svg'), attribs) def effect(self) : layer_name = self.options.layer_name obj_name = self.options.obj_name obj_width = self.options.obj_width obj_height = self.options.obj_height obj_radius = self.options.obj_radius obj_posX = self.options.obj_posX obj_posY = self.options.obj_posY obj_type = self.options.obj_type obj_d_type = self.options.obj_d_type obj_density = self.options.obj_density obj_friction = self.options.obj_friction obj_restitution = self.options.obj_restitution obj_isSensor = self.options.obj_isSensor obj_isRotable = self.options.obj_isRotable obj_hasImage = self.options.obj_hasImage svg = self.document.getroot() d_root = self.document.getroot() layer = None iter = 0 for item in d_root: if (item.attrib.get('id') == 'pf_go_id' and item.attrib.get('level_name') == layer_name): layer = item iter += 1 break if(iter == 0): layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('id'), 'pf_go_id') layer.set(inkex.addNS('level_name'), layer_name) layer.set(inkex.addNS('label', 'inkscape'), layer_name) layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.generate_object(obj_width, obj_height, obj_radius, obj_posX, obj_posY, obj_density, obj_friction, obj_restitution, obj_isSensor, obj_isRotable, layer, obj_type, obj_d_type, obj_name, obj_hasImage) effect = PFEditor() effect.affect()
self.OptionParser.add_option('--layer_name', action='store',
type='string', dest='layer_name', default='Game objects',
help='Layer name which objects append to')
self.OptionParser.add_option('--layer_name', action='store',
type='string', dest='layer_name', default='Game objects',
help='Layer name which objects append to')
self.OptionParser.add_option('--layer_name', action='store',
type='string', dest='layer_name', default='Game objects',
help='Layer name which objects append to')
set the incoming parameters, their type (the names of the parameters with the names from .inx are the same). Further, in the effect function, the input data for the script is pushed into variables. Then I'm looking for something like for item in d_root:
if (item.attrib.get('id') == 'pf_go_id' and item.attrib.get('level_name') == layer_name)
for item in d_root:
if (item.attrib.get('id') == 'pf_go_id' and item.attrib.get('level_name') == layer_name)
for item in d_root:
if (item.attrib.get('id') == 'pf_go_id' and item.attrib.get('level_name') == layer_name)
: in SVG, the layers have the id property, and I’m stuffing it with 'pf_go_id'
, for simplicity of identifying "their layers" with levels. If the layer already exists, we will add new objects to it, if not, we create a new layer, “level”, and work with it. The following lines create a layer, and already inside the generate_object function, I create objects. I think everything is clear there. <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="630" height="480" id="svg2" version="1.1" inkscape:version="0.48.4 r9939" sodipodi:docname="levels_tmp.svg"> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.98994949" inkscape:cx="60.920287" inkscape:cy="223.06442" inkscape:document-units="px" inkscape:current-layer="pf_go_id" showgrid="false" inkscape:window-width="1366" inkscape:window-height="716" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" /> <defs id="defs4" /> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title /> </cc:Work> </rdf:RDF> </metadata> <g id="pf_go_id" level_name="Menu" inkscape:label="Menu" inkscape:groupmode="layer" style="display:inline"> <circle transform="translate(194.95944,151.52288)" sodipodi:ry="40" sodipodi:rx="40" sodipodi:cy="40" sodipodi:cx="40" isSensor="false" isRotable="true" height="10" cy="40" cx="40" friction="0.5" restitution="0.5" style="fill:#00ff00;fill-rule:evenodd;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0" name="Object1" density="0.5" isDynamic="false" width="100" r="40" type="CIRCLE" d_type="STATIC" hasImage="false" id="circle3294" /> <rect id="rect2997" hasImage="false" d_type="DYNAMIC" type="SQUARE" x="4.7976952" y="405.67188" width="100" isDynamic="true" density="0.5" name="Object2" style="fill:#ff0000;fill-rule:evenodd;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0" restitution="0.5" friction="0.5" height="10" isRotable="true" isSensor="false" transform="matrix(0.88912747,-0.45765964,0.45765964,0.88912747,0,0)" /> <rect isSensor="false" isRotable="true" height="10" friction="0.5" restitution="0.5" style="fill:#00ff00;fill-rule:evenodd;stroke-width:0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0" name="Object2" density="0.5" isDynamic="false" width="300" y="391.62952" x="173.53809" type="SQUARE" d_type="STATIC" hasImage="false" id="rect3011" /> </g> <g inkscape:groupmode="layer" inkscape:label="Level_1" level_name="Level_1" id="g3027"> <circle id="circle3029" hasImage="false" d_type="DYNAMIC" type="CIRCLE" r="30" width="300" isDynamic="true" density="0.5" name="Object1" style="stroke-linejoin:miter;stroke-opacity:0;fill-rule:evenodd;stroke:000000;stroke-linecap:butt;stroke-width:0px;fill:#ff0000" restitution="0.5" friction="0.5" cx="120" cy="130" height="10" isRotable="true" isSensor="false" /> </g> </svg>
Source: https://habr.com/ru/post/208094/
All Articles