Hi guys,
I was able to use Calin's AGS Blend plugin to blend 2 alpha sprites together to make a "resume" cursor when my mouse hovers over the resume button in my inventory...it uses the item's cursor sprite and combines it with an arrow + resume text so the player knows he can resume with that item.
Everything is fine up until I try to restore the item's "normal" cursor sprite...so when the mouse cursor is no longer hovering over the resume button, I would like it to "revert" back to the item's normal cursor without the drawn "resume arrow" over it.
Im guessing I need to somehow store the item's cursor image somewhere? Does this mean I need to store copies of all my different item's cursors? (That would suck)...
Im using Calin's plugin so I dont have to make new "resume" cursors for all the game's inventory items.
Im not too sure how to proceed :-[
I'm guessing you've imported the standard cursor images as sprites; all you'd need to do is populate a dynamic array (size: Game.InventoryItemCount) with the slots of the cursor images.
To revert to default, call player.ActiveInventory.CursorGraphic = def_curs[player.ActiveInventory.ID];
I don't know how the plugin works or what you're using to change the cursor image though, so I can merely guess whether this will work.
Hey Khris!
Ok, Ill try that out sometime today and let you know what happens!
Ok, well I went another route since I think it has the potental of being easier...although I ran into a problem and Ive tried for quite a while now to fix it:
1) What I decided to do is when I select an item, its cursor graphic gets drawn into temp sprite 132:
if (mouse.Mode == eModeSelectInv || mouse.Mode == eModeUseinv) //save the "Resume with Item" cursor graphic to a variable
{
//clear sprite 132 so it can be drawn to
clearThisSprite(iBufferItem132);
//draw default cursor onto empty sprite 132, save it temporarily
DrawAlpha(iBufferItem132.Graphic, overItem.CursorGraphic, 0, 0, 0);
bDrawn = false;
}
2) In rep exec, if the mouse is over my "resume" button in the inv menu, drawResumeItemCursor gets called:
void clearThisSprite(InventoryItem *Buffer)
{
DrawAlpha(Buffer.Graphic, 1827, 0, 0, 0);
//clearSprite = DynamicSprite.CreateFromExistingSprite(Buffer.Graphic);
//DrawingSurface *surface = clearSprite.GetDrawingSurface();
//surface.Clear();
//Buffer.Graphic = clearSprite.Graphic;
//surface.Release();
}
void drawResumeItemCursor()
{
clearThisSprite(iBufferItem133);
//draw 132 default item image onto empty sprite 133
DrawAlpha(iBufferItem133.Graphic, 132, 0, 0, 0);
//draw Resume Arrow over the item's cursor into sprite 133
DrawAlpha(iBufferItem133.Graphic, 1826, 0, 0, 0);
mouse.ChangeModeGraphic(eModePointer, iBufferItem133.Graphic);
mouse.ChangeModeHotspot(eModePointer, 65, 34);
}
Anyways, it works fine if the sprite image in "clearThisSprite" is opaque (1827)...Of course I dont want that...If I make sprite 1827 a fully transparent png, it wont really "replace" the other sprite with itself, it just draws "nothing" over it...
How can I "clear" a sprite to nothing?
ps: I checked the "clear" command in the manual and tried it but it doesnt seem to work in this case(dynamic sprites not existing):
void clearThisSprite(InventoryItem *Buffer)
{
//DrawAlpha(Buffer.Graphic, 1827, 0, 0, 0);
clearSprite = DynamicSprite.CreateFromExistingSprite(Buffer.Graphic);
DrawingSurface *surface = clearSprite.GetDrawingSurface();
surface.Clear();
Buffer.Graphic = clearSprite.Graphic;
surface.Release();
}
Im really not sure how to proceed here!
Do you get an error message?
What's the exact wording and which line does it refer to?
Ok, if I use the first solution for "void clearThisSprite": (DrawAlpha(Buffer.CursorGraphic, 1827, 0, 0, 0);)
I get 99% of what I want, except of course the opaque background of sprite 1827.
Now, if on the other hand I use the other solution for "void clearThisSprite":
clearSprite = DynamicSprite.CreateFromExistingSprite(Buffer.Graphic);
DrawingSurface *surface = clearSprite.GetDrawingSurface();
surface.Clear();
Buffer.Graphic = clearSprite.Graphic;
surface.Release();
...this is where I get errors...First of all, the pointer's cursor becomes the arrow image over an invisible background (doesnt show the arrow over the item's cursor, just the arrow)...and secondly, when I go back into the inventory window with that "only the arrow" cursor, and I try clicking on another item, I get an error like this:
Error: DynamicSprite.CreateFromExistingSprite: sprite 1834 does not exist
**EDIT**
ps: The error pop-up box didnt give me any lines, its one of those internal errors (not the kind that gives an error message in the ouput window).
**EDIT**
Ok, well I got it to work finally, the way I wanted...the only thing is, the result of the blended sprites is much nicer if instead of clearing the sprite to be drawn on, I put an opaque sprite and then draw my alpha arrow over it...if the sprite being drawn to is fully transparent, the result of the combination with DrawAlpha seems to be a bit "blocky"....as in, the gradient shadows arent smooth, but just black, and blotchy/blocky.
Here is what I did:
void clearThisSprite(InventoryItem *Buffer)
{
//DrawAlpha(Buffer.CursorGraphic, 1827, 0, 0, 0);
clearSprite = DynamicSprite.CreateFromExistingSprite(Buffer.CursorGraphic);
DrawingSurface *surface = clearSprite.GetDrawingSurface();
surface.Clear();
Buffer.CursorGraphic = clearSprite.Graphic;
surface.Release();
}
void drawResumeItemCursor()
{
clearThisSprite(iBufferItem132);
DrawAlpha(iBufferItem132.CursorGraphic, player.ActiveInventory.CursorGraphic, 0, 0, 0);
//draw Resume Arrow over the item's cursor into sprite iBufferItem132.CursorGraphic
DrawAlpha(iBufferItem132.CursorGraphic, 1826, 0, 0, 0);
mouse.ChangeModeGraphic(eModePointer, iBufferItem132.CursorGraphic);
mouse.ChangeModeHotspot(eModePointer, 65, 34);
}
Arrow drawn onto a transparent sprite (with the "clear" function):
(http://www.2dadventure.com/ags/blocky.PNG)
Arrow drawn on an opaque sprite:
(http://www.2dadventure.com/ags/smooth.png)
All that is left to figure out is why is the combined sprite nicer when the background is opaque...and then trying to fix that!
Alright, let's start over.
This seems to be getting way to complicated otherwise.
All we need to do is assign a DynamicSprite to the UseInv cursor.
When the mouse moves over the button, redraw the sprite using .CursorGraphic & resume sprite.
When the mouse leaves the button, redraw sprite using .CursorGraphic.
DynamicSprite*inv_curs;
bool mouse_was_over_resume = true; // force sprite initialization
void RedrawInvCursor(bool resume) {
int cg = player.ActiveInventory.CursorGraphic;
// init DynamicSprite (once, when an inv item is selected for the first time)
if (inv_curs == null) {
inv_curs = DynamicSprite.CreateFromExistingSprite(cg, true); // create sprite
mouse.ChangeModeGraphic(eModeUseinv, inv_curs.Graphic); // assign sprite to mouse mode
}
else inv_curs.Resize(Game.SpriteWidth[cg], Game.SpriteHeight[cg]); // remove if all inv cursor sprites are of same size
// clear it
DrawingSurface*ds = inv_curs.GetDrawingSurface();
ds.Clear(Game.GetColorFromRGB(255, 0, 255)); // clear with magic pink i.e. make it transparent
ds.Release();
// redraw it
DrawAlpha(inv_curs.Graphic, cg, 0, 0, 0);
if (resume) DrawAlpha(inv_curs.Graphic, 1826, 0, 0, 0);
}
// rep_ex_always
GUIControl*gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
Button*b;
if (mouse.Mode == eModeUseinv && gc != null) {
b = gc.AsInt;
if (b == bResume && !mouse_was_over_resume) {
mouse_was_over_resume = true;
RedrawInvCursor(true);
}
else if (b != bResume && mouse_was_over_resume) {
mouse_was_over_resume = false;
RedrawInvCursor(false);
}
}
(The code assumes that the button's script name is "bResume".
NOT TESTED.)
The "trick" is never to delete the sprite that's used by the cursor. It is just redrawn as necessary.
Well Holy CRAP, this works SUPER nicely...now the newly drawn cursors have perfect alpha blending!
This will save me from having to draw many cursor sprites individually...like close to a hundred, serious :P
You made my day,
Thanks Khris!!
Great, glad it finally worked!
Don't thank me, thank the magic pink ;)