Substituting Animated Buttons or Sprites for Default Buttons
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
Substituting Animated Buttons or Sprites for Default Buttons
If one wishes to create totally custom "user interfaces" - and include many animated interface items (game-like), that respond in various ways to "MouseOver", "MouseDown", etc. - what is the method one would be advised to use?
Which image formats for image sequences give the highest quality results in terms of speed and image quality?
Are there built-in commands that allow LiveCoders to deploy such elements?
Once such elements are created, is there a way to store them in a library or add them to the Tool Panel for repeated use and access?
For a simple case in point: How would one employ a button which is composed of a sequence of images (an insect crawling), that both cycles through all the images in a loop and moves the "button" along a predetermined or random path each time the mouse is "Over" the "button" (the insect graphic).
How would a LiveCoder implement a change of image sequence whenever the insect "button" is clicked upon?
Psmith
Which image formats for image sequences give the highest quality results in terms of speed and image quality?
Are there built-in commands that allow LiveCoders to deploy such elements?
Once such elements are created, is there a way to store them in a library or add them to the Tool Panel for repeated use and access?
For a simple case in point: How would one employ a button which is composed of a sequence of images (an insect crawling), that both cycles through all the images in a loop and moves the "button" along a predetermined or random path each time the mouse is "Over" the "button" (the insect graphic).
How would a LiveCoder implement a change of image sequence whenever the insect "button" is clicked upon?
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
P,
Probably, you want to use buttons with icons. The advantage of buttons is that you can re-use icons as often as you like with a minimum of file size and memory usage. Whenever using buttons appears to become too complicated, you can still use images.
Kind regards,
Mark
Probably, you want to use buttons with icons. The advantage of buttons is that you can re-use icons as often as you like with a minimum of file size and memory usage. Whenever using buttons appears to become too complicated, you can still use images.
Kind regards,
Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
Re: Substituting Animated Buttons or Sprites for Default Buttons
Yes, buttons with icons would be nice. I read the short tutorial on making a rollover button, but I am still wondering what the method is for playing a sequence of images, instead of a single image, when the mouse pointer "rolls over" the icon based button.
Thanks,
Psmith
Thanks,
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
Either use an animated GIF, or just use a repeat loop with a wait for messages command and change the icon property of the button..
Code: Select all
repeat with i = 1 to 10
set the icon of button "ants" to ("ant" & i) -- works out to ant1, ant2, ..., ant10
wait for messages -- allows Rev to process other commands (leaves your application responsive)
end repeat
Re: Substituting Animated Buttons or Sprites for Default Buttons
Thank you.
So, when "wait for messages" is going through the loop, how does the repeating animation receive mouse commands? This must be another line of code, somewhere.
Psmith
So, when "wait for messages" is going through the loop, how does the repeating animation receive mouse commands? This must be another line of code, somewhere.
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
There are some different approaches, but this little sampler may give some hints.
- Attachments
-
- ants.zip
- (9.92 KiB) Downloaded 335 times
Re: Substituting Animated Buttons or Sprites for Default Buttons
Thanks.
This is pretty much what I was trying to understand, however I don't seem to be able to view any code.
I'm brand new to LiveCode, so it is probably just my ignorance kicking in.
Psmith
This is pretty much what I was trying to understand, however I don't seem to be able to view any code.
I'm brand new to LiveCode, so it is probably just my ignorance kicking in.
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
All the code is in the button script of the button with the moving ant icon. If you're having trouble selecting the moving ant button to be able to edit its script then you can use the application browser to find it, and select the edit script option there. Or, in the top right of the card, uncheck the "Test active" box to disable the moving behaviour.
Re: Substituting Animated Buttons or Sprites for Default Buttons
Sparkout:
Perhaps you didn't want this to turn into a teaching session, and, if so, I totally understand.
Having only the resources given with the LiveCode app, I've looked up some of the terms in the "Dictionary", only to find no entries. I also looked into the "Variables" category at the bottom of the "Code" section and cannot find these terms:
uMoving, sIconList, cycleimages.
I'm sure I'll understand this, someday, but the means to do so escapes me now.
Psmith
Perhaps you didn't want this to turn into a teaching session, and, if so, I totally understand.
Having only the resources given with the LiveCode app, I've looked up some of the terms in the "Dictionary", only to find no entries. I also looked into the "Variables" category at the bottom of the "Code" section and cannot find these terms:
uMoving, sIconList, cycleimages.
I'm sure I'll understand this, someday, but the means to do so escapes me now.
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
One of the best ways to support my own learning is to try and help others learn too. Hopefully I've done this right and it's "teaching" not "patronising".
sIconList is a variable declared in the button, at the top, outside any handlers kept inside the button. This means that it is a "script local" variable and the value it contains is available in the local context to all the handlers in the buttons script. This is in contrast with a variable declared as a global variable which, as you might expect, is available globally to all handlers in all open stacks. It also is different from a variable declared locally to an individual handler - each of the handlers in the button script may declare their own "transient"/"temporary"/"volatile"/"unpreserved" variables which are only available in the context of the handler in which they are defined. You may often see the convention used to prefix variable names with "t" or "s" or "g" to indicate their context.
cycleImages is my own handler that I created for the purposes of this sampler stack. A "routine"/"module"/"command" defined in the button, so it is available only within that part of the message path. In other words, another object in the card or stack would not have direct access to the handler via the message path, they would have to specifically call the handler with a "send" or "dispatch" command (not that there would be any reason to for a handler such as this).
uMoving is a custom property I defined. Think of it as a variable attached to an object. In this context it is a flag set or unset to determine whether the button is moving or not moving, and control the animation accordingly. If there were no test to check for the move having finished, then the ant would still wave its legs about without actually walking anywhere.
So, what happened is, I set up 4 images to use for the animation. I couldn't be bothered to make any more "frames" than two, so there are actually just two pairs of identical images, which is just the fault of laziness on my part, not because there is a technical reason. The image ids for those "frames" were then put in the list defined as the script local variable "sIconsList".
The mouseEnter message is sent through the message path whenever the mouse pointer enters an object. Unless it is trapped and "handled" then that "message" will carry on up the message path from the target object, to parent groups to the parent card to the parent substack/mainstack and finally the engine. (OK, front and backscripts may intercept a message too but... we're trying to learn rather than overload.) So we have a "handler" in the button (the target which generated the mouseEnter event message we want to deal with) that catches the message, so it didn't need to travel very far up the message path. After having caught it, we could "pass mouseEnter" and allow the message to carry on up the message path to be dealt with by other handlers further up. There is no reason to in this case, the handler is specific to the target button in question. So, "on" catching that message in the button, we will now deal with it by:
Making a check to see if the "test" button is hilited or not. If it is not hilited, then we will do nothing. That's so you can actually grab the button to check its properties and edit, etc.
Assuming the "test" hilite is true, then we react to the mouseEnter message by giving it something to do. We make some random coordinates to give as a destination. We set the uMoving flag to tell the cycleImages handler that movement is in progress so we will want to change the icon images for the button in sequence, and send off a message to "me" (in the context of the button) to look for a handler to process the "cycleImages" message (or command). While that is going off and doing its thing we tell the button to go and shift itself from the current location to the random coordinates we gave it. We do this "without waiting" so that when the button reaches the specified destination there will be another message "moveStopped" sent by the target object ("me" - the button we're animating).
Meanwhile the cycleImages command has received its message and begins to work. First it checks whether the uMoving property (of "me" - we're working entirely within the context of the button here) has been set to true. If not then we don't do anything, as there is no movement, so we don't want any animation. But since we set the uMoving flag in the mouseEnter handler, we deal with the image cycling. First we check the position in the sIconList variable of the icon which is in use at the moment, and pick the next position (wrapped around with the mod calculation) and use the value in that item as the icon id for the button's next frame.
Finally, we send off another message "to me" to be checked in 200 milliseconds (or appropriate frame interval) which will again be "caught" by "me" to test whether animation should cycle through to the next image.
Meanwhile, the engine is busy doing its thing, moving the button along the route to the destination coordinates. When it gets to that location, because the button was moved "without waiting" the engine triggers a "moveStopped" message. We've caught that message in the button too, before it goes anywhere else up the message path. When that event fires, it simply sets the uMoving flag to false. Thus, when the next cycleImages message comes round it will not do anything - so no new icon will be set, and no more cycleImages messages will be sent. (Until the mouseEnter event triggers the handler to start it all off again anyway.)
Now, all these handlers have been set down low in the message path, specifically in the button. You could easily want to have lots of similar buttons with movement or other things going on. So it's entirely possible to make the one handler available to the different objects by putting it higher up the message path. For instance in the card script. Then any mouseEnter event for that button, or another button, or a field or other control would generate a message. Assuming we took this set of handlers out of the buttons script and put it in the card, when we did a mouseEnter on the button, it would not be handled in the context of "me" (the button) alone. Without being trapped in that context, the message would pass up, through any group scripts that didn't handle it, and reach the card. Once reaching the handler in the card script, the message could be dealt with and we could adapt the handler to check if "the target" was a button, ignore any non-button targets, do some further tests on buttons to see if they are the sort you want to animate and so on, making the code more generic. In that situation though, rather than using the inheritance of the message path to generalise the code, you would probably find it best to use "behaviors", in which the context of "me" is virtualised to each child control of the behavior. But it's probably long overdue that I shut up now.
sIconList is a variable declared in the button, at the top, outside any handlers kept inside the button. This means that it is a "script local" variable and the value it contains is available in the local context to all the handlers in the buttons script. This is in contrast with a variable declared as a global variable which, as you might expect, is available globally to all handlers in all open stacks. It also is different from a variable declared locally to an individual handler - each of the handlers in the button script may declare their own "transient"/"temporary"/"volatile"/"unpreserved" variables which are only available in the context of the handler in which they are defined. You may often see the convention used to prefix variable names with "t" or "s" or "g" to indicate their context.
cycleImages is my own handler that I created for the purposes of this sampler stack. A "routine"/"module"/"command" defined in the button, so it is available only within that part of the message path. In other words, another object in the card or stack would not have direct access to the handler via the message path, they would have to specifically call the handler with a "send" or "dispatch" command (not that there would be any reason to for a handler such as this).
uMoving is a custom property I defined. Think of it as a variable attached to an object. In this context it is a flag set or unset to determine whether the button is moving or not moving, and control the animation accordingly. If there were no test to check for the move having finished, then the ant would still wave its legs about without actually walking anywhere.
So, what happened is, I set up 4 images to use for the animation. I couldn't be bothered to make any more "frames" than two, so there are actually just two pairs of identical images, which is just the fault of laziness on my part, not because there is a technical reason. The image ids for those "frames" were then put in the list defined as the script local variable "sIconsList".
The mouseEnter message is sent through the message path whenever the mouse pointer enters an object. Unless it is trapped and "handled" then that "message" will carry on up the message path from the target object, to parent groups to the parent card to the parent substack/mainstack and finally the engine. (OK, front and backscripts may intercept a message too but... we're trying to learn rather than overload.) So we have a "handler" in the button (the target which generated the mouseEnter event message we want to deal with) that catches the message, so it didn't need to travel very far up the message path. After having caught it, we could "pass mouseEnter" and allow the message to carry on up the message path to be dealt with by other handlers further up. There is no reason to in this case, the handler is specific to the target button in question. So, "on" catching that message in the button, we will now deal with it by:
Making a check to see if the "test" button is hilited or not. If it is not hilited, then we will do nothing. That's so you can actually grab the button to check its properties and edit, etc.
Assuming the "test" hilite is true, then we react to the mouseEnter message by giving it something to do. We make some random coordinates to give as a destination. We set the uMoving flag to tell the cycleImages handler that movement is in progress so we will want to change the icon images for the button in sequence, and send off a message to "me" (in the context of the button) to look for a handler to process the "cycleImages" message (or command). While that is going off and doing its thing we tell the button to go and shift itself from the current location to the random coordinates we gave it. We do this "without waiting" so that when the button reaches the specified destination there will be another message "moveStopped" sent by the target object ("me" - the button we're animating).
Meanwhile the cycleImages command has received its message and begins to work. First it checks whether the uMoving property (of "me" - we're working entirely within the context of the button here) has been set to true. If not then we don't do anything, as there is no movement, so we don't want any animation. But since we set the uMoving flag in the mouseEnter handler, we deal with the image cycling. First we check the position in the sIconList variable of the icon which is in use at the moment, and pick the next position (wrapped around with the mod calculation) and use the value in that item as the icon id for the button's next frame.
Finally, we send off another message "to me" to be checked in 200 milliseconds (or appropriate frame interval) which will again be "caught" by "me" to test whether animation should cycle through to the next image.
Meanwhile, the engine is busy doing its thing, moving the button along the route to the destination coordinates. When it gets to that location, because the button was moved "without waiting" the engine triggers a "moveStopped" message. We've caught that message in the button too, before it goes anywhere else up the message path. When that event fires, it simply sets the uMoving flag to false. Thus, when the next cycleImages message comes round it will not do anything - so no new icon will be set, and no more cycleImages messages will be sent. (Until the mouseEnter event triggers the handler to start it all off again anyway.)
Now, all these handlers have been set down low in the message path, specifically in the button. You could easily want to have lots of similar buttons with movement or other things going on. So it's entirely possible to make the one handler available to the different objects by putting it higher up the message path. For instance in the card script. Then any mouseEnter event for that button, or another button, or a field or other control would generate a message. Assuming we took this set of handlers out of the buttons script and put it in the card, when we did a mouseEnter on the button, it would not be handled in the context of "me" (the button) alone. Without being trapped in that context, the message would pass up, through any group scripts that didn't handle it, and reach the card. Once reaching the handler in the card script, the message could be dealt with and we could adapt the handler to check if "the target" was a button, ignore any non-button targets, do some further tests on buttons to see if they are the sort you want to animate and so on, making the code more generic. In that situation though, rather than using the inheritance of the message path to generalise the code, you would probably find it best to use "behaviors", in which the context of "me" is virtualised to each child control of the behavior. But it's probably long overdue that I shut up now.
Re: Substituting Animated Buttons or Sprites for Default Buttons
Thanks for the detailed description. There are, however, a few things I don't understand:
What is a "flag"? (my guess that it is a boolean something that is either on or off). Nobody has explained this term yet.
When was "sIconList" declared, where is the declaration? Where is it listed in any kind of inspector as being a local variable?
When was "uMoving" defined or set? I can't find anything within the code, itself, that defines it.
There are others, but these, alone, are enough to derail my train of thought.
Psmith
What is a "flag"? (my guess that it is a boolean something that is either on or off). Nobody has explained this term yet.
When was "sIconList" declared, where is the declaration? Where is it listed in any kind of inspector as being a local variable?
When was "uMoving" defined or set? I can't find anything within the code, itself, that defines it.
There are others, but these, alone, are enough to derail my train of thought.
Psmith
Re: Substituting Animated Buttons or Sprites for Default Buttons
A flag is, as you said, just a parlance for a boolean setting, true or false. It's got nothing to do with Livecode syntax, just a value to check the state "is the test active or not?" or "is the button moving?"
local sIconList = "1003,1004,1013,1014" was the declaration for the (script) local variable, in the button script, at the top, outside any handlers. It might not be a good idea to try with this particular stack because of the movement and timing behaviours, but if you were to set a breakpoint and step through the code in the debugger, the variables shown in the list at the bottom would identify sIconList. If you were debugging another handler in another script, you wouldn't see the reference to sIconList, since it is only available locally to the button script in which it is declared.
The line "set the uMoving of me to true" between the coordinate definition and the command to send the cycleImages message is where the uMoving property was first set, on "me" (the button, in this case). If you (turn off the test active checkbox) inspect the button, on the custom properties pane you will now see the uMoving property. It's value would subsequently have been set to false, in the handler that caught the moveStopped message.
The uMoving is a "custom property". I can put anything in there I like, and attach it to a control. I can use it to store a file that's read in from somewhere else and save it along with the stack for writing out again later. Or a simple boolean flag, like this. There is no "definition" of the property, because it is user defined, as a "custom" property. (You will therefore frequently see a convention for naming custom properties with either a "u" prefix (user defined) or "c" prefix (custom).
local sIconList = "1003,1004,1013,1014" was the declaration for the (script) local variable, in the button script, at the top, outside any handlers. It might not be a good idea to try with this particular stack because of the movement and timing behaviours, but if you were to set a breakpoint and step through the code in the debugger, the variables shown in the list at the bottom would identify sIconList. If you were debugging another handler in another script, you wouldn't see the reference to sIconList, since it is only available locally to the button script in which it is declared.
The line "set the uMoving of me to true" between the coordinate definition and the command to send the cycleImages message is where the uMoving property was first set, on "me" (the button, in this case). If you (turn off the test active checkbox) inspect the button, on the custom properties pane you will now see the uMoving property. It's value would subsequently have been set to false, in the handler that caught the moveStopped message.
The uMoving is a "custom property". I can put anything in there I like, and attach it to a control. I can use it to store a file that's read in from somewhere else and save it along with the stack for writing out again later. Or a simple boolean flag, like this. There is no "definition" of the property, because it is user defined, as a "custom" property. (You will therefore frequently see a convention for naming custom properties with either a "u" prefix (user defined) or "c" prefix (custom).
Re: Substituting Animated Buttons or Sprites for Default Buttons
I didn't see the "Local sIconList . . . " variable declaration because it was off the screen when I opened the script. Shux.
So, now I understand the prefix "c" for "custom" and "u" for "user" (defined), now, where does the prefix "s" come in (as in "s"IconList).
And let me interject something here: if LiveCode is designed to be the ultimate in "English-like" coding or the ultimate in understandable coding, why do all the programs I see written in LiveCode look mostly like jibberish?
Honestly, there is not that much difference between traditional LiveCode "code" and the "dot.syntax" code that prevails everywhere else. I will say that LiveCode simplifies syntax, but does not really optimize it.
How much time, in the code execution cycle, would adding a few more English words make? Instead of writing a bunch of comments, why not make your entire program a comment, of sorts?
It really seems like those who take to programming, (like a fish to water), are those who love acronyms and abbreviations of all sorts. I'm even amazed at how un-intuitive graphic programming languages like Scratch or Google's adaptation, App Inventor, really are. In other words, they are not either graphical or intuitive - or, at least, not very.
I'm still waiting for someone, somewhere to see the light regarding what makes a truly "popular", intuitive programming "language". It's still not a pleasant experience, regardless of the poison you choose.
Psmith
So, now I understand the prefix "c" for "custom" and "u" for "user" (defined), now, where does the prefix "s" come in (as in "s"IconList).
And let me interject something here: if LiveCode is designed to be the ultimate in "English-like" coding or the ultimate in understandable coding, why do all the programs I see written in LiveCode look mostly like jibberish?
Honestly, there is not that much difference between traditional LiveCode "code" and the "dot.syntax" code that prevails everywhere else. I will say that LiveCode simplifies syntax, but does not really optimize it.
How much time, in the code execution cycle, would adding a few more English words make? Instead of writing a bunch of comments, why not make your entire program a comment, of sorts?
It really seems like those who take to programming, (like a fish to water), are those who love acronyms and abbreviations of all sorts. I'm even amazed at how un-intuitive graphic programming languages like Scratch or Google's adaptation, App Inventor, really are. In other words, they are not either graphical or intuitive - or, at least, not very.
I'm still waiting for someone, somewhere to see the light regarding what makes a truly "popular", intuitive programming "language". It's still not a pleasant experience, regardless of the poison you choose.
Psmith
-
- VIP Livecode Opensource Backer
- Posts: 10048
- Joined: Sat Apr 08, 2006 7:05 am
- Contact:
Re: Substituting Animated Buttons or Sprites for Default Buttons
I don't know about others, but I use the "s" prefix to denote script-local variables.Psmith wrote:So, now I understand the prefix "c" for "custom" and "u" for "user" (defined), now, where does the prefix "s" come in (as in "s"IconList).
More on Hungarian-lite notation here:
http://www.fourthworld.com/embassy/arti ... style.html
Code is written for two audiences: a machine too stupid to count past 1, and an unknown person who may be maintaining the code years down the road. Both audiences have special needs.And let me interject something here: if LiveCode is designed to be the ultimate in "English-like" coding or the ultimate in understandable coding, why do all the programs I see written in LiveCode look mostly like jibberish?
The machine needs explicit instructions with minimal ambiguity, and while LiveCode does a generally good job of providing this with reasonably human-readable text there are things like array notation which are difficult to express by any means other than the geeky-looking tMyArray[someKey].
The maintainer of the code is a much more difficult audience. Countless volumes have been written about code style over the decades, and more will surely come. There are endless recommendations for both style and architecture, and each year brings new insights which refine these even further.
But two things have remained fairly constant over the decades people have been programming: human cognitive process, and the fact that code is more frequently skimmed than truly read.
Readability is useful when telling a story, and indeed code is a form of story-telling. But since code is far more frequently skimmed than read, it can help to use conventions which immediately draw attention visually to the nature and origin of a token. Prefixing constants with "k" and globals with "g" is a long-held practice across many languages for this reason, and the widespread use of additional prefixes and suffixes to denote other types of tokens provides similar additional benefit; when you see pRect down in the middle of a long handler and you've adopted a style which uses "p" to denote parameters, you know exactly where it came from without having to scroll back up to the top of the handler to find out.
Charles Simonyi, formerly one of the lead engineers at Microsoft, popularized this sort of naming convention so broadly that its name is a reference to his origin: it's commonly called Hungarian notation. Since he worked in lower-level languages he took it further to include notation for data types, but in LiveCode (and many other high-level languages) we have very few types and variables can be easily converted from one type to another, so the more common set of conventions you'll find in LiveCode and similar languages is what I call "Hungarian-lite" since it's a much simpler form.
Sure, it makes code less readable in terms of English. But for maintaining and enhancing non-trivial code bases over many years, it provides rapid at-a-glance understanding of token use for all the reasons described in industry literature over the years.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
Re: Substituting Animated Buttons or Sprites for Default Buttons
Thank you Richard.
But, to me, it seems like the shoe is still being put on the wrong foot - and the horse is riding behind the cart - (and other colloquial sayings).
The machine we designed to be a servant is still being treated like the master. We are being forced to twist our minds around the "requirements" of the machine. Those who get into these contortions at early ages, and persist throughout adulthood must surely suffer from doing so.
Also, the discipline of giving a machine instructions to perform useful service is still one that only a select few, (relatively speaking), have the tenacity or inclination to pursue for any length of time. And the reason for this, I think, is that stated above. Perhaps, also, those who have managed these contorted exercises over the length of their career are not eager to abandon their tenure.
Psmith
But, to me, it seems like the shoe is still being put on the wrong foot - and the horse is riding behind the cart - (and other colloquial sayings).
The machine we designed to be a servant is still being treated like the master. We are being forced to twist our minds around the "requirements" of the machine. Those who get into these contortions at early ages, and persist throughout adulthood must surely suffer from doing so.
Also, the discipline of giving a machine instructions to perform useful service is still one that only a select few, (relatively speaking), have the tenacity or inclination to pursue for any length of time. And the reason for this, I think, is that stated above. Perhaps, also, those who have managed these contorted exercises over the length of their career are not eager to abandon their tenure.
Psmith