ColorPane, a suite of color tools for Studio [v0.5.0]

Hello everyone, ColorPane has been updated to v0.3.1. This is a very small update which fixes a single bug:

  • Fixed a bug where trying to use the scroll wheel on a dropdown selector (e.g. slider or palette pickers) resulted in a blank page

If you don’t know what this update is talking about, there is a shortcut where you can use the scroll wheel to switch between sliders and palettes instead of having to open the dropdown. Here’s a video (scroll wheel not included):

Technical information about the bug

As far as I can tell, sometime between v0.3.0 and v0.3.1 there was an update where the Z component of an InputObject’s Position was changed from -1 or 1 to -0.5 or 0.5. The original dropdown UI code relied on this value being -1 or 1, so the change broke scroll wheel functionality.

Apologies for the lack of new stuff in this update. Unless there are new bugs discovered or reported, the next version should be a feature update.


In other news, we recently passed 300 sales! It means a lot to know that so many people have tried out ColorPane. Thank you for using the plugin, and happy holidays!

:christmas_tree: :cookie:

3 Likes

Thanks for making this available to the community! I am interested in using this as part of a plugin, as it appears Roblox Studio does not provide color picker functionality for plugin authors. I’ve seen a lot of Roblox devs asking for this feature, so I imagine yours would be great for many of us.

How can I reference ColorPane from my plugin? I am OK with either compiling your code directly into mine or requiring the end user to have already downloaded your plugin and referencing it that way. I tried both and failed.

Reference Github Sources
When I cloned your repo from github and referenced it from my script, I get all sorts of errors relating to not being able to find referenced .lua files. Specifically, the folders under your ‘include’ dir are empty - promises, roact, etc.

I could take some guesses at which repo/release/etc. to clone for each of those repos and try to manually plumb things in, but I’m guessing there is some procedure to do this automatically that I’m not aware of.

Reference Live Plugin
I am not familiar with how to reference an existing live plugin, so I guessed a few things - CoreGui:WaitForChild(…), PluginGuiService(…) - and haven’t yet been able to figure it out.

Thanks for your help!

To use the color pickers from another plugin, you need to use the ColorPane API, which requires having the plugin installed.

This API is only exposed after the user presses the Inject API button in the toolbar, or at start-up if the user has the specific setting enabled. If the user allows this, there will be a ModuleScript inserted into CoreGui named ColorPane which will contain the API. You can read this page for more information about how to inject and acquire the API, and this page for the API reference.

You don’t need to compile any code unless you want to contribute to the plugin’s development. Hope this helps!

1 Like

Thank you! This helped me better understand what “Inject API” means and I was able to get the color picker to pop up from my plugin. Success!

One note to other “promise-newbies” like me: I had a hard time figuring out how to determine if the user had pressed the “Cancel” button on ColorPane. This is what I ended up with to detect cancellation:

        promise
            :andThen(
                function(newColor)
                    -- This never seems to get triggered.  Don't know why... 
                    -- ... but it's not important because we get notified in PromptOptions::OnColorChanged
                    print("Promise finished with status=" .. tostring(promise:getStatus()))
                end,
                function(errorObject)
                    error("Caught promise error: " .. tostring(errorObject))
                end)
            :doneCall(
                function()
                    local promiseStatus = promise:getStatus()
                    if (promiseStatus == "Cancelled") then
                        print("User cancelled color selection")
                    end
                end)
            :catch(
                function(errorObject)
                    error("Promise catch block entered: " .. tostring(errorObject))
                end)

Can you color a specific face on the part?

No, but as far as I know you can’t color individual faces of Parts anyway. This plugin doesn’t add building utilities like the one you’re describing, it adds ways for designers to choose colors for their projects.

1 Like

This looks pretty cool, I wanted to try this out myself at one point but I couldn’t figure out the math.

Anyway, is there any chance of a built-in module that just calculates the colors with the UI? This would make it easier for integration with games, where a localscript can just call a function in a modulescript, passing in a folder which contains the UI, and gets the Color3 as a response.

I think I need clarification on what you’re asking for. Are you asking for a module that lets you pass a GUI element to hook up for picking colors?

