Drawing on cursors, but restoring the old version after **SOLVED**

Started by Knox, Tue 10/08/2010 22:04:01

Previous topic - Next topic

Knox

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  :-[
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

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.

Knox

Hey Khris!

Ok, Ill try that out sometime today and let you know what happens!
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

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:
Code: ags

  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:
Code: ags

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):

Code: ags

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!
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

Do you get an error message?
What's the exact wording and which line does it refer to?

Knox

#5
Ok, if I use the first solution for "void clearThisSprite":
Code: ags
 (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":
Code: ags

  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:
Code: ags

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:

Code: ags

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):



Arrow drawn on an opaque sprite:




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!
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

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.

Code: ags
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.

Knox

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!!
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

Great, glad it finally worked!

Don't thank me, thank the magic pink ;)

SMF spam blocked by CleanTalk