Bug? Transitions on Logic Blocks not active at start up?

Q&A about the latest versions
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Thu Aug 27, 2020 11:31 pm

Neal wrote:
Thu Aug 27, 2020 4:29 pm
Assumptions -- I have been doing this for a long time. My first lines of code were written over 4 decades ago. The hardest thing to learn about computers and coding is to not make assumptions. If your code depends on items happening in a specific order, and you do not have control over those items, you need to check that they occurred as you wanted. If you want your banner to show after the tiles are loaded, you need to check the status of "Loading tiles". Now the documentation does assume some basic knowledge of webpage design and coding. That level of knowledge is needed for the level of control and customization that it gives you.
Well, I'll bow to your superior knowledge. I only first starting coding 38 years ago and that was in assembler where I could design my own State Engines with Macros before moving on to C and C++. Now that's an inefficient language. :roll: So I guess you win that round. :D But if I check for a condition and the result of that condition being True leads to an action that happens every single other time - both the change from a predefined Default value to a New one (Tick) AND a Transition (Also Tick) - then in my opinion, it's bad coding when it's not consistent. I'd certainly have got a chewing out if I wrote something like that before I was in a position to chew someone else out who wrote something like that.

We'll have to agree to disagree on how default values should work. If they do not exist unless a failure condition causes them to be created: bad coding dependency and worse coding environment that relies on that.

To not have a default value in place to compare with the updated value that is the very reason for needing the Transition that you specifically request to blend between those two values on the first time the test is checked because "Oops, I haven't put the original Default in there yet, so I can't compare it to the New one, so I can't do a Transition" is bad code.

If it's relying on the test failing once on the IF THEN part, so the ELSE can initialise the default value (maybe even have to instantiate the whole object, if they do those in Java (Edit: Javascript)?), so NEXT time around the loop there is something there to compare with and then be able to do the requested Transition: bad code. When a simply delay changes the action of the same code: bad code.

There should no need to make up excuses for extenuating circumstances of what should be loading when and why and having to wait for a browser to do its thing. Either it does what it does every time, or throws an error message to tell us why it fails. It doesn't just shrug and move on.

Well, it can if it want things to stay quiet for users who don't need to care 99.9% of the time, :) but maybe under the hood there could be a log we could check? I think Hopki said there will be some debugging tools in V7.

Looks like I'm going to have to invest in some Java (Edit: Javascript) script books and learn the language. :lol:
Last edited by Branigan on Fri Aug 28, 2020 9:24 am, edited 2 times in total.
Neal
Posts: 166
Joined: Thu Dec 12, 2013 11:14 am

Fri Aug 28, 2020 12:44 am

We can agree to disagree, so long as everyone else thinks I'm right :D :D :D

For debugging javascript, I just use the tools in the browsers. I don't know how much you have used them, but for javascript and HTML they work really well.

Just in case it's not a typo, the output is in javascript, not java. Similar names but very different languages. You might also want to check out this site: https://www.w3schools.com/js/default.asp. It will save you the cost of the books. Javascript isn't very hard. If you can program in C, you can learn javascript. Just remember, javascript isn't linear like C.
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Fri Aug 28, 2020 9:22 am

Neal wrote:
Fri Aug 28, 2020 12:44 am
We can agree to disagree, so long as everyone else thinks I'm right :D :D :D

For debugging javascript, I just use the tools in the browsers. I don't know how much you have used them, but for javascript and HTML they work really well.

Just in case it's not a typo, the output is in javascript, not java. Similar names but very different languages. You might also want to check out this site: https://www.w3schools.com/js/default.asp. It will save you the cost of the books. Javascript isn't very hard. If you can program in C, you can learn javascript. Just remember, javascript isn't linear like C.
Yeah, was a typo. :oops: Realised it just as I turned the PC off but bed beckoned. You beat me to being able to fix it quietly this morning. ;)

Was dreaming of Pseudo code half the night, so here it is.

It's in no known language and is just an overview of some of the things you might do and test for.

But, basically if changing a variable is tied to a transition, I want the transition to occur. No ifs, ands, ors or buts.

---------
init num_Default_Pos_X ; // For holding the Default position
init num_New_Pos_X ; // For holding where the text will move to later

init flag_Transition_required ; // For Transition Tick box
init flag_Transition_active ; // For running state of Transition
init flag_Transition_complete ; // For "all done" state.

