main
reng 2 months ago
parent 3bbd9848e3
commit cf7ae2ff66
  1. 50
      public/cuelist - 複製.json
  2. 109
      public/cuelist_1009.json
  3. 2
      src/App.css
  4. 38
      src/App.jsx
  5. 28
      src/utils/light.jsx

@ -1,50 +0,0 @@
{
"cuelist": [
{
"id": 1,
"name": "Q1",
"type": "bg",
"description": "preset bg",
"audioCue": "Q0",
"clientCue":"Q1"
},
{
"id": 2,
"name": "Q2",
"type": "announce",
"description": "announce",
"audioCue": "Q2"
},
{
"id": 3,
"name": "Q3",
"type": "bg",
"description": "(START) CQ2-CQ4.1",
"audioCue": "Q3",
"clientCue":"Q2",
"duration":495,
"auto": true
},
{
"id": 4,
"name": "Q4",
"type": "light",
"description": "(AI) CQ4.11-CQ5.6",
"lightCue":"fade_out_light",
"duration":298,
"clientCue":"Q4.11",
"auto": true
},
{
"id": 5,
"name": "Q5",
"type": "bg",
"description": "(END)",
"audioCue": "Q6",
"status":"end",
"lightCue":"fade_in_light",
"clientCue":"Q6"
}
]
}

@ -0,0 +1,109 @@
{
"cuelist": [
{
"id": 1,
"name": "Q1",
"type": "bg",
"description": "[外場+電話亭] preset 音樂",
"audioCue": "Q0",
"clientCue":"Q1",
"reset":true
},
{
"id": 2,
"name": "Q2",
"type": "announce",
"description": "[外場 + 電話亭] announce",
"audioCue": "Q1",
"clientCue":"Q1.1"
},
{
"id": 3,
"name": "Q3",
"type": "bg",
"description": "[電話亭] 開始流程 CQ2-CQ4.1",
"audioCue": "Q3",
"clientCue":"Q2",
"duration":110,
"auto": true,
"reset":true
},
{
"id": 3.1,
"name": "Q3.1",
"type": "light",
"description": "關燈",
"duration":62,
"auto": true,
"lightCue":"fade_out_light",
"lightDuration":8,
"syncUnityLight":true
},
{
"id": 3.2,
"name": "Q3.2",
"type": "light",
"description": "開燈",
"duration":126,
"auto": true,
"lightCue":"fade_in_light",
"lightDuration":4,
"syncUnityLight":true
},
{
"id": 4,
"name": "Q4",
"type": "light",
"description": "[電話亭] 記憶裝置啟動 (AI) CQ4.11-CQ5.6",
"audioCue": "Q4",
"lightCue":"fade_out_light",
"duration":250,
"clientCue":"Q4.11",
"auto": true
},
{
"id": 5,
"name": "Q5",
"type": "bg",
"description": "[電話亭] 結尾announce",
"duration":25,
"status":"end",
"lightCue":"fade_in_light",
"clientCue":"Q6",
"audioCue": "Q5",
"auto":true
},
{
"id": 6,
"name": "Q6",
"type": "bg",
"description": "[外場] 結尾音樂",
"audioCue": "Q6",
"clientCue":"Q7"
},
{
"id": 7,
"name": "Q7",
"type": "bg",
"description": "[外場] fadeout",
"audioCue": "Q7"
},
{
"id": 0.1,
"name": "CQ101",
"type": "debug",
"description": "debug-key",
"clientCue":"Q101",
"debug":true
},{
"id": 0.2,
"name": "CQ103",
"type": "debug",
"description": "debug-speech",
"lightCue":"fade_out_light",
"clientCue":"Q103",
"debug":true
}
]
}

