/** @jsx jsx */ import React, { useState, useEffect, useRef } from 'react' import { jsx, css } from '@emotion/core' import styled from '@emotion/styled' import * as skinview3d from 'skinview3d' import { t } from '@/scripts/i18n' import * as cssUtils from '@/styles/utils' import * as breakpoints from '@/styles/breakpoints' import SkinSteve from '../../../misc/textures/steve.png' import bg1 from '../../../misc/backgrounds/1.png' import bg2 from '../../../misc/backgrounds/2.png' import bg3 from '../../../misc/backgrounds/3.png' import bg4 from '../../../misc/backgrounds/4.png' import bg5 from '../../../misc/backgrounds/5.png' import bg6 from '../../../misc/backgrounds/6.png' import bg7 from '../../../misc/backgrounds/7.png' const backgrounds = [bg1, bg2, bg3, bg4, bg5, bg6, bg7] export const PICTURES_COUNT = backgrounds.length interface Props { skin?: string cape?: string isAlex: boolean showIndicator?: boolean initPositionZ?: number } type ViewerStuff = { handles: { walk: skinview3d.AnimationHandle run: skinview3d.AnimationHandle rotate: skinview3d.AnimationHandle } control: skinview3d.OrbitControls firstRun: boolean } const emptyStuff: ViewerStuff = { handles: { walk: {} as skinview3d.AnimationHandle, run: {} as skinview3d.AnimationHandle, rotate: {} as skinview3d.AnimationHandle, }, control: {} as skinview3d.OrbitControls, firstRun: true, } const ActionButton = styled.i` display: inline; padding: 0.5em 0.5em; &:hover { color: #555; cursor: pointer; } ` const cssCardBody = css` background-repeat: no-repeat; background-position: center; background-size: cover; ` const cssViewer = css` ${breakpoints.greaterThan(breakpoints.Breakpoint.lg)} { min-height: 500px; } canvas { cursor: move; } ` const Viewer: React.FC = (props) => { const { initPositionZ = 70 } = props const viewRef: React.MutableRefObject = useRef(null!) const containerRef = useRef(null) const stuffRef = useRef(emptyStuff) const [paused, setPaused] = useState(false) const [running, setRunning] = useState(false) const [reset, setReset] = useState(0) const [background, setBackground] = useState('#fff') const [bgPicture, setBgPicture] = useState(0) const indicator = (() => { const { skin, cape } = props if (skin && cape) { return `${t('general.skin')} & ${t('general.cape')}` } else if (skin) { return t('general.skin') } else if (cape) { return t('general.cape') } return '' })() useEffect(() => { const container = containerRef.current! const viewer = new skinview3d.SkinViewer({ domElement: container, width: container.clientWidth, height: container.clientHeight, skinUrl: props.skin || SkinSteve, capeUrl: props.cape || '', detectModel: false, }) viewer.camera.position.z = initPositionZ viewer.playerObject.skin.slim = props.isAlex const animation = new skinview3d.CompositeAnimation() stuffRef.current.handles = { walk: animation.add(skinview3d.WalkingAnimation), run: animation.add(skinview3d.RunningAnimation), rotate: animation.add(skinview3d.RotatingAnimation), } stuffRef.current.handles.run.paused = true // @ts-ignore viewer.animation = animation as skinview3d.Animation stuffRef.current.control = skinview3d.createOrbitControls(viewer) if (!stuffRef.current.firstRun) { const { handles } = stuffRef.current handles.walk.paused = true handles.run.paused = true handles.rotate.paused = true viewer.camera.position.z = 70 } viewRef.current = viewer return () => { viewer.dispose() stuffRef.current.firstRun = false } }, [reset]) useEffect(() => { return () => { stuffRef.current.firstRun = true } }, []) useEffect(() => { const viewer = viewRef.current viewer.skinUrl = props.skin || SkinSteve }, [props.skin]) useEffect(() => { const viewer = viewRef.current if (props.cape) { viewer.capeUrl = props.cape } else { viewer.playerObject.cape.visible = false } }, [props.cape]) useEffect(() => { const viewer = viewRef.current viewer.playerObject.skin.slim = props.isAlex }, [props.isAlex]) const togglePause = () => { setPaused((paused) => !paused) viewRef.current.animationPaused = !viewRef.current.animationPaused } const toggleRun = () => { setRunning((running) => !running) const { handles } = stuffRef.current handles.run.paused = !handles.run.paused handles.walk.paused = false } const toggleRotate = () => { const { handles } = stuffRef.current handles.rotate.paused = !handles.rotate.paused } const handleReset = () => { setReset((c) => c + 1) } const setWhite = () => setBackground('#fff') const setGray = () => setBackground('#6c757d') const setBlack = () => setBackground('#000') const setPrevPicture = () => { let index = bgPicture if (bgPicture <= 0) { index = PICTURES_COUNT - 1 } else { index -= 1 } setBgPicture(index) setBackground(`url('${backgrounds[index]}')`) } const setNextPicture = () => { let index = bgPicture if (bgPicture >= PICTURES_COUNT - 1) { index = 1 } else { index += 1 } setBgPicture(index) setBackground(`url('${backgrounds[index]}')`) } return (

{t('general.texturePreview')} {props.showIndicator && ( {indicator} )}

{props.children}
) } export default Viewer