private static void ExecuteEventForObject(VRC_EventHandler.VrcEvent triggerEvent, GameObject obj, VRC_EventHandler.EventInfo eventInfo, VRC_Trigger.TriggerEvent originalTrigger)
        {
            instance_.Log("Executing Trigger Event: " + triggerEvent.GetEventAsString(obj) + "\n_On Trigger: " + originalTrigger?.GetTriggerEventAsString());

            bool isBufferedExecution = eventInfo.broadcast.IsBufferedBroadcastType() && eventInfo.instagator == null;

            if (eventInfo.broadcast.IsOwnerBroadcastType())
            {
                if (!Networking.IsOwner(obj) || isBufferedExecution)
                {
                    instance_.LogWarning("Not executing as user is not the owner");
                    return;
                }
            }

            if (!isBufferedExecution && eventInfo.broadcast.IsMasterBroadcastType())
            {
                if (!Networking.IsMaster || isBufferedExecution)
                {
                    instance_.LogWarning("Not executing as user is not the master");
                    return;
                }
            }

            if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.ActivateCustomTrigger)
            {
                // Only activates first one
                VRC_Trigger trigger = obj.GetComponent <VRC_Trigger>();
                if (obj.activeInHierarchy && trigger.enabled)
                {
                    trigger.ExecuteCustomTrigger(triggerEvent.ParameterString);
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationBool)
            {
                Animator animator = obj.GetComponent <Animator>();
                bool     value    = animator.GetBool(triggerEvent.ParameterString);
                bool     newValue = VRC_EventHandler.BooleanOp(triggerEvent.ParameterBoolOp, value);
                animator.SetBool(triggerEvent.ParameterString, newValue);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationInt)
            {
                Animator animator = obj.GetComponent <Animator>();
                animator.SetInteger(triggerEvent.ParameterString, triggerEvent.ParameterInt);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationFloat)
            {
                Animator animator = obj.GetComponent <Animator>();
                animator.SetFloat(triggerEvent.ParameterString, triggerEvent.ParameterFloat);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationIntAdd)
            {
                Animator animator = obj.GetComponent <Animator>();
                int      value    = animator.GetInteger(triggerEvent.ParameterString);
                animator.SetInteger(triggerEvent.ParameterString, value + triggerEvent.ParameterInt);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationIntDivide)
            {
                Animator animator = obj.GetComponent <Animator>();
                int      value    = animator.GetInteger(triggerEvent.ParameterString);
                animator.SetInteger(triggerEvent.ParameterString, value / triggerEvent.ParameterInt);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationIntMultiply)
            {
                Animator animator = obj.GetComponent <Animator>();
                int      value    = animator.GetInteger(triggerEvent.ParameterString);
                animator.SetInteger(triggerEvent.ParameterString, value * triggerEvent.ParameterInt);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationIntSubtract)
            {
                Animator animator = obj.GetComponent <Animator>();
                int      value    = animator.GetInteger(triggerEvent.ParameterString);
                animator.SetInteger(triggerEvent.ParameterString, value - triggerEvent.ParameterInt);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AnimationTrigger)
            {
                obj.GetComponent <Animator>().SetTrigger(triggerEvent.ParameterString);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.PlayAnimation)
            {
                obj.GetComponent <Animation>().Play(triggerEvent.ParameterString);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AudioTrigger)
            {
                AudioSource[] audioSources = obj.GetComponents <AudioSource>();
                foreach (var source in audioSources)
                {
                    if (source.clip.name == triggerEvent.ParameterString)
                    {
                        source.Play();
                    }
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.DestroyObject)
            {
                Destroy(obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SendRPC)
            {
                object[] parameters     = VRC_Serialization.ParameterDecoder(triggerEvent.ParameterBytes);
                Type[]   parameterTypes = new Type[parameters.Length];
                for (int paramIndex = 0; paramIndex < parameters.Length; ++paramIndex)
                {
                    parameterTypes[paramIndex] = parameters[paramIndex].GetType();
                }

                foreach (MonoBehaviour mono in obj.GetComponents <MonoBehaviour>())
                {
                    MethodInfo methodInfo = mono.GetType().GetMethod(triggerEvent.ParameterString, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, parameterTypes, null);

                    if (methodInfo != null)
                    {
                        methodInfo.Invoke(mono, parameters);
                    }
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetComponentActive)
            {
                Type type = instance_.GetTypeForComponent(triggerEvent.ParameterString);
                if (type != null)
                {
                    PropertyInfo property = type.GetProperty("enabled");
                    if (property != null)
                    {
                        foreach (Component component in obj.GetComponents(type))
                        {
                            bool value    = (bool)property.GetValue(component, null);
                            bool newValue = VRC_EventHandler.BooleanOp(triggerEvent.ParameterBoolOp, value);
                            property.SetValue(component, newValue, null);
                        }
                    }
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetGameObjectActive)
            {
                bool newValue = VRC_EventHandler.BooleanOp(triggerEvent.ParameterBoolOp, obj.activeSelf);
                obj.SetActive(newValue);

                CyanEmuTriggerHelper triggerHelper = obj.GetComponent <CyanEmuTriggerHelper>();
                if (triggerHelper != null && isTriggerGlobalBroadcast_)
                {
                    if (newValue && triggerHelper.HasGlobalOnDisable)
                    {
                        instance_.LogWarning("Posisble OnEnable or OnTimer oversync!");
                    }
                    else if (!newValue && triggerHelper.HasGlobalOnDisable)
                    {
                        instance_.LogWarning("Posisble OnDisable oversync!");
                    }
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetLayer)
            {
                obj.layer = triggerEvent.ParameterInt;
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetMaterial)
            {
                Material mat = VRC_SceneDescriptor.GetMaterial(triggerEvent.ParameterString);
                obj.GetComponent <Renderer>().material = mat;
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetParticlePlaying)
            {
                ParticleSystem system   = obj.GetComponent <ParticleSystem>();
                bool           newValue = VRC_EventHandler.BooleanOp(triggerEvent.ParameterBoolOp, system.isPlaying);
                if (newValue)
                {
                    system.Play();
                }
                else
                {
                    system.Stop();
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetUIText)
            {
                obj.GetComponent <UnityEngine.UI.Text>().text = triggerEvent.ParameterString;
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SpawnObject)
            {
                GameObject prefab = VRC_SceneDescriptor.GetPrefab(triggerEvent.ParameterString);
                CyanEmuMain.SpawnObject(prefab, obj.transform.position, obj.transform.rotation);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.TeleportPlayer)
            {
                if (isBufferedExecution)
                {
                    instance_.LogWarning("Teleport player actions should not be buffered. Ignoring");
                }
                else
                {
                    if (CyanEmuPlayerController.instance != null)
                    {
                        CyanEmuPlayerController.instance.Teleport(triggerEvent.ParameterObjects[0].transform, triggerEvent.ParameterBoolOp == VRC_EventHandler.VrcBooleanOp.True);
                    }
                    else
                    {
                        instance_.LogWarning("No player container to teleport!");
                    }

                    if (eventInfo.broadcast != VRC_EventHandler.VrcBroadcastType.Local)
                    {
                        instance_.LogWarning("TeleportPlayer action should be set to local!");
                    }
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AddForce)
            {
                HandleTriggerPhysicsEvent(triggerEvent, obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AddVelocity)
            {
                HandleTriggerPhysicsEvent(triggerEvent, obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetVelocity)
            {
                HandleTriggerPhysicsEvent(triggerEvent, obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AddAngularVelocity)
            {
                HandleTriggerPhysicsEvent(triggerEvent, obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetAngularVelocity)
            {
                HandleTriggerPhysicsEvent(triggerEvent, obj);
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AddDamage)
            {
                HandleTriggerDamageEvent(triggerEvent, obj);

                if (isBufferedExecution)
                {
                    instance_.LogWarning("AddDamage action should not be buffered!");
                }
                else if (eventInfo.broadcast != VRC_EventHandler.VrcBroadcastType.Local)
                {
                    instance_.LogWarning("AddDamage action should be set to local!");
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.AddHealth)
            {
                HandleTriggerDamageEvent(triggerEvent, obj);

                if (isBufferedExecution)
                {
                    instance_.LogWarning("AddHealth action should not be buffered!");
                }
                else if (eventInfo.broadcast != VRC_EventHandler.VrcBroadcastType.Local)
                {
                    instance_.LogWarning("AddHealth action should be set to local!");
                }
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetWebPanelURI)
            {
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.SetWebPanelVolume)
            {
            }
            else if (triggerEvent.EventType == VRC_EventHandler.VrcEventType.MeshVisibility)
            {
            }
        }
        private void Awake()
        {
            if (instance != null)
            {
                this.LogError("Player controller instance already exists!");
                DestroyImmediate(this);
                return;
            }

#if VRC_SDK_VRCSDK2
            legacyLocomotion_ = true;
#endif

            instance         = this;
            descriptor_      = FindObjectOfType <VRC_SceneDescriptor>();
            gameObject.layer = LayerMask.NameToLayer("PlayerLocal");
            gameObject.tag   = "Player";

            rigidbody_             = gameObject.AddComponent <Rigidbody>();
            rigidbody_.isKinematic = true;

            characterController_                 = gameObject.AddComponent <CharacterController>();
            characterController_.slopeLimit      = 50;
            characterController_.stepOffset      = .5f;
            characterController_.skinWidth       = 0.005f;
            characterController_.minMoveDistance = 0;
            characterController_.center          = new Vector3(0, 0.8f, 0);
            characterController_.radius          = 0.2f;
            characterController_.height          = 1.6f;


            GameObject capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);
            capsule.transform.localScale = new Vector3(0.4f, 1, 0.4f);
            capsule.transform.SetParent(transform, false);
            capsule.transform.localPosition = new Vector3(0, 1, 0);
            capsule.layer = LayerMask.NameToLayer("MirrorReflection");
            DestroyImmediate(capsule.GetComponent <Collider>());


            playerCamera_ = new GameObject("Player Camera");
            GameObject cameraHolder = new GameObject("CameraHolder");
            cameraHolder.transform.SetParent(playerCamera_.transform, false);
            camera_              = cameraHolder.AddComponent <Camera>();
            camera_.cullingMask &= ~(1 << 18); // remove mirror reflection

            // TODO, make based on avatar armspan/settings
            cameraHolder.transform.localScale = Vector3.one * AVATAR_SCALE_;

            playerCamera_.AddComponent <AudioListener>();
            playerCamera_.transform.SetParent(transform, false);
            playerCamera_.transform.localPosition = new Vector3(0, STANDING_HEIGHT_, .1f);
            playerCamera_.transform.localRotation = Quaternion.identity;

            playspace_ = new GameObject("Playspace Center");
            playspace_.transform.SetParent(transform, false);
            playspace_.transform.localPosition = new Vector3(-1, 0, -1);
            playspace_.transform.localRotation = Quaternion.Euler(0, 45, 0);

            rightArmPosition_ = new GameObject("Right Arm Position");
            rightArmPosition_.transform.SetParent(playerCamera_.transform, false);
            rightArmPosition_.transform.localPosition = new Vector3(0.2f, -0.2f, 0.75f);
            rightArmRigidbody_             = rightArmPosition_.AddComponent <Rigidbody>();
            rightArmRigidbody_.isKinematic = true;

            leftArmPosition_ = new GameObject("Left Arm Position");
            leftArmPosition_.transform.SetParent(playerCamera_.transform, false);
            leftArmPosition_.transform.localPosition = new Vector3(-0.2f, -0.2f, 0.75f);
            leftArmRigidbody_             = leftArmPosition_.AddComponent <Rigidbody>();
            leftArmRigidbody_.isKinematic = true;

            mouseLook_ = new MouseLook();
            mouseLook_.Init(transform, playerCamera_.transform);

            stance_ = Stance.STANDING;

            baseInput_ = transform.parent.gameObject.GetComponent <CyanEmuBaseInput>();
            CreateMenu();

            GameObject interactHelper = new GameObject("InteractHelper");
            interactHelper.transform.SetParent(transform.parent, false);
            interactHelper_ = interactHelper.AddComponent <CyanEmuInteractHelper>();
            Func <bool> shouldCheckForInteracts = () => { return(currentPickup_ == null && !menu_.activeInHierarchy && !isDead_); };
            interactHelper_.Initialize(playerCamera_.transform, playerCamera_.transform, shouldCheckForInteracts);

            reticleTexture_ = Resources.Load <Texture2D>("Images/Reticle");

            cameraProxyObject_ = new GameObject("CameraDamageProxy").transform;
            cameraProxyObject_.SetParent(CyanEmuMain.GetProxyObjectTransform(), false);
            UpdateCameraProxyPosition();

            // experimental!
            //interactHelper_.highlightManager = playerCamera_.AddComponent<VRCP_HighlightManager>();
        }
        private void OnGUISceneSettings(VRC_SceneDescriptor scene)
        {
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.BeginVertical(VRCSdkControlPanel.boxGuiStyle, GUILayout.Width(VRCSdkControlPanel.SdkWindowWidth));

            string name = "Unpublished VRChat World";

            if (scene.apiWorld != null)
            {
                name = (scene.apiWorld as Core.ApiWorld)?.name;
            }
            EditorGUILayout.Space();
            EditorGUILayout.LabelField(name, VRCSdkControlPanel.titleGuiStyle);

            Core.PipelineManager[] pms = Tools.FindSceneObjectsOfTypeAll <Core.PipelineManager>();
            if (pms.Length == 1)
            {
                if (!string.IsNullOrEmpty(pms[0].blueprintId))
                {
                    if (scene.apiWorld == null)
                    {
                        Core.ApiWorld world = Core.API.FromCacheOrNew <Core.ApiWorld>(pms[0].blueprintId);
                        world.Fetch(null, null,
                                    (c) => scene.apiWorld = c.Model as Core.ApiWorld,
                                    (c) =>
                        {
                            if (c.Code == 404)
                            {
                                Core.Logger.Log(
                                    $"Could not load world {pms[0].blueprintId} because it didn't exist.", Core.DebugLevel.All);
                                Core.ApiCache.Invalidate <Core.ApiWorld>(pms[0].blueprintId);
                            }
                            else
                            {
                                Debug.LogErrorFormat("Could not load world {0} because {1}", pms[0].blueprintId,
                                                     c.Error);
                            }
                        });
                        scene.apiWorld = world;
                    }
                }
                else
                {
                    // clear scene.apiWorld if blueprint ID has been detached, so world details in builder panel are also cleared
                    scene.apiWorld = null;
                }
            }

            if (scene.apiWorld != null)
            {
                Core.ApiWorld w = (scene.apiWorld as Core.ApiWorld);
                DrawContentInfoForWorld(w);
                VRCSdkControlPanel.DrawContentPlatformSupport(w);
            }

            VRCSdkControlPanel.DrawBuildTargetSwitcher();

            GUILayout.EndVertical();
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }
        protected virtual void OnGUISceneCheck(VRC_SceneDescriptor scene)
        {
            CheckUploadChanges(scene);
#if !VRC_SDK_VRCSDK3
            bool isSdk3Scene = false;
#elif UDON
            bool isSdk3Scene = scene as VRC.SDK3.Components.VRCSceneDescriptor != null;
#endif

            List <VRC_EventHandler> sdkBaseEventHandlers =
                new List <VRC_EventHandler>(Object.FindObjectsOfType <VRC_EventHandler>());
#if VRC_SDK_VRCSDK2
            if (isSdk3Scene == false)
            {
                for (int i = sdkBaseEventHandlers.Count - 1; i >= 0; --i)
                {
                    if (sdkBaseEventHandlers[i] as VRCSDK2.VRC_EventHandler)
                    {
                        sdkBaseEventHandlers.RemoveAt(i);
                    }
                }
            }
#endif
            if (sdkBaseEventHandlers.Count > 0)
            {
                _builder.OnGUIError(scene,
                                    "You have Event Handlers in your scene that are not allowed in this build configuration.",
                                    delegate
                {
                    List <Object> gos = sdkBaseEventHandlers.ConvertAll(item => (Object)item.gameObject);
                    Selection.objects = gos.ToArray();
                },
                                    delegate
                {
                    foreach (VRC_EventHandler eh in sdkBaseEventHandlers)
                    {
#if VRC_SDK_VRCSDK2
                        GameObject go = eh.gameObject;
                        if (isSdk3Scene == false)
                        {
                            if (VRC_SceneDescriptor.Instance as VRCSDK2.VRC_SceneDescriptor != null)
                            {
                                go.AddComponent <VRCSDK2.VRC_EventHandler>();
                            }
                        }
#endif
                        Object.DestroyImmediate(eh);
                    }
                });
            }

            Vector3 g = Physics.gravity;
            if (Math.Abs(g.x) > float.Epsilon || Math.Abs(g.z) > float.Epsilon)
            {
                _builder.OnGUIWarning(scene,
                                      "Gravity vector is not straight down. Though we support different gravity, player orientation is always 'upwards' so things don't always behave as you intend.",
                                      delegate { SettingsService.OpenProjectSettings("Project/Physics"); }, null);
            }
            if (g.y > 0)
            {
                _builder.OnGUIWarning(scene,
                                      "Gravity vector is not straight down, inverted or zero gravity will make walking extremely difficult.",
                                      delegate { SettingsService.OpenProjectSettings("Project/Physics"); }, null);
            }
            if (Math.Abs(g.y) < float.Epsilon)
            {
                _builder.OnGUIWarning(scene,
                                      "Zero gravity will make walking extremely difficult, though we support different gravity, player orientation is always 'upwards' so this may not have the effect you're looking for.",
                                      delegate { SettingsService.OpenProjectSettings("Project/Physics"); }, null);
            }

            if (CheckFogSettings())
            {
                _builder.OnGUIWarning(
                    scene,
                    "Fog shader stripping is set to Custom, this may lead to incorrect or unnecessary shader variants being included in the build. You should use Automatic unless you change the fog mode at runtime.",
                    delegate { SettingsService.OpenProjectSettings("Project/Graphics"); },
                    delegate
                {
                    EnvConfig.SetFogSettings(
                        new EnvConfig.FogSettings(EnvConfig.FogSettings.FogStrippingMode.Automatic));
                });
            }

            if (scene.autoSpatializeAudioSources)
            {
                _builder.OnGUIWarning(scene,
                                      "Your scene previously used the 'Auto Spatialize Audio Sources' feature. This has been deprecated, press 'Fix' to disable. Also, please add VRC_SpatialAudioSource to all your audio sources. Make sure Spatial Blend is set to 3D for the sources you want to spatialize.",
                                      null,
                                      delegate { scene.autoSpatializeAudioSources = false; }
                                      );
            }

            AudioSource[] audioSources = Object.FindObjectsOfType <AudioSource>();
            foreach (AudioSource a in audioSources)
            {
                if (a.GetComponent <ONSPAudioSource>() != null)
                {
                    _builder.OnGUIWarning(scene,
                                          "Found audio source(s) using ONSP, this is deprecated. Press 'fix' to convert to VRC_SpatialAudioSource.",
                                          delegate { Selection.activeObject = a.gameObject; },
                                          delegate
                    {
                        Selection.activeObject = a.gameObject;
                        AutoAddSpatialAudioComponents.ConvertONSPAudioSource(a);
                    }
                                          );
                    break;
                }
                else if (a.GetComponent <VRC_SpatialAudioSource>() == null)
                {
                    string msg =
                        "Found 3D audio source with no VRC Spatial Audio component, this is deprecated. Press 'fix' to add a VRC_SpatialAudioSource.";
                    if (IsAudioSource2D(a))
                    {
                        msg =
                            "Found 2D audio source with no VRC Spatial Audio component, this is deprecated. Press 'fix' to add a (disabled) VRC_SpatialAudioSource.";
                    }

                    _builder.OnGUIWarning(scene, msg,
                                          delegate { Selection.activeObject = a.gameObject; },
                                          delegate
                    {
                        Selection.activeObject = a.gameObject;
                        AutoAddSpatialAudioComponents.AddVRCSpatialToBareAudioSource(a);
                    }
                                          );
                    break;
                }
            }

            if (VRCSdkControlPanel.HasSubstances())
            {
                _builder.OnGUIWarning(scene,
                                      "One or more scene objects have Substance materials. This is not supported and may break in game. Please bake your Substances to regular materials.",
                                      () => { Selection.objects = VRCSdkControlPanel.GetSubstanceObjects(); },
                                      null);
            }

#if VRC_SDK_VRCSDK2
            foreach (VRC_DataStorage ds in Object.FindObjectsOfType <VRC_DataStorage>())
            {
                VRCSDK2.VRC_ObjectSync os = ds.GetComponent <VRCSDK2.VRC_ObjectSync>();
                if (os != null && os.SynchronizePhysics)
                {
                    _builder.OnGUIWarning(scene, ds.name + " has a VRC_DataStorage and VRC_ObjectSync, with SynchronizePhysics enabled.",
                                          delegate { Selection.activeObject = os.gameObject; }, null);
                }
            }
#else
            foreach (VRC.SDK3.Components.VRCObjectSync os in Object.FindObjectsOfType <VRC.SDK3.Components.VRCObjectSync>())
            {
                if (os.GetComponents <VRC.Udon.UdonBehaviour>().Any((ub) => ub.Reliable))
                {
                    _builder.OnGUIError(scene, "Object Sync cannot share an object with a manually synchronized Udon Behaviour",
                                        delegate { Selection.activeObject = os.gameObject; }, null);
                }
                if (os.GetComponent <VRC.SDK3.Components.VRCObjectPool>() != null)
                {
                    _builder.OnGUIError(scene, "Object Sync cannot share an object with an object pool",
                                        delegate { Selection.activeObject = os.gameObject; }, null);
                }
            }
#endif

            string vrcFilePath = UnityWebRequest.UnEscapeURL(EditorPrefs.GetString("lastVRCPath"));
            if (!string.IsNullOrEmpty(vrcFilePath) &&
                ValidationHelpers.CheckIfAssetBundleFileTooLarge(ContentType.World, vrcFilePath, out int fileSize))
            {
                _builder.OnGUIWarning(scene,
                                      ValidationHelpers.GetAssetBundleOverSizeLimitMessageSDKWarning(ContentType.World, fileSize), null,
                                      null);
            }

            foreach (GameObject go in Object.FindObjectsOfType <GameObject>())
            {
                if (go.transform.parent == null)
                {
                    // check root game objects
#if UNITY_ANDROID
                    IEnumerable <Shader> illegalShaders = VRC.SDKBase.Validation.WorldValidation.FindIllegalShaders(go);
                    foreach (Shader s in illegalShaders)
                    {
                        _builder.OnGUIWarning(scene, "World uses unsupported shader '" + s.name + "'. This could cause low performance or future compatibility issues.", null, null);
                    }
#endif
                }
                else
                {
                    // Check sibling game objects
                    for (int idx = 0; idx < go.transform.parent.childCount; ++idx)
                    {
                        Transform t = go.transform.parent.GetChild(idx);
                        if (t == go.transform)
                        {
                            continue;
                        }

#if VRC_SDK_VRCSDK2
                        bool allowedType = (t.GetComponent <VRCSDK2.VRC_ObjectSync>() ||
                                            t.GetComponent <VRCSDK2.VRC_SyncAnimation>() ||
                                            t.GetComponent <VRCSDK2.VRC_SyncVideoPlayer>() ||
                                            t.GetComponent <VRCSDK2.VRC_SyncVideoStream>());
                        if (t.name != go.transform.name || allowedType)
                        {
                            continue;
                        }
#else
                        if (t.name != go.transform.name)
                        {
                            continue;
                        }
#endif

                        string    path = t.name;
                        Transform p    = t.parent;
                        while (p != null)
                        {
                            path = p.name + "/" + path;
                            p    = p.parent;
                        }

                        _builder.OnGUIWarning(scene,
                                              "Sibling objects share the same path, which may break network events: " + path,
                                              delegate
                        {
                            List <Object> gos = new List <Object>();
                            for (int c = 0; c < go.transform.parent.childCount; ++c)
                            {
                                if (go.transform.parent.GetChild(c).name == go.name)
                                {
                                    gos.Add(go.transform.parent.GetChild(c).gameObject);
                                }
                            }
                            Selection.objects = gos.ToArray();
                        },
                                              delegate
                        {
                            List <Object> gos = new List <Object>();
                            for (int c = 0; c < go.transform.parent.childCount; ++c)
                            {
                                if (go.transform.parent.GetChild(c).name == go.name)
                                {
                                    gos.Add(go.transform.parent.GetChild(c).gameObject);
                                }
                            }
                            Selection.objects = gos.ToArray();
                            for (int i = 0; i < gos.Count; ++i)
                            {
                                gos[i].name = gos[i].name + "-" + i.ToString("00");
                            }
                        });
                        break;
                    }
                }
            }

            // detect dynamic materials and prefabs with identical names (since these could break triggers)
            VRC_Trigger[]     triggers  = Tools.FindSceneObjectsOfTypeAll <VRC_Trigger>();
            List <GameObject> prefabs   = new List <GameObject>();
            List <Material>   materials = new List <Material>();

#if VRC_SDK_VRCSDK2
            AssetExporter.FindDynamicContent(ref prefabs, ref materials);
#elif VRC_SDK_VRCSDK3
            AssetExporter.FindDynamicContent(ref prefabs, ref materials);
#endif

            foreach (VRC_Trigger t in triggers)
            {
                foreach (VRC_Trigger.TriggerEvent triggerEvent in t.Triggers)
                {
                    foreach (VRC_EventHandler.VrcEvent e in triggerEvent.Events.Where(evt =>
                                                                                      evt.EventType == VRC_EventHandler.VrcEventType.SpawnObject))
                    {
                        GameObject go =
                            AssetDatabase.LoadAssetAtPath(e.ParameterString, typeof(GameObject)) as GameObject;
                        if (go == null)
                        {
                            continue;
                        }
                        foreach (GameObject existing in prefabs)
                        {
                            if (go == existing || go.name != existing.name)
                            {
                                continue;
                            }
                            _builder.OnGUIWarning(scene,
                                                  "Trigger prefab '" + AssetDatabase.GetAssetPath(go).Replace(".prefab", "") +
                                                  "' has same name as a prefab in another folder. This may break the trigger.",
                                                  delegate { Selection.objects = new Object[] { go }; },
                                                  delegate
                            {
                                AssetDatabase.RenameAsset(AssetDatabase.GetAssetPath(go),
                                                          go.name + "-" + go.GetInstanceID());
                                AssetDatabase.Refresh();
                                e.ParameterString = AssetDatabase.GetAssetPath(go);
                            });
                        }
                    }

                    foreach (VRC_EventHandler.VrcEvent e in triggerEvent.Events.Where(evt =>
                                                                                      evt.EventType == VRC_EventHandler.VrcEventType.SetMaterial))
                    {
                        Material mat = AssetDatabase.LoadAssetAtPath <Material>(e.ParameterString);
                        if (mat == null || mat.name.Contains("(Instance)"))
                        {
                            continue;
                        }
                        foreach (Material existing in materials)
                        {
                            if (mat == existing || mat.name != existing.name)
                            {
                                continue;
                            }
                            _builder.OnGUIWarning(scene,
                                                  "Trigger material '" + AssetDatabase.GetAssetPath(mat).Replace(".mat", "") +
                                                  "' has same name as a material in another folder. This may break the trigger.",
                                                  delegate { Selection.objects = new Object[] { mat }; },
                                                  delegate
                            {
                                AssetDatabase.RenameAsset(AssetDatabase.GetAssetPath(mat),
                                                          mat.name + "-" + mat.GetInstanceID());
                                AssetDatabase.Refresh();
                                e.ParameterString = AssetDatabase.GetAssetPath(mat);
                            });
                        }
                    }
                }
            }
        }
Esempio n. 5
0
        public static void ExportCurrentSceneResource()
        {
            //IL_001e: Unknown result type (might be due to invalid IL or missing references)
            //IL_0023: Unknown result type (might be due to invalid IL or missing references)
            //IL_00b7: Unknown result type (might be due to invalid IL or missing references)
            //IL_00bc: Unknown result type (might be due to invalid IL or missing references)
            //IL_00e7: Unknown result type (might be due to invalid IL or missing references)
            //IL_00f9: Unknown result type (might be due to invalid IL or missing references)
            //IL_0104: Unknown result type (might be due to invalid IL or missing references)
            //IL_0109: Unknown result type (might be due to invalid IL or missing references)
            //IL_017f: Unknown result type (might be due to invalid IL or missing references)
            //IL_0184: Unknown result type (might be due to invalid IL or missing references)
            //IL_0186: Unknown result type (might be due to invalid IL or missing references)
            //IL_018b: Unknown result type (might be due to invalid IL or missing references)
            //IL_0193: Unknown result type (might be due to invalid IL or missing references)
            //IL_019e: Unknown result type (might be due to invalid IL or missing references)
            //IL_01a0: Unknown result type (might be due to invalid IL or missing references)
            object text;

            if (EditorPrefs.HasKey("originalScenePath"))
            {
                text = EditorPrefs.GetString("originalScenePath");
            }
            else
            {
                Scene activeScene = SceneManager.GetActiveScene();
                text = activeScene.get_path();
            }
            string path = (string)text;
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
            string text2 = null;

            VRC_SceneDescriptor[] array = Tools.FindSceneObjectsOfTypeAll <VRC_SceneDescriptor>();
            if (array == null || array.Length != 1)
            {
                EditorUtility.DisplayDialog("Build Custom Scene", "Scene needs exactly one VRC_SceneDescriptor", "Ok");
            }
            else
            {
                VRC_SceneDescriptor val = array[0];
                if (val == null)
                {
                    EditorUtility.DisplayDialog("Build Custom Scene", "You must place a VRC_SceneDescriptor on the root of you custom scene", "Ok");
                }
                else if (val.spawns.Length < 1)
                {
                    EditorUtility.DisplayDialog("Build Custom Scene", "You must add at least one spawn to spawns in your VRC_SceneDescriptor.", "Ok");
                }
                else
                {
                    FindDynamicContent(val);
                    val.gravity           = Physics.get_gravity();
                    val.layerCollisionArr = UpdateLayers.GetLayerCollisionArray();
                    val.unityVersion      = Application.get_unityVersion();
                    EditorUtility.SetDirty(val);
                    EditorSceneManager.MarkSceneDirty(val.get_gameObject().get_scene());
                    EditorSceneManager.SaveScene(val.get_gameObject().get_scene());
                    try
                    {
                        Scene  activeScene2 = SceneManager.GetActiveScene();
                        string text3        = activeScene2.get_path();
                        string text4        = fileNameWithoutExtension;
                        bool   flag         = false;
                        if (text4.Contains("."))
                        {
                            flag = true;
                            string text5 = "Assets/customTmpScene12345.unity";
                            AssetDatabase.CopyAsset(text3, text5);
                            text3 = text5;
                            AssetDatabase.Refresh();
                        }
                        AssetDatabase.RemoveUnusedAssetBundleNames();
                        string        text6  = "customscene.vrcw";
                        AssetImporter atPath = AssetImporter.GetAtPath(text3);
                        atPath.set_assetBundleName(text6);
                        atPath.SaveAndReimport();
                        text2 = Application.get_temporaryCachePath() + "/" + text6;
                        BuildTarget      activeBuildTarget        = EditorUserBuildSettings.get_activeBuildTarget();
                        BuildTargetGroup selectedBuildTargetGroup = EditorUserBuildSettings.get_selectedBuildTargetGroup();
                        BuildPipeline.BuildAssetBundles(Application.get_temporaryCachePath(), 0, EditorUserBuildSettings.get_activeBuildTarget());
                        EditorUserBuildSettings.SwitchActiveBuildTarget(selectedBuildTargetGroup, activeBuildTarget);
                        EditorPrefs.SetString("currentBuildingAssetBundlePath", text2);
                        EditorPrefs.SetString("lastVRCPath", text2);
                        atPath.set_assetBundleName(string.Empty);
                        atPath.SaveAndReimport();
                        if (flag)
                        {
                            AssetDatabase.DeleteAsset(text3);
                        }
                        AssetDatabase.RemoveUnusedAssetBundleNames();
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError((object)("Export Exception - " + ex.ToString()));
                        throw ex;
                        IL_0205 :;
                    }
                    if (text2 != null)
                    {
                        VRC_Editor.RecordActivity("scene", Path.GetFileName(text2));
                    }
                }
            }
        }
Esempio n. 6
0
        private static void SetupBasicPostProcessing(VRC_SceneDescriptor descriptor)
        {
#if UNITY_POST_PROCESSING_STACK_V2
            if (!UpdateLayers.AreLayersSetup())
            {
                EditorUtility.DisplayDialog("Layers Missing", "Start by setting up your layers in the VRCSDK builder tab", "OK");
            }
            else
            {
                if (EditorUtility.DisplayDialog("Setup Post Processing?", "This will setup your scenes Reference Camera and make a new global volume using the included example Post Processing Profile", "OK", "Cancel"))
                {
                    //Check if reference camera exists
                    if (!descriptor.ReferenceCamera)
                    {
                        if (Camera.main == null)
                        {
                            GameObject camera = new GameObject("Main Camera");
                            camera.AddComponent <Camera>();
                            camera.AddComponent <AudioListener>();
                            camera.tag = "MainCamera";
                        }
                        descriptor.ReferenceCamera = Camera.main.gameObject;
                    }

                    //Use PostProcessing layer if it exists otherwise use Water
                    var layer = LayerMask.NameToLayer("PostProcessing") > -1 ? "PostProcessing" : "Water";

                    //Make sure the Post Process Layer exists and set it up
                    if (!descriptor.ReferenceCamera.gameObject.GetComponent <PostProcessLayer>())
                    {
                        descriptor.ReferenceCamera.gameObject.AddComponent(typeof(PostProcessLayer));
                    }
                    var postprocessLayer = descriptor.ReferenceCamera.gameObject.GetComponent(typeof(PostProcessLayer)) as PostProcessLayer;
                    postprocessLayer.volumeLayer = LayerMask.GetMask(layer);

                    //Copy the example profile to the Post Processing folder
                    if (!Directory.Exists("Assets/Post Processing"))
                    {
                        AssetDatabase.CreateFolder("Assets", "Post Processing");
                    }
                    if (AssetDatabase.LoadAssetAtPath("Assets/Post Processing/SilentProfile.asset", typeof(PostProcessProfile)) == null)
                    {
                        var path = AssetDatabase.GUIDToAssetPath("eaac6f7291834264f97854154e89bf76");
                        if (path != null)
                        {
                            AssetDatabase.CopyAsset(path, "Assets/Post Processing/SilentProfile.asset");
                        }
                    }

                    //Set up the post process volume
                    var volume = GameObject.Instantiate(PostProcessManager.instance.QuickVolume(16, 100f));
                    if (File.Exists("Assets/Post Processing/SilentProfile.asset"))
                    {
                        volume.sharedProfile = (PostProcessProfile)AssetDatabase.LoadAssetAtPath("Assets/Post Processing/SilentProfile.asset", typeof(PostProcessProfile));
                    }
                    volume.gameObject.name  = "Post Processing Volume";
                    volume.gameObject.layer = LayerMask.NameToLayer(layer);

                    //Mark the scene as dirty for saving
                    EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                }
            }
#endif
        }