init var_Text_Pos_X ; // Only 'active' variable here and where the text is going to be drawn

---

;// Assume nothing, set all defaults (could also set when 'init'ing, but this is explicit)

set num_Default_Pos_X = -400 ; // Start off screen
set num_New_Pos_X = 0 ; // Slide onto the screen later

set var_Text_Pos_X = num_Default_Pos_X ; // Set Text position Variable to the Default offscreen value (Don't do this? Expect weirdness... ;) )
set flag_Transition_required = True ; // Yes, we want transitions
set flag_Transition_active = False ; // It's not running yet
set flag_Transition_complete = False ; // It's not finished yet


;// Something to check the Trigger has fired
function Logic_test_function()
Check something, return True/False ; // Check the thing we want, say if it's True.
end_function

;// Something to do the work.
function Do_Transition_function()
Do_transition_over_time, Set flag_Transition_complete = True/False ; // do the Transition loop, set Flag=True when finished
end_function

---

Loop start

IF Logic_test_function() = True AND flag_Transition_complete = False ; // Has it triggered for the first time?
THEN flag_Transition_active = True ; // Our test came back true, so trigger the Transition
ELSE do nothing

IF flag_Transition_active = True AND flag_Transition_complete = False ; // are we (still) doing the transition?
THEN Do_Transition_function(num_Default_Pos_X, num_New_Pos_X) ; // go from old to new position over time
ELSE do nothing

IF flag_Transition_complete = True AND flag_Transition_active = True ; // Transition all done?
THEN var_Text_Pos_X = num_New_Pos_X, flag_Transition_active = False ; // update position in variable, turn off Transition and we're outta here...
ELSE do nothing

Loop end ; // go round and round until dizzy
Neal
Posts: 166
Joined: Thu Dec 12, 2013 11:14 am

Fri Aug 28, 2020 5:36 pm

I'm getting a whiff of C language code, I may have to report that post :wink:

The big difference I'm seeing is that your code starts by defining a start location. In the skin, you are using a switch statement to define the starting point. That logic block for the banner position is a switch statement. As in C, the code that gets executed when all the cases are false is the default case.

You always want the banner to be created at -400,-10. So there is no need to use a switch block for the position. What you want is an action, something that occurs after the banner is created.

On your skin, delete the position logic block for the banner. Also, delete timer 1.
Under actions, add this:
Source: Config Loaded (This is the trigger to start the move)
Action: Change Element Position (This is what you want it to do)
Parameters: x=400, Y=0 (This is how far you want it to move)
Transition Time: 0.50 seconds (How fast you want it to move)
Target: _self (Do the action on the banner)

You will still need timer 2, That is what moves the banner offscreen after 4 seconds.
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Fri Aug 28, 2020 11:13 pm

Neal wrote:
Fri Aug 28, 2020 5:36 pm
In the skin, you are using a switch statement to define the starting point. That logic block for the banner position is a switch statement.
Whaaaa? I'm really not. :? It's like I'm showing you a picture of a cat and you say "cute doggy" :shock:

The psuedo code doesn't really follow the skin, it's just an alternative look at how the order of things could be triggered, i.e. the Transition as the driving force and it updating the Position when complete instead of the Position Updater code calling the Transition code. Six-of-one, or Half-a-dozen of the other, kinda thing.

The Default position is offscreen. See the Yellow line? It's because 'View>Show Off Canvas Elements' is On. It has to move from there when the trigger is set. If you remove the Logic Block: it will stay there because: Default Position. You'll note there are no blanks in the top right circle, as you might do with URLs etc. for which images to load under various circumstances/platforms/screen sizes. So it really ought to have that value in there before it does anything else and not rely on the False condition in the Logic Block to fill it in, which you seem to be implying? :?

