From 0e2922d9a24cac434e16b66e227f9002fb976e12 Mon Sep 17 00:00:00 2001 From: antpb Date: Wed, 2 Aug 2023 21:52:54 -0500 Subject: [PATCH] V 1.5.0 - Audio Block (#57) * dont lose the nights work * add audio block frontend and icons * adds changelog --- .../components/EnvironmentFront.js | 113 ++++++++++++++ blocks/environment/components/Player.js | 6 +- .../environment/components/ThreeObjectEdit.js | 146 ++++++++++++++++++ .../components/core/front/ThreeAudio.js | 81 ++++++++++ blocks/environment/frontend.js | 4 + blocks/three-audio-block/Edit.js | 102 ++++++++---- blocks/three-audio-block/Save.js | 35 ++++- blocks/three-audio-block/block.json | 36 ++--- inc/assets/audio_icon.png | Bin 0 -> 5322 bytes php/Plugin.php | 1 + readme.txt | 6 +- three-object-viewer.php | 2 +- 12 files changed, 468 insertions(+), 64 deletions(-) create mode 100644 blocks/environment/components/core/front/ThreeAudio.js create mode 100644 inc/assets/audio_icon.png diff --git a/blocks/environment/components/EnvironmentFront.js b/blocks/environment/components/EnvironmentFront.js index 4a38ff5..ddd4e4e 100644 --- a/blocks/environment/components/EnvironmentFront.js +++ b/blocks/environment/components/EnvironmentFront.js @@ -35,6 +35,7 @@ import { BoxGeometry } from "three"; import { ThreeImage } from "./core/front/ThreeImage"; import { ThreeVideo } from "./core/front/ThreeVideo"; +import { ThreeAudio } from "./core/front/ThreeAudio"; import { ModelObject } from "./core/front/ModelObject"; import { NPCObject } from "./core/front/NPCObject"; import { Portal } from "./core/front/Portal"; @@ -1089,6 +1090,118 @@ export default function EnvironmentFront(props) { /> ); })} + {Object.values(props.audiosToAdd).map((item, index) => { + const audioPosX = item.querySelector("p.audio-block-positionX") + ? item.querySelector("p.audio-block-positionX").innerText + : ""; + + const audioPosY = item.querySelector("p.audio-block-positionY") + ? item.querySelector("p.audio-block-positionY").innerText + : ""; + + const audioPosZ = item.querySelector("p.audio-block-positionZ") + ? item.querySelector("p.audio-block-positionZ").innerText + : ""; + + const audioScaleX = item.querySelector("p.audio-block-scaleX") + ? item.querySelector("p.audio-block-scaleX").innerText + : ""; + + const audioScaleY = item.querySelector("p.audio-block-scaleY") + ? item.querySelector("p.audio-block-scaleY").innerText + : ""; + + const audioScaleZ = item.querySelector("p.audio-block-scaleZ") + ? item.querySelector("p.audio-block-scaleZ").innerText + : ""; + + const audioRotationX = item.querySelector("p.audio-block-rotationX") + ? item.querySelector("p.audio-block-rotationX").innerText + : ""; + + const audioRotationY = item.querySelector("p.audio-block-rotationY") + ? item.querySelector("p.audio-block-rotationY").innerText + : ""; + + const audioRotationZ = item.querySelector("p.audio-block-rotationZ") + ? item.querySelector("p.audio-block-rotationZ").innerText + : ""; + + const audioUrl = item.querySelector("p.audio-block-url") + ? item.querySelector("p.audio-block-url").innerText + : ""; + + const autoPlay = item.querySelector("p.audio-block-autoPlay") + ? item.querySelector("p.audio-block-autoPlay").innerText === "1" + : false; + + const loop = item.querySelector("p.audio-block-loop") + ? item.querySelector("p.audio-block-loop").innerText === "1" + : false; + + const volume = item.querySelector("p.audio-block-volume") + ? Number(item.querySelector("p.audio-block-volume").innerText) + : 1; + + const positional = item.querySelector("p.audio-block-positional") + ? item.querySelector("p.audio-block-positional").innerText === "1" + : false; + + const coneInnerAngle = item.querySelector("p.audio-block-coneInnerAngle") + ? Number(item.querySelector("p.audio-block-coneInnerAngle").innerText) + : 1; + + const coneOuterAngle = item.querySelector("p.audio-block-coneOuterAngle") + ? Number(item.querySelector("p.audio-block-coneOuterAngle").innerText) + : 1; + + const coneOuterGain = item.querySelector("p.audio-block-coneOuterGain") + ? Number(item.querySelector("p.audio-block-coneOuterGain").innerText) + : 1; + + const distanceModel = item.querySelector("p.audio-block-distanceModel") + ? item.querySelector("p.audio-block-distanceModel").innerText + : "inverse"; + + const maxDistance = item.querySelector("p.audio-block-maxDistance") + ? Number(item.querySelector("p.audio-block-maxDistance").innerText) + : 1; + + const refDistance = item.querySelector("p.audio-block-refDistance") + ? Number(item.querySelector("p.audio-block-refDistance").innerText) + : 1; + + const rolloffFactor = item.querySelector("p.audio-block-rolloffFactor") + ? Number(item.querySelector("p.audio-block-rolloffFactor").innerText) + : 1; + + return ( + + ); + })} {Object.values( props.npcsToAdd ).map((npc, index) => { diff --git a/blocks/environment/components/Player.js b/blocks/environment/components/Player.js index 250f827..be213c1 100644 --- a/blocks/environment/components/Player.js +++ b/blocks/environment/components/Player.js @@ -301,7 +301,7 @@ export default function Player(props) { const currentTime = state.clock.elapsedTime; const timeSinceLastUpdate = currentTime - lastUpdateTime; let rigidBodyPosition = [0, 0, 0] - if(rigidRef){ + if(rigidRef.current?.translation()){ rigidBodyPosition = rigidRef.current.translation(); } const forward = new Vector3(); @@ -448,7 +448,9 @@ export default function Player(props) { // Apply slerp to the player's current quaternion, gradually aligning it with the desired quaternion playerController.scene.quaternion.slerp(desiredQuaternion, rotationSpeed); } - castRef.current.setRotation(desiredQuaternion); + if(castRef.current){ + castRef.current.setRotation(desiredQuaternion); + } if (isMoving && canMoveRef.current) { newPosition = [ diff --git a/blocks/environment/components/ThreeObjectEdit.js b/blocks/environment/components/ThreeObjectEdit.js index 1435d61..e4d6c41 100644 --- a/blocks/environment/components/ThreeObjectEdit.js +++ b/blocks/environment/components/ThreeObjectEdit.js @@ -23,6 +23,7 @@ import { Perf } from "r3f-perf"; // import EditControls from "./EditControls"; import { Resizable } from "re-resizable"; import defaultFont from "../../../inc/fonts/roboto.woff"; +import audioIcon from "../../../inc/assets/audio_icon.png"; const { registerStore } = wp.data; @@ -328,6 +329,115 @@ function ImageObject(threeImage) { ); } +function AudioObject(threeAudio) { + const texture2 = useLoader(THREE.TextureLoader, (threeObjectPlugin + audioIcon)); + + const [threeAudioBlockAttributes, setThreeAudioBlockAttributes] = useState( + wp.data + .select("core/block-editor") + .getBlockAttributes(threeAudio.audioID) + ); + + useEffect(() => { + const attributes = wp.data + .select("core/block-editor") + .getBlockAttributes(threeAudio.audioID); + setThreeAudioBlockAttributes(attributes); + }, [threeAudio.audioID]); + + const [isSelected, setIsSelected] = useState(); + + const clicked = true; + const audioObj = useRef(); + const TransformController = ({ condition, wrap, children }) => + condition ? wrap(children) : children; + + // useEffect(() => void (clicked && video.play()), [video, clicked]); + + useEffect(() => { + if( threeAudio.focusID === threeAudio.audioID ) { + const someFocus = new THREE.Vector3(Number(threeAudio.positionX), Number(threeAudio.positionY), Number(threeAudio.positionZ)); + threeAudio.changeFocusPoint(someFocus); + } + }, [threeAudio.focusID]); + + return ( + + ); +} + function VideoObject(threeVideo) { const [url, setUrl] = useState(threeVideo.modelUrl); const [screen, setScreen] = useState(null); @@ -1117,6 +1227,10 @@ function ThreeObject(props) { let videoobject; const videoElementsToAdd = []; + let audioID; + let audioObject; + const audioElementsToAdd = []; + const editorHtmlToAdd = []; let htmlobject; let htmlobjectId; @@ -1173,6 +1287,14 @@ function ThreeObject(props) { videoID = innerBlock.clientId; videoElementsToAdd.push({ videoobject, videoID }); } + if ( + innerBlock.name === + "three-object-viewer/three-audio-block" + ) { + audioObject = innerBlock.attributes; + audioID = innerBlock.clientId; + audioElementsToAdd.push({ audioObject, audioID }); + } if ( innerBlock.name === "three-object-viewer/three-portal-block" @@ -1408,6 +1530,30 @@ function ThreeObject(props) { ); } })} + {Object.values(audioElementsToAdd).map((model, index) => { + if (model.audioObject.audioUrl) { + return ( + + ); + } + })} {Object.values(editorHtmlToAdd).map((text, index) => { return ( { + const listener = new AudioListener(); + camera.add(listener); + + // Create either a PositionalAudio object or a normal Audio object based on the positional attribute + const audio = threeAudio.positional === "1" ? new PositionalAudio(listener) : new Audio(listener); + + if (threeAudio.audioUrl) { + const audioLoader = new AudioLoader(); + audioLoader.load(threeAudio.audioUrl, (buffer) => { + audio.setBuffer(buffer); + audio.setLoop(threeAudio.loop === "1" ? true : false); + audio.setVolume(threeAudio.volume); + if (threeAudio.autoPlay === "1") audio.play(); + }); + } + + if (threeAudio.positional === "1") { + audio.refDistance = threeAudio.refDistance; + audio.maxDistance = threeAudio.maxDistance; + audio.rolloffFactor = threeAudio.rolloffFactor; + audio.coneInnerAngle = threeAudio.coneInnerAngle; + audio.coneOuterAngle = threeAudio.coneOuterAngle; + audio.coneOuterGain = threeAudio.coneOuterGain; + audio.distanceModel = threeAudio.distanceModel; + audio.position.set(threeAudio.positionX, threeAudio.positionY, threeAudio.positionZ); + audio.rotation.set(threeAudio.rotationX, threeAudio.rotationY, threeAudio.rotationZ); + } + + setAudio(audio); + + return () => { + audio.stop(); + camera.remove(listener); + } + }, []); + + return ( + <> + {audio && } + + ); +} diff --git a/blocks/environment/frontend.js b/blocks/environment/frontend.js index cf8d992..f2123cb 100644 --- a/blocks/environment/frontend.js +++ b/blocks/environment/frontend.js @@ -29,6 +29,9 @@ const spawnToAdd = document.querySelectorAll( const videosToAdd = document.querySelectorAll( ".three-object-three-app-video-block" ); +const audiosToAdd = document.querySelectorAll( + ".three-object-three-app-audio-block" +); threeApp.forEach((threeApp) => { if (threeApp) { const spawnPoint = @@ -120,6 +123,7 @@ threeApp.forEach((threeApp) => { portalsToAdd={portalsToAdd} imagesToAdd={imagesToAdd} videosToAdd={videosToAdd} + audiosToAdd={audiosToAdd} spawnPoint={spawnPoint ? spawnPoint : null} htmlToAdd={htmlToAdd} npcsToAdd={npcsToAdd} diff --git a/blocks/three-audio-block/Edit.js b/blocks/three-audio-block/Edit.js index 8739332..103f9f0 100644 --- a/blocks/three-audio-block/Edit.js +++ b/blocks/three-audio-block/Edit.js @@ -1,5 +1,5 @@ import { __ } from "@wordpress/i18n"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { DropZone } from "@wordpress/components"; import "./editor.scss"; import { @@ -19,15 +19,25 @@ import { } from "@wordpress/components"; import { more } from "@wordpress/icons"; -export default function Edit({ attributes, setAttributes, isSelected }) { +export default function Edit({ attributes, setAttributes, isSelected, clientId }) { + const { select, dispatch } = wp.data; + const onImageSelect = (imageObject) => { - setAttributes({ videoUrl: null }); + setAttributes({ audioUrl: null }); setAttributes({ - videoUrl: imageObject.url, - aspectHeight: imageObject.height, - aspectWidth: imageObject.width + audioUrl: imageObject.url, }); }; + useEffect(() => { + if( isSelected ){ + dispatch( 'three-object-environment-events' ).setFocusEvent( clientId ); + } + }, [isSelected]); + + const onChangeName = (name) => { + setAttributes({ name }); + }; + const onChangePositionX = (positionX) => { setAttributes({ positionX }); }; @@ -123,12 +133,22 @@ export default function Edit({ attributes, setAttributes, isSelected }) { icon={more} initialOpen={true} > + + onChangeName(value)} + /> + - Select an image or object to attach to your - audio. Leave blank for no mesh. + Select an audio file to add to your scene. + { attributes.audioUrl && ( { attributes.audioUrl } )} + + @@ -374,15 +394,26 @@ export default function Edit({ attributes, setAttributes, isSelected }) { {isSelected ? ( <> - {attributes.videoUrl ? ( - <> - - - ) : ( + {attributes.audioUrl ? ( +
+
+ + + + + +

+ Audio block +

+ {/*

URL: {attributes.threeObjectUrl}

*/} +
+
+ ) : (
( )} @@ -419,15 +450,26 @@ export default function Edit({ attributes, setAttributes, isSelected }) { ) : ( <> - {attributes.videoUrl ? ( - <> - - - ) : ( + {attributes.audioUrl ? ( +
+
+ + + + + +

+ Audio block +

+ {/*

URL: {attributes.threeObjectUrl}

*/} +
+
+ ) : (
(

- {attributes.aspectHeight} +

+ {attributes.autoPlay ? '1' : '0'}

-

- {attributes.aspectWidth} +

+ {attributes.loop ? '1' : '0'} +

+

+ {attributes.volume} +

+

+ {attributes.positional ? '1' : '0'} +

+

+ {attributes.coneInnerAngle} +

+

+ {attributes.coneOuterAngle} +

+

+ {attributes.coneOuterGain} +

+

+ {attributes.distanceModel} +

+

+ {attributes.maxDistance} +

+

+ {attributes.refDistance} +

+

+ {attributes.rolloffFactor}

diff --git a/blocks/three-audio-block/block.json b/blocks/three-audio-block/block.json index 4f895d1..6472f50 100644 --- a/blocks/three-audio-block/block.json +++ b/blocks/three-audio-block/block.json @@ -3,6 +3,10 @@ "title": "3D Audio", "description": "An audio block for your environment", "attributes": { + "name": { + "type": "string", + "default": null + }, "audioUrl": { "type": "string", "default": null @@ -25,15 +29,15 @@ }, "coneInnerAngle": { "type": "int", - "default":1 + "default":360 }, "coneOuterAngle": { "type": "int", - "default":1 + "default":0 }, "coneOuterGain": { "type": "int", - "default":1 + "default":0.8 }, "distanceModel": { "type": "string", @@ -41,27 +45,15 @@ }, "maxDistance": { "type": "int", - "default":1 + "default":10000 }, "refDistance": { "type": "int", - "default":1 + "default":5 }, "rolloffFactor": { "type": "int", - "default":1 - }, - "scaleX": { - "type": "int", - "default":1 - }, - "scaleY": { - "type": "int", - "default":1 - }, - "scaleZ": { - "type": "int", - "default":1 + "default":5 }, "positionX": { "type": "int", @@ -86,14 +78,6 @@ "rotationZ": { "type": "int", "default":0 - }, - "aspectHeight": { - "type": "int", - "default":0 - }, - "aspectWidth": { - "type": "int", - "default":0 } }, "category": "design", diff --git a/inc/assets/audio_icon.png b/inc/assets/audio_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..890feca03d3d95777ea899901381b59c72c6de4a GIT binary patch literal 5322 zcmdT|d03KZ*T*z0*R;$%49m(CTtE{=Bf+I4bIBz|B}GLYOoGKz=>QG_+1SO? ziNO>SQ|~Y-j2wlAj`NzJdgKr^)EkL6!PD(Y;bf=8Xp%?be$U`UO0ZQ3)XrAUCLRSC zppuwGy?AP56ay8HhOXE}0nf|ZaH!sj2$O<_`rr@f+0&v)dPo=&W&*X9)3b>V2}QYM z9lk09D>O8m$)uy;@VK}*Se!YG799pRwX(8;o0!4P%!~mEV@5(0lNfIt#n4|i@x=y~ z#0ZWi)0t#il-{yU;$d106Ags|xZYReqrsra;R8g#ml3!r%mn^taV9zRU&NP@ zzlqbsX-pa;oJRj6fWI8^2mCihfWCiLi6_$kNf?j+-^Hoazl6bH;$i_JzLNSEpZ|JEca(WL&k%4&3zFG76hM}RB zX7E29Y6Pj4mDC}Qw3NoXiNnidihObS^E3o!Qu zWza&Ial~j6CJab28j1-GB?ELO=mG6R4vQj1>zTq#O<>5sD#eA9mec;P;laN;2VZWy z|9WQw|C|3dD*}J&R6y^`9xwrbQ3C&CmH>-CrV%L$7(vm%tm#au2?T+pj+24R{4FCO z(Dv+@oc^6GH;spO+TD}f9Weh}K6kqeE^V}YT`{=+J3z zYt0zV5uI{Q*OTgXF>BLE0c+$v&r*jZUoSavY$OiUI%``YY~Qjml&eHb_V zLRJheBzWC;rc_AV^N_U(Sz?!Sr4gN-DqbIcYIhG30n1~2U^seG zkcX97W$-kwENyMM#~PNAB&eSE>$|KZ-8@ngufKihMf*_l_>c``Y20f3d7rqK(O=AH zmvYY8^5rkn2WMLi4TKOJcNA$7QXji#XGs|j$OWm>4@TlhCXz!L8Ao?bfCoke@9(_b z@Q_1!X*h`!bP0BdZvOC?Lm?VY`U+wMPbG);h6%fP8AqY5>p!XLJ@C>uk^Jt~6P~0^ zx1xv8t-4QQyu+wmYUU+TtUuif1!7g~H=KNcXr9jHQbh9#4TJ94mYs<1w#*9L$xtCO zH{;WuqR1QMEk!DX)L$<`A%5AF(qo}-HW!ETcQ%|LO`WP>U3ugPYTDb05B$-gXHF1^ zQ?GWh72T}JxUD;DGXeA3_6B6Pi6FQ>hZT2vzNsN=QT<9NzUx>O(FfnCixAxb+Jxp3 z7xRKtb*#8L5=`)X6Pyt3*rRgitx@+*u6%lsP`_pqmSC$O~6}qocOv? zr^_lB=%Y;jbtbscL~Txo?a*T-x+$~k!l3YUrGxtQNO0piDtA;XD2ZvDmf>H^!UQI$ z&FvbfBlBT?9~^ovZg`$9&EjA0cIbJF$gB-!HLta7)p4lNuW$k3}n{x*|mgiD5vrFysC(z&cN1jLEte8}ntB$n%0i27ehs(Pq30EL@t0b~S)YMVu0&yeIrRo%?Wc_v z-FcfQKY!Yzkmzd|y^0UGYg)@Tb1{DiveQD$Ff^XgX28jJ3?~x+ziUb;J6bGWB_8Pc zvW+pE+##?|^>!4ymrFV`ellVu0TGt0gwB2{r8J5 z{WK)~^Xk^*RTJ((VfQ}`n@V&69WhX%Dcf)9AYmYPVXvJEVjQD6tpw=B+**hTKWf*X zg(|^k=&&vKL5#8C*;9_QkNi)QqDW z@LcNg%-V~L=P4lYXFb3iX?JF3ZFTyhFZG<(};L~U;Gz=e3tyFPO%d?l6=P|~S(QUU7;r%|So;qA7P(QDfv z_oh0$F;4nXY%8VN>hyZc$K28Zu)>@KZ~pVDZ8G>JLvT?UM!hb46#a^pUSZ!j5q6Wc z9VJ2JZ-_w7rlhQU0B(fRqysh*PBs*Tscp_}Cr0 z){7&YlR7%(-#^pZRfmCGiB;x_H(fj1sc�R4I6ix2>8cb6~Z=O@u4AbhEqKcs%=P zt51Z`@qHFoF=@Z>HrJ=tz8)ivIE8|=arRyPrSWnM!rD-=0Z}ZkA*%ljCa~MX^MLv- zOVDJJf5e;jD@SHj1aAcP`^t+3m-o-WB#lKTHLOoY?9ueFRbilqGgc{q9|a<1NA-(t z5lug6zo8n*cJ33#oy)pp<@sKHL5q>?|7$r5FPOo)*tF`{I*(i!YL8vCYhoRhn($>W z2xKAAm${D^i$jZhD?I?cW1DViHpzHc?TH%sDYOW4@`a!m(~nui4506in&&~W$?IYa zbd|*CcS@|;0= z4k|WSp4r>X*sL3<8LBj|G)WX>F@N&xa6uXO5c%8Yl|k*lqpC|47cN&wx2&Houi$zX zk_X>T(`U;zME$|6-*M*Mx0tOO=#8M0v4u9FAX1o;&QYca|30ZKN!b}4{(8~D4V-GEuw@tMsU z0C4vA<)xZ{vv0MD#9d0E!4vfVV2QA)A76D6c7aZ$qFID zvNZOVA`ba+OejF=FljCd_*&3ToMlssILB&+OLHtjbK=*{iYs2X=u9I!SOR;(w!9m} z3;E+yu)d|s!}oJ6jEp43@0JtHlb&_Rml{-@cTA(j{p8c}tBYzL3uj$amG_$$O9yBXnvD|W=lM^a zl%m);@#1*T~3HT5jBRb%`iw>X#pJ#HE$eyprJqv^{)I;g&JkvCQ*HUN~^$+o79R^(Vt?+>HA7Db3?WtII9x zz-?5a>{#P{SrXBaxmy>QjX!PKw0X?)m9^&V`bZTwvlnePTMV!gQHJpQxQ&{&1!5Tfo;;}9!=uRWdoq!bP+NGq1+ ztNNb}joUevWT(gC7qfq$bS$KLkQ*j1!0I|DT~zz^B$xU>ZXaAadp=1YxFsSw>LNP2 z1iuL&FUxX*Rp!ilg5vzNrtQm}mBppaX`SJ)a$(h65pcyMvm!ds$ah@=3x}%pSAvRV zK7w15*Go6DTR83I27PjcxG6?&KC4-jVsL6nYSA=&>}2Y()8`isD9r10pXggigMd?V zZ?Tk_L9qUrV4-!mcC1*47+GAW9c%xRKl52*def8A%C6F#;bX7orzDB@F9_<65AxNX z=^|zt6cV!{I@BXNDB)VMV^#8I&LiNlHSC3BX+8Rbwi+xxh$ zT{{pX0a=Q?gwNI!bf$_(VP0@kk!M#%e%7d_9cxZ5I9!JntF&^musv10ywH<##il>0PmaHA? zEkcag>JZx3xu^z~3^c9*Cx72nnndY{9q=FU5PeYCUF{mf3P@!$9q}mHTN`e{8;W*6 zuy~`82vB)46)&iC3%%F2t>N)9O*nw2M7fA(cvWT43=q>Dj`|e?^r74rE>qt%nKl${ zHH-#^qr7+S*j49zkY9MzF5eg&3>c@Na_6|GrN)A-zr@}f+c{;NmiV2;{BLS%j|F;2SG<1@;ul33@i z(15z^oYhrYC)7!Ne^HXi3<47x%bjP$rTfTQv2~7O?$2hD-w)#FJ@MUgk+OUZLY5Yo zAn%rI>(W`3w0^>gZuP)ia_Bt!Mx8-p!Jq<