Simulating Infinite Numbers of Buttons

From Multiverse

Jump to: navigation, search

For this project, we will use a concept known as windowing. You have a large or variable amount of data, but cannot display it all at once.

Usefulness

Being able to simulate a theoretically infinite number of buttons is useful. Lets say that you want a crafting menu that allows the user to simply click on the thing that he wants to create, but the amount of options available could be hundreds and could vary for each player. Because UI elements are defined in XML, they are statically generated. You could create 100000 buttons and hide the ones that you are not using, but this will be slow to load, inefficient, and still puts a cap on what you are capable of. That is the method used in MvDialog and will suit some basic purposes. Another possible method would be to put each item in a ScrollingMessageFrame and check for OnClick events. Then, with some hand-waving, you might be able to figure out which item the user clicked on based upon how high up he is scrolled and the Y position of the mouse. That is far too much work, however, and may not even be entirely possible. Even then, it has limited usefulness since it can only display items in a manner supported by ScrollingMessageFrame. If you're really desperate, you might have your python code rewrite the XML code and call /reloadui. That is a truly drastic measure with many side-effects. But there is a better way than all of these.

I am developing this system for several purposes, including:

  • Have a dynamic number of chat tabs. Perhaps you could have one chat tab for each private /tell conversation, for instance.
  • Have a dynamic NPC conversation system where many dozens of options might be available at any one time, and you can just click on one to proceed.
  • Crafting, mentioned above
  • Dynamic number of inventory objects that can be clicked on

Theory

Because you cannot create buttons on the fly and defining thousands of buttons is impractical, we will instead have a fixed number of buttons that scroll through data on their own. For instance, let us say that you have 20 options but only want to have 5 buttons visible at a time. In python, we will store all available options and only display the ones we are currently interested in. For instance...

[Option 1] [Option 2] [Option 3] [Option 4] [Option 5] (6-20 stored in memory)

When the user presses the scroll button, instead of physically moving those buttons, we will instead change the text / texture of every single button. Those same buttons now read

[Option 2] [Option 3] [Option 4] [Option 5] [Option 6] (1, 7-20 stored in memory)

Doing it this way, we no longer care how many buttons are displayed because all the data is saved in a list, and the list can be as big or small as we like.

Implementation

Create the buttons as you would any other, but it's easiest if you have them inherit this:

<Scripts language="python">
<OnClick>OnClick(this.GetText())</OnClick> 
<OnMouseWheel>OnWheel(args)</OnMouseWheel>  		
</Scripts>

The frame containing those buttons also needs to have this:

<Scripts language="python">
<OnLoad> Init() </OnLoad>
</Scripts>

Then, write your Python something like this:

topics=[]
topindex=0
maxindex=20

def Init():
	global topics
	for j in xrange(0,20,5):
		topics.append("Greetings" + str(j))
		topics.append("Gossip" + str(j+1))
		topics.append("News" + str(j+2))
		topics.append("Local" + str(j+3))
		topics.append("Something" + str(j+4))
	
def OnClick(string):
	global maxindex
	topics.append(string)
	maxindex = maxindex + 1

	
def OnWheel(args):
	if (args.data>0.0):
		ScrollUp()
	else:
		ScrollDown()
		
def ScrollUp():
	global topics
	global topindex
	if (topindex==0):
		return
	topindex = topindex-1
	for j in range(0,7):
		button = getglobal("TopicListButton%d" % (j))
		button.SetText((topics[j+topindex]))
	
		

def ScrollDown():
	global topics
	global topindex
	if (topindex==maxindex-7):
		return
	topindex = topindex+1
	for j in range(0,7):
		button = getglobal("TopicListButton%d" % (j))
		button.SetText((topics[j+topindex]))


Clicking on a button will add a new element to the list with a higher number. It's not particularly useful, but it does demonstrate the concept. You will, of course, also need to have some way to scroll up and down. Here, I just check for the MouseWheel event. A simple modification could make it so that instead of storing a list, the text of the button is dynamically generated from the position number. This would effetively give you a theoretically infinite number of buttons, since Python's long data type is bounded only by your computer's memory.

To change textures rather than the text of the button, you would just need to save each texture in the list and call SetNormalTexture(x) instead of SetText.

Personal tools