summaryrefslogtreecommitdiff
path: root/VRCSDK3Worlds/Assets/Bakery/examples/scripts/BakeryVolumeTrigger.cs
blob: 1be7f78d490cbc8eba039fce2023cd28fef5d183 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Example volume switching script
//
// The high-level logic is following:
//
// - Volumes overlap each other a bit, so we don't need blending! The size of the overlap is the size of your largest dynamic object.
// - As object enters the volume, set volume data to it. Increment the counter.
// - As object leaves the volume, decrement the counter. If it equals 0, use global volume (set empty property block).
// - If the volume is moving, set volume data every frame, in LateUpdate.
//
public class BakeryVolumeTrigger : MonoBehaviour
{
    public bool movable;

    BakeryVolume vol;
    MaterialPropertyBlock mb; // current volume shader properties

    static MaterialPropertyBlock mbEmpty; // default empty block, no values (will revert to global volume)
    static int mVolumeMin, mVolumeInvSize; // shader property IDs

    void Awake()
    {
        if (mbEmpty == null) mbEmpty = new MaterialPropertyBlock();

        // Create a MaterialPropertyBlock with Volume parameters for future use
        vol = GetComponent<BakeryVolume>();
        mb = new MaterialPropertyBlock();
        if (vol.bakedTexture0 != null)
        {
            mb.SetTexture("_Volume0", vol.bakedTexture0);
            mb.SetTexture("_Volume1", vol.bakedTexture1);
            mb.SetTexture("_Volume2", vol.bakedTexture2);
            if (vol.bakedTexture3 != null) mb.SetTexture("_Volume3", vol.bakedTexture3);
        }
        if (vol.bakedMask != null) mb.SetTexture("_VolumeMask", vol.bakedMask);
        if (mVolumeMin == 0) mVolumeMin = Shader.PropertyToID("_VolumeMin");
        if (mVolumeInvSize == 0) mVolumeInvSize = Shader.PropertyToID("_VolumeInvSize");
        mb.SetVector(mVolumeMin, vol.GetMin());
        mb.SetVector(mVolumeInvSize, vol.GetInvSize());
        if (vol.supportRotationAfterBake) mb.SetMatrix("_VolumeMatrix", vol.GetMatrix());
    }

    // Apply MaterialPropertyBlock to renderers entering the trigger
    void OnTriggerEnter(Collider c)
    {
        var rcv = c.GetComponent<BakeryVolumeReceiver>();
        if (rcv == null) return;

        Debug.Log(c.name + " entered " + this.name);

        rcv.enterCounter++;
        rcv.movableTrigger = movable ? this : null;
        rcv.SetPropertyBlock(mb);
    }

    // Handle exiting the trigger
    void OnTriggerExit(Collider c)
    {
        var rcv = c.GetComponent<BakeryVolumeReceiver>();
        if (rcv == null) return;

        Debug.Log(c.name + " exited " + this.name);

        // Only set empty property block, if the counter is 0 (= exited ALL volumes)
        rcv.enterCounter--;
        if (rcv.enterCounter == 0) rcv.SetPropertyBlock(mbEmpty);
    }

    public void UpdateBounds()
    {
        vol.UpdateBounds();
        mb.SetVector(mVolumeMin, vol.GetMin());
        mb.SetVector(mVolumeInvSize, vol.GetInvSize());
    }
}