mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Readded camera plugin, hotgroups, fixed smoke spawning
This commit is contained in:
@@ -8,7 +8,7 @@ export function OlStateButton(props: {
|
||||
className?: string;
|
||||
buttonColor?: string | null;
|
||||
checked: boolean;
|
||||
icon: IconProp;
|
||||
icon?: IconProp;
|
||||
tooltip: string;
|
||||
onClick: () => void;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
@@ -20,14 +20,16 @@ export function OlStateButton(props: {
|
||||
(props.className ?? "") +
|
||||
`
|
||||
h-[40px] w-[40px] flex-none rounded-md text-lg font-medium
|
||||
dark:bg-olympus-600 dark:text-gray-300 dark:hover:bg-olympus-300
|
||||
dark:bg-olympus-600 dark:text-gray-300
|
||||
`;
|
||||
|
||||
let textColor = "white";
|
||||
if (props.checked && props.buttonColor == "white") {
|
||||
textColor = "#243141"
|
||||
if ((props.checked || hover) && props.buttonColor == "white") {
|
||||
textColor = "#243141";
|
||||
}
|
||||
|
||||
const opacity = (hover && !props.checked) ? "AA" : "FF";
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
@@ -41,7 +43,7 @@ export function OlStateButton(props: {
|
||||
className={className}
|
||||
style={{
|
||||
border: props.buttonColor ? "2px solid " + props.buttonColor : "0px solid transparent",
|
||||
background: props.checked ? (props.buttonColor? props.buttonColor: "#3b82f6"): "#243141",
|
||||
background: props.checked || hover ? (props.buttonColor ? props.buttonColor : "#3b82f6" + opacity) : "#243141" + opacity,
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setHover(true);
|
||||
@@ -51,7 +53,7 @@ export function OlStateButton(props: {
|
||||
}}
|
||||
>
|
||||
<div className="m-auto flex w-fit content-center justify-center gap-2">
|
||||
<FontAwesomeIcon icon={props.icon} className="m-auto" style={{color: textColor}} />
|
||||
{props.icon && <FontAwesomeIcon icon={props.icon} className="m-auto" style={{ color: textColor }} />}
|
||||
{props.children}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { faArrowLeft, faClose } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FaChevronDown, FaChevronUp } from "react-icons/fa";
|
||||
import { HideMenuEvent } from "../../../events";
|
||||
|
||||
export function Menu(props: {
|
||||
title: string;
|
||||
@@ -15,7 +16,11 @@ export function Menu(props: {
|
||||
const [hide, setHide] = useState(true);
|
||||
|
||||
if (!props.open && hide) setHide(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
HideMenuEvent.dispatch(hide)
|
||||
}, [hide])
|
||||
|
||||
return (
|
||||
<div
|
||||
data-open={props.open}
|
||||
|
||||
@@ -62,7 +62,7 @@ export function EffectSpawnMenu(props: { effect: string }) {
|
||||
setSmokeColor(optionSmokeColor);
|
||||
}}
|
||||
tooltip=""
|
||||
borderColor={optionSmokeColor}
|
||||
buttonColor={optionSmokeColor}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -61,177 +61,187 @@ export function Header() {
|
||||
}
|
||||
|
||||
return (
|
||||
<nav
|
||||
<nav
|
||||
className={`
|
||||
z-10 flex w-full gap-4 border-gray-200 bg-gray-300 px-3 drop-shadow-md
|
||||
align-center
|
||||
dark:border-gray-800 dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
<img src="images/icon.png" className={`my-auto h-10 w-10 rounded-md p-0`}></img>
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
className={`
|
||||
z-10 flex w-full gap-4 border-gray-200 bg-gray-300 px-3
|
||||
drop-shadow-md align-center
|
||||
dark:border-gray-800 dark:bg-olympus-900
|
||||
absolute left-14 h-full w-6 rounded-lg px-2 py-3.5 text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={`
|
||||
my-2 flex w-full items-center gap-3 overflow-x-scroll no-scrollbar
|
||||
`}
|
||||
onScroll={(ev) => onScroll(ev.target)}
|
||||
ref={scrollRef}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
mr-auto hidden flex-none flex-row items-center justify-start gap-6
|
||||
lg:flex
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src="images/icon.png"
|
||||
className={`my-auto h-10 w-10 rounded-md p-0`}
|
||||
></img>
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
<div className="flex flex-col items-start">
|
||||
<div
|
||||
className={`
|
||||
absolute left-14 h-full w-6 rounded-lg px-2 py-3.5 text-gray-200
|
||||
dark:bg-olympus-900
|
||||
pt-1 text-xs text-gray-800
|
||||
dark:text-gray-400
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
Connected to
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-center gap-2 text-sm font-extrabold
|
||||
text-gray-800
|
||||
dark:text-gray-200
|
||||
`}
|
||||
>
|
||||
{IP}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{commandModeOptions.commandMode === BLUE_COMMANDER && (
|
||||
<div
|
||||
className={`
|
||||
my-2 flex w-full items-center gap-3 overflow-x-scroll no-scrollbar
|
||||
`}
|
||||
onScroll={(ev) => onScroll(ev.target)}
|
||||
ref={scrollRef}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
mr-auto hidden flex-none flex-row items-center justify-start
|
||||
gap-6
|
||||
lg:flex
|
||||
`}
|
||||
>
|
||||
<div className="flex flex-col items-start">
|
||||
<div
|
||||
className={`
|
||||
pt-1 text-xs text-gray-800
|
||||
dark:text-gray-400
|
||||
`}
|
||||
>
|
||||
Connected to
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-center gap-2 text-sm
|
||||
font-extrabold text-gray-800
|
||||
dark:text-gray-200
|
||||
`}
|
||||
>
|
||||
{IP}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{commandModeOptions.commandMode === BLUE_COMMANDER && <div className={`
|
||||
flex h-full rounded-md bg-blue-600 px-4 text-white
|
||||
`}><span className="my-auto font-bold">BLUE Commander ({commandModeOptions.spawnPoints.blue} points)</span></div>}
|
||||
<div
|
||||
className={`flex h-fit flex-row items-center justify-start gap-1`}
|
||||
>
|
||||
<OlLockStateButton
|
||||
checked={!mapOptions.protectDCSUnits}
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("protectDCSUnits", !mapOptions.protectDCSUnits);
|
||||
}}
|
||||
tooltip="Lock/unlock protected units (from scripted mission)"
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
checked={audioEnabled}
|
||||
onClick={() => {
|
||||
audioEnabled ? getApp().getAudioManager().stop() : getApp().getAudioManager().start();
|
||||
setAudioEnabled(!audioEnabled);
|
||||
}}
|
||||
tooltip="Enable/disable audio and radio backend"
|
||||
icon={faVolumeHigh}
|
||||
/>
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div
|
||||
className={`flex h-fit flex-row items-center justify-start gap-1`}
|
||||
>
|
||||
{Object.entries({
|
||||
human: olButtonsVisibilityHuman,
|
||||
olympus: olButtonsVisibilityOlympus,
|
||||
dcs: olButtonsVisibilityDcs,
|
||||
}).map((entry) => {
|
||||
return (
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp().getMap().setHiddenType(entry[0], !mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
tooltip={"Hide/show " + entry[0] + " units"}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div
|
||||
className={`flex h-fit flex-row items-center justify-start gap-1`}
|
||||
>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("blue", !mapHiddenTypes["blue"])}
|
||||
checked={!mapHiddenTypes["blue"]}
|
||||
icon={faFlag}
|
||||
className={"!text-blue-500"}
|
||||
tooltip={"Hide/show blue units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("red", !mapHiddenTypes["red"])}
|
||||
checked={!mapHiddenTypes["red"]}
|
||||
icon={faFlag}
|
||||
className={"!text-red-500"}
|
||||
tooltip={"Hide/show red units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("neutral", !mapHiddenTypes["neutral"])}
|
||||
checked={!mapHiddenTypes["neutral"]}
|
||||
icon={faFlag}
|
||||
className={"!text-gray-500"}
|
||||
tooltip={"Hide/show neutral units"}
|
||||
/>
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div
|
||||
className={`flex h-fit flex-row items-center justify-start gap-1`}
|
||||
>
|
||||
{Object.entries({
|
||||
aircraft: olButtonsVisibilityAircraft,
|
||||
helicopter: olButtonsVisibilityHelicopter,
|
||||
"groundunit-sam": olButtonsVisibilityGroundunitSam,
|
||||
groundunit: olButtonsVisibilityGroundunit,
|
||||
navyunit: olButtonsVisibilityNavyunit,
|
||||
airbase: olButtonsVisibilityAirbase,
|
||||
dead: faSkull,
|
||||
}).map((entry) => {
|
||||
return (
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp().getMap().setHiddenType(entry[0], !mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
tooltip={"Hide/show " + entry[0] + " units"}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<OlLabelToggle toggled={false} leftLabel={"Live"} rightLabel={"Map"} onClick={() => {}}></OlLabelToggle>
|
||||
<OlStateButton checked={false} icon={faCamera} onClick={() => {}} tooltip="Activate/deactivate camera plugin" />
|
||||
<OlDropdown label={mapSource} className="w-60">
|
||||
{mapSources.map((source) => {
|
||||
return (
|
||||
<OlDropdownItem key={source} onClick={() => getApp().getMap().setLayerName(source)}>
|
||||
<div className="truncate">{source}</div>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
`}
|
||||
>
|
||||
<span className="my-auto font-bold">BLUE Commander ({commandModeOptions.spawnPoints.blue} points)</span>
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5 text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</nav>
|
||||
)}
|
||||
<div className={`flex h-fit flex-row items-center justify-start gap-1`}>
|
||||
<OlLockStateButton
|
||||
checked={!mapOptions.protectDCSUnits}
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("protectDCSUnits", !mapOptions.protectDCSUnits);
|
||||
}}
|
||||
tooltip="Lock/unlock protected units (from scripted mission)"
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
checked={audioEnabled}
|
||||
onClick={() => {
|
||||
audioEnabled ? getApp().getAudioManager().stop() : getApp().getAudioManager().start();
|
||||
setAudioEnabled(!audioEnabled);
|
||||
}}
|
||||
tooltip="Enable/disable audio and radio backend"
|
||||
icon={faVolumeHigh}
|
||||
/>
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div className={`flex h-fit flex-row items-center justify-start gap-1`}>
|
||||
{Object.entries({
|
||||
human: olButtonsVisibilityHuman,
|
||||
olympus: olButtonsVisibilityOlympus,
|
||||
dcs: olButtonsVisibilityDcs,
|
||||
}).map((entry) => {
|
||||
return (
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp().getMap().setHiddenType(entry[0], !mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
tooltip={"Hide/show " + entry[0] + " units"}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div className={`flex h-fit flex-row items-center justify-start gap-1`}>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("blue", !mapHiddenTypes["blue"])}
|
||||
checked={!mapHiddenTypes["blue"]}
|
||||
icon={faFlag}
|
||||
className={"!text-blue-500"}
|
||||
tooltip={"Hide/show blue units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("red", !mapHiddenTypes["red"])}
|
||||
checked={!mapHiddenTypes["red"]}
|
||||
icon={faFlag}
|
||||
className={"!text-red-500"}
|
||||
tooltip={"Hide/show red units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() => getApp().getMap().setHiddenType("neutral", !mapHiddenTypes["neutral"])}
|
||||
checked={!mapHiddenTypes["neutral"]}
|
||||
icon={faFlag}
|
||||
className={"!text-gray-500"}
|
||||
tooltip={"Hide/show neutral units"}
|
||||
/>
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div className={`flex h-fit flex-row items-center justify-start gap-1`}>
|
||||
{Object.entries({
|
||||
aircraft: olButtonsVisibilityAircraft,
|
||||
helicopter: olButtonsVisibilityHelicopter,
|
||||
"groundunit-sam": olButtonsVisibilityGroundunitSam,
|
||||
groundunit: olButtonsVisibilityGroundunit,
|
||||
navyunit: olButtonsVisibilityNavyunit,
|
||||
airbase: olButtonsVisibilityAirbase,
|
||||
dead: faSkull,
|
||||
}).map((entry) => {
|
||||
return (
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp().getMap().setHiddenType(entry[0], !mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
tooltip={"Hide/show " + entry[0] + " units"}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<OlLabelToggle
|
||||
toggled={mapOptions.cameraPluginMode === "live"}
|
||||
leftLabel={"Live"}
|
||||
rightLabel={"Map"}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("cameraPluginMode", mapOptions.cameraPluginMode === "live" ? "map" : "live");
|
||||
}}
|
||||
></OlLabelToggle>
|
||||
<OlStateButton
|
||||
checked={mapOptions.cameraPluginEnabled}
|
||||
icon={faCamera}
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("cameraPluginEnabled", !mapOptions.cameraPluginEnabled);
|
||||
}}
|
||||
tooltip="Activate/deactivate camera plugin"
|
||||
/>
|
||||
<OlDropdown label={mapSource} className="w-60">
|
||||
{mapSources.map((source) => {
|
||||
return (
|
||||
<OlDropdownItem key={source} onClick={() => getApp().getMap().setLayerName(source)}>
|
||||
<div className="truncate">{source}</div>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5 text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
53
frontend/react/src/ui/panels/hotgroupsbar.tsx
Normal file
53
frontend/react/src/ui/panels/hotgroupsbar.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { AppStateChangedEvent, ContextActionChangedEvent, HideMenuEvent, HotgroupsChangedEvent, InfoPopupEvent } from "../../events";
|
||||
import { OlympusState } from "../../constants/constants";
|
||||
import { ContextAction } from "../../unit/contextaction";
|
||||
import { OlStateButton } from "../components/olstatebutton";
|
||||
import { faUserGroup } from "@fortawesome/free-solid-svg-icons";
|
||||
import { getApp } from "../../olympusapp";
|
||||
|
||||
export function HotGroupBar(props: {}) {
|
||||
const [hotgroups, setHotgroups] = useState({} as { [key: number]: number });
|
||||
const [appState, setAppState] = useState(OlympusState.NOT_INITIALIZED);
|
||||
const [menuHidden, setMenuHidden] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
AppStateChangedEvent.on((state, subState) => setAppState(state));
|
||||
HideMenuEvent.on((hidden) => setMenuHidden(hidden));
|
||||
HotgroupsChangedEvent.on((hotgroups) => setHotgroups({ ...hotgroups }));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-menuhidden={menuHidden || appState === OlympusState.IDLE}
|
||||
className={`
|
||||
absolute bottom-16 left-[50%] flex gap-2
|
||||
data-[menuhidden='false']:translate-x-[calc(200px-50%+2rem)]
|
||||
data-[menuhidden='true']:translate-x-[calc(-50%+2rem)]
|
||||
`}
|
||||
>
|
||||
{Object.entries(hotgroups).map(([hotgroup, counter]) => {
|
||||
return (
|
||||
<div className="flex flex-col content-center gap-2">
|
||||
<div
|
||||
className={`
|
||||
mx-auto aspect-square rotate-45 rounded-sm bg-olympus-900
|
||||
text-center text-xs font-bold text-gray-200
|
||||
`}
|
||||
>
|
||||
<div className="relative -rotate-45">{hotgroup}</div>
|
||||
</div>
|
||||
|
||||
<OlStateButton checked={false} onClick={() => {getApp().getUnitsManager().selectUnitsByHotgroup(parseInt(hotgroup))}} tooltip="">
|
||||
<span
|
||||
className={`text-sm text-white`}
|
||||
>
|
||||
{counter}
|
||||
</span>
|
||||
</OlStateButton>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { AppStateChangedEvent, ContextActionChangedEvent, InfoPopupEvent } from "../../events";
|
||||
import { AppStateChangedEvent, ContextActionChangedEvent, HideMenuEvent, InfoPopupEvent } from "../../events";
|
||||
import { OlympusState } from "../../constants/constants";
|
||||
import { ContextAction } from "../../unit/contextaction";
|
||||
|
||||
@@ -7,17 +7,19 @@ export function InfoBar(props: {}) {
|
||||
const [messages, setMessages] = useState([] as string[]);
|
||||
const [appState, setAppState] = useState(OlympusState.NOT_INITIALIZED);
|
||||
const [contextAction, setContextAction] = useState(null as ContextAction | null);
|
||||
const [menuHidden, setMenuHidden] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
InfoPopupEvent.on((messages) => setMessages([...messages]));
|
||||
AppStateChangedEvent.on((state, subState) => setAppState(state));
|
||||
ContextActionChangedEvent.on((contextAction) => setContextAction(contextAction));
|
||||
HideMenuEvent.on((hidden) => setMenuHidden(hidden));
|
||||
}, []);
|
||||
|
||||
let topString = "";
|
||||
if (appState === OlympusState.UNIT_CONTROL) {
|
||||
if (contextAction === null) {
|
||||
topString = "top-32";
|
||||
topString = "top-36";
|
||||
} else {
|
||||
topString = "top-48";
|
||||
}
|
||||
@@ -27,19 +29,21 @@ export function InfoBar(props: {}) {
|
||||
|
||||
return (
|
||||
<div
|
||||
data-menuhidden={menuHidden || appState === OlympusState.IDLE}
|
||||
className={`
|
||||
absolute left-[50%]
|
||||
data-[menuhidden='false']:translate-x-[calc(200px-50%+2rem)]
|
||||
data-[menuhidden='true']:translate-x-[calc(-50%+2rem)]
|
||||
${topString}
|
||||
flex w-[400px] max-w-[80%] translate-x-[calc(-50%+2rem)]
|
||||
`}
|
||||
>
|
||||
{messages.map((message, idx) => {
|
||||
{messages.slice(Math.max(0, messages.length - 4), Math.max(0, messages.length)).map((message, idx) => {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
absolute left-0 w-full gap-2 rounded-md bg-olympus-800/90 px-4
|
||||
py-2 text-center text-sm text-white backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
absolute w-fit translate-x-[-50%] gap-2 text-nowrap rounded-full
|
||||
bg-olympus-800/90 px-4 py-2 text-center text-sm text-white
|
||||
shadow-md backdrop-blur-lg backdrop-grayscale
|
||||
`}
|
||||
style={{ top: `${idx * 20}px` }}
|
||||
>
|
||||
|
||||
@@ -199,35 +199,49 @@ export function OptionsMenu(props: { open: boolean; onClose: () => void; childre
|
||||
</kbd>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
<hr className="w-auto m-2 my-1 bg-gray-700 border-[1px] dark:border-olympus-500"></hr>
|
||||
<div className="flex flex-col content-center items-start justify-between p-2 gap-2">
|
||||
|
||||
<hr className={`
|
||||
m-2 my-1 w-auto border-[1px] bg-gray-700
|
||||
dark:border-olympus-500
|
||||
`}></hr>
|
||||
<div className={`
|
||||
flex flex-col content-center items-start justify-between gap-2 p-2
|
||||
`}>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-normal dark:text-white">DCS Camera Zoom Scaling</span>
|
||||
<span className="dark:text-blue-500 font-bold"> x5
|
||||
</span>
|
||||
<span className={`
|
||||
font-normal
|
||||
dark:text-white
|
||||
`}>DCS Camera Zoom Scaling</span>
|
||||
|
||||
</div>
|
||||
<OlRangeSlider
|
||||
onChange={() => { }}
|
||||
value={5}
|
||||
min={1}
|
||||
max={10}
|
||||
step={2}
|
||||
onChange={(ev) => {
|
||||
getApp().getMap().setOption("cameraPluginRatio", parseInt(ev.target.value))
|
||||
}}
|
||||
value={mapOptions.cameraPluginRatio}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col content-center items-start justify-between p-2 gap-2">
|
||||
<span className="font-normal dark:text-white">DCS Camera Port</span>
|
||||
<div className={`
|
||||
flex flex-col content-center items-start justify-between gap-2 p-2
|
||||
`}>
|
||||
<span className={`
|
||||
font-normal
|
||||
dark:text-white
|
||||
`}>DCS Camera Port</span>
|
||||
<div className="flex">
|
||||
<OlNumberInput
|
||||
value={3004}
|
||||
value={mapOptions.cameraPluginPort}
|
||||
min={0}
|
||||
max={9999}
|
||||
onDecrease={() => { }}
|
||||
onIncrease={() => { }}
|
||||
onChange={(ev) => { }}
|
||||
onDecrease={() => { getApp().getMap().setOption("cameraPluginPort", mapOptions.cameraPluginPort - 1) }}
|
||||
onIncrease={() => { getApp().getMap().setOption("cameraPluginPort", mapOptions.cameraPluginPort + 1) }}
|
||||
onChange={(ev) => { getApp().getMap().setOption("cameraPluginPort", ev.target.value)}}
|
||||
/>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { CONTEXT_ACTION_COLORS } from "../../constants/constants";
|
||||
import { FaInfoCircle } from "react-icons/fa";
|
||||
import { FaChevronLeft, FaChevronRight } from "react-icons/fa6";
|
||||
import { OlympusState } from "../../constants/constants";
|
||||
import { AppStateChangedEvent, ContextActionChangedEvent, ContextActionSetChangedEvent } from "../../events";
|
||||
import { AppStateChangedEvent, ContextActionChangedEvent, ContextActionSetChangedEvent, HideMenuEvent } from "../../events";
|
||||
|
||||
export function UnitControlBar(props: {}) {
|
||||
const [appState, setAppState] = useState(OlympusState.NOT_INITIALIZED);
|
||||
@@ -15,6 +15,7 @@ export function UnitControlBar(props: {}) {
|
||||
const [contextAction, setContextAction] = useState(null as ContextAction | null);
|
||||
const [scrolledLeft, setScrolledLeft] = useState(true);
|
||||
const [scrolledRight, setScrolledRight] = useState(false);
|
||||
const [menuHidden, setMenuHidden] = useState(false);
|
||||
|
||||
/* Initialize the "scroll" position of the element */
|
||||
var scrollRef = useRef(null);
|
||||
@@ -26,6 +27,7 @@ export function UnitControlBar(props: {}) {
|
||||
AppStateChangedEvent.on((state, subState) => setAppState(state));
|
||||
ContextActionSetChangedEvent.on((contextActionSet) => setcontextActionSet(contextActionSet));
|
||||
ContextActionChangedEvent.on((contextAction) => setContextAction(contextAction));
|
||||
HideMenuEvent.on((hidden) => setMenuHidden(hidden));
|
||||
}, []);
|
||||
|
||||
function onScroll(el) {
|
||||
@@ -48,10 +50,13 @@ export function UnitControlBar(props: {}) {
|
||||
{appState === OlympusState.UNIT_CONTROL && contextActionSet && Object.keys(contextActionSet.getContextActions()).length > 0 && (
|
||||
<>
|
||||
<div
|
||||
data-menuhidden={menuHidden}
|
||||
className={`
|
||||
absolute left-[50%] top-16 flex max-w-[80%]
|
||||
translate-x-[calc(-50%+2rem)] gap-2 rounded-md bg-gray-200
|
||||
absolute left-[50%] top-16 flex max-w-[80%] gap-2 rounded-md
|
||||
bg-gray-200
|
||||
dark:bg-olympus-900
|
||||
data-[menuhidden='false']:translate-x-[calc(200px-50%+2rem)]
|
||||
data-[menuhidden='true']:translate-x-[calc(-50%+2rem)]
|
||||
`}
|
||||
>
|
||||
{!scrolledLeft && (
|
||||
|
||||
@@ -37,6 +37,7 @@ import { JTACMenu } from "./panels/jtacmenu";
|
||||
import { AppStateChangedEvent, MapOptionsChangedEvent } from "../events";
|
||||
import { GameMasterMenu } from "./panels/gamemastermenu";
|
||||
import { InfoBar } from "./panels/infobar";
|
||||
import { HotGroupBar } from "./panels/hotgroupsbar";
|
||||
|
||||
export type OlympusUIState = {
|
||||
mainMenuVisible: boolean;
|
||||
@@ -161,6 +162,7 @@ export function UI() {
|
||||
<MapContextMenu />
|
||||
<SideBar />
|
||||
<InfoBar />
|
||||
<HotGroupBar />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user