Correct Syntax for a Few Things - Question

Posts: 100
Hi guys,

Making the first major updates to our theme in quite some time. I have a script that returns the live gap, PIT, OUT, etc, normal things.

I'd now like to incorporate manufacturer logos in place of this data on occasion via a button press. Could you explain the syntax for how I could achieve pressing a button, then loading an image in place of text in the relevant label? I imagine I'd have to return " " in the label, to clear it, and then turn on another label with the manufacturer image loaded over it. Once I click another button, I'd like the script to return to giving gap data.

Previously I had just loaded another ticker in an adjacent column, which worked nicely but was a little clunky looking. Thank you for your help!

Kyle Heyer
Posts: 785
I'm assuming these labels are in a ticker? Because that complicates matters a little bit.

In principle (ignoring the ticker aspect for now), the logic is pretty simple. I would simply build two labels on top of each other, one with the text and one with the image. Then in a script you can switch between the two by making one label invisible and the other visible. Probably something very close to this:
var labelText = subwidget.Labels.Find("TextLabel");
var labelImg = subwidget.Labels.Find("ImageLabel");

// Switch from text to image:
labelText.IsVisible = false;
labelImg.IsVisible = true;


For a ticker, you will need to do this for every copy of the labels in the ticker. For your understand, the ticker works by making several copies of the "template" subwidget (which you select in the properties). If there are 26 drivers, it will create 26 copies of that template. These copies are used until the ticker decides it needs to rebuild the copies (which happens sometimes, e.g. when number of drivers change). Simply changing the template subwidget after the fact will not impact the copies already made.

So to change all labels in a ticker you'll have to loop through all copies of the subwidgets and change them. And at the same time, I would also change the template itself, so that in the event that the copies are rebuilt, they are rebuilt using the current desired state.

The copies of the template are available from the ticker via the 'RepeatedSubWidgets' property. You can loop over those and change the properties, and then also change them for the template itself.

There is one tricky complication: the labels in a copy of the template do not get a name, so you cannot use the standard "subwidget.Find" method to get them. You can instead just get them by index but you'd need to find out the index first, and take care that it does not change (e.g. if you add or move around labels in the template subwidget).

Assuming the labels are the first and second (index 0 and 1), this should work I think:

using System;
using ATVO.ThemesSDK;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Scripting.DotNET;

namespace Scripts
{
public class ChangeTickerImg : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
var widget = item.Theme.Widgets.Find("Widget1");

foreach (var subwidget in widget.Ticker.RepeatedSubWidgets)
{
ChangeLabels(subwidget);
}
ChangeLabels(widget.Ticker.TemplateSubWidget);

return null;
}

private void ChangeLabels(SubWidget subwidget)
{
var labelText = subwidget.Labels[0];
var labelImg = subwidget.Labels[1];

labelText.IsVisible = false;
labelImg.IsVisible = true;
}
}
}
Posts: 100
Thanks Nick! This will give me a good direction to go. How do I make a button in the controls trigger the swap in the script? Just by using Action type "Script" with the "Execute" effect?



**Edit** I discovered that the way above is the correct way to trigger the label change. I have it working nicely - except all the labels sit on top of each other until I click the button to run the script. I'll make another script to initialize the ticker to show only the label I want on startup.

**Edit 2**

It seems every time the gap data updates, it sets itself visible again. I assume this is because my button runs the script once, and then it returns back to the default status of everything being visible when the ticker runs through again.




Appreciate the help as always!

Kyle
Edited (2 times)
Posts: 785
It may be the 'Dynamic' property messing with the visibility when the text goes from empty to some value. Instead of making it invisible perhaps you can just set the text of the label to empty ("") to hide it, and back to the default "{0:0}" (or whatever formatting you want) to show it again.
Posts: 100
Nick Thissen wrote:
It may be the 'Dynamic' property messing with the visibility when the text goes from empty to some value. Instead of making it invisible perhaps you can just set the text of the label to empty ("") to hide it, and back to the default "{0:0}" (or whatever formatting you want) to show it again.


This pretty much worked, for some reason it doesn't work with something entirely empty, but as long as there's some form of character in there it works fine. Perhaps I could set the color to transparent and that would achieve the same effect. I'll give that a go. Great progress - thanks!!!
Posts: 100
Got it working exactly how I envisioned. This is a tad messier since it was more than just car manufacturer I wanted to show, so I have to turn off more than just one label.

Thank you so much!


using System;
using ATVO.ThemesSDK;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Scripting.DotNET;
using System.Drawing;
using System.Windows.Media;

namespace Scripts
{
public class Manufacturer : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
var widget = item.Theme.Widgets.Find("Top TickerB");
var widget2 = item.Theme.Widgets.Find("Ticker");
var widget3 = item.Theme.Widgets.Find("Ticker - Scrolling");

foreach (var subwidget in widget.Ticker.RepeatedSubWidgets)
{
ChangeLabels(subwidget);
}

foreach (var subwidget in widget2.Ticker.RepeatedSubWidgets)
{
ChangeLabels(subwidget);
}

foreach (var subwidget in widget3.Ticker.RepeatedSubWidgets)
{
ChangeLabels(subwidget);
}
ChangeLabels(widget.Ticker.TemplateSubWidget);
ChangeLabels(widget2.Ticker.TemplateSubWidget);
ChangeLabels(widget3.Ticker.TemplateSubWidget);

return null;
}

private void ChangeLabels(SubWidget subwidget)
{
Color OFF = Color.FromArgb(0, 0, 0, 0);
Color ON = Color.FromArgb(255, 255, 255, 255);

var labelText = subwidget.Labels[2];
var labelImg = subwidget.Labels[6];
var labelStart = subwidget.Labels[7];

labelText.Text = ".";
labelText.Font.FontColor = OFF;

labelImg.Text = "{0:0}";
labelImg.Font.FontColor = ON;

labelStart.Text = ".";
labelStart.Font.FontColor = OFF;
}
}
}
Posts: 287
Hi,
I really don't know how to use scripts correctly but I try ...
I want to check if the session is RACE or not to mask a the label wich inform the number of lap in race.
This label is in Widget with dataset SESSION STATE.
I try to adapt a script I see here but it must be use with other dataset ...

using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Entity;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Controls;
using ATVO.ThemeEditor.Scripting.DotNET;
using ATVO.ThemesSDK.Data.Enums;
using ATVO.ThemesSDK.Data.Results;
namespace Scripts
{
public class Script : IScript
{
public object Execute(ThemeContentItem item, object value,string parameter, ISimulation sim)
{
// Bind to "entitysessionresult_obj" to get the IEntitySessionResult as the value

// Cast to IEntitySessionResult type
IEntitySessionResult sessionResult = (IEntitySessionResult) sessionResult;


var type = result.Session.Type;

if (type == SessionType.Race)

return "Lap";
else
return "";
}

}

}


I use data converter, but I can't set entitysessionresult_obj in this data set.

Posts: 785
If you use 'sessionstate' dataset, then the databindings you can use are different. In that case you can bind directly to "sessiontype" binding, which returns "Practice", "Qualification", "Warmup" or "Race".

If you bind to that, your "value" in the script will be a string and you can directly compare if it equals Race:
if (value == "Race")
Posts: 287
Thanks, I do (only 3 hours to understand .... :(  )
With that code it is ok
using System;
using ATVO.ThemesSDK;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Scripting.DotNET;

namespace Scripts
{
public class Scripts1 : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
// Get databinding value as string:
string sessionname = value.ToString();

if (sessionname == "Practice")
return "";

if (sessionname == "Race")
return "Lap";

else
return value;


}
}
}

I put value for else to check what hapen !

Now I try do the same with a non text label : currentlap
I look what I have to change ...
Edited (1 time)
Posts: 287
Finaly I decide to add a SubWidget only to do a masquing image. One to mask area and other totally clear to see information when sessiontype = race.
Edited (1 time)
Posts: 287
I make some test and I do a little script which show fast lap or delta depend if sessiontype is race or not.
Now I want to find how if it is a Multiclass to change the label I use to indicate CLASS, to change text to "Multiclass" .
I don't find that !
Posts: 785
You can count the number of classes in the session via the sim object:
var numClasses = sim.Session.ClassManager.Classes.Count;


Then simply check if numClasses > 1 (multiclass) or not (single class).
Posts: 287
Thanks it is ok and I can change what I want. I try to find on GitHub some variable, but it is not so easy ;)
if I want to say give the good name else, I don't find the fonction ... Class.Name or other ...

Other things, I do a DROPDOWN to select wich standing class to show. When we choose class with no cars it's freeze the computer for long time. So I try to imput a condition that if I got 3 classes I can show only class 1/2 & 3 and not class4.
I don't see how Do a Condition if a label has a specific value !
Posts: 287
Just to understand, in GitHub it is old system ?
The complet name to use are in dll at C:\Program Files (x86)\Appgineer.in\ATVO Launcher\bin ?
Posts: 785
The Github is relatively old yes, but there are only additions which are not yet in the Github, and no other changes.
We will try to update it soon.

There is also a nuget package which is referenced automatically if you open the scripts in VS Code (via right-click on Scripts - Open in VS Code). This is also not fully up to date currently, but we'll update that soon.

Why are you looking for the DLL?
Posts: 287
As you can see I'm not programer, but I try, so First I want to fing correct name of "variable".

For exemple in GitHub I saw the name Class and you give me Classes. So I only try to undernstand.

I use Visual Studio, but yes, no all name :)
Edited (1 time)
Posts: 287
Hi Nick, i saw a post where you describe how to change color of delta time if it under a value. But i can't find it again !! Could you give me the path ?
Posts: 287
Nick Thissen wrote:
You can count the number of classes in the session via the sim object:
var numClasses = sim.Session.ClassManager.Classes.Count;


Then simply check if numClasses > 1 (multiclass) or not (single class).

Ok with that, I get the number of classes and I use it.

But if I want to check this car is in the first class, nomaly I have to check Classes[0] , yes ?

Something like If (Classes[0] == true) ?
Posts: 785
There is Car.Class which returns IClass object. I think the Id property is the index from 0 to however many classes there are. Or perhaps you need the Order. Just check in the Data Explorer what gives the value you're looking for.

if (result.Entity.Car.Class.Id == 0) ...
Posts: 287
Name on Data Explorer is classorder
0 is the first ....
Posts: 785
Looks like you need Order and not Id indeed. Then I think Order goes from 0 - 6 (or however many classes), and Id is probably the ClassId as defined by iRacing.

You can see the "classorder" binding in the Data Explorer, but you can also use "Expand object" on an "..._object" type to see what properties are available from a script. For example, expanding the "entitysessionresult_object" you can find Entity and then Car and then Class and then you can see the properties:

Posts: 287
So in script I have to check
if (result.Entity.Car.Class.Order ==0)  ?
Edited (1 time)
Posts: 785
Yes, that will be 'true' if the car is in the fastest class.

Note that the order of classes (by how fast they are) is defined by iRacing, unless you use custom classes.
Edited (1 time)
Posts: 287
Yes, I try with 3 classes and it is ok. (this is in relation with override color question ;) )
Edited (1 time)
Posts: 785
Are you just trying to replace the font color of a class? You can do that with the custom classes setting in ATVO, no need to use overrides for this.