When it moves from that Default Position (and please show when, where and why that Initial value isn't already in place in your interpretation of how it works), it is supposed to Transition, because it's Enabled (I'm really beginning to think it just plain forgets to check that flag under some circumstances). Every other time you do this, including if you change "Has Touch" to "Loading" (and the False to True), it will Transition. It's just that "Loading" does not work consistently, because the time it takes to become True is variable depending on the amount of data to load and it can trigger at the wrong time and then you get no transition. On mobiles, where I've thinned the data down considerably, mainly.

You can remove the timers entirely and just have the single text object and nothing else and try to get it to slide on by Triggering a Transition in any way, shape or form you like. It's what I started with, then wrapped the rest around it. Some ways work, some don't. They all change the X position when Triggered. :)
.
what_you_talkin_abaht.jpg
what_you_talkin_abaht.jpg (453.34 KiB) Viewed 368 times
Neal
Posts: 166
Joined: Thu Dec 12, 2013 11:14 am

Sat Aug 29, 2020 2:01 am

Branigan wrote:
Fri Aug 28, 2020 11:13 pm
Neal wrote:
Fri Aug 28, 2020 5:36 pm
In the skin, you are using a switch statement to define the starting point. That logic block for the banner position is a switch statement.
Whaaaa? I'm really not. :? It's like I'm showing you a picture of a cat and you say "cute doggy" :shock:
The wasn't a guess or an opinion, that logic block is in skin.js as an if-else statement. I simplified the code a little, but this is the basics:

Code: Select all

if ((player.getVariableValue('var_hs_move_trigger') == 1) {
	me._text_banner.style.left='0px';
} else {
       me._text_banner.style.left='-400px';
}
The logic blocks are coded into the skin script as

if (condition 1 true) {
do something
} else if (condition 2 true)
do something
} else if (condition 3 true)
do something
:
:
:
else {
do the default
}

Functionally that is the equivalent of a switch statement.

You might want it to be a cat, you think it should be a cat, but I'm looking at the front of the photo and tell you it's a dog.
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Sat Sep 05, 2020 1:08 pm

Neal wrote:
Sat Aug 29, 2020 2:01 am
The wasn't a guess or an opinion, that logic block is in skin.js as an if-else statement. I simplified the code a little, but this is the basics:

Code: Select all

if ((player.getVariableValue('var_hs_move_trigger') == 1) {
	me._text_banner.style.left='0px';
} else {
       me._text_banner.style.left='-400px';
}
Functionally that is the equivalent of a switch statement.
You might want it to be a cat, you think it should be a cat, but I'm looking at the front of the photo and tell you it's a dog.
Sorry, been a bit busy, but back to this again.

So, what you're saying is: it's just bad code that hasn't populated the default value before running the code for the first time and only does so when it falls through to the Else, so the Transition value has nothing to do. That's what I feared it was doing. Yuk.

Why it works if you use "Loading" as the trigger, must be because it falls through on the very first pass when Loading is still False then fills in the ELSE value, according to your code example above.

Thereafter, as the 'Player Loader' gets all its ducks in a row and is ready to rock'n'roll: 'Loading' changes to True, it now has the default value already in place and the Transition does its thing. Except when different timing on some platforms is such that it's ready too early and still fails... :(

Rather than arguing sideways about what to call what it does and excusing it for 'reasons', are you completely happy that it does that? I'm just not. Especially as it's not described like that anywhere in the docs; rather the opposite.

https://ggnome.com/doc/skin-logic/

"The Default Value is whatever was set in the properties panel of that property." Note: 'was', so that came first, the logic block came later and did its thing.

The line "✭ For logic blocks that have two values (size, position, and scale), one value can can be left empty to use the parameter’s default value." is also relevant.

It clearly implies that the Default value is right there for it to use and is stored elsewhere (even if only at Compile time and is inserted in the ELSE for you), if you miss it out in the Logic Block, so to only 'notice it' when the ELSE condition makes it a requirement to fill it in again and then not bother with any Transition (on the other fields, which will/could have changed) is still just: sloppy code which gives a bad, and platform-dependant, result.

It might be interesting to see when that value is inserted and compile it both with and without one parameter filled in to see if it generates different code.

If this behaviour was considered at the design stage and is actually done on purpose to prevent/avoid a problem, I'd like to see an explanation as to what that is and why this method is considered better.

It just seems accidental, considering you can get it to do what you want by fudging things with timers as Triggers where they MUST fail and are False on the first tick, the ELSE fills in the Default value, then they are True on the second Tick and the Transition occurs when the IF condition is met.

I prefer to use my screwdrivers like a normal person and not to hold them by the shaft and hammer in the screws. :)

I'll guess the only way to really find out is: does this behaviour (quietly) change in future releases.... ;)
Neal
Posts: 166
Joined: Thu Dec 12, 2013 11:14 am

Tue Sep 08, 2020 7:32 am

Just returned back from spending a little time with the family, so just saw your response.

OK, let's follow your logic.

First, you want it to create the DOM object using the default values. In your case, offscreen.
At the exact same time as the above, you want it to check the logic block for where it should move to next. (This is a major logic flaw because it assumes that the future value of the logic block can be predetermined and that it will occur)
It is then to transition to that location over a period of time (slide onscreen).

So let us see how that order causes other things to fail.
First, positioning or sizing objects by screen size. Based on the above, the menus. etc, would be first created at the default location/size. The logic blocked would then be checked for the correct location and size for that screen. The objects would then move to those locations and be resized. Clearly not something that is generally wanted.
Or, displaying objects based on the browser interface. The default objects would first flash on the screen only to be replaced by the correct objects after the logic blocked was checked. Clearly not the desired effect and generally considered very annoying and a side of poor programming.

So to avoid both of the above, there needs to be something in place to determine the correct starting position. The logic block is that something. So the correct logic for all the above, including yours, is to first set the initial position using the logic block when necessary. Then to use an event or timer to trigger the movement to another position under a specific set of conditions. That is standard Javascript. Your logic fails because you are trying to set both the initial and the final positions of the text banner at the same time.

So let's look at the loading trigger in the logic block and how it works here. Loading is true while the panorama is loading and false after the loading is complete. Note, that the loading of the panorama is different than the loading of the tiles used to construct the images. The change of the Loading event from true to false will cause the logic block to be re-evaluated. If this results in a different position for the object, the object will transaction to the new location. The loading trigger occurs before the loading tiles trigger, however, for a fast connection, the difference might not be noticeable. For a slow connection, the tile might still be loading after the loading trigger. This would cause the text banner to start scrolling onscreen while the tiles are still loading.

I am going to assume that you want the text banner to move onscreen after the tiles are finished loading.
First I would create the object offscreen. Since there is only one possible initial position, a logic block isn't needed. Just set the position at -400,0.
Then I would use the action to state what I wanted to happen once the tiles are loaded. In this case, I want the text block to start moving onscreen and for a timmer to start.
One action changes the text banners position 400px to the right across 3 seconds. The second starts the timer with a value of 5 seconds. The timer will then deactivate 2 seconds after the text banner finished moving.
The timer has one action. When it is done (deactivate), move the text banner 400px to the left across 3 seconds.
The end result, on all devices, on all connections, is that after the tiles are loaded, the banner starts moving onscreen. That takes 3 seconds. It then stays put for 2 seconds. Then it moves offscreen over the next 3 seconds.

You asked me if I am happy with how it works, the answer is yes I am. The reason is that it works as it should work. It follows standard Javascript logic and is event triggered. I haven't been making excuses, I have been trying to teach you the why. The reason that you are not getting the results you want or expect is that 1) you don't understand how the logic blocks work, 2) you don't understand how the triggers work and 3) your logic is faulty.
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Fri Oct 09, 2020 1:06 pm

