forked from cgvr/DeltaVR
created ShapeDetectionNPC with voicelines, moved shape detection minigame controller logic inside it
This commit is contained in:
174
Assets/_PROJECT/Scripts/ModeGeneration/NPCs/ShapeDetectionNPC.cs
Normal file
174
Assets/_PROJECT/Scripts/ModeGeneration/NPCs/ShapeDetectionNPC.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
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; }
|
||||
public Image imageDisplay;
|
||||
|
||||
public GameObject GeneratedModel { get; private set; }
|
||||
public Transform modelSpawnPoint;
|
||||
public string shapeScannerTag = "ShapeScannable";
|
||||
public int ignorePlayerCollisionLayer = 2;
|
||||
|
||||
// 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;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
state = 0;
|
||||
lastPlayerApproachTime = Time.time;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
string inputPrompt = microphoneStand.GetTextOutput();
|
||||
byte[] imageBytes = await InvokeAiClient.Instance.GenerateImage(inputPrompt);
|
||||
GeneratedTexture = ModelGenerationUtils.CreateTexture(imageBytes);
|
||||
Sprite sprite = ModelGenerationUtils.CreateSprite(GeneratedTexture);
|
||||
imageDisplay.sprite = sprite;
|
||||
|
||||
imageGenerationButton.Deactivate();
|
||||
if (state == 4)
|
||||
{
|
||||
modelGenerationButton.Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnPlayerInitiatedPrinting()
|
||||
{
|
||||
if (state == 4)
|
||||
{
|
||||
SpeakVoiceLine(5);
|
||||
state = 5;
|
||||
}
|
||||
|
||||
string encodedTexture = Convert.ToBase64String(GeneratedTexture.EncodeToJPG());
|
||||
byte[] encodedModel = await TrellisClient.Instance.GenerateModel(encodedTexture);
|
||||
|
||||
GameObject spawnedObject = await ModelGenerationUtils.Instance.SpawnModel(encodedModel);
|
||||
InitializeSpawnedObject(spawnedObject);
|
||||
|
||||
if (GeneratedModel != null)
|
||||
{
|
||||
// Destroy previous generated object (first move out of ShapeScanner to trigger OnTriggerExit
|
||||
GeneratedModel.transform.position = Vector3.zero;
|
||||
}
|
||||
GeneratedModel = spawnedObject;
|
||||
modelGenerationButton.Deactivate();
|
||||
|
||||
if (state == 5)
|
||||
{
|
||||
state = 6;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeSpawnedObject(GameObject spawnedObject)
|
||||
{
|
||||
GameObject spawnedObjectParent = new GameObject("SpawnedModelParent");
|
||||
spawnedObjectParent.transform.parent = modelSpawnPoint;
|
||||
spawnedObjectParent.transform.position = modelSpawnPoint.transform.position;
|
||||
spawnedObjectParent.layer = ignorePlayerCollisionLayer;
|
||||
Rigidbody rigidbody = spawnedObjectParent.AddComponent<Rigidbody>();
|
||||
rigidbody.isKinematic = true;
|
||||
|
||||
//spawnedObject.AddComponent<NetworkObject>();
|
||||
//spawnedObject.AddComponent<NetworkTransform>();
|
||||
|
||||
MeshCollider spawnedObjectCollider = spawnedObject.GetComponent<MeshCollider>();
|
||||
spawnedObjectCollider.convex = false;
|
||||
spawnedObject.transform.parent = spawnedObjectParent.transform;
|
||||
spawnedObject.transform.position = spawnedObjectParent.transform.position;
|
||||
spawnedObject.tag = shapeScannerTag;
|
||||
spawnedObject.layer = ignorePlayerCollisionLayer;
|
||||
|
||||
spawnedObjectParent.AddComponent<TwoHandScaleGrabInteractable>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user