1 Like

Yes, so developers can get the color tools UI, add it to their game and use a module to handle updating the UI and get the selected color etc.

Ok, I see. I don’t have any plans on making such a module, but I have been thinking about how ColorPane could be adapted to be used in games. It’s a project I want to try in the future, but I don’t have any immediate plans to work on it. Sorry about that.

1 Like

Just an update on how things are going

Hello everyone, v0.4 isn’t ready yet, but there are some important things I want to tell you about before its release. I’m planning for a release by the end of the month, if nothing goes wrong.

Translations

I’ve recently added localisation functionality, so that ColorPane can be accessible to people who speak different languages. I don’t know any langauges other than English, however, so I would like your help to translate the plugin.

If you’re interested in helping to translate ColorPane, you can contribute to the Crowdin project.

API Injection Changes

API injection is becoming automatic in v0.4. The first time you open up ColorPane after the update, you will receive a prompt that you are about to be asked for script injection. You won’t be able to use the plugin until you click “I understand”.

Script injection prompt

This is being done to simplify user experience. If you’re not comfortable with script injection, you can of course deny the permission, however you won’t be able to export palettes to ModuleScripts or let other plugins use the API, which may break the functionality of plugins that require it.

API Changes (for plugin developers)

There are some changes to the API coming in v0.4. You can view the updated API reference here.

  • API.PromptForColorSequence is being deprecated. API.PromptForGradient will be replacing it.
  • API.IsColorSequenceEditorOpen is being deprecated. API.IsGradientEditorOpen will be replacing it, but it works the exact same way.
  • Immediately-rejected Promises returned by the API return a PromptError (see below) instead of a string with a message.

API.PromptForGradient works similarly to PromptForColorSequence, but has different options.

{
    PromptTitle: string?,
    GradientType: string?,
    InitialGradient: (Gradient | ColorSequence)?,
    InitialColorSpace: string?,
    InitialHueAdjustment: string?,
    InitialPrecision: number?,
    OnGradientChanged: ((Gradient | ColorSequence) -> nil)?
}
  • PromptTitle will not be changed.
  • InitialColor will be changed to InitialGradient.
  • OnColorChanged will be changed to OnGradientChanged.

If you’re using API.PromptForColorSequence you will need to change your code for the renamed options, but otherwise should work as before.

Explanations of the other options

Unless you want to get really specific about how the gradient is constructed, you don’t need to read this section.

  • GradientType tells what the data type of the gradient is, either ColorSequence or Gradient.
    • If you pass InitialGradient but not GradientType, it will be inferred by the data type of InitialGradient.
    • If you pass both InitialGradient and GradientType, they must correspond with each other, otherwise the Promise will be immediately rejected with an InvalidPromptOptions error.
  • InitialColorSpace refers to the color space that the gradient should be in. By default, this option is RGB, but you can specify any of the available color spaces.
  • InitialHueAdjustment refers to the hue adjustment for the gradient. By default, this option is Shorter, but you can specify any of the available adjustments.
  • InitialPrecision refers to the “precision” of the gradient, or how closely it resembles what the gradient should actually look like. This can range from 0-18, but the maximum precision depends on the number of keypoints in the gradient.
    • Specifically, the maximum precision for k keypoints, with maximum km keypoints (currently 20) is math.floor((km - 1) / (k - 1)) - 1

Additionally, there will be some new API members:

  • API.GetVersion returns the version of the API as a tuple.
  • API.PromptError is an enum with the following members: InvalidPromptOptions, PromptAlreadyOpen, and ReservationProblem. You can view what each of these means in the updated API reference.

Any deprecated API members will be removed with the v1.0 update, but there’s no ETA on when v1.0 is coming, if it ever does. I don’t anticipate on removing them before 1.0, though.

If you have any question, don’t hesitate to PM me or reply to the message.


In other news, we recently passed 500 sales! :tada: I honestly didn’t expect my plugin to get this many sales. Thank you to everyone who’s tried out ColorPane, even if you ended up uninstalling it.

