Jump to content

null54

Moderator
  • Posts

    1,962
  • Joined

  • Last visited

  • Days Won

    89

Posts posted by null54

  1. 12 hours ago, Rick Brewster said:

    Well, it looks like a DDS from Starfield. Not sure we should post their assets here, that might be copyright infringement.

     

    There are already over 300 mods for Starfield on Nexus Mods, so I doubt Bethesda would care about one file being posted as part of a modding question.

     

    12 hours ago, Rick Brewster said:

    do you have Starfield yet? If not I can grab it and get the file to you. I'm still playing Baldur's Gate 3 (10 out of 10 btw), but I'm sure I'll be getting to Starfield too.

     

    No I do not, but I will be getting it eventually.

    Starfield is still in pre-order on Steam (it releases on the 5th), so I am wondering if this issue is due to Valve encrypting the pre-load files.

    I don't think Bethesda has released the official modding tools either, but I could be wrong about that.

     

    While I was trying to find documentation on the Starfield DDS files, I found a few posts on the Nexus Mods Bethesda Archive Extractor page about an older version of that tool not extracting some DDS files from the game archives correctly.

    I am not blaming that tool, it could be a bug in the DDS plugin but I will not know that unless I can examine the DDS file.

  2. 2 hours ago, FreePainter said:

    Does the "secured browse extension" change my Edge browser so that ongoing updates from Microsoft to the Edge browser will present potential conflicts with my Windows 11 install?

     

    Paint.NET does not bundle anything with the installer, you probably clicked on an ad.

    You can also download the Paint.NET installer from the mirror on GitHub: https://github.com/paintdotnet/release/releases/latest

  3. 1 hour ago, pn20190618 said:

    I am using Paint.net 5.0.8 portable.
    The command "paintdotnet:/set:FileTypes/BuiltInHEICFileTypeEnabled=false" tries to open the MS App Store

     

    That makes sense, as the paintdotnet protocol would only be registered for the installed version (either classic or Microsoft Store).

    You should be able to set the value by opening a command prompt in the folder that Paint.NET is located in and typing:

     

    paintdotnet.exe /set:FileTypes/BuiltInHEICFileTypeEnabled=false

     

  4. 4 minutes ago, Rick Brewster said:

    I'm guessing you want to use the built-in JPEG FileType because it knows how to deal with WIC and all of its sharp corners.

     

    That is correct. Mainly for the fact that it handles all of the metadata support, which would be a pain to re-implement using WIC.

    I considered casting the token returned by CreateDefaultSaveConfigToken to PropertyBasedSaveConfigToken, but that is a bit of a hack.

     

    19 minutes ago, Rick Brewster said:

    However, instead of general purpose APIs (e.g. FileType), it might be reasonable to put in a special purpose interface for this sort of thing, e.g.

     

    That would work.

  5. 3 hours ago, Rick Brewster said:

    You don't need to use ClearWithCheckerboardPattern(), which is a weird old method that doesn't give you, or allow you to provide, any layout or colorization information. Just clear with solid color (light or dark), then fill in the diagonal squares with the other color.

     

    I used ClearWithCheckerboardPattern() because it was the only public API I could find that would allow a plugin get a checkerboard with the same colors as the native PDN one.

     

    4 hours ago, Rick Brewster said:

    You can also use Direct2DPictureBox if you're working with a static image (or mostly static -- you can still update it with InvalidateBitmap(), but it will re-upload the whole thing to the GPU). It has an EnableAlphaCheckerboard property you can enable. You can derive from the class and override OnRenderBackground() and OnRenderForeground() to draw decorations below or above the bitmap.

     

    That would be the way to go for almost any other plugin, but in PSFilterPdn I am implementing a Photoshop plugin API that only provides the plugin host with the pixels to render and the destination HDC.

     

    4 hours ago, Rick Brewster said:

    If necessary I can also look at providing some additional classes in PDN to help out with your scenario(s)

     

    As I mentioned above, PSFilterPdn only requires a checkerboard that matches the PDN canvas.

    But an ICheckerboardRendererService would be useful for most of the tool plugins, perhaps something like:

    public enum CheckerboardTileSize
    {
        Small,
        Medium,
        Large
    }
    
    public interface ICheckerboardRendererService
    {
        Render(RegionPtr<ColorBgra32> destination);
        // Other overloads as necessary
        Render(RegionPtr<ColorBgra32> destination, Point2Int32 srcOffset, ColorBgr32 light, ColorBgr32 dark, CheckerboardTileSize tileSize);
    }

    The single parameter overload would render the same checkerboard as the PDN canvas, with the other overloads allowing the plugin to customize the checkerboard.

    The proposed API probably need some refinement, I was basing it off the methods in CheckerboardUtil.

     

    Another API that would probably be useful for the various tool plugins that show their own dialogs (e.g. Shapemaker) is an ICanvasUIColorsService:

    public interface ICanvasUIColorsService
    {
        // The color surrounding the outside of the canvas
        ColorBgr32 Background { get; }
        
        ColorBgr32 CheckerboardDark { get; }
        
        ColorBgr32 CheckerboardLight { get; }
    }
  6. 11 hours ago, Rick Brewster said:

    I prepare a regular IBitmap<ColorPbgra32> with only the top-left 2x2 squares of the checkerboard. At 96 DPI this is only an 8x8 bitmap (I use the integer floor of the DPI/scaling factor in order to scale the 8x8 pixel size). Load it into an IDeviceBitmap (aka ID2D1Bitmap1). Then create an IBitmapBrush (aka ID2D1BitmapBrush) around that with InterpolationMode.NearestNeighbor.

     

    Is it an 8x8 bitmap or 16x16?

    I had to use 16x16 with the following code, otherwise it rendered as a solid color.

     

    int dpiScaleFactor = (int)Math.Floor(UIScaleFactor.Current.Scale);
    int size = 16 * dpiScaleFactor;
    
    bitmap = new WICBitmapSurface<ColorPbgra32>(size, size, imagingFactory);
    
    using (Surface checkerboardSurface = new(size, size))
    {
        checkerboardSurface.ClearWithCheckerboardPattern();
    
        RegionPtr<ColorBgra> region = checkerboardSurface.AsRegionPtr();
    
        PixelKernels.SetAlphaChannel(region.Cast<ColorBgra32>(), ColorAlpha8.Opaque);
    
        RegionPtr<ColorPbgra32> premultiplied = region.Cast<ColorPbgra32>();
    
        PixelKernels.ConvertBgra32ToPbgra32(premultiplied);
    
        using (ISurfaceLock surfaceLock = bitmap.Lock(SurfaceLockMode.Write))
        {
            RegionPtr<ColorPbgra32> dst = new((ColorPbgra32*)surfaceLock.Buffer,
                                              surfaceLock.Width,
                                              surfaceLock.Height,
                                              surfaceLock.BufferStride);
            premultiplied.CopyTo(dst);
        }
    }
  7. My current GDI+ code renders the checkerboard to its own Bitmap, and then performs a double-buffered copy to render it to the target Graphics object.

    The double buffering is used to prevent flickering when the main image is rendered over the checkerboard.

     

    Here is a link to the code for DrawCheckerboardBitmap: https://github.com/0xC0000054/PSFilterPdn/blob/61aef4befe814e8043e208334fb7bfc17aed98b6/src/PSApi/LoadPsFilter.cs#L2526

    I did not include a copy of its code to reduce the length of this post.

     

    int width = displaySurface.Width;
    int height = displaySurface.Height;
    
    if (checkerBoardBitmap == null ||
        checkerBoardBitmap.Width != width ||
        checkerBoardBitmap.Height != height)
    {
        DrawCheckerBoardBitmap(width, height);
    }
    
    // Use a temporary bitmap to prevent flickering when the image is rendered over the checker board.
    using (Bitmap temp = new(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
    {
        Rectangle rect = new(0, 0, width, height);
    
        using (Graphics tempGr = Graphics.FromImage(temp))
        {
            tempGr.DrawImageUnscaled(checkerBoardBitmap, rect);
            tempGr.DrawImageUnscaled(aliasedDisplayPixelsBitmap, rect);
        }
    
        hdc.DrawImageUnscaled(temp, dstX, dstY);
    }

     

    Based on the existence of the BeginDraw and EndDraw methods, I am assuming that Direct2D does not require the manual double buffering.

     

    Is there a more efficient method of rendering the checkerboard than creating a full-size image?

    Looking at the ID2D1RenderTarget documentation, it appears that an ID2D1BitmapBrush could be used with the ID2DRenderTarget FillRectangle method.

  8. It turns out that NuGet installs those dotnet packages, even though it exits with an error message.

    The final command I am using in PSFilterPdn to trim CommunityToolkit.HighPerformace and TerraFX.Interop.Windows is below.

     

    <ItemGroup>
      <PackageReference Include="CommunityToolkit.HighPerformance" Version="8.2.1" />
      <PackageReference Include="MessagePack" Version="2.5.124" />
      <PackageReference Include="NuGet.CommandLine" Version="6.6.1">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      </PackageReference>
      <PackageReference Include="TerraFX.Interop.Windows" Version="10.0.22621.2" />
    </ItemGroup>
    <PropertyGroup>
      <!-- This is required for MSBuild to copy the refrenced NuGet packages to the build output folder -->
      <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
      <!-- Set the .NET runtime information -->
      <CurrentRuntime>$(TargetFramework.Replace('-windows', ''))</CurrentRuntime>
      <CurrentRuntimeVersion>$(BundledNETCoreAppPackageVersion)</CurrentRuntimeVersion>
      <CurrentRID>$(NETCoreSdkRuntimeIdentifier)</CurrentRID>
      <!-- Set Path Variables -->
      <PdnRoot>D:\Program Files\paint.net</PdnRoot>
      <SDKRoot>$(NetCoreRoot)sdk\$(NETCoreSdkVersion)</SDKRoot>
      <illink>$(SDKRoot)\Sdks\Microsoft.NET.ILLink.Tasks\tools\$(CurrentRuntime)\illink.dll</illink>
      <NugetSourceRoot>$(UserProfile)\.nuget\packages</NugetSourceRoot>
      <NETCoreAppPackageName>Microsoft.NETCore.App.Runtime.$(CurrentRID)</NETCoreAppPackageName>
      <NETCoreAppDir>$(NugetSourceRoot)\$(NETCoreAppPackageName)\$(CurrentRuntimeVersion)\runtimes\$(CurrentRID)\lib\$(CurrentRuntime)</NETCoreAppDir>
      <WindowsDesktopPackageName>Microsoft.WindowsDesktop.App.Runtime.$(CurrentRID)</WindowsDesktopPackageName>
      <WindowsDesktopAppDir>$(NugetSourceRoot)\$(WindowsDesktopPackageName)\$(CurrentRuntimeVersion)\runtimes\$(CurrentRID)\lib\$(CurrentRuntime)</WindowsDesktopAppDir>
      <!-- Set a few additional properties -->
      <!-- All of these warnings are related to the DLLs that are not being trimmed -->
      <ILLinkIgnoredWarnings>IL2026;IL2028;IL2034;IL2046;IL2050;IL2055;IL2057;IL2058;IL2059;IL2060;IL2062;IL2065;IL2066;IL2067;IL2070;IL2072;IL2075;IL2077;IL2080;IL2087;IL2088;IL2090;IL2091;IL2092;IL2093;IL2094;IL2096;IL2104;IL2111;IL2118;IL2121</ILLinkIgnoredWarnings>
      <ILLinkFolderName>link</ILLinkFolderName>
    </PropertyGroup>
    <ItemGroup>
      <!-- The SourceFile items will be copied to the output folder -->
      <SourceFile Include="$(TargetPath)" />
      <SourceFile Include="$(TargetDir)$(TargetName).pdb" />
      <SourceFile Include="$(TargetDir)$(TargetName).deps.json" />
      <SourceFile Include="$(TargetDir)MessagePack.dll" />
      <SourceFile Include="$(TargetDir)MessagePack.Annotations.dll" />
      <!-- The FastDebug configuration does not call ILLink to trim the DLLs -->
      <SourceFile Condition="'$(Configuration)' == 'FastDebug'" Include="$(TargetDir)CommunityToolkit.HighPerformance.dll" />
      <SourceFile Condition="'$(Configuration)' == 'FastDebug'" Include="$(TargetDir)TerraFX.Interop.Windows.dll" />
      <SourceFile Condition="'$(Configuration)' != 'FastDebug'" Include="$(TargetDir)$(ILLinkFolderName)\CommunityToolkit.HighPerformance.dll" />
      <SourceFile Condition="'$(Configuration)' != 'FastDebug'" Include="$(TargetDir)$(ILLinkFolderName)\TerraFX.Interop.Windows.dll" />
      <OutputDirFiles Include="$(TargetDir)output\*.*" />
    </ItemGroup>
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
      <!-- 1st Step: Install the .NET packages that are required for trimming -->
      <!-- All errors are ignored because NuGet reports that is doesn't support the package type after installing it -->
      <Exec Condition="'$(Configuration)' != 'FastDebug' And !Exists('$(NETCoreAppDir)')" Command="$(PkgNuGet_CommandLine)\tools\NuGet.exe install $(NETCoreAppPackageName) -Version $(CurrentRuntimeVersion) -OutputDirectory $(NugetSourceRoot)" IgnoreExitCode="true" IgnoreStandardErrorWarningFormat="true" />
      <Exec Condition="'$(Configuration)' != 'FastDebug' And !Exists('$(WindowsDesktopAppDir)')" Command="$(PkgNuGet_CommandLine)\tools\NuGet.exe install $(WindowsDesktopPackageName) -Version $(CurrentRuntimeVersion) -OutputDirectory $(NugetSourceRoot)" IgnoreExitCode="true" IgnoreStandardErrorWarningFormat="true" />
      <!-- 2nd Step: Trimming with ILLink -->
      <Exec Condition="'$(Configuration)' != 'FastDebug'" Command="dotnet exec &quot;$(illink)&quot; -a &quot;$(TargetPath)&quot; all &#45;&#45;trim-mode copy &#45;&#45;action copy &#45;&#45;action link &quot;CommunityToolkit.HighPerformance&quot; &#45;&#45;action link &quot;TerraFX.Interop.Windows&quot;  -d $(TargetDir) -d $(NETCoreAppDir) -d $(WindowsDesktopAppDir) &#45;&#45;skip-unresolved -out &quot;$(TargetDir)$(ILLinkFolderName)&quot; &#45;&#45;nowarn $(ILLinkIgnoredWarnings)" />
      <!-- 3rd Step: Copy all dependencies to the output directory -->
      <Copy SourceFiles="@(SourceFile)" DestinationFolder="$(TargetDir)output" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="true" />
      <!-- 4th Step: Delete the ILLink output directory -->
      <RemoveDir Condition="'$(Configuration)' != 'FastDebug'" Directories="$(TargetDir)$(ILLinkFolderName)\" />
      <!-- 5th Step: Copy the output folder to the Paint.NET Effects folder -->
      <Copy SourceFiles="@(OutputDirFiles)" DestinationFolder="$(PdnRoot)\Effects\PSFilterPdn" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="true" />
    </Target>

     

    Because trimming takes a significant amount of time it is skipped for the FastDebug project configuration, I copied this from CodeLab's build process.

    The appropriate Microsoft.NETCore.App.Runtime and Microsoft.WindowsDesktop.App.Runtime packages will be downloaded and installed if necessary.

     

    After trimming, the trimmed files are copied into an output folder and the ILLink trimming folder is deleted.

    This step could probably be skipped and replaced with step 5, but it simplified the process of verifying that things were working correctly.

    • Like 1
  9. 3 hours ago, Rick Brewster said:

    What happens if you add in those?

     

    That worked.

    So it appears that part of the problem may have been that the -d commands should be placed after all of the DLL commands.

    I had also used the wrong paths in my previous attempt with those packages.

     

    Now I just need to figure out how to make msbuild automate installing those packages if they are not present.

    Unfortunately, it is not possible to add a reference to those packages in the project file or install them with the NuGet command line client. Both of those methods produce an error that the DotnetPlatform package type is not supported.

  10. 58 minutes ago, Rick Brewster said:

    What is the command line that you're using?

     

    <SDKRoot>$(NetCoreRoot)sdk\$(NETCoreSdkVersion)</SDKRoot>
    <CurrentRuntimeId>net$([System.Version]::Parse($(NETCoreSdkVersion)).ToString(2))</CurrentRuntimeId>
    
    <illink>$(SDKRoot)\Sdks\Microsoft.NET.ILLink.Tasks\tools\$(CurrentRuntimeId)\illink.dll</illink>
    <!-- All of these warnings are related to the various Paint.NET DLLs, which are not being trimmed -->
    <ILLinkIgnoredWarnings>IL2026;IL2028;IL2034;IL2050;IL2055;IL2057;IL2060;IL2065;IL2066;IL2067;IL2070;IL2075;IL2080;IL2104;IL2121</ILLinkIgnoredWarnings>
    
    dotnet exec &quot;$(illink)&quot; -a &quot;$(TargetPath)&quot; all &#45;&#45;trim-mode copy &#45;&#45;action copy -d $(TargetDir) &#45;&#45;skip-unresolved &#45;&#45;action link &quot;CommunityToolkit.HighPerformance&quot; &#45;&#45;action link &quot;TerraFX.Interop.Windows&quot; -out &quot;$(TargetDir)trim&quot; &#45;&#45;nowarn $(ILLinkIgnoredWarnings)

     

    The command is a slightly modified version of the one that otuncelli posted above, I changed the link targets and suppressed the trim warnings from the Paint.NET DLLs.

  11. The ILLink command that @otuncelli posted does not work correctly for some of the types in CommunityToolkit.HighPerformace or TerraFX.Interop.Windows.

    The linker removes the IDisposable implementation from types that implement it (e.g. ArrayPoolBufferWriter<T> or ComPtr<T>),  resulting in a crash when the runtime tries to call the now missing Dispose() method.

     

    I have not been able to figure out the ILLink command to keep those references when trimming.

×
×
  • Create New...