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 8f61d725..827c0253 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 @@ -4,44 +4,107 @@ import MUI_Slider from "@mui/material/Slider"; import clsx from "clsx"; export const Slider = (props) => { + const location = props.valueLabelDisplayLocation || "top"; + + const sliderSx = { + color: "var(--dark_700_color)", + "& .MuiSlider-thumb": { + backgroundColor: "var(--primary_600_color)", + "&:hover, &.Mui-focusVisible, &.Mui-active": { + boxShadow: `0 0 0 0.8rem var(--primary_600_color_44)`, + }, + "& .MuiSlider-valueLabel": { + position: "absolute", + backgroundColor: "var(--dark_800_color)", + width: "fit-content", + minWidth: "4.8rem", + padding: "0.4rem 0.8rem", + lineHeight: "1.15", + "& .MuiSlider-valueLabelLabel": { + fontSize: "1.4rem", + }, + ...(location === "top" && { + top: "-110%", + left: "50%", + transform: "translate(-50%, -50%) scale(0)", + transformOrigin: "bottom center", + "&.MuiSlider-valueLabelOpen": { + transform: "translate(-50%, -50%) scale(1)", + }, + "&::before": { + bottom: "0%", + left: "50%", + }, + }), + ...(location === "right" && { + top: "50%", + left: "150%", + transform: "translate(0, -50%) scale(0)", + transformOrigin: "left center", + "&.MuiSlider-valueLabelOpen": { + transform: "translate(0, -50%) scale(1)", + }, + "&::before": { + bottom: "50%", + left: "0", + }, + }), + ...(location === "left" && { + // top: "50%", + // right: "50%", + // transform: "translate(-50%, -50%) scale(0)", + // transformOrigin: "bottom center", + // "&.MuiSlider-valueLabelOpen": { + // transform: "translate(-50%, -50%) scale(1)", + // }, + // "&::before": { + // bottom: "50%", + // left: "100%", + // }, + }), + }, + }, + "& .MuiSlider-markLabel": { + fontSize: "1.4rem", + color: "var(--dark_550_color)", + whiteSpace: "nowrap", + }, + "& .MuiSlider-markLabelActive": { + color: "var(--primary_300_color)", + }, + }; + return ( -
+
props.onchangeFunction(value)} - onChangeCommitted={(_e, value) => props.onchangeCommittedFunction ? props.onchangeCommittedFunction(value) : null} + onChangeCommitted={(_e, value) => + props.onchangeCommittedFunction ? props.onchangeCommittedFunction(value) : null + } + onMouseEnter={(event) => + props.onMouseEnterFunction ? props.onMouseEnterFunction(event) : null + } + onMouseLeave={(event) => + props.onMouseLeaveFunction ? props.onMouseLeaveFunction(event) : null + } marks={props.marks} track={props.track} orientation={props.orientation} valueLabelFormat={`${props.valueLabelFormat ? props.valueLabelFormat : props.variable}`} - sx={{ - color: "var(--dark_700_color)", - "& .MuiSlider-thumb": { - backgroundColor: "var(--primary_600_color)", - "&:hover, &.Mui-focusVisible, &.Mui-active": { - boxShadow: `0 0 0 0.8rem var(--primary_600_color_44)`, - }, - "& .MuiSlider-valueLabel": { - fontSize: "1.4rem", - backgroundColor: "var(--dark_800_color)", - padding: "0.6rem 1rem", - lineHeight: "1.15", - }, - }, - "& .MuiSlider-markLabel": { - fontSize: "1.4rem", - color: "var(--dark_550_color)", - whiteSpace: "nowrap", - }, - "& .MuiSlider-markLabelActive": { - color: "var(--primary_300_color)", - }, - }} + sx={sliderSx} />
); 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 06920712..b145bb44 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, useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import clsx from "clsx"; import styles from "./Vr.module.scss"; @@ -25,6 +25,10 @@ import { import RedoSvg from "@images/redo.svg?react"; +import SquareSvg from "@images/square.svg?react"; +import TriangleSvg from "@images/triangle.svg?react"; +import { randomIntMinMax } from "@utils"; + export const Vr = () => { const { t } = useTranslation(); const [is_opened_small_settings, setIsOpenedSmallSettings] = useState(true); @@ -147,7 +151,7 @@ const OverlaySettingsContainer = ({ ) : ( )} - +
{ ); }; -const PositionControls = ({settings, onchangeFunction, selectFunction, ui_configs, default_ui_configs}) => { + +export const PositionControls = ({ settings, onchangeFunction, selectFunction, ui_configs, default_ui_configs }) => { const { t } = useTranslation(); + const { + variable_display: x_variable_display, + is_max: is_max_position_x, + is_min: is_min_position_x, + countUp: countUpPositionX, + countDown: countDownPositionX, + } = useVariableControl("x_pos", settings, onchangeFunction, ui_configs); + + const { + variable_display: y_variable_display, + is_max: is_max_position_y, + is_min: is_min_position_y, + countUp: countUpPositionY, + countDown: countDownPositionY, + } = useVariableControl("y_pos", settings, onchangeFunction, ui_configs); + + const { + variable_display: z_variable_display, + is_max: is_max_position_z, + is_min: is_min_position_z, + countUp: countUpPositionZ, + countDown: countDownPositionZ, + } = useVariableControl("z_pos", settings, onchangeFunction, ui_configs); + return (
@@ -205,8 +234,18 @@ const PositionControls = ({settings, onchangeFunction, selectFunction, ui_config min={ui_configs.x_pos.min} max={ui_configs.x_pos.max} onchangeFunction={(value) => onchangeFunction("x_pos", value)} + valueLabelDisplay={x_variable_display} + valueLabelDisplayLocation="top" + /> +
+

{t("config_page.vr.y_position")} @@ -221,8 +260,18 @@ const PositionControls = ({settings, onchangeFunction, selectFunction, ui_config max={ui_configs.y_pos.max} onchangeFunction={(value) => onchangeFunction("y_pos", value)} orientation="vertical" + valueLabelDisplay={y_variable_display} + valueLabelDisplayLocation="right" + /> +

+

{t("config_page.vr.z_position")} @@ -237,69 +286,162 @@ const PositionControls = ({settings, onchangeFunction, selectFunction, ui_config max={ui_configs.z_pos.max} onchangeFunction={(value) => onchangeFunction("z_pos", value)} orientation="vertical" + valueLabelDisplay={z_variable_display} + valueLabelDisplayLocation="left" + /> +

); }; -const RotationControls = ({settings, onchangeFunction, selectFunction, default_ui_configs}) => { +export const RotationControls = ({ settings, onchangeFunction, selectFunction, ui_configs, default_ui_configs }) => { const { t } = useTranslation(); + const { + variable_display: x_variable_display, + is_max: is_max_rotation_x, + is_min: is_min_rotation_x, + countUp: countUpRotationX, + countDown: countDownRotationX, + } = useVariableControl("x_rotation", settings, onchangeFunction, ui_configs); + + const { + variable_display: y_variable_display, + is_max: is_max_rotation_y, + is_min: is_min_rotation_y, + countUp: countUpRotationY, + countDown: countDownRotationY, + } = useVariableControl("y_rotation", settings, onchangeFunction, ui_configs); + + const { + variable_display: z_variable_display, + is_max: is_max_rotation_z, + is_min: is_min_rotation_z, + countUp: countUpRotationZ, + countDown: countDownRotationZ, + } = useVariableControl("z_rotation", settings, onchangeFunction, ui_configs); + return (

{t("config_page.vr.x_rotation")} - selectFunction("x_rotation", default_ui_configs.y_pos)} /> + selectFunction("x_rotation", default_ui_configs.x_rotation)} />

onchangeFunction("x_rotation", -value)} orientation="vertical" + valueLabelDisplay={x_variable_display} + valueLabelDisplayLocation="right" + /> +
+

{t("config_page.vr.y_rotation")} - selectFunction("y_rotation", default_ui_configs.y_pos)} /> + selectFunction("y_rotation", default_ui_configs.y_rotation)} />

onchangeFunction("y_rotation", value)} + valueLabelDisplay={y_variable_display} + valueLabelDisplayLocation="top" + /> +
+

{t("config_page.vr.z_rotation")} - selectFunction("z_rotation", default_ui_configs.y_pos)} /> + selectFunction("z_rotation", default_ui_configs.z_rotation)} />

onchangeFunction("z_rotation", value)} orientation="vertical" + valueLabelDisplay={z_variable_display} + valueLabelDisplayLocation="left" + /> +
); }; +const AdjustButtonContainer = ({ wrapper_class_name, is_max, is_min, countUp, countDown }) => { + return ( +
+
+ +
+
+ +
+
+ ); +}; + + const OtherControls = ({settings, onchangeFunction, ui_configs}) => { const { t } = useTranslation(); @@ -393,10 +535,6 @@ const ResetButton = ({onClickFunction}) => { ); }; -import SquareSvg from "@images/square.svg?react"; -import TriangleSvg from "@images/triangle.svg?react"; -import { randomIntMinMax } from "@utils"; - const SendSampleTextToggleButton = () => { const { t } = useTranslation(); const { sendTextToOverlay } = useSendTextToOverlay(); @@ -445,4 +583,58 @@ const SendSampleTextToggleButton = () => {

{label}

); +}; + + + +const useVariableControl = (key, settings, onchangeFunction, ui_configs) => { + const [variable_display, setVariableDisplay] = useState("auto"); + + const [is_max, setIsMax] = useState(settings[key] >= ui_configs[key].max); + const [is_min, setIsMin] = useState(settings[key] <= ui_configs[key].min); + + const timerRef = useRef(); + + useEffect(() => { + return () => { + clearTimeout(timerRef.current); + }; + }, []); + + const triggerDisplay = () => { + setVariableDisplay("on"); + clearTimeout(timerRef.current); + timerRef.current = setTimeout(() => { + setVariableDisplay("auto"); + }, 2000); + }; + + useEffect(() => { + setIsMax(settings[key] >= ui_configs[key].max); + setIsMin(settings[key] <= ui_configs[key].min); + }, [settings[key]]); + + const countUp = () => { + if (is_max) return; + const step = ui_configs[key].step; + const new_value = parseFloat((settings[key] + step).toFixed(2)); + onchangeFunction(key, new_value); + triggerDisplay(); + }; + + const countDown = () => { + if (is_min) return; + const step = ui_configs[key].step; + const new_value = parseFloat((settings[key] - step).toFixed(2)); + onchangeFunction(key, new_value); + triggerDisplay(); + }; + + return { + variable_display, + is_max, + is_min, + countUp, + countDown, + }; }; \ 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 35798530..9d0963e8 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 @@ -16,7 +16,7 @@ justify-content: center; width: 100%; max-width: 56rem; - gap: 2rem; + gap: 4rem; } .controller_type_switch { @@ -58,12 +58,13 @@ .sample_text_button_wrapper { position: absolute; - bottom: 0; - left: -74%; + bottom: -12%; + left: -80%; display: flex; justify-content: center; align-items: center; flex-direction: column; + // transform: translate(-50%, -50%); } .sample_text_button { background-color: var(--dark_850_color); @@ -121,20 +122,20 @@ } .x_position_label { position: absolute; - bottom: -4.6rem; + bottom: -5rem; right: -46%; justify-content: end; } .y_position_label { position: absolute; - top: -44%; - left: 10%; - justify-content: start; + bottom: 110%; + right: 119%; + justify-content: end; } .z_position_label { position: absolute; - top: 30%; - left: 80%; + top: 14%; + left: 110%; } .x_position_slider { @@ -155,14 +156,84 @@ .z_position_slider { position: absolute; - bottom: 61%; - left: 61%; + bottom: 80%; + left: 88%; transform: translate(50%,50%) rotate(45deg); width: 0%; height: 100%; } +%variable-button { + width: 3.8rem; + border-radius: 0.4rem; + aspect-ratio: 1.2 / 1; + background-color: var(--dark_850_color); + display: flex; + justify-content: center; + align-items: center; + font-size: 1.6rem; + cursor: pointer; + + &:hover { + background-color: var(--primary_500_color); + } + &:active { + background-color: var(--primary_600_color); + } + &.is_disabled { + pointer-events: none; + background-color: var(--dark_875_color); + & .adjust_button_triangle_svg { + color: var(--dark_800_color); + } + } +} + +@mixin variable-button-wrapper($vertical-pos, $vertical-value, $horizontal-pos, $horizontal-value, $rotate: 0deg) { + position: absolute; + #{$vertical-pos}: $vertical-value; + #{$horizontal-pos}: $horizontal-value; + display: flex; + gap: 1.6rem; + flex-direction: column; + transform: translate(-50%) rotate($rotate); +} + +.button_wrapper { + @extend %variable-button; + + &.up .adjust_button_triangle_svg { + transform: rotate(0deg); + } + &:not(.up) .adjust_button_triangle_svg { + transform: rotate(180deg); + } + &.is_disabled { + pointer-events: none; + color: var(--dark_875_color); + } +} + +.adjust_button_triangle_svg { + width: 1.8rem; + color: var(--dark_400_color); +} + + + +.y_position_button_wrapper { + @include variable-button-wrapper(top, 30%, left, -26%); +} + +.x_position_button_wrapper { + @include variable-button-wrapper(bottom, -38%, left, 46%, 90deg); +} + +.z_position_button_wrapper { + @include variable-button-wrapper(bottom, 26%, right, -4%, 45deg); +} + // .rotation_controls { @@ -175,19 +246,20 @@ .x_rotation_label { position: absolute; - top: -44%; - left: 10%; + bottom: 110%; + right: 119%; + justify-content: end; } .y_rotation_label { position: absolute; - bottom: -4.6rem; + bottom: -5rem; right: -46%; justify-content: end; } .z_rotation_label { position: absolute; - top: -10%; - right: -110%; + top: -20%; + right: -100%; } .x_rotation_slider { @@ -216,6 +288,21 @@ } + +.x_rotation_button_wrapper { + @include variable-button-wrapper(top, 30%, left, -26%); +} + +.y_rotation_button_wrapper { + @include variable-button-wrapper(bottom, -38%, left, 46%, 90deg); +} + +.z_rotation_button_wrapper { + @include variable-button-wrapper(bottom, 50%, right, -60%, -45deg); +} + + + .slider_reset_button { background-color: var(--dark_875_color); padding: 0.6rem; diff --git a/src-ui/ui_configs.js b/src-ui/ui_configs.js index d6ef28eb..915d6a6b 100644 --- a/src-ui/ui_configs.js +++ b/src-ui/ui_configs.js @@ -7,12 +7,18 @@ export const ui_configs = { x_pos: { step: 0.05, min: -0.5, max: 0.5 }, y_pos: { step: 0.05, min: -0.8, max: 0.8 }, z_pos: { step: 0.05, min: -0.5, max: 1.5 }, + x_rotation: { min: -180, max: 180, step: 5 }, + y_rotation: { min: -180, max: 180, step: 5 }, + z_rotation: { min: -180, max: 180, step: 5 }, ui_scaling: { step: 10, min: 40, max: 200 }, }, overlay_large_log: { x_pos: { step: 0.05, min: -0.5, max: 0.5 }, y_pos: { step: 0.05, min: -0.8, max: 0.8 }, z_pos: { step: 0.05, min: -0.5, max: 1.5 }, + x_rotation: { min: -180, max: 180, step: 5 }, + y_rotation: { min: -180, max: 180, step: 5 }, + z_rotation: { min: -180, max: 180, step: 5 }, ui_scaling: { step: 10, min: 40, max: 200 }, },