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); } } //受信と更新のタイミングは切り離した } } }