Slider OnChange[SOLVED]

Started by Vincent, Sat 11/11/2017 15:17:41

Previous topic - Next topic

Vincent

Good Evening to all AGSer.

So I have an inventory window (78x156) that can display 12 items before that a vertical slider is showed. My intention would be to scroll the inventory items by a single row with the vertical slider when changing. But I am having some issues about how to according the slider value (max and min) with how many items the inventory window can display. So to achieve the slider movement to be adjusted with how many items the inventory window can display?

Khris

#1
This should do it:
Code: ags
// Global script

function on_event(EventType event, int data) {
  if (event == eEventAddInventory || event == eEventLoseInventory) {
    // calculate how many rows of inv items are going to be hidden
    int hiddenRows = (iw.ItemCount - 1) / iw.ItemsPerRow - iw.RowCount + 1;
    if (hiddenRows > 0) {
      sldInv.Max = hiddenRows;
      sldInv.Visible = true;
    }
    else sldInv.Visible = false;
  }
}

function sldInv_OnChange(GUIControl* control) {
  invWindow.TopItem  = (sld.Max - sldInv.Value) * invWindow.ItemsPerRow;
}


Edit:
Changed the slider to become visible/invisible, which makes much more sense, fixed min-max axis.

Vincent

Hi Khris, thanks a lot for answering.
Well, somehow this is working but in a very strange way.
When I first move a little the slider to the down side all items disappears, if I keep moving the slider to the down side (and I reach the min value of the slider) then it scroll all the items per row but somehow it make the scroll in reverse.

Khris

I tested it and the slider's max value is at the top, which means the OnChange line should be
Code: ags
  invWindow.TopItem  = (sld.Max - sldInv.Value) * invWindow.ItemsPerRow;

Vincent

Hi Khris, I would like to say that this is working perfectly now! :-D
Thank you very much once again.

There is one essential thing that is not working properly yet as I wish.
At the moment, I reach the end of all the items when the slider is more or less at the centre.
I would like to reach the end of the items when the slider is at min value, and viceversa the top item would be at max of the slider (just like it is working right now) It is possible to do something like this?

Khris

Did you set the slider's min value to 0 in the editor?

Vincent

Yes of course, I have it in this way.



Your code is working perfectly.
I just wish that when I move the slider his movement should be accorded with how many items there are in the inventory window. I wish that if I reach the min value of the slider I should reach the last items in the inventory window and viceversa (otherwhise the slider shouldn't be able to scroll).

At the moment, when I reach more or less the centre of the slider value I see the latest items and if I continue to move the slider down it keep scrolling. (But in this way it's not working very well because when I reach the latest items more or less at the centre value of the slider then I am able to keep scrolling the items and the inventory window look empty) :(

Khris

Quote from: Vincent on Mon 13/11/2017 10:07:13I just wish that when I move the slider his movement should be accorded with how many items there are in the inventory window.
But that is of course what my code is supposed to be doing, and does, when I test it.
It's why I start with calculating the number of hidden rows: so I can set the slider' max value to it.

The only thing I can think of right now is that you are testing this with an inventory that's already pretty full and expect it to work from the start of the game. That's actually not the case; the bulk of my code is only called after an inventory item is gained or lost for the first time.
Your Max value of 100, which gives you a ton of empty rows, is never changed until on_event is called for the first time.

Just put player.AddInventory[iWhatever]; in your first room's room_Load and it will update the slider.

Vincent

Hi Khris, I am sorry because sometimes I am a fool. I was testing your code with the debug command (give all inventory items, which I was sure that your code were calling properly since you have done the code in on_event adding or losing an item) and pretending that to work good. However I have test it properly throught the game and of course, it is working as I wish! You have done an exellent work as usual. Thank you very much! :)

Please, if you don't mind, I would like to ask you a couple of questions more. I have two buttons which (on_click) it is called properly (InventoryWindow.ScrollUp/ScrollDown) When I do that, can I adjust the slider value as we are doing at the moment? So if I move the slider or click the buttons it will be the same thing? Also, can I do exactly all of this for a listbox too? 

Khris

Sure, at this point it's probably best to factor out the slider update code:
Code: ags
void updateSlider() {
  int hiddenRows = (iw.ItemCount - 1) / iw.ItemsPerRow - iw.RowCount + 1;
  if (hiddenRows > 0) {
    sldInv.Max = hiddenRows;
    sldInv.Visible = true;
  }
  else sldInv.Visible = false;
}

function on_event(EventType event, int data) {
  if (event == eEventAddInventory || event == eEventLoseInventory) {
    updateSlider();
  }
}

function btnInvDown(GUIControl* control, MouseButton button) {
  if (button != eMouseLeft) return;
  InventoryWindow.ScrollDown();
  updateSlider();
}


Same for the other button.

As for the listbox, I guess you can. .ItemCount - .RowCount will give the number of hidden items.

Vincent

#10
Alright, this was simple after all! I really appreciated all the help you gave me! :)
Best regards once again!