Apologies for the latest update taking longer than previous versions. I’ve gone back to school, which means that I have less time to work on the plugin.

:cookie:

2 Likes

v0.4.0

Hello everyone, it’s been a long while since the last major update (I’ve been busy with school), but I’m happy to announce that a new version is available. A lot of the work for this version is focused on the API and internal plumbing, but there a plenty of new features in the mix. As always, you can read the full changelog here.

The update notes for this release are split into two sections, one for user-related changes, and one for API-related changes.

User-related Highlights

  • Added color interpolation controls and ColorSequence code exporting to the Gradient Editor
  • Added the Color Tools section where the Color Info page used to be
  • Added HWB, Lab, Luv, LCh(ab/uv), xyY, and XYZ to Color Info
  • Added a color sorter that uses CIEDE2000 in the Color Tools section
  • Added a Picular palette (idea from csqrl’s Picular plugin)
  • Added a Gradient picker tool which allows users to pick colors from their gradients
  • Color Properties now shows the color type of the each property
  • Mouse drag inputs now work outside of editor windows
  • Scrollbars no longer interfere with mouse drag inputs
  • Improved keypoint dragging behaviour in the Gradient Editor
  • Exporting palettes now lists color components correctly (components were listed in the order RBG instead of RGB)
  • A first-time use prompt will now appear informing the user that script injection is required for exporting palettes to ModuleScripts and the API
  • API injection is now automatically done at startup
Video gallery of some new features


The new Picular palette


The new gradient pickers


The new color sorter

Automatic API injection

As of v0.4, API injection will now be automatic. When you install the plugin for the first time (or you run the plugin for the first time if you were using it before v0.4), a prompt will pop up notifying you about the automatic API injection.

After you click the “I understand” button, if you’ve never injected the API before you will get a prompt to allow script injection. Afterwards, the plugin will inject the API automatically whenever you start up the plugin. You can’t use the plugin until you’ve clicked the button.

What if I don't want to allow script injection?

Of course, you don’t have to allow script injection. if you’re not comfortable with a script being injected, you can deny the permission, however you will be getting a warning every time the plugin starts up. You can always turn script injection on (or off) if you change your mind later.

Most of the plugin will work, regardless of whether you allow script injection. Other plugins, however, will not be able to use the API, which may limit or break their functionality.

Better mouse dragging

In previous versions of ColorPane, mouse drag inputs would stop updating once the mouse left the plugin window. This update changes the internals of how mouse dragging works, so mouse inputs should now continue to update outside the plugin window.

You may remember a certain bug I mentioned in the v0.3.0 release. With the changes made to mouse dragging, this bug no longer occurs. Whether or not it still exists, you won’t run into it anymore. :tada:

API-related Changes

  • Added API.GetVersion which allows external applications to check which version of the plugin is installed (the absence of this function indicates versions below v0.4)
  • Added API.PromptForGradient as a replacement for API.PromptForColorSequence, which can prompt for either Gradients or ColorSequences
  • API.PromptForColor now allows for prompting either Colors or Color3s
  • API.PromptForColor and API.PromptForGradient now reject with PromptErrors instead of message strings
  • API.PromptForColorSequence has been deprecated, please use API.PromptForGradient for new work
  • API.IsColorSequenceEditorOpen has been deprecated, please use API.IsGradientEditorOpen for new work

The primary prompt function for gradients is now API.PromptForGradient. API.PromptForColorSequence will continue to work until v1, which releases soon™. This is a summary of how the arguments have changed:

API.PromptForGradient({
    InitialGradient = ..., -- not InitialColor anymore
    OnGradientChanged = ..., -- not OnColorChanged anymore
})

All prompt options now return a API.PromptError, which is an enum with the following items:

  • InvalidPromptOptions, if the options passed to the prompt function are invalid (e.g. trying to pass a Color3 value to the InitialGradient key of GradientPromptOptions).
  • PromptAlreadyOpen, which should be self-explanatory.
  • ReservationProblem, if you either try to prompt for a color and the gradient editor is already open, or you try to prompt for a gradient and the color editor is already open.

Example usage:

