blacktrigram 0.7.44 → 0.7.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/audio/AudioManager.d.ts +26 -0
- package/lib/audio/AudioManager.d.ts.map +1 -1
- package/lib/audio/AudioManager.js +26 -0
- package/lib/audio/AudioManager.js.map +1 -1
- package/lib/audio/index.d.ts.map +1 -1
- package/lib/audio/index.js.map +1 -1
- package/lib/audio/types.d.ts +18 -2
- package/lib/audio/types.d.ts.map +1 -1
- package/lib/audio/types.js +1 -0
- package/lib/audio/types.js.map +1 -1
- package/lib/components/effects/WindParticles3D.d.ts.map +1 -1
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js.map +1 -1
- package/lib/components/screens/combat/CombatScreen3D.d.ts.map +1 -1
- package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts +0 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.js +0 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.js.map +1 -1
- package/lib/components/screens/combat/components/controls/PauseMenu.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/PauseMenu.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ArterialSpray3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodDecals3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodDecals3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodParticles3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodViscosity3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodViscosity3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BoneCrackParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ConsciousnessBlur.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ConsciousnessBlur.js.map +1 -1
- package/lib/components/screens/combat/components/effects/DustClouds3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/EarthCrackEffect3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/EarthHealingEffect3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ImpactSparks3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/InternalDamage3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/InternalDamage3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/LiPrecisionTargetingOverlay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/NerveStrikeParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/PainVignette.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/PainVignette.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ParticleAudio3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ParticleAudio3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/TraumaOverlay3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/TraumaOverlay3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/WaterRipple3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/WaterWave3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/index.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/MatchCountdown.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/MatchCountdown.js.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatBottomHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatBottomHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatLeftHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatLeftHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatRightHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatRightHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatTopHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatTopHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.js.map +1 -1
- package/lib/components/screens/combat/components/hud/FPSMonitor.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/FPSMonitor.js.map +1 -1
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/BalanceIndicator.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/BalanceIndicator.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts +0 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js +0 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/StaminaWarning.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/StaminaWarning.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts +0 -2
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js +0 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js.map +1 -1
- package/lib/components/screens/combat/helpers/AnimationUpdater.d.ts.map +1 -1
- package/lib/components/screens/combat/helpers/AnimationUpdater.js.map +1 -1
- package/lib/components/screens/combat/helpers/combatHelpers.d.ts.map +1 -1
- package/lib/components/screens/combat/helpers/combatHelpers.js.map +1 -1
- package/lib/components/screens/combat/hooks/useAICombat.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useAICombat.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatActions.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatActions.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAttackMovement.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAttackMovement.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAudio.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAudio.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatLayout.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatLayout.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatState.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatState.js.map +1 -1
- package/lib/components/screens/combat/hooks/useGrapplingAudio.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/usePreloadCombatAudio.d.ts.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.d.ts.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.js.map +1 -1
- package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.js.map +1 -1
- package/lib/components/screens/controls/components/GamepadVisualization3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/GamepadVisualization3D.js.map +1 -1
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js.map +1 -1
- package/lib/components/screens/controls/components/Key3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/Key3D.js.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.js.map +1 -1
- package/lib/components/screens/controls/constants/ControlsConstants.d.ts.map +1 -1
- package/lib/components/screens/controls/constants/ControlsConstants.js.map +1 -1
- package/lib/components/screens/controls/hooks/useControlsState.d.ts.map +1 -1
- package/lib/components/screens/controls/hooks/useControlsState.js.map +1 -1
- package/lib/components/screens/endscreen/EndScreen3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/EndScreen3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/DefeatAnimation3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/DefeatAnimation3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/VictoryAnimation3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/VictoryAnimation3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/index.d.ts.map +1 -1
- package/lib/components/screens/endscreen/index.d.ts.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.d.ts.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js.map +1 -1
- package/lib/components/screens/intro/components/AbilityListOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/AbilityListOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/MenuSectionOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/MenuSectionOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/StatBarOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/StatBarOverlayHtml.js.map +1 -1
- package/lib/components/screens/philosophy/PhilosophyScreen3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/PhilosophyScreen3D.js.map +1 -1
- package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts +0 -1
- package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts +0 -1
- package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts +0 -1
- package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts.map +1 -1
- package/lib/components/screens/training/TrainingScreen3D.d.ts.map +1 -1
- package/lib/components/screens/training/TrainingScreen3D.js.map +1 -1
- package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/AnatomyOverlay3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/AnatomyOverlay3D.js.map +1 -1
- package/lib/components/screens/training/components/DamageNumber3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootPlacementMarkers3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootPlacementMarkers3D.js.map +1 -1
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/HitFeedbackEffect3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/HitFeedbackEffect3D.js.map +1 -1
- package/lib/components/screens/training/components/TrainingAICharacter3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingArena3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingControlsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingControlsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingDummy3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingDummy3D.js.map +1 -1
- package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingHitEffects3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingStatsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingStatsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/VitalPointMarker3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/VitalPointMarker3D.js.map +1 -1
- package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingBottomHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingBottomHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingLeftHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingLeftHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingRightHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingRightHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.js.map +1 -1
- package/lib/components/screens/training/components/index.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useAttackMovement.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useAttackMovement.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingActions.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingActions.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingLayout.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingLayout.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingState.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingState.js.map +1 -1
- package/lib/components/shared/base/AccessibilityProvider.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButton.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButton.js.map +1 -1
- package/lib/components/shared/base/BaseButtonOverlayHtml.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButtonOverlayHtml.js.map +1 -1
- package/lib/components/shared/base/BasePanel.d.ts.map +1 -1
- package/lib/components/shared/base/BasePanel.js.map +1 -1
- package/lib/components/shared/base/BaseText.d.ts.map +1 -1
- package/lib/components/shared/base/BaseText.js.map +1 -1
- package/lib/components/shared/base/ResponsiveContainer.d.ts.map +1 -1
- package/lib/components/shared/base/index.d.ts.map +1 -1
- package/lib/components/shared/base/useKoreanTheme.d.ts.map +1 -1
- package/lib/components/shared/base/useKoreanTheme.js.map +1 -1
- package/lib/components/shared/debug/PerformanceDebugOverlayHtml.d.ts.map +1 -1
- package/lib/components/shared/debug/PerformanceDebugOverlayHtml.js.map +1 -1
- package/lib/components/shared/effects/ScreenFlash.d.ts.map +1 -1
- package/lib/components/shared/mobile/ActionButtons.d.ts.map +1 -1
- package/lib/components/shared/mobile/ActionButtons.js +0 -1
- package/lib/components/shared/mobile/ActionButtons.js.map +1 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.d.ts +0 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.js +0 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.js.map +1 -1
- package/lib/components/shared/mobile/HapticController.d.ts +0 -13
- package/lib/components/shared/mobile/HapticController.d.ts.map +1 -1
- package/lib/components/shared/mobile/HapticController.js +0 -10
- package/lib/components/shared/mobile/HapticController.js.map +1 -1
- package/lib/components/shared/mobile/MobileControlsPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/MobileControlsPure.js.map +1 -1
- package/lib/components/shared/mobile/PerformanceMonitor.d.ts +0 -15
- package/lib/components/shared/mobile/PerformanceMonitor.d.ts.map +1 -1
- package/lib/components/shared/mobile/StanceWheelPure.d.ts +0 -1
- package/lib/components/shared/mobile/StanceWheelPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/StanceWheelPure.js +0 -1
- package/lib/components/shared/mobile/StanceWheelPure.js.map +1 -1
- package/lib/components/shared/mobile/TouchOptimizer.d.ts +0 -4
- package/lib/components/shared/mobile/TouchOptimizer.d.ts.map +1 -1
- package/lib/components/shared/mobile/TouchOptimizer.js +0 -3
- package/lib/components/shared/mobile/TouchOptimizer.js.map +1 -1
- package/lib/components/shared/mobile/VirtualDPad.d.ts.map +1 -1
- package/lib/components/shared/mobile/VirtualDPad.js +0 -1
- package/lib/components/shared/mobile/VirtualDPad.js.map +1 -1
- package/lib/components/shared/mobile/index.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BodySurface.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BodySurface.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneAttachedMuscles.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneAttachedMuscles.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneClothing.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneClothing.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.d.ts +0 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.js.map +1 -1
- package/lib/components/shared/three/anatomy/Face3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Face3D.js.map +1 -1
- package/lib/components/shared/three/anatomy/Foot3D.d.ts +0 -1
- package/lib/components/shared/three/anatomy/Foot3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Foot3D.js.map +1 -1
- package/lib/components/shared/three/anatomy/Hand3D.d.ts +0 -1
- package/lib/components/shared/three/anatomy/Hand3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Hand3D.js.map +1 -1
- package/lib/components/shared/three/effects/ActionFeedback.d.ts.map +1 -1
- package/lib/components/shared/three/effects/ActionFeedback.js.map +1 -1
- package/lib/components/shared/three/effects/DamageNumbers.d.ts.map +1 -1
- package/lib/components/shared/three/effects/DamageNumbers.js.map +1 -1
- package/lib/components/shared/three/effects/ExplosiveBurstEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/GrapplingIndicator3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/HitEffects3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/HitEffects3D.js.map +1 -1
- package/lib/components/shared/three/effects/LimbExposureIndicator3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/NerveDisruptionEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/PlayerStateIndicators.d.ts.map +1 -1
- package/lib/components/shared/three/effects/PlayerStateIndicators.js.map +1 -1
- package/lib/components/shared/three/effects/StanceSymbol3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/StanceSymbol3D.js.map +1 -1
- package/lib/components/shared/three/effects/StanceTransitionEffect.d.ts.map +1 -1
- package/lib/components/shared/three/effects/StanceTransitionEffect.js.map +1 -1
- package/lib/components/shared/three/effects/ThunderEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/VitalPointMarkers3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/VitalPointMarkers3D.js.map +1 -1
- package/lib/components/shared/three/index.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts +0 -6
- package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/ElementalColorSystem.js +0 -4
- package/lib/components/shared/three/indicators/ElementalColorSystem.js.map +1 -1
- package/lib/components/shared/three/indicators/GuardIndicator.d.ts +0 -1
- package/lib/components/shared/three/indicators/GuardIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/GuardIndicator.js +0 -1
- package/lib/components/shared/three/indicators/GuardIndicator.js.map +1 -1
- package/lib/components/shared/three/indicators/HapticFeedback.d.ts +0 -7
- package/lib/components/shared/three/indicators/HapticFeedback.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/HapticFeedback.js +0 -2
- package/lib/components/shared/three/indicators/HapticFeedback.js.map +1 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts +0 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.js +0 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.js.map +1 -1
- package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts +0 -1
- package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts.map +1 -1
- package/lib/components/shared/three/models/Player3DWithTransitions.d.ts.map +1 -1
- package/lib/components/shared/three/models/Player3DWithTransitions.js.map +1 -1
- package/lib/components/shared/three/models/SkeletalPlayer3D.d.ts.map +1 -1
- package/lib/components/shared/three/models/SkeletalPlayer3D.js.map +1 -1
- package/lib/components/shared/three/optimization/AdaptiveQuality.d.ts.map +1 -1
- package/lib/components/shared/three/optimization/AdaptiveQuality.js.map +1 -1
- package/lib/components/shared/three/optimization/InstancedGeometry.d.ts.map +1 -1
- package/lib/components/shared/three/optimization/LODSystem.d.ts.map +1 -1
- package/lib/components/shared/three/scene/AtmosphericParticles3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/AtmosphericParticles3D.js.map +1 -1
- package/lib/components/shared/three/scene/BackgroundScene3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/BackgroundScene3D.js.map +1 -1
- package/lib/components/shared/three/scene/CombatArena3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/CombatArena3D.js.map +1 -1
- package/lib/components/shared/three/scene/DebugCollision.d.ts +0 -2
- package/lib/components/shared/three/scene/DebugCollision.d.ts.map +1 -1
- package/lib/components/shared/three/scene/KoreanSignage3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/KoreanSignage3D.js.map +1 -1
- package/lib/components/shared/three/ui/ArchetypeCard.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ArchetypeCard.js.map +1 -1
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.d.ts.map +1 -1
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.js.map +1 -1
- package/lib/components/shared/three/ui/BreathingIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/ui/BreathingIndicator2.js.map +1 -1
- package/lib/components/shared/three/ui/CombatReadinessBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/CombatReadinessBar.js.map +1 -1
- package/lib/components/shared/three/ui/ComboCounter.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ComboCounter.js.map +1 -1
- package/lib/components/shared/three/ui/HealthBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/HealthBar.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanButton.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanButton.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanPanel.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanPanel.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanText.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanText.js.map +1 -1
- package/lib/components/shared/three/ui/MenuList.d.ts.map +1 -1
- package/lib/components/shared/three/ui/MenuList.js.map +1 -1
- package/lib/components/shared/three/ui/PlayerHUD.d.ts.map +1 -1
- package/lib/components/shared/three/ui/PlayerHUD.js.map +1 -1
- package/lib/components/shared/three/ui/ProgressBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ProgressBar.js.map +1 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts +0 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts.map +1 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.js +0 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.js.map +1 -1
- package/lib/components/shared/three/ui/StaminaBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/StaminaBar.js.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBar.js.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBarContainer.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.js.map +1 -1
- package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.d.ts.map +1 -1
- package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.js.map +1 -1
- package/lib/components/shared/three/ui/VulnerabilityWindowHUD.d.ts.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.d.ts.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.js.map +1 -1
- package/lib/components/shared/ui/CombatTimer.d.ts.map +1 -1
- package/lib/components/shared/ui/CombatTimer.js.map +1 -1
- package/lib/components/shared/ui/ErrorBoundary.d.ts.map +1 -1
- package/lib/components/shared/ui/ErrorModal.d.ts.map +1 -1
- package/lib/components/shared/ui/ErrorModal.js.map +1 -1
- package/lib/components/shared/ui/HUDSection.d.ts.map +1 -1
- package/lib/components/shared/ui/LoadingState.d.ts.map +1 -1
- package/lib/components/shared/ui/LoadingState.js.map +1 -1
- package/lib/components/shared/ui/MobileHUDLayout.d.ts +0 -1
- package/lib/components/shared/ui/MobileHUDLayout.d.ts.map +1 -1
- package/lib/components/shared/ui/ResponsiveContainer.d.ts +0 -1
- package/lib/components/shared/ui/ResponsiveContainer.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.js +2 -2
- package/lib/components/shared/ui/SplashScreen.js.map +1 -1
- package/lib/components/shared/ui/StyledHUDPanel.d.ts.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.d.ts.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.js.map +1 -1
- package/lib/components/shared/ui/VolumeControl.d.ts.map +1 -1
- package/lib/components/shared/ui/VolumeControl.js.map +1 -1
- package/lib/components/shared/ui/shared/ConfirmDialog.d.ts.map +1 -1
- package/lib/components/shared/ui/shared/ConfirmDialog.js.map +1 -1
- package/lib/components/test/Hello3D.d.ts.map +1 -1
- package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.d.ts.map +1 -1
- package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.js.map +1 -1
- package/lib/components/ui/combat/ComboCounter.d.ts.map +1 -1
- package/lib/components/ui/combat/PressureMeter.d.ts.map +1 -1
- package/lib/systems/CombatSystem.d.ts +0 -6
- package/lib/systems/CombatSystem.d.ts.map +1 -1
- package/lib/systems/CombatSystem.js +0 -6
- package/lib/systems/CombatSystem.js.map +1 -1
- package/lib/systems/EffectCalculator.d.ts +0 -7
- package/lib/systems/EffectCalculator.d.ts.map +1 -1
- package/lib/systems/EffectCalculator.js +0 -4
- package/lib/systems/EffectCalculator.js.map +1 -1
- package/lib/systems/LayoutSystem.d.ts +0 -1
- package/lib/systems/LayoutSystem.d.ts.map +1 -1
- package/lib/systems/LayoutSystem.js +0 -1
- package/lib/systems/LayoutSystem.js.map +1 -1
- package/lib/systems/PlayerEffectManager.d.ts +0 -10
- package/lib/systems/PlayerEffectManager.d.ts.map +1 -1
- package/lib/systems/PlayerEffectManager.js +0 -3
- package/lib/systems/PlayerEffectManager.js.map +1 -1
- package/lib/systems/ResponsiveScaling.d.ts +0 -12
- package/lib/systems/ResponsiveScaling.d.ts.map +1 -1
- package/lib/systems/ResponsiveScaling.js +0 -12
- package/lib/systems/ResponsiveScaling.js.map +1 -1
- package/lib/systems/TrigramSystem.d.ts +0 -13
- package/lib/systems/TrigramSystem.d.ts.map +1 -1
- package/lib/systems/TrigramSystem.js +0 -13
- package/lib/systems/TrigramSystem.js.map +1 -1
- package/lib/systems/VitalPointSystem.d.ts +0 -10
- package/lib/systems/VitalPointSystem.d.ts.map +1 -1
- package/lib/systems/VitalPointSystem.js +0 -10
- package/lib/systems/VitalPointSystem.js.map +1 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.d.ts +0 -4
- package/lib/systems/animation/builders/KeyframeInterpolation.d.ts.map +1 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.js +0 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.js.map +1 -1
- package/lib/systems/animation/builders/SkeletonRig.d.ts +0 -4
- package/lib/systems/animation/builders/SkeletonRig.d.ts.map +1 -1
- package/lib/systems/animation/builders/SkeletonRig.js +0 -3
- package/lib/systems/animation/builders/SkeletonRig.js.map +1 -1
- package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts +0 -5
- package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts.map +1 -1
- package/lib/systems/animation/catalogs/RecoveryAnimations.js +0 -5
- package/lib/systems/animation/catalogs/RecoveryAnimations.js.map +1 -1
- package/lib/systems/animation/core/AnimationHitTiming.d.ts +0 -6
- package/lib/systems/animation/core/AnimationHitTiming.d.ts.map +1 -1
- package/lib/systems/animation/core/AnimationHitTiming.js +0 -4
- package/lib/systems/animation/core/AnimationHitTiming.js.map +1 -1
- package/lib/systems/animation/core/AnimationTransitions.d.ts +0 -3
- package/lib/systems/animation/core/AnimationTransitions.d.ts.map +1 -1
- package/lib/systems/animation/core/AnimationTransitions.js.map +1 -1
- package/lib/systems/animation/core/LateralityTransform.d.ts +0 -3
- package/lib/systems/animation/core/LateralityTransform.d.ts.map +1 -1
- package/lib/systems/animation/core/LateralityTransform.js +0 -1
- package/lib/systems/animation/core/LateralityTransform.js.map +1 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts +0 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts.map +1 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.js.map +1 -1
- package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts +0 -10
- package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts.map +1 -1
- package/lib/systems/animation/core/TechniqueAnimationMapper.js +0 -8
- package/lib/systems/animation/core/TechniqueAnimationMapper.js.map +1 -1
- package/lib/systems/animation/core/TrigramAnimationMapping.d.ts +0 -10
- package/lib/systems/animation/core/TrigramAnimationMapping.d.ts.map +1 -1
- package/lib/systems/animation/core/TrigramStanceTransitions.d.ts +0 -2
- package/lib/systems/animation/core/TrigramStanceTransitions.d.ts.map +1 -1
- package/lib/systems/animation/core/types.d.ts +0 -39
- package/lib/systems/animation/core/types.d.ts.map +1 -1
- package/lib/systems/animation/core/types.js +0 -9
- package/lib/systems/animation/core/types.js.map +1 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.d.ts +0 -27
- package/lib/systems/animation/systems/AdvancedJointMovements.d.ts.map +1 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.js +0 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.js.map +1 -1
- package/lib/systems/animation/systems/BodyFacingSystem.d.ts +0 -19
- package/lib/systems/animation/systems/BodyFacingSystem.d.ts.map +1 -1
- package/lib/systems/animation/systems/BodyFacingSystem.js +0 -14
- package/lib/systems/animation/systems/BodyFacingSystem.js.map +1 -1
- package/lib/systems/animation/systems/FacialExpressions.d.ts +0 -10
- package/lib/systems/animation/systems/FacialExpressions.d.ts.map +1 -1
- package/lib/systems/animation/systems/FacialExpressions.js +0 -2
- package/lib/systems/animation/systems/FacialExpressions.js.map +1 -1
- package/lib/systems/animation/systems/FallAnimations.d.ts +0 -4
- package/lib/systems/animation/systems/FallAnimations.d.ts.map +1 -1
- package/lib/systems/animation/systems/FallAnimations.js +0 -2
- package/lib/systems/animation/systems/FallAnimations.js.map +1 -1
- package/lib/systems/animation/systems/HeadMovements.d.ts +0 -10
- package/lib/systems/animation/systems/HeadMovements.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts +0 -7
- package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartDamageIntegration.js +0 -7
- package/lib/systems/bodypart/BodyPartDamageIntegration.js.map +1 -1
- package/lib/systems/bodypart/BodyPartHealthSystem.d.ts +0 -13
- package/lib/systems/bodypart/BodyPartHealthSystem.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartHealthSystem.js +0 -13
- package/lib/systems/bodypart/BodyPartHealthSystem.js.map +1 -1
- package/lib/systems/bodypart/BodyPartPositionMapping.d.ts +0 -6
- package/lib/systems/bodypart/BodyPartPositionMapping.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartPositionMapping.js +0 -6
- package/lib/systems/bodypart/BodyPartPositionMapping.js.map +1 -1
- package/lib/systems/bodypart/CombatInjuryIntegration.d.ts +0 -10
- package/lib/systems/bodypart/CombatInjuryIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/CombatInjuryIntegration.js +0 -8
- package/lib/systems/bodypart/CombatInjuryIntegration.js.map +1 -1
- package/lib/systems/bodypart/InjuryIntegration.d.ts +0 -2
- package/lib/systems/bodypart/InjuryIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/InjuryIntegration.js +0 -2
- package/lib/systems/bodypart/InjuryIntegration.js.map +1 -1
- package/lib/systems/bodypart/InjuryTracker.d.ts +0 -14
- package/lib/systems/bodypart/InjuryTracker.d.ts.map +1 -1
- package/lib/systems/bodypart/InjuryTracker.js +0 -12
- package/lib/systems/bodypart/InjuryTracker.js.map +1 -1
- package/lib/systems/bodypart/MovementPenaltySystem.d.ts +0 -8
- package/lib/systems/bodypart/MovementPenaltySystem.d.ts.map +1 -1
- package/lib/systems/bodypart/MovementPenaltySystem.js +0 -8
- package/lib/systems/bodypart/MovementPenaltySystem.js.map +1 -1
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts +0 -8
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts.map +1 -1
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.js +0 -8
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.js.map +1 -1
- package/lib/systems/bodypart/types.d.ts +0 -13
- package/lib/systems/bodypart/types.d.ts.map +1 -1
- package/lib/systems/bodypart/types.js +0 -5
- package/lib/systems/bodypart/types.js.map +1 -1
- package/lib/systems/breathing/BreathingDisruptionSystem.d.ts +0 -3
- package/lib/systems/breathing/BreathingDisruptionSystem.d.ts.map +1 -1
- package/lib/systems/breathing/BreathingDisruptionSystem.js +0 -2
- package/lib/systems/breathing/BreathingDisruptionSystem.js.map +1 -1
- package/lib/systems/combat/BalanceSystem.d.ts +0 -25
- package/lib/systems/combat/BalanceSystem.d.ts.map +1 -1
- package/lib/systems/combat/BalanceSystem.js +0 -25
- package/lib/systems/combat/BalanceSystem.js.map +1 -1
- package/lib/systems/combat/BreakingStatusEffects.d.ts +0 -4
- package/lib/systems/combat/BreakingStatusEffects.d.ts.map +1 -1
- package/lib/systems/combat/BreakingStatusEffects.js +0 -3
- package/lib/systems/combat/BreakingStatusEffects.js.map +1 -1
- package/lib/systems/combat/CombatStateSystem.d.ts +0 -9
- package/lib/systems/combat/CombatStateSystem.d.ts.map +1 -1
- package/lib/systems/combat/CombatStateSystem.js +0 -9
- package/lib/systems/combat/CombatStateSystem.js.map +1 -1
- package/lib/systems/combat/ConsciousnessSystem.d.ts +0 -16
- package/lib/systems/combat/ConsciousnessSystem.d.ts.map +1 -1
- package/lib/systems/combat/ConsciousnessSystem.js +0 -16
- package/lib/systems/combat/ConsciousnessSystem.js.map +1 -1
- package/lib/systems/combat/FallIntegration.d.ts +0 -3
- package/lib/systems/combat/FallIntegration.d.ts.map +1 -1
- package/lib/systems/combat/FallIntegration.js +0 -3
- package/lib/systems/combat/FallIntegration.js.map +1 -1
- package/lib/systems/combat/GrappleSystem.d.ts +0 -2
- package/lib/systems/combat/GrappleSystem.d.ts.map +1 -1
- package/lib/systems/combat/GrappleSystem.js +0 -2
- package/lib/systems/combat/GrappleSystem.js.map +1 -1
- package/lib/systems/combat/LimbExposureSystem.d.ts +0 -7
- package/lib/systems/combat/LimbExposureSystem.d.ts.map +1 -1
- package/lib/systems/combat/LimbExposureSystem.js +0 -7
- package/lib/systems/combat/LimbExposureSystem.js.map +1 -1
- package/lib/systems/combat/PainResponseSystem.d.ts +0 -11
- package/lib/systems/combat/PainResponseSystem.d.ts.map +1 -1
- package/lib/systems/combat/PainResponseSystem.js +0 -11
- package/lib/systems/combat/PainResponseSystem.js.map +1 -1
- package/lib/systems/combat/painConsciousnessUtils.d.ts +0 -7
- package/lib/systems/combat/painConsciousnessUtils.d.ts.map +1 -1
- package/lib/systems/combat/painConsciousnessUtils.js +0 -7
- package/lib/systems/combat/painConsciousnessUtils.js.map +1 -1
- package/lib/systems/effects.d.ts +11 -0
- package/lib/systems/effects.d.ts.map +1 -1
- package/lib/systems/effects.js +10 -0
- package/lib/systems/effects.js.map +1 -1
- package/lib/systems/game.d.ts +16 -0
- package/lib/systems/game.d.ts.map +1 -1
- package/lib/systems/game.js +1 -0
- package/lib/systems/game.js.map +1 -1
- package/lib/systems/index.d.ts +5 -1
- package/lib/systems/index.d.ts.map +1 -1
- package/lib/systems/index.js.map +1 -1
- package/lib/systems/movement/InjuryMovementModifier.d.ts +0 -10
- package/lib/systems/movement/InjuryMovementModifier.d.ts.map +1 -1
- package/lib/systems/movement/InjuryMovementModifier.js +0 -7
- package/lib/systems/movement/InjuryMovementModifier.js.map +1 -1
- package/lib/systems/movement/integration.d.ts +0 -3
- package/lib/systems/movement/integration.d.ts.map +1 -1
- package/lib/systems/movement/integration.js +0 -3
- package/lib/systems/movement/integration.js.map +1 -1
- package/lib/systems/physics/AttackMovementPhysics.d.ts +0 -9
- package/lib/systems/physics/AttackMovementPhysics.d.ts.map +1 -1
- package/lib/systems/physics/AttackMovementPhysics.js +0 -7
- package/lib/systems/physics/AttackMovementPhysics.js.map +1 -1
- package/lib/systems/physics/CollisionDetection.d.ts +0 -6
- package/lib/systems/physics/CollisionDetection.d.ts.map +1 -1
- package/lib/systems/physics/CollisionDetection.js +0 -6
- package/lib/systems/physics/CollisionDetection.js.map +1 -1
- package/lib/systems/physics/CoordinateMapper.d.ts +0 -1
- package/lib/systems/physics/CoordinateMapper.d.ts.map +1 -1
- package/lib/systems/physics/CoordinateMapper.js +0 -1
- package/lib/systems/physics/CoordinateMapper.js.map +1 -1
- package/lib/systems/physics/KnockbackPhysics.d.ts +0 -11
- package/lib/systems/physics/KnockbackPhysics.d.ts.map +1 -1
- package/lib/systems/physics/KnockbackPhysics.js +0 -8
- package/lib/systems/physics/KnockbackPhysics.js.map +1 -1
- package/lib/systems/physics/MovementPhysics.d.ts +0 -10
- package/lib/systems/physics/MovementPhysics.d.ts.map +1 -1
- package/lib/systems/physics/MovementPhysics.js +0 -8
- package/lib/systems/physics/MovementPhysics.js.map +1 -1
- package/lib/systems/physics/PhysicalReachCalculator.d.ts +0 -6
- package/lib/systems/physics/PhysicalReachCalculator.d.ts.map +1 -1
- package/lib/systems/physics/PhysicalReachCalculator.js +0 -5
- package/lib/systems/physics/PhysicalReachCalculator.js.map +1 -1
- package/lib/systems/physics/SpeedModifierSystem.d.ts +0 -5
- package/lib/systems/physics/SpeedModifierSystem.d.ts.map +1 -1
- package/lib/systems/physics/SpeedModifierSystem.js +0 -4
- package/lib/systems/physics/SpeedModifierSystem.js.map +1 -1
- package/lib/systems/player.d.ts +0 -5
- package/lib/systems/player.d.ts.map +1 -1
- package/lib/systems/trigram/TrigramCalculator.d.ts +0 -1
- package/lib/systems/trigram/TrigramCalculator.d.ts.map +1 -1
- package/lib/systems/trigram/TrigramCalculator.js +0 -1
- package/lib/systems/trigram/TrigramCalculator.js.map +1 -1
- package/lib/systems/trigram/types.d.ts +0 -4
- package/lib/systems/trigram/types.d.ts.map +1 -1
- package/lib/systems/trigram/types.js +0 -2
- package/lib/systems/trigram/types.js.map +1 -1
- package/lib/systems/types.d.ts +7 -2
- package/lib/systems/types.d.ts.map +1 -1
- package/lib/systems/types.js.map +1 -1
- package/lib/systems/vitalpoint/DamageCalculator.d.ts +0 -3
- package/lib/systems/vitalpoint/DamageCalculator.d.ts.map +1 -1
- package/lib/systems/vitalpoint/DamageCalculator.js +0 -3
- package/lib/systems/vitalpoint/DamageCalculator.js.map +1 -1
- package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts +0 -8
- package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts.map +1 -1
- package/lib/systems/vitalpoint/KoreanVitalPoints.js +0 -8
- package/lib/systems/vitalpoint/KoreanVitalPoints.js.map +1 -1
- package/lib/systems/vitalpoint/VitalPointsData.d.ts +0 -3
- package/lib/systems/vitalpoint/VitalPointsData.d.ts.map +1 -1
- package/lib/systems/vitalpoint/VitalPointsData.js +0 -1
- package/lib/systems/vitalpoint/VitalPointsData.js.map +1 -1
- package/lib/types/PhysicsTypes.d.ts +21 -78
- package/lib/types/PhysicsTypes.d.ts.map +1 -1
- package/lib/types/PhysicsTypes.js +17 -63
- package/lib/types/PhysicsTypes.js.map +1 -1
- package/lib/types/clothing.d.ts +0 -9
- package/lib/types/clothing.d.ts.map +1 -1
- package/lib/types/constants/animations.d.ts +35 -1
- package/lib/types/constants/animations.d.ts.map +1 -1
- package/lib/types/constants/animations.js +12 -1
- package/lib/types/constants/animations.js.map +1 -1
- package/lib/types/constants/colors.d.ts +28 -2
- package/lib/types/constants/colors.d.ts.map +1 -1
- package/lib/types/constants/colors.js +30 -4
- package/lib/types/constants/colors.js.map +1 -1
- package/lib/types/constants/index.d.ts +5 -1
- package/lib/types/constants/index.d.ts.map +1 -1
- package/lib/types/constants/index.js.map +1 -1
- package/lib/types/constants/performance.d.ts +0 -2
- package/lib/types/constants/performance.d.ts.map +1 -1
- package/lib/types/constants/performance.js +0 -2
- package/lib/types/constants/performance.js.map +1 -1
- package/lib/types/constants/typography.d.ts +40 -2
- package/lib/types/constants/typography.d.ts.map +1 -1
- package/lib/types/constants/typography.js +40 -2
- package/lib/types/constants/typography.js.map +1 -1
- package/lib/types/constants/ui.d.ts +89 -1
- package/lib/types/constants/ui.d.ts.map +1 -1
- package/lib/types/constants/ui.js +33 -1
- package/lib/types/constants/ui.js.map +1 -1
- package/lib/types/facial.d.ts +0 -15
- package/lib/types/facial.d.ts.map +1 -1
- package/lib/types/facial.js +0 -8
- package/lib/types/facial.js.map +1 -1
- package/lib/types/hand-animation.d.ts +34 -147
- package/lib/types/hand-animation.d.ts.map +1 -1
- package/lib/types/hand-animation.js +0 -2
- package/lib/types/hand-animation.js.map +1 -1
- package/lib/types/injury.d.ts +0 -2
- package/lib/types/injury.d.ts.map +1 -1
- package/lib/types/injury.js +0 -1
- package/lib/types/injury.js.map +1 -1
- package/lib/types/physics.d.ts +0 -21
- package/lib/types/physics.d.ts.map +1 -1
- package/lib/types/physics.js +0 -6
- package/lib/types/physics.js.map +1 -1
- package/lib/types/physicsConstants.d.ts +0 -12
- package/lib/types/physicsConstants.d.ts.map +1 -1
- package/lib/types/physicsConstants.js +0 -12
- package/lib/types/physicsConstants.js.map +1 -1
- package/lib/types/player-visual.d.ts +45 -189
- package/lib/types/player-visual.d.ts.map +1 -1
- package/lib/types/technique.d.ts +1 -5
- package/lib/types/technique.d.ts.map +1 -1
- package/lib/types/techniqueId.d.ts +0 -1
- package/lib/types/techniqueId.d.ts.map +1 -1
- package/lib/types/techniqueId.js +0 -1
- package/lib/types/techniqueId.js.map +1 -1
- package/lib/utils/arenaWorldDimensions.d.ts +0 -11
- package/lib/utils/arenaWorldDimensions.d.ts.map +1 -1
- package/lib/utils/arenaWorldDimensions.js +0 -6
- package/lib/utils/arenaWorldDimensions.js.map +1 -1
- package/lib/utils/controlMapping.d.ts +3 -4
- package/lib/utils/controlMapping.d.ts.map +1 -1
- package/lib/utils/controlMapping.js +1 -2
- package/lib/utils/controlMapping.js.map +1 -1
- package/lib/utils/deviceDetection.d.ts +0 -5
- package/lib/utils/deviceDetection.d.ts.map +1 -1
- package/lib/utils/deviceDetection.js +0 -5
- package/lib/utils/deviceDetection.js.map +1 -1
- package/lib/utils/hapticFeedback.d.ts +23 -95
- package/lib/utils/hapticFeedback.d.ts.map +1 -1
- package/lib/utils/hapticFeedback.js +9 -39
- package/lib/utils/hapticFeedback.js.map +1 -1
- package/lib/utils/haptics.d.ts +0 -3
- package/lib/utils/haptics.d.ts.map +1 -1
- package/lib/utils/haptics.js +0 -1
- package/lib/utils/haptics.js.map +1 -1
- package/lib/utils/math.d.ts +0 -3
- package/lib/utils/math.d.ts.map +1 -1
- package/lib/utils/math.js +0 -2
- package/lib/utils/math.js.map +1 -1
- package/lib/utils/mobileLayoutHelpers.d.ts +0 -3
- package/lib/utils/mobileLayoutHelpers.d.ts.map +1 -1
- package/lib/utils/mobileLayoutHelpers.js +0 -1
- package/lib/utils/mobileLayoutHelpers.js.map +1 -1
- package/lib/utils/mobileUIUtils.d.ts +5 -100
- package/lib/utils/mobileUIUtils.d.ts.map +1 -1
- package/lib/utils/mobileUIUtils.js +0 -9
- package/lib/utils/mobileUIUtils.js.map +1 -1
- package/lib/utils/physicalAttributeValidation.d.ts.map +1 -1
- package/lib/utils/player3DHelpers.d.ts.map +1 -1
- package/lib/utils/player3DHelpers.js.map +1 -1
- package/lib/utils/responsiveLayoutHelpers.d.ts +0 -65
- package/lib/utils/responsiveLayoutHelpers.d.ts.map +1 -1
- package/lib/utils/responsiveLayoutHelpers.js +0 -65
- package/lib/utils/responsiveLayoutHelpers.js.map +1 -1
- package/lib/utils/responsiveOrientationConstants.d.ts +0 -7
- package/lib/utils/responsiveOrientationConstants.d.ts.map +1 -1
- package/lib/utils/responsiveOrientationConstants.js +0 -7
- package/lib/utils/responsiveOrientationConstants.js.map +1 -1
- package/lib/utils/safeAreaUtils.d.ts +0 -6
- package/lib/utils/safeAreaUtils.d.ts.map +1 -1
- package/lib/utils/safeAreaUtils.js +0 -2
- package/lib/utils/safeAreaUtils.js.map +1 -1
- package/lib/utils/sharedPhysicsConfig.d.ts +0 -4
- package/lib/utils/sharedPhysicsConfig.d.ts.map +1 -1
- package/lib/utils/sharedPhysicsConfig.js +0 -2
- package/lib/utils/sharedPhysicsConfig.js.map +1 -1
- package/lib/utils/skeletonScaling.d.ts +0 -9
- package/lib/utils/skeletonScaling.d.ts.map +1 -1
- package/lib/utils/skeletonScaling.js +0 -1
- package/lib/utils/skeletonScaling.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuardIndicator.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/GuardIndicator.tsx"],"sourcesContent":["/**\n * GuardIndicator - Visual indicator showing current fighting stance guard position\n * Displays Korean traditional stance name, English translation, and guard characteristics\n *\n * @module components/shared/three/indicators/GuardIndicator\n * @category Combat UI\n * @korean 방어자세표시기\n */\n\nimport React, { useMemo } from \"react\";\nimport { STANCE_GUARD_CONFIGS } from \"../../../../systems/animation\";\nimport { TRIGRAM_DATA } from \"../../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport { KOREAN_COLORS } from \"../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../utils/colorUtils\";\n\n/**\n * Props for GuardIndicator component\n */\nexport interface GuardIndicatorProps {\n /** Current trigram stance */\n readonly currentStance: TrigramStance;\n /** Whether player is in guard animation state */\n readonly isInGuard: boolean;\n /** Player position: 'left' for player 1, 'right' for player 2 */\n readonly position: \"left\" | \"right\";\n /** Whether to use mobile-optimized sizing */\n readonly isMobile?: boolean;\n}\n\n/**\n * Get guard height label based on arm positions\n *\n * Guard heights based on shoulder.x (vertical angle in radians):\n * - High guard (고위): shoulder at chin level (x <= -0.8)\n * GEON (-1.0), LI (-1.6), GAN (-1.0)\n * - Mid guard (중위): shoulder at chest level (-0.8 < x < -0.4)\n * TAE (-0.7), JIN (-0.6), SON (-0.8), GAM (-0.8)\n * - Low guard (저위): shoulder low (x >= -0.4)\n * GON (-0.4)\n */\nfunction getGuardHeight(stance: TrigramStance): {\n korean: string;\n english: string;\n} {\n const config = STANCE_GUARD_CONFIGS[stance];\n const shoulderY = config.guardPose.leftArm.shoulder.x; // x is vertical in Euler\n\n if (shoulderY <= -0.8) {\n return { korean: \"고위\", english: \"High\" };\n } else if (shoulderY < -0.4) {\n return { korean: \"중위\", english: \"Mid\" };\n } else {\n return { korean: \"저위\", english: \"Low\" };\n }\n}\n\n/**\n * Get traditional Korean stance name from guard config\n */\nfunction getTraditionalStanceName(stance: TrigramStance): {\n korean: string;\n romanized: string;\n} {\n const stanceNames: Record<\n TrigramStance,\n { korean: string; romanized: string }\n > = {\n [TrigramStance.GEON]: { korean: \"앞서기\", romanized: \"Ap Seogi\" },\n [TrigramStance.TAE]: { korean: \"범서기\", romanized: \"Beom Seogi\" },\n [TrigramStance.LI]: { korean: \"겨루기 준비\", romanized: \"Gyeorugi Junbi\" },\n [TrigramStance.JIN]: { korean: \"주춤서기\", romanized: \"Juchum Seogi\" },\n [TrigramStance.SON]: { korean: \"학다리서기\", romanized: \"Hakdari Seogi\" },\n [TrigramStance.GAM]: { korean: \"뒷발서기\", romanized: \"Dwitbal Seogi\" },\n [TrigramStance.GAN]: { korean: \"모아서기\", romanized: \"Moa Seogi\" },\n [TrigramStance.GON]: { korean: \"중하\", romanized: \"Joong Ha Seogi\" },\n };\n return stanceNames[stance];\n}\n\n/**\n * Get weight distribution icon\n */\nfunction getWeightIcon(weight: \"forward\" | \"neutral\" | \"back\"): string {\n switch (weight) {\n case \"forward\":\n return \"▲\"; // Forward lean\n case \"back\":\n return \"▼\"; // Back lean\n case \"neutral\":\n return \"●\"; // Centered\n }\n}\n\n/**\n * GuardIndicator Component\n *\n * Displays current guard position information with Korean martial arts terminology.\n * Shows only when player is in a stance guard animation state.\n *\n * Features:\n * - Traditional Korean stance name (앞서기, 앞굽이, etc.)\n * - Romanized pronunciation\n * - Guard height indicator (High/Mid/Low)\n * - Weight distribution visualization\n * - Korean cyberpunk styling with glow effects\n * - Responsive mobile layout\n * - Accessible with proper ARIA labels\n *\n * @example\n * ```tsx\n * <GuardIndicator\n * currentStance={TrigramStance.GEON}\n * isInGuard={true}\n * position=\"left\"\n * isMobile={false}\n * />\n * ```\n *\n * @public\n * @korean 방어자세표시기\n */\nexport const GuardIndicator: React.FC<GuardIndicatorProps> = ({\n currentStance,\n isInGuard,\n position: _position, // Currently unused - indicator always positioned bottom-right\n isMobile = false,\n}) => {\n // Get guard configuration\n const config = useMemo(\n () => STANCE_GUARD_CONFIGS[currentStance],\n [currentStance],\n );\n\n const trigramData = useMemo(\n () => TRIGRAM_DATA[currentStance],\n [currentStance],\n );\n\n const stanceName = useMemo(\n () => getTraditionalStanceName(currentStance),\n [currentStance],\n );\n\n const guardHeight = useMemo(\n () => getGuardHeight(currentStance),\n [currentStance],\n );\n\n const weightIcon = useMemo(\n () => getWeightIcon(config.guardPose.weight),\n [config.guardPose.weight],\n );\n\n // Memoize responsive sizing\n const layout = useMemo(\n () => ({\n fontSize: isMobile ? 10 : 12,\n titleSize: isMobile ? 13 : 16,\n iconSize: isMobile ? 14 : 18,\n padding: isMobile ? \"6px 10px\" : \"8px 12px\",\n gap: isMobile ? \"3px\" : \"4px\",\n }),\n [isMobile],\n );\n\n // Container style - uses relative positioning for embedding in container HUDs\n const containerStyle = useMemo(\n () => ({\n position: \"relative\" as const,\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: layout.gap,\n backgroundColor: hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85),\n border: `1px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.6)}`,\n borderRadius: \"6px\",\n padding: layout.padding,\n pointerEvents: \"none\" as const,\n width: \"100%\",\n boxSizing: \"border-box\" as const,\n boxShadow: `0 0 15px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.3)}`,\n }),\n [layout],\n );\n\n // Don't render if not in guard state\n if (!isInGuard) return null;\n\n return (\n <div\n data-testid=\"guard-indicator\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={`Guard position: ${stanceName.romanized}, ${guardHeight.english} guard, ${config.guardPose.weight} weight`}\n style={containerStyle}\n >\n {/* Title: GUARD with trigram symbol */}\n <div\n style={{\n fontSize: layout.titleSize,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1),\n fontWeight: \"bold\",\n textAlign: \"center\",\n textShadow: `0 0 10px ${hexToRgbaString(\n KOREAN_COLORS.ACCENT_GOLD,\n 0.6,\n )}`,\n borderBottom: `1px solid ${hexToRgbaString(\n KOREAN_COLORS.PRIMARY_CYAN,\n 0.4,\n )}`,\n paddingBottom: layout.gap,\n }}\n >\n {trigramData.symbol} GUARD\n </div>\n\n {/* Traditional stance name (Korean) */}\n <div\n style={{\n fontSize: layout.fontSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n textAlign: \"center\",\n fontWeight: \"600\",\n }}\n >\n {stanceName.korean}\n </div>\n\n {/* Romanized name */}\n <div\n style={{\n fontSize: layout.fontSize,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.8),\n textAlign: \"center\",\n fontStyle: \"italic\",\n }}\n >\n {stanceName.romanized}\n </div>\n\n {/* Guard characteristics row */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-around\",\n marginTop: layout.gap,\n paddingTop: layout.gap,\n borderTop: `1px solid ${hexToRgbaString(\n KOREAN_COLORS.PRIMARY_CYAN,\n 0.3,\n )}`,\n }}\n >\n {/* Guard height */}\n <div style={{ textAlign: \"center\" }}>\n <div\n style={{\n fontSize: layout.iconSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n }}\n >\n ⚔️\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 1,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9),\n }}\n >\n {guardHeight.korean}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 2,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6),\n }}\n >\n {guardHeight.english}\n </div>\n </div>\n\n {/* Weight distribution */}\n <div style={{ textAlign: \"center\" }}>\n <div\n style={{\n fontSize: layout.iconSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n }}\n >\n {weightIcon}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 1,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9),\n }}\n >\n {config.guardPose.weight === \"forward\" && \"전방\"}\n {config.guardPose.weight === \"neutral\" && \"중립\"}\n {config.guardPose.weight === \"back\" && \"후방\"}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 2,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6),\n textTransform: \"capitalize\" as const,\n }}\n >\n {config.guardPose.weight}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\n/**\n * Memoized GuardIndicator to prevent unnecessary re-renders\n */\nexport default React.memo(GuardIndicator);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GuardIndicator.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/GuardIndicator.tsx"],"sourcesContent":["/**\n * GuardIndicator - Visual indicator showing current fighting stance guard position\n * Displays Korean traditional stance name, English translation, and guard characteristics\n *\n * @module components/shared/three/indicators/GuardIndicator\n * @category Combat UI\n * @korean 방어자세표시기\n */\n\nimport React, { useMemo } from \"react\";\nimport { STANCE_GUARD_CONFIGS } from \"../../../../systems/animation\";\nimport { TRIGRAM_DATA } from \"../../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport { KOREAN_COLORS } from \"../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../utils/colorUtils\";\n\n/**\n * Props for GuardIndicator component\n */\nexport interface GuardIndicatorProps {\n /** Current trigram stance */\n readonly currentStance: TrigramStance;\n /** Whether player is in guard animation state */\n readonly isInGuard: boolean;\n /** Player position: 'left' for player 1, 'right' for player 2 */\n readonly position: \"left\" | \"right\";\n /** Whether to use mobile-optimized sizing */\n readonly isMobile?: boolean;\n}\n\n/**\n * Get guard height label based on arm positions\n *\n * Guard heights based on shoulder.x (vertical angle in radians):\n * - High guard (고위): shoulder at chin level (x <= -0.8)\n * GEON (-1.0), LI (-1.6), GAN (-1.0)\n * - Mid guard (중위): shoulder at chest level (-0.8 < x < -0.4)\n * TAE (-0.7), JIN (-0.6), SON (-0.8), GAM (-0.8)\n * - Low guard (저위): shoulder low (x >= -0.4)\n * GON (-0.4)\n */\nfunction getGuardHeight(stance: TrigramStance): {\n korean: string;\n english: string;\n} {\n const config = STANCE_GUARD_CONFIGS[stance];\n const shoulderY = config.guardPose.leftArm.shoulder.x; // x is vertical in Euler\n\n if (shoulderY <= -0.8) {\n return { korean: \"고위\", english: \"High\" };\n } else if (shoulderY < -0.4) {\n return { korean: \"중위\", english: \"Mid\" };\n } else {\n return { korean: \"저위\", english: \"Low\" };\n }\n}\n\n/**\n * Get traditional Korean stance name from guard config\n */\nfunction getTraditionalStanceName(stance: TrigramStance): {\n korean: string;\n romanized: string;\n} {\n const stanceNames: Record<\n TrigramStance,\n { korean: string; romanized: string }\n > = {\n [TrigramStance.GEON]: { korean: \"앞서기\", romanized: \"Ap Seogi\" },\n [TrigramStance.TAE]: { korean: \"범서기\", romanized: \"Beom Seogi\" },\n [TrigramStance.LI]: { korean: \"겨루기 준비\", romanized: \"Gyeorugi Junbi\" },\n [TrigramStance.JIN]: { korean: \"주춤서기\", romanized: \"Juchum Seogi\" },\n [TrigramStance.SON]: { korean: \"학다리서기\", romanized: \"Hakdari Seogi\" },\n [TrigramStance.GAM]: { korean: \"뒷발서기\", romanized: \"Dwitbal Seogi\" },\n [TrigramStance.GAN]: { korean: \"모아서기\", romanized: \"Moa Seogi\" },\n [TrigramStance.GON]: { korean: \"중하\", romanized: \"Joong Ha Seogi\" },\n };\n return stanceNames[stance];\n}\n\n/**\n * Get weight distribution icon\n */\nfunction getWeightIcon(weight: \"forward\" | \"neutral\" | \"back\"): string {\n switch (weight) {\n case \"forward\":\n return \"▲\"; // Forward lean\n case \"back\":\n return \"▼\"; // Back lean\n case \"neutral\":\n return \"●\"; // Centered\n }\n}\n\n/**\n * GuardIndicator Component\n *\n * Displays current guard position information with Korean martial arts terminology.\n * Shows only when player is in a stance guard animation state.\n *\n * Features:\n * - Traditional Korean stance name (앞서기, 앞굽이, etc.)\n * - Romanized pronunciation\n * - Guard height indicator (High/Mid/Low)\n * - Weight distribution visualization\n * - Korean cyberpunk styling with glow effects\n * - Responsive mobile layout\n * - Accessible with proper ARIA labels\n *\n * @example\n * ```tsx\n * <GuardIndicator\n * currentStance={TrigramStance.GEON}\n * isInGuard={true}\n * position=\"left\"\n * isMobile={false}\n * />\n * ```\n *\n * @korean 방어자세표시기\n */\nexport const GuardIndicator: React.FC<GuardIndicatorProps> = ({\n currentStance,\n isInGuard,\n position: _position, // Currently unused - indicator always positioned bottom-right\n isMobile = false,\n}) => {\n const config = useMemo(\n () => STANCE_GUARD_CONFIGS[currentStance],\n [currentStance],\n );\n\n const trigramData = useMemo(\n () => TRIGRAM_DATA[currentStance],\n [currentStance],\n );\n\n const stanceName = useMemo(\n () => getTraditionalStanceName(currentStance),\n [currentStance],\n );\n\n const guardHeight = useMemo(\n () => getGuardHeight(currentStance),\n [currentStance],\n );\n\n const weightIcon = useMemo(\n () => getWeightIcon(config.guardPose.weight),\n [config.guardPose.weight],\n );\n\n const layout = useMemo(\n () => ({\n fontSize: isMobile ? 10 : 12,\n titleSize: isMobile ? 13 : 16,\n iconSize: isMobile ? 14 : 18,\n padding: isMobile ? \"6px 10px\" : \"8px 12px\",\n gap: isMobile ? \"3px\" : \"4px\",\n }),\n [isMobile],\n );\n\n const containerStyle = useMemo(\n () => ({\n position: \"relative\" as const,\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: layout.gap,\n backgroundColor: hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85),\n border: `1px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.6)}`,\n borderRadius: \"6px\",\n padding: layout.padding,\n pointerEvents: \"none\" as const,\n width: \"100%\",\n boxSizing: \"border-box\" as const,\n boxShadow: `0 0 15px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.3)}`,\n }),\n [layout],\n );\n\n if (!isInGuard) return null;\n\n return (\n <div\n data-testid=\"guard-indicator\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={`Guard position: ${stanceName.romanized}, ${guardHeight.english} guard, ${config.guardPose.weight} weight`}\n style={containerStyle}\n >\n {/* Title: GUARD with trigram symbol */}\n <div\n style={{\n fontSize: layout.titleSize,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1),\n fontWeight: \"bold\",\n textAlign: \"center\",\n textShadow: `0 0 10px ${hexToRgbaString(\n KOREAN_COLORS.ACCENT_GOLD,\n 0.6,\n )}`,\n borderBottom: `1px solid ${hexToRgbaString(\n KOREAN_COLORS.PRIMARY_CYAN,\n 0.4,\n )}`,\n paddingBottom: layout.gap,\n }}\n >\n {trigramData.symbol} GUARD\n </div>\n\n {/* Traditional stance name (Korean) */}\n <div\n style={{\n fontSize: layout.fontSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n textAlign: \"center\",\n fontWeight: \"600\",\n }}\n >\n {stanceName.korean}\n </div>\n\n {/* Romanized name */}\n <div\n style={{\n fontSize: layout.fontSize,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.8),\n textAlign: \"center\",\n fontStyle: \"italic\",\n }}\n >\n {stanceName.romanized}\n </div>\n\n {/* Guard characteristics row */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-around\",\n marginTop: layout.gap,\n paddingTop: layout.gap,\n borderTop: `1px solid ${hexToRgbaString(\n KOREAN_COLORS.PRIMARY_CYAN,\n 0.3,\n )}`,\n }}\n >\n {/* Guard height */}\n <div style={{ textAlign: \"center\" }}>\n <div\n style={{\n fontSize: layout.iconSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n }}\n >\n ⚔️\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 1,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9),\n }}\n >\n {guardHeight.korean}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 2,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6),\n }}\n >\n {guardHeight.english}\n </div>\n </div>\n\n {/* Weight distribution */}\n <div style={{ textAlign: \"center\" }}>\n <div\n style={{\n fontSize: layout.iconSize,\n color: hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1),\n }}\n >\n {weightIcon}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 1,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9),\n }}\n >\n {config.guardPose.weight === \"forward\" && \"전방\"}\n {config.guardPose.weight === \"neutral\" && \"중립\"}\n {config.guardPose.weight === \"back\" && \"후방\"}\n </div>\n <div\n style={{\n fontSize: layout.fontSize - 2,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6),\n textTransform: \"capitalize\" as const,\n }}\n >\n {config.guardPose.weight}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\n/**\n * Memoized GuardIndicator to prevent unnecessary re-renders\n */\nexport default React.memo(GuardIndicator);\n"],"mappings":"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"}
|
|
@@ -27,7 +27,6 @@ export type HapticPattern = number | number[];
|
|
|
27
27
|
* }
|
|
28
28
|
* ```
|
|
29
29
|
*
|
|
30
|
-
* @public
|
|
31
30
|
* @korean 햅틱지원여부
|
|
32
31
|
*/
|
|
33
32
|
export declare function isHapticSupported(): boolean;
|
|
@@ -52,7 +51,6 @@ export declare function isHapticSupported(): boolean;
|
|
|
52
51
|
* triggerGuardHaptic('break');
|
|
53
52
|
* ```
|
|
54
53
|
*
|
|
55
|
-
* @public
|
|
56
54
|
* @korean 방어햅틱트리거
|
|
57
55
|
*/
|
|
58
56
|
export declare function triggerGuardHaptic(type: "activate" | "break"): void;
|
|
@@ -68,7 +66,6 @@ export declare function triggerGuardHaptic(type: "activate" | "break"): void;
|
|
|
68
66
|
* triggerStanceChangeHaptic();
|
|
69
67
|
* ```
|
|
70
68
|
*
|
|
71
|
-
* @public
|
|
72
69
|
* @korean 자세변경햅틱트리거
|
|
73
70
|
*/
|
|
74
71
|
export declare function triggerStanceChangeHaptic(): void;
|
|
@@ -92,7 +89,6 @@ export declare function triggerStanceChangeHaptic(): void;
|
|
|
92
89
|
* triggerCustomHaptic([100, 50, 100, 50, 100]);
|
|
93
90
|
* ```
|
|
94
91
|
*
|
|
95
|
-
* @public
|
|
96
92
|
* @korean 사용자정의햅틱트리거
|
|
97
93
|
*/
|
|
98
94
|
export declare function triggerCustomHaptic(pattern: HapticPattern): void;
|
|
@@ -108,7 +104,6 @@ export declare function triggerCustomHaptic(pattern: HapticPattern): void;
|
|
|
108
104
|
* stopHaptic();
|
|
109
105
|
* ```
|
|
110
106
|
*
|
|
111
|
-
* @public
|
|
112
107
|
* @korean 햅틱중지
|
|
113
108
|
*/
|
|
114
109
|
export declare function stopHaptic(): void;
|
|
@@ -127,7 +122,6 @@ export declare function stopHaptic(): void;
|
|
|
127
122
|
* }
|
|
128
123
|
* ```
|
|
129
124
|
*
|
|
130
|
-
* @public
|
|
131
125
|
* @korean 모바일기기여부
|
|
132
126
|
*/
|
|
133
127
|
export declare function isMobileDevice(): boolean;
|
|
@@ -177,7 +171,6 @@ export declare function applyIntensity(pattern: HapticPattern, intensity: number
|
|
|
177
171
|
* triggerWithSettings(100, settings); // Triggers 70ms vibration
|
|
178
172
|
* ```
|
|
179
173
|
*
|
|
180
|
-
* @public
|
|
181
174
|
* @korean 설정포함햅틱트리거
|
|
182
175
|
*/
|
|
183
176
|
export declare function triggerWithSettings(pattern: HapticPattern, settings?: HapticSettings): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HapticFeedback.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/HapticFeedback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"HapticFeedback.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/HapticFeedback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,IAAI,CAcnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAUhD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAUjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAexC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAGrC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAChB,aAAa,CAQf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EACtB,QAAQ,GAAE,cAAwC,GACjD,IAAI,CAON"}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* }
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
|
-
* @public
|
|
15
14
|
* @korean 햅틱지원여부
|
|
16
15
|
*/
|
|
17
16
|
function isHapticSupported() {
|
|
@@ -29,7 +28,6 @@ function isHapticSupported() {
|
|
|
29
28
|
* triggerStanceChangeHaptic();
|
|
30
29
|
* ```
|
|
31
30
|
*
|
|
32
|
-
* @public
|
|
33
31
|
* @korean 자세변경햅틱트리거
|
|
34
32
|
*/
|
|
35
33
|
function triggerStanceChangeHaptic() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HapticFeedback.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/HapticFeedback.ts"],"sourcesContent":["/**\n * Haptic Feedback System for Combat UI\n * \n * Provides tactile feedback for mobile devices during combat interactions\n * such as guard activation, stance changes, and guard breaks.\n * \n * Uses the Vibration API with fallback for unsupported devices.\n * \n * @module components/shared/three/indicators/HapticFeedback\n * @category Combat UI\n * @korean 햅틱피드백\n */\n\n/**\n * Haptic pattern type\n * @korean 햅틱패턴타입\n */\nexport type HapticPattern = number | number[];\n\n/**\n * Check if haptic feedback is supported on this device\n * \n * @returns True if the Vibration API is available\n * \n * @example\n * ```typescript\n * if (isHapticSupported()) {\n * triggerGuardHaptic('activate');\n * }\n * ```\n * \n * @
|
|
1
|
+
{"version":3,"file":"HapticFeedback.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/HapticFeedback.ts"],"sourcesContent":["/**\n * Haptic Feedback System for Combat UI\n * \n * Provides tactile feedback for mobile devices during combat interactions\n * such as guard activation, stance changes, and guard breaks.\n * \n * Uses the Vibration API with fallback for unsupported devices.\n * \n * @module components/shared/three/indicators/HapticFeedback\n * @category Combat UI\n * @korean 햅틱피드백\n */\n\n/**\n * Haptic pattern type\n * @korean 햅틱패턴타입\n */\nexport type HapticPattern = number | number[];\n\n/**\n * Check if haptic feedback is supported on this device\n * \n * @returns True if the Vibration API is available\n * \n * @example\n * ```typescript\n * if (isHapticSupported()) {\n * triggerGuardHaptic('activate');\n * }\n * ```\n * \n * @korean 햅틱지원여부\n */\nexport function isHapticSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"vibrate\" in navigator &&\n typeof navigator.vibrate === \"function\"\n );\n}\n\n/**\n * Trigger haptic feedback for guard activation or break\n * \n * Provides tactile feedback when a player activates their guard\n * or when their guard is broken by an opponent.\n * \n * Patterns:\n * - **activate**: Light single vibration (50ms) for guard activation\n * - **break**: Strong triple-pulse pattern (100ms, 50ms pause, 100ms) for guard break\n * \n * @param type - Type of guard haptic feedback\n * \n * @example\n * ```typescript\n * // When player activates guard\n * triggerGuardHaptic('activate');\n * \n * // When guard is broken\n * triggerGuardHaptic('break');\n * ```\n * \n * @korean 방어햅틱트리거\n */\nexport function triggerGuardHaptic(type: \"activate\" | \"break\"): void {\n if (!isHapticSupported()) {\n return;\n }\n\n try {\n if (type === \"activate\") {\n navigator.vibrate(50);\n } else if (type === \"break\") {\n navigator.vibrate([100, 50, 100]);\n }\n } catch (error) {\n console.warn(\"Haptic feedback failed:\", error);\n }\n}\n\n/**\n * Trigger haptic feedback for stance change\n * \n * Provides medium-strength tactile feedback when a player transitions\n * between trigram stances (건→태→리→진→손→감→간→곤).\n * \n * @example\n * ```typescript\n * // When stance changes from Geon to Tae\n * triggerStanceChangeHaptic();\n * ```\n * \n * @korean 자세변경햅틱트리거\n */\nexport function triggerStanceChangeHaptic(): void {\n if (!isHapticSupported()) {\n return;\n }\n\n try {\n navigator.vibrate(75);\n } catch (error) {\n console.warn(\"Haptic feedback failed:\", error);\n }\n}\n\n/**\n * Trigger custom haptic pattern\n * \n * Allows for custom vibration patterns using the Vibration API.\n * Can specify either a single duration or a pattern array.\n * \n * Pattern arrays alternate between vibration and pause:\n * - [200, 100, 200] = vibrate 200ms, pause 100ms, vibrate 200ms\n * \n * @param pattern - Vibration duration in ms or pattern array\n * \n * @example\n * ```typescript\n * // Single vibration\n * triggerCustomHaptic(200);\n * \n * // Complex pattern\n * triggerCustomHaptic([100, 50, 100, 50, 100]);\n * ```\n * \n * @korean 사용자정의햅틱트리거\n */\nexport function triggerCustomHaptic(pattern: HapticPattern): void {\n if (!isHapticSupported()) {\n return;\n }\n\n try {\n navigator.vibrate(pattern);\n } catch (error) {\n console.warn(\"Haptic feedback failed:\", error);\n }\n}\n\n/**\n * Stop all haptic feedback\n * \n * Immediately stops any ongoing vibration. Useful for interrupting\n * long or repeated patterns.\n * \n * @example\n * ```typescript\n * // Stop any ongoing haptic feedback\n * stopHaptic();\n * ```\n * \n * @korean 햅틱중지\n */\nexport function stopHaptic(): void {\n if (!isHapticSupported()) {\n return;\n }\n\n try {\n navigator.vibrate(0);\n } catch (error) {\n console.warn(\"Haptic stop failed:\", error);\n }\n}\n\n/**\n * Check if device is mobile\n * \n * Simple heuristic to detect mobile devices based on screen size,\n * user agent, and touch support.\n * \n * @returns True if device is likely mobile\n * \n * @example\n * ```typescript\n * if (isMobileDevice() && isHapticSupported()) {\n * triggerStanceChangeHaptic();\n * }\n * ```\n * \n * @korean 모바일기기여부\n */\nexport function isMobileDevice(): boolean {\n if (typeof window === \"undefined\" || typeof navigator === \"undefined\") {\n return false;\n }\n\n const isMobileSize = window.innerWidth < 768;\n\n const mobileKeywords = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;\n const isMobileUA = mobileKeywords.test(navigator.userAgent);\n\n const hasTouch =\n \"ontouchstart\" in window ||\n navigator.maxTouchPoints > 0;\n\n return (isMobileSize || isMobileUA) && hasTouch;\n}\n\n/**\n * Haptic feedback settings\n * \n * Allows for global configuration of haptic feedback intensity\n * and enable/disable state.\n * \n * @korean 햅틱설정\n */\nexport interface HapticSettings {\n /** Whether haptic feedback is enabled */\n readonly enabled: boolean;\n /** Intensity multiplier (0.0 to 1.0) */\n readonly intensity: number;\n}\n\n/**\n * Default haptic settings\n * @korean 기본햅틱설정\n */\nexport const DEFAULT_HAPTIC_SETTINGS: HapticSettings = {\n enabled: true,\n intensity: 1.0,\n};\n\n/**\n * Apply intensity modifier to haptic pattern\n * \n * Scales vibration durations based on intensity setting.\n * \n * @param pattern - Original haptic pattern\n * @param intensity - Intensity multiplier (0.0 to 1.0)\n * @returns Scaled haptic pattern\n * \n * @internal\n * @korean 햅틱강도적용\n */\nexport function applyIntensity(\n pattern: HapticPattern,\n intensity: number\n): HapticPattern {\n const clampedIntensity = Math.max(0, Math.min(1, intensity));\n\n if (typeof pattern === \"number\") {\n return Math.round(pattern * clampedIntensity);\n }\n\n return pattern.map((duration) => Math.round(duration * clampedIntensity));\n}\n\n/**\n * Trigger haptic with settings\n * \n * Wrapper function that applies haptic settings before triggering.\n * \n * @param pattern - Haptic pattern to trigger\n * @param settings - Haptic settings to apply\n * \n * @example\n * ```typescript\n * const settings = { enabled: true, intensity: 0.7 };\n * triggerWithSettings(100, settings); // Triggers 70ms vibration\n * ```\n * \n * @korean 설정포함햅틱트리거\n */\nexport function triggerWithSettings(\n pattern: HapticPattern,\n settings: HapticSettings = DEFAULT_HAPTIC_SETTINGS\n): void {\n if (!settings.enabled || !isHapticSupported()) {\n return;\n }\n\n const scaledPattern = applyIntensity(pattern, settings.intensity);\n triggerCustomHaptic(scaledPattern);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAiCA,SAAgB,oBAA6B;CAC3C,OACE,OAAO,cAAc,eACrB,aAAa,aACb,OAAO,UAAU,YAAY;;;;;;;;;;;;;;;;AAyDjC,SAAgB,4BAAkC;CAChD,IAAI,CAAC,mBAAmB,EACtB;CAGF,IAAI;EACF,UAAU,QAAQ,GAAG;UACd,OAAO;EACd,QAAQ,KAAK,2BAA2B,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StanceChangeIndicator.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/StanceChangeIndicator.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA+C,MAAM,OAAO,CAAC;AAapE;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED
|
|
1
|
+
{"version":3,"file":"StanceChangeIndicator.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/StanceChangeIndicator.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA+C,MAAM,OAAO,CAAC;AAapE;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CA+OtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StanceChangeIndicator.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/StanceChangeIndicator.tsx"],"sourcesContent":["/**\n * StanceChangeIndicator - Visual feedback for stance changes\n * Displays Korean and English stance names with trigram symbols\n * \n * @module components/shared/three/indicators/StanceChangeIndicator\n * @category Combat UI\n * @korean 자세변경표시기\n */\n\n \nimport { Html } from \"@react-three/drei\";\nimport React, { useEffect, useState, useMemo, useRef } from \"react\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../utils/colorUtils\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport { \n getTrigramElementColor, \n getTrigramKoreanName, \n getTrigramEnglishName,\n getTrigramSymbol\n} from \"./ElementalColorSystem\";\nimport { triggerStanceChangeHaptic } from \"./HapticFeedback\";\n\n/**\n * Props for StanceChangeIndicator component\n */\nexport interface StanceChangeIndicatorProps {\n /** Current stance index (0-7) */\n readonly currentStance: number;\n /** Previous stance index (0-7) for change detection */\n readonly previousStance: number;\n /** Mobile layout flag */\n readonly isMobile?: boolean;\n /** Display duration in milliseconds (default: 1000ms) */\n readonly duration?: number;\n /** Show transition progress bar (default: true) */\n readonly showProgress?: boolean;\n /** Transition duration in milliseconds for progress bar (default: 600ms) */\n readonly transitionDuration?: number;\n}\n\n/**\n * StanceChangeIndicator Component\n * \n * Displays a temporary overlay showing the current trigram stance\n * with Korean name, English name, and trigram symbol.\n * \n * Features:\n * - Fade in/out animation\n * - Korean cyberpunk styling\n * - Responsive mobile layout\n * - Trigram symbol display\n * - Glow effect for visual emphasis\n * \n * @example\n * ```tsx\n * <StanceChangeIndicator\n * currentStance={player.stance}\n * previousStance={previousStance}\n * isMobile={isMobile}\n * />\n * ```\n * \n * @public\n * @korean 자세변경표시기\n */\nexport const StanceChangeIndicator: React.FC<StanceChangeIndicatorProps> = ({\n currentStance,\n previousStance,\n isMobile = false,\n duration = 1000,\n showProgress = true,\n transitionDuration = 600,\n}) => {\n const [showIndicator, setShowIndicator] = useState(false);\n const [progress, setProgress] = useState(0);\n const isMountedRef = useRef(true);\n const startTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n // Track component mount state\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // Show/hide indicator based on stance change\n // This effect intentionally sets state synchronously for immediate visual feedback\n useEffect(() => {\n // Cancel any existing animation frame first\n if (animationFrameRef.current !== undefined) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = undefined;\n }\n\n if (currentStance !== previousStance) {\n setShowIndicator(true);\n setProgress(0);\n startTimeRef.current = 0;\n\n // Trigger haptic feedback for stance change\n triggerStanceChangeHaptic();\n\n // Animation loop for progress bar\n if (showProgress) {\n const animate = (timestamp: number) => {\n if (!isMountedRef.current) return;\n \n // Initialize start time on first frame\n if (startTimeRef.current === 0) {\n startTimeRef.current = timestamp;\n }\n \n const elapsed = timestamp - startTimeRef.current;\n const newProgress = Math.min((elapsed / transitionDuration) * 100, 100);\n \n setProgress(newProgress);\n\n if (newProgress < 100) {\n animationFrameRef.current = requestAnimationFrame(animate);\n }\n };\n\n animationFrameRef.current = requestAnimationFrame(animate);\n }\n\n const timer = setTimeout(() => {\n if (isMountedRef.current) {\n setShowIndicator(false);\n }\n }, duration);\n\n return () => {\n clearTimeout(timer);\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }\n }, [currentStance, previousStance, duration, showProgress, transitionDuration]);\n\n // Get trigram stance from index\n const stance = useMemo(\n () => TRIGRAM_STANCES_ORDER[currentStance] ?? TrigramStance.GEON,\n [currentStance]\n );\n\n // Get elemental color for stance\n const elementalColor = useMemo(\n () => getTrigramElementColor(stance),\n [stance]\n );\n\n // Get trigram names using elemental color system\n const koreanName = useMemo(\n () => getTrigramKoreanName(stance),\n [stance]\n );\n\n const englishName = useMemo(\n () => getTrigramEnglishName(stance),\n [stance]\n );\n\n const trigramSymbol = useMemo(\n () => getTrigramSymbol(stance),\n [stance]\n );\n\n // Memoize animation styles to prevent redefinition on every render\n const animationStyles = useMemo(() => (\n <style>\n {`\n @keyframes fadeInOut {\n 0% {\n opacity: 0;\n transform: translateY(-20px);\n }\n 10% {\n opacity: 1;\n transform: translateY(0);\n }\n 90% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px);\n }\n }\n `}\n </style>\n ), []);\n\n if (!showIndicator) return null;\n\n const fontSize = isMobile ? 24 : 36;\n const subFontSize = isMobile ? 14 : 18;\n const top = isMobile ? \"30%\" : \"20%\";\n\n // Use elemental color system\n const primaryColorHex = hexToRgbaString(elementalColor, 1);\n\n return (\n <Html fullscreen>\n <div\n data-testid=\"stance-change-indicator\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={`Stance changed to ${englishName}`}\n style={{\n position: \"absolute\",\n top,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n textAlign: \"center\",\n animation: \"fadeInOut 1s\",\n pointerEvents: \"none\",\n zIndex: 1000,\n }}\n >\n {/* Main stance display */}\n <div\n style={{\n fontSize: `${fontSize}px`,\n color: primaryColorHex,\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: `0 0 20px ${hexToRgbaString(elementalColor, 0.8)}, \n 0 0 40px ${hexToRgbaString(elementalColor, 0.5)}`,\n marginBottom: \"8px\",\n }}\n >\n {koreanName} {trigramSymbol}\n </div>\n\n {/* English name */}\n <div\n style={{\n fontSize: `${subFontSize}px`,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1),\n fontFamily: FONT_FAMILY.KOREAN,\n textShadow: `0 0 10px ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6)}`,\n marginBottom: showProgress ? \"12px\" : \"0\",\n }}\n >\n {englishName}\n </div>\n\n {/* Transition progress bar (600ms) */}\n {showProgress && (\n <div\n data-testid=\"stance-transition-progress\"\n style={{\n width: \"200px\",\n margin: \"0 auto\",\n padding: \"8px 0\",\n }}\n >\n {/* Progress label */}\n <div\n style={{\n fontSize: \"11px\",\n color: \"rgba(255, 255, 255, 0.7)\",\n fontFamily: FONT_FAMILY.KOREAN,\n marginBottom: \"4px\",\n letterSpacing: \"1px\",\n }}\n >\n 팔괘전환 | Transition\n </div>\n \n {/* Progress bar container */}\n <div\n style={{\n width: \"100%\",\n height: \"6px\",\n backgroundColor: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: \"3px\",\n overflow: \"hidden\",\n border: `1px solid ${hexToRgbaString(elementalColor, 0.3)}`,\n }}\n >\n {/* Progress bar fill */}\n <div\n style={{\n width: `${progress}%`,\n height: \"100%\",\n backgroundColor: primaryColorHex,\n transition: \"width 0.05s linear\",\n boxShadow: `0 0 8px ${primaryColorHex}`,\n }}\n />\n </div>\n \n {/* Time remaining */}\n <div\n style={{\n fontSize: \"10px\",\n color: \"rgba(255, 255, 255, 0.5)\",\n fontFamily: FONT_FAMILY.KOREAN,\n marginTop: \"4px\",\n }}\n >\n {Math.max(0, Math.ceil(transitionDuration * (1 - progress / 100)))}ms\n </div>\n </div>\n )}\n\n {/* CSS Animation - Memoized to prevent redefinition */}\n {animationStyles}\n </div>\n </Html>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StanceChangeIndicator.js","names":[],"sources":["../../../../../src/components/shared/three/indicators/StanceChangeIndicator.tsx"],"sourcesContent":["/**\n * StanceChangeIndicator - Visual feedback for stance changes\n * Displays Korean and English stance names with trigram symbols\n * \n * @module components/shared/three/indicators/StanceChangeIndicator\n * @category Combat UI\n * @korean 자세변경표시기\n */\n\n \nimport { Html } from \"@react-three/drei\";\nimport React, { useEffect, useState, useMemo, useRef } from \"react\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../utils/colorUtils\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport { \n getTrigramElementColor, \n getTrigramKoreanName, \n getTrigramEnglishName,\n getTrigramSymbol\n} from \"./ElementalColorSystem\";\nimport { triggerStanceChangeHaptic } from \"./HapticFeedback\";\n\n/**\n * Props for StanceChangeIndicator component\n */\nexport interface StanceChangeIndicatorProps {\n /** Current stance index (0-7) */\n readonly currentStance: number;\n /** Previous stance index (0-7) for change detection */\n readonly previousStance: number;\n /** Mobile layout flag */\n readonly isMobile?: boolean;\n /** Display duration in milliseconds (default: 1000ms) */\n readonly duration?: number;\n /** Show transition progress bar (default: true) */\n readonly showProgress?: boolean;\n /** Transition duration in milliseconds for progress bar (default: 600ms) */\n readonly transitionDuration?: number;\n}\n\n/**\n * StanceChangeIndicator Component\n * \n * Displays a temporary overlay showing the current trigram stance\n * with Korean name, English name, and trigram symbol.\n * \n * Features:\n * - Fade in/out animation\n * - Korean cyberpunk styling\n * - Responsive mobile layout\n * - Trigram symbol display\n * - Glow effect for visual emphasis\n * \n * @example\n * ```tsx\n * <StanceChangeIndicator\n * currentStance={player.stance}\n * previousStance={previousStance}\n * isMobile={isMobile}\n * />\n * ```\n * \n * @korean 자세변경표시기\n */\nexport const StanceChangeIndicator: React.FC<StanceChangeIndicatorProps> = ({\n currentStance,\n previousStance,\n isMobile = false,\n duration = 1000,\n showProgress = true,\n transitionDuration = 600,\n}) => {\n const [showIndicator, setShowIndicator] = useState(false);\n const [progress, setProgress] = useState(0);\n const isMountedRef = useRef(true);\n const startTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n useEffect(() => {\n if (animationFrameRef.current !== undefined) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = undefined;\n }\n\n if (currentStance !== previousStance) {\n setShowIndicator(true);\n setProgress(0);\n startTimeRef.current = 0;\n\n triggerStanceChangeHaptic();\n\n if (showProgress) {\n const animate = (timestamp: number) => {\n if (!isMountedRef.current) return;\n \n if (startTimeRef.current === 0) {\n startTimeRef.current = timestamp;\n }\n \n const elapsed = timestamp - startTimeRef.current;\n const newProgress = Math.min((elapsed / transitionDuration) * 100, 100);\n \n setProgress(newProgress);\n\n if (newProgress < 100) {\n animationFrameRef.current = requestAnimationFrame(animate);\n }\n };\n\n animationFrameRef.current = requestAnimationFrame(animate);\n }\n\n const timer = setTimeout(() => {\n if (isMountedRef.current) {\n setShowIndicator(false);\n }\n }, duration);\n\n return () => {\n clearTimeout(timer);\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }\n }, [currentStance, previousStance, duration, showProgress, transitionDuration]);\n\n const stance = useMemo(\n () => TRIGRAM_STANCES_ORDER[currentStance] ?? TrigramStance.GEON,\n [currentStance]\n );\n\n const elementalColor = useMemo(\n () => getTrigramElementColor(stance),\n [stance]\n );\n\n const koreanName = useMemo(\n () => getTrigramKoreanName(stance),\n [stance]\n );\n\n const englishName = useMemo(\n () => getTrigramEnglishName(stance),\n [stance]\n );\n\n const trigramSymbol = useMemo(\n () => getTrigramSymbol(stance),\n [stance]\n );\n\n const animationStyles = useMemo(() => (\n <style>\n {`\n @keyframes fadeInOut {\n 0% {\n opacity: 0;\n transform: translateY(-20px);\n }\n 10% {\n opacity: 1;\n transform: translateY(0);\n }\n 90% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px);\n }\n }\n `}\n </style>\n ), []);\n\n if (!showIndicator) return null;\n\n const fontSize = isMobile ? 24 : 36;\n const subFontSize = isMobile ? 14 : 18;\n const top = isMobile ? \"30%\" : \"20%\";\n\n const primaryColorHex = hexToRgbaString(elementalColor, 1);\n\n return (\n <Html fullscreen>\n <div\n data-testid=\"stance-change-indicator\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={`Stance changed to ${englishName}`}\n style={{\n position: \"absolute\",\n top,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n textAlign: \"center\",\n animation: \"fadeInOut 1s\",\n pointerEvents: \"none\",\n zIndex: 1000,\n }}\n >\n {/* Main stance display */}\n <div\n style={{\n fontSize: `${fontSize}px`,\n color: primaryColorHex,\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: `0 0 20px ${hexToRgbaString(elementalColor, 0.8)}, \n 0 0 40px ${hexToRgbaString(elementalColor, 0.5)}`,\n marginBottom: \"8px\",\n }}\n >\n {koreanName} {trigramSymbol}\n </div>\n\n {/* English name */}\n <div\n style={{\n fontSize: `${subFontSize}px`,\n color: hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1),\n fontFamily: FONT_FAMILY.KOREAN,\n textShadow: `0 0 10px ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.6)}`,\n marginBottom: showProgress ? \"12px\" : \"0\",\n }}\n >\n {englishName}\n </div>\n\n {/* Transition progress bar (600ms) */}\n {showProgress && (\n <div\n data-testid=\"stance-transition-progress\"\n style={{\n width: \"200px\",\n margin: \"0 auto\",\n padding: \"8px 0\",\n }}\n >\n {/* Progress label */}\n <div\n style={{\n fontSize: \"11px\",\n color: \"rgba(255, 255, 255, 0.7)\",\n fontFamily: FONT_FAMILY.KOREAN,\n marginBottom: \"4px\",\n letterSpacing: \"1px\",\n }}\n >\n 팔괘전환 | Transition\n </div>\n \n {/* Progress bar container */}\n <div\n style={{\n width: \"100%\",\n height: \"6px\",\n backgroundColor: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: \"3px\",\n overflow: \"hidden\",\n border: `1px solid ${hexToRgbaString(elementalColor, 0.3)}`,\n }}\n >\n {/* Progress bar fill */}\n <div\n style={{\n width: `${progress}%`,\n height: \"100%\",\n backgroundColor: primaryColorHex,\n transition: \"width 0.05s linear\",\n boxShadow: `0 0 8px ${primaryColorHex}`,\n }}\n />\n </div>\n \n {/* Time remaining */}\n <div\n style={{\n fontSize: \"10px\",\n color: \"rgba(255, 255, 255, 0.5)\",\n fontFamily: FONT_FAMILY.KOREAN,\n marginTop: \"4px\",\n }}\n >\n {Math.max(0, Math.ceil(transitionDuration * (1 - progress / 100)))}ms\n </div>\n </div>\n )}\n\n {/* CSS Animation - Memoized to prevent redefinition */}\n {animationStyles}\n </div>\n </Html>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,yBAA+D,EAC1E,eACA,gBACA,WAAW,OACX,WAAW,KACX,eAAe,MACf,qBAAqB,UACjB;CACJ,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,UAAU,eAAe,SAAS,EAAE;CAC3C,MAAM,eAAe,OAAO,KAAK;CACjC,MAAM,eAAe,OAAe,EAAE;CACtC,MAAM,oBAAoB,OAA2B,KAAA,EAAU;CAE/D,gBAAgB;EACd,aAAa,UAAU;EACvB,aAAa;GACX,aAAa,UAAU;;IAExB,EAAE,CAAC;CAEN,gBAAgB;EACd,IAAI,kBAAkB,YAAY,KAAA,GAAW;GAC3C,qBAAqB,kBAAkB,QAAQ;GAC/C,kBAAkB,UAAU,KAAA;;EAG9B,IAAI,kBAAkB,gBAAgB;GACpC,iBAAiB,KAAK;GACtB,YAAY,EAAE;GACd,aAAa,UAAU;GAEvB,2BAA2B;GAE3B,IAAI,cAAc;IAChB,MAAM,WAAW,cAAsB;KACrC,IAAI,CAAC,aAAa,SAAS;KAE3B,IAAI,aAAa,YAAY,GAC3B,aAAa,UAAU;KAGzB,MAAM,UAAU,YAAY,aAAa;KACzC,MAAM,cAAc,KAAK,IAAK,UAAU,qBAAsB,KAAK,IAAI;KAEvE,YAAY,YAAY;KAExB,IAAI,cAAc,KAChB,kBAAkB,UAAU,sBAAsB,QAAQ;;IAI9D,kBAAkB,UAAU,sBAAsB,QAAQ;;GAG5D,MAAM,QAAQ,iBAAiB;IAC7B,IAAI,aAAa,SACf,iBAAiB,MAAM;MAExB,SAAS;GAEZ,aAAa;IACX,aAAa,MAAM;IACnB,IAAI,kBAAkB,SACpB,qBAAqB,kBAAkB,QAAQ;;;IAIpD;EAAC;EAAe;EAAgB;EAAU;EAAc;EAAmB,CAAC;CAE/E,MAAM,SAAS,cACP,sBAAsB,kBAAkB,cAAc,MAC5D,CAAC,cAAc,CAChB;CAED,MAAM,iBAAiB,cACf,uBAAuB,OAAO,EACpC,CAAC,OAAO,CACT;CAED,MAAM,aAAa,cACX,qBAAqB,OAAO,EAClC,CAAC,OAAO,CACT;CAED,MAAM,cAAc,cACZ,sBAAsB,OAAO,EACnC,CAAC,OAAO,CACT;CAED,MAAM,gBAAgB,cACd,iBAAiB,OAAO,EAC9B,CAAC,OAAO,CACT;CAED,MAAM,kBAAkB,cACtB,oBAAC,SAAD,EAAA,UACG;;;;;;;;;;;;;;;;;;;SAoBK,CAAA,EACP,EAAE,CAAC;CAEN,IAAI,CAAC,eAAe,OAAO;CAE3B,MAAM,WAAW,WAAW,KAAK;CACjC,MAAM,cAAc,WAAW,KAAK;CACpC,MAAM,MAAM,WAAW,QAAQ;CAE/B,MAAM,kBAAkB,gBAAgB,gBAAgB,EAAE;CAE1D,OACE,oBAAC,MAAD;EAAM,YAAA;YACJ,qBAAC,OAAD;GACE,eAAY;GACZ,MAAK;GACL,aAAU;GACV,cAAY,qBAAqB;GACjC,OAAO;IACL,UAAU;IACV;IACA,MAAM;IACN,WAAW;IACX,WAAW;IACX,WAAW;IACX,eAAe;IACf,QAAQ;IACT;aAdH;IAiBE,qBAAC,OAAD;KACE,OAAO;MACL,UAAU,GAAG,SAAS;MACtB,OAAO;MACP,YAAY,YAAY;MACxB,YAAY;MACZ,YAAY,YAAY,gBAAgB,gBAAgB,GAAI,CAAC;mCACtC,gBAAgB,gBAAgB,GAAI;MAC3D,cAAc;MACf;eATH;MAWG;MAAW;MAAE;MACV;;IAGN,oBAAC,OAAD;KACE,OAAO;MACL,UAAU,GAAG,YAAY;MACzB,OAAO,gBAAgB,cAAc,aAAa,EAAE;MACpD,YAAY,YAAY;MACxB,YAAY,YAAY,gBAAgB,cAAc,aAAa,GAAI;MACvE,cAAc,eAAe,SAAS;MACvC;eAEA;KACG,CAAA;IAGL,gBACC,qBAAC,OAAD;KACE,eAAY;KACZ,OAAO;MACL,OAAO;MACP,QAAQ;MACR,SAAS;MACV;eANH;MASE,oBAAC,OAAD;OACE,OAAO;QACL,UAAU;QACV,OAAO;QACP,YAAY,YAAY;QACxB,cAAc;QACd,eAAe;QAChB;iBACF;OAEK,CAAA;MAGN,oBAAC,OAAD;OACE,OAAO;QACL,OAAO;QACP,QAAQ;QACR,iBAAiB;QACjB,cAAc;QACd,UAAU;QACV,QAAQ,aAAa,gBAAgB,gBAAgB,GAAI;QAC1D;iBAGD,oBAAC,OAAD,EACE,OAAO;QACL,OAAO,GAAG,SAAS;QACnB,QAAQ;QACR,iBAAiB;QACjB,YAAY;QACZ,WAAW,WAAW;QACvB,EACD,CAAA;OACE,CAAA;MAGN,qBAAC,OAAD;OACE,OAAO;QACL,UAAU;QACV,OAAO;QACP,YAAY,YAAY;QACxB,WAAW;QACZ;iBANH,CAQG,KAAK,IAAI,GAAG,KAAK,KAAK,sBAAsB,IAAI,WAAW,KAAK,CAAC,EAAC,KAC/D;;MACF;;IAIP;IACG;;EACD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrigramSymbol3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/TrigramSymbol3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC;IACtC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gCAAgC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED
|
|
1
|
+
{"version":3,"file":"TrigramSymbol3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/indicators/TrigramSymbol3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC;IACtC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gCAAgC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0E1D,CAAC;AAEF;;;GAGG;;AACH,wBAA2C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Player3DWithTransitions.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/models/Player3DWithTransitions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAK5E;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,oBAAoB;IACxE,wDAAwD;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,uDAAuD;IACvD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,oDAAoD;IACpD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,oDAAoD;IACpD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CACjC,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,aAAa,KACpB,IAAI,CAAC;IACV,gDAAgD;IAChD,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CACvE;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAC5C,4BAA4B,
|
|
1
|
+
{"version":3,"file":"Player3DWithTransitions.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/models/Player3DWithTransitions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAK5E;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,oBAAoB;IACxE,wDAAwD;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,uDAAuD;IACvD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,oDAAoD;IACpD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,oDAAoD;IACpD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CACjC,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,aAAa,KACpB,IAAI,CAAC;IACV,gDAAgD;IAChD,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CACvE;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAC5C,4BAA4B,CA2E7B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Player3DWithTransitions.js","names":[],"sources":["../../../../../src/components/shared/three/models/Player3DWithTransitions.tsx"],"sourcesContent":["/**\n * Enhanced Player3D component with stance transition animations\n *\n * Demonstrates integration of stance change visual effects:\n * - StanceSymbol3D for floating trigram symbol\n * - StanceTransitionEffect for smooth transitions\n *\n * This wrapper can be used to enhance SkeletalPlayer3D with automatic\n * stance change detection and visual effects.\n *\n * @module components/three/Player3DWithTransitions\n * @category 3D Components\n * @korean 자세전환플레이어3D\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useAudio } from \"../../../../audio/AudioProvider\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport type { Player3DUnifiedProps } from \"../../../../types/player-visual\";\nimport StanceSymbol3D from \"../effects/StanceSymbol3D\";\nimport StanceTransitionEffect from \"../effects/StanceTransitionEffect\";\nimport { SkeletalPlayer3D } from \"./SkeletalPlayer3D\";\n\n/**\n * Props for Player3DWithTransitions component\n */\nexport interface Player3DWithTransitionsProps extends Player3DUnifiedProps {\n /** Specific attack animation name (for attack state) */\n readonly attackAnimation?: string;\n /** Enable stance transition effects (default: true) */\n readonly enableTransitionEffects?: boolean;\n /** Enable floating stance symbol (default: true) */\n readonly enableStanceSymbol?: boolean;\n /** Enable stance change audio (default: true) */\n readonly enableStanceAudio?: boolean;\n /** Transition duration in seconds (default: 0.5) */\n readonly transitionDuration?: number;\n /** Callback when stance transition starts */\n readonly onStanceTransitionStart?: (\n fromStance: TrigramStance,\n toStance: TrigramStance\n ) => void;\n /** Callback when stance transition completes */\n readonly onStanceTransitionComplete?: (stance: TrigramStance) => void;\n}\n\n/**\n * Audio asset IDs for stance transitions\n */\nconst AUDIO_ASSETS = {\n STANCE_CHANGE: \"stance_change\",\n} as const;\n\n/**\n * Player3DWithTransitions Component\n *\n * Enhanced player component with automatic stance change detection and visual effects.\n * Wraps SkeletalPlayer3D and adds:\n * - Floating trigram symbol\n * - Smooth transition effects\n * - Audio synchronization\n *\n * Performance optimized:\n * - Effects can be individually disabled for mobile\n * - Uses stance change detection to minimize updates\n * - Reuses components efficiently\n *\n * @example\n * ```tsx\n * <Player3DWithTransitions\n * playerId=\"player1\"\n * archetype={PlayerArchetype.MUSA}\n * stance={currentStance}\n * position={[0, 0, 0]}\n * rotation={0}\n * health={85}\n * maxHealth={100}\n * stamina={60}\n * ki={40}\n * pain={20}\n * balance=\"READY\"\n * consciousness={100}\n * bloodLoss={0}\n * currentAnimation=\"idle\"\n * isMobile={false}\n * enableTransitionEffects={true}\n * enableStanceSymbol={true}\n * onStanceTransitionComplete={(stance) => console.log('Transitioned to:', stance)}\n * />\n * ```\n */\nexport const Player3DWithTransitions: React.FC<\n Player3DWithTransitionsProps\n> = ({\n stance,\n ki,\n isMobile = false,\n attackAnimation,\n enableTransitionEffects = true,\n enableStanceSymbol = true,\n enableStanceAudio = true,\n transitionDuration = 0.5,\n onStanceTransitionStart,\n onStanceTransitionComplete,\n ...playerProps\n}) => {\n const audio = useAudio();\n const prevStanceRef = useRef<TrigramStance>(stance);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const [fromStance, setFromStance] = useState<TrigramStance>(stance);\n\n
|
|
1
|
+
{"version":3,"file":"Player3DWithTransitions.js","names":[],"sources":["../../../../../src/components/shared/three/models/Player3DWithTransitions.tsx"],"sourcesContent":["/**\n * Enhanced Player3D component with stance transition animations\n *\n * Demonstrates integration of stance change visual effects:\n * - StanceSymbol3D for floating trigram symbol\n * - StanceTransitionEffect for smooth transitions\n *\n * This wrapper can be used to enhance SkeletalPlayer3D with automatic\n * stance change detection and visual effects.\n *\n * @module components/three/Player3DWithTransitions\n * @category 3D Components\n * @korean 자세전환플레이어3D\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useAudio } from \"../../../../audio/AudioProvider\";\nimport { TrigramStance } from \"../../../../types/common\";\nimport type { Player3DUnifiedProps } from \"../../../../types/player-visual\";\nimport StanceSymbol3D from \"../effects/StanceSymbol3D\";\nimport StanceTransitionEffect from \"../effects/StanceTransitionEffect\";\nimport { SkeletalPlayer3D } from \"./SkeletalPlayer3D\";\n\n/**\n * Props for Player3DWithTransitions component\n */\nexport interface Player3DWithTransitionsProps extends Player3DUnifiedProps {\n /** Specific attack animation name (for attack state) */\n readonly attackAnimation?: string;\n /** Enable stance transition effects (default: true) */\n readonly enableTransitionEffects?: boolean;\n /** Enable floating stance symbol (default: true) */\n readonly enableStanceSymbol?: boolean;\n /** Enable stance change audio (default: true) */\n readonly enableStanceAudio?: boolean;\n /** Transition duration in seconds (default: 0.5) */\n readonly transitionDuration?: number;\n /** Callback when stance transition starts */\n readonly onStanceTransitionStart?: (\n fromStance: TrigramStance,\n toStance: TrigramStance\n ) => void;\n /** Callback when stance transition completes */\n readonly onStanceTransitionComplete?: (stance: TrigramStance) => void;\n}\n\n/**\n * Audio asset IDs for stance transitions\n */\nconst AUDIO_ASSETS = {\n STANCE_CHANGE: \"stance_change\",\n} as const;\n\n/**\n * Player3DWithTransitions Component\n *\n * Enhanced player component with automatic stance change detection and visual effects.\n * Wraps SkeletalPlayer3D and adds:\n * - Floating trigram symbol\n * - Smooth transition effects\n * - Audio synchronization\n *\n * Performance optimized:\n * - Effects can be individually disabled for mobile\n * - Uses stance change detection to minimize updates\n * - Reuses components efficiently\n *\n * @example\n * ```tsx\n * <Player3DWithTransitions\n * playerId=\"player1\"\n * archetype={PlayerArchetype.MUSA}\n * stance={currentStance}\n * position={[0, 0, 0]}\n * rotation={0}\n * health={85}\n * maxHealth={100}\n * stamina={60}\n * ki={40}\n * pain={20}\n * balance=\"READY\"\n * consciousness={100}\n * bloodLoss={0}\n * currentAnimation=\"idle\"\n * isMobile={false}\n * enableTransitionEffects={true}\n * enableStanceSymbol={true}\n * onStanceTransitionComplete={(stance) => console.log('Transitioned to:', stance)}\n * />\n * ```\n */\nexport const Player3DWithTransitions: React.FC<\n Player3DWithTransitionsProps\n> = ({\n stance,\n ki,\n isMobile = false,\n attackAnimation,\n enableTransitionEffects = true,\n enableStanceSymbol = true,\n enableStanceAudio = true,\n transitionDuration = 0.5,\n onStanceTransitionStart,\n onStanceTransitionComplete,\n ...playerProps\n}) => {\n const audio = useAudio();\n const prevStanceRef = useRef<TrigramStance>(stance);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const [fromStance, setFromStance] = useState<TrigramStance>(stance);\n\n\n useEffect(() => {\n const previousStance = prevStanceRef.current;\n\n if (previousStance !== stance) {\n prevStanceRef.current = stance;\n\n setIsTransitioning(true);\n setFromStance(previousStance);\n onStanceTransitionStart?.(previousStance, stance);\n\n if (enableStanceAudio) {\n audio.playSFX(AUDIO_ASSETS.STANCE_CHANGE);\n }\n }\n }, [stance, audio, enableStanceAudio, onStanceTransitionStart]);\n\n const handleTransitionComplete = useCallback(() => {\n setIsTransitioning(false);\n onStanceTransitionComplete?.(stance);\n }, [stance, onStanceTransitionComplete]);\n\n return (\n <group name=\"player3d-with-transitions\">\n {/* Base player model */}\n <SkeletalPlayer3D\n stance={stance}\n ki={ki}\n isMobile={isMobile}\n attackAnimation={attackAnimation}\n {...playerProps}\n />\n\n {/* Floating stance symbol */}\n {enableStanceSymbol && (\n <StanceSymbol3D\n stance={stance}\n heightOffset={2.5}\n animated={true}\n scale={isMobile ? 0.8 : 1.0} // Smaller on mobile\n showName={!isMobile} // Hide Korean name on mobile for clarity\n />\n )}\n\n {/* Stance transition effect */}\n {enableTransitionEffects && isTransitioning && (\n <StanceTransitionEffect\n fromStance={fromStance}\n toStance={stance}\n onTransitionComplete={handleTransitionComplete}\n duration={transitionDuration}\n showNameOverlay={!isMobile} // Hide overlay on mobile\n />\n )}\n </group>\n );\n};\n\nexport default Player3DWithTransitions;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiDA,IAAM,eAAe,EACnB,eAAe,iBAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCD,IAAa,2BAER,EACH,QACA,IACA,WAAW,OACX,iBACA,0BAA0B,MAC1B,qBAAqB,MACrB,oBAAoB,MACpB,qBAAqB,IACrB,yBACA,4BACA,GAAG,kBACC;CACJ,MAAM,QAAQ,UAAU;CACxB,MAAM,gBAAgB,OAAsB,OAAO;CACnD,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,MAAM;CAC7D,MAAM,CAAC,YAAY,iBAAiB,SAAwB,OAAO;CAGnE,gBAAgB;EACd,MAAM,iBAAiB,cAAc;EAErC,IAAI,mBAAmB,QAAQ;GAC7B,cAAc,UAAU;GAExB,mBAAmB,KAAK;GACxB,cAAc,eAAe;GAC7B,0BAA0B,gBAAgB,OAAO;GAEjD,IAAI,mBACF,MAAM,QAAQ,aAAa,cAAc;;IAG5C;EAAC;EAAQ;EAAO;EAAmB;EAAwB,CAAC;CAE/D,MAAM,2BAA2B,kBAAkB;EACjD,mBAAmB,MAAM;EACzB,6BAA6B,OAAO;IACnC,CAAC,QAAQ,2BAA2B,CAAC;CAExC,OACE,qBAAC,SAAD;EAAO,MAAK;YAAZ;GAEE,oBAAC,kBAAD;IACU;IACJ;IACM;IACO;IACjB,GAAI;IACJ,CAAA;GAGD,sBACC,oBAAC,gBAAD;IACU;IACR,cAAc;IACd,UAAU;IACV,OAAO,WAAW,KAAM;IACxB,UAAU,CAAC;IACX,CAAA;GAIH,2BAA2B,mBAC1B,oBAAC,wBAAD;IACc;IACZ,UAAU;IACV,sBAAsB;IACtB,UAAU;IACV,iBAAiB,CAAC;IAClB,CAAA;GAEE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkeletalPlayer3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/models/SkeletalPlayer3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAA+C,MAAM,OAAO,CAAC;AAkBpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAiD5E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CACrC,oBAAoB,GAAG;IACrB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC,
|
|
1
|
+
{"version":3,"file":"SkeletalPlayer3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/models/SkeletalPlayer3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAA+C,MAAM,OAAO,CAAC;AAkBpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAiD5E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CACrC,oBAAoB,GAAG;IACrB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC,CA6XF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkeletalPlayer3D.js","names":[],"sources":["../../../../../src/components/shared/three/models/SkeletalPlayer3D.tsx"],"sourcesContent":["/**\n * SkeletalPlayer3D component with articulated body model\n *\n * Implements full skeletal rigging system for realistic fighter animations\n * with independent limb movement, elbow/knee joints, and attack animations.\n *\n * @module components/three/SkeletalPlayer3D\n * @category 3D Components\n * @korean 골격플레이어3D컴포넌트\n */\n\nimport { Html } from \"@react-three/drei\";\nimport { useFrame } from \"@react-three/fiber\";\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport * as THREE from \"three\";\nimport { getArchetypePhysicalAttributes } from \"../../../../data/archetypePhysicalAttributes\";\nimport { useBalanceAnimations } from \"../../../../hooks/useBalanceAnimations\";\nimport { useHandPoseTransitions } from \"../../../../hooks/useHandPoseTransitions\";\nimport { useMuscleActivation } from \"../../../../hooks/useMuscleActivation\";\nimport { useSkeletalAnimation } from \"../../../../hooks/useSkeletalAnimation\";\nimport {\n createDefaultFacialDamage,\n createScaledHumanoidRig,\n getExpressionFromCombatState,\n getHeadAngleRadians,\n lockFacing,\n unlockFacing,\n updateFacingTowardOpponent,\n} from \"../../../../systems/animation\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"../../../../types/constants\";\nimport { FacialExpression } from \"../../../../types/facial\";\nimport type { Player3DUnifiedProps } from \"../../../../types/player-visual\";\nimport type { SkeletalRig } from \"../../../../types/skeletal\";\nimport { toHexColor } from \"../../../../utils/colorHelpers\";\nimport { getArchetypeSkinTone } from \"../../../../utils/colorUtils\";\nimport BoneRenderer from \"../anatomy/BoneRenderer\";\nimport PlayerStateIndicators from \"../effects/PlayerStateIndicators\";\n\n/**\n * Get stance-specific color from Korean theming\n *\n * @param stance - Current trigram stance\n * @returns Hex color number\n * @korean 자세색상가져오기\n */\nconst getStanceColor = (stance: string): number => {\n const stanceColors: Record<string, number> = {\n geon: KOREAN_COLORS.TRIGRAM_GEON_PRIMARY,\n tae: KOREAN_COLORS.TRIGRAM_TAE_PRIMARY,\n li: KOREAN_COLORS.TRIGRAM_LI_PRIMARY,\n jin: KOREAN_COLORS.TRIGRAM_JIN_PRIMARY,\n son: KOREAN_COLORS.TRIGRAM_SON_PRIMARY,\n gam: KOREAN_COLORS.TRIGRAM_GAM_PRIMARY,\n gan: KOREAN_COLORS.TRIGRAM_GAN_PRIMARY,\n gon: KOREAN_COLORS.TRIGRAM_GON_PRIMARY,\n };\n return stanceColors[stance] ?? KOREAN_COLORS.PRIMARY_CYAN;\n};\n\n/**\n * Get trigram symbol for stance\n *\n * @param stance - Current trigram stance\n * @returns Unicode trigram symbol\n * @korean 팔괘기호가져오기\n */\nconst getTrigramSymbol = (stance: string): string => {\n const symbols: Record<string, string> = {\n geon: \"☰\",\n tae: \"☱\",\n li: \"☲\",\n jin: \"☳\",\n son: \"☴\",\n gam: \"☵\",\n gan: \"☶\",\n gon: \"☷\",\n };\n return symbols[stance] ?? \"☰\";\n};\n\n/**\n * SkeletalPlayer3D Component\n *\n * Complete skeletal player with 28-bone rig and realistic animations.\n * Supports all Korean martial arts attack animations (jab, cross, kicks, block).\n *\n * @example\n * ```tsx\n * <SkeletalPlayer3D\n * playerId=\"player1\"\n * archetype={PlayerArchetype.MUSA}\n * stance={TrigramStance.GEON}\n * position={[0, 0, 0]}\n * rotation={0}\n * health={85}\n * maxHealth={100}\n * stamina={60}\n * ki={40}\n * currentAnimation=\"attack\"\n * attackAnimation=\"jab\"\n * showDetails={true}\n * />\n * ```\n *\n * @korean 골격플레이어3D컴포넌트\n */\nexport const SkeletalPlayer3D: React.FC<\n Player3DUnifiedProps & {\n readonly attackAnimation?: string;\n readonly showSkeleton?: boolean;\n }\n> = ({\n playerId,\n archetype,\n stance,\n position,\n rotation,\n health,\n maxHealth,\n stamina,\n ki,\n pain,\n balance,\n consciousness,\n bloodLoss,\n isBlocking,\n isStunned = false,\n isCountering = false,\n currentAnimation,\n isMobile,\n name,\n scale = 1,\n showDetails = true,\n facing = \"right\",\n showStanceIndicator = true,\n onAnimationComplete,\n attackAnimation,\n showSkeleton = false,\n facialExpression,\n facialDamage,\n enableFacialExpressions = false,\n enableEyeTracking = true,\n opponentPosition,\n bodyFacing,\n onBodyFacingUpdate,\n laterality, // Stance laterality (left/right foot forward)\n}) => {\n // Use laterality with default to \"right\"\n const effectiveLaterality = laterality ?? \"right\";\n // Get physical attributes for the archetype\n const physicalAttributes = useMemo(\n () => getArchetypePhysicalAttributes(archetype),\n [archetype],\n );\n\n // Create skeletal rig with scaled dimensions based on archetype\n const rig = useMemo<SkeletalRig>(\n () => createScaledHumanoidRig(physicalAttributes),\n [physicalAttributes],\n );\n\n // ========================================\n // ANIMATION HOOKS - Modular animation system\n // ========================================\n\n // Base skeletal animation (idle, walk, attack, etc.)\n const { updateRigAnimation, diagonalRotationY } = useSkeletalAnimation({\n currentAnimation,\n attackAnimation,\n isBlocking,\n stance,\n laterality: effectiveLaterality, // Pass laterality for animation mirroring\n onAnimationComplete,\n });\n\n // Hand pose transitions for both hands\n const { leftHandState, rightHandState, updateHandAnimations } =\n useHandPoseTransitions({\n currentAnimation,\n attackAnimation,\n isBlocking,\n });\n\n // NOTE: Guard pose overlay removed - stance animations built with MartialArtsAnimationBuilder\n // already include proper guard positions via transitionToStanceGuard()\n // 가드 포즈 오버레이 제거 - MartialArtsAnimationBuilder로 빌드된 자세 애니메이션에\n // transitionToStanceGuard()를 통한 적절한 가드 위치가 이미 포함되어 있음\n\n // Balance animations (sway, stumble, lean based on balance state)\n const { swayPosition, helplessRotation, updateBalanceAnimations } =\n useBalanceAnimations({\n balance,\n });\n\n // Muscle activation system\n const { muscleStates, updateMuscleActivations } = useMuscleActivation({\n currentAnimation,\n attackAnimation,\n isBlocking,\n stamina,\n });\n\n // Get archetype-specific skin tone\n const skinTone = useMemo(() => getArchetypeSkinTone(archetype), [archetype]);\n\n // Body color - use skin tone for normal, override for special states\n const bodyColor = useMemo(() => {\n if (isStunned) return KOREAN_COLORS.WARNING_YELLOW;\n if (health / maxHealth < 0.3) return KOREAN_COLORS.ACCENT_RED;\n if (ki / 100 > 0.8) return KOREAN_COLORS.PRIMARY_CYAN;\n return skinTone; // Use archetype skin tone instead of primary color\n }, [isStunned, health, maxHealth, ki, skinTone]);\n\n // Stance color\n const stanceColor = useMemo(() => getStanceColor(stance), [stance]);\n const trigramSymbol = useMemo(() => getTrigramSymbol(stance), [stance]);\n\n // Track recent combat events for expression calculation\n const [justHit, setJustHit] = useState(false);\n const [justLanded, setJustLanded] = useState(false);\n const lastHealthRef = useRef(health);\n\n // Detect hit events (health decreased)\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (health < lastHealthRef.current) {\n setJustHit(true);\n timeoutId = setTimeout(() => setJustHit(false), 1000); // Clear after 1 second\n }\n\n lastHealthRef.current = health;\n\n return () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [health]);\n\n // Detect successful attacks (currentAnimation changed to attack)\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (currentAnimation === \"attack\") {\n setJustLanded(true);\n timeoutId = setTimeout(() => setJustLanded(false), 500); // Clear after 0.5 seconds\n }\n\n return () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [currentAnimation]);\n\n // Calculate facial expression from combat state (or use provided one)\n const calculatedExpression = useMemo(() => {\n if (!enableFacialExpressions) {\n return FacialExpression.NEUTRAL;\n }\n\n if (facialExpression) {\n return facialExpression;\n }\n\n return getExpressionFromCombatState(\n health,\n maxHealth,\n stamina,\n pain,\n consciousness,\n justHit,\n justLanded,\n );\n }, [\n enableFacialExpressions,\n facialExpression,\n health,\n maxHealth,\n stamina,\n pain,\n consciousness,\n justHit,\n justLanded,\n ]);\n\n // Facial damage state\n const calculatedFacialDamage = useMemo(() => {\n return facialDamage ?? createDefaultFacialDamage();\n }, [facialDamage]);\n\n // Opponent position for eye tracking\n const opponentPos = useMemo(() => {\n if (opponentPosition) {\n return new THREE.Vector3(...opponentPosition);\n }\n // Default: opponent in front\n return new THREE.Vector3(facing === \"right\" ? 5 : -5, 2, 0);\n }, [opponentPosition, facing]);\n\n // ========================================\n // ANIMATION FRAME LOOP - Modular hook-based system\n // ========================================\n\n // Frame counter for periodic updates\n const frameCounter = useRef(0);\n\n // Animation loop using useFrame (60fps)\n useFrame((_state, delta) => {\n // Update body facing to track opponent (if enabled)\n // ONLY track opponent when NOT moving (walk animations handle their own direction)\n const isWalkingAnimation =\n currentAnimation === \"walk\" ||\n (typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"step_\"));\n\n if (\n bodyFacing &&\n opponentPosition &&\n onBodyFacingUpdate &&\n !isWalkingAnimation\n ) {\n const playerPos = { x: position[0], y: position[2] }; // X and Z for 2D top-down\n const opponentPos = { x: opponentPosition[0], y: opponentPosition[2] };\n\n // Check if facing should be locked during committed animations\n const isStepAnimation =\n typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"step_\");\n const isTurnAnimation =\n typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"turn_\");\n\n const shouldLock =\n currentAnimation === \"attack\" ||\n currentAnimation === \"defend\" ||\n isStepAnimation ||\n isTurnAnimation;\n\n let updatedFacing = bodyFacing;\n\n if (shouldLock && !bodyFacing.isLocked) {\n // Lock facing at start of committed action (attack/defend/step/turn)\n updatedFacing = lockFacing(bodyFacing);\n } else if (!shouldLock && bodyFacing.isLocked) {\n // Unlock facing after committed action completes\n updatedFacing = unlockFacing(bodyFacing);\n }\n\n // Update facing direction (handles rotation speed, head tracking, turns)\n if (!updatedFacing.isLocked) {\n updatedFacing = updateFacingTowardOpponent(\n updatedFacing,\n playerPos,\n opponentPos,\n delta,\n Date.now(),\n );\n }\n\n // Notify parent if facing changed\n if (updatedFacing !== bodyFacing) {\n onBodyFacingUpdate(updatedFacing);\n }\n }\n\n // ========================================\n // HOOK-BASED ANIMATION UPDATES (60fps)\n // ========================================\n\n // Update frame counter for periodic state sync\n frameCounter.current = (frameCounter.current + 1) % 10;\n\n // 1. Base skeletal animation (idle, walk, attack, etc.)\n // Stance-specific guard positions are built into the MartialArtsAnimationBuilder animations\n // 자세별 가드 위치가 MartialArtsAnimationBuilder 애니메이션에 포함됨\n updateRigAnimation(rig, delta);\n\n // 2. Hand pose transitions\n updateHandAnimations(delta);\n\n // 3. Balance animations (sway, stumble, lean)\n updateBalanceAnimations(delta, frameCounter.current);\n\n // 5. Muscle activation states\n updateMuscleActivations(delta, frameCounter.current);\n\n // Apply head rotation toward opponent (if body facing tracking is enabled)\n // Note: Torso rotation is now handled by guard pose overlay for proper stance positioning\n // Only the head tracks the opponent independently for natural looking\n if (bodyFacing) {\n // Apply head rotation to head bone (includes independent offset)\n // Head can track ±45° independently from torso for natural looking\n const head = rig.bones.get(\"head\");\n if (head) {\n const headRotation = getHeadAngleRadians(bodyFacing);\n head.rotation.y = headRotation;\n }\n }\n });\n\n // Use diagonal rotation override if set, otherwise use prop rotation\n const effectiveRotation = diagonalRotationY ?? rotation;\n\n return (\n <group\n position={position}\n rotation={[0, effectiveRotation, 0]}\n scale={[facing === \"left\" ? -scale : scale, scale, scale]}\n name={`skeletal-player3d-${playerId}`}\n >\n {/* Inner group for sway animation and helpless lean */}\n <group position={swayPosition} rotation={[helplessRotation, 0, 0]}>\n {/* Skeletal rig rendering with bone-attached muscles */}\n <BoneRenderer\n rig={rig}\n color={bodyColor}\n showBones={true}\n renderMode={showSkeleton ? \"debug\" : \"solid\"}\n leftHandState={leftHandState}\n rightHandState={rightHandState}\n cameraDistance={10}\n facialExpression={calculatedExpression}\n facialDamage={calculatedFacialDamage}\n opponentPosition={opponentPos}\n enableFacialExpressions={enableFacialExpressions}\n enableEyeTracking={enableEyeTracking}\n physicalAttributes={{\n muscleMass: physicalAttributes.muscleMass,\n fatMass: physicalAttributes.fatMass,\n shoulderWidth: physicalAttributes.shoulderWidth,\n torsoLength: physicalAttributes.torsoLength,\n armLength: physicalAttributes.armLength,\n legLength: physicalAttributes.legLength,\n }}\n muscleStates={muscleStates}\n isExhausted={stamina < 20}\n archetype={archetype}\n />\n\n {/* Clothing is now rendered via BoneClothing inside BoneRenderer */}\n {/* This ensures clothing inherits bone transforms automatically */}\n\n {/* Blocking shield effect */}\n {isBlocking && (\n <mesh position={[0, 1.2, 0.3]}>\n <circleGeometry args={[0.5, 32]} />\n <meshBasicMaterial\n color={KOREAN_COLORS.PRIMARY_BLUE}\n transparent\n opacity={0.5}\n side={2}\n />\n </mesh>\n )}\n\n {/* Counter indicator */}\n {isCountering && (\n <mesh position={[0, 1.5, 0]}>\n <torusGeometry args={[0.4, 0.05, 8, 32]} />\n <meshBasicMaterial color={KOREAN_COLORS.ACCENT_PURPLE} />\n </mesh>\n )}\n\n {/* Player name overlay */}\n {showDetails && name && (\n <Html\n position={[0, 2.8, 0]}\n center\n distanceFactor={isMobile ? 15 : 10}\n occlude={false}\n style={{ pointerEvents: \"none\", userSelect: \"none\" }}\n >\n <div\n style={{\n fontFamily: FONT_FAMILY.KOREAN,\n textAlign: \"center\",\n color: \"white\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n }}\n >\n {/* Player name */}\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n fontWeight: \"bold\",\n marginBottom: \"4px\",\n }}\n data-testid=\"player-name\"\n >\n {name.korean}\n </div>\n\n {/* Trigram symbol */}\n {showStanceIndicator && (\n <div\n style={{\n fontSize: isMobile ? \"14px\" : \"16px\",\n color: toHexColor(stanceColor),\n }}\n data-testid=\"trigram-symbol\"\n >\n {trigramSymbol}\n </div>\n )}\n\n {/* Combat state text */}\n {(isBlocking || isStunned || isCountering) && (\n <div\n style={{\n fontSize: isMobile ? \"10px\" : \"12px\",\n fontWeight: \"bold\",\n color: \"#ffff00\",\n marginTop: \"4px\",\n }}\n data-testid=\"combat-state\"\n >\n {isBlocking ? \"방어\" : isStunned ? \"기절\" : \"반격\"}\n </div>\n )}\n </div>\n </Html>\n )}\n\n {/* State indicators (health, stamina, Ki, balance) */}\n {showDetails && (\n <PlayerStateIndicators\n health={health}\n maxHealth={maxHealth}\n stamina={stamina}\n ki={ki}\n balance={balance}\n consciousness={consciousness}\n pain={pain}\n bloodLoss={bloodLoss}\n isMobile={isMobile}\n />\n )}\n </group>{\" \"}\n {/* Close inner sway group */}\n </group>\n );\n};\n\nexport default SkeletalPlayer3D;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SkeletalPlayer3D.js","names":[],"sources":["../../../../../src/components/shared/three/models/SkeletalPlayer3D.tsx"],"sourcesContent":["/**\n * SkeletalPlayer3D component with articulated body model\n *\n * Implements full skeletal rigging system for realistic fighter animations\n * with independent limb movement, elbow/knee joints, and attack animations.\n *\n * @module components/three/SkeletalPlayer3D\n * @category 3D Components\n * @korean 골격플레이어3D컴포넌트\n */\n\nimport { Html } from \"@react-three/drei\";\nimport { useFrame } from \"@react-three/fiber\";\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport * as THREE from \"three\";\nimport { getArchetypePhysicalAttributes } from \"../../../../data/archetypePhysicalAttributes\";\nimport { useBalanceAnimations } from \"../../../../hooks/useBalanceAnimations\";\nimport { useHandPoseTransitions } from \"../../../../hooks/useHandPoseTransitions\";\nimport { useMuscleActivation } from \"../../../../hooks/useMuscleActivation\";\nimport { useSkeletalAnimation } from \"../../../../hooks/useSkeletalAnimation\";\nimport {\n createDefaultFacialDamage,\n createScaledHumanoidRig,\n getExpressionFromCombatState,\n getHeadAngleRadians,\n lockFacing,\n unlockFacing,\n updateFacingTowardOpponent,\n} from \"../../../../systems/animation\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"../../../../types/constants\";\nimport { FacialExpression } from \"../../../../types/facial\";\nimport type { Player3DUnifiedProps } from \"../../../../types/player-visual\";\nimport type { SkeletalRig } from \"../../../../types/skeletal\";\nimport { toHexColor } from \"../../../../utils/colorHelpers\";\nimport { getArchetypeSkinTone } from \"../../../../utils/colorUtils\";\nimport BoneRenderer from \"../anatomy/BoneRenderer\";\nimport PlayerStateIndicators from \"../effects/PlayerStateIndicators\";\n\n/**\n * Get stance-specific color from Korean theming\n *\n * @param stance - Current trigram stance\n * @returns Hex color number\n * @korean 자세색상가져오기\n */\nconst getStanceColor = (stance: string): number => {\n const stanceColors: Record<string, number> = {\n geon: KOREAN_COLORS.TRIGRAM_GEON_PRIMARY,\n tae: KOREAN_COLORS.TRIGRAM_TAE_PRIMARY,\n li: KOREAN_COLORS.TRIGRAM_LI_PRIMARY,\n jin: KOREAN_COLORS.TRIGRAM_JIN_PRIMARY,\n son: KOREAN_COLORS.TRIGRAM_SON_PRIMARY,\n gam: KOREAN_COLORS.TRIGRAM_GAM_PRIMARY,\n gan: KOREAN_COLORS.TRIGRAM_GAN_PRIMARY,\n gon: KOREAN_COLORS.TRIGRAM_GON_PRIMARY,\n };\n return stanceColors[stance] ?? KOREAN_COLORS.PRIMARY_CYAN;\n};\n\n/**\n * Get trigram symbol for stance\n *\n * @param stance - Current trigram stance\n * @returns Unicode trigram symbol\n * @korean 팔괘기호가져오기\n */\nconst getTrigramSymbol = (stance: string): string => {\n const symbols: Record<string, string> = {\n geon: \"☰\",\n tae: \"☱\",\n li: \"☲\",\n jin: \"☳\",\n son: \"☴\",\n gam: \"☵\",\n gan: \"☶\",\n gon: \"☷\",\n };\n return symbols[stance] ?? \"☰\";\n};\n\n/**\n * SkeletalPlayer3D Component\n *\n * Complete skeletal player with 28-bone rig and realistic animations.\n * Supports all Korean martial arts attack animations (jab, cross, kicks, block).\n *\n * @example\n * ```tsx\n * <SkeletalPlayer3D\n * playerId=\"player1\"\n * archetype={PlayerArchetype.MUSA}\n * stance={TrigramStance.GEON}\n * position={[0, 0, 0]}\n * rotation={0}\n * health={85}\n * maxHealth={100}\n * stamina={60}\n * ki={40}\n * currentAnimation=\"attack\"\n * attackAnimation=\"jab\"\n * showDetails={true}\n * />\n * ```\n *\n * @korean 골격플레이어3D컴포넌트\n */\nexport const SkeletalPlayer3D: React.FC<\n Player3DUnifiedProps & {\n readonly attackAnimation?: string;\n readonly showSkeleton?: boolean;\n }\n> = ({\n playerId,\n archetype,\n stance,\n position,\n rotation,\n health,\n maxHealth,\n stamina,\n ki,\n pain,\n balance,\n consciousness,\n bloodLoss,\n isBlocking,\n isStunned = false,\n isCountering = false,\n currentAnimation,\n isMobile,\n name,\n scale = 1,\n showDetails = true,\n facing = \"right\",\n showStanceIndicator = true,\n onAnimationComplete,\n attackAnimation,\n showSkeleton = false,\n facialExpression,\n facialDamage,\n enableFacialExpressions = false,\n enableEyeTracking = true,\n opponentPosition,\n bodyFacing,\n onBodyFacingUpdate,\n laterality, // Stance laterality (left/right foot forward)\n}) => {\n const effectiveLaterality = laterality ?? \"right\";\n const physicalAttributes = useMemo(\n () => getArchetypePhysicalAttributes(archetype),\n [archetype],\n );\n\n const rig = useMemo<SkeletalRig>(\n () => createScaledHumanoidRig(physicalAttributes),\n [physicalAttributes],\n );\n\n\n const { updateRigAnimation, diagonalRotationY } = useSkeletalAnimation({\n currentAnimation,\n attackAnimation,\n isBlocking,\n stance,\n laterality: effectiveLaterality, // Pass laterality for animation mirroring\n onAnimationComplete,\n });\n\n const { leftHandState, rightHandState, updateHandAnimations } =\n useHandPoseTransitions({\n currentAnimation,\n attackAnimation,\n isBlocking,\n });\n\n\n const { swayPosition, helplessRotation, updateBalanceAnimations } =\n useBalanceAnimations({\n balance,\n });\n\n const { muscleStates, updateMuscleActivations } = useMuscleActivation({\n currentAnimation,\n attackAnimation,\n isBlocking,\n stamina,\n });\n\n const skinTone = useMemo(() => getArchetypeSkinTone(archetype), [archetype]);\n\n const bodyColor = useMemo(() => {\n if (isStunned) return KOREAN_COLORS.WARNING_YELLOW;\n if (health / maxHealth < 0.3) return KOREAN_COLORS.ACCENT_RED;\n if (ki / 100 > 0.8) return KOREAN_COLORS.PRIMARY_CYAN;\n return skinTone; // Use archetype skin tone instead of primary color\n }, [isStunned, health, maxHealth, ki, skinTone]);\n\n const stanceColor = useMemo(() => getStanceColor(stance), [stance]);\n const trigramSymbol = useMemo(() => getTrigramSymbol(stance), [stance]);\n\n const [justHit, setJustHit] = useState(false);\n const [justLanded, setJustLanded] = useState(false);\n const lastHealthRef = useRef(health);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (health < lastHealthRef.current) {\n setJustHit(true);\n timeoutId = setTimeout(() => setJustHit(false), 1000); // Clear after 1 second\n }\n\n lastHealthRef.current = health;\n\n return () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [health]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (currentAnimation === \"attack\") {\n setJustLanded(true);\n timeoutId = setTimeout(() => setJustLanded(false), 500); // Clear after 0.5 seconds\n }\n\n return () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [currentAnimation]);\n\n const calculatedExpression = useMemo(() => {\n if (!enableFacialExpressions) {\n return FacialExpression.NEUTRAL;\n }\n\n if (facialExpression) {\n return facialExpression;\n }\n\n return getExpressionFromCombatState(\n health,\n maxHealth,\n stamina,\n pain,\n consciousness,\n justHit,\n justLanded,\n );\n }, [\n enableFacialExpressions,\n facialExpression,\n health,\n maxHealth,\n stamina,\n pain,\n consciousness,\n justHit,\n justLanded,\n ]);\n\n const calculatedFacialDamage = useMemo(() => {\n return facialDamage ?? createDefaultFacialDamage();\n }, [facialDamage]);\n\n const opponentPos = useMemo(() => {\n if (opponentPosition) {\n return new THREE.Vector3(...opponentPosition);\n }\n return new THREE.Vector3(facing === \"right\" ? 5 : -5, 2, 0);\n }, [opponentPosition, facing]);\n\n\n const frameCounter = useRef(0);\n\n useFrame((_state, delta) => {\n const isWalkingAnimation =\n currentAnimation === \"walk\" ||\n (typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"step_\"));\n\n if (\n bodyFacing &&\n opponentPosition &&\n onBodyFacingUpdate &&\n !isWalkingAnimation\n ) {\n const playerPos = { x: position[0], y: position[2] }; // X and Z for 2D top-down\n const opponentPos = { x: opponentPosition[0], y: opponentPosition[2] };\n\n const isStepAnimation =\n typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"step_\");\n const isTurnAnimation =\n typeof currentAnimation === \"string\" &&\n currentAnimation.startsWith(\"turn_\");\n\n const shouldLock =\n currentAnimation === \"attack\" ||\n currentAnimation === \"defend\" ||\n isStepAnimation ||\n isTurnAnimation;\n\n let updatedFacing = bodyFacing;\n\n if (shouldLock && !bodyFacing.isLocked) {\n updatedFacing = lockFacing(bodyFacing);\n } else if (!shouldLock && bodyFacing.isLocked) {\n updatedFacing = unlockFacing(bodyFacing);\n }\n\n if (!updatedFacing.isLocked) {\n updatedFacing = updateFacingTowardOpponent(\n updatedFacing,\n playerPos,\n opponentPos,\n delta,\n Date.now(),\n );\n }\n\n if (updatedFacing !== bodyFacing) {\n onBodyFacingUpdate(updatedFacing);\n }\n }\n\n\n frameCounter.current = (frameCounter.current + 1) % 10;\n\n updateRigAnimation(rig, delta);\n\n updateHandAnimations(delta);\n\n updateBalanceAnimations(delta, frameCounter.current);\n\n updateMuscleActivations(delta, frameCounter.current);\n\n if (bodyFacing) {\n const head = rig.bones.get(\"head\");\n if (head) {\n const headRotation = getHeadAngleRadians(bodyFacing);\n head.rotation.y = headRotation;\n }\n }\n });\n\n const effectiveRotation = diagonalRotationY ?? rotation;\n\n return (\n <group\n position={position}\n rotation={[0, effectiveRotation, 0]}\n scale={[facing === \"left\" ? -scale : scale, scale, scale]}\n name={`skeletal-player3d-${playerId}`}\n >\n {/* Inner group for sway animation and helpless lean */}\n <group position={swayPosition} rotation={[helplessRotation, 0, 0]}>\n {/* Skeletal rig rendering with bone-attached muscles */}\n <BoneRenderer\n rig={rig}\n color={bodyColor}\n showBones={true}\n renderMode={showSkeleton ? \"debug\" : \"solid\"}\n leftHandState={leftHandState}\n rightHandState={rightHandState}\n cameraDistance={10}\n facialExpression={calculatedExpression}\n facialDamage={calculatedFacialDamage}\n opponentPosition={opponentPos}\n enableFacialExpressions={enableFacialExpressions}\n enableEyeTracking={enableEyeTracking}\n physicalAttributes={{\n muscleMass: physicalAttributes.muscleMass,\n fatMass: physicalAttributes.fatMass,\n shoulderWidth: physicalAttributes.shoulderWidth,\n torsoLength: physicalAttributes.torsoLength,\n armLength: physicalAttributes.armLength,\n legLength: physicalAttributes.legLength,\n }}\n muscleStates={muscleStates}\n isExhausted={stamina < 20}\n archetype={archetype}\n />\n\n {/* Clothing is now rendered via BoneClothing inside BoneRenderer */}\n {/* This ensures clothing inherits bone transforms automatically */}\n\n {/* Blocking shield effect */}\n {isBlocking && (\n <mesh position={[0, 1.2, 0.3]}>\n <circleGeometry args={[0.5, 32]} />\n <meshBasicMaterial\n color={KOREAN_COLORS.PRIMARY_BLUE}\n transparent\n opacity={0.5}\n side={2}\n />\n </mesh>\n )}\n\n {/* Counter indicator */}\n {isCountering && (\n <mesh position={[0, 1.5, 0]}>\n <torusGeometry args={[0.4, 0.05, 8, 32]} />\n <meshBasicMaterial color={KOREAN_COLORS.ACCENT_PURPLE} />\n </mesh>\n )}\n\n {/* Player name overlay */}\n {showDetails && name && (\n <Html\n position={[0, 2.8, 0]}\n center\n distanceFactor={isMobile ? 15 : 10}\n occlude={false}\n style={{ pointerEvents: \"none\", userSelect: \"none\" }}\n >\n <div\n style={{\n fontFamily: FONT_FAMILY.KOREAN,\n textAlign: \"center\",\n color: \"white\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n }}\n >\n {/* Player name */}\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n fontWeight: \"bold\",\n marginBottom: \"4px\",\n }}\n data-testid=\"player-name\"\n >\n {name.korean}\n </div>\n\n {/* Trigram symbol */}\n {showStanceIndicator && (\n <div\n style={{\n fontSize: isMobile ? \"14px\" : \"16px\",\n color: toHexColor(stanceColor),\n }}\n data-testid=\"trigram-symbol\"\n >\n {trigramSymbol}\n </div>\n )}\n\n {/* Combat state text */}\n {(isBlocking || isStunned || isCountering) && (\n <div\n style={{\n fontSize: isMobile ? \"10px\" : \"12px\",\n fontWeight: \"bold\",\n color: \"#ffff00\",\n marginTop: \"4px\",\n }}\n data-testid=\"combat-state\"\n >\n {isBlocking ? \"방어\" : isStunned ? \"기절\" : \"반격\"}\n </div>\n )}\n </div>\n </Html>\n )}\n\n {/* State indicators (health, stamina, Ki, balance) */}\n {showDetails && (\n <PlayerStateIndicators\n health={health}\n maxHealth={maxHealth}\n stamina={stamina}\n ki={ki}\n balance={balance}\n consciousness={consciousness}\n pain={pain}\n bloodLoss={bloodLoss}\n isMobile={isMobile}\n />\n )}\n </group>{\" \"}\n {/* Close inner sway group */}\n </group>\n );\n};\n\nexport default SkeletalPlayer3D;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdaptiveQuality.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/AdaptiveQuality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,yCAAyC;IACzC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,uCAAuC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAYD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,eAAe,CAsBxD,CAAC;AAEX;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;gBAE3C,UAAU,GAAE,OAAO,CAAC,yBAAyB,CAAM;IAI/D;;;OAGG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"AdaptiveQuality.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/AdaptiveQuality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,yCAAyC;IACzC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,uCAAuC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAYD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,eAAe,CAsBxD,CAAC;AAEX;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;gBAE3C,UAAU,GAAE,OAAO,CAAC,yBAAyB,CAAM;IAI/D;;;OAGG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IA0D/C;;OAEG;IACH,iBAAiB,IAAI,YAAY;IAIjC;;OAEG;IACH,kBAAkB,IAAI,eAAe;IAIrC;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAMvC;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,OAAc,EACvB,QAAQ,GAAE,OAAe,EACzB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAChD,eAAe,CA4DjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdaptiveQuality.js","names":[],"sources":["../../../../../src/components/shared/three/optimization/AdaptiveQuality.ts"],"sourcesContent":["/**\n * AdaptiveQuality - Dynamic quality adjustment system for mobile performance\n *\n * Monitors real-time FPS and automatically adjusts rendering quality to maintain\n * 55fps target on mobile devices. Provides quality presets and smooth transitions.\n *\n * Features:\n * - Real-time FPS monitoring\n * - Automatic quality adjustment (high/medium/low)\n * - Debounced quality changes to prevent thrashing\n * - Mobile-optimized thresholds\n * - React hook integration\n *\n * @module components/shared/three/optimization/AdaptiveQuality\n * @category Performance Optimization\n * @korean 적응형품질시스템\n */\n\nimport { useFrame } from \"@react-three/fiber\";\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Quality levels for adaptive rendering\n */\nexport type QualityLevel = \"high\" | \"medium\" | \"low\";\n\n/**\n * Quality settings for each level\n */\nexport interface QualitySettings {\n readonly level: QualityLevel;\n readonly shadowMapSize: number;\n readonly maxParticles: number;\n readonly postProcessing: boolean;\n readonly effectsQuality: number; // 0.0-1.0 multiplier\n}\n\n/**\n * FPS thresholds for quality adjustment\n */\nexport interface AdaptiveQualityThresholds {\n /** FPS threshold to downgrade quality */\n readonly downgradeThreshold: number;\n /** FPS threshold to upgrade quality */\n readonly upgradeThreshold: number;\n /** Minimum time between quality changes (ms) */\n readonly debounceTime: number;\n /** Number of frames to average for stability */\n readonly sampleSize: number;\n}\n\n/**\n * Default thresholds for mobile optimization\n */\nconst DEFAULT_MOBILE_THRESHOLDS: AdaptiveQualityThresholds = {\n downgradeThreshold: 45, // Downgrade if fps drops below 45\n upgradeThreshold: 58, // Upgrade if fps consistently above 58\n debounceTime: 2000, // 2 seconds between changes\n sampleSize: 60, // Average over 60 frames (~1 second at 60fps)\n};\n\n/**\n * Quality presets optimized for mobile performance\n */\nexport const QUALITY_PRESETS: Record<QualityLevel, QualitySettings> = {\n high: {\n level: \"high\",\n shadowMapSize: 1536,\n maxParticles: 60,\n postProcessing: false, // Keep disabled on mobile\n effectsQuality: 1.0,\n },\n medium: {\n level: \"medium\",\n shadowMapSize: 1024,\n maxParticles: 40,\n postProcessing: false,\n effectsQuality: 0.75,\n },\n low: {\n level: \"low\",\n shadowMapSize: 512,\n maxParticles: 20,\n postProcessing: false,\n effectsQuality: 0.5,\n },\n} as const;\n\n/**\n * Adaptive quality system class\n */\nexport class AdaptiveQualitySystem {\n private currentQuality: QualityLevel = \"high\";\n private fpsHistory: number[] = [];\n private lastQualityChange = 0;\n private readonly thresholds: AdaptiveQualityThresholds;\n\n constructor(thresholds: Partial<AdaptiveQualityThresholds> = {}) {\n this.thresholds = { ...DEFAULT_MOBILE_THRESHOLDS, ...thresholds };\n }\n\n /**\n * Update system with current FPS\n * Returns new quality level if changed, null otherwise\n */\n update(currentFps: number): QualityLevel | null {\n const now = performance.now();\n\n // Add to history\n this.fpsHistory.push(currentFps);\n if (this.fpsHistory.length > this.thresholds.sampleSize) {\n this.fpsHistory.shift();\n }\n\n // Need enough samples before adjusting\n if (this.fpsHistory.length < this.thresholds.sampleSize) {\n return null;\n }\n\n // Check debounce time\n if (now - this.lastQualityChange < this.thresholds.debounceTime) {\n return null;\n }\n\n // Calculate average FPS\n const avgFps =\n this.fpsHistory.reduce((a, b) => a + b, 0) / this.fpsHistory.length;\n\n // Determine if quality should change\n let newQuality: QualityLevel | null = null;\n\n if (\n avgFps < this.thresholds.downgradeThreshold &&\n this.currentQuality !== \"low\"\n ) {\n // Downgrade quality\n if (this.currentQuality === \"high\") {\n newQuality = \"medium\";\n } else if (this.currentQuality === \"medium\") {\n newQuality = \"low\";\n }\n } else if (\n avgFps > this.thresholds.upgradeThreshold &&\n this.currentQuality !== \"high\"\n ) {\n // Upgrade quality\n if (this.currentQuality === \"low\") {\n newQuality = \"medium\";\n } else if (this.currentQuality === \"medium\") {\n newQuality = \"high\";\n }\n }\n\n if (newQuality !== null) {\n this.currentQuality = newQuality;\n this.lastQualityChange = now;\n this.fpsHistory = []; // Reset history after change\n\n if (import.meta.env.DEV) {\n console.log(\n `[AdaptiveQuality] Quality changed to ${newQuality} (avg fps: ${avgFps.toFixed(1)})`,\n );\n }\n\n return newQuality;\n }\n\n return null;\n }\n\n /**\n * Get current quality level\n */\n getCurrentQuality(): QualityLevel {\n return this.currentQuality;\n }\n\n /**\n * Get settings for current quality level\n */\n getCurrentSettings(): QualitySettings {\n return QUALITY_PRESETS[this.currentQuality];\n }\n\n /**\n * Manually set quality level\n */\n setQuality(quality: QualityLevel): void {\n this.currentQuality = quality;\n this.lastQualityChange = performance.now();\n this.fpsHistory = [];\n }\n\n /**\n * Reset the system\n */\n reset(): void {\n this.fpsHistory = [];\n this.lastQualityChange = 0;\n }\n}\n\n/**\n * React hook for adaptive quality management\n *\n * Automatically monitors FPS and adjusts quality settings.\n * Returns current quality level and settings.\n *\n * @param enabled - Whether adaptive quality is enabled\n * @param isMobile - Whether device is mobile (stricter thresholds)\n * @param onQualityChange - Callback when quality level changes\n * @returns Current quality settings\n *\n * @example\n * ```tsx\n * function CombatScene({ isMobile }) {\n * const quality = useAdaptiveQuality(true, isMobile, (level) => {\n * console.log(`Quality changed to ${level}`);\n * });\n *\n * return (\n * <Canvas shadowMap={{ size: quality.shadowMapSize }}>\n * <ParticleSystem maxParticles={quality.maxParticles} />\n * </Canvas>\n * );\n * }\n * ```\n */\nexport function useAdaptiveQuality(\n enabled: boolean = true,\n isMobile: boolean = false,\n onQualityChange?: (quality: QualityLevel) => void,\n): QualitySettings {\n // Initialize with appropriate starting quality\n const initialQuality: QualityLevel = isMobile ? \"medium\" : \"high\";\n\n const [currentQuality, setCurrentQuality] =\n useState<QualityLevel>(initialQuality);\n\n // Create system instance\n const systemRef = useRef<AdaptiveQualitySystem | null>(null);\n\n useEffect(() => {\n // Create system with mobile-optimized thresholds\n const thresholds = isMobile\n ? {\n downgradeThreshold: 45, // More aggressive on mobile\n upgradeThreshold: 58,\n debounceTime: 2000,\n sampleSize: 60,\n }\n : {\n downgradeThreshold: 50,\n upgradeThreshold: 59,\n debounceTime: 3000,\n sampleSize: 90,\n };\n\n systemRef.current = new AdaptiveQualitySystem(thresholds);\n systemRef.current.setQuality(initialQuality);\n }, [isMobile, initialQuality]);\n\n // FPS tracking - Initialize with 0, will be set on first frame\n const lastTimeRef = useRef(0);\n const frameCountRef = useRef(0);\n const initializedRef = useRef(false);\n\n useFrame(() => {\n if (!enabled || !systemRef.current) return;\n\n // Calculate FPS\n const now = performance.now();\n\n // Initialize on first frame\n if (!initializedRef.current) {\n lastTimeRef.current = now;\n initializedRef.current = true;\n return;\n }\n\n const delta = now - lastTimeRef.current;\n\n if (delta > 0) {\n const fps = 1000 / delta;\n frameCountRef.current++;\n\n // Update every frame for smooth monitoring\n const newQuality = systemRef.current.update(fps);\n\n if (newQuality !== null) {\n setCurrentQuality(newQuality);\n onQualityChange?.(newQuality);\n }\n }\n\n lastTimeRef.current = now;\n });\n\n return QUALITY_PRESETS[currentQuality];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdaptiveQuality.js","names":[],"sources":["../../../../../src/components/shared/three/optimization/AdaptiveQuality.ts"],"sourcesContent":["/**\n * AdaptiveQuality - Dynamic quality adjustment system for mobile performance\n *\n * Monitors real-time FPS and automatically adjusts rendering quality to maintain\n * 55fps target on mobile devices. Provides quality presets and smooth transitions.\n *\n * Features:\n * - Real-time FPS monitoring\n * - Automatic quality adjustment (high/medium/low)\n * - Debounced quality changes to prevent thrashing\n * - Mobile-optimized thresholds\n * - React hook integration\n *\n * @module components/shared/three/optimization/AdaptiveQuality\n * @category Performance Optimization\n * @korean 적응형품질시스템\n */\n\nimport { useFrame } from \"@react-three/fiber\";\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Quality levels for adaptive rendering\n */\nexport type QualityLevel = \"high\" | \"medium\" | \"low\";\n\n/**\n * Quality settings for each level\n */\nexport interface QualitySettings {\n readonly level: QualityLevel;\n readonly shadowMapSize: number;\n readonly maxParticles: number;\n readonly postProcessing: boolean;\n readonly effectsQuality: number; // 0.0-1.0 multiplier\n}\n\n/**\n * FPS thresholds for quality adjustment\n */\nexport interface AdaptiveQualityThresholds {\n /** FPS threshold to downgrade quality */\n readonly downgradeThreshold: number;\n /** FPS threshold to upgrade quality */\n readonly upgradeThreshold: number;\n /** Minimum time between quality changes (ms) */\n readonly debounceTime: number;\n /** Number of frames to average for stability */\n readonly sampleSize: number;\n}\n\n/**\n * Default thresholds for mobile optimization\n */\nconst DEFAULT_MOBILE_THRESHOLDS: AdaptiveQualityThresholds = {\n downgradeThreshold: 45, // Downgrade if fps drops below 45\n upgradeThreshold: 58, // Upgrade if fps consistently above 58\n debounceTime: 2000, // 2 seconds between changes\n sampleSize: 60, // Average over 60 frames (~1 second at 60fps)\n};\n\n/**\n * Quality presets optimized for mobile performance\n */\nexport const QUALITY_PRESETS: Record<QualityLevel, QualitySettings> = {\n high: {\n level: \"high\",\n shadowMapSize: 1536,\n maxParticles: 60,\n postProcessing: false, // Keep disabled on mobile\n effectsQuality: 1.0,\n },\n medium: {\n level: \"medium\",\n shadowMapSize: 1024,\n maxParticles: 40,\n postProcessing: false,\n effectsQuality: 0.75,\n },\n low: {\n level: \"low\",\n shadowMapSize: 512,\n maxParticles: 20,\n postProcessing: false,\n effectsQuality: 0.5,\n },\n} as const;\n\n/**\n * Adaptive quality system class\n */\nexport class AdaptiveQualitySystem {\n private currentQuality: QualityLevel = \"high\";\n private fpsHistory: number[] = [];\n private lastQualityChange = 0;\n private readonly thresholds: AdaptiveQualityThresholds;\n\n constructor(thresholds: Partial<AdaptiveQualityThresholds> = {}) {\n this.thresholds = { ...DEFAULT_MOBILE_THRESHOLDS, ...thresholds };\n }\n\n /**\n * Update system with current FPS\n * Returns new quality level if changed, null otherwise\n */\n update(currentFps: number): QualityLevel | null {\n const now = performance.now();\n\n this.fpsHistory.push(currentFps);\n if (this.fpsHistory.length > this.thresholds.sampleSize) {\n this.fpsHistory.shift();\n }\n\n if (this.fpsHistory.length < this.thresholds.sampleSize) {\n return null;\n }\n\n if (now - this.lastQualityChange < this.thresholds.debounceTime) {\n return null;\n }\n\n const avgFps =\n this.fpsHistory.reduce((a, b) => a + b, 0) / this.fpsHistory.length;\n\n let newQuality: QualityLevel | null = null;\n\n if (\n avgFps < this.thresholds.downgradeThreshold &&\n this.currentQuality !== \"low\"\n ) {\n if (this.currentQuality === \"high\") {\n newQuality = \"medium\";\n } else if (this.currentQuality === \"medium\") {\n newQuality = \"low\";\n }\n } else if (\n avgFps > this.thresholds.upgradeThreshold &&\n this.currentQuality !== \"high\"\n ) {\n if (this.currentQuality === \"low\") {\n newQuality = \"medium\";\n } else if (this.currentQuality === \"medium\") {\n newQuality = \"high\";\n }\n }\n\n if (newQuality !== null) {\n this.currentQuality = newQuality;\n this.lastQualityChange = now;\n this.fpsHistory = []; // Reset history after change\n\n if (import.meta.env.DEV) {\n console.log(\n `[AdaptiveQuality] Quality changed to ${newQuality} (avg fps: ${avgFps.toFixed(1)})`,\n );\n }\n\n return newQuality;\n }\n\n return null;\n }\n\n /**\n * Get current quality level\n */\n getCurrentQuality(): QualityLevel {\n return this.currentQuality;\n }\n\n /**\n * Get settings for current quality level\n */\n getCurrentSettings(): QualitySettings {\n return QUALITY_PRESETS[this.currentQuality];\n }\n\n /**\n * Manually set quality level\n */\n setQuality(quality: QualityLevel): void {\n this.currentQuality = quality;\n this.lastQualityChange = performance.now();\n this.fpsHistory = [];\n }\n\n /**\n * Reset the system\n */\n reset(): void {\n this.fpsHistory = [];\n this.lastQualityChange = 0;\n }\n}\n\n/**\n * React hook for adaptive quality management\n *\n * Automatically monitors FPS and adjusts quality settings.\n * Returns current quality level and settings.\n *\n * @param enabled - Whether adaptive quality is enabled\n * @param isMobile - Whether device is mobile (stricter thresholds)\n * @param onQualityChange - Callback when quality level changes\n * @returns Current quality settings\n *\n * @example\n * ```tsx\n * function CombatScene({ isMobile }) {\n * const quality = useAdaptiveQuality(true, isMobile, (level) => {\n * console.log(`Quality changed to ${level}`);\n * });\n *\n * return (\n * <Canvas shadowMap={{ size: quality.shadowMapSize }}>\n * <ParticleSystem maxParticles={quality.maxParticles} />\n * </Canvas>\n * );\n * }\n * ```\n */\nexport function useAdaptiveQuality(\n enabled: boolean = true,\n isMobile: boolean = false,\n onQualityChange?: (quality: QualityLevel) => void,\n): QualitySettings {\n const initialQuality: QualityLevel = isMobile ? \"medium\" : \"high\";\n\n const [currentQuality, setCurrentQuality] =\n useState<QualityLevel>(initialQuality);\n\n const systemRef = useRef<AdaptiveQualitySystem | null>(null);\n\n useEffect(() => {\n const thresholds = isMobile\n ? {\n downgradeThreshold: 45, // More aggressive on mobile\n upgradeThreshold: 58,\n debounceTime: 2000,\n sampleSize: 60,\n }\n : {\n downgradeThreshold: 50,\n upgradeThreshold: 59,\n debounceTime: 3000,\n sampleSize: 90,\n };\n\n systemRef.current = new AdaptiveQualitySystem(thresholds);\n systemRef.current.setQuality(initialQuality);\n }, [isMobile, initialQuality]);\n\n const lastTimeRef = useRef(0);\n const frameCountRef = useRef(0);\n const initializedRef = useRef(false);\n\n useFrame(() => {\n if (!enabled || !systemRef.current) return;\n\n const now = performance.now();\n\n if (!initializedRef.current) {\n lastTimeRef.current = now;\n initializedRef.current = true;\n return;\n }\n\n const delta = now - lastTimeRef.current;\n\n if (delta > 0) {\n const fps = 1000 / delta;\n frameCountRef.current++;\n\n const newQuality = systemRef.current.update(fps);\n\n if (newQuality !== null) {\n setCurrentQuality(newQuality);\n onQualityChange?.(newQuality);\n }\n }\n\n lastTimeRef.current = now;\n });\n\n return QUALITY_PRESETS[currentQuality];\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstancedGeometry.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/InstancedGeometry.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,6BAA6B;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,oBAAoB;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC;IAC3C,0BAA0B;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;CACrE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAsBhE,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,0BAA0B;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC;IAC3C,0BAA0B;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;CACxE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAqB5D,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC1E,iCAAiC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,CAAC,mBAAmB,EAAE,CAAC;IACvD,oBAAoB;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC7C,0BAA0B;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,
|
|
1
|
+
{"version":3,"file":"InstancedGeometry.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/InstancedGeometry.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LODSystem.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/LODSystem.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAEzB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"LODSystem.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/optimization/LODSystem.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAEzB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,YAGlC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IACrC,qDAAqD;IACrD,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,sCAAsC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuBpD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,CACjB,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,KACnC,KAAK,CAAC,SAAS,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAiB9C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,YAAY,CASd;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GACrC,MAAM,CAWR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GACrC,MAAM,CAWR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AtmosphericParticles3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/scene/AtmosphericParticles3D.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"AtmosphericParticles3D.d.ts","sourceRoot":"","sources":["../../../../../src/components/shared/three/scene/AtmosphericParticles3D.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AA6BD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAC3C,2BAA2B,CAmD5B,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AtmosphericParticles3D.js","names":[],"sources":["../../../../../src/components/shared/three/scene/AtmosphericParticles3D.tsx"],"sourcesContent":["/**\n * AtmosphericParticles3D - Three.js 3D atmospheric particle effects\n *\n * Renders rain/mist particles for environmental depth in the combat arena\n * Creates an immersive cyberpunk urban night atmosphere\n */\n\nimport { useFrame } from \"@react-three/fiber\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport * as THREE from \"three\";\n\n/**\n * Props for the AtmosphericParticles3D component.\n */\nexport interface AtmosphericParticles3DProps {\n /** Number of particles to render. Defaults to 500 */\n readonly count?: number;\n /** Scale factor for particle spread (1.0 = desktop, <1.0 = mobile). Defaults to 1.0 */\n readonly scale?: number;\n /** Particle fall speed. Defaults to 2 */\n readonly speed?: number;\n}\n\n/**\n * Generate particle positions using a deterministic pattern\n * This avoids Math.random() in render functions for React purity\n */\nfunction generateParticlePositions(\n count: number,\n spreadX: number,\n spreadY: number,\n spreadZ: number\n): Float32Array {\n const pos = new Float32Array(count * 3);\n\n
|
|
1
|
+
{"version":3,"file":"AtmosphericParticles3D.js","names":[],"sources":["../../../../../src/components/shared/three/scene/AtmosphericParticles3D.tsx"],"sourcesContent":["/**\n * AtmosphericParticles3D - Three.js 3D atmospheric particle effects\n *\n * Renders rain/mist particles for environmental depth in the combat arena\n * Creates an immersive cyberpunk urban night atmosphere\n */\n\nimport { useFrame } from \"@react-three/fiber\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport * as THREE from \"three\";\n\n/**\n * Props for the AtmosphericParticles3D component.\n */\nexport interface AtmosphericParticles3DProps {\n /** Number of particles to render. Defaults to 500 */\n readonly count?: number;\n /** Scale factor for particle spread (1.0 = desktop, <1.0 = mobile). Defaults to 1.0 */\n readonly scale?: number;\n /** Particle fall speed. Defaults to 2 */\n readonly speed?: number;\n}\n\n/**\n * Generate particle positions using a deterministic pattern\n * This avoids Math.random() in render functions for React purity\n */\nfunction generateParticlePositions(\n count: number,\n spreadX: number,\n spreadY: number,\n spreadZ: number\n): Float32Array {\n const pos = new Float32Array(count * 3);\n\n for (let i = 0; i < count; i++) {\n const t = i / count; // Normalized index [0, 1]\n\n const offsetX = Math.sin(t * 123.456) * Math.cos(t * 789.012);\n const offsetY = Math.sin(t * 234.567) * Math.cos(t * 890.123);\n const offsetZ = Math.sin(t * 345.678) * Math.cos(t * 901.234);\n\n pos[i * 3] = offsetX * spreadX * 0.5;\n pos[i * 3 + 1] = offsetY * spreadY * 0.5 + spreadY * 0.5; // Bias upward\n pos[i * 3 + 2] = offsetZ * spreadZ * 0.5;\n }\n\n return pos;\n}\n\n/**\n * AtmosphericParticles3D Component\n * Creates rain/mist particle effects for atmospheric depth\n *\n * Performance optimized with:\n * - BufferGeometry for efficient rendering\n * - Additive blending for transparent particles\n * - Configurable particle count for mobile optimization\n * - Deterministic position generation (no Math.random in render)\n */\nexport const AtmosphericParticles3D: React.FC<\n AtmosphericParticles3DProps\n> = ({ count = 500, scale = 1.0, speed = 2 }) => {\n const particlesRef = useRef<THREE.Points>(null);\n const [geometry] = useState(() => new THREE.BufferGeometry());\n\n const spreadX = 40 * scale;\n const spreadY = 20;\n const spreadZ = 40 * scale;\n\n useEffect(() => {\n const positions = generateParticlePositions(\n count,\n spreadX,\n spreadY,\n spreadZ\n );\n \n geometry.setAttribute(\"position\", new THREE.BufferAttribute(positions, 3));\n\n return () => {\n geometry.dispose();\n };\n }, [count, spreadX, spreadY, spreadZ, geometry]);\n\n useFrame((_state, delta) => {\n if (!particlesRef.current) return;\n\n const positions =\n particlesRef.current.geometry.attributes.position.array as Float32Array;\n for (let i = 0; i < count; i++) {\n positions[i * 3 + 1] -= delta * speed; // Fall down\n if (positions[i * 3 + 1] < 0) {\n positions[i * 3 + 1] = spreadY; // Reset to top\n }\n }\n particlesRef.current.geometry.attributes.position.needsUpdate = true;\n });\n\n return (\n <points ref={particlesRef} geometry={geometry}>\n <pointsMaterial\n size={0.05}\n color={0xffffff}\n transparent\n opacity={0.3}\n sizeAttenuation\n blending={THREE.AdditiveBlending}\n depthWrite={false}\n />\n </points>\n );\n};\n\nexport default AtmosphericParticles3D;\n"],"mappings":";;;;;;;;;;;;;;;AA2BA,SAAS,0BACP,OACA,SACA,SACA,SACc;CACd,MAAM,MAAM,IAAI,aAAa,QAAQ,EAAE;CAEvC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;EAC9B,MAAM,IAAI,IAAI;EAEd,MAAM,UAAU,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,IAAI,IAAI,QAAQ;EAC7D,MAAM,UAAU,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,IAAI,IAAI,QAAQ;EAC7D,MAAM,UAAU,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,IAAI,IAAI,QAAQ;EAE7D,IAAI,IAAI,KAAK,UAAU,UAAU;EACjC,IAAI,IAAI,IAAI,KAAK,UAAU,UAAU,KAAM,UAAU;EACrD,IAAI,IAAI,IAAI,KAAK,UAAU,UAAU;;CAGvC,OAAO;;;;;;;;;;;;AAaT,IAAa,0BAER,EAAE,QAAQ,KAAK,QAAQ,GAAK,QAAQ,QAAQ;CAC/C,MAAM,eAAe,OAAqB,KAAK;CAC/C,MAAM,CAAC,YAAY,eAAe,IAAI,MAAM,gBAAgB,CAAC;CAE7D,MAAM,UAAU,KAAK;CACrB,MAAM,UAAU;CAChB,MAAM,UAAU,KAAK;CAErB,gBAAgB;EACd,MAAM,YAAY,0BAChB,OACA,SACA,SACA,QACD;EAED,SAAS,aAAa,YAAY,IAAI,MAAM,gBAAgB,WAAW,EAAE,CAAC;EAE1E,aAAa;GACX,SAAS,SAAS;;IAEnB;EAAC;EAAO;EAAS;EAAS;EAAS;EAAS,CAAC;CAEhD,UAAU,QAAQ,UAAU;EAC1B,IAAI,CAAC,aAAa,SAAS;EAE3B,MAAM,YACJ,aAAa,QAAQ,SAAS,WAAW,SAAS;EACpD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC9B,UAAU,IAAI,IAAI,MAAM,QAAQ;GAChC,IAAI,UAAU,IAAI,IAAI,KAAK,GACzB,UAAU,IAAI,IAAI,KAAK;;EAG3B,aAAa,QAAQ,SAAS,WAAW,SAAS,cAAc;GAChE;CAEF,OACE,oBAAC,UAAD;EAAQ,KAAK;EAAwB;YACnC,oBAAC,kBAAD;GACE,MAAM;GACN,OAAO;GACP,aAAA;GACA,SAAS;GACT,iBAAA;GACA,UAAU,MAAM;GAChB,YAAY;GACZ,CAAA;EACK,CAAA"}
|