Inkscape.org
Creating New Extensions Developing internal extension
  1. #1
    reddomon reddomon @reddomon

    Hi all.

    I developed some extension for inkscape and it works well. But it lacks of getting dynamic data properties. For example i want to get layer names and set to different props for each layer. As you know we can do it using custom ui for inkex.api extension but it locks the inkscape UI at running.  So i decided to develop extension internally.  How can i do that? please advise me.

  2. #2
    inklinea inklinea @inklinea⛰️

    When you say 'extension internally' do you mean in the Inkscape source code itself ? If so probably best to ask here https://chat.inkscape.org/channel/team_devel

    However if you just mean a basic .inx / .py extension. The Inkscape gui should only be locked if you have 'Live Preview' checked.

    What kind of layer information do you want to get ?  most of it should be available. Layers are just groups with a special attribute. They behave as other objects.

     

  3. #3
    reddomon reddomon @reddomon

    Hi. Thank you for your answer.

    Yes I do mean in the source code. If i use "custum-gui" option with tk ui, i can get dynamic ui like listing layer names on UI. But i locks the Inkscape GUI. If i use the "cutom-gui: no" option it did not lock the UI but i can not create the GUI dynamically. Only static GUI applicable. So there is one option left that is embed code into inkscape codebase. If onother option exist please infor me. Because i want to use written code rather than rewrite everyting in CPP. I will check the chat channel.

    Thank you again.

  4. #4
    Marc Jeanmougin Marc Jeanmougin @MarcJeanmougin👁️‍

    For now, as far as I know you cannot do non-blocking extensions in python. We have a way to do extensions that integrate into the loaded code, but only in cpp or equivalent.

  5. #5
    inklinea inklinea @inklinea⛰️

    Yes, if you use a custom gui, (I use GTK3+) then you do not have access to 'Live Preview' and the Inkscape gui is locked until you exit the custom gui.

    So you can either have 'non-dynamic' basic .inx and .py with 'Live Preview' 

    or you can have 'dynamic-gui' with no 'Live Preview' and no access to the Inkscape gui.

    The reason is, the extension system simply runs the python loop then returns. Tk or Gtk3+ are in that loop :) So the gui is destroyed when the loop ends.

    You can make a custom preview window using pixbuf, but that creates other problems ( text and some filters render differently ) 

    Here is an example ( the code is horrible but that is just me ). https://inkscape.org/~inklinea/%E2%98%85funshapes

    or you can command call to make a .png and preview that - super slow, cannot do realtime changes.

    or maybe if you are clever https://wiki.inkscape.org/wiki/DBus  - but that is far beyond my abilities.

     

  6. #6
    reddomon reddomon @reddomon

    Thank you for your answers.

    @marc

    Plesa lead me the right direction. Is there any example for that or where have to i examine inkscape sources?

    @inklinea
    I tried your extension and see that it is same as my extension and the difference, my extension made  by not using gtk but using tk and works perfectly. Great example by the way. I guess the only way is cpp :(

  7. #7
    Marc Jeanmougin Marc Jeanmougin @MarcJeanmougin👁️‍
    *

    The example is here : https://gitlab.com/inkscape/inkscape/-/tree/master/src/extension/plugins/grid2

    The example uses a toy extension to draw grids, but can do anything, even non-blocking in the gtk main loop, and is being linked to the inkscape.so file.

    You'll have to produce a so file and an inx file to place in the extensions.

  8. #8
    reddomon reddomon @reddomon

    Thank you @marc

  9. #9
    reddomon reddomon @reddomon

    Hi again.
    I examine the grid 2 but it seems it uses hardcoded UI like the other extensions. i guess only it runs as a dll not a script. I may not tell myself good enough. I wantto make an extension like layer manager or object manager.

  10. #10
    reddomon reddomon @reddomon

    You can see external extension that i made and one example of what i want to make.

    https://disk.yandex.com.tr/d/nhcz7c9AilK0OA

  11. #11
    krishnarupa krishnarupa @krishnarupa

    @MarcJeanmougin

    I just found this post and took a look at your extension. I have a few questions:

    1. How to properly build the extension??? Any special parameters to link? Any documentation on how to do that on Windows? I have some experience with CPP, but it's been a while...

    2. On the inx file I don't see it referencing the binary as we do with the python extensions. Is this something that Inkscape will execute te library automatically based on the .so (or dll) name?

    Thanks,

    Igor

  12. #12
    Marc Jeanmougin Marc Jeanmougin @MarcJeanmougin👁️‍

    @krishnarupa

    1/ no documentation other than "copy what's done for grid", as it needs to be compiled in the inkscape tree (no stable api) and cmake will take care of the build and link. No specificity for windows that I know of, just compile within a normal inkscape build.

    2/ iirc yes if it was not broken

     

    changeset needed to compile grid2 on master (currently broken afaict):

     

    diff --git a/src/extension/plugins/grid2/grid.cpp b/src/extension/plugins/grid2/grid.cpp
    index 8f40b34e9f..cb2cf1d501 100644
    --- a/src/extension/plugins/grid2/grid.cpp
    +++ b/src/extension/plugins/grid2/grid.cpp
    @@ -17,6 +17,7 @@
     #include <gtkmm/spinbutton.h>
     
     #include "desktop.h"
    +#include "layer-manager.h"
     
     #include "document.h"
     #include "selection.h"
    @@ -96,7 +97,7 @@ Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape:
         Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100));
         if (selection->isEmpty()) {
             /* get page size */
    -        SPDocument * doc = document->doc();
    +        SPDocument * doc = desktop->doc();
             bounding_area = *(doc->preferredBounds());
         } else {
             Geom::OptRect bounds = selection->visualBounds();
    @@ -104,14 +105,14 @@ Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape:
                 bounding_area = *bounds;
             }
     
    -        gdouble doc_height  =  (document->doc())->getHeight().value("px");
    +        gdouble doc_height  =  (desktop->doc())->getHeight().value("px");
             Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]),
                                         Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y]));
     
             bounding_area = temprec;
         }
     
    -    double scale = document->doc()->getDocumentScale().inverse()[Geom::X];
    +    double scale = desktop->doc()->getDocumentScale().inverse()[Geom::X];
     
         bounding_area *= Geom::Scale(scale);
         Geom::Point spacings( scale * module->get_param_float("xspacing"),
    @@ -123,10 +124,10 @@ Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape:
         Glib::ustring path_data("");
     
         path_data = build_lines(bounding_area, offsets, spacings);
    -    Inkscape::XML::Document * xml_doc = document->doc()->getReprDoc();
    +    Inkscape::XML::Document * xml_doc = desktop->doc()->getReprDoc();
     
         //XML Tree being used directly here while it shouldn't be.
    -    Inkscape::XML::Node * current_layer = static_cast<SPDesktop *>(document)->currentLayer()->getRepr();
    +    Inkscape::XML::Node * current_layer = desktop->layerManager().currentLayer()->getRepr();
         Inkscape::XML::Node * path = xml_doc->createElement("svg:path");
     
         path->setAttribute("d", path_data);