1
0
forked from cgvr/DeltaVR

replaced demo boxes with microphone stand and buttons, in archery range

This commit is contained in:
2026-01-10 17:00:45 +02:00
parent 46b1c7e1de
commit ce75a1f343
39 changed files with 2631 additions and 141 deletions

View File

@@ -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;
}
}

View File

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

View 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;
}
}

View File

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

View 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;
}
}

View File

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

View File

@@ -35,7 +35,6 @@ public class NPCController : MonoBehaviour
private void OnTriggerEnter(Collider other)
{
Debug.Log("Collided with " + other);
KbmController controller = other.GetComponent<KbmController>();
XROrigin playerOrigin = other.GetComponent<XROrigin>();
if (controller != null)