Jump to content

midora

Members
  • Posts

    1,782
  • Joined

  • Last visited

  • Days Won

    26

Posts posted by midora

  1. Very nice explanation of the plugin system Midora! Thank you for making it so clear.

     

    It's a pleasure to share an explanation in exchange to other support like the plugin index or plugins like FurBlur.

     

    But also think about, why is it possible to explain the concept in just a few words?

     

    The reason is a well designed software. This is not the standard if you are looking under the hood.

  2. Where can I find documentation for the  OptionBasedLibrary

     

    There is an ExampleOptionBasedEffect project like the ExamplePropertyBasedEffect which I posted earlier in this forum. This I may upload because it exists. Everything else is - as always - timecritical. To provide a good documentation is costly I guess you know. But we may discuss the stuff in an OptionBasedEffect thread.

  3. Wouldn't tuples of an image and a preset would make sense?

     

     

    Do I understand correctly, XML presets could only be used with a Windows Forms based effect (or the 'OptionBasedLibrary' in the future) but are not possible with the current IndirectUI?
     

     

    Imagine the following (simplyfied): PropertyBasedEffect derives from Effect. It provides a token, a dialog and the renderer. The properties (variables) you are defining are used to create the controls in the dialog and the content of the token. Entering a property value in the dialog triggers the creation of a token containing all current values of the properties. The token will then be sent to the render function. Dialog and render function are running in different threads. So render does not block the UI.

    If you press OK then a final token will be created and sent to render. At the same time Paint.NET stores this token and and reuses it the next time to setup the dialog or to allow to repeat the command by just sending the token to render w/o opening the dialog.

     

    But there is no way in PropertyBasedEffects to create a token and tell the effect to use it. The only thing you may do is to set a flag which will be evaluated in the render function which uses a different setting or saves the current one. But there is no way to store property values in a token and sent it back to the effect or dialog. This disturbs the standard way how Paint.NET works.

     

    OptionBasedEffect is simular to PropertyBased but with some add-ons like the load/save copy/paste of the token feature. You do not have to do something special. This is a build-in functionality (OK you have to set a config flag ;-) Only if you are creating your own OptionControls and the datatype of the control is complex then you also have to provide an xml-serializer and deserializer.

    • Upvote 1
  4. If your still looking for a Save Settings method Maybe this will help. It's my Pixel Puller with 10 save-able slots. kinda like GameBoy.

     

    Please don't use such methods to implement things. This is really not the Paint.NET way and there is no need to do it.

    1) You should never write to the program folder. It should be write protected.

    2) If the UI elements do not reflect the settings used to render then you are disturbing the way how tokens are handled by the application. This has several side effects. I.e. you are not able to repeat the effect using Ctrl-F.

    3) In general try to avoid to kill the multithreading of Paint.NET. Use the OnRender function to render the stuff. If you are not doing this then the user will never get any feedback in the progressbar nor gain from multicore environments.

    4) Respect that IndirectUi is limited and allows together with CodeLab fast programming of effects (you are allowed to concentrate on the math). If you need more UI things go one step back and use the basic effect interface (Or maybe OptionBasedLibrary ;-)

    • Upvote 1
  5. Instead of a PropertyBased solution (using IndirectUi) the OptionBasedLibrary may be used. It offers the simplicity of PropertyBased plus extra features like

    - xml serialization of options (load/save copy/paste of options)

    - reset all

    - about

    - more ui elements including containers (i.e. tabs)

    - translations via .dlc file

    - extensibility (define your own option controls)

    - distinguishes between intermediate and final rendering

    There is just no final version in the moment because I^m a little bit busy on real life work ;-)

    The library versions differ in name so there is no risk that changes in the interface will create incompatibilities.

    The switch from a property based solution to the option based is typically done in some minutes (if you know both interfaces).

    The library will be open source after reaching version 1.0 ;-)

    • Upvote 1
  6. None of the following issues is in any way important. Just a list I collected for a while.

     

    1) Shortcuts in menus

    There is a small issue with OEM character shortcuts. I.E Ctrl++ does not work with a german keyboard layout. The reason is that '+' is Shift+1. Here a code snippet how I solved this in other applications

     

       tsmi.ShortcutKeys = OemCharacterToKeys(Keys.Control, '+');
       tsmi.ShortcutKeyDisplayString = OemCharacterToDisplayString(Keys.Control, '+');

     

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern short VkKeyScanW(char ch);
    
    private static Keys CharactertoKeys(char c)
    {
        // Map character to scan code
        short scanCode = VkKeyScanW(c);
    
        // Translate scan code to key
        Keys key = (Keys)(scanCode & 0x00FF);
        if ((scanCode & 0x0100) != 0) key |= Keys.Shift;
        if ((scanCode & 0x0200) != 0) key |= Keys.Control;
        if ((scanCode & 0x0400) != 0) key |= Keys.Alt;
    
        return key;
    }
    
    public static Keys OemCharacterToKeys(Keys modifiers, char c)
    {
        return modifiers | CharactertoKeys(c);
    }
    
    public static string OemCharacterToDisplayString(Keys modifiers, char c)
    {
        // Get the text for the combination of the modifiers with the A key
        string text = new KeysConverter().ConvertToString(modifiers | Keys.A);
    
        // Replace the dummy A key with the character
        return text.Remove(text.Length - 1) + c;
    }
    

     

    And please do not translate the ShortcutKeyDisplayString. The result is that some few shortcuts are translated and the most other ones are not. I.e. Ctrl++ shows STRG++ while Ctrl+B shows Ctrl-B.

     

    2) Zooming with the wheel does not look to be deterministic ;-)

     

    Here is a proposal

     

      scaleFactor = ScaleByIncrement(scaleFactor, (int)Math.Round(wheelDeltaNormalized));

     

    private float ScaleByIncrement(float scaleFactor, int increment)
    {
        const double steps = 8;                     // number of steps between 2^n and 2^(n+1)
        double n = Math.Log(scaleFactor, 2);        // scaleFactor=2^n => determine n
        n = Math.Round(n * steps) / steps;          // round n depending on steps
        n += (double)increment / steps;             // add the increment
        scaleFactor = (float)Math.Pow(2, n);        // calculate the scale factor
    
        // This generates the following scaleFactor values (steps=8)
        // ..., 0.125, ..., 0.25, ..., 0.5, 0.545, 0.595, 0.648, 0.707, 0.771, 0.841, 0.917, 1
        // 1, 1.091, 1.189, 1.297, 1.414, 1.542, 1.682, 1.834, 2, ..., 4, ..., 8, ...
    
        return scaleFactor;
    }
    

     

    3) Ticks in ruler. OK this is a bit pedantic ;-)

     

    If the main division is 50 then the next subdivision is 20 40 70 90 better would be 20 40 60 80.

    This seems always be the case if the subdivision is 1/2.5 (and not 1/2).

    It took a while figuring out why the rulers are looking strange to me.

    But maybe this is a US thing...

     

    4) Allow escape key to reset the pan function (this is what Windows allows while moving a window).

     

    5) Show the drag image while dragging on top of Paint.NET and not just the drag cursor.

     

     

     

    • Upvote 1
  7. I created this using this plugin in development and welshblue's Glossy metallic text tutorial. Nice plugin, I do look forward to a final version :)

     

    Nice to see your results. 'Final' will take a while. There are so many things to do. But after getting the SVG loader in an acceptable stage, let us continue with this part of the path tools. Still fighting with text and other effects on paths...

  8. Version 0.7 is no longer Tiny (this part of the SVG standard is too restrictive). Beside of filter effects it renders not too bad ;-)

    At the end it shows the power of GDI+ (even if the internal lib may move in the future to a different graphics interface).

  9. As for this, you'll have to describe what happens in more detail. (Okay you told me it doesn't revert to Save As, ... so what does it do?)

     

    Paint.NET crashes if you are pressing Ctrl-S after loading an image using this file type (ImSVGTiny). But only if this image is the active one. I would expect a fallback to Save as if the SupportSaving flag is not set. Means it should not touch the SaveToken at all even if the implementation is not correct as you mentioned.

  10. Imports SVG files and renders them to Paint.NET bitmap layers.
    This is a stand-alone plugin for Paint.NET and does not require Inkscape.

    This plugin will be part of the path tools.

    Warning: This software is still beta and just for test. If you see issues not on the ToDo list then feel free to provide a test svg file.

     

    Example:

    post-79572-0-26869600-1375979904_thumb.j gallardo.svg.zip

    Installation
    - Copy the two files OptionBasedLibrary v0.3.dll/.dlc to the Paint.NET\ folder (NOT to Paint.NET\FileTypes\ !!!)
    - Copy the two files ImSVGTiny.FileType.dll/.dlc to the Paint.NET\FileTypes\ folder
    - Remove other plugins supporting the same file type (.svg) from Paint.NET\FileTypes\ folder (to avoid possible conflicts)
      I.e. 'SVGImport.dll' plugin.
    - Do not remove older versions of the OptionBasedLibrary if they are required from other plugins.

    Load dialog options
    - Canvas: The SVG file may or may not contain settings about the size of the image to produce (see 'File settings' at the
      end of the dialog). You may overwrite the proposed option to get a better quality of the image.
    - Resolution: The DPI value is used to setup the document and to calculate coordinates and lengths in the SVG file (if
      a unit identifier like inch or mm is used with a value).
    - Background: Typically the background of an SVG file is transparent. This option allows you to select your own background.
      If the 'Layers' option is not set to 'flat' then the background will be placed in a seperate layer.
    - Layers: If this option is not set to 'flat' then a new layer will be generated for each top-level element in the
      svg file. If you created the file with Inkscape it will show you the inkscape layer structure.
      Be warned: Depending on the file the not 'flat' option will generate a lot of layers. This may slow down the application.
    - File folder: Paint.NET does not provide the file path to the plugin (just a data stream). If an SVG file uses
      relative references to other files (like bitmap images) then this option allows you to specify the SVG file folder.
    - 'File settings' options (read only)
      - Viewport is the size to use on the canvas
      - Viewbox is the range of coordinates used in the SVG file. The viewbox will be stretched to the viewport respecting
        aspect ratio (or not).
      - Title: The 'title' element of the svg file.
      - Description: The 'desc' element of the svg file.

    Known issues:
    - If you are canceling the option dialog you will get an unspecified error. But this just means that Paint.NET
      has no idea about canceling the load operation.
    - If you try to 'Save' (not 'Save As') a loaded svg then Paint.NET will not fallback to 'Save As' automatically.
      The 'Save' dialog opens and shows an error.
    - The option dialog has no owner because OnLoad() runs in a different thread than the Paint.NET Ui. The disadvantage
      is that you will not get a warning beep if you try to activate the application. Still the dialog stays modal to Paint.NET.
    - The Browse For Folder dialog is even worse. Because this dialog requires OLE it has to run in a STA thread.

    On the 'To do'  list:
    - Add support for filter element (Minimum Gaussean blur).
    - Improve text support (Font handling, text areas and text on path)
    - Better support for SpreadMethod attribute used for gradients.
     

    ImSVG.FileType v0.7.zip

  11. There are several reasons. I.e:

    - the user gets more information on the type of the file from the input stream and changes the decicision to load the file

    - loading takes too long and the user likes to abort. (there is a reason why a running effect can be aborted)

     

    If you like to keep the error for any reason then I would propose to show the reason if possible (and not unspecified which is not true). This would help the user to understand what's going on.

  12. Maybe someone could point me in the right direction to fix this exception

     

    System.InvalidCastException: Unable to cast object of type 'PaintDotNet.SaveConfigToken' to type 'OptionBased.FileTypes.OptionBasedSaveConfigToken'.
       at PaintDotNet.SaveConfigWidget`2.InitWidgetFromToken(SaveConfigToken sourceToken) in D:\src\pdn\pdn_35x\src\Data\SaveConfigWidget`2.cs:line 52
       at PaintDotNet.Dialogs.SaveConfigDialog.set_FileType(FileType value) in D:\src\pdn\pdn_35x\src\PaintDotNet\Dialogs\SaveConfigDialog.cs:line 346
       at PaintDotNet.Controls.DocumentWorkspace.GetSaveConfigToken(FileType currentFileType, SaveConfigToken currentSaveConfigToken, SaveConfigToken& newSaveConfigToken, Surface saveScratchSurface) in D:\src\pdn\pdn_35x\src\PaintDotNet\Controls\DocumentWorkspace.cs:line 1877
       at PaintDotNet.Controls.DocumentWorkspace.DoSave(Boolean tryToFlatten) in D:\src\pdn\pdn_35x\src\PaintDotNet\Controls\DocumentWorkspace.cs:line 2266
       at PaintDotNet.Menus.FileMenu.MenuFileSave_Click(Object sender, EventArgs e) in D:\src\pdn\pdn_35x\src\PaintDotNet\Menus\FileMenu.cs:line 245
       at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
       at System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
       at PaintDotNet.Menus.PdnMenuItem.OnClick(EventArgs e) in D:\src\pdn\pdn_35x\src\PaintDotNet\Menus\PdnMenuItem.cs:line 302
       at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
       at PaintDotNet.Menus.PdnMenuItem.OnShortcutKeyPressed(Keys keys) in D:\src\pdn\pdn_35x\src\PaintDotNet\Menus\PdnMenuItem.cs:line 174
       at PaintDotNet.PdnBaseForm.ProcessFormHotKey(Keys keyData) in D:\src\pdn\pdn_35x\src\Core\PdnBaseForm.cs:line 791
       at PaintDotNet.PdnBaseForm.ProcessCmdKeyData(Keys keyData) in D:\src\pdn\pdn_35x\src\Core\PdnBaseForm.cs:line 846
       at PaintDotNet.PdnBaseForm.ProcessCmdKey(Message& msg, Keys keyData) in D:\src\pdn\pdn_35x\src\Core\PdnBaseForm.cs:line 829
       at System.Windows.Forms.Control.ProcessCmdKey(Message& msg, Keys keyData)
       at System.Windows.Forms.ContainerControl.ProcessCmdKey(Message& msg, Keys keyData)
       at System.Windows.Forms.Control.ProcessCmdKey(Message& msg, Keys keyData)
       at System.Windows.Forms.Control.ProcessCmdKey(Message& msg, Keys keyData)
       at System.Windows.Forms.ContainerControl.ProcessCmdKey(Message& msg, Keys keyData)
       at PaintDotNet.Controls.DocumentView.ProcessCmdKey(Message& msg, Keys keyData) in D:\src\pdn\pdn_35x\src\PaintDotNet\Controls\DocumentView.cs:line 1318
       at System.Windows.Forms.Control.ProcessCmdKey(Message& msg, Keys keyData)
       at System.Windows.Forms.Control.PreProcessMessage(Message& msg)
       at System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg)
       at System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)
    

     

    I created a new abstract filetype OptionBasedFileType and derived SvgTinyFileType from it. SvgTinyFileType does not set SupportsSaving.

    Loading works fine but using File->Save (via menu or keyboard) throws the above exception.

     

    There are two issue now:

    1) Why does 'Save' not fall back to 'Save As' if  SupportsSaving is not set

    2) Why is there this cast exception

     

    Here the code of OptionBasedFileType

     

    namespace OptionBased.FileTypes
    {
        using System;
        using System.IO;
        using System.Reflection;
        using PaintDotNet;
        using OptionControls; 
        using ControlExtensions;
    
    
    #if false
        internal class TestFileType : OptionBasedFileType
        {
            protected override void OnSaveT(Document input, Stream output, OptionBasedSaveConfigToken token, Surface scratchSurface, ProgressEventHandler progressCallback)
            {
            }
    
            protected override Document OnLoad(Stream input)
            {
                return null;
            }
    
            internal TestFileType()
                : base(
                    "OBF - Example", 
                    0
                    //| FileTypeFlags.SupportsLayers
                    //| FileTypeFlags.SupportsCustomHeaders
                    //| FileTypeFlags.SupportsSaving
                    | FileTypeFlags.SupportsLoading
                    //| FileTypeFlags.SavesWithProgress
                    ,
                   new[] { ".obf" })
            {
            }
        }
    #endif
        
        
        public sealed class OptionBasedSaveConfigToken 
            : SaveConfigToken
        {
            // ...
        }
    
        public sealed class OptionBasedSaveConfigWidget 
            : SaveConfigWidget<OptionBasedFileType, OptionBasedSaveConfigToken>
        {
            // ...
    
            protected override void InitWidgetFromToken(OptionBasedSaveConfigToken sourceToken)
            {
                // ...
            }
    
            protected override OptionBasedSaveConfigToken CreateTokenFromWidget()
            {
                // ...
                return new OptionBasedSaveConfigToken();
            }
    
            public OptionBasedSaveConfigWidget(FileType fileType)
                : base(fileType)
            {
            }
        }
    
        public abstract class OptionBasedFileType
                : FileType<OptionBasedSaveConfigToken, OptionBasedSaveConfigWidget>
        {
    
           protected override sealed OptionBasedSaveConfigToken OnCreateDefaultSaveConfigTokenT()
            {
                return new OptionBasedSaveConfigToken();
            }
    
            protected override sealed OptionBasedSaveConfigWidget OnCreateSaveConfigWidgetT()
            {
                return new OptionBasedSaveConfigWidget(this);
            }
    
            public OptionContext Context
            {
                get; private set;
            }
    
            internal OptionBasedFileType(OptionContext context, FileTypeFlags flags, string[] extensions)
                : base(context.GetTranslatedText(context.Id), flags, extensions)
            {
                Context = context;
            }
    
            protected OptionBasedFileType(Type type, FileTypeFlags flags, string[] extensions)
                : this(OptionContext.GetContext(type.Name, Assembly.GetCallingAssembly()), flags, extensions)
            {
            }
        }
    
    }
    
    
    

     

     

    BTW: It would be nice if Paint.NET would add the plugin to Utilities->View Plugin Load Errors if Paint.NET fails to load a filetype plugin.

     

     

     

     

     

     

     

     

     

     

     

     

  13. As far as I understand the issue, it is not forseen to cancel OnLoad().

     

    Returning null or throwing an exception will result in the message box

     

    "There was an unspecified error while opening the file."

     

    So if there is no other solution I propose to check for OperationCanceledException in the future and skip the messagebox in this case.

     

    I will add this to my FileType plugins.

     

    BTW: Returning a document w/o any layer will kill Paint.NET, sooner or later.

     

     

     

     

     

  14. Please edit the first post and add more info:

    A description where the plugin should be placed and how to call it.

    Does it handle the whole image or just the current layer?

    A short readme in the zip would be nice.

     

    Do not misunderstand me but I would need more information to install a plugin from an unknown source.

×
×
  • Create New...