forked from cgvr/DeltaVR
replaced demo boxes with microphone stand and buttons, in archery range
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ArcheryRangeModelGenerationController : MonoBehaviour
|
||||
{
|
||||
public MicrophoneStand microphoneStand;
|
||||
public PushableButton imageGenerationButton;
|
||||
public PushableButton modelGenerationButton;
|
||||
|
||||
public string imageGenerationPromptSuffix = ", single object, front and side fully visible, realistic style, plain neutral background, clear details, soft studio lighting, true-to-scale";
|
||||
public Texture2D GeneratedTexture { get; private set; }
|
||||
public Image imageDisplay;
|
||||
|
||||
public Transform modelSpawnPoint;
|
||||
public GameObject GeneratedModel { get; private set; }
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
imageGenerationButton.OnButtonPressed += InvokeImageGeneration;
|
||||
modelGenerationButton.OnButtonPressed += InvokeModelGeneration;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async void InvokeImageGeneration()
|
||||
{
|
||||
string inputPrompt = microphoneStand.GetTextOutput();
|
||||
string refinedPrompt = inputPrompt + imageGenerationPromptSuffix;
|
||||
|
||||
|
||||
byte[] imageBytes = await InvokeAiClient.Instance.GenerateImage(refinedPrompt);
|
||||
GeneratedTexture = CreateTexture(imageBytes);
|
||||
Sprite sprite = CreateSprite(GeneratedTexture);
|
||||
imageDisplay.sprite = sprite;
|
||||
|
||||
imageGenerationButton.MoveButtonUp();
|
||||
}
|
||||
|
||||
private async void InvokeModelGeneration()
|
||||
{
|
||||
string encodedTexture = Convert.ToBase64String(GeneratedTexture.EncodeToJPG());
|
||||
byte[] encodedModel = await TrellisClient.Instance.GenerateModel(encodedTexture);
|
||||
|
||||
GameObject spawnedObject = await PipelineManager.Instance.SpawnModel(encodedModel);
|
||||
spawnedObject.AddComponent<Rigidbody>();
|
||||
spawnedObject.transform.parent = modelSpawnPoint;
|
||||
spawnedObject.transform.position = modelSpawnPoint.position;
|
||||
GeneratedModel = spawnedObject;
|
||||
|
||||
modelGenerationButton.MoveButtonUp();
|
||||
}
|
||||
|
||||
private Texture2D CreateTexture(byte[] imageBytes)
|
||||
{
|
||||
var tex = new Texture2D(2, 2, TextureFormat.RGBA32, false);
|
||||
// ImageConversion.LoadImage returns bool (true = success)
|
||||
if (!ImageConversion.LoadImage(tex, imageBytes, markNonReadable: false))
|
||||
{
|
||||
Destroy(tex);
|
||||
throw new InvalidOperationException("Failed to decode image bytes into Texture2D.");
|
||||
}
|
||||
|
||||
tex.filterMode = FilterMode.Bilinear;
|
||||
tex.wrapMode = TextureWrapMode.Clamp;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
private Sprite CreateSprite(Texture2D tex)
|
||||
{
|
||||
var sprite = Sprite.Create(
|
||||
tex,
|
||||
new Rect(0, 0, tex.width, tex.height),
|
||||
new Vector2(0.5f, 0.5f),
|
||||
pixelsPerUnit: 100f
|
||||
);
|
||||
|
||||
return sprite;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99e1fdda206b5d04082b6a45593a1e84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
87
Assets/_PROJECT/Scripts/ModeGeneration/MicrophoneStand.cs
Normal file
87
Assets/_PROJECT/Scripts/ModeGeneration/MicrophoneStand.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using Whisper;
|
||||
using Whisper.Utils;
|
||||
|
||||
public class MicrophoneStand : MonoBehaviour
|
||||
{
|
||||
public WhisperManager whisper;
|
||||
public MicrophoneRecord microphoneRecord;
|
||||
public string microphoneDevice;
|
||||
public TextMeshProUGUI outputText;
|
||||
|
||||
private WhisperStream stream;
|
||||
|
||||
private string textOutput;
|
||||
|
||||
public GameObject microphoneOffStatus;
|
||||
public GameObject microphoneOnStatus;
|
||||
|
||||
// Start is called before the first frame update
|
||||
async void Start()
|
||||
{
|
||||
Debug.Log("Mic devices: " + string.Join(", ", Microphone.devices));
|
||||
Debug.Log("Using mic device: " + microphoneDevice);
|
||||
microphoneRecord.SelectedMicDevice = microphoneDevice;
|
||||
|
||||
// This causes about 1 sec long freeze, has to be done once at the start of the game
|
||||
microphoneRecord.StartRecord();
|
||||
|
||||
stream = await whisper.CreateStream(microphoneRecord);
|
||||
stream.OnResultUpdated += OnWhisperResult;
|
||||
|
||||
microphoneOffStatus.SetActive(true);
|
||||
microphoneOnStatus.SetActive(false);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
KbmController controller = other.GetComponent<KbmController>();
|
||||
Debug.Log("Mic stand collided with object " + other.gameObject.name);
|
||||
|
||||
if (controller != null || other.gameObject.tag == "Player Head")
|
||||
{
|
||||
microphoneOffStatus.SetActive(false);
|
||||
microphoneOnStatus.SetActive(true);
|
||||
|
||||
stream.StartStream();
|
||||
Debug.Log("Whisper stream started.");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
KbmController controller = other.GetComponent<KbmController>();
|
||||
if (controller != null | other.gameObject.tag == "Player Head")
|
||||
{
|
||||
microphoneOffStatus.SetActive(true);
|
||||
microphoneOnStatus.SetActive(false);
|
||||
|
||||
stream.StopStream();
|
||||
textOutput = outputText.text;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWhisperResult(string result)
|
||||
{
|
||||
Debug.Log("Whisper result processed: " + result);
|
||||
outputText.text = result;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
microphoneRecord.StopRecord();
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
public string GetTextOutput()
|
||||
{
|
||||
return textOutput;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 357101b2cface4943b04dfd25d4944e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
52
Assets/_PROJECT/Scripts/ModeGeneration/PushableButton.cs
Normal file
52
Assets/_PROJECT/Scripts/ModeGeneration/PushableButton.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
public class PushableButton : MonoBehaviour
|
||||
{
|
||||
public delegate void OnButtonPressedDelegate();
|
||||
public event OnButtonPressedDelegate OnButtonPressed;
|
||||
|
||||
|
||||
public Transform movableParts;
|
||||
public float moveDuration = 0.25f;
|
||||
|
||||
private float upPositionY;
|
||||
private float downPositionY;
|
||||
private bool isButtonDown;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
upPositionY = movableParts.localPosition.y;
|
||||
downPositionY = movableParts.localPosition.y - 0.1f;
|
||||
isButtonDown = false;
|
||||
}
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
if (!isButtonDown && collision.gameObject.tag.EndsWith("Hand"))
|
||||
{
|
||||
movableParts.DOLocalMoveY(downPositionY, moveDuration);
|
||||
isButtonDown = true;
|
||||
OnButtonPressed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveButtonUp()
|
||||
{
|
||||
movableParts.DOLocalMoveY(upPositionY, moveDuration);
|
||||
isButtonDown = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 682848c63dbd4614880393ae570f719c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user