mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-10 11:16:10 +01:00
animation pause button
This commit is contained in:
4 files changed
+47
No files matched your search
@@ -1,8 +1,10 @@
|
|||||||
import { alias } from "@blitzkit/core";
|
import { alias } from "@blitzkit/core";
|
||||||
|
import { PauseIcon, PlayIcon } from "@radix-ui/react-icons";
|
||||||
import { uniqBy } from "lodash-es";
|
import { uniqBy } from "lodash-es";
|
||||||
import { api } from "../../api/dynamic";
|
import { api } from "../../api/dynamic";
|
||||||
import { SKIN_NUMBER } from "../../constants/skinNumber";
|
import { SKIN_NUMBER } from "../../constants/skinNumber";
|
||||||
import { DuelModule, useDuel } from "../../hooks/useDuel";
|
import { DuelModule, useDuel } from "../../hooks/useDuel";
|
||||||
|
import { hasSkinAnimations } from "../../hooks/useSkin";
|
||||||
import { useUnwrapper } from "../../hooks/useUnwrapper";
|
import { useUnwrapper } from "../../hooks/useUnwrapper";
|
||||||
import { Tankopedia } from "../../stores/tankopedia";
|
import { Tankopedia } from "../../stores/tankopedia";
|
||||||
import { TankopediaDisplay } from "../../stores/tankopediaPersistent/constants";
|
import { TankopediaDisplay } from "../../stores/tankopediaPersistent/constants";
|
||||||
@@ -20,6 +22,11 @@ export function TankopediaSkinSwitcher() {
|
|||||||
const skin = Tankopedia.use((state) => state.loaders.skin.requested);
|
const skin = Tankopedia.use((state) => state.loaders.skin.requested);
|
||||||
const showControls = Tankopedia.use((state) => state.showControls);
|
const showControls = Tankopedia.use((state) => state.showControls);
|
||||||
const display = Tankopedia.use((state) => state.loaders.display.loaded);
|
const display = Tankopedia.use((state) => state.loaders.display.loaded);
|
||||||
|
const loadedSkin = Tankopedia.use((state) => state.loaders.skin.loaded);
|
||||||
|
const loadedAttachment = Tankopedia.use(
|
||||||
|
(state) => state.loaders.attachment.loaded,
|
||||||
|
);
|
||||||
|
const playing = Tankopedia.use((state) => state.animate);
|
||||||
|
|
||||||
const skins = uniqBy(
|
const skins = uniqBy(
|
||||||
Object.values(camouflageDefinitions.camouflages).filter(
|
Object.values(camouflageDefinitions.camouflages).filter(
|
||||||
@@ -36,6 +43,11 @@ export function TankopediaSkinSwitcher() {
|
|||||||
].filter((group) => group.length > 0);
|
].filter((group) => group.length > 0);
|
||||||
|
|
||||||
const isVisible = showControls && display === TankopediaDisplay.Model;
|
const isVisible = showControls && display === TankopediaDisplay.Model;
|
||||||
|
const hasAnimations =
|
||||||
|
hasSkinAnimations(tank.id, loadedSkin) ||
|
||||||
|
hasSkinAnimations(tank.id, loadedAttachment);
|
||||||
|
|
||||||
|
console.log("hasAnimations", hasAnimations);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["skin-switcher"]} data-visible={isVisible}>
|
<div className={styles["skin-switcher"]} data-visible={isVisible}>
|
||||||
@@ -80,6 +92,26 @@ export function TankopediaSkinSwitcher() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{hasAnimations && (
|
||||||
|
<Tooltip
|
||||||
|
tooltip={playing ? "Pause animations" : "Play animations"}
|
||||||
|
side="left"
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
color="gray"
|
||||||
|
variant="soft"
|
||||||
|
size="major"
|
||||||
|
onClick={() => {
|
||||||
|
Tankopedia.mutate((draft) => {
|
||||||
|
draft.animate = !draft.animate;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{playing ? <PauseIcon /> : <PlayIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -79,6 +79,14 @@ function skinPath(id: number, skin: number) {
|
|||||||
return alias("models_legendary", `/${id}/skins/${skin}.glb`);
|
return alias("models_legendary", `/${id}/skins/${skin}.glb`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** whether an already loaded skin of this tank has animations */
|
||||||
|
export function hasSkinAnimations(id: number, skin: number | undefined) {
|
||||||
|
return (
|
||||||
|
skin !== undefined &&
|
||||||
|
loadedSkins.get(skinPath(id, skin))?.mixer !== undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// attachments load the same way as camouflages and can be shown with one
|
// attachments load the same way as camouflages and can be shown with one
|
||||||
export function useSkin(id: number, loader: "skin" | "attachment" = "skin") {
|
export function useSkin(id: number, loader: "skin" | "attachment" = "skin") {
|
||||||
const requested = Tankopedia.use((state) => state.loaders[loader].requested);
|
const requested = Tankopedia.use((state) => state.loaders[loader].requested);
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import { invalidate, useFrame } from "@react-three/fiber";
|
import { invalidate, useFrame } from "@react-three/fiber";
|
||||||
|
import { Tankopedia } from "../stores/tankopedia";
|
||||||
import type { Skin } from "./useSkin";
|
import type { Skin } from "./useSkin";
|
||||||
|
|
||||||
export function useSkinAnimation(skins: Skin[]) {
|
export function useSkinAnimation(skins: Skin[]) {
|
||||||
|
const animate = Tankopedia.use((state) => state.animate);
|
||||||
|
|
||||||
useFrame((_, delta) => {
|
useFrame((_, delta) => {
|
||||||
|
if (animate) return;
|
||||||
|
|
||||||
for (const { mixer } of skins) {
|
for (const { mixer } of skins) {
|
||||||
if (!mixer) continue;
|
if (!mixer) continue;
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ interface Tankopedia {
|
|||||||
disturbed: boolean;
|
disturbed: boolean;
|
||||||
revealed: boolean;
|
revealed: boolean;
|
||||||
showControls: boolean;
|
showControls: boolean;
|
||||||
|
animate: boolean;
|
||||||
|
|
||||||
protagonist: TankState;
|
protagonist: TankState;
|
||||||
antagonist: TankState;
|
antagonist: TankState;
|
||||||
@@ -131,6 +132,7 @@ export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>(
|
|||||||
disturbed: false,
|
disturbed: false,
|
||||||
revealed: false,
|
revealed: false,
|
||||||
showControls: false,
|
showControls: false,
|
||||||
|
animate: true,
|
||||||
|
|
||||||
protagonist: createTankState(tank),
|
protagonist: createTankState(tank),
|
||||||
antagonist: createTankState(tank),
|
antagonist: createTankState(tank),
|
||||||
|
|||||||
Reference in new issue
Block a user