Skip to content

Commit

Permalink
feat(Star Map): Add an editor palette for updating properties of sola…
Browse files Browse the repository at this point in the history
…r systems.
  • Loading branch information
alexanderson1993 committed Mar 28, 2022
1 parent ee662d5 commit 877156c
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 17 deletions.
5 changes: 4 additions & 1 deletion client/src/components/ui/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ interface CommonProps {
const Input = (
props:
| (React.InputHTMLAttributes<HTMLInputElement> & {
as?: "input" | "textarea";
as?: "input";
} & CommonProps)
| (React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
as: "textarea";
} & CommonProps)
| (React.SelectHTMLAttributes<HTMLSelectElement> & {
as: "select";
Expand Down
4 changes: 3 additions & 1 deletion client/src/context/netSend.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {AllInputNames, AllInputParams, AllInputReturns} from "@thorium/inputs";
import {getTabId} from "@thorium/tab-id";

type UnPromise<T> = T extends Promise<infer U> ? UnPromise<U> : T;

export async function netSend<
InputName extends AllInputNames,
Params extends AllInputParams[InputName],
Return extends AllInputReturns[InputName]
>(type: InputName, params?: Params): Promise<Return> {
>(type: InputName, params?: Params): Promise<UnPromise<Return>> {
const clientId = await getTabId();
const body = new FormData();
body.append("input", type.toString());
Expand Down
107 changes: 93 additions & 14 deletions client/src/pages/Config/Starmap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {IoMdClose} from "react-icons/io";
import {FaMinus, FaTimes} from "react-icons/fa";
import Input from "@thorium/ui/Input";
import {useLocalStorage} from "client/src/hooks/useLocalStorage";
import debounce from "lodash.debounce";
const FAR = 1e27;

interface SceneRef {
Expand Down Expand Up @@ -73,11 +74,16 @@ function useSynchronizeSystemId() {
return storedSystemId;
}

function EditorPalette() {
const [[x, y], setXY] = useLocalStorage(
"starmapEditorPalettePosition",
[0, 0]
);
function EditorPalette({
isOpen,
onClose,
children,
}: {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}) {
const [[x, y], setXY] = useLocalStorage("editorPalettePosition", [0, 0]);

const bind = useDrag(
({offset: [x, y]}) => {
Expand All @@ -89,9 +95,8 @@ function EditorPalette() {
}
);
const [minimized, setMinimized] = useState(false);
const selectedItem = useStarmapStore(store => store.selectedObjectId);

if (!selectedItem) return null;
if (!isOpen) return null;

return (
<Portal>
Expand All @@ -110,7 +115,7 @@ function EditorPalette() {
>
<button
className="p-1 ml-1 rounded-full hover:bg-white/10 cursor-pointer"
onClick={() => useStarmapStore.setState({selectedObjectId: null})}
onClick={onClose}
aria-label="Close"
>
<FaTimes />
Expand All @@ -124,16 +129,85 @@ function EditorPalette() {
<FaMinus />
</button>
</div>
{minimized ? null : (
<div className="w-full h-full overflow-y-auto p-2 text-white">
<Input label="Name" />
</div>
)}
{minimized ? null : children}
</animated.div>
</Portal>
);
}

const InterstellarPalette = () => {
const {pluginId} = useParams() as {
pluginId: string;
};
const selectedObjectId = useStarmapStore(store => store.selectedObjectId);
const stars = useNetRequest("pluginSolarSystems", {pluginId});

const selectedStar = stars.find(s => s.name === selectedObjectId);

useEffect(() => {
if (!selectedStar) {
useStarmapStore.setState({selectedObjectId: null});
}
}, []);

const [name, setName] = useState(selectedStar?.name || "");
const [description, setDescription] = useState(
selectedStar?.description || ""
);

const update = React.useMemo(
() =>
debounce(
async (params: {name?: string; description?: string}) => {
if (!selectedObjectId) return;
const result = await netSend("pluginSolarSystemUpdate", {
pluginId,
solarSystemId: selectedObjectId,
...params,
});
if (params.name) {
useStarmapStore.setState({selectedObjectId: result.solarSystemId});
}
},
500,
{maxWait: 2000, trailing: true}
),
[pluginId, selectedObjectId]
);

useEffect(() => {
if (!selectedStar) return;
setName(selectedStar.name);
setDescription(selectedStar.description);
}, [selectedStar?.name, selectedStar?.description]);

return (
<div className="w-full h-full overflow-y-auto p-2 text-white">
<Input
label="Name"
value={name}
onChange={e => {
setName(e.target.value);
update({name: e.target.value});
}}
name="name"
/>
<Input
label="Description"
as="textarea"
rows={5}
className="resize-none"
value={description}
onChange={e => {
setDescription(e.target.value);
update({description: e.target.value});
}}
name="description"
/>
</div>
);
};

export default function StarMap() {
const {pluginId} = useParams() as {
pluginId: string;
Expand Down Expand Up @@ -223,7 +297,12 @@ export default function StarMap() {
Edit
</Button>
</Menubar>
<EditorPalette />
<EditorPalette
isOpen={!!selectedObjectId}
onClose={() => useStarmapStore.setState({selectedObjectId: null})}
>
{systemId ? null : <InterstellarPalette />}
</EditorPalette>
<div className="h-[calc(100%-2rem)] relative bg-black">
<Canvas
onContextMenu={e => {
Expand Down
9 changes: 8 additions & 1 deletion server/src/inputs/plugins/universe/solarSystems.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import SolarSystemPlugin from "server/src/classes/Plugins/Universe/SolarSystem";
import {DataContext} from "server/src/utils/DataContext";
import {generateIncrementedName} from "server/src/utils/generateIncrementedName";
import {pubsub} from "server/src/utils/pubsub";
import {AstronomicalUnit, LightMinute} from "server/src/utils/unitTypes";
import {getPlugin} from "../utils";
Expand Down Expand Up @@ -72,7 +73,13 @@ export const solarSystemsPluginInputs = {
);
if (!solarSystem) return {solarSystemId: ""};
if (params.position) solarSystem.position = params.position;
if (params.name) solarSystem.name = params.name;
if (params.name) {
let name = generateIncrementedName(
params.name,
plugin.aspects.solarSystems.map(solarSystem => solarSystem.name)
);
solarSystem.name = name;
}
if (params.description) solarSystem.description = params.description;
if (params.tags) solarSystem.tags = params.tags;
if (params.habitableZoneInner)
Expand Down

0 comments on commit 877156c

Please sign in to comment.