summaryrefslogtreecommitdiff
path: root/VRCSDK3Worlds/Assets/Udon/WrapperModules/ExternVRCInstantiate.cs
blob: 70d22e78a3d813d36b6d097823abd347ac5c5e8f (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
#if !VRC_CLIENT
using System.Collections.Generic;
using UnityEngine;
using VRC.Udon;
using VRC.Udon.Common.Attributes;
using VRC.Udon.Common.Delegates;
using VRC.Udon.Common.Interfaces;
using VRC.Udon.Security.Interfaces;
using VRC.Udon.Wrapper.Modules;

[assembly: UdonWrapperModule(typeof(ExternVRCInstantiate))]

namespace VRC.Udon.Wrapper.Modules
{
    public class ExternVRCInstantiate : IUdonWrapperModule
    {
        public string Name => "VRCInstantiate";

        private readonly Dictionary<string, int> _parameterCounts;
        private readonly Dictionary<string, UdonExternDelegate> _functionDelegates;
        private readonly IUdonSecurityBlacklist _blacklist;

        //Passing unused parameter for consistent construction
        // ReSharper disable once UnusedParameter.Local
        public ExternVRCInstantiate(IUdonComponentGetter componentGetter, IUdonSecurityBlacklist blacklist)
        {
            _blacklist = blacklist;
            _parameterCounts = new Dictionary<string, int>
            {
                {"__Instantiate__UnityEngineGameObject__UnityEngineGameObject", 2},
            };

            _functionDelegates = new Dictionary<string, UdonExternDelegate>
            {
                {"__Instantiate__UnityEngineGameObject__UnityEngineGameObject", __Instantiate__UnityEngineGameObject__UnityEngineGameObject}
            };
        }

        public int GetExternFunctionParameterCount(string externFunctionSignature)
        {
            if(_parameterCounts.TryGetValue(externFunctionSignature, out int numParameters))
            {
                return numParameters;
            }

            throw new System.NotSupportedException($"Function '{externFunctionSignature}' is not implemented yet");
        }

        public UdonExternDelegate GetExternFunctionDelegate(string externFunctionSignature)
        {
            if(_functionDelegates.TryGetValue(externFunctionSignature, out UdonExternDelegate externDelegate))
            {
                return externDelegate;
            }

            throw new System.NotSupportedException($"Function '{externFunctionSignature}' is not implemented yet");
        }

        private void __Instantiate__UnityEngineGameObject__UnityEngineGameObject(IUdonHeap heap, uint[] parameterAddresses)
        {
            GameObject original = heap.GetHeapVariable<GameObject>(parameterAddresses[0]);
            #if !UDON_DISABLE_SECURITY
            _blacklist.FilterBlacklisted(ref original);
            #endif

            GameObject clone = Object.Instantiate(original);
            foreach(UdonBehaviour udonBehaviour in clone.GetComponentsInChildren<UdonBehaviour>(true))
            {
                UdonManager.Instance.RegisterUdonBehaviour(udonBehaviour);
            }

            heap.SetHeapVariable(parameterAddresses[1], clone);
        }
    }
}
#endif