@ -11,7 +11,7 @@ tr{
@apply border-b border-gray-400;
}
td{
@apply p-1;
@apply px-1;
}
input[type='range'] {
overflow: hidden;

@ -9,7 +9,10 @@ import { Light } from "./utils/light";
const DefaultFadeDuration = 3; // 1 second
const CLIENT_COUNT = 13;
const CUE_FILE = 'cuelist_0924.json';
const CUE_FILE = 'cuelist_1009.json';
// const OSC_BROADCAST_IP='192.168.51.255:8000';
const OSC_BROADCAST_IP = '192.168.234.255:8000';
const UNITY_BROADCAST_IP = '192.168.234.255:9000';
const CueType = {
@ -44,7 +47,7 @@ function App() {
key: addr,
message: `${id}#${message}`,
host: '0.0.0.0:0',
target: '192.168.51.255:8000',
target: OSC_BROADCAST_IP,
});
}
@ -134,14 +137,16 @@ function App() {
if (props.lightCue) {
// sendOsc(OSC_ADDRESS.CLIENT_INPUT, props.lightCue);
if (props.lightCue == 'fade_in_light') refLight.current.fadeIn(); // Fade in light for conversation start
if (props.lightCue == 'fade_out_light') refLight.current.fadeOut(); // Fade out light for conversation end
if (props.lightCue == 'fade_in_light'){
refLight.current.fadeIn(props.lightDuration, props.syncUnityLight?UNITY_BROADCAST_IP:null); // Fade in light for conversation start
}
if (props.lightCue == 'fade_out_light'){
refLight.current.fadeOut(props.lightDuration, props.syncUnityLight?UNITY_BROADCAST_IP:null); // Fade out light for conversation end
}
}
if (props.reset) {
//sendOsc(OSC_ADDRESS.RESETCUE,'','all');
refLight.current.set(1);
resetLight();
}
if (refTimer.current) {
@ -172,7 +177,11 @@ function App() {
refTimer.current = null;
if (auto) {
const next = cuelist.find(c => c.id === id + 1);
// const next = cuelist.find(c => c.id === id + 1);
const index = cuelist.findIndex(c => c.id === id);
const next = cuelist[index + 1];
if (!next) return;
console.log('Auto play next cue:', next);
playCue(next);
}
@ -209,7 +218,16 @@ function App() {
sendOsc(OSC_ADDRESS.RESETCUE, '', 'all');
sendOscToSound(OSC_ADDRESS.SCS_STOP_ALL, '');
resetLight();
}
function resetLight(){
refLight.current.set(1);
invoke('send_osc_message', {
key: '/amplitude',
message: 1.0.toString(),
host:`0.0.0.0:0`,
target: UNITY_BROADCAST_IP,
});
}
function secondToTime(seconds) {
@ -267,7 +285,7 @@ function App() {
<main className="overflow-y-auto flex flex-row gap-8 p-4 min-h-screen">
<section className="flex-1 flex flex-col gap-4">
<section className="grid grid-cols-4 items-center gap-2">
<div className="flex flex-row font-bold items-stretch justify-bewteen bg-pink-300 gap-4 p-2">
<div className="grid grid-cols-1 font-bold items-stretch justify-between bg-pink-300 gap-4 p-2">
<div className="text-4xl">{currentCue ? `${currentCue.name}` : 'None'}</div>
<div className="text-4xl" ref={refDuration}></div>
</div>
@ -284,7 +302,7 @@ function App() {
<span className="text-2xl">{fadeDuration}s</span>
</span>
</section>
<table className="border-collapse w-full **:p-1 border-green-500 border-4">
<table className="border-collapse w-full **:px-1 border-green-500 border-4">
<thead className="bg-green-500">
<tr className="text-left lowercase font-[900]">
{/* <th>ID</th> */}

@ -11,13 +11,14 @@ export const Light=forwardRef((props, ref)=>{
const refContainer=useRef();
const refGsap=useRef();
function fade(from, to){
const time= parseFloat(refInput.current.value) || FADE_TIME;
function fade(from, to, duration=null, unity_ip=null){
const time= duration || parseFloat(refInput.current.value) || FADE_TIME;
console.log(`fade light from ${from} to ${to} in ${time}s`, unity_ip);
gsap.killTweensOf(refVal.current); // Kill all tweens of refVal
gsap.current=gsap.fromTo(refVal.current,{val: from}, {
refGsap.current=gsap.fromTo(refVal.current,{val: from}, {
val: to,
duration: time,
onUpdate: () => {
@ -32,6 +33,14 @@ export const Light=forwardRef((props, ref)=>{
// console.error('Error sending DMX message:', error);
// });
if(unity_ip){
invoke('send_osc_message', {
key: '/amplitude',
message: refVal.current.val.toString(),
host:`0.0.0.0:0`,
target: unity_ip,
});
}
invoke('send_osc_message', {
key: '/light',
message: refVal.current.val.toString(),
@ -45,13 +54,13 @@ export const Light=forwardRef((props, ref)=>{
});
}
useImperativeHandle(ref, () => ({
fadeIn: ()=>{
fadeIn: (duration, sync_unity)=>{
console.log('fadeIn');
fade(0, 1);
fade(0, 1, duration, sync_unity);
},
fadeOut: ()=>{
fadeOut: (duration, sync_unity)=>{
console.log('fadeOut');
fade(1, 0);
fade(1, 0, duration, sync_unity);
},
reset:()=>{
console.log('reset');
@ -70,8 +79,11 @@ export const Light=forwardRef((props, ref)=>{
},
set: (value)=>{
console.log('set', value);
gsap.killTweensOf(refVal.current);
refVal.current.val=value;
refContainer.current.style.background= `rgba(0, 255, 0, ${value})`; // Update background color based on value
invoke('send_osc_message', {
key: '/light',
message: value.toString(),

Loading…
Cancel
Save