-
Notifications
You must be signed in to change notification settings - Fork 162
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
AGS 4: support Alpha in Color parameter #2525
Comments
we don't have uints in ags script itself, what's the idea of colors there? Uhm, the text functions use blit so if the color alpha isn't 0 I think they are going to be weird. (They don't blend , this means they will replace the alpha of whatever was meant to be below the text) Other issue may be anything that has color and transparency. In general I have a bad feeling for alpha usage in color fields. Also about drawing remember that bitmaps needs to be fixed currently for the color leak issue when using linear blending instead of nearest neighbor in the bitmap to video functions. There's also the pixelperfect click detection My gut feeling is to not support alpha as color. |
Having alpha in a drawing color is the same as having alpha in imported sprites. All the logical and technical difficulties are shared between these 2 cases. When a final image is used by an object, or drawn elsewhere, there's no difference in whether it was created by importing pixels from a file, or by drawing pixels following a script command.
This does not matter, as colors are encoded as ARGBs, and should not be viewed as numbers, but as something that has a sequence of bytes combined with bitwise operations. |
remember we do a post processing currently of alpha on import in the editor! So if you read alpha it won't match the color that it was when you saved on the image editor. Plus a lot of image editors DO NOT save non black full alpha - what I mean is if you draw 0x00RRGGBB it will be then saved as 0x00000000 by a lot of image editors. We may need to notedown this somewhere in the manual because I understand the image preprocessing in the editor is going to be removed. ags/Editor/AGS.Native/agsnative.cpp Lines 1042 to 1060 in a34c748
my main concern : ags/Engine/gfx/gfxdriverbase.cpp Lines 496 to 518 in 6ce71b4
this is_mask check is about to be more expensive, this is the most expensive function in the bitmap to video memory. Other than this, all the pixelperfect tests that currently simply compare with the mask color - this is for clicking on a character or an object. plus blitting text where the color is alpha is going to puncture holes in the dialog boxes - they would need to blit to make the border in a separate bitmap and then later blended.
sure you need to do something like FFacolor now because you need the alpha to be 255. this means we are always using a negative int. |
That alpha post-processing replaces colors with alpha == 0 with a mask color (00FF00FF in 32-bit). It does not affect those pixels with non-zero alpha, they will keep their alpha value. What I meant is, AGS already may have sprites with pixels where alpha is between 0 and 255, which come by importing sprites. These sprites already affect pixel-perfect detection logic, for example. Having those alpha values put by a drawing operation in script will not add anything new here. Similarly, these sprites with varied alpha already pass through bitmap->texture conversion. Having pixels drawn with alpha won't add anything new here either. The only thing which will affect logic here are colors with 0 alpha. As you rightly mentioned, currently they are replaced by the "transparent color" constant. I did not yet decide what should happen with the "transparent color" constant, this is something to think well about, keeping consequences in mind. But in the worst case, in a short term, we may keep the rule that any drawing color with alpha 0 becomes a "mask color". Sure that will be strange (to read these pixels back), but will keep things consistent so long as this post-processing exists in sprite load.
Yes, I am aware of that. That's why I mentioned that possibly we'll have to have 2 sets of functions: for opaque drawing color, and non-opaque drawing color, where the first uses fast blitting and second uses an extra processing. This way common operations will be kept as fast as before.
That is correct. Do you see a problem with this? EDIT: EDIT2: |
Could you elaborate, why would it be more expensive, and in which circumstances? |
I think overall the idea of keeping the mask color is a good one, simply because most image drawing software do not keep the colors when drawing with zero alpha and write with 0 instead to all colors
I believe this will save us from debugging lots of user images where their software is not saving what is in memory correctly. Plus if we are going to have to do the fix for linear rendering anyway for our own drawing surfaces, there isn't much to gain from importing the images from users and keeping their alpha untouched (supposing someone uses a software that allows to correctly prepare the 0 alpha colors correctly for linear rendering). |
As for scripting, what is going to happen with
|
My first thought was that these will need to be updated on older project / game load, but that is it. The colors should not be set directly at all, but using Game.GetColorFromRGB(A), which solves the compatibility issues in script (I guess?). BTW, to clarify, all of these properties are already updated on project / game load after changing from 16-bit to 32-bit values. Then, I'd even replace these properties with ColorType struct (it exists in the script api already) which has RGB fields inside, but AGS cannot return structs from a function, so sadly obj.Color = Game.GetColorFromRGB() won't work, and neither would passing these into other functions as arguments. |
Why not setting them directly? Couldn't they be set with hex like 0xFFRRGGBB ? I am mostly worried because Everytime I need to call the script API it takes a lot of time and mostly of the optimized stuff I do in AGS Script is basically doing as few call to the engine as possible and this will make it obligatory to use the engine script api for something that was possible to do without going there at all. Calling functions from the script API is SUPER slow.
I think if it needs to be a managed struct these should be something like obj.Color.RGB = 0xRRGGBB. |
Mmm, yes, that is true. For the most of the common users, and simple cases, GetColorFromRGB would be more convenient, as that does not require to worry about how values are formed. Setting encoded values directly will be faster, but requires to comply to the current form. So, now I see that the problem of backwards compatibility can be real in this regard. EDIT: |
But AGS4 is meant to drop retrocompat. I'd rather we did not keep special cases, unless for the most dire necessity. Even in the worst case, a user would spend no more than a couple of days fixing their color assignment instances. Would it be possible to have alternative assignments like erico suggested? Like |
Any kind of multiple assignment would require to replace In this context, an idea of having separate property for "color with alpha" does not look so bad... Another approach could be in supporting parameterized macros, in which case we could replace GetColorFromRGB with a macro too, and have macros like GetOpaqueColor(r,g,b) which would add 0xFF alpha. But I don't have a defined opinion on this atm. There's an alternative posted as #1514 originally, where Alpha itself is a standalone property for drawing color in DrawingSurface. |
I see now that I opened this ticket too early, without thinking it all through from the design perspective. There are cases where having alpha in a color will either duplicate existing feature, or may not be enough to achieve all wanted effects.
Unfortunately, I did not ask @fernewelten which exactly effect of these two did he have in mind when writing #1514. I need to think more about all this... |
When writing this ticket I thought that this is an optional feature; but I did not realize at the time that after we moved to 32-bit color definition, there's now no way to distinguish "transparent color" assigned to properties, such as GUI.BackgroundColor, for instance. To be precise, it's not possible to distinguish "black" color (rgb 0,0,0) from "transparent", as traditionally ags treats color property 0 as transparent color. This is related to 8-bit, where historically palette index 0 means transparent. Because of that, in practice, since #1980 it is not possible to assign a real black color to some of the properties. This is a real bug, and should be resolved somehow soon, regardless of whether we will have full ARGB colors support or not. But at the same time, I think it's desired to implement this in a future compatible way, so that we don't completely close a ARGB opportunity. The way I see this, there are really 2 ways to deal with this:
So this is in a way related to how we think the alpha may be supported in the future. |
In regards to approaches suggested in the earlier conversation here, there are 3 distinct proposals. Few days ago we talked about this again on AGS Forums, and I will copy parts of my comments here, as a summary to these. Approach 1: Color as a managed struct Where you access colors as There are multiple issues here: the color storage in dynamic memory that has to be serialized, how game objects will be accessing these, will the Color instance duplicate color values from object's own data or read/write directly to them, etc. There will be a use of Color in object properties, but also in user script, then likely it has to contain all data within itself. AGS engine's code currently has a number of problems in its organization, which may make it inconvenient to bind a game class to a separate managed object. An example is GUI classes that do not have any proper "runtime" class equivalent yet which would allow to handle access to managed data. We'd need to reorganize them first prior to doing something like that. If we replace types of properties, then should likely also replace function arguments. There is "color" arg in few functions, like Overlay.CreateTextual; which in turn means that users will have to create Color instance explicitly there (e.g. using a constructor or a factory method). If Color is a managed struct, then it's assigned by a reference and shared, meaning that changing it in one reference will change all of instances. We may try making builtin object properties make a full copy instead of assigning a Color reference, but user variables in script will still be references. It maybe would be better if Color were a non-referenced POD type (plain struct), but then we need AGS script to implement plain struct assignment by value. So, such approach has multiple prerequisites, but doing all this just to be able to assign "alpha" value to a color sometimes seems unjustified at this point in engine development. Approach 2: Have all colors treated uniformly as ARGB in all properties and arguments. That will be most consistent, and simple to implement, but will make 0xFF... prefix mandatory for opaque colors when you define the color by hand. The downsides here are:
More notes here:
Approach 3: Have separate properties for RGB and ARGB. After some hesitation, I suppose that this is also a viable alternative. In this pair Object.Color would interpret positive integer values as RGB, and let's say "-1", or any invalid value would mean "transparent color". COLOR_TRANSPARENT constant stays as it is. The upsides of this approach are:
The downsides:
|
I think I somewhat naively assumed that supporting proper 32-bit color meant that all colors would be 32-bit. So my default assumption was Approach 2. I don't think the issue about people constructing color values manually is very serious. Anyone who is doing that will be able to adapt. For everyone else, a robust and convenient API (e.g. to adjust the opacity of a given color, or get its fully-opaque version) is key. Alternative 1 is the one I think would be most elegant from a user POV, if the building blocks were there. I feel it ought to be a non-managed struct with only one field, but you'd need to be able to pass it to as an argument. It's probably not so much better that it justifies the work. For Alternative 3, I'm mainly concerned about functions that return a color (like Aside from that, I would also suggest replacing For example, I would suggest the API in action might look something like:
|
Right, i forgot about the return values... indeed that will make things even more confusing.
I suppose that if we get plain struct copied by value someday in the future, then we could also replace xColor properties type to Color struct, which will could have a constructor and/or factory methods. Maybe it would be possible even to cast integer value to Color struct directly, implicitly calling its initializer (hence achieving script compatibility). I'm only imagining possibilities right now.
I don't know how to do this in AGS, currently it does not support such syntax for enums. Maybe this could be left for later, after it is supported. The rest of API suggestions should rather be put into a separate task imo, in order to not overload this one. |
I am tending back to the plain int approach, specially because we now have both explicitly 32-bit and 8-bit color dynamic sprites. I am back playing with my cool things and 8-bit is definitely much easier to use when using sprites to encode levels, maps and other game elements. I guess in above this is approach 2. |
After #2648 the color properties are true ARGB now, but at the moment they are "clamped" to RGB by the property grid in the editor, and they probably won't work or may cause unexpected effects if any alpha value is used when assigning them in script, besides 0 and 255. In order to make them work, we'd need at the very least:
|
I think 2 is done, but not 3 and 5 was split in it's own issue. |
So, what is left here, more or less, is -
|
I'd say to make a new Game.GetColorFromRGBA() so they're self explanatory.
This could start as a module. I've been playing with the concept and could try building something complete so we can explore how it would work. How it would perform, and stuff. |
About having script module, I think that it's a good thing to have this as a engine api anyway, because this is related to the basic operations over color data. If performance is an issue, a person may always write their own script in an optimized way, but engine api will still be there for when performance is not a problem, or user does not have time to write extra scripts for that. |
Added GetColorFromRGBA: c9367d9 |
I tested, and apparently all color properties may already be with alpha: gui and gui controls draw proper translucent colors. Same is with the speech, and text windows. I could have missed some setting, but I suppose it will be easier to fix if someone notices if one does not work. Enabled setting alpha in color properties in the Editor: f64d837 I shall close this ticket as complete now. |
This is written after #1514 and #1980.
Now when AGS supports true 32-bit colors for drawing in game, we may consider supporting Alpha value as well.
In terms of storing Alpha component in a color number, this is already supported by the field format, but there are several issues to resolve before this may be actively used.
The subtasks follow:
EDIT: alternatively, make another function for getting ARGB/RGBA.
In case alpha is 255 the standard functions are called;
In case alpha is 0, nothing is drawn and whole operation may be skipped.
In short term we may leave things as is, but then you won't be able to set alpha in the editor other than by editing a Color value by hand (and choosing a different color in the picker dialog will reset alpha to 255).
EDIT: split into ticket AGS 4: Editor: Color Picker dialog with alpha selection #2656
ints
, that is - signed ints, having alpha in them will make them go negative. That's not an issue in UI anymore, since I changed all Color properties to be displayed as RGB sequence, but they will be written as negative in the Game.agf xml. What can be done about it? We may change all of these properties touint
; but these properties are in AGS.Types, so I wonder if that will affect editor plugins. I am not versed enough in how C# interfaces work to predict the consequence of this change. Another way is to serializes these as hex. We'd probably need to add a new attribute "SerializeAsHex" for these properties.Is there anything else that comes to mind that might require attention?
UPDATE:
Subtasks 4 and 6 are resolved by #2648
Subtask 2 is resolved within #2661
The text was updated successfully, but these errors were encountered: