From 6950347ffb09cbad2bd389f2aa3ef72616aab04c Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Sun, 20 Oct 2024 09:58:16 +0900 Subject: [PATCH 1/6] [Update/Memo] Config Page: Add VR Tab. Overlay settings. --- .../setting_box/SettingBox.jsx | 3 + .../setting_box/_components/slider/Slider.jsx | 52 +++--- .../_components/slider/Slider.module.scss | 24 ++- .../setting_section/setting_box/vr/Vr.jsx | 149 ++++++++++++++++++ .../setting_box/vr/Vr.module.scss | 79 ++++++++++ 5 files changed, 278 insertions(+), 29 deletions(-) create mode 100644 src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx create mode 100644 src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss diff --git a/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx b/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx index d78ec87e..adec9373 100644 --- a/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/SettingBox.jsx @@ -5,6 +5,7 @@ import { Appearance } from "./appearance/Appearance"; import { Transcription } from "./transcription/Transcription"; import { Others } from "./others/Others"; import { AdvancedSettings } from "./advanced_settings/AdvancedSettings"; +import { Vr } from "./vr/Vr"; // import { AboutVrct } from "./about_vrct/AboutVrct"; export const SettingBox = () => { @@ -18,6 +19,8 @@ export const SettingBox = () => { return ; case "others": return ; + case "vr": + return ; case "advanced_settings": return ; // case "about_vrct": diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx index 280ec3f9..e0da05a6 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx @@ -20,7 +20,6 @@ export const Slider = (props) => {
{ min={Number(props.min)} max={Number(props.max)} onChange={(_e, value) => props.onchangeFunction(value)} - onChangeCommitted={(_e, value) => props.onchangeCommittedFunction(value)} + onChangeCommitted={(_e, value) => props.onchangeCommittedFunction ? props.onchangeCommittedFunction(value) : null} marks={props.marks} track={props.track} + orientation={props.orientation} sx={{ color: baseColor, - "& .MuiSlider-thumb": { - backgroundColor: activeColor, - "&:hover, &.Mui-focusVisible, &.Mui-active": { - boxShadow: "0 0 0 0.8rem" + activeColor + "44", - }, - "& .MuiSlider-valueLabel": { - fontSize: "1.4rem", - backgroundColor: toolTipColor, - padding: "0.6rem 1rem", - lineHeight: "1.15", - top: "-1.4rem", - "&::before": { - left: "30%", - width: "1rem", - height: "1rem", - clipPath: "polygon(50% 0, 100% 100%, 0 100%)", - } - } + "& .MuiSlider-thumb": { + backgroundColor: activeColor, + "&:hover, &.Mui-focusVisible, &.Mui-active": { + boxShadow: `0 0 0 0.8rem ${activeColor}44`, }, - "& .MuiSlider-markLabel": { + "& .MuiSlider-valueLabel": { fontSize: "1.4rem", - color: "white" + backgroundColor: toolTipColor, + padding: "0.6rem 1rem", + lineHeight: "1.15", + top: "-1.4rem", + "&::before": { + left: "30%", + width: "1rem", + height: "1rem", + clipPath: "polygon(50% 0, 100% 100%, 0 100%)", + }, }, - "& .MuiSlider-markLabelActive": { - color: activeColor, - } - }} + }, + "& .MuiSlider-markLabel": { + fontSize: "1.4rem", + color: "white", + }, + "& .MuiSlider-markLabelActive": { + color: activeColor, + }, + }} />
); diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss index 873029b1..907f7529 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss @@ -1,12 +1,30 @@ .container { display: flex; flex-direction: column; - align-items: end; + align-items: center; // 中央に揃え justify-content: center; width: 100%; padding-left: 4rem; } .range_slider { - // max-width: 60rem; -} \ No newline at end of file + // スライダーの幅を調整(必要に応じて調整) + height: 200px; // 縦スライダーの高さ + padding: 10px 0; // スライダーの上下のパディング + + & .MuiSlider-thumb { + // スライダーのつまみのサイズを調整 + height: 24px; + width: 24px; + margin-top: -12px; // つまみが中心に来るように調整 + } + + & .MuiSlider-track { + height: 2px; // トラックの高さを調整 + } + + & .MuiSlider-vertical { + // 縦スライダー用のスタイル + height: 100%; // コンテナの高さにフィット + } +} diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx new file mode 100644 index 00000000..b78be1be --- /dev/null +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx @@ -0,0 +1,149 @@ +import React, { useState } from "react"; +import styles from "./Vr.module.scss"; +import { Slider } from "../_components/"; + +export const Vr = () => { + const [position, setPosition] = useState({ x: 0, y: 0, z: 0 }); + const [rotation, setRotation] = useState({ rotate_x: 0, rotate_y: 0, rotate_z: 0 }); + const [opacity, setOpacity] = useState(1); + const [ui_scaling, setUiScaling] = useState(100); + + const handlePositionChange = (axis, value) => { + setPosition((prev) => ({ ...prev, [axis]: value })); + }; + + const handleRotationChange = (axis, value) => { + setRotation((prev) => ({ ...prev, [axis]: value })); + }; + + const handleOpacityChange = (value) => { + setOpacity(value / 100); + }; + + const handleUiScalingChange = (value) => { + setUiScaling(value); + }; + + + const scale = position.z >= 0 + ? (1 - position.z / 200) * (ui_scaling / 100) + : (1 + Math.abs(position.z) / 200) * (ui_scaling / 100); + + + const x_factor = Math.min(Math.abs(position.x) / 100, 1); + const y_factor = Math.min(Math.abs(position.y) / 100, 1); + + const translate_x = position.x + (position.z * x_factor * (position.x >= 0 ? -1 : 1)); + const translate_y = -1 * (position.y + (position.z * y_factor * (position.y >= 0 ? -1 : 1))); + + + return ( +
+
+
+ + handlePositionChange("z", value)} + orientation="vertical" + /> +
+
+
+

+ 実際の表示とは大きく違います。これはただのイメージ図です。 +

+
+
+
+ + handlePositionChange("y", value)} + orientation="vertical" + /> +
+
+ + handlePositionChange("x", value)} + /> +
+
+
+
+ + handleRotationChange("rotate_x", value)} + /> +
+
+ + handleRotationChange("rotate_y", value)} + /> +
+
+ + handleRotationChange("rotate_z", value)} + /> +
+
+ + +
+
+ + +
+
+
+ ); +}; diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss new file mode 100644 index 00000000..8c2f3bc4 --- /dev/null +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss @@ -0,0 +1,79 @@ +.app { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + margin-top: 4rem; +} + +.canvas_container { + display: flex; + position: relative; +} + +.canvas { + width: 40rem; + height: 30rem; + border: 0.1rem solid #fff; + background-color: var(--dark_800_color); + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +.chat_box { + max-width: 20rem; + background-color: #33363a; + border-radius: 0.4rem; + padding: 1.2rem; + position: absolute; + transform-origin: center; + transition: transform 0.1s ease-out, opacity 0.1s ease-out; +} + +.chat_text { + font-size: 1.2rem; +} + +.x_position { + position: absolute; + bottom: -6rem; + left: 50%; + transform: translateX(-50%); + width: 100%; +} + +.y_position { + position: absolute; + right: -8rem; + top: 50%; + transform: translateY(-50%); + writing-mode: vertical-rl; + text-orientation: mixed; + height: 100%; +} + +.z_position { + position: absolute; + left: -8rem; + top: 50%; + transform: translateY(-50%); + writing-mode: vertical-rl; + text-orientation: mixed; + height: 100%; +} + +.other_controls { + margin-top: 10rem; + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + width: 100%; +} + +.x_rotation, .y_rotation, .z_rotation, .opacity, .ui_scaling { + width: 100%; +} \ No newline at end of file From 69953eec1b3d113afb40ee4d33850fb27a439904 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:40:07 +0900 Subject: [PATCH 2/6] [Update] Config Page: VR Tab. Change the design. --- .../setting_box/_components/slider/Slider.jsx | 19 +- .../_components/slider/Slider.module.scss | 2 +- .../setting_section/setting_box/vr/Vr.jsx | 312 +++++++++++------- .../setting_box/vr/Vr.module.scss | 191 ++++++++--- 4 files changed, 352 insertions(+), 172 deletions(-) diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx index e0da05a6..a24cb9dc 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; import styles from "./Slider.module.scss"; import MUI_Slider from "@mui/material/Slider"; +import { clsx } from "clsx"; export const Slider = (props) => { const [baseColor, setBaseColor] = useState(""); @@ -17,7 +18,7 @@ export const Slider = (props) => { }, []); return ( -
+
{ marks={props.marks} track={props.track} orientation={props.orientation} + valueLabelFormat={props.valueLabelFormat ? props.valueLabelFormat : null} sx={{ color: baseColor, "& .MuiSlider-thumb": { @@ -43,18 +45,19 @@ export const Slider = (props) => { backgroundColor: toolTipColor, padding: "0.6rem 1rem", lineHeight: "1.15", - top: "-1.4rem", - "&::before": { - left: "30%", - width: "1rem", - height: "1rem", - clipPath: "polygon(50% 0, 100% 100%, 0 100%)", - }, + // top: "-1.4rem", + // "&::before": { + // left: "30%", + // width: "1rem", + // height: "1rem", + // clipPath: "polygon(50% 0, 100% 100%, 0 100%)", + // }, }, }, "& .MuiSlider-markLabel": { fontSize: "1.4rem", color: "white", + whiteSpace: "nowrap", }, "& .MuiSlider-markLabelActive": { color: activeColor, diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss index 907f7529..645a3a24 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.module.scss @@ -4,7 +4,7 @@ align-items: center; // 中央に揃え justify-content: center; width: 100%; - padding-left: 4rem; + // padding-left: 4rem; } .range_slider { diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx index b78be1be..b4191672 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx @@ -1,21 +1,151 @@ import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; import styles from "./Vr.module.scss"; import { Slider } from "../_components/"; +import { clsx } from "clsx"; export const Vr = () => { + const { t } = useTranslation(); + const [is_opened_position_controller, setIsOpenedPositionController] = useState(true); + + const toggleController = () => { + setIsOpenedPositionController(!is_opened_position_controller); + }; + + const toggle_button_class_names__position = clsx(styles.controller_type_switcher, { + [styles.is_selected]: is_opened_position_controller + }); + const toggle_button_class_names__rotation = clsx(styles.controller_type_switcher, { + [styles.is_selected]: !is_opened_position_controller + }); + + return ( +
+
+
+

Position

+
+
+

Rotation

+
+
+
+ {is_opened_position_controller + ? + : + } +
+ + +
+ ); +}; + +const PositionControls = () => { + const { t } = useTranslation(); const [position, setPosition] = useState({ x: 0, y: 0, z: 0 }); - const [rotation, setRotation] = useState({ rotate_x: 0, rotate_y: 0, rotate_z: 0 }); - const [opacity, setOpacity] = useState(1); - const [ui_scaling, setUiScaling] = useState(100); const handlePositionChange = (axis, value) => { setPosition((prev) => ({ ...prev, [axis]: value })); }; + return ( +
+
+ + handlePositionChange("x", value)} + /> +
+
+ + handlePositionChange("y", value)} + orientation="vertical" + /> +
+
+ + handlePositionChange("z", value)} + orientation="vertical" + /> +
+
+ ); +}; +const RotationControls = () => { + const { t } = useTranslation(); + const [rotation, setRotation] = useState({ rotate_x: 0, rotate_y: 0, rotate_z: 0 }); + const handleRotationChange = (axis, value) => { setRotation((prev) => ({ ...prev, [axis]: value })); }; + + return ( +
+
+ + handleRotationChange("rotate_x", -value)} + orientation="vertical" + /> +
+
+ + handleRotationChange("rotate_y", value)} + /> +
+
+ + handleRotationChange("rotate_z", value)} + orientation="vertical" + /> +
+
+ ); +}; + + +const OtherControls = () => { + const { t } = useTranslation(); + const [opacity, setOpacity] = useState(1); + const [ui_scaling, setUiScaling] = useState(100); + const handleOpacityChange = (value) => { setOpacity(value / 100); }; @@ -24,126 +154,70 @@ export const Vr = () => { setUiScaling(value); }; + const ui_variable_opacity = (opacity * 100).toFixed(0); - const scale = position.z >= 0 - ? (1 - position.z / 200) * (ui_scaling / 100) - : (1 + Math.abs(position.z) / 200) * (ui_scaling / 100); + const [display_duration, setDisplayDuration] = useState(5); + const [fadeout_duration, setFadeoutDuration] = useState(2); + + const handleDisplayDurationChange = (value) => { + setDisplayDuration(value); + }; + + const handleFadeoutDurationChange = (value) => { + setFadeoutDuration(value); + }; - const x_factor = Math.min(Math.abs(position.x) / 100, 1); - const y_factor = Math.min(Math.abs(position.y) / 100, 1); - - const translate_x = position.x + (position.z * x_factor * (position.x >= 0 ? -1 : 1)); - const translate_y = -1 * (position.y + (position.z * y_factor * (position.y >= 0 ? -1 : 1))); - - - return ( -
-
-
- - handlePositionChange("z", value)} - orientation="vertical" - /> -
-
-
-

- 実際の表示とは大きく違います。これはただのイメージ図です。 -

-
-
-
- - handlePositionChange("y", value)} - orientation="vertical" - /> -
-
- - handlePositionChange("x", value)} - /> -
+ return( +
+
+ +
-
-
- - handleRotationChange("rotate_x", value)} - /> -
-
- - handleRotationChange("rotate_y", value)} - /> -
-
- - handleRotationChange("rotate_z", value)} - /> -
-
- - -
-
- - -
+
+ + +
+
+ + +
+
+ +
); -}; +}; \ No newline at end of file diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss index 8c2f3bc4..299b3c2d 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss @@ -1,79 +1,182 @@ -.app { +.container { display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; - margin-top: 4rem; + padding: 2rem; } -.canvas_container { - display: flex; - position: relative; -} - -.canvas { - width: 40rem; - height: 30rem; - border: 0.1rem solid #fff; - background-color: var(--dark_800_color); +.controller_type_switch { display: flex; + border: 0.1rem solid var(--dark_600_color); + border-radius: 0.4rem; + width: 50%; align-items: center; justify-content: center; + cursor: pointer; + color: var(--dark_600_color); + &:hover { + color: var(--dark_400_color); + } +} +.controller_type_switcher { + width: 100%; + &.is_selected { + background-color: var(--dark_850_color); + } + &.is_selected .controller_switcher_label { + color: var(--dark_basic_text_color); + } +} +.controller_switcher_label { + padding: 1rem; + font-size: 1.6rem; +} + +.position_rotation_controls_box { + margin-top: 14rem; position: relative; + aspect-ratio: 1 / 1; + width: 36%; + max-width: 40rem; + transform: translate(-10%); } -.chat_box { - max-width: 20rem; - background-color: #33363a; - border-radius: 0.4rem; - padding: 1.2rem; - position: absolute; - transform-origin: center; - transition: transform 0.1s ease-out, opacity 0.1s ease-out; -} +// .position_controls { +// background-color: gray; +// } -.chat_text { - font-size: 1.2rem; -} +// .position_wrapper { +// background-color: gray; +// } -.x_position { - position: absolute; - bottom: -6rem; - left: 50%; - transform: translateX(-50%); +.slider_label { + font-size: 1.6rem; width: 100%; } - -.y_position { +.x_position_label { position: absolute; - right: -8rem; - top: 50%; - transform: translateY(-50%); - writing-mode: vertical-rl; - text-orientation: mixed; + bottom: -4rem; + right: -30%; + text-align: end; +} +.y_position_label { + position: absolute; + top: -27%; + left: 10%; +} +.z_position_label { + position: absolute; + top: 30%; + left: 80%; +} + +.x_position_slider { + position: absolute; + bottom: 0; + left: 27%; + width: 100%; + height: 0%; +} + +.y_position_slider { + position: absolute; + bottom: 27%; + left: 0; + width: 0%; height: 100%; } -.z_position { +.z_position_slider { position: absolute; - left: -8rem; - top: 50%; - transform: translateY(-50%); - writing-mode: vertical-rl; - text-orientation: mixed; + bottom: 61%; + left: 61%; + transform: translate(50%,50%) rotate(45deg); + width: 0%; height: 100%; } + + + +// .rotation_controls { +// background-color: gray; +// } + +// .rotation_wrapper { +// background-color: gray; +// } + +.x_rotation_label { + position: absolute; + top: -27%; + left: 10%; +} +.y_rotation_label { + position: absolute; + bottom: -4rem; + right: -30%; + text-align: end; +} +.z_rotation_label { + position: absolute; + top: -10%; + right: -110%; +} + +.x_rotation_slider { + position: absolute; + bottom: 27%; + left: 0; + width: 0%; + height: 100%; +} + +.y_rotation_slider { + position: absolute; + bottom: 0; + left: 27%; + width: 100%; + height: 0%; +} + +.z_rotation_slider { + position: absolute; + bottom: 90%; + left: 100%; + transform: translate(50%,50%) rotate(-45deg); + width: 0%; + height: 100%; +} + + + + .other_controls { margin-top: 10rem; display: flex; flex-direction: column; align-items: center; - gap: 1rem; + gap: 2rem; width: 100%; + max-width: 56rem; } -.x_rotation, .y_rotation, .z_rotation, .opacity, .ui_scaling { +.other_controls_wrapper { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + width: 100%; + position: relative; +} +.other_controls_slider { + margin-left: 18rem; +} + +.other_controls_slider_label { + position: absolute; + font-size: 1.6rem; width: 100%; } \ No newline at end of file From 984f989646f0d18257fec1d66f0d96c23cae9287 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:56:17 +0900 Subject: [PATCH 3/6] [bugfix] Config Page: VR Tab. Fix the error "Failed prop type: Invalid prop `valueLabelFormat` supplied to `ForwardRef(Slider2)`, expected one of type [function, string]." It should've put strings but I put number (init value 0) --- .../setting_section/setting_box/_components/slider/Slider.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx index a24cb9dc..7f96bd86 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/_components/slider/Slider.jsx @@ -32,7 +32,7 @@ export const Slider = (props) => { marks={props.marks} track={props.track} orientation={props.orientation} - valueLabelFormat={props.valueLabelFormat ? props.valueLabelFormat : null} + valueLabelFormat={`${props.valueLabelFormat ? props.valueLabelFormat : props.variable}`} sx={{ color: baseColor, "& .MuiSlider-thumb": { From ed24dbd42834de49e32592bcb5cc358017ee2895 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:45:23 +0900 Subject: [PATCH 4/6] [Update] Config Page: VR Tab. Connect to the backend and save the data. --- .../setting_section/setting_box/vr/Vr.jsx | 167 ++++++++++-------- .../setting_box/vr/Vr.module.scss | 39 +++- src-ui/logics/configs/index.js | 3 + .../logics/configs/vr/useOverlaySettings.js | 24 +++ .../configs/vr/useOverlaySmallLogSettings.js | 24 +++ src-ui/logics/useReceiveRoutes.js | 12 ++ src-ui/store.js | 16 ++ 7 files changed, 209 insertions(+), 76 deletions(-) create mode 100644 src-ui/logics/configs/vr/useOverlaySettings.js create mode 100644 src-ui/logics/configs/vr/useOverlaySmallLogSettings.js diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx index b4191672..c16ecfe7 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx @@ -3,15 +3,43 @@ import { useTranslation } from "react-i18next"; import styles from "./Vr.module.scss"; import { Slider } from "../_components/"; import { clsx } from "clsx"; +import { + useOverlaySettings, + useOverlaySmallLogSettings, +} from "@logics_configs"; export const Vr = () => { const { t } = useTranslation(); const [is_opened_position_controller, setIsOpenedPositionController] = useState(true); - const toggleController = () => { setIsOpenedPositionController(!is_opened_position_controller); }; + const { currentOverlaySmallLogSettings, setOverlaySmallLogSettings } = useOverlaySmallLogSettings(); + + + const [settings, setSettings] = useState({ + x_pos: 0, + y_pos: 0, + z_pos: 0, + x_rotation: 0, + y_rotation: 0, + z_rotation: 0, + display_duration: 5, + fadeout_duration: 2, + }); + + const onchangeFunction = (key, value) => { + setSettings((prev) => { + const new_data = { ...prev, [key]: value }; + setOverlaySmallLogSettings(new_data); + return new_data; + }); + }; + + + + const toggle_button_class_names__position = clsx(styles.controller_type_switcher, { [styles.is_selected]: is_opened_position_controller }); @@ -21,6 +49,7 @@ export const Vr = () => { return (
+

Position

@@ -31,23 +60,17 @@ export const Vr = () => {
{is_opened_position_controller - ? - : - } + ? + : + }
- - +
); }; -const PositionControls = () => { +const PositionControls = ({settings, onchangeFunction}) => { const { t } = useTranslation(); - const [position, setPosition] = useState({ x: 0, y: 0, z: 0 }); - - const handlePositionChange = (axis, value) => { - setPosition((prev) => ({ ...prev, [axis]: value })); - }; return (
@@ -55,22 +78,22 @@ const PositionControls = () => { handlePositionChange("x", value)} + variable={settings.x_pos} + step={0.05} + min={-0.5} + max={0.5} + onchangeFunction={(value) => onchangeFunction("x_pos", value)} />
handlePositionChange("y", value)} + variable={settings.y_pos} + step={0.05} + min={-0.8} + max={0.8} + onchangeFunction={(value) => onchangeFunction("y_pos", value)} orientation="vertical" />
@@ -78,25 +101,20 @@ const PositionControls = () => { handlePositionChange("z", value)} + variable={settings.z_pos} + step={0.05} + min={-0.5} + max={1.5} + onchangeFunction={(value) => onchangeFunction("z_pos", value)} orientation="vertical" />
); }; -const RotationControls = () => { + +const RotationControls = ({settings, onchangeFunction}) => { const { t } = useTranslation(); - const [rotation, setRotation] = useState({ rotate_x: 0, rotate_y: 0, rotate_z: 0 }); - - const handleRotationChange = (axis, value) => { - setRotation((prev) => ({ ...prev, [axis]: value })); - }; - return (
@@ -104,12 +122,12 @@ const RotationControls = () => { handleRotationChange("rotate_x", -value)} + onchangeFunction={(value) => onchangeFunction("x_rotation", -value)} orientation="vertical" />
@@ -117,22 +135,22 @@ const RotationControls = () => { handleRotationChange("rotate_y", value)} + onchangeFunction={(value) => onchangeFunction("y_rotation", value)} />
handleRotationChange("rotate_z", value)} + onchangeFunction={(value) => onchangeFunction("z_rotation", value)} orientation="vertical" />
@@ -141,39 +159,34 @@ const RotationControls = () => { }; -const OtherControls = () => { +const CommonControls = () => { const { t } = useTranslation(); + const { currentOverlaySettings, setOverlaySettings } = useOverlaySettings(); const [opacity, setOpacity] = useState(1); - const [ui_scaling, setUiScaling] = useState(100); + const [ui_scaling, setUiScaling] = useState(1); const handleOpacityChange = (value) => { setOpacity(value / 100); + const set_data = { opacity: (value / 100), ui_scaling: ui_scaling }; + setOverlaySettings(set_data); }; const handleUiScalingChange = (value) => { - setUiScaling(value); + setUiScaling(value / 100); + const set_data = { opacity: opacity, ui_scaling: (value / 100) }; + setOverlaySettings(set_data); }; const ui_variable_opacity = (opacity * 100).toFixed(0); - - const [display_duration, setDisplayDuration] = useState(5); - const [fadeout_duration, setFadeoutDuration] = useState(2); - - const handleDisplayDurationChange = (value) => { - setDisplayDuration(value); - }; - - const handleFadeoutDurationChange = (value) => { - setFadeoutDuration(value); - }; + const ui_variable_ui_scaling = (ui_scaling * 100).toFixed(0); return( -
-
- +
+
+ { onchangeFunction={handleOpacityChange} />
-
- +
+
+
+ ); +}; +const OtherControls = ({settings, onchangeFunction}) => { + const { t } = useTranslation(); + + return( +
onchangeFunction("display_duration", value)} />
onchangeFunction("fadeout_duration", value)} />
diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss index 299b3c2d..7a00c692 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss @@ -8,6 +8,7 @@ } .controller_type_switch { + margin-top: 6rem; display: flex; border: 0.1rem solid var(--dark_600_color); border-radius: 0.4rem; @@ -35,11 +36,11 @@ } .position_rotation_controls_box { - margin-top: 14rem; + margin-top: 8rem; position: relative; aspect-ratio: 1 / 1; width: 36%; - max-width: 40rem; + max-width: 36rem; transform: translate(-10%); } @@ -153,8 +154,40 @@ +.common_controls { + padding-top: 4rem; + padding-bottom: 2rem; + display: flex; + flex-direction: column; + align-items: center; + gap: 2rem; + width: 100%; + max-width: 56rem; + border-bottom: 0.1rem solid var(--dark_700_color); +} + +.common_controls_wrapper { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + width: 100%; + position: relative; +} +.common_controls_slider { + margin-left: 18rem; +} + +.common_controls_slider_label { + position: absolute; + font-size: 1.6rem; + width: 100%; +} + + + .other_controls { - margin-top: 10rem; + margin-top: 6rem; display: flex; flex-direction: column; align-items: center; diff --git a/src-ui/logics/configs/index.js b/src-ui/logics/configs/index.js index 9badb2fd..d5cdffab 100644 --- a/src-ui/logics/configs/index.js +++ b/src-ui/logics/configs/index.js @@ -31,6 +31,9 @@ export { useSpeakerRecordTimeout } from "./transcription/useSpeakerRecordTimeout export { useSpeakerPhraseTimeout } from "./transcription/useSpeakerPhraseTimeout"; export { useSpeakerMaxWords } from "./transcription/useSpeakerMaxWords"; +export { useOverlaySettings } from "./vr/useOverlaySettings"; +export { useOverlaySmallLogSettings } from "./vr/useOverlaySmallLogSettings"; + export { useOscIpAddress } from "./advanced_settings/useOscIpAddress"; export { useOscPort } from "./advanced_settings/useOscPort"; diff --git a/src-ui/logics/configs/vr/useOverlaySettings.js b/src-ui/logics/configs/vr/useOverlaySettings.js new file mode 100644 index 00000000..3394c800 --- /dev/null +++ b/src-ui/logics/configs/vr/useOverlaySettings.js @@ -0,0 +1,24 @@ +import { useStore_OverlaySettings } from "@store"; +import { useStdoutToPython } from "@logics/useStdoutToPython"; + +export const useOverlaySettings = () => { + const { asyncStdoutToPython } = useStdoutToPython(); + const { currentOverlaySettings, updateOverlaySettings, pendingOverlaySettings } = useStore_OverlaySettings(); + + const getOverlaySettings = () => { + // pendingOverlaySettings(); + asyncStdoutToPython("/get/data/overlay_settings"); + }; + + const setOverlaySettings = (overlay_settings) => { + // pendingOverlaySettings(); + asyncStdoutToPython("/set/data/overlay_settings", overlay_settings); + }; + + return { + currentOverlaySettings, + getOverlaySettings, + updateOverlaySettings, + setOverlaySettings, + }; +}; \ No newline at end of file diff --git a/src-ui/logics/configs/vr/useOverlaySmallLogSettings.js b/src-ui/logics/configs/vr/useOverlaySmallLogSettings.js new file mode 100644 index 00000000..03b61393 --- /dev/null +++ b/src-ui/logics/configs/vr/useOverlaySmallLogSettings.js @@ -0,0 +1,24 @@ +import { useStore_OverlaySmallLogSettings } from "@store"; +import { useStdoutToPython } from "@logics/useStdoutToPython"; + +export const useOverlaySmallLogSettings = () => { + const { asyncStdoutToPython } = useStdoutToPython(); + const { currentOverlaySmallLogSettings, updateOverlaySmallLogSettings, pendingOverlaySmallLogSettings } = useStore_OverlaySmallLogSettings(); + + const getOverlaySmallLogSettings = () => { + // pendingOverlaySmallLogSettings(); + asyncStdoutToPython("/get/data/overlay_small_log_settings"); + }; + + const setOverlaySmallLogSettings = (overlay_small_log_settings) => { + // pendingOverlaySmallLogSettings(); + asyncStdoutToPython("/set/data/overlay_small_log_settings", overlay_small_log_settings); + }; + + return { + currentOverlaySmallLogSettings, + getOverlaySmallLogSettings, + updateOverlaySmallLogSettings, + setOverlaySmallLogSettings, + }; +}; \ No newline at end of file diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js index fe75557d..639edfd1 100644 --- a/src-ui/logics/useReceiveRoutes.js +++ b/src-ui/logics/useReceiveRoutes.js @@ -45,6 +45,8 @@ import { useSpeakerRecordTimeout, useSpeakerPhraseTimeout, useSpeakerMaxWords, + useOverlaySettings, + useOverlaySmallLogSettings, useOscIpAddress, useOscPort, } from "@logics_configs"; @@ -113,6 +115,9 @@ export const useReceiveRoutes = () => { const { updateSpeakerPhraseTimeout } = useSpeakerPhraseTimeout(); const { updateSpeakerMaxWords } = useSpeakerMaxWords(); + const { updateOverlaySettings } = useOverlaySettings(); + const { updateOverlaySmallLogSettings } = useOverlaySmallLogSettings(); + const { updateOscIpAddress } = useOscIpAddress(); const { updateOscPort } = useOscPort(); @@ -311,6 +316,13 @@ export const useReceiveRoutes = () => { "/get/data/speaker_max_phrases": updateSpeakerMaxWords, "/set/data/speaker_max_phrases": updateSpeakerMaxWords, + // VR + "/get/data/overlay_settings": updateOverlaySettings, + "/set/data/overlay_settings": updateOverlaySettings, + + "/get/data/overlay_small_log_settings": updateOverlaySmallLogSettings, + "/set/data/overlay_small_log_settings": updateOverlaySmallLogSettings, + // Others Tab "/get/data/auto_clear_message_box": updateEnableAutoClearMessageInputBox, "/set/enable/auto_clear_message_box": updateEnableAutoClearMessageInputBox, diff --git a/src-ui/store.js b/src-ui/store.js index 2bb95a9d..856a24cb 100644 --- a/src-ui/store.js +++ b/src-ui/store.js @@ -189,6 +189,22 @@ export const { atomInstance: Atom_SpeakerRecordTimeout, useHook: useStore_Speake export const { atomInstance: Atom_SpeakerPhraseTimeout, useHook: useStore_SpeakerPhraseTimeout } = createAtomWithHook(0, "SpeakerPhraseTimeout"); export const { atomInstance: Atom_SpeakerMaxWords, useHook: useStore_SpeakerMaxWords } = createAtomWithHook(0, "SpeakerMaxWords"); +// VR +export const { atomInstance: Atom_OverlaySettings, useHook: useStore_OverlaySettings } = createAtomWithHook({ + opacity: 1.0, + ui_scaling: 1.0, +}, "OverlaySettings"); +export const { atomInstance: Atom_OverlaySmallLogSettings, useHook: useStore_OverlaySmallLogSettings } = createAtomWithHook({ + x_pos: 0.0, + y_pos: 0.0, + z_pos: 0.0, + x_rotation: 0.0, + y_rotation: 0.0, + z_rotation: 0.0, + display_duration: 5, + fadeout_duration: 2, +}, "OverlaySmallLogSettings"); + // Others export const { atomInstance: Atom_EnableAutoClearMessageInputBox, useHook: useStore_EnableAutoClearMessageInputBox } = createAtomWithHook(true, "EnableAutoClearMessageInputBox"); export const { atomInstance: Atom_EnableSendOnlyTranslatedMessages, useHook: useStore_EnableSendOnlyTranslatedMessages } = createAtomWithHook(false, "EnableSendOnlyTranslatedMessages"); From 54388746681b0da23e512c9b22ab0807d0725b8a Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:18:07 +0900 Subject: [PATCH 5/6] [Update] Config Page: VR Tab. Add delay when send and save the settings data to the backend. --- .../setting_section/setting_box/vr/Vr.jsx | 145 +++++++++++------- 1 file changed, 88 insertions(+), 57 deletions(-) diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx index c16ecfe7..faf524d2 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import styles from "./Vr.module.scss"; import { Slider } from "../_components/"; @@ -17,7 +17,6 @@ export const Vr = () => { const { currentOverlaySmallLogSettings, setOverlaySmallLogSettings } = useOverlaySmallLogSettings(); - const [settings, setSettings] = useState({ x_pos: 0, y_pos: 0, @@ -32,19 +31,31 @@ export const Vr = () => { const onchangeFunction = (key, value) => { setSettings((prev) => { const new_data = { ...prev, [key]: value }; - setOverlaySmallLogSettings(new_data); return new_data; }); }; + useEffect(() => { + let settings_timeout; + if (settings_timeout) { + clearTimeout(settings_timeout); + } + settings_timeout = setTimeout(() => { + setOverlaySmallLogSettings(settings); + }, 50); + + return () => { + clearTimeout(settings_timeout); + }; + }, [settings]); const toggle_button_class_names__position = clsx(styles.controller_type_switcher, { - [styles.is_selected]: is_opened_position_controller + [styles.is_selected]: is_opened_position_controller, }); const toggle_button_class_names__rotation = clsx(styles.controller_type_switcher, { - [styles.is_selected]: !is_opened_position_controller + [styles.is_selected]: !is_opened_position_controller, }); return ( @@ -69,6 +80,78 @@ export const Vr = () => { ); }; + + + +const CommonControls = () => { + const { t } = useTranslation(); + const { currentOverlaySettings, setOverlaySettings } = useOverlaySettings(); + + const [settings, setSettings] = useState({ + opacity: 1, + ui_scaling: 1, + }); + + const onchangeFunction = (key, value) => { + setSettings((prev) => { + const new_data = { ...prev, [key]: value }; + return new_data; + }); + }; + + + useEffect(() => { + let settings_timeout; + + settings_timeout = setTimeout(() => { + setOverlaySettings(settings); + }, 50); + + return () => { + clearTimeout(settings_timeout); + }; + }, [settings]); + + const ui_variable_opacity = (settings.opacity * 100).toFixed(0); + const ui_variable_ui_scaling = (settings.ui_scaling * 100).toFixed(0); + + return ( +
+
+ + onchangeFunction("opacity", value / 100)} + /> +
+
+ + onchangeFunction("ui_scaling", value / 100)} + /> +
+
+ ); +}; + + + + const PositionControls = ({settings, onchangeFunction}) => { const { t } = useTranslation(); @@ -158,58 +241,6 @@ const RotationControls = ({settings, onchangeFunction}) => { ); }; - -const CommonControls = () => { - const { t } = useTranslation(); - const { currentOverlaySettings, setOverlaySettings } = useOverlaySettings(); - const [opacity, setOpacity] = useState(1); - const [ui_scaling, setUiScaling] = useState(1); - - const handleOpacityChange = (value) => { - setOpacity(value / 100); - const set_data = { opacity: (value / 100), ui_scaling: ui_scaling }; - setOverlaySettings(set_data); - }; - - const handleUiScalingChange = (value) => { - setUiScaling(value / 100); - const set_data = { opacity: opacity, ui_scaling: (value / 100) }; - setOverlaySettings(set_data); - }; - - const ui_variable_opacity = (opacity * 100).toFixed(0); - const ui_variable_ui_scaling = (ui_scaling * 100).toFixed(0); - - - return( -
-
- - -
-
- - -
-
- ); -}; const OtherControls = ({settings, onchangeFunction}) => { const { t } = useTranslation(); From 33bb2c7620147ec6de8972cfd8dd4f2d40194896 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:02:53 +0900 Subject: [PATCH 6/6] [bugfix] Config Page: VR Tab. Fix the bug that the settings data has sent to the backend when init. --- .../setting_section/setting_box/vr/Vr.jsx | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx index faf524d2..92bc97cf 100644 --- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import styles from "./Vr.module.scss"; import { Slider } from "../_components/"; @@ -28,28 +28,26 @@ export const Vr = () => { fadeout_duration: 2, }); + const [timeout_id, setTimeoutId] = useState(null); + const onchangeFunction = (key, value) => { setSettings((prev) => { const new_data = { ...prev, [key]: value }; return new_data; }); - }; - useEffect(() => { - let settings_timeout; - - if (settings_timeout) { - clearTimeout(settings_timeout); + if (timeout_id) { + clearTimeout(timeout_id); } - settings_timeout = setTimeout(() => { - setOverlaySmallLogSettings(settings); + const newTimeoutId = setTimeout(() => { + let new_data = settings; + new_data[key] = value; + setOverlaySmallLogSettings(new_data); }, 50); - return () => { - clearTimeout(settings_timeout); - }; - }, [settings]); + setTimeoutId(newTimeoutId); + }; const toggle_button_class_names__position = clsx(styles.controller_type_switcher, { [styles.is_selected]: is_opened_position_controller, @@ -80,9 +78,6 @@ export const Vr = () => { ); }; - - - const CommonControls = () => { const { t } = useTranslation(); const { currentOverlaySettings, setOverlaySettings } = useOverlaySettings(); @@ -92,25 +87,26 @@ const CommonControls = () => { ui_scaling: 1, }); + const [timeout_id, setTimeoutId] = useState(null); + const onchangeFunction = (key, value) => { setSettings((prev) => { const new_data = { ...prev, [key]: value }; return new_data; }); - }; + if (timeout_id) { + clearTimeout(timeout_id); + } - useEffect(() => { - let settings_timeout; - - settings_timeout = setTimeout(() => { + const newTimeoutId = setTimeout(() => { + let new_data = settings; + new_data[key] = value; setOverlaySettings(settings); }, 50); - return () => { - clearTimeout(settings_timeout); - }; - }, [settings]); + setTimeoutId(newTimeoutId); + }; const ui_variable_opacity = (settings.opacity * 100).toFixed(0); const ui_variable_ui_scaling = (settings.ui_scaling * 100).toFixed(0);