Skip to content

Commit 2941991

Browse files
andybakmikeage
andauthored
Plugin scripting (#699)
* Fix an oversight * Always supply a canvas to SelectAll and Invert * SelectionWidget axis locks should be based on selection canvas not active canvas * Update __autocomplete.lua * Do something sensible if canvas is null * Docs and autocomplete generation fixes * Fix examples scripts and update docs [CI BUILD] * API docs update [CI BUILD] * fix autocomplete syntax for return values * Some example script fixes [CI BUILD] * Hide pseudo-private method _SubdivideSegments * Lerping for transforms * (Untested) settings for brush position, rotation and pressure * Update lua autocomplete * dotnet-format * Allow position and rotation constructors to accept vector3 and rotation instances * Allow symmetry and tool plugins to return lua arrays * Simplify the example * dotnet-format * make inverse a property. Use "Position" for example snapshot code * Small docs tweak * dotnet format * Operator overloading for lua wrappers [CI BUILD] * dotnet-format * Fix some broken scripts * Remove some buggy scripts * Fix typo [CI BUILD] * Fix camera path not respecting scene/canvas transforms * Remove clockwise and anticlockwise properties of rotation - they were just confusing * Update example scripts now anti and clockwise properties are removed * Some extra overloads for API methods * Update autocomplete * Fix default argument for svg draw path. Fix svg object case in lua docs * Allow identity to be used as a default parameter in other places * Fix spiral example plugin [CI BUILD] * dotnet-format * Update UnityXRInputAction.cs * Fixes for API docs and autocomplete [CI BUILD] * [CI BUILD] * dotnet-format * Excessive amount of try/catch to pin down a bug on android builds * Quick debug test to see which panels are loading on Quest * More debug info and a small refactor * Use our fork of moonsharp * Revert "Quick debug test to see which panels are loading on Quest" This reverts commit f5f258a. * Log to the Controller Console to avoid messing with logcat * More debug code * Revert "More debug code" This reverts commit 501ce63. * Change stripping level * [CI BUILD] * Remove the logging now code stripping issue is fixed. * [CI BUILD] * Use a regular select multiple for background scripts * Fix http API for environments (broken by localization) * Fix some shader compilation errors [CI BUILD] * Fix Leaky Pen on Quest * Make StandardSingleSided more consistent with StandardDoubleSided [CI BUILD] * Fix another shader error [CI BUILD] * [CI BUILD] * [CI BUILD] * Typo crept in last merge * [CI BUILD] * Switch to "Parameters.foo" syntax in plugins * Small refactor for efficiency * small autocomplete update * Tool should be a top level class to appear in autocomplete * Fix Tool autocomplete docs not generating * hard code Moonsharp builtins into autocomplete. Fix type for Tool.vector * Make autocomplete happy * Shader fix * Gridfollow rotation fix. Better defaults [CI BUILD] * Support a shorter shorthand for generating a T transform * Fix symmetry widget transform api. Don't store an undo * Example script fix * Update __autocomplete.lua [CI BUILD] * Docs and example script tweaks * dotnet-format * Round slider values in the widget * Fix symmetryhueshift include for recent changes [CI BUILD] * Revert "Round slider values in the widget" This reverts commit 9724c6f. * Maintain float value internally but send int out to subscribers [CI BUILD] * Example script fixes [CI BUILD] * Fix ducklings * Incremental GC [CI BUILD] * Color widget. Refactor popups to allow popups to open other popups. [CI BUILD] * More script widget types (WIP) * Update scripts to use new widgets [CI BUILD] * Fix paging popup with dynamic items * Update example script to use new widgets. * Fewer items per page to stop overlap with nav buttons * Fix Scripts Panel collider and centering * Bigger script parameter popup [CI BUILD] * Small cosmetic and docs tweaks * Matrix and Vector4 wrappers * API support for getting matrices from multimirror * API docs fix * Register the Vector4 and Matrix types * Return MatrixList * Update __autocomplete.lua * MatrixListWrapper should implement IPathApiWrapper * Handle matrix lists the same as any IPathApiWrapper instance * Register MatrixList * Setters for position, rotation and scale on Matrix wrapper * Setter for MatrixList indexer * Symmetry scripts refactor and fix * Update __autocomplete.lua * Remove some junk comments * Post-merge fix * Setters for indexers * dotnet-format [CI BUILD] * Display image picker icons with correct aspect ratio * Assign image button results correctly [CI BUILD] * Post-merge panel fixes [CI BUILD] * picker popup fixes * picker popup fixes * svg mesh import fix * Image api fixes * Minimal port of text tool - just enough to allow API creation of text objects and save/load support * Add Open Type glyph loader * Update the vector graphic package * Add various text utility methods * formatting * Image extrusion (WIP) * Needed for image extrusion * Fixes for image and text widget changes * "Save as" fixed (overwriting and file extensions) * Http API endpoint for image extrusion (WIP) * Move example usages into the endpoint attribute * Stub for text extrusion. Disable image extrusion for now as it doesn't work. * Remove debug log * Change folder where open type fonts are looked for [CI BUILD] * Refactor and simplify stroke drawing for Lua and Http APIs [CI BUILD] * Endpoint for drawing full SVG docs * API SVG fixes [CI BUILD] * Rename dither param to _Dissolve and ensure it's on all brush shaders * Update example script to use _Dissolve * Post-merge fixes * Post-merge fix * [CI BUILD] * Fix shaders (mostly the dissolve logic) [CI BUILD] * Fix bubblewand dissolve [CI BUILD] * Util to read current git branch * Allow loading of bundled sketches with "tiltbrush://builtin/" prefix * Tweak location and content of profiling summary * [CI BUILD] * Stroke debug command * Fix spelling * Add another fps bucket to profiler * Update Zapbox SDK (#770) Update version hashes * gzip config.vdf before storing as a secret (#771) * Fix speling * Include build string in profile summary. Add a 40fps bucket * Use mult compile flags for scripted shader properties Set keyword when using scripted shader params Fix time override includes * Post-merge package changes * Set the default sdk back to openxr. Assorted unity changes * Fix Ballistic Missile script * Refactor the api interface for controller actions * Better up vector for scripted tool * Scripts panel shouldn't start fixed * Unity being unity * Yet another Rider update * Make the console window a prefab * Basic ram logging for Android [CI BUILD] * ram log font size and bounding box [CI BUILD] * Post-merge fix * Lazy init of Lua stuff * Make sure "New Sketch" cleans up lua stuff properly * Delete test.jpg * Remove commented out update method * Delete .gitkeep * Post-merge fixes * Modified English text for View-only mode (other languages are still needed) * Always replace script placeholders in html even if Lua isn't initialized * Fix a null exception and ignore transform buffers if not initialized * typo * Support enums for list widgets * Fixes for enum picker widget * Incremental GC is rather a necessity with the current plugin implementation * See if this prevents the glitching when CPU load is high [CI BUILD] * Fixes for new sketch with the scripting panel open * Fix scale for scripted tool * Apply jitter to toolscript output * Enable support for snapping when using scripted tools * Add/update example plugins and remove some duds * dotnet-format * more dotnet-format * [CI BUILD] * Use a different material for extruded images * WIP fix svg image handling when extruding * Fix a potential null * Don't spam the log * Update vectorgraphics package (our fork) * Fix typo * Downgrade some errors to warnings * Fix duplicate packages after merge * Post-merge automatic change * [CI BUILD] * Catch occasional null error when initializing * [CI BUILD] * Post-merge changes to main scene * dotnet format * Fix random avatar script * [CI BUILD] --------- Co-authored-by: Mike Miller <[email protected]>
1 parent 313e36e commit 2941991

File tree

618 files changed

+48503
-11558
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

618 files changed

+48503
-11558
lines changed

Assets/Editor/BrushLister.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,15 @@ public static string getBrushRowString(BrushDescriptor brush, bool experimental)
8585
{
8686
manifest = "Experimental";
8787
}
88-
return $"{brush.Description}\t{brush.m_AudioReactive}\t{prefabName}\t{materialName}\t{shaderName}\t{brushScripts}\t{experimental}\t{brush.m_SupersededBy}\t{manifest}";
88+
89+
string semantics = "";
90+
if (brush.m_BrushPrefab != null)
91+
{
92+
var script = brush.m_BrushPrefab.GetComponentInChildren<BaseBrushScript>();
93+
var layout = script.GetVertexLayout(brush);
94+
semantics = $"{layout.texcoord0.semantic}\t{layout.texcoord1.semantic}\t{layout.texcoord2.semantic}";
95+
}
96+
return $"{brush.m_DurableName}\t{brush.m_AudioReactive}\t{prefabName}\t{materialName}\t{shaderName}\t{brushScripts}\t{experimental}\t{brush.m_SupersededBy}\t{manifest}\t{semantics}";
8997
}
9098

