1
0
forked from cgvr/DeltaVR
Files
DeltaVR3DModelGeneration/Assets/_PROJECT/Scripts/ModeGeneration/NPCs/ShapeDetectionNPC.cs

180 lines
5.3 KiB
C#

using System;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
public class ShapeDetectionNPC : NPCController
{
[Header("Shape Detection Minigame Config")]
public QuestMarker questMarker;
public MicrophoneStand microphoneStand;
public RadioTransmitter radio;
public PushableButton imageGenerationButton;
public PushableButton modelGenerationButton;
public Texture2D GeneratedTexture { get; private set; }
public Image imageDisplay;
public ShapeScanner shapeScanner;
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();
await Task.Delay(2500);
questMarker.MoveTo(radio.transform);
}
}
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 async void OnPlayerPickedUpRadio()
{
if (state == 1)
{
SpeakVoiceLine(2);
state = 2;
await Task.Delay(5000);
questMarker.MoveTo(microphoneStand.transform);
}
}
// TODO: replace microphone with radio
private void OnPlayerUsedMicrophone()
{
if (state == 2)
{
SpeakVoiceLine(3);
state = 3;
questMarker.MoveTo(imageGenerationButton.transform);
}
}
private async void OnPlayerPressedKeyboard()
{
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 == 3)
{
SpeakVoiceLine(4);
state = 4;
questMarker.MoveTo(modelGenerationButton.transform);
modelGenerationButton.Deactivate();
}
}
private async void OnPlayerInitiatedPrinting()
{
if (state == 4)
{
SpeakVoiceLine(5);
state = 5;
questMarker.MoveTo(shapeScanner.transform);
}
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>();
}
}