Neal wrote:
Tue Sep 08, 2020 7:32 am

You asked me if I am happy with how it works, the answer is yes I am. The reason is that it works as it should work. It follows standard Javascript logic and is event triggered. I haven't been making excuses, I have been trying to teach you the why. The reason that you are not getting the results you want or expect is that 1) you don't understand how the logic blocks work, 2) you don't understand how the triggers work and 3) your logic is faulty.
Well, I've been off gadding about Europe, but now back in quarantine. I will say: holiday resorts are immeasurably improved by the lack of other people spoiling the view and clogging up the gloriously sunny beaches and with just enough shops and cafes open to be able to get a good table quickly and with near-instant service.

I'll be honest and say I only skimmed most of the above (so don't feel you need to read any of this, either) because I could see you were misunderstanding the problem and my expectations and telling me that bad coding practice is in fact good coding practice. :D

When you write well structured code you use the Init() function (or the equivalent in JS), or you get results like this. It's not like this hasn't been thought of literally decades ago and the solution made available. If this is not accepted practice in Javascript then it's just asking for trouble. More likely, someone just forgot to use the language properly and/or thought they were being 'clever/efficient'.

If Javascript runs in a non-linear way, then even more reason to be completely paranoid about which variables are (even tangentially) dependent on others. This isn't rocket science and when I wrote code that ran under interupt (music drivers etc. and pre-multi-tasking days) that interacted with the code it was interupting, everything needed to know that nothing had changed since the last time it checked, or it would check again. Best test was a handle-based memory manager that would defragment and optimise memory blocks under interupt without the underlying program noticing - or falling over. You could actually have interupts within interupts if their tasks over-ran their 'tick time' and you had to be able to unwrap back out of it trying to disappear up its own backside without anything failing, or the stack getting corrupted. Fun times... :)