9199
public static string sniffBrushScript(BrushDescriptor brush)

Assets/Editor/LuaAssetImporter.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.IO;
2+
using UnityEditor.AssetImporters;
3+
using UnityEngine;
4+
5+
[ScriptedImporter(1, "lua")]
6+
public class LuaAssetImporter : ScriptedImporter
7+
{
8+
// Allow loading of .lua files as TextAssets
9+
public override void OnImportAsset(AssetImportContext ctx)
10+
{
11+
TextAsset subAsset = new TextAsset(File.ReadAllText(ctx.assetPath));
12+
ctx.AddObjectToAsset("text", subAsset);
13+
ctx.SetMainObject(subAsset);
14+
}
15+
}

Assets/ThirdParty/SVGMeshUnity/Runtime/SVGData.cs.meta renamed to Assets/Editor/LuaAssetImporter.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Editor/LuaDocsGenerator.cs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright 2023 The Tilt Brush Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System.Collections.Generic;
16+
using System.IO;
17+
using System.Text;
18+
using MoonSharp.Interpreter;
19+
using UnityEditor;
20+
using UnityEngine;
21+
22+
namespace TiltBrush
23+
{
24+
25+
public class LuaDocsGenerator : Editor
26+
{
27+
[MenuItem("Open Brush/API/Generate Lua Docs")]
28+
static void GenerateDocs()
29+
{
30+
if (!Application.isPlaying)
31+
{
32+
Debug.LogError("You can only run this whilst in Play Mode");
33+
return;
34+
}
35+
36+
Script script = new Script();
37+
38+
// Initializing this list triggers the docs generation via RegisterApiClasses
39+
LuaDocsRegistration.ApiDocClasses = new List<LuaDocsClass>();
40+
LuaManager.Instance.RegisterApiClasses(script);
41+
42+
// List wrappers aren't places in the script's namespace but we do want to register them
43+
// so we can generate docs for them.
44+
LuaDocsRegistration.RegisterForDocs(typeof(CameraPathListApiWrapper), false);
45+
LuaDocsRegistration.RegisterForDocs(typeof(EnvironmentListApiWrapper), false);
46+
LuaDocsRegistration.RegisterForDocs(typeof(GuideListApiWrapper), false);
47+
LuaDocsRegistration.RegisterForDocs(typeof(ImageListApiWrapper), false);
48+
LuaDocsRegistration.RegisterForDocs(typeof(LayerListApiWrapper), false);
49+
LuaDocsRegistration.RegisterForDocs(typeof(ModelListApiWrapper), false);
50+
LuaDocsRegistration.RegisterForDocs(typeof(VideoListApiWrapper), false);
51+
LuaDocsRegistration.RegisterForDocs(typeof(StrokeListApiWrapper), false);
52+
53+
// Manually add some entries that aren't added the standard way
54+
var transformProp = new LuaDocsType { PrimitiveType = LuaDocsPrimitiveType.UserData, CustomTypeName = "Transform" };
55+
var vector3Prop = new LuaDocsType { PrimitiveType = LuaDocsPrimitiveType.UserData, CustomTypeName = "Vector3" };
56+
var rotationProp = new LuaDocsType { PrimitiveType = LuaDocsPrimitiveType.UserData, CustomTypeName = "Rotation" };
57+
var toolApiDocClass = new LuaDocsClass
58+
{
59+
Name = "Tool",
60+
Methods = new List<LuaDocsMethod>(),
61+
EnumValues = new List<LuaDocsEnumValue>(),
62+
Description = "A class to interact with Scripted Tools",
63+
IsTopLevelClass = true,
64+
Properties = new List<LuaDocsProperty>
65+
{
66+
new() {Name=LuaNames.ToolScriptStartPoint, PropertyType = transformProp, Description = "The position and orientation of the point where the trigger was pressed"},
67+
new() {Name=LuaNames.ToolScriptEndPoint, PropertyType = transformProp, Description = "The position and orientation of the point where the trigger was released"},
68+
new() {Name=LuaNames.ToolScriptVector, PropertyType = vector3Prop, Description = "The vector from startPoint to endPoint"},
69+
new() {Name=LuaNames.ToolScriptRotation, PropertyType = rotationProp, Description = "The rotation from startPoint to endPoint"},
70+
}
71+
};
72+
LuaDocsRegistration.ApiDocClasses.Add(toolApiDocClass);
73+
74+
// JSON docs if needed
75+
// var json = JsonConvert.SerializeObject(LuaDocsRegistration.ApiDocClasses, Formatting.Indented);
76+
// File.WriteAllText(Path.Join(docsPath, "docs.json"), json);
77+
78+
// Generate __autocomplete.lua
79+
var autocomplete = new StringBuilder();
80+
autocomplete.Append("---@meta\n\n");
81+
string autocompleteFilePath = Path.Combine("Assets/Resources/LuaModules", "__autocomplete.lua");
82+
foreach (var klass in LuaDocsRegistration.ApiDocClasses)
83+
{
84+
// Only top level classes are included in autocomplete
85+
// This excludes all ListWrapper classes which can't be instantiated directly
86+
// And don't have any useful static members
87+
if (!klass.IsTopLevelClass) continue;
88+
autocomplete.Append(klass.AutocompleteSerialize());
89+
}
90+
91+
// Some hardcoded Moonsharp built-ins
92+
autocomplete.Append(@"
93+
---@class json
94+
json = {}
95+
---@param jsonString string The JSON string to parse
96+
---@return table # A table representing the parsed JSON
97+
function json:parse(jsonString) end
98+
99+
---@param table table The table to serialize to JSON
100+
---@return string # The JSON representation of the table
101+
function json:serialize(table) end
102+
103+
---@return jsonNull # a special value which is a representation of a null in JSON
104+
function json:null() end
105+
106+
---@return bool # true if the value specified is a null read from JSON
107+
function json:isNull() end
108+
");
109+
110+
File.WriteAllText(autocompleteFilePath, autocomplete.ToString());
111+
LuaManager.Instance.CopyLuaModules(); // Update the copy in User docs (also done on app start)
112+
113+
// Generate markdown docs
114+
string docsPath = Path.Join(LuaManager.Instance.UserPluginsPath(), "LuaDocs");
115+
if (!Directory.Exists(docsPath)) Directory.CreateDirectory(docsPath);
116+
foreach (var klass in LuaDocsRegistration.ApiDocClasses)
117+
{
118+
var markDown = klass.MarkdownSerialize();
119+
File.WriteAllText(Path.Join(docsPath, $"{klass.Name.ToLower()}.md"), markDown);
120+
}
121+
122+
// Done
123+
LuaDocsRegistration.ApiDocClasses = null;
124+
Debug.Log($"Finished Generating Lua Docs");
125+
}
126+
}
127+
}

Assets/Editor/LuaDocsGenerator.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright 2023 The Tilt Brush Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Linq;
17+
using MoonSharp.Interpreter;
18+
using UnityEditor;
19+
using UnityEngine;
20+
21+
namespace TiltBrush
22+
{
23+
24+
// Attempts to call all known functions on all scripts.
25+
// Currently lots of false positives because we aren't calling the script as it's usually called.
26+
// But still a useful smoke test for syntax errors and name changes.
27+
public class LuaExampleScriptsTest : Editor
28+
{
29+
public static DynValue CallFunctionIfExists(Script script, string fnName)
30+
{
31+
var fn = script.Globals.Get(fnName).Function;
32+
if (fn != null)
33+
{
34+
try
35+
{
36+
return script.Call(fn);
37+
}
38+
catch (InterpreterException e)
39+
{
40+
string msg = e.DecoratedMessage ?? e.Message;
41+
msg = LuaManager.ReformatLuaError(script, fnName, msg);
42+
Debug.LogError(msg);
43+
}
44+
catch (Exception e)
45+
{
46+
string msg = e.Message;
47+
msg = LuaManager.ReformatLuaError(script, fnName, msg);
48+
Debug.LogError(msg);
49+
}
50+
}
51+
return null;
52+
}
53+
54+
[MenuItem("Open Brush/API/Test Example Scripts")]
55+
static void DoTest()
56+
{
57+
if (!Application.isPlaying)
58+
{
59+
Debug.LogError("You can only run this whilst in Play Mode");
60+
return;
61+
}
62+
63+
var pointerScripts = LuaManager.Instance.Scripts[LuaApiCategory.PointerScript];
64+
var symmetryScripts = LuaManager.Instance.Scripts[LuaApiCategory.SymmetryScript];
65+
var toolScripts = LuaManager.Instance.Scripts[LuaApiCategory.ToolScript];
66+
var backgroundScripts = LuaManager.Instance.Scripts[LuaApiCategory.BackgroundScript];
67+
68+
foreach (var example in pointerScripts)
69+
{
70+
var script = example.Value;
71+
TestAllKnown(script);
72+
}
73+
74+
foreach (var example in symmetryScripts)
75+
{
76+
var script = example.Value;
77+
TestAllKnown(script);
78+
}
79+
80+
foreach (var example in toolScripts)
81+
{
82+
var script = example.Value;
83+
LuaManager.Instance.SetApiProperty(script, $"Tool.{LuaNames.ToolScriptVector}", Vector3.one);
84+
LuaManager.Instance.SetApiProperty(script, $"Tool.{LuaNames.ToolScriptRotation}", Quaternion.LookRotation(Vector3.one));
85+
TestAllKnown(script);
86+
}
87+
88+
foreach (var example in backgroundScripts)
89+
{
90+
var script = example.Value;
91+
TestAllKnown(script);
92+
}
93+
94+
void TestAllKnown(Script script)
95+
{
96+
LuaManager.Instance.InitScript(script);
97+
DynValue result;
98+
result = CallFunctionIfExists(script, LuaNames.Start);
99+
result = CallFunctionIfExists(script, LuaNames.Main);
100+
result = CallFunctionIfExists(script, LuaNames.End);
101+
}
102+
}
103+
}
104+
105+
public class TestSpecificScript : EditorWindow
106+
{
107+
private int selectedIndex = 0;
108+
private string inputText = "";
109+
110+
[MenuItem("Open Brush/API/Test Specific Script")]
111+
static void Init()
112+
{
113+
if (!Application.isPlaying)
114+
{
115+
Debug.LogError("You can only run this whilst in Play Mode");
116+
return;
117+
}
118+
TestSpecificScript window = (TestSpecificScript)GetWindow(typeof(TestSpecificScript));
119+
window.Show();
120+
}
121+
122+
void OnGUI()
123+
{
124+
if (!Application.isPlaying) return;
125+
126+
EditorGUILayout.BeginVertical();
127+
128+
string[] scriptNames = LuaManager.Instance.GetScriptNames(LuaApiCategory.ToolScript).ToArray();
129+
selectedIndex = EditorGUILayout.Popup("Dropdown", selectedIndex, scriptNames);
130+
131+
if (GUILayout.Button("Submit"))
132+
{
133+
SubmitDropDownValue(scriptNames[selectedIndex]);
134+
}
135+
136+
inputText = EditorGUILayout.TextField("Input Text", inputText);
137+
138+
if (Event.current.type == EventType.KeyDown
139+
&& Event.current.keyCode == KeyCode.Return
140+
&& GUI.GetNameOfFocusedControl() == "TextField")
141+
{
142+
SubmitTextValue(inputText);
143+
Event.current.Use(); // Consume this event, we don't want to trigger other behavior with return key.
144+
}
145+
146+
if (GUILayout.Button("Submit Text"))
147+
{
148+
SubmitTextValue(inputText);
149+
}
150+
151+
EditorGUILayout.EndVertical();
152+
}
153+
154+
void SubmitTextValue(string cmd)
155+
{
156+
Script script = new Script();
157+
LuaManager.Instance.InitScriptOnce(script);
158+
var result = script.DoString($"return {cmd}");
159+
Debug.Log(result);
160+
}
161+
162+
void SubmitDropDownValue(string value)
163+
{
164+
var script = LuaManager.Instance.Scripts[LuaApiCategory.ToolScript][value];
165+
SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.ScriptedTool);
166+
LuaManager.Instance.SetActiveScriptByName(LuaApiCategory.ToolScript, value);
167+
168+
var startPoint = Vector3.up;
169+
var endPoint = Vector3.up + Vector3.one;
170+
LuaManager.Instance.SetApiProperty(script, $"Tool.{LuaNames.ToolScriptVector}", endPoint - startPoint);
171+
LuaManager.Instance.SetApiProperty(script, $"Tool.{LuaNames.ToolScriptRotation}", Quaternion.LookRotation(endPoint - startPoint));
172+
LuaManager.Instance.DoToolScript(LuaNames.Main, TrTransform.T(startPoint), TrTransform.T(endPoint));
173+
}
174+
}
175+
176+
}

Assets/Editor/LuaExampleScriptsTest.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)