API.PromptForColor({
    ...
}):andThen(function()
    ...
end, function(e)
    if (e == API.PromptError.PromptAlreadyOpen) then
        ...
    end
end)

In addition, there are new prompt options that allow for advanced usage. You can review the updated API reference for more information.

There will be more significant API changes in future versions, so please pay attention to future releases.


Thank you for using ColorPane. :cookie:

2 Likes

This looks like a very well-made resource. However, I don’t understand why this would be useful. Can you please explain?

Thank you for your interest in ColorPane.

I don’t know your individual situation, so I can’t tell you why it would be useful for you. Other people may find some of the color picker methods useful, or perhaps they would prefer the color wheel arrangement in the plugin over the color square arrangement in the default picker.

Another reason is the palette capability. The default color picker doesn’t have robust capability for storing colors, only a small palette of custom colors. ColorPane lets you create discrete palettes, and lets you share them with others. If you do UI work in Studio, you might to use palettes to keep track of component colors, keeping a consistent color scheme throughout the UI.

Hopefully I’ve explained to you why this plugin would be useful, if not to you, then to others. If you have any further questions, feel free to reply or send a PM.

2 Likes

Hello everyone, it has come to my attention that the plugin asset in the library was uploaded with some missing files, which resulted in the plugin not working. This issue has been fixed, and I’m very sorry that I didn’t notice this issue earlier.

This does not affect the plugin file uploaded on GitHub.

If there are other problems, please don’t hesitate to send me a message. Thank you.

Can you please add a HUE change for the entire gradient as an option? Much appreciated.

thank you so much im gonna use this for my plugin, crazy how easy it is to use

is there any way to make it so my plugin can install color pane for the user so they don’t have to install it themselves?

With the current version (0.4), the user has to install the plugin themself. I have been working on a new version which will allow you to use ColorPane without requiring the user to install the plugin (unless they want extra features), and it’s mostly done, but I don’t have a release date yet.

1 Like

Oh yes, an update is here.

Hello everyone, v0.5 has been released. This version has mostly been an effort to make it easier for plugin developers to use ColorPane in their own plugins.

Please let me know if you encounter any bugs. I’ve tried my best to test everything, but with the amount of stuff that’s changed, I wouldn’t be surprised if there were still bugs.

For plugin developers

Instead of having to do some weird script searching like in previous versions, I’ve put the color tools of ColorPane into their own library. To use it, you just put the script in your project and require it like any other module. In hindsight, the old way of integrating ColorPane didn’t make a whole lot of sense, and that was reflected in several of the plugins I saw that tried to integrate it. You were not, in fact, supposed to insert the whole plugin into your own plugin.

:warning: Unsurprisingly, if you’ve integrated a previous version of ColorPane, that method’s not going to work anymore. You’ll need to use the library to keep using the color tools. The process is much easier, and outlined in the documentation.

:warning: One thing end-users of ColorPane in your plugin may notice is limited functionality. Unless the end-user has the Companion plugin installed (see next section), palette editing (creation, editing, deletion, etc.) and settings changes are disabled. Palettes and settings are stored in the Companion plugin, and acts as the settings bridge between the various ColorPane instances. These instances otherwise have no way to share this information.

For everyone else

The current ColorPane plugin is being enhanced and renamed to the ColorPane Companion. These changes should be transparent to you, but are important for a seamless user experience in any other plugins integrating ColorPane.

Additionally, you should notice better multi-session (when you have multiple Studio windows open) behaviour. Settings and palette changes should now propagate between all sessions. To avoid synchronisation issues, you should only change settings from one session at a time.

Changelog

Most of the big changes are on the developer side, but here are some highlighted user-facing changes:

  • Partial translations for French, Korean, and Russian
  • Removed the Copic color palette
  • Creating colors/gradients/palettes with the same name will now name them “New Thing (1/2/3/4/etc.)” instead of “New Thing (1) (1) (1) (1) …”
  • If you have invalid palette information, only the invalid information will be removed, as opposed to literally all of your palettes (oops)
  • Changing color properties now uses the Recording API, which should result in more reliable undo/redo
