internal void OnDeserializingMethod(StreamingContext context)
 {
     CurrentPathOnSettingFileDialog        = "";
     CurrentPathOnVRMFileDialog            = "";
     CurrentPathOnExternalCameraFileDialog = "";
     CurrentPathOnCameraPlusFileDialog     = "";
     LastCalibrateType         = PipeCommands.CalibrateType.Default;
     EnableCalibrationEndSound = false;
 }
    void OnDataReceived(uOSC.Message message)
    {
        //有効なとき以外処理しない
        if (this.isActiveAndEnabled)
        {
            //仮想コントローラー V2.3
            if (message.address == "/VMC/Ext/Con/Pos" &&
                (message.values[0] is string) &&
                (message.values[1] is float) &&
                (message.values[2] is float) &&
                (message.values[3] is float) &&
                (message.values[4] is float) &&
                (message.values[5] is float) &&
                (message.values[6] is float) &&
                (message.values[7] is float)
                )
            {
                string serial         = (string)message.values[0];
                var    rigidTransform = SetTransform(ref pos, ref rot, ref message);

                lock (LockObject)
                {
                    if (virtualController.ContainsKey(serial))
                    {
                        virtualController[serial] = rigidTransform;
                    }
                    else
                    {
                        virtualController.Add(serial, rigidTransform);
                        virtualControllerFiltered.Add(serial, rigidTransform);
                    }
                }
            }
            //仮想トラッカー V2.3
            else if ((message.address == "/VMC/Ext/Hmd/Pos" ||
                      message.address == "/VMC/Ext/Tra/Pos") &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float)
                     )
            {
                string serial         = (string)message.values[0];
                var    rigidTransform = SetTransform(ref pos, ref rot, ref message);

                lock (LockObject)
                {
                    if (virtualTracker.ContainsKey(serial))
                    {
                        virtualTracker[serial] = rigidTransform;
                    }
                    else
                    {
                        virtualTracker.Add(serial, rigidTransform);
                        virtualTrackerFiltered.Add(serial, rigidTransform);
                    }
                }
            }
            //フレーム設定 V2.3
            else if (message.address == "/VMC/Ext/Set/Period" &&
                     (message.values[0] is int) &&
                     (message.values[1] is int) &&
                     (message.values[2] is int) &&
                     (message.values[3] is int) &&
                     (message.values[4] is int) &&
                     (message.values[5] is int)
                     )
            {
                externalSender.periodStatus     = (int)message.values[0];
                externalSender.periodRoot       = (int)message.values[1];
                externalSender.periodBone       = (int)message.values[2];
                externalSender.periodBlendShape = (int)message.values[3];
                externalSender.periodCamera     = (int)message.values[4];
                externalSender.periodDevices    = (int)message.values[5];
            }
            //Virtual MIDI CC V2.3
            else if (message.address == "/VMC/Ext/Midi/CC/Val" &&
                     (message.values[0] is int) &&
                     (message.values[1] is float)
                     )
            {
                MIDICCWrapper.KnobUpdated(0, (int)message.values[0], (float)message.values[1]);
            }
            //Camera Control V2.3
            else if (message.address == "/VMC/Ext/Cam" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float) &&
                     (message.values[8] is float)
                     )
            {
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];
                rot.x = (float)message.values[4];
                rot.y = (float)message.values[5];
                rot.z = (float)message.values[6];
                rot.w = (float)message.values[7];
                float fov = (float)message.values[8];

                //FreeCameraじゃなかったらFreeCameraにする
                if (ControlWPFWindow.CurrentSettings.CameraType != UnityMemoryMappedFile.CameraTypes.Free)
                {
                    window.ChangeCamera(UnityMemoryMappedFile.CameraTypes.Free);
                }

                //カメラ制御を切る
                window.FreeCamera.GetComponent <CameraMouseControl>().enabled = false;

                //座標とFOVを適用
                window.FreeCamera.transform.position = pos;
                window.FreeCamera.transform.rotation = rot;
                window.FreeCamera.fieldOfView        = fov;
            } //ブレンドシェープ同期
            else if (message.address == "/VMC/Ext/Blend/Val" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float)
                     )
            {
                blendShapeBuffer[new BlendShapeKey((string)message.values[0])] = (float)message.values[1];
            }
            //ブレンドシェープ適用
            else if (message.address == "/VMC/Ext/Blend/Apply")
            {
                faceController.MixPresets(nameof(ExternalReceiverForVMC), blendShapeBuffer.Keys.ToArray(), blendShapeBuffer.Values.ToArray());
                blendShapeBuffer.Clear();
            }//外部アイトラ V2.3
            else if (message.address == "/VMC/Ext/Set/Eye" &&
                     (message.values[0] is int) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float)
                     )
            {
                bool enable = ((int)message.values[0]) != 0;
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];

                if (enable)
                {
                    //ターゲットが存在しなければ作る
                    if (lookTargetOSC == null)
                    {
                        lookTargetOSC = new GameObject();
                        lookTargetOSC.transform.parent = null;
                        lookTargetOSC.name             = "lookTargetOSC";
                    }
                    //位置を書き込む
                    if (lookTargetOSC.transform != null)
                    {
                        lookTargetOSC.transform.position = pos;
                    }

                    //視線に書き込む
                    if (vrmLookAtHead != null && setFaceApplyAction == false)
                    {
                        faceController.BeforeApply += beforeFaceApply;
                        setFaceApplyAction          = true;
                    }
                }
                else
                {
                    //視線を止める
                    if (vrmLookAtHead != null && setFaceApplyAction == true)
                    {
                        faceController.BeforeApply -= beforeFaceApply;
                        setFaceApplyAction          = false;
                    }
                }
            }
            //情報要求 V2.4
            else if (message.address == "/VMC/Ext/Set/Req")
            {
                externalSender.SendPerLowRate(); //即時送信
            }
            //情報表示 V2.4
            else if (message.address == "/VMC/Ext/Set/Res" && (message.values[0] is string))
            {
                statusString = (string)message.values[0];
            }
            //キャリブレーション準備 V2.5
            else if (message.address == "/VMC/Ext/Set/Calib/Ready")
            {
                if (File.Exists(ControlWPFWindow.CurrentSettings.VRMPath))
                {
                    window.ImportVRM(ControlWPFWindow.CurrentSettings.VRMPath, true, true, true);
                }
            }
            //キャリブレーション実行 V2.5
            else if (message.address == "/VMC/Ext/Set/Calib/Exec" && (message.values[0] is int))
            {
                PipeCommands.CalibrateType calibrateType = PipeCommands.CalibrateType.Default;

                switch ((int)message.values[0])
                {
                case 0:
                    calibrateType = PipeCommands.CalibrateType.Default;
                    break;

                case 1:
                    calibrateType = PipeCommands.CalibrateType.FixedHand;
                    break;

                case 2:
                    calibrateType = PipeCommands.CalibrateType.FixedHandWithGround;
                    break;

                default: return;     //無視
                }
                StartCoroutine(window.Calibrate(calibrateType));
                Invoke("EndCalibrate", 2f);
            }
            //設定読み込み V2.5
            else if (message.address == "/VMC/Ext/Set/Config" && (message.values[0] is string))
            {
                string path = (string)message.values[0];
                if (File.Exists(path))
                {
                    //なぜか時間がかかる
                    window.LoadSettings(path);
                }
            }
        }
    }
    void OnDataReceived(uOSC.Message message)
    {
        //有効なとき以外処理しない
        if (this.isActiveAndEnabled)
        {
            //生存チェックのためのパケットカウンタ
            packets++;
            if (packets > int.MaxValue / 2)
            {
                packets = 0;
            }

            //仮想コントローラー V2.3
            if (message.address == "/VMC/Ext/Con/Pos" &&
                (message.values[0] is string) &&
                (message.values[1] is float) &&
                (message.values[2] is float) &&
                (message.values[3] is float) &&
                (message.values[4] is float) &&
                (message.values[5] is float) &&
                (message.values[6] is float) &&
                (message.values[7] is float)
                )
            {
                string serial         = (string)message.values[0];
                var    rigidTransform = SetTransform(ref pos, ref rot, ref message);

                lock (LockObject)
                {
                    if (virtualController.ContainsKey(serial))
                    {
                        virtualController[serial] = rigidTransform;
                    }
                    else
                    {
                        virtualController.Add(serial, rigidTransform);
                        virtualControllerFiltered.Add(serial, rigidTransform);
                    }
                }
            }
            //仮想トラッカー V2.3
            else if ((message.address == "/VMC/Ext/Hmd/Pos" ||
                      message.address == "/VMC/Ext/Tra/Pos") &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float)
                     )
            {
                string serial         = (string)message.values[0];
                var    rigidTransform = SetTransform(ref pos, ref rot, ref message);

                lock (LockObject)
                {
                    if (virtualTracker.ContainsKey(serial))
                    {
                        virtualTracker[serial] = rigidTransform;
                    }
                    else
                    {
                        virtualTracker.Add(serial, rigidTransform);
                        virtualTrackerFiltered.Add(serial, rigidTransform);
                    }
                }
            }
            //フレーム設定 V2.3
            else if (message.address == "/VMC/Ext/Set/Period" &&
                     (message.values[0] is int) &&
                     (message.values[1] is int) &&
                     (message.values[2] is int) &&
                     (message.values[3] is int) &&
                     (message.values[4] is int) &&
                     (message.values[5] is int)
                     )
            {
                externalSender.periodStatus     = (int)message.values[0];
                externalSender.periodRoot       = (int)message.values[1];
                externalSender.periodBone       = (int)message.values[2];
                externalSender.periodBlendShape = (int)message.values[3];
                externalSender.periodCamera     = (int)message.values[4];
                externalSender.periodDevices    = (int)message.values[5];
            }
            //Virtual MIDI CC V2.3
            else if (message.address == "/VMC/Ext/Midi/CC/Val" &&
                     (message.values[0] is int) &&
                     (message.values[1] is float)
                     )
            {
                MIDICCWrapper.KnobUpdated(0, (int)message.values[0], (float)message.values[1]);
            }
            //Camera Control V2.3
            else if (message.address == "/VMC/Ext/Cam" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float) &&
                     (message.values[8] is float)
                     )
            {
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];
                rot.x = (float)message.values[4];
                rot.y = (float)message.values[5];
                rot.z = (float)message.values[6];
                rot.w = (float)message.values[7];
                float fov = (float)message.values[8];

                //FreeCameraじゃなかったらFreeCameraにする
                if (ControlWPFWindow.CurrentSettings.CameraType != UnityMemoryMappedFile.CameraTypes.Free)
                {
                    window.ChangeCamera(UnityMemoryMappedFile.CameraTypes.Free);
                }

                //カメラ制御を切る
                window.FreeCamera.GetComponent <CameraMouseControl>().enabled = false;

                //座標とFOVを適用
                window.FreeCamera.transform.localPosition = pos;
                window.FreeCamera.transform.localRotation = rot;
                window.ControlCamera.fieldOfView          = fov;
            } //ブレンドシェープ同期
            else if (message.address == "/VMC/Ext/Blend/Val" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float)
                     )
            {
                blendShapeBuffer[(string)message.values[0]] = (float)message.values[1];
            }
            //ブレンドシェープ適用
            else if (message.address == "/VMC/Ext/Blend/Apply")
            {
                faceController.MixPresets(nameof(ExternalReceiverForVMC), blendShapeBuffer.Keys.ToArray(), blendShapeBuffer.Values.ToArray());
                blendShapeBuffer.Clear();
            }//外部アイトラ V2.3
            else if (message.address == "/VMC/Ext/Set/Eye" &&
                     (message.values[0] is int) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float)
                     )
            {
                bool enable = ((int)message.values[0]) != 0;
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];

                if (enable)
                {
                    //ターゲットが存在しなければ作る
                    if (lookTargetOSC == null)
                    {
                        lookTargetOSC      = new GameObject();
                        lookTargetOSC.name = "lookTargetOSC";
                    }
                    //位置を書き込む
                    if (lookTargetOSC.transform != null)
                    {
                        lookTargetOSC.transform.parent        = headTransform;
                        lookTargetOSC.transform.localPosition = pos;
                    }

                    //視線に書き込む
                    if (vrmLookAtHead != null && setFaceApplyAction == false)
                    {
                        faceController.BeforeApply += beforeFaceApply;
                        setFaceApplyAction          = true;
                    }
                }
                else
                {
                    //視線を止める
                    if (vrmLookAtHead != null && setFaceApplyAction == true)
                    {
                        faceController.BeforeApply -= beforeFaceApply;
                        setFaceApplyAction          = false;
                    }
                }
            }
            //情報要求 V2.4
            else if (message.address == "/VMC/Ext/Set/Req")
            {
                if (externalSender.isActiveAndEnabled && externalSender.uClient != null)
                {
                    externalSender.SendPerLowRate(); //即時送信
                }
            }
            //情報表示 V2.4
            else if (message.address == "/VMC/Ext/Set/Res" && (message.values[0] is string))
            {
                statusString = (string)message.values[0];
            }
            //キャリブレーション準備 V2.5
            else if (message.address == "/VMC/Ext/Set/Calib/Ready")
            {
                if (File.Exists(ControlWPFWindow.CurrentSettings.VRMPath))
                {
                    window.ImportVRM(ControlWPFWindow.CurrentSettings.VRMPath, true, true, true);
                }
            }
            //キャリブレーション実行 V2.5
            else if (message.address == "/VMC/Ext/Set/Calib/Exec" && (message.values[0] is int))
            {
                PipeCommands.CalibrateType calibrateType = PipeCommands.CalibrateType.Default;

                switch ((int)message.values[0])
                {
                case 0:
                    calibrateType = PipeCommands.CalibrateType.Default;
                    break;

                case 1:
                    calibrateType = PipeCommands.CalibrateType.FixedHand;
                    break;

                case 2:
                    calibrateType = PipeCommands.CalibrateType.FixedHandWithGround;
                    break;

                default: return;     //無視
                }
                StartCoroutine(window.Calibrate(calibrateType));
                Invoke("EndCalibrate", 2f);
            }
            //設定読み込み V2.5
            else if (message.address == "/VMC/Ext/Set/Config" && (message.values[0] is string))
            {
                string path = (string)message.values[0];
                if (File.Exists(path))
                {
                    //なぜか時間がかかる
                    window.LoadSettings(path);
                }
            }
            //スルー情報 V2.6
            else if (message.address != null && message.address.StartsWith("/VMC/Thru/"))
            {
                //転送する
                if (externalSender.isActiveAndEnabled && externalSender.uClient != null)
                {
                    externalSender.uClient.Send(message.address, message.values);
                }
            }
            //Directional Light V2.9
            else if (message.address == "/VMC/Ext/Light" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float) &&
                     (message.values[8] is float) &&
                     (message.values[9] is float) &&
                     (message.values[10] is float) &&
                     (message.values[11] is float)
                     )
            {
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];
                rot.x = (float)message.values[4];
                rot.y = (float)message.values[5];
                rot.z = (float)message.values[6];
                rot.w = (float)message.values[7];
                float r = (float)message.values[8];
                float g = (float)message.values[9];
                float b = (float)message.values[10];
                float a = (float)message.values[11];

                window.MainDirectionalLight.color             = new Color(r, g, b, a);
                window.MainDirectionalLightTransform.position = pos;
                window.MainDirectionalLightTransform.rotation = rot;
            }

            //ボーン姿勢
            else if (message.address == "/VMC/Ext/Bone/Pos" &&
                     (message.values[0] is string) &&
                     (message.values[1] is float) &&
                     (message.values[2] is float) &&
                     (message.values[3] is float) &&
                     (message.values[4] is float) &&
                     (message.values[5] is float) &&
                     (message.values[6] is float) &&
                     (message.values[7] is float)
                     )
            {
                string boneName = (string)message.values[0];
                pos.x = (float)message.values[1];
                pos.y = (float)message.values[2];
                pos.z = (float)message.values[3];
                rot.x = (float)message.values[4];
                rot.y = (float)message.values[5];
                rot.z = (float)message.values[6];
                rot.w = (float)message.values[7];

                //Humanoidボーンに該当するボーンがあるか調べる
                HumanBodyBones bone;
                if (HumanBodyBonesTryParse(ref boneName, out bone))
                {
                    //あれば位置と回転をキャッシュする
                    if (HumanBodyBonesPositionTable.ContainsKey(bone))
                    {
                        HumanBodyBonesPositionTable[bone] = pos;
                    }
                    else
                    {
                        HumanBodyBonesPositionTable.Add(bone, pos);
                    }

                    if (HumanBodyBonesRotationTable.ContainsKey(bone))
                    {
                        HumanBodyBonesRotationTable[bone] = rot;
                    }
                    else
                    {
                        HumanBodyBonesRotationTable.Add(bone, rot);
                    }
                }
                //受信と更新のタイミングは切り離した
            }
        }
    }