There is evidence of other 'efficiencies' being used when you put the Player or a Skin through a Javascript code checker, when it generates lots of "Ooh, well; technically it might work, but you really shouldn't be doing it like that any more..." messages, or 'Deprecated coding practices' warnings.

There is nothing in the documentation that says logic blocks should work the way you say they do and this particular example breaks when you change the timing of other variables being populated. It has dependencies that are completely opaque to the user and which produces different results on different platforms with no change in input from the user. That's just wrong, however nicely the bow that's tied on top of it.

The fix is pretty simple though and the overhead is so negligible that it probably couldn't be measured: Init() the variables with their Default values before running though the logic blocks. That's it. Fixed, finito and no more problems. :wink:

Worse case scenario is: you Init() a variable and some unspecified time later the logic block condition check falls through and the Else() sets it to the same value again. Whoop-de-doo :lol:
Neal
Posts: 166
Joined: Thu Dec 12, 2013 11:14 am

Fri Oct 09, 2020 4:41 pm

It's been a long time since I went to Europe. The last time I was there I went to see the Berlin wall .... and it wasn't in a museum. I need to get back one of these days.

As for the code being inefficient and having some items that are deprecated, you are correct. It still uses "var" instead of the current practice of using "let" and "const". There are likely several more examples. "Best Practices" change depending on the checker used, with many contradicting what another says. As for being inefficient, that is typical of computer-generated code. I suspect the skin size could be cut down by 30% by combining and optimizing the code. Would that change download time or speed, not to any significant amount.

A simple question, do you realize that the creation of the element object in the JS code is not the same as the insertion of the element into the DOM?
Branigan
Posts: 221
Joined: Tue May 19, 2020 3:43 pm

Mon Oct 12, 2020 4:16 pm

Neal wrote:
Fri Oct 09, 2020 4:41 pm
... As for being inefficient, that is typical of computer-generated code. I suspect the skin size could be cut down by 30% by combining and optimizing the code. Would that change download time or speed, not to any significant amount.
Actually, minifying Skin.js shrinks it by ~20% (varies) and I felt it was snappier as a result - on mobile mainly - then I also manually massage the file sizes of the tiles - with variable compressions to get them all fairly uniform. Really needed something more agressive though that will go through and really shorten variable names down to a nub, and maybe pre-compile it with a table of offsets to variables and routines at the start - if JS supported such a thing. But...at some point I added something to a skin that now generates errors in the minifier, so it won't do it any more. Actually more than one refuses - hence I found all the other error messages while trying.
Neal wrote:
Fri Oct 09, 2020 4:41 pm
A simple question, do you realize that the creation of the element object in the JS code is not the same as the insertion of the element into the DOM?
Nope, and don't care to find out. Just like the 'excuse' that we got that wobbly Hotspots was because they were some kind of DOM element - but those that are 3D Distorted aren't subject to the same problems and don't wobble (just skip about like flea-ridden kangaroos if you add timers to them) - I just want to be able to produce panoramas that look professional and don't promote questions like "Why is it doing that?" When every other panoramic product out there has stable hotspots that don't jiggle and much better transformations. Not much to ask, is it?

Annoyingly, looks like I'll have to upgrade from Lite to Pro for a biggish project, when I've got my eyes on 3D Vista; which seems to have none of these problems - plays video overlays in the correct colour space - and also allows self-hosting (main draw for me), but haven't got time to get up to speed on that and it's more expensive.
Last edited by Branigan on Mon Oct 12, 2020 4:58 pm, edited 1 time in total.
User avatar
Hopki
Gnome
Posts: 10748
Joined: Thu Jan 10, 2008 3:16 pm
Location: Layer de la Haye, Essex UK
Contact:

Mon Oct 12, 2020 9:12 pm

This post has run its course and is now closed.
Hopki
Garden Gnome Software Support
If you send an e-mail to support please send a link to the forum post for reference.
support@ggnome.com
https://ggnome.com/wiki/documentation/
Locked