Skip to content

Allowing user to choose gradients from different sources, and allowing CloudsEffect to make use of custom gradients#683

Merged
cameronwhite merged 26 commits into
PintaProject:masterfrom
Lehonti:feature/gradient_from_selected
Jan 14, 2024
Merged

Allowing user to choose gradients from different sources, and allowing CloudsEffect to make use of custom gradients#683
cameronwhite merged 26 commits into
PintaProject:masterfrom
Lehonti:feature/gradient_from_selected

Conversation

@Lehonti

@Lehonti Lehonti commented Jan 13, 2024

Copy link
Copy Markdown
Contributor

Besides the pre-defined ones, the user can choose to get them from the colors that are currently selected (like it's done in CloudsEffect or to randomize the colors and the stops).

Also, modified CloudsEffect to be able to use custom gradients. Here's a rendering of clouds with the Electric color scheme:

image

...but at the same time the defaults should make it behave the same way it always has.

@Lehonti Lehonti changed the title Allow user to choose gradients from different sources Allow user to choose gradients from different sources, and allowed CloudsEffect to make use of custom gradients Jan 13, 2024
@Lehonti Lehonti changed the title Allow user to choose gradients from different sources, and allowed CloudsEffect to make use of custom gradients Allowing user to choose gradients from different sources, and allowing CloudsEffect to make use of custom gradients Jan 13, 2024
Comment thread Pinta.Effects/Effects/GradientHelper.cs Outdated
return CreateColorGradient (colorScheme);
case ColorSchemeSource.SelectedColors:
return ColorGradient.Create (
PintaCore.Palette.PrimaryColor.ToColorBgra (),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than accessing PintaCore.Palette, the caller should provide an IPaletteService.
For unit tests, this avoids initializing a ton of things in Pinta.Core that end up failing (this is one of the reasons why the clouds effect didn't have a unit test already)

Instead of accessing `PintaCore.Palette`
@Lehonti

Lehonti commented Jan 13, 2024

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback. I've now changed it so that an IPaletteService is passed as an argument

@Lehonti

Lehonti commented Jan 13, 2024

Copy link
Copy Markdown
Contributor Author

Also, I added IgnoreAttribute to some tests while the dependency on the global palette is still there

… the global palette is removed"

This reverts commit 71fc127.
@cameronwhite

Copy link
Copy Markdown
Member

Also, I added IgnoreAttribute to some tests while the dependency on the global palette is still there

We should remove that dependency so we can test them :)
I think the effect needs to be constructed with an IPaletteService. I'm not sure if we do that for any effects yet, but the tools are a good example of doing that. And then the unit tests can create a mock palette with the colours to test with

@Lehonti

Lehonti commented Jan 13, 2024

Copy link
Copy Markdown
Contributor Author

I removed the IgnoreAttributes, and got the palette to be accessed lazily while this is done. This has the added advantage that we can now test the CloudsEffect

@Lehonti

Lehonti commented Jan 13, 2024

Copy link
Copy Markdown
Contributor Author

These effects are now being passed an IServiceManager to the constructor, and there is now a mock palette :)

(We should probably pass IServiceManager to the constructor of other effects, but since they aren't part of the public API, I don't think it's urgent, and it may be for a future pull request, also for keeping the pull request bite-sized)

Comment thread Pinta.Effects/Effects/CloudsEffect.cs Outdated
public CloudsData Data => (CloudsData) EffectData!; // NRT - Set in constructor

public CloudsEffect ()
public IPaletteService palette { get; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have been private?

@Lehonti Lehonti Jan 14, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should have been private. Thanks for catching it. It has been corrected now

Comment thread Pinta.Effects/Effects/GradientHelper.cs Outdated

public enum ColorSchemeSource
{
[Caption ("Predefined Gradient")]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer Preset Gradient as the label for the user here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem. The label has been changed

internal sealed class MockPalette : IPaletteService
{
public Color PrimaryColor { get; set; } = new (0, 0, 0); // Black
public Color SecondaryColor { get; set; } = new (255, 255, 255); // White

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is incorrect since Cairo.Color is floating point, so the 255's should be just 1 (look at the ToColorBgra method)
You could also just do ColorBgra.White.ToCairoColor()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. For a moment I forgot that in Cairo the color channels go from 0 to 1. It's corrected now

public Color PrimaryColor { get; set; } = new (0, 0, 0); // Black
public Color SecondaryColor { get; set; } = new (255, 255, 255); // White

public void SetColor (bool setPrimary, Color color, bool addToRecent = true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the Utilities class is creating a singleton palette, this could be a future source of bugs - if tests try to set the color then this might cause the changes to affect other test runs. (And tests are executed in parallel)
I'd maybe lean towards not caching the mock service manager for now since it's currently very cheap to construct

@Lehonti Lehonti Jan 14, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. It's now creating an instance every time

mock_services = CreateMockServices ();
}

private static IServiceManager CreateMockServices ()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tried running the benchmarks with these changes, but will it cause any runtime errors if there isn't a palette provided now?

@Lehonti Lehonti Jan 14, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it shouldn't cause any runtime errors. This was added because the constructors of those effects now receive an IServiceManager, but I was careful so that the default behaviors have the exact same result as before the changes.

If the code path that was being followed before did not access the palette, it doesn't access the palette now, either.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following from running dotnet run --project tests/PintaBenchmarks -c Release -- -f \*JuliaFractalEffect

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.ApplicationException: Could not resolve service type Pinta.Core.IPaletteService
   at Pinta.Core.ServiceManager.GetService[T]() in /Users/cameron/code/Pinta/Pinta.Core/Managers/ServiceManager.cs:line 55
   at Pinta.Effects.JuliaFractalEffect..ctor(IServiceManager services) in /Users/cameron/code/Pinta/Pinta.Effects/Effects/JuliaFractalEffect.cs:line 35
   at PintaBenchmarks.EffectsBenchmarks.JuliaFractalEffect() in /Users/cameron/code/Pinta/tests/PintaBenchmarks/EffectsBenchmarks.cs:line 96

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right...The mock palette should be created and added to the service manager first. I just added it; this error you got shouldn't happen again

@cameronwhite cameronwhite merged commit d460c63 into PintaProject:master Jan 14, 2024
@Lehonti Lehonti deleted the feature/gradient_from_selected branch January 14, 2024 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants