SteamVR/Environments/Scripting/Linking Lua with Javascript
This tutorial shows how to communicate between the server-side VScript (Lua) and the client-side Panorama (Javascript) scripting systems.
Linking Lua with Javascript
In some cases, you will need the Lua script to communicate with Javascript. In Arcade Toss, there’s a scoreboard that displays things like the scores, the timer and instructions. This is done using Custom Nettables in conjunction with Panorama, Javascript, and CSS.
You’ll first need to place a point_clientui_world_panel in your map. This the panel used for the Arcade Toss scoreboard:
Create an XML file in your
\content\steamtours_addons\arcade_roll\panorama\layout\custom_destination
directory.
There is one called arcade_toss_scoreboard.xml
in the example. Your dialog_layout_name
will need a path to this file similar to this:
file://{resources}/layout/custom_destination/arcade_toss_scoreboard.xml
The scoreboard is pretty large, so the panel_dpi
is lower than a typical panel and the ignore_input
should be off.
Your XML file will include a styles (.CSS) file and a Javascript (.JS) file:
<styles>
<include src="file://{resources}/styles/custom_destination/arcade_toss_scoreboard.css" />
</styles>
<scripts>
<include src="file://{resources}/scripts/custom_destination/arcade_toss_scoreboard.js" />
</scripts>
You’ll need a custom_net_tables.txt
file in your_addon\scripts
directory.
You can change the key in the table, but the Arcade Toss table contains “hoops_score”:
{
custom_net_tables =
[
"hoops_score",
]
}
Then, you’ll need global variables created in your addon_game_mode.lua
file with a SetTableValue
function:
-- Team Scoring
_G.Scores = { red_score = 0, blue_score = 0 }
_G.Timer = 121
CustomNetTables:SetTableValue( "hoops_score", "scores", _G.Scores );
Your key name in the custom_net_tables.txt
file should match the string in the SetTableValue
function.
The next entry in the table is “scores” which is the data that the Javascript will use and the final entry “_G.Scores” is the global variable table that stores the scores of both teams.
In Arcade Toss, the UpdateScoreboard
function is called whenever a red ball goes into a red target hole or a blue ball goes into a blue target hole.
--------------------------------------------------------------------------------
-- Scoreboard
--------------------------------------------------------------------------------
function UpdateScoreboard(team, value)
--Team (Red = 1, Blue = 2)
if _G.Timer > 0 then
if team == 1 then
if bIsRedTeamBehindTheLine == true then
EmitGlobalSound("red_score_point")
red_total = red_total + value
_G.Scores = { red_score = red_total, blue_score = blue_total }
CustomNetTables:SetTableValue( "hoops_score", "scores", _G.Scores );
else
EmitGlobalSound("score_error")
end
else
if bIsBlueTeamBehindTheLine == true then
EmitGlobalSound("blue_score_point")
blue_total = blue_total + value
_G.Scores = { red_score = red_total, blue_score = blue_total }
CustomNetTables:SetTableValue( "hoops_score", "scores", _G.Scores );
else
EmitGlobalSound("score_error")
end
end
end
end
The SetTableValue
function is called if the team is not across the line. This sends the data referenced to the Javascript.
You’ll need to create a Javascript file in your
\content\steamtours_addons\your_addon\panorama\scripts\custom_destination\
directory.
There’s a listener in the arcade_toss_scoreboard.js
file that listens for the data from the custom_net_table.txt
file:
(function()
{
CustomNetTables.SubscribeNetTableListener( "hoops_score", OnGameStateChanged );
UpdateScoreboard();
GameEvents.Subscribe( "countdown", UpdateTimer );
GameEvents.Subscribe( "pregame_countdown", PreGameTimer );
})();
It also provides the functions in the Javascript file to execute when the data is received OnGameStateChanged
and UpdateScoreboard
.
These two functions set up the scores to be displayed:
function OnGameStateChanged( table, key, data )
{
$.Msg( "Table '", table, "' changed: '", key, "' = ", data );
UpdateScoreboard();
}
function UpdateScoreboard()
{
var scores = CustomNetTables.GetTableValue( "hoops_score", "scores" );
var blueScore = CustomNetTables.GetTableValue( "hoops_score", "blue_score" );
$("#RedScore").text = scores.red_score;
$("#BlueScore").text = scores.blue_score;
}
This takes the data sent from the Lua file and breaks them down into Team Red’s score (known simply as “scores”) and Team Blue’s score (“blue_score”).
Then, the function puts them into the Panorama display. The #RedScore
and #BlueScore
refer to the ID’s of the panels in the XML file:
<Panel class="Scoreboard">
<Panel class="TeamScore" id="RedScoreGroup">
<Panel class="TeamNameWrapper" id="RedWrapper">
<Label class="TeamName" text="#ArcadeToss_ScoreRed" />
</Panel>
<Panel class="RedScoreWrapper">
<Label class="Score" id="RedScore" text="999" />
</Panel>
</Panel>
<Panel class="CenterPanel">
<Image id="DestinationsTitle" src="file://{resources}/images/destinations_title_large.png" />
<Label id="Title" text="#ArcadeToss_ScoreTitle" />
<Label id="PreGameTimer" text="#ArcadeToss_ScoreStart" />
<Label id="Timer" text="--:--" />
</Panel>
<Panel class="TeamScore" id="BlueScoreGroup">
<Panel class="TeamNameWrapper" id="BlueWrapper">
<Label class="TeamName" text="#ArcadeToss_ScoreBlue" />
</Panel>
<Panel class="BlueScoreWrapper">
<Label class="Score" id="BlueScore" text="999" />
</Panel>
</Panel>
</Panel>
The data from the Lua file will then get placed into these score panels.
The CSS file placed in \content\steamtours_addons\arcade_roll\panorama\styles\custom_destination
will contain the styles used for the panels in the XML file.