Full changelog

Added

  • Added partial translations for French (fr), Korean (ko), and Russian (ru)
  • Color editor: Added a dedicated “Set Color” button for colors in the palette list layout
  • Color editor: Added a random color button
  • Gradient editor: Added a “Reset” button for gradient precision
  • Companion: Added settings importing and exporting
  • API: Added API.IsColorPromptAvailable to check if calling API.PromptForColor will succeed or immediately reject (replaces API.IsColorEditorOpen)
  • API: Added API.IsGradientPromptAvailable to check if calling API.PromptForGradient will succeed or immediately reject (replaces API.IsGradientEditorOpen)

Changed

  • Script injection is no longer a required plugin permission
  • Settings: Invalid palettes will no longer cause the entire list of palettes to be removed, just the invalid palettes
  • Color editor: Duplicating palettes with the same name will now create or increment a counter instead of naming it “Palette (1) (1) (1) …”
  • Color Properties: Changing color properties now uses the Recording API
  • API: Promises from the API no longer cancel if the user closes the prompt, they will now instead reject with PromptError.PromptCancelled
  • API: For GradientPromptOptions, the type of InitialGradient and the value of GradientType are no longer required to match
  • API: For ColorPromptOptions, the type of InitialColor and the value of ColorType are no longer required to match
  • API: The API.PromptError enum has been re-named to API.PromptRejection
  • API: The API.PromptForColor Promise now rejects with SameAsInitial instead of PromptCancelled if the initial and new colors are the same
  • API: The API.PromptForGradient Promise now rejects with SameAsInitial instead of PromptCancelled if the initial and new gradients are the same
  • API: The color tools of ColorPane have been spun off into their own library, and the old method of using ColorPane will no longer work. Please read the Integration page of the documentation for details on the updated integration method.

Fixed

  • API: API.PromptForColorSequence (deprecated) now returns a Promise as expected
  • API: Promises returned by API.PromptForColor will no longer reject when the initial and new colors are the same even though you didn’t specify an initial color
  • API: Promises returned by API.PromptForGradient will no longer reject when the initial and new gradients are the same even though you didn’t specify an initial gradient

Deprecated

  • API: API.IsColorEditorOpen is now deprecated, please use API.IsColorPromptAvailable for new work
  • API: API.IsGradientEditorOpen is now deprecated, please use API.IsGradientPromptAvailable for new work
  • API: API.PromptError is now deprecated, please use API.PromptRejection for new work
  • API: API.Unloading is now deprecated, you should use your plugin’s Unloading event instead
  • API: API.GetVersion is now deprecated

Removed

  • Removed the first-time use plugin permissions warning
  • Automatic update-checking has been removed
  • Color editor: Removed the Copic color palette

What’s Next

The UI code will need an overhaul since it uses legacy Roact, which has been deprecated in favour of React Lua. Much of the code in general needs to be refactored for type safety and modern styling conventions.

There are also several quality-of-life changes I want to add to ColorPane, including:

  • Make UIs resize-friendly (minimum sizes on plugin widgets are no longer enforced)
  • Make UIs translation-friendly (a lot of the text box sizes in the current UI are fixed-size and may not accommodate translated text)
  • A history system that lets you un/re-do color updates
  • An overhauled gradient palette experience
  • and others!

I’m anticipating that the next version will be v1.0, which also means that all the deprecated API members will be removed. If you happen to be using these members, I’ve included some replacements (which may not be 1-to-1, please review the documentation):

  • API.Unloading → Use your plugin’s Unloading event
  • API.PromptErrorAPI.PromptRejection
  • API.PromptForColorSequenceAPI.PromptForGradient
  • API.IsColorEditorOpenAPI.IsColorPromptAvailable
  • API.IsGradientEditorOpenAPI.IsGradientPromptAvailable
  • API.IsColorSequenceEditorOpenAPI.IsGradientPromptAvailable
  • API.GetVersion → None

Seeing the timeline of this update, I don’t want to make any promises as to when the next version will come out. It may be a few months, a few years, or soon™.

Regardless, thank you for using ColorPane. :cookie: