1
0
forked from cgvr/DeltaVR

created ShapeDetectionNPC with voicelines, moved shape detection minigame controller logic inside it

This commit is contained in:
2026-02-12 12:22:23 +02:00
parent dc55e8d884
commit d0b909a1ab
9 changed files with 709 additions and 25 deletions

View File

@@ -1,10 +1,13 @@
using System;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
public class ShapeDetectionMinigameController : MonoBehaviour
public class ShapeDetectionNPC : NPCController
{
[Header("Shape Detection Minigame Config")]
public MicrophoneStand microphoneStand;
public RadioTransmitter radio;
public PushableButton imageGenerationButton;
public PushableButton modelGenerationButton;
public Texture2D GeneratedTexture { get; private set; }
@@ -15,24 +18,97 @@ public class ShapeDetectionMinigameController : MonoBehaviour
public string shapeScannerTag = "ShapeScannable";
public int ignorePlayerCollisionLayer = 2;
private bool modelGenerationInProgress;
// states:
// 0 - idle
// 1 - noticed player
// 2 - player picked up radio
// 3 - player spoke into the radio
// 4 - player pressed enter on keyboard
// 5 - player inserted picture into printer
// 6 - finished speaking
private int state;
private float lastPlayerApproachTime;
// Start is called before the first frame update
void Start()
private void Awake()
{
imageGenerationButton.OnButtonPressed += InvokeImageGeneration;
modelGenerationButton.OnButtonPressed += InvokeModelGeneration;
modelGenerationInProgress = false;
state = 0;
lastPlayerApproachTime = Time.time;
}
// Update is called once per frame
void Update()
private void Start()
{
radio.OnPlayerPickUp += OnPlayerPickedUpRadio;
microphoneStand.OnPlayerFinishedSpeaking += OnPlayerUsedMicrophone;
imageGenerationButton.OnButtonPressed += OnPlayerPressedKeyboard;
modelGenerationButton.OnButtonPressed += OnPlayerInitiatedPrinting;
}
protected async override void OnPlayerApproach()
{
if (Time.time < lastPlayerApproachTime + 0.5f)
{
return;
}
lastPlayerApproachTime = Time.time;
if (state == 0)
{
state = 1;
await CallPlayer();
}
}
protected override void OnPlayerLeave()
{
if (Time.time < lastPlayerApproachTime + 0.5f)
{
return;
}
if (state == 1)
{
state = 0;
}
}
private async Task CallPlayer()
{
if (state == 1)
{
SpeakVoiceLine(0);
await Task.Delay(2000);
SpeakVoiceLine(1);
Invoke(nameof(CallPlayer), 4f);
}
}
private void OnPlayerPickedUpRadio()
{
if (state == 1)
{
SpeakVoiceLine(2);
state = 2;
}
}
// TODO: replace microphone with radio
private void OnPlayerUsedMicrophone()
{
if (state == 2)
{
SpeakVoiceLine(3);
state = 3;
}
}
private async void OnPlayerPressedKeyboard()
{
if (state == 3)
{
SpeakVoiceLine(4);
state = 4;
}
}
private async void InvokeImageGeneration()
{
string inputPrompt = microphoneStand.GetTextOutput();
byte[] imageBytes = await InvokeAiClient.Instance.GenerateImage(inputPrompt);
GeneratedTexture = ModelGenerationUtils.CreateTexture(imageBytes);
@@ -40,15 +116,20 @@ public class ShapeDetectionMinigameController : MonoBehaviour
imageDisplay.sprite = sprite;
imageGenerationButton.Deactivate();
if (!modelGenerationInProgress)
if (state == 4)
{
modelGenerationButton.Deactivate();
}
}
private async void InvokeModelGeneration()
private async void OnPlayerInitiatedPrinting()
{
modelGenerationInProgress = true;
if (state == 4)
{
SpeakVoiceLine(5);
state = 5;
}
string encodedTexture = Convert.ToBase64String(GeneratedTexture.EncodeToJPG());
byte[] encodedModel = await TrellisClient.Instance.GenerateModel(encodedTexture);
@@ -59,12 +140,14 @@ public class ShapeDetectionMinigameController : MonoBehaviour
{
// Destroy previous generated object (first move out of ShapeScanner to trigger OnTriggerExit
GeneratedModel.transform.position = Vector3.zero;
//Destroy(GeneratedModel);
}
GeneratedModel = spawnedObject;
modelGenerationButton.Deactivate();
modelGenerationInProgress = false;
if (state == 5)
{
state = 6;
}
}
private void InitializeSpawnedObject(GameObject spawnedObject)

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7000d3fd17422c74e9f86757bc8529f0
guid: c5280c89a923c584db07cbc2e946f33e
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
public class RadioTransmitter : XRGrabInteractable
{
public delegate void OnPlayerPickUpDelegate();
public event OnPlayerPickUpDelegate OnPlayerPickUp;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
protected override void OnSelectEntered(SelectEnterEventArgs args)
{
base.OnSelectEntered(args);
OnPlayerPickUp?.Invoke();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5f509001c54a4e4794e50075eb0e214
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: