Bolt-Scripts / UI_Scaler

2 stars 3 forks source link

Small tips #1

Open praydog opened 2 years ago

praydog commented 2 years ago

First of all, good work. These are some things I noticed in the code that can be slightly improved.

You don't need to this:

local newScale = ValueType.new(vec3Type);
vecCtor:call(newScale, tmpScale, tmpScale, 1.0);
set_Scale:call(tp, newScale);

You can just do:

set_Scale:call(tp, Vector4f.new(newScale, tmpScale, tmpScale, 1.0))

And apply the same idea to the rest of the areas you're manually constructing a via.vec3 (which is a vector4 in size, with a w).

The same thing can be applied to via.Size, instead of:

local scaleWidth = baseWidth / tmpScale;
sizeCtor:call(newSize, scaleWidth, scaleWidth * aspect);
set_ScreenSize:call(view, newSize); 

You can do:

set_ScreenSize:call(view, Vector2f.new(scaleWidth, scaleWidth * aspect))

These work because the size and internal data matches the structures for via.vec3 and via.Size.

Instead of calling ToString to check type names which creates a managed string and just allocates more memory, you can do: behaviour:get_type_definition():get_full_name()

And finally, to only operate on GUI elements that are currently rendering without list iteration, you can use:

-- the element component passed in here is the `via.gui.GUI` for the game object
-- you can get the via.gui.View from that
re.on_pre_gui_draw_element(function(element, context)
    local gui_game_object = element:call("get_GameObject")
    local components = gui_game_object:call("get_Components"):get_elements()

    -- ALTERNATIVELY, you can compare the game object name with gui_game_object:call("get_Name")
    -- they will be in the form of "I_GlaGauge", "hud_Sharpness", etc.
    for i, component in ipairs(components) do
        local component_name = component:get_type_definition():get_full_name()
        local element_data = elementDatas[component_name]

        if element_data ~= nil then
            -- do your UI rescaling shenanigans
        end
    end
end)

I use this in the VR code for MHRise to move all of the rendering UI elements in front of the camera.

Bolt-Scripts commented 2 years ago

Ah, thanks for the tips oh wise bestower of knowledge. I knew there must be a better way as I vaguely think I saw you mention it before but I couldn't find it quickly. behaviour:get_type_definition():get_full_name() is definitely a hot tip. I was worried a bit about garbage collection because I'm unsure of how all this is handled behind the scenes with all the fuckery going on. Creating new vectors and apparently strings every frame doesn't sound good. And I've gotten reports of people getting framedrops now so not sure but seems possibly related. Ideally I wouldn't even deal with the strings, but I don't know how to create a lookup table for types in lua, like being able to use a dictionary would be great but idk.

I did see the gui_draw_element thing only after finding the gui list stuff, but everything it returned was a via.gui.GUI and I didn't really know what to make of it and already had the other thing working anyway. But would it really be any more performant or anything like is there a reason to do that instead? It feels like ultimately the same work will need to be done anyway. Just wanna be lazy yknow.

Bolt-Scripts commented 2 years ago

Oh also, the thing with using the vector add and subtract operations was out of necessity, like for some reason if i tried to read the values after calling get_Position it just was always garbage no matter how I tried. Dunno if I was doing something wrong but sheesh. But for some reason it was fine if I just never read the values and instead called the vector functions. Maybe you could enlighten me

Bolt-Scripts commented 2 years ago

Also Also V2: in your example and in the docs for Vector4f it says w comes first, but it only works as expected with this when using an x,y,z,w format. Not sure about it but worth noting.

praydog commented 2 years ago

In regards to the GUI callback, from what I could tell, it is much less work than doing the list iteration like you're doing. From a quick glance, that list contained GUI elements that weren't being rendered, and contained a lot of them. It will effectively do the same thing, but only for the elements currently being rendered, cutting down on comparisons and function calls.

Also Also V2: in your example and in the docs for Vector4f it says w comes first, but it only works as expected with this when using an x,y,z,w format. Not sure about it but worth noting.

Oops. I must've gotten Vector4f and Quaternion mixed up. It only comes first in Quaternion. I'll fix that.

Perhaps a profiling system for method calls would be helpful? To monitor whether you're calling game methods that are exceeding a certain elapsed time. Since these methods are out of our control, and we don't really know what they're doing under the hood.

Bolt-Scripts commented 2 years ago

Mmm, yeahh, probably makes sense to use the on_gui thing, but at the end of the day it's probably pinching pennies. A profiler could be good but I doubt that's much of an issue in this case since not really calling many of those, at least none that would be heavy. And with stuttering it feels like its just random which wouldn't make sense if it was just a slow function. But we'll see.

Bolt-Scripts commented 2 years ago

Would it be possible to get information on GC stuff? At least like notifications when a big GC happens to see if its correlated to these stutters