Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ crashlytics-build.properties
.idea/.idea.playroom-unity/.idea/workspace.xml
.idea/.idea.playroom-unity/.idea/workspace.xml
node_modules
node_modules.meta
metaList
package-lock.json
package-lock.json.meta
Expand Down
3 changes: 2 additions & 1 deletion Assets/PlayroomKit/Editor/PlayroomDevEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public class PrkMockInspector : Editor

public void OnEnable()
{
styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/PlayroomKit/Editor/PlayroomkitDevManagerEditor.uss");
styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Packages/com.playroomkit.sdk/Editor/PlayroomkitDevManagerEditor.uss");

}

public override VisualElement CreateInspectorGUI()
Expand Down
283 changes: 283 additions & 0 deletions Assets/PlayroomKit/Editor/PlayroomKitNPMManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using System.IO;
using System.Linq;

#if UNITY_EDITOR
public class PlayroomKitSetupWindow : EditorWindow
{
private const string defaultNodePath = @"C:\Program Files\nodejs";

[MenuItem("PlayroomKit/Run Setup")]
public static void ShowWindow()
{
var window = GetWindow<PlayroomKitSetupWindow>();
window.titleContent = new GUIContent("PlayroomKit Setup");
window.minSize = new Vector2(450, 300);
}

public void CreateGUI()
{
// Load UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
"Packages/com.playroomkit.sdk/Editor/PlayroomKitNPMManager.uxml"
);

if (visualTree == null)
{
Debug.LogError("Could not find UXML file. Check the path.");
return;
}

VisualElement root = visualTree.CloneTree();
rootVisualElement.Add(root);

// Reference UI elements
Toggle npmCheck = root.Q<Toggle>("npmCheck");
Toggle modulesCheck = root.Q<Toggle>("modulesCheck");
TextField pathField = root.Q<TextField>("pathField");
Button inputPathButton = root.Q<Button>("inputPath");
Button downloadButton = root.Q<Button>("downloadButton");
Button refreshButton = root.Q<Button>("refreshButton");
Button installButton = root.Q<Button>("installButton");


// Set initial display values
npmCheck.SetEnabled(false);
modulesCheck.SetEnabled(false);
npmCheck.value = CheckIfNpmExists();
modulesCheck.value = CheckIfNodeModulesExist();
installButton.SetEnabled(false);

bool modulesExist = CheckIfNodeModulesExist();
installButton.SetEnabled(!modulesExist);

if (string.IsNullOrWhiteSpace(pathField.value))
{
pathField.value = defaultNodePath;
}

// Let user select custom Node.js path
inputPathButton.clicked += () =>
{
string selectedPath = EditorUtility.OpenFolderPanel("Select Node.js directory", pathField.value, "");
if (!string.IsNullOrEmpty(selectedPath))
{
pathField.value = selectedPath;
}
};

installButton.clicked += () =>
{
string npmPath = FindNpmInGlobalPath();
if (string.IsNullOrEmpty(npmPath) || !File.Exists(npmPath))
{
Debug.LogError("Cannot run npm install. npm not found.");
return;
}

// Locate PlayroomKit package in PackageCache
string packagePrefix = "com.playroomkit.sdk@";
string packageCacheRoot = "Library/PackageCache";
string editorCachePath = null;

try
{
var matchingDir = Directory.GetDirectories(packageCacheRoot, $"{packagePrefix}*")
.FirstOrDefault(d => Directory.Exists(Path.Combine(d, "Editor")));

if (matchingDir == null)
{
Debug.LogError("PlayroomKit package not found in PackageCache.");
return;
}

editorCachePath = Path.Combine(matchingDir, "Editor");
}
catch (System.Exception ex)
{
Debug.LogException(ex);
return;
}

// Run `npm install` in that editor path
var process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = npmPath,
Arguments = "install",
WorkingDirectory = editorCachePath,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

process.OutputDataReceived += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
Debug.Log("[npm] " + e.Data);
};

process.ErrorDataReceived += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
Debug.LogWarning("[npm error] " + e.Data);
};

try
{
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();

Debug.Log("npm install finished with exit code: " + process.ExitCode);

if (process.ExitCode == 0)
{
string sourcePath = Path.Combine(editorCachePath, "node_modules");
string targetRoot = Path.Combine("Assets", "Playroom");
string targetEditorPath = Path.Combine(targetRoot, "Editor");
string targetNodeModules = Path.Combine(targetEditorPath, "node_modules");

// Create destination folders if missing
if (!Directory.Exists(targetEditorPath))
{
Directory.CreateDirectory(targetEditorPath);
Debug.Log("Created directory: " + targetEditorPath);
}

// Remove old node_modules if already there
if (Directory.Exists(targetNodeModules))
{
Directory.Delete(targetNodeModules, true);
Debug.Log("Old node_modules deleted in target.");
}

// Move node_modules to the embedded package
Directory.Move(sourcePath, targetNodeModules);
Debug.Log("node_modules successfully moved to: " + targetNodeModules);
refreshCheck();
}
else
{
Debug.LogWarning("npm install failed.");
}
}
catch (System.Exception ex)
{
Debug.LogError("Failed during npm install or moving node_modules: " + ex.Message);
}
};



// Open Node.js download page
downloadButton.clicked += () =>
{
Application.OpenURL("https://nodejs.org/");
};

// Refresh environment check
refreshButton.clicked += () =>
{
refreshCheck();
};

// Optional: validate path on change
pathField.RegisterValueChangedCallback(evt =>
{
string testPath = Path.Combine(evt.newValue.Trim(), "npm.cmd");
if (!File.Exists(testPath))
{
Debug.LogWarning("npm.cmd not found in: " + evt.newValue);
}
}
);
}

private bool CheckIfNpmExists(string userDefinedPath = null)
{
string npmPath = !string.IsNullOrWhiteSpace(userDefinedPath)
? Path.Combine(userDefinedPath.Trim(), Application.platform == RuntimePlatform.WindowsEditor ? "npm.cmd" : "npm")
: FindNpmInGlobalPath();

if (string.IsNullOrEmpty(npmPath) || !File.Exists(npmPath))
{
Debug.LogWarning("npm not found.");
return false;
}

try
{
var process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = npmPath,
Arguments = "--version",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (!string.IsNullOrEmpty(error))
Debug.LogWarning("npm error: " + error);

return !string.IsNullOrEmpty(output);
}
catch (System.Exception ex)
{
Debug.LogWarning("Failed to run npm: " + ex.Message);
return false;
}
}

private string FindNpmInGlobalPath()
{
string envPath = System.Environment.GetEnvironmentVariable("PATH");
if (string.IsNullOrEmpty(envPath))
return null;

string[] pathDirs = envPath.Split(Path.PathSeparator);
string npmFile = Application.platform == RuntimePlatform.WindowsEditor ? "npm.cmd" : "npm";

foreach (string dir in pathDirs)
{
string fullPath = Path.Combine(dir.Trim(), npmFile);
if (File.Exists(fullPath))
{
return fullPath;
}
}

return null;
}


private bool CheckIfNodeModulesExist()
{
string path = "Assets/Playroom/Editor/node_modules";
return Directory.Exists(path);
}

private null refreshCheck()
{

bool npmInstalled = CheckIfNpmExists(userNodePath);
bool modulesInstalled = CheckIfNodeModulesExist();

npmCheck.value = npmInstalled;
modulesCheck.value = modulesInstalled;

Debug.Log("Environment refreshed.");
}
}
#endif // UNITY_EDITOR
12 changes: 12 additions & 0 deletions Assets/PlayroomKit/Editor/PlayroomKitNPMManager.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions Assets/PlayroomKit/Editor/PlayroomKitNPMManager.uxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement name="root" style="flex-grow: 1;">
<ui:Label text="This is the node and npm package installation window to prompt you to install node.js so we can add the required node_modules required for the PlayroomKit Unity SDK to work" style="height: 96px; width: 340px; -unity-text-align: upper-center; white-space: normal; text-overflow: clip; align-self: center;" />
<ui:Toggle label="NPM Installed:" value="false" name="npmCheck" />
<ui:Toggle label="Modules Installed:" name="modulesCheck" />
<ui:VisualElement name="pathContainer" style="flex-grow: 1;">
<ui:TextField picking-mode="Ignore" label="Node Path:" value="C:\Program Files\nodejs" name="pathField" />
<ui:Button text="Set Custom Node Path" parse-escape-sequences="true" display-tooltip-when-elided="true" name="inputPath" style="width: 169px; -unity-text-align: middle-center; white-space: nowrap; align-self: flex-end;" />
</ui:VisualElement>
<ui:Button text="Download Node.js" parse-escape-sequences="true" display-tooltip-when-elided="true" name="downloadButton" />
<ui:Button text="Download Chrome Driver (For Mock Mode)" parse-escape-sequences="true" display-tooltip-when-elided="true" name="driverDownloadButton" />
<ui:Button text="Install Node Modules" parse-escape-sequences="true" display-tooltip-when-elided="true" name="installButton" style="height: 41px;" />
<ui:Button text="Refresh" parse-escape-sequences="true" display-tooltip-when-elided="true" name="refreshButton" />
</ui:VisualElement>
</ui:UXML>
10 changes: 10 additions & 0 deletions Assets/PlayroomKit/Editor/PlayroomKitNPMManager.uxml.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 120dfa1b0ad7e96479cb0286e61ad19d, type: 3}
m_Name:
m_EditorClassIdentifier:
mockMode: 1
mockMode: 0
insertCoinCaller: {fileID: 0}
enableLogs: 0
--- !u!1 &5935941862803782869
Expand Down
Loading