Forum Discussion

daria's avatar
daria
Visitor
10 years ago

Utility functions in Scene Graph SDK

Hi!

I want to add a set of utility functions available for scenes components (say, some formatting functions that should be used by different classes). It's silly, but I don't understand how to do this. Code from source directory is not visible for scenes, and classes in components seems to be not suitable for this.
What's the recommended way for it?

10 Replies

  • in your component xml you can include scripts as such:
    <script type="text/brightscript" uri="pkg:/source/utils.brs" />

    this also helps separate your code from your xml
  • "floatleftinteractive" wrote:
    in your component xml you can include scripts as such:
    <script type="text/brightscript" uri="pkg:/source/utils.brs" />

    What happens when you need the same function in >1 component?
  • any functions defined in the included script will only work within the scope of that component so it can get included in multiple components as long as there are no function name conflicts.
  • "floatleftinteractive" wrote:
    any functions defined in the included script will only work within the scope of that component so it can get included in multiple components as long as there are no function name conflicts.

    Wait, you are confusing me!
    Functions either are global (and therefore fn name conflicts can occur and should be actively avoided) or they are local (and therefore there'd be no problem re-defining in other components). Right?

    What you say seems contradictory, that a fn is both global (cannot re-use the name in another component) and not-global (cannot call it from another).

    If there are name collisions (resulting in error) because same fn was defined in 2 distinct components, that means it's the same interpreter instance that sees all functions, which means fn defined in component A can be used in component B. Now, "m" context is another story. you won't get A's data when calling from B - but let's not digress, let's assume pure utility fn like "toString()" or "isString()" etc


    PS. we are talking only about the render thread only. Tasks and main threads - those be a different ball of wax (tar).
  • to avoid using functions within an inline <script> tag you can include a separate file for a component's sub init(). For shared or common functions like utility functions you can include another <script> tag and these functions will work within the scope of that component as well as any other component that includes it.

    Example
    source/utils/string.brs has:
    function tokenize() as object

    component A includes its component script, at pkg:/components/component_a.brs and includes a tag with pkg:/source/utils/string.brs
    component B includes its own script, pkg:/components/component_b.brs and pkg:/source/utils/string.brs

    both components can use tokenize() within their own scope. At runtime scripts from components/ do not conflict with each other while scripts in source/ would.
  • Ah, so perhaps <script uri="..."/> are treated like #import, i.e. compiled only once.

    There is one thing that i don't understand though, since you mentioned sub init() - how come there is no error message on that? When both component A and B each define inline their init() - those two definitions should clash, just like two inlined tokenize() would have?

    PS. curiously, TFM insists URI must to point to components/ -
    "<script>" wrote:


    uri | optional | A string specifying an external file that contains script code associated with the component. This file must be located in the components directory of the application, and have the .brs extension for BrightScript code.
    I'll take a guess doco is wrong on that...
  • yes if you were to import/include component a's script into b's it would conflict on sub init().

    We've had no issues using includes from source/ and this may prove as a useful way of integrating non-scenegraph libraries into something like a Task component.
  • What is the impact of multiple components including the same utils file over and over.
    We have a rowlist that has over 100 items in it that each include the utils. Is this going to kill the UI thread over time?
  • "Tyler Smith" wrote:
    What is the impact of multiple components including the same utils file over and over.
    We have a rowlist that has over 100 items in it that each include the utils. Is this going to kill the UI thread over time?

    That is a great question!
    Theoretically if done well, there should be practically no impact (B/S functions are constant/literals, they carry no lexical context with them so can take memory only once and be shared between all components/threads/interpreters; the price could be as low as dictionary entry name: *fnBody). In practice i suspect they are duplicated...

    Hey, you are in good position to test that - why don't you? Spin lots and lots instances of the same component until the player crashes, periodically print to console so you can see approx. how many instances it took to run out of memory. Do the same experiment WITH and WITHOUT including some massive B/S utility library in that component. And let's take a gander at the two numbers. Chances are, we'll learn something...