diff --git a/.github/workflows/testRunner.yml b/.github/workflows/testRunner.yml index 88be90b..7d84a1f 100644 --- a/.github/workflows/testRunner.yml +++ b/.github/workflows/testRunner.yml @@ -4,35 +4,48 @@ on: [pull_request] jobs: test: + name: Run Tests in PlayMode and EditMode ✨ permissions: checks: write - name: Run Tests in PlayMode and EditMode ✨ runs-on: ubuntu-latest - steps: + timeout-minutes: 45 + steps: # Checkout - name: Checkout repository uses: actions/checkout@v4 with: lfs: true - # Cache - - uses: actions/cache@v3 + # Cache the Library folder for faster runs + - name: Cache Library + uses: actions/cache@v3 with: path: Library key: Library-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }} restore-keys: | Library- - - # Test - - name: Run tests - uses: game-ci/unity-test-runner@v4 + + # Run Unity tests (both EditMode + PlayMode by default) + - name: Run tests (Ubuntu + Xvfb) id: tests + uses: game-ci/unity-test-runner@v4 env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} with: githubToken: ${{ secrets.GITHUB_TOKEN }} + # Linux editor image for 6000.0.39f1; "base" is fine for tests + customImage: unityci/editor:ubuntu-6000.0.39f1-base-3.1.0 + # Stabilize headless graphics & stream logs to STDOUT + customParameters: "-force-glcore -logFile -" + testMode: All - \ No newline at end of file + # Always upload test artifacts (XML, logs, etc.) + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Unity Test Results + path: ${{ steps.tests.outputs.artifactsPath }} \ No newline at end of file diff --git a/Assets/Samples/SampleMenu/SampleMenuScript/InfoWindowPresenter.cs b/Assets/Samples/SampleMenu/SampleMenuScript/InfoWindowPresenter.cs index 893c942..0f26b29 100644 --- a/Assets/Samples/SampleMenu/SampleMenuScript/InfoWindowPresenter.cs +++ b/Assets/Samples/SampleMenu/SampleMenuScript/InfoWindowPresenter.cs @@ -1,3 +1,5 @@ +using System.Collections; +using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; @@ -8,51 +10,238 @@ public class InfoWindowPresenter : MonoBehaviour private VisualElement informationView; private VisualElement welcomeView; private TextElement informationText; + private TextElement inforHeader; + + private VisualElement upCard; + private VisualElement confirmCard; + private VisualElement downCard; + + + [SerializeField] + private StyleSheet informationStyleSheet; + + public List ButtonData; + public ScrollView ScrollButtonView; + + private int selectedIndex = 3; + + private const int DefaultSelectedIndex = 3; + + private Coroutine scrollCoroutine; + + [SerializeField] + private Texture2D backgroundMapTexture; + + private VisualElement informationImageWindow; + + private const string PulseClass = "pulse-color"; + private Color pulseColor = new Color(0.98f, 0.79f, 0.04f, 0.5f); // yellow w/ alpha + private Color originalColor = new Color(0.133f, 0.133f, 0.133f); private void Start() { VisualElement root = GetComponent().rootVisualElement; + root.styleSheets.Add(informationStyleSheet); + ScrollButtonView = root.Q("ButtonScroll"); informationView = root.Q("InformationView"); + informationImageWindow = informationView.Q("InformationContainer"); + upCard = informationView.Q("UpCard"); + confirmCard = informationView.Q("ConfirmCard"); + downCard = informationView.Q("DownCard"); welcomeView = root.Q("WelcomeView"); informationText = root.Q("InformationText"); + inforHeader = root.Q("InfoHeader"); + + ScrollButtonView.Clear(); + + // Initialize buttons + foreach (var data in ButtonData) + { + var button = new Button(); + button.text = data.ButtonName; + button.AddToClassList("button"); + ScrollButtonView.Add(button); + } + + HideInformationView(); } public void ShowInformationView() { informationView.style.display = DisplayStyle.Flex; welcomeView.style.display = DisplayStyle.None; + SetInformationText("To read information on possible use cases please match one of the gestures on the left", " "); + // Highlight new button + var centerButton = (Button)ScrollButtonView.ElementAt(selectedIndex); + HighlightButton(centerButton); + + // Center the selected button in the scroll view + ScrollToCenter(centerButton); + } public void HideInformationView() { - SetInformationText(0); + // Reset selection by taking the total cound and current index and math it to get back to 3 + MoveSelection(DefaultSelectedIndex - selectedIndex + 1); + + SetInformationText("To read information on possible use cases please match one of the gestures on the left", " "); informationView.style.display = DisplayStyle.None; welcomeView.style.display = DisplayStyle.Flex; + selectedIndex = DefaultSelectedIndex; + } + public void HighlightButton(Button button) + { + // Remove highlight + glow from all buttons + foreach (var child in ScrollButtonView.Children()) + { + if (child is Button b) + { + b.RemoveFromClassList("button-hover"); + b.RemoveFromClassList("button-glow"); + } + } + + // Add highlight + glow to the current one + button.AddToClassList("button-hover"); + button.AddToClassList("button-glow"); } - public void SetInformationText(int index = 0) + public void MoveSelection(int direction) { - if (informationView.style.display == DisplayStyle.Flex) + if (direction >= 0) + { + PlayPulse(downCard); + } + else + { + PlayPulse(upCard); + } + + // Wrap index instead of clamping + selectedIndex += direction; + if (selectedIndex < 0) selectedIndex = ScrollButtonView.childCount - 1; + else if (selectedIndex >= ScrollButtonView.childCount) selectedIndex = 0; + + // Highlight new button + var newButton = (Button)ScrollButtonView.ElementAt(selectedIndex); + HighlightButton(newButton); + + // Center the selected button in the scroll view + SmoothScrollToCenter(newButton); + + } + + public void ConfirmSelection() + { + // Clear the background image for any other button + informationImageWindow.style.backgroundImage = null; + + if (informationView.style.display == DisplayStyle.None) { - switch (index) + ShowInformationView(); + return; + } + + PlayPulse(confirmCard); + + if (selectedIndex >= 0 && selectedIndex < ButtonData.Count) + { + // if info text is "Return" hide the information view + if (ButtonData[selectedIndex].InfoText == "Return") + { + HideInformationView(); + return; + } + else if (ButtonData[selectedIndex].InfoText == "MAP") { - case 0: - informationText.text = "To read information on possible use cases please match one of the gestures on the left"; - break; - case 1: - informationText.text = "Our Unity plugin enables intuitive hand gesture recognition, making it ideal for modern kiosk technologies. It allows users to interact with digital content in a completely touchless manner, which is especially valuable in public environments where hygiene is a concern. This can be applied to interactive information kiosks in museums, airports, or retail settings, where users can browse content, navigate menus, or trigger actions using simple gestures. Additionally, the plugin supports integration with projector-based or holographic displays, enabling users to control immersive content in mid-air without physical contact, enhancing accessibility and creating futuristic, engaging user experiences."; - break; - case 2: - informationText.text = "Our Unity plugin opens up powerful possibilities in the realm of sign language recognition and learning. By accurately detecting and interpreting hand gestures, it can be used to create real-time translation tools that convert sign language into text or speech, improving communication accessibility for Deaf and hard-of-hearing individuals. Additionally, it can support immersive educational applications, allowing users to learn sign language through interactive lessons, visual feedback, and guided practice in a virtual environment. This makes it a valuable tool for both assistive technology and inclusive education."; - break; - default: - informationText.text = "To read information on possible use cases please match one of the gestures on the left"; - break; + if (backgroundMapTexture != null) + { + informationImageWindow.style.backgroundImage = new StyleBackground(backgroundMapTexture); + SetInformationText("", " "); + return; + } } + + SetInformationText(ButtonData[selectedIndex].InfoText, ButtonData[selectedIndex].ButtonName); + + var selectedButton = (Button)ScrollButtonView.ElementAt(selectedIndex); } } + + public void SetInformationText(string text, string header) + { + if (informationView.style.display == DisplayStyle.Flex) + { + informationText.text = text; + inforHeader.text = header; + } + } + + public void PlayPulse(VisualElement card) + { + // Set pulse color + card.style.backgroundColor = pulseColor; + + // Schedule reset back to original + card.schedule.Execute(() => + { + card.style.backgroundColor = originalColor; + }).StartingIn(300); // 300ms + } + + // function to scroll the selected button to the center of the scroll view + private void ScrollToCenter(Button button) + { + if (scrollCoroutine != null) + { + StopCoroutine(scrollCoroutine); + } + scrollCoroutine = StartCoroutine(ScrollToCenterCoroutine(button)); + } + + private void SmoothScrollToCenter(Button button) + { + if (scrollCoroutine != null) + { + StopCoroutine(scrollCoroutine); + } + scrollCoroutine = StartCoroutine(SmoothScrollToCenterCoroutine(button)); + } + + private IEnumerator ScrollToCenterCoroutine(Button button) + { + // Wait for the next frame to ensure the button is fully rendered + yield return null; + // Calculate the position of the button in the scroll view + float buttonPosition = button.resolvedStyle.top + button.resolvedStyle.height / 2; + float scrollViewHeight = ScrollButtonView.resolvedStyle.height; + // Calculate the new scroll position to center the button + float newScrollPosition = buttonPosition - scrollViewHeight / 2; + // Smoothly scroll to the new position + ScrollButtonView.scrollOffset = new Vector2(0, newScrollPosition); + } + + // coroutine to smoothly scroll the scroll view to the center of the selected button + private IEnumerator SmoothScrollToCenterCoroutine(Button button) + { + float targetPosition = button.resolvedStyle.top + button.resolvedStyle.height / 2; + float scrollViewHeight = ScrollButtonView.resolvedStyle.height; + float startPosition = ScrollButtonView.scrollOffset.y; + float newScrollPosition = targetPosition - scrollViewHeight / 2; + float duration = 0.25f; // Duration of the scroll + float elapsedTime = 0f; + while (elapsedTime < duration) + { + elapsedTime += Time.deltaTime; + float t = Mathf.Clamp01(elapsedTime / duration); + ScrollButtonView.scrollOffset = new Vector2(0, Mathf.Lerp(startPosition, newScrollPosition, t)); + yield return null; + } + ScrollButtonView.scrollOffset = new Vector2(0, newScrollPosition); + } } } diff --git a/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs b/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs new file mode 100644 index 0000000..08a0226 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "InformationWindowText", menuName = "Scriptable Objects/InformationWindowText")] +public class InformationWindowText : ScriptableObject +{ + // variable for name + [Tooltip("The name of the button")] + public string ButtonName; + + // variable for text + [Tooltip("The text to display in the information window")] + public string InfoText; + +} diff --git a/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs.meta b/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs.meta new file mode 100644 index 0000000..9185ab4 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScript/InformationWindowText.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 41e5796312d05d64784aac2a13a585bf \ No newline at end of file diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects.meta new file mode 100644 index 0000000..e9f36f9 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e84449d2ba9e90a44bd0877384f6a409 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset new file mode 100644 index 0000000..6ba0478 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset @@ -0,0 +1,20 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Art + m_EditorClassIdentifier: + ButtonName: Art & Creative Installations + InfoText: Transform exhibitions, performances, or installations with mid-air gesture + control. Artists and designers can allow audiences to interact with digital content, + manipulate visuals, or trigger audiovisual effects in real-time. The plugin makes + it possible to create immersive, participatory art experiences that blend technology + and creativity seamlessly. diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset.meta new file mode 100644 index 0000000..5141c99 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Art.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4ecbee8bc8eb56641903dfb8fae9ee31 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset new file mode 100644 index 0000000..11d208d --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset @@ -0,0 +1,20 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Education + m_EditorClassIdentifier: + ButtonName: Education & Interactive Learning + InfoText: Enhance classroom or virtual learning experiences with gesture-driven + interactions. The plugin allows students to manipulate virtual objects, navigate + lessons, or engage with interactive simulations using only their hands. This + encourages active participation, improves engagement, and supports diverse learning + styles in both in-person and remote education settings. diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset.meta new file mode 100644 index 0000000..eeefabf --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Education.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db4214065e2f8b548b119149de0add1e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset new file mode 100644 index 0000000..9707788 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset @@ -0,0 +1,24 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Kiosk + m_EditorClassIdentifier: + ButtonName: Kiosk + InfoText: Our Unity plugin enables intuitive hand gesture recognition, making it + ideal for modern kiosk technologies. It allows users to interact with digital + content in a completely touchless manner, which is especially valuable in public + environments where hygiene is a concern. This can be applied to interactive information + kiosks in museums, airports, or retail settings, where users can browse content, + navigate menus, or trigger actions using simple gestures. Additionally, the plugin + supports integration with projector-based or holographic displays, enabling users + to control immersive content in mid-air without physical contact, enhancing accessibility + and creating futuristic, engaging user experiences. diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset.meta new file mode 100644 index 0000000..afe9f97 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Kiosk.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 11dfd12b0b932a04fa40a507481a6bbf +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset new file mode 100644 index 0000000..3ca6655 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Map + m_EditorClassIdentifier: + ButtonName: Campus Map + InfoText: MAP diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset.meta new file mode 100644 index 0000000..bc5475a --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Map.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a37829ee2eb0f6428afcc90be20406e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset new file mode 100644 index 0000000..184c1e7 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Return + m_EditorClassIdentifier: + ButtonName: Return + InfoText: Return diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset.meta new file mode 100644 index 0000000..26a0bf5 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Return.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f1b28ab63389b14285466b91fd70bdb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset new file mode 100644 index 0000000..8483f91 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset @@ -0,0 +1,23 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: SignlLanguage + m_EditorClassIdentifier: + ButtonName: Sign Language + InfoText: Our Unity plugin opens up powerful possibilities in the realm of sign + language recognition and learning. By accurately detecting and interpreting hand + gestures, it can be used to create real-time translation tools that convert sign + language into text or speech, improving communication accessibility for Deaf + and hard-of-hearing individuals. Additionally, it can support immersive educational + applications, allowing users to learn sign language through interactive lessons, + visual feedback, and guided practice in a virtual environment. This makes it + a valuable tool for both assistive technology and inclusive education. diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset.meta new file mode 100644 index 0000000..6ab8452 --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/SignlLanguage.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9969bff3646d6ea4d8559f005430d7c2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset new file mode 100644 index 0000000..a9c311e --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset @@ -0,0 +1,20 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41e5796312d05d64784aac2a13a585bf, type: 3} + m_Name: Smart Home + m_EditorClassIdentifier: + ButtonName: 'Smart Home & IoT ' + InfoText: Integrate gesture recognition into smart home systems to control lights, + appliances, and entertainment systems with simple hand movements. Our Unity plugin + enables intuitive, touchless interactions, improving convenience and accessibility. + It can be used in public smart spaces, offices, or homes to create futuristic, + hygienic, and user-friendly environments. diff --git a/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset.meta b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset.meta new file mode 100644 index 0000000..b96273f --- /dev/null +++ b/Assets/Samples/SampleMenu/SampleMenuScriptableObjects/Smart Home.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc16f9603d3a74c458d5e58728796fad +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/SampleMenu/SampleMenuUI/SampleMenuInformation.uxml b/Assets/Samples/SampleMenu/SampleMenuUI/SampleMenuInformation.uxml index f3bbd07..a7f1c6b 100644 --- a/Assets/Samples/SampleMenu/SampleMenuUI/SampleMenuInformation.uxml +++ b/Assets/Samples/SampleMenu/SampleMenuUI/SampleMenuInformation.uxml @@ -1,26 +1,32 @@ -