:EDIT:
So now, for the slider listbox I have something like this.
Code: ags

void UpdateSliderListbox()
{
  // calculate how many rows of inv items are going to be hidden
  int hiddenRows = (ListBox1.ItemCount - ListBox1.RowCount);
  if (hiddenRows > 0) 
  {
    SliderListBox1.Max = hiddenRows;
    SliderListBox1.Enabled = true;
  }
  else SliderListBox1.Enabled = false;
}

I am calling this function on game_start!


On slider change I have something like this:
Code: ags

ListBox1.TopItem  = (SliderListBox1.Max - SliderListBox1.Value) * ListBox1.ItemCount; 


But when I try to test it (moving the slider) I get this message.
ListBox1SetTopItem: tried to set top to beyond top or bottom of list
I am not sure how to fix it at all.

Khris

No need to multiply; it should be
Code: ags
  ListBox1.TopItem  = SliderListBox1.Max - SliderListBox1.Value;

Vincent

Okay, but this is strange, because it show exactly the same error message.

Khris

Where did you move the slider? All the way to the bottom, I assume?

Let's say we have a list of 10 items, of which 7 are visible.
That should set .Max to 3, which means there's a total of 4 positions.
If the slider is all the way up, we're setting TopItem to 3 - 3, which is 0.
If the slider is all the way down, we're setting TopItem to 3 - 0, which is 3. That should show items 3 to 9, that's 7 items.

To find the error, as usual, do some basic debugging:
Code: ags
  int ti = (SliderListBox1.Max - SliderListBox1.Value) * ListBox1.ItemCount;
  Display("Setting .TopItem to %d", ti);
  ListBox1.TopItem = ti;

Vincent

#14
Quote from: Khris on Tue 14/11/2017 14:04:55
Where did you move the slider? All the way to the bottom, I assume?

Yes, you are right. Well, the listbox get populated with items in run-time and in case they can even be deleted. So I think the slider should be updated dinamically I suppose. The listbox can contain a max of 5 items before the slider get enabled. If I start to populate the listbox with items and do something like this it work fine:

Code: ags

void UpdateSliderListBox()
{
  // calculate how many rows of items are going to be hidden
  int hiddenRows = (ListBox1.ItemCount - ListBox1.RowCount) - 5;
  if (hiddenRows > 0) 
  {
    SliderListBox1.Max = hiddenRows;
    SliderListBox1.Enabled = true;
  }
  else SliderListBox1.Enabled = false;
}


Code: ags

function SliderListBox1_OnChange(GUIControl *control)
{
  ListBox1.TopItem = (SliderListBox1.Max - SliderListBox1.Value);
}


Well, since I don't add an item or remove it, how to find the right formula?

Khris

Just to make sure we aren't talking past each other: you need to call UpdateSliderListBox(); whenever you have just added or removed items to/from the listbox. That is the only way to make sure the current .Max value properly reflects how many hidden items there are.
That's why there's a formula in the first place: to calculate the Max value based on the current length of the list and the number of visible items.

Quote from: Vincent on Wed 15/11/2017 15:32:57So I think the slider should be updated dinamically I suppose.
Again, yes, OF COURSE it does. It needs to be updated whenever the number of total items changes. How else is it supposed to work? I didn't even think to mention this, since I thought it's obvious.

Adding an item without calling the update function afterwards will cause the slider to hit the end before the bottom of the list is reached.
Removing an item without calling the update function afterwards will cause the game to crash when you scroll too far down.

Vincent

I am sorry because this is working just good.
For some odd reason, I didn't add UpdateSliderListBox(); whenever adding or removing an item...


Quote from: Khris on Wed 15/11/2017 16:55:43
It needs to be updated whenever the number of total items changes. How else is it supposed to work?

I am sorry about this but thank you very much for your help, it is all working good! :)

SMF spam blocked by CleanTalk