HeroEngine Forums

HeroEngine Support => GUI Creation => Topic started by: JoshHalls on Dec 21, 10, 03:29:16 PM

Title: [Resolved] GUI Performance + Layers + Possible Fix (well adjustment)
Post by: JoshHalls on Dec 21, 10, 03:29:16 PM
We have a gui with a list of skills (104 I believe) and each one has some text, a progress bar (combination of a few controls) and some wrappers such as _spacers, and a collapseable panel control we put together.  A lot of controls once you add it all up.  Some animation here and there (cleaned that up some as it eats up cycles), but the big issue seems to be the gui layer placement.  Here is a short profile out.

Code: [Select]
14:56:49: SCRIPT[RPCharacterSpendDNAWindowClassMethods]:  500 millis (71.15%) in script GUIControlClassMethods function MOVETOGUILAYER executed 1430 times
14:56:49: SCRIPT[RPCharacterSpendDNAWindowClassMethods]:   19 millis (2.71%) in script GUIControlClassMethods function ONCONTROLBUILD executed 1320 times
14:56:49: SCRIPT[RPCharacterSpendDNAWindowClassMethods]:    1 millis (0.23%) in script RPProgressBarClassMethods function ONCONTROLBUILD executed 104 times
14:56:49: SCRIPT[RPCharacterSpendDNAWindowClassMethods]:    0 millis (0.01%) in script RPCollapsablePanelClassMethods function ONCONTROLBUILD executed 6 times
14:56:49: SCRIPT[RPCharacterSpendDNAWindowClassMethods]:total: 0.521012604 seconds (74.11%)
14:56:49: **** 304581 : 0.814585 sec for Probe HeroScript Exec ***

While the total time and the probe message are a bit off, you get the general idea. 

You can cut this time in half by a simple change (this is in the HeroEngine core GuiControlClassMethods, hopefully you will add this as I don't want to override all of my controls)

In findMyInitialLayers() find the following lines

Code: [Select]
    if not($GUI._isGUILayerValid(myLayerString)) // only those specifically included are allowed at all
      scriptError("Invalid GUI Layer [" + myLayerString + "] on control: " + me.name + " (" + me + ") layer(" + me.layer + ")")
    .

Change it to this

Code: [Select]
    if myLayerString != "default" and not($GUI._isGUILayerValid(myLayerString)) // only those specifically included are allowed at all
      scriptError("Invalid GUI Layer [" + myLayerString + "] on control: " + me.name + " (" + me + ") layer(" + me.layer + ")")
    .

The reason for this change is it will try to build a list with 10 items 1280 times or so.  Most controls are not going to have a layer and thus getting out of this check early should save a bit of time (controls that are blank on the layer value are then set to default in the code, you could override this earlier just to return $GUI._getGUIMasterLayer() if it is blank as that what it does ultimately after a few checks).

Thoughts?



Title: Re: GUI Performance + Layers + Possible Fix (well adjustment)
Post by: HE-JAY on Dec 22, 10, 10:25:27 AM
This looks like a perfectly valid change at first glance.  However, the $GUI._isGUILayerValid(...) method does offer a hook for game-specific code to latch onto and - if for some reason there is a desire by a licensee to invalidate the default layer - this would become impossible with the proposed change.

I would suggest providing your own HE_isGUILayerValid(...) method and escape it early when it detects the "default" string.  Though this won't give you all of your cycles back, it should be far more efficient than running through that findString and searching the valid layers list.

Let me know what kind of boost you get from doing this and - if it fails to give you back a significant chunk of cycles back - we can revisit the issue.

Thanks! (:
Title: Re: GUI Performance + Layers + Possible Fix (well adjustment)
Post by: JoshHalls on Dec 22, 10, 12:30:18 PM
If there a quick way of doing that that doesn't involve adding that to 20 different controls or modifying the core HE files?
Title: Re: GUI Performance + Layers + Possible Fix (well adjustment)
Post by: HE-JAY on Dec 22, 10, 01:06:43 PM
Absolutely.  HE_isGUILayerValid(...) is called from the method _isGUILayerValid(...) on the $GUI system node.  All you have to do is:

Then, every time $GUI._isGUILayerValid(...) is called, your custom method HE_isGUILayerValid(...) will handle the call.  Any custom rules you want to add can be stored here, such as the exclusion of "default" from the test.

Your custom method which would always flag the default layer as valid might look something like this:
Code: [Select]
method HE_isGUILayerValid(layerName copies String) as Boolean
  if layerName = "default"
    return true
  .
  if findString(layerName, "_popupLayer") > 0
    layerName = replaceString(layerName, "_popupLayer", "")
  .
  var layers = me._validGUILayersList()
  foreach layer in layers
    if layer == layerName
      return true
    .
  .
  return false
.

With the added snippet being:
Code: [Select]
method HE_isGUILayerValid(layerName copies String) as Boolean
  if layerName = "default"
    return true
  .
...
Title: Re: GUI Performance + Layers + Possible Fix (well adjustment)
Post by: HE-CHRISTOPHER on Jan 03, 11, 04:55:31 PM

Extremely complex dynamically generated UIs often benefit from supressing layout during construction only resuming once all controls have been instantiated.

Code: [Select]
external function SuppressLayout(GUInode as NodeRef)

external function ResumeLayout(GUInode as NodeRef, forceLayout as Boolean)
Title: Re: GUI Performance + Layers + Possible Fix (well adjustment)
Post by: JoshHalls on Jan 04, 11, 01:20:51 PM
Thanks Chris, I will look into adding that to see if it helps.