Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Implement ColorFloat #1772

Draft
wants to merge 13 commits into
base: development
Choose a base branch
from

Conversation

pushfoo
Copy link
Member

@pushfoo pushfoo commented May 15, 2023

Core questions / tasks:

  • Implement core class
  • Resolve circular dependency questions for conversion methods
  • Add tests

Follow-up work:

  1. Resolve naming issues (ColorFloat vs ColorNorm, RGBAFloat vs RGBANorm)

@@ -410,6 +412,324 @@ def random(
return cls(r, g, b, a)


class ColorFloat(RGBANormalized):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a good candidate for NamedTuple? I think it gives us the @propertys, the deepcopy, and the default a value for free.

I used this snippet to test, I may have missed corner cases.

class Color(NamedTuple):
    r: float
    g: float
    b: float
    a: float = 1.0

a = Color(1, 2, 3)
b = copy.deepcopy(a)
print(repr(a), repr(b))
print(a is b)

Copy link
Member Author

Choose a reason for hiding this comment

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

tl;dr NamedTuple subclassing made validation harder for Color, and is much slower according to einarf.

I don't know if the latter is still true on more recent Python versions, and it may be worth rebenchmarking periodically. I agree that your proposal could be cleaner if future minimum Python versions lose its current disadvantages.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I see einarf saying NamedTuple is slow, but not saying that what you have written is faster. That makes me think that both might be equally slow. Did anyone benchmark at the time of that conversation?

There's good precedent for this question, since one of my first benchmarks found that shapely was slower even though the shapely code was meant to be faster.

@cspotcode
Copy link
Collaborator

cspotcode commented May 22, 2023

Should there be a class like this for every form of color, with conversion methods between them all? Or should this be the only color class, and all conversions between color formats are done into or out of this class? E.g.

my_color_rgba255 = ColorFloat.from_hex_string("FFEE00").as_rgba255

EDIT Actually, is that conversion safe? I guess floats have enough precision to reliably convert "EE" -> float -> 238. It feels dirty but is probably fine.

@pushfoo
Copy link
Member Author

pushfoo commented May 22, 2023

tl;dr to my knowledge, the current approach is compatible and performant at the price of verbosity

Should there be a class like this for every form of color, with conversion methods between them all?

There are only two color formats I know of supported in arcade and pyglet:

  1. Byte-value RGBA tuples on the user-facing side
  2. Float-valued RGBA tuples on the internal OpenGL side, as inside SpriteList

The implementation in this PR will cover both of them with backward-compatible fancy versions. It will also help with a potential switch to storing colors as floats internally across the codebase. It's something which einarf has brought up at least once before, and I think it's worth pursuing.

Or should this be the only color class, and all conversions between color formats are done into or out of this class? E.g.

I'm not sure which other color formats we'd want to add. HSV or HSL seem like the best candidates, but their primary use for games seems like it would be color shifting or generating palettes rather than real-time gameplay. Other color models don't seem as useful since this is a games library rather than image editor or color framework.

Building a fully generic, extensible Color type doesn't seem worth the disadvantages it seems to have:

  1. Loss of easy compatibility with pyglet and older arcade-dependent code
  2. Possible performance hits from more complicated conversion logic

If there's a way to do it without these problems, then it's worth considering.

It feels dirty but is probably fine.

It's worth double checking. The current implementation is a conversion function from 2.6.X moved into an instance method and with nicer formatting.

@pushfoo
Copy link
Member Author

pushfoo commented Jun 4, 2023

Should there be a class like this for every form of color, with conversion methods between them all? Or should this be the only color class, and all conversions between color formats are done into or out of this class? E.g.

After giving the issue additional thought, I think the following approach is best:

  1. Finish this PR
  2. If needed, optimize or replace the backing implementation

We're getting bogged down in details. As much as I love the idea of HSV support, I don't think it's crucial for 3.0.

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.

None yet

2 participants