From 87ee749801a01de5ae6a327bedcb5533150191b2 Mon Sep 17 00:00:00 2001 From: Areloch Date: Thu, 7 Mar 2019 16:23:41 -0600 Subject: [PATCH] (Mostly) updated verve implementation. --- Engine/modules/Verve/Core/ITreeNode.h | 76 + .../Verve/Core/Persistence/VPersistence.cpp | 137 + .../Verve/Core/Persistence/VPersistence.h | 286 ++ .../modules/Verve/Core/Util/VSharedEnum.cpp | 31 + Engine/modules/Verve/Core/Util/VSharedEnum.h | 49 + Engine/modules/Verve/Core/VController.cpp | 1160 ++++++ Engine/modules/Verve/Core/VController.h | 246 ++ Engine/modules/Verve/Core/VDataTable.cpp | 254 ++ Engine/modules/Verve/Core/VDataTable.h | 118 + Engine/modules/Verve/Core/VEvent.cpp | 406 ++ Engine/modules/Verve/Core/VEvent.h | 109 + Engine/modules/Verve/Core/VGroup.cpp | 32 + Engine/modules/Verve/Core/VGroup.h | 47 + Engine/modules/Verve/Core/VObject.cpp | 483 +++ Engine/modules/Verve/Core/VObject.h | 126 + Engine/modules/Verve/Core/VTrack.cpp | 448 +++ Engine/modules/Verve/Core/VTrack.h | 123 + Engine/modules/Verve/Core/VTreeNode.cpp | 471 +++ Engine/modules/Verve/Core/VTreeNode.h | 73 + .../Animation/VShapeAnimationEvent.cpp | 154 + .../Animation/VShapeAnimationEvent.h | 69 + .../Animation/VShapeAnimationTrack.cpp | 185 + .../Animation/VShapeAnimationTrack.h | 64 + .../Verve/Extension/Camera/VCameraGroup.cpp | 224 ++ .../Verve/Extension/Camera/VCameraGroup.h | 97 + .../Extension/Camera/VCameraShakeEvent.cpp | 83 + .../Extension/Camera/VCameraShakeEvent.h | 59 + .../Extension/Camera/VCameraShakeTrack.cpp | 114 + .../Extension/Camera/VCameraShakeTrack.h | 55 + .../Verve/Extension/Camera/VCameraTrack.cpp | 108 + .../Verve/Extension/Camera/VCameraTrack.h | 60 + .../Extension/Director/VDirectorEvent.cpp | 75 + .../Verve/Extension/Director/VDirectorEvent.h | 61 + .../Extension/Director/VDirectorGroup.cpp | 57 + .../Verve/Extension/Director/VDirectorGroup.h | 59 + .../Extension/Director/VDirectorTrack.cpp | 63 + .../Verve/Extension/Director/VDirectorTrack.h | 47 + .../Extension/Director/VSceneJumpEvent.cpp | 82 + .../Extension/Director/VSceneJumpEvent.h | 57 + .../Extension/Director/VSceneJumpTrack.cpp | 32 + .../Extension/Director/VSceneJumpTrack.h | 47 + .../Verve/Extension/Director/VSlowMoEvent.cpp | 130 + .../Verve/Extension/Director/VSlowMoEvent.h | 60 + .../Verve/Extension/Director/VSlowMoTrack.cpp | 93 + .../Verve/Extension/Director/VSlowMoTrack.h | 52 + .../Verve/Extension/GUI/VFadeEvent.cpp | 111 + .../modules/Verve/Extension/GUI/VFadeEvent.h | 60 + .../Verve/Extension/GUI/VFadeTrack.cpp | 139 + .../modules/Verve/Extension/GUI/VFadeTrack.h | 52 + .../Extension/Game/VSpawnSphereGroup.cpp | 32 + .../Verve/Extension/Game/VSpawnSphereGroup.h | 47 + .../Game/VSpawnSphereSpawnTargetEvent.cpp | 68 + .../Game/VSpawnSphereSpawnTargetEvent.h | 56 + .../Game/VSpawnSphereSpawnTargetTrack.cpp | 155 + .../Game/VSpawnSphereSpawnTargetTrack.h | 69 + .../VLightObjectAnimationEvent.cpp | 92 + .../LightObject/VLightObjectAnimationEvent.h | 62 + .../VLightObjectAnimationTrack.cpp | 118 + .../LightObject/VLightObjectAnimationTrack.h | 56 + .../LightObject/VLightObjectGroup.cpp | 32 + .../Extension/LightObject/VLightObjectGroup.h | 47 + .../LightObject/VLightObjectToggleEvent.cpp | 70 + .../LightObject/VLightObjectToggleEvent.h | 65 + .../LightObject/VLightObjectToggleTrack.cpp | 63 + .../LightObject/VLightObjectToggleTrack.h | 55 + .../Verve/Extension/Motion/VMotionEvent.cpp | 212 + .../Verve/Extension/Motion/VMotionEvent.h | 61 + .../Verve/Extension/Motion/VMotionTrack.cpp | 442 +++ .../Verve/Extension/Motion/VMotionTrack.h | 85 + .../ParticleEffect/VParticleEffectGroup.cpp | 32 + .../ParticleEffect/VParticleEffectGroup.h | 47 + .../VParticleEffectToggleEvent.cpp | 70 + .../VParticleEffectToggleEvent.h | 65 + .../VParticleEffectToggleTrack.cpp | 63 + .../VParticleEffectToggleTrack.h | 55 + .../PostEffect/VPostEffectToggleEvent.cpp | 77 + .../PostEffect/VPostEffectToggleEvent.h | 65 + .../PostEffect/VPostEffectToggleTrack.cpp | 103 + .../PostEffect/VPostEffectToggleTrack.h | 65 + .../SceneObject/VSceneObjectEvent.cpp | 77 + .../Extension/SceneObject/VSceneObjectEvent.h | 63 + .../SceneObject/VSceneObjectGroup.cpp | 104 + .../Extension/SceneObject/VSceneObjectGroup.h | 72 + .../SceneObject/VSceneObjectTrack.cpp | 77 + .../Extension/SceneObject/VSceneObjectTrack.h | 63 + .../Verve/Extension/Script/VScriptEvent.cpp | 101 + .../Verve/Extension/Script/VScriptEvent.h | 74 + .../Extension/Script/VScriptEventTrack.cpp | 32 + .../Extension/Script/VScriptEventTrack.h | 47 + .../SoundEffect/VSoundEffectEvent.cpp | 131 + .../Extension/SoundEffect/VSoundEffectEvent.h | 74 + .../SoundEffect/VSoundEffectTrack.cpp | 111 + .../Extension/SoundEffect/VSoundEffectTrack.h | 60 + Engine/modules/Verve/GUI/VEditorButton.cpp | 216 ++ Engine/modules/Verve/GUI/VEditorButton.h | 62 + .../Verve/GUI/VEditorScrollControl.cpp | 97 + .../modules/Verve/GUI/VEditorScrollControl.h | 56 + Engine/modules/Verve/GUI/VEditorWindow.cpp | 158 + Engine/modules/Verve/GUI/VEditorWindow.h | 49 + Engine/modules/Verve/GUI/VFadeControl.cpp | 114 + Engine/modules/Verve/GUI/VFadeControl.h | 73 + Engine/modules/Verve/GUI/VTimeLineControl.cpp | 476 +++ Engine/modules/Verve/GUI/VTimeLineControl.h | 91 + Engine/modules/Verve/Torque/TAnimation.h | 45 + Engine/modules/Verve/Torque/TCamera.h | 43 + Engine/modules/Verve/Torque/TLightObject.h | 48 + Engine/modules/Verve/Torque/TMotion.h | 57 + Engine/modules/Verve/Torque/TParticleEffect.h | 43 + Engine/modules/Verve/Torque/TPostEffect.h | 42 + Engine/modules/Verve/Torque/TSceneObject.h | 35 + Engine/modules/Verve/Torque/TSoundEffect.h | 57 + Engine/modules/Verve/Torque/TSpawnSphere.h | 39 + Engine/modules/Verve/Torque3D/VAnimation.cpp | 172 + Engine/modules/Verve/Torque3D/VCamera.cpp | 57 + .../modules/Verve/Torque3D/VCameraShake.cpp | 245 ++ Engine/modules/Verve/Torque3D/VCameraShake.h | 65 + .../modules/Verve/Torque3D/VLightObject.cpp | 89 + Engine/modules/Verve/Torque3D/VMotion.cpp | 458 +++ .../Verve/Torque3D/VParticleEffect.cpp | 53 + Engine/modules/Verve/Torque3D/VPostEffect.cpp | 152 + Engine/modules/Verve/Torque3D/VPostEffect.h | 55 + .../modules/Verve/Torque3D/VSoundEffect.cpp | 354 ++ Engine/modules/Verve/Torque3D/VSoundEffect.h | 60 + .../modules/Verve/Torque3D/VSpawnSphere.cpp | 0 .../Verve/VActor/Humanoid/VHumanoidActor.cpp | 259 ++ .../Verve/VActor/Humanoid/VHumanoidActor.h | 84 + .../VHumanoidActorAnimationController.cpp | 65 + .../VHumanoidActorAnimationController.h | 90 + .../VActor/Humanoid/VHumanoidActorData.cpp | 96 + .../VActor/Humanoid/VHumanoidActorData.h | 81 + .../VHumanoidActorPhysicsController.cpp | 35 + .../VHumanoidActorPhysicsController.h | 45 + .../Humanoid/VHumanoidAnimationStates.cpp | 213 + .../Humanoid/VHumanoidAnimationStates.h | 46 + .../Humanoid/VHumanoidPhysicsStates.cpp | 113 + .../VActor/Humanoid/VHumanoidPhysicsStates.h | 38 + .../modules/Verve/VActor/Types/VEnumerators.h | 52 + Engine/modules/Verve/VActor/Types/VRange.h | 55 + Engine/modules/Verve/VActor/Types/VTypes.h | 34 + Engine/modules/Verve/VActor/VActor.cpp | 232 ++ Engine/modules/Verve/VActor/VActor.h | 116 + .../VActor/VActorAnimationController.cpp | 354 ++ .../Verve/VActor/VActorAnimationController.h | 102 + .../Verve/VActor/VActorAnimationStates.h | 64 + Engine/modules/Verve/VActor/VActorData.cpp | 170 + Engine/modules/Verve/VActor/VActorData.h | 132 + .../Verve/VActor/VActorPhysicsController.cpp | 1277 ++++++ .../Verve/VActor/VActorPhysicsController.h | 160 + .../Verve/VActor/VActorPhysicsStates.h | 72 + .../modules/Verve/VActor/VActorStateTable.cpp | 155 + .../modules/Verve/VActor/VActorStateTable.h | 134 + .../modules/Verve/VActor/VInterpController.h | 207 + Engine/modules/Verve/VPath/VNetState.cpp | 143 + Engine/modules/Verve/VPath/VNetState.h | 84 + Engine/modules/Verve/VPath/VPath.cpp | 3452 +++++++++++++++++ Engine/modules/Verve/VPath/VPath.h | 271 ++ Engine/modules/Verve/VPath/VPathEditor.cpp | 2205 +++++++++++ Engine/modules/Verve/VPath/VPathEditor.h | 293 ++ Engine/modules/Verve/VPath/VPathNode.cpp | 470 +++ Engine/modules/Verve/VPath/VPathNode.h | 172 + Engine/modules/Verve/VPath/VPathObject.cpp | 731 ++++ Engine/modules/Verve/VPath/VPathObject.h | 246 ++ Engine/modules/Verve/VerveConfig.h | 32 + Engine/source/Verve/Core/ITreeNode.h | 76 + .../Verve/Core/Persistence/VPersistence.cpp | 137 + .../Verve/Core/Persistence/VPersistence.h | 286 ++ Engine/source/Verve/Core/Util/VSharedEnum.cpp | 31 + Engine/source/Verve/Core/Util/VSharedEnum.h | 49 + Engine/source/Verve/Core/VController.cpp | 1160 ++++++ Engine/source/Verve/Core/VController.h | 246 ++ Engine/source/Verve/Core/VDataTable.cpp | 253 ++ Engine/source/Verve/Core/VDataTable.h | 118 + Engine/source/Verve/Core/VEvent.cpp | 406 ++ Engine/source/Verve/Core/VEvent.h | 109 + Engine/source/Verve/Core/VGroup.cpp | 32 + Engine/source/Verve/Core/VGroup.h | 47 + Engine/source/Verve/Core/VObject.cpp | 489 +++ Engine/source/Verve/Core/VObject.h | 126 + Engine/source/Verve/Core/VTrack.cpp | 448 +++ Engine/source/Verve/Core/VTrack.h | 123 + Engine/source/Verve/Core/VTreeNode.cpp | 471 +++ Engine/source/Verve/Core/VTreeNode.h | 73 + .../Animation/VShapeAnimationEvent.cpp | 154 + .../Animation/VShapeAnimationEvent.h | 69 + .../Animation/VShapeAnimationTrack.cpp | 185 + .../Animation/VShapeAnimationTrack.h | 64 + .../Verve/Extension/Camera/VCameraGroup.cpp | 224 ++ .../Verve/Extension/Camera/VCameraGroup.h | 97 + .../Extension/Camera/VCameraShakeEvent.cpp | 83 + .../Extension/Camera/VCameraShakeEvent.h | 59 + .../Extension/Camera/VCameraShakeTrack.cpp | 114 + .../Extension/Camera/VCameraShakeTrack.h | 55 + .../Verve/Extension/Camera/VCameraTrack.cpp | 108 + .../Verve/Extension/Camera/VCameraTrack.h | 60 + .../Extension/Director/VDirectorEvent.cpp | 75 + .../Verve/Extension/Director/VDirectorEvent.h | 61 + .../Extension/Director/VDirectorGroup.cpp | 57 + .../Verve/Extension/Director/VDirectorGroup.h | 59 + .../Extension/Director/VDirectorTrack.cpp | 63 + .../Verve/Extension/Director/VDirectorTrack.h | 47 + .../Extension/Director/VSceneJumpEvent.cpp | 82 + .../Extension/Director/VSceneJumpEvent.h | 57 + .../Extension/Director/VSceneJumpTrack.cpp | 32 + .../Extension/Director/VSceneJumpTrack.h | 47 + .../Verve/Extension/Director/VSlowMoEvent.cpp | 130 + .../Verve/Extension/Director/VSlowMoEvent.h | 60 + .../Verve/Extension/Director/VSlowMoTrack.cpp | 93 + .../Verve/Extension/Director/VSlowMoTrack.h | 52 + .../source/Verve/Extension/GUI/VFadeEvent.cpp | 111 + .../source/Verve/Extension/GUI/VFadeEvent.h | 60 + .../source/Verve/Extension/GUI/VFadeTrack.cpp | 139 + .../source/Verve/Extension/GUI/VFadeTrack.h | 52 + .../Extension/Game/VSpawnSphereGroup.cpp | 32 + .../Verve/Extension/Game/VSpawnSphereGroup.h | 47 + .../Game/VSpawnSphereSpawnTargetEvent.cpp | 68 + .../Game/VSpawnSphereSpawnTargetEvent.h | 56 + .../Game/VSpawnSphereSpawnTargetTrack.cpp | 155 + .../Game/VSpawnSphereSpawnTargetTrack.h | 69 + .../VLightObjectAnimationEvent.cpp | 92 + .../LightObject/VLightObjectAnimationEvent.h | 62 + .../VLightObjectAnimationTrack.cpp | 118 + .../LightObject/VLightObjectAnimationTrack.h | 56 + .../LightObject/VLightObjectGroup.cpp | 32 + .../Extension/LightObject/VLightObjectGroup.h | 47 + .../LightObject/VLightObjectToggleEvent.cpp | 70 + .../LightObject/VLightObjectToggleEvent.h | 65 + .../LightObject/VLightObjectToggleTrack.cpp | 63 + .../LightObject/VLightObjectToggleTrack.h | 55 + .../Verve/Extension/Motion/VMotionEvent.cpp | 212 + .../Verve/Extension/Motion/VMotionEvent.h | 61 + .../Verve/Extension/Motion/VMotionTrack.cpp | 442 +++ .../Verve/Extension/Motion/VMotionTrack.h | 85 + .../ParticleEffect/VParticleEffectGroup.cpp | 32 + .../ParticleEffect/VParticleEffectGroup.h | 47 + .../VParticleEffectToggleEvent.cpp | 70 + .../VParticleEffectToggleEvent.h | 65 + .../VParticleEffectToggleTrack.cpp | 63 + .../VParticleEffectToggleTrack.h | 55 + .../PostEffect/VPostEffectToggleEvent.cpp | 77 + .../PostEffect/VPostEffectToggleEvent.h | 65 + .../PostEffect/VPostEffectToggleTrack.cpp | 103 + .../PostEffect/VPostEffectToggleTrack.h | 65 + .../SceneObject/VSceneObjectEvent.cpp | 77 + .../Extension/SceneObject/VSceneObjectEvent.h | 63 + .../SceneObject/VSceneObjectGroup.cpp | 104 + .../Extension/SceneObject/VSceneObjectGroup.h | 72 + .../SceneObject/VSceneObjectTrack.cpp | 77 + .../Extension/SceneObject/VSceneObjectTrack.h | 63 + .../Verve/Extension/Script/VScriptEvent.cpp | 101 + .../Verve/Extension/Script/VScriptEvent.h | 74 + .../Extension/Script/VScriptEventTrack.cpp | 32 + .../Extension/Script/VScriptEventTrack.h | 47 + .../SoundEffect/VSoundEffectEvent.cpp | 131 + .../Extension/SoundEffect/VSoundEffectEvent.h | 74 + .../SoundEffect/VSoundEffectTrack.cpp | 111 + .../Extension/SoundEffect/VSoundEffectTrack.h | 60 + Engine/source/Verve/GUI/VEditorButton.cpp | 216 ++ Engine/source/Verve/GUI/VEditorButton.h | 62 + .../source/Verve/GUI/VEditorScrollControl.cpp | 97 + .../source/Verve/GUI/VEditorScrollControl.h | 56 + Engine/source/Verve/GUI/VEditorWindow.cpp | 145 + Engine/source/Verve/GUI/VEditorWindow.h | 49 + Engine/source/Verve/GUI/VFadeControl.cpp | 114 + Engine/source/Verve/GUI/VFadeControl.h | 73 + Engine/source/Verve/GUI/VTimeLineControl.cpp | 476 +++ Engine/source/Verve/GUI/VTimeLineControl.h | 91 + Engine/source/Verve/Torque/TAnimation.h | 45 + Engine/source/Verve/Torque/TCamera.h | 43 + Engine/source/Verve/Torque/TLightObject.h | 48 + Engine/source/Verve/Torque/TMotion.h | 57 + Engine/source/Verve/Torque/TParticleEffect.h | 43 + Engine/source/Verve/Torque/TPostEffect.h | 42 + Engine/source/Verve/Torque/TSceneObject.h | 35 + Engine/source/Verve/Torque/TSoundEffect.h | 57 + Engine/source/Verve/Torque/TSpawnSphere.h | 39 + Engine/source/Verve/Torque3D/VAnimation.cpp | 172 + Engine/source/Verve/Torque3D/VCamera.cpp | 57 + Engine/source/Verve/Torque3D/VCameraShake.cpp | 231 ++ Engine/source/Verve/Torque3D/VCameraShake.h | 65 + Engine/source/Verve/Torque3D/VLightObject.cpp | 89 + Engine/source/Verve/Torque3D/VMotion.cpp | 458 +++ .../source/Verve/Torque3D/VParticleEffect.cpp | 53 + Engine/source/Verve/Torque3D/VPostEffect.cpp | 152 + Engine/source/Verve/Torque3D/VPostEffect.h | 55 + Engine/source/Verve/Torque3D/VSoundEffect.cpp | 354 ++ Engine/source/Verve/Torque3D/VSoundEffect.h | 60 + Engine/source/Verve/Torque3D/VSpawnSphere.cpp | 0 .../Verve/VActor/Humanoid/VHumanoidActor.cpp | 259 ++ .../Verve/VActor/Humanoid/VHumanoidActor.h | 84 + .../VHumanoidActorAnimationController.cpp | 65 + .../VHumanoidActorAnimationController.h | 90 + .../VActor/Humanoid/VHumanoidActorData.cpp | 96 + .../VActor/Humanoid/VHumanoidActorData.h | 81 + .../VHumanoidActorPhysicsController.cpp | 35 + .../VHumanoidActorPhysicsController.h | 45 + .../Humanoid/VHumanoidAnimationStates.cpp | 213 + .../Humanoid/VHumanoidAnimationStates.h | 46 + .../Humanoid/VHumanoidPhysicsStates.cpp | 113 + .../VActor/Humanoid/VHumanoidPhysicsStates.h | 38 + .../source/Verve/VActor/Types/VEnumerators.h | 52 + Engine/source/Verve/VActor/Types/VRange.h | 55 + Engine/source/Verve/VActor/Types/VTypes.h | 34 + Engine/source/Verve/VActor/VActor.cpp | 232 ++ Engine/source/Verve/VActor/VActor.h | 116 + .../VActor/VActorAnimationController.cpp | 354 ++ .../Verve/VActor/VActorAnimationController.h | 102 + .../Verve/VActor/VActorAnimationStates.h | 64 + Engine/source/Verve/VActor/VActorData.cpp | 170 + Engine/source/Verve/VActor/VActorData.h | 132 + .../Verve/VActor/VActorPhysicsController.cpp | 1277 ++++++ .../Verve/VActor/VActorPhysicsController.h | 160 + .../source/Verve/VActor/VActorPhysicsStates.h | 72 + .../source/Verve/VActor/VActorStateTable.cpp | 155 + Engine/source/Verve/VActor/VActorStateTable.h | 134 + .../source/Verve/VActor/VInterpController.h | 207 + Engine/source/Verve/VPath/VNetState.cpp | 143 + Engine/source/Verve/VPath/VNetState.h | 84 + Engine/source/Verve/VPath/VPath.cpp | 3375 ++++++++++++++++ Engine/source/Verve/VPath/VPath.h | 271 ++ Engine/source/Verve/VPath/VPathEditor.cpp | 2190 +++++++++++ Engine/source/Verve/VPath/VPathEditor.h | 293 ++ Engine/source/Verve/VPath/VPathNode.cpp | 470 +++ Engine/source/Verve/VPath/VPathNode.h | 172 + Engine/source/Verve/VPath/VPathObject.cpp | 731 ++++ Engine/source/Verve/VPath/VPathObject.h | 246 ++ Engine/source/Verve/VerveConfig.h | 32 + Engine/source/console/simObject.cpp | 4 + Engine/source/gfx/D3D11/gfxD3D11Device.cpp | 8 +- Templates/BaseGame/game/data/Verve/Verve.cs | 19 + .../BaseGame/game/data/Verve/Verve.module | 9 + .../art/shapes/VervePathTutorial/BLACK.png | Bin 0 -> 2824 bytes .../shapes/VervePathTutorial/DemoRoomLrg.dae | 1258 ++++++ .../art/shapes/VervePathTutorial/Door.dae | 219 ++ .../VervePathTutorial/ElevatorPlatform.dae | 180 + .../shapes/VervePathTutorial/FULL128X128G.png | Bin 0 -> 3266 bytes .../shapes/VervePathTutorial/FULL64X64G.png | Bin 0 -> 2952 bytes .../VervePathTutorial/PILLAR128X128G.png | Bin 0 -> 4917 bytes .../art/shapes/VervePathTutorial/materials.cs | 179 + .../shapes/actors/Soldier/soldier_rigged.dts | Bin 0 -> 2237151 bytes .../game/data/Verve/gui/VerveCinematic.gui | 43 + .../Verve/scripts/datablocks/datablockExec.cs | 68 + .../datablocks/verve/VerveActorData.cs | 40 + .../datablocks/verve/VervePathTutorialData.cs | 34 + .../server/VerveCinematicController.cs | 130 + .../scripts/server/VerveCinematicTrigger.cs | 35 + .../scripts/server/VervePathTutorialData.cs | 34 + .../DoorGroup0_Open+Close.vsf | 85 + .../DoorGroup1_Open+Close.vsf | 87 + .../ElevatorPlatform_Up+Down.vsf | 53 + .../data/shaderCache/76d48535f69be600_P.hlsl | 94 + .../data/shaderCache/76d48535f69be600_V.hlsl | 74 + .../data/shaderCache/7a74ac0558b62462_P.hlsl | 52 + .../data/shaderCache/7a74ac0558b62462_V.hlsl | 51 + .../data/shaderCache/8625023c97ea6cf9_P.hlsl | 77 + .../data/shaderCache/8625023c97ea6cf9_V.hlsl | 67 + .../data/shaderCache/a1a7a101cca9ce72_P.hlsl | 54 + .../data/shaderCache/a1a7a101cca9ce72_V.hlsl | 58 + .../data/shaderCache/autogenConditioners.h | 58 + .../data/shaderCache/b524839793fade4e_P.hlsl | 80 + .../data/shaderCache/b524839793fade4e_V.hlsl | 57 + .../data/shaderCache/c5e4ec9bb49846a9_P.hlsl | 87 + .../data/shaderCache/c5e4ec9bb49846a9_V.hlsl | 70 + .../data/shaderCache/c74b275969540357_P.hlsl | 47 + .../data/shaderCache/c74b275969540357_V.hlsl | 61 + .../data/shaderCache/d653a08573e79020_P.hlsl | 52 + .../data/shaderCache/d653a08573e79020_V.hlsl | 51 + .../data/shaderCache/efef832dc37c8755_P.hlsl | 69 + .../data/shaderCache/efef832dc37c8755_V.hlsl | 63 + .../data/shaderCache/f04ad263e891c04c_P.hlsl | 52 + .../data/shaderCache/f04ad263e891c04c_V.hlsl | 67 + .../data/shaderCache/fd1301c841a0c80b_P.hlsl | 84 + .../data/shaderCache/fd1301c841a0c80b_V.hlsl | 73 + .../VPathEditor/GUI/Images/btn_Palette_d.png | Bin 0 -> 3125 bytes .../VPathEditor/GUI/Images/btn_Palette_h.png | Bin 0 -> 3298 bytes .../VPathEditor/GUI/Images/btn_Palette_n.png | Bin 0 -> 2928 bytes .../game/tools/VPathEditor/GUI/Profiles.cs | 12 + .../tools/VPathEditor/GUI/VPathEditor.gui | 434 +++ .../VPathEditor/GUI/VPathEditorPalette.gui | 176 + .../VPathEditor/GUI/VPathEditorToolbar.gui | 72 + .../game/tools/VPathEditor/Scripts/Editor.cs | 228 ++ .../game/tools/VPathEditor/Scripts/Plugin.cs | 178 + .../BaseGame/game/tools/VPathEditor/main.cs | 20 + .../game/tools/VerveEditor/DefaultPrefs.cs | 23 + .../game/tools/VerveEditor/GUI/Buttons.psd | Bin 0 -> 120172 bytes .../game/tools/VerveEditor/GUI/GuiProfiles.cs | 213 + .../tools/VerveEditor/GUI/Images/Button.png | Bin 0 -> 1307 bytes .../GUI/Images/GroupBackground.png | Bin 0 -> 272 bytes .../GUI/Images/GroupBackground_h.png | Bin 0 -> 2859 bytes .../GUI/Images/GroupBackground_i.png | Bin 0 -> 2865 bytes .../GUI/Images/PropertyRollout.png | Bin 0 -> 3200 bytes .../VerveEditor/GUI/Images/ScrollBar.png | Bin 0 -> 3713 bytes .../VerveEditor/GUI/Images/ScrollBar_.png | Bin 0 -> 3884 bytes .../tools/VerveEditor/GUI/Images/Spacer.png | Bin 0 -> 1219 bytes .../VerveEditor/GUI/Images/btn_AddEvent.png | Bin 0 -> 3564 bytes .../VerveEditor/GUI/Images/btn_AddEvent_d.png | Bin 0 -> 3626 bytes .../VerveEditor/GUI/Images/btn_AddEvent_h.png | Bin 0 -> 3629 bytes .../VerveEditor/GUI/Images/btn_AddGroup.png | Bin 0 -> 3525 bytes .../VerveEditor/GUI/Images/btn_AddGroup_d.png | Bin 0 -> 3553 bytes .../VerveEditor/GUI/Images/btn_AddGroup_h.png | Bin 0 -> 3574 bytes .../tools/VerveEditor/GUI/Images/btn_AddL.png | Bin 0 -> 3560 bytes .../VerveEditor/GUI/Images/btn_AddL_d.png | Bin 0 -> 3623 bytes .../VerveEditor/GUI/Images/btn_AddL_h.png | Bin 0 -> 3626 bytes .../tools/VerveEditor/GUI/Images/btn_AddR.png | Bin 0 -> 3561 bytes .../VerveEditor/GUI/Images/btn_AddR_d.png | Bin 0 -> 3615 bytes .../VerveEditor/GUI/Images/btn_AddR_h.png | Bin 0 -> 3632 bytes .../VerveEditor/GUI/Images/btn_AddSml.png | Bin 0 -> 3216 bytes .../VerveEditor/GUI/Images/btn_AddSml_d.png | Bin 0 -> 3244 bytes .../VerveEditor/GUI/Images/btn_AddSml_h.png | Bin 0 -> 3262 bytes .../VerveEditor/GUI/Images/btn_AddTrack.png | Bin 0 -> 3577 bytes .../VerveEditor/GUI/Images/btn_AddTrack_d.png | Bin 0 -> 3637 bytes .../VerveEditor/GUI/Images/btn_AddTrack_h.png | Bin 0 -> 3656 bytes .../VerveEditor/GUI/Images/btn_Delete.png | Bin 0 -> 3440 bytes .../VerveEditor/GUI/Images/btn_DeleteSml.png | Bin 0 -> 3189 bytes .../GUI/Images/btn_DeleteSml_d.png | Bin 0 -> 3218 bytes .../GUI/Images/btn_DeleteSml_h.png | Bin 0 -> 3238 bytes .../VerveEditor/GUI/Images/btn_Delete_d.png | Bin 0 -> 3469 bytes .../VerveEditor/GUI/Images/btn_Delete_h.png | Bin 0 -> 3473 bytes .../VerveEditor/GUI/Images/btn_Forward.png | Bin 0 -> 3820 bytes .../VerveEditor/GUI/Images/btn_Forward_d.png | Bin 0 -> 3898 bytes .../VerveEditor/GUI/Images/btn_Forward_h.png | Bin 0 -> 3895 bytes .../VerveEditor/GUI/Images/btn_Palette_d.png | Bin 0 -> 3284 bytes .../VerveEditor/GUI/Images/btn_Palette_h.png | Bin 0 -> 3683 bytes .../VerveEditor/GUI/Images/btn_Palette_n.png | Bin 0 -> 2982 bytes .../VerveEditor/GUI/Images/btn_Pause.png | Bin 0 -> 3606 bytes .../VerveEditor/GUI/Images/btn_Pause_d.png | Bin 0 -> 3690 bytes .../VerveEditor/GUI/Images/btn_Pause_h.png | Bin 0 -> 3683 bytes .../tools/VerveEditor/GUI/Images/btn_Play.png | Bin 0 -> 3774 bytes .../VerveEditor/GUI/Images/btn_Play_d.png | Bin 0 -> 3817 bytes .../VerveEditor/GUI/Images/btn_Play_h.png | Bin 0 -> 3820 bytes .../VerveEditor/GUI/Images/btn_Rewind.png | Bin 0 -> 3832 bytes .../VerveEditor/GUI/Images/btn_Rewind_d.png | Bin 0 -> 3906 bytes .../VerveEditor/GUI/Images/btn_Rewind_h.png | Bin 0 -> 3906 bytes .../VerveEditor/GUI/Images/btn_StepB.png | Bin 0 -> 3804 bytes .../VerveEditor/GUI/Images/btn_StepB_d.png | Bin 0 -> 3869 bytes .../VerveEditor/GUI/Images/btn_StepB_h.png | Bin 0 -> 3859 bytes .../VerveEditor/GUI/Images/btn_StepF.png | Bin 0 -> 3808 bytes .../VerveEditor/GUI/Images/btn_StepF_d.png | Bin 0 -> 3838 bytes .../VerveEditor/GUI/Images/btn_StepF_h.png | Bin 0 -> 3848 bytes .../VerveEditor/GUI/PropertyContainer.psd | Bin 0 -> 35698 bytes .../tools/VerveEditor/GUI/VerveEditor.gui | 764 ++++ .../GUI/VerveEditorGroupBuilder.gui | 434 +++ .../GUI/VerveEditorImportPathNodes.gui | 133 + .../GUI/VerveEditorPreferences.gui | 367 ++ .../game/tools/VerveEditor/GUI/btn_AddSml.psd | Bin 0 -> 29278 bytes .../tools/VerveEditor/GUI/btn_Palette.psd | Bin 0 -> 30228 bytes .../Scripts/Controller/VController.cs | 362 ++ .../Controller/VControllerProperties.cs | 217 ++ .../VerveEditor/Scripts/Controller/main.cs | 15 + .../VerveEditor/Scripts/EditorControls.cs | 241 ++ .../VerveEditor/Scripts/EditorHistory.cs | 265 ++ .../tools/VerveEditor/Scripts/EditorMenu.cs | 261 ++ .../VerveEditor/Scripts/EditorPreferences.cs | 29 + .../tools/VerveEditor/Scripts/EditorWindow.cs | 215 + .../Scripts/Events/VCameraShakeEvent.cs | 15 + .../Scripts/Events/VDirectorEvent.cs | 99 + .../VerveEditor/Scripts/Events/VEvent.cs | 314 ++ .../VerveEditor/Scripts/Events/VFadeEvent.cs | 30 + .../Events/VLightObjectAnimationEvent.cs | 49 + .../Scripts/Events/VLightObjectToggleEvent.cs | 14 + .../Scripts/Events/VMotionEvent.cs | 183 + .../Events/VParticleEffectToggleEvent.cs | 14 + .../Scripts/Events/VPostEffectToggleEvent.cs | 14 + .../Scripts/Events/VSceneJumpEvent.cs | 14 + .../Scripts/Events/VScriptEvent.cs | 15 + .../Scripts/Events/VShapeAnimationEvent.cs | 55 + .../Scripts/Events/VSlowMoEvent.cs | 13 + .../Scripts/Events/VSoundEffectEvent.cs | 39 + .../Events/VSpawnSphereSpawnTargetEvent.cs | 10 + .../tools/VerveEditor/Scripts/Events/main.cs | 30 + .../Scripts/Groups/VCameraGroup.cs | 57 + .../Scripts/Groups/VDirectorGroup.cs | 75 + .../VerveEditor/Scripts/Groups/VGroup.cs | 360 ++ .../Scripts/Groups/VLightObjectGroup.cs | 120 + .../Scripts/Groups/VParticleEffectGroup.cs | 118 + .../Scripts/Groups/VSceneObjectGroup.cs | 159 + .../Scripts/Groups/VSpawnSphereGroup.cs | 100 + .../tools/VerveEditor/Scripts/Groups/main.cs | 25 + .../VerveEditor/Scripts/Inspector/Controls.cs | 163 + .../Scripts/Inspector/CutCopyPaste.cs | 152 + .../Scripts/Inspector/EventNotify.cs | 53 + .../VerveEditor/Scripts/Inspector/Factory.cs | 248 ++ .../Scripts/Inspector/FactoryControls.cs | 115 + .../Scripts/Inspector/FieldNotify.cs | 136 + .../Scripts/Inspector/Fields/TypeBool.cs | 47 + .../Scripts/Inspector/Fields/TypeData.cs | 336 ++ .../Scripts/Inspector/Fields/TypeEnum.cs | 94 + .../Scripts/Inspector/Fields/TypeString.cs | 58 + .../Inspector/Fields/TypeToggleEnum.cs | 16 + .../Inspector/Fields/TypeVCameraGroupEnum.cs | 32 + .../Inspector/Fields/TypeVCommandEnum.cs | 16 + .../Fields/TypeVControllerDataEnum.cs | 28 + .../Inspector/Fields/TypeVGroupEnum.cs | 28 + .../Fields/TypeVLightAnimationDataEnum.cs | 15 + .../Fields/TypeVPathOrientationModeEnum.cs | 19 + .../Inspector/Fields/TypeVPostEffectEnum.cs | 15 + .../Inspector/Fields/TypeVSFXProfileEnum.cs | 15 + .../Inspector/Fields/TypeVSceneEnum.cs | 69 + .../Fields/TypeVShapeAnimationEnum.cs | 78 + .../Scripts/Inspector/Fields/main.cs | 25 + .../VerveEditor/Scripts/Inspector/Lists.cs | 50 + .../Scripts/Inspector/Properties.cs | 144 + .../Scripts/Inspector/Selection.cs | 224 ++ .../VerveEditor/Scripts/Inspector/main.cs | 20 + .../tools/VerveEditor/Scripts/Persistence.cs | 232 ++ .../game/tools/VerveEditor/Scripts/Plugin.cs | 63 + .../tools/VerveEditor/Scripts/ScrollNotify.cs | 154 + .../Scripts/Tracks/VCameraShakeTrack.cs | 18 + .../Scripts/Tracks/VDirectorTrack.cs | 55 + .../VerveEditor/Scripts/Tracks/VFadeTrack.cs | 43 + .../Tracks/VLightObjectAnimationTrack.cs | 22 + .../Scripts/Tracks/VLightObjectToggleTrack.cs | 18 + .../Scripts/Tracks/VMotionTrack.cs | 264 ++ .../Tracks/VParticleEffectToggleTrack.cs | 18 + .../Scripts/Tracks/VPostEffectToggleTrack.cs | 22 + .../Scripts/Tracks/VSceneJumpTrack.cs | 18 + .../Scripts/Tracks/VScriptEventTrack.cs | 18 + .../Scripts/Tracks/VShapeAnimationTrack.cs | 61 + .../Scripts/Tracks/VSlowMoTrack.cs | 18 + .../Scripts/Tracks/VSoundEffectTrack.cs | 18 + .../Tracks/VSpawnSphereSpawnTargetTrack.cs | 22 + .../VerveEditor/Scripts/Tracks/VTrack.cs | 266 ++ .../tools/VerveEditor/Scripts/Tracks/main.cs | 33 + .../game/tools/VerveEditor/Scripts/Utility.cs | 99 + .../game/tools/VerveEditor/Scripts/VObject.cs | 98 + .../VerveEditor/Templates/VCameraGroup.vsf | 17 + .../VerveEditor/Templates/VDirectorGroup.vsf | 16 + .../tools/VerveEditor/Templates/VGroup.vsf | 10 + .../Templates/VLightObjectGroup.vsf | 17 + .../Templates/VParticleEffectGroup.vsf | 17 + .../Templates/VSceneObjectGroup.vsf | 17 + .../tools/VerveEditor/Torque/ObjectClasses.cs | 45 + .../tools/VerveEditor/Torque/Selection.cs | 50 + .../game/tools/VerveEditor/Torque/main.cs | 18 + .../BaseGame/game/tools/VerveEditor/main.cs | 234 ++ Templates/BaseGame/game/tools/settings.xml | 121 +- .../Full/game/art/datablocks/datablockExec.cs | 9 +- Tools/CMake/modules/module_verve.cmake | 31 + Tools/CMake/torque3d.cmake | 8 + 538 files changed, 68727 insertions(+), 49 deletions(-) create mode 100644 Engine/modules/Verve/Core/ITreeNode.h create mode 100644 Engine/modules/Verve/Core/Persistence/VPersistence.cpp create mode 100644 Engine/modules/Verve/Core/Persistence/VPersistence.h create mode 100644 Engine/modules/Verve/Core/Util/VSharedEnum.cpp create mode 100644 Engine/modules/Verve/Core/Util/VSharedEnum.h create mode 100644 Engine/modules/Verve/Core/VController.cpp create mode 100644 Engine/modules/Verve/Core/VController.h create mode 100644 Engine/modules/Verve/Core/VDataTable.cpp create mode 100644 Engine/modules/Verve/Core/VDataTable.h create mode 100644 Engine/modules/Verve/Core/VEvent.cpp create mode 100644 Engine/modules/Verve/Core/VEvent.h create mode 100644 Engine/modules/Verve/Core/VGroup.cpp create mode 100644 Engine/modules/Verve/Core/VGroup.h create mode 100644 Engine/modules/Verve/Core/VObject.cpp create mode 100644 Engine/modules/Verve/Core/VObject.h create mode 100644 Engine/modules/Verve/Core/VTrack.cpp create mode 100644 Engine/modules/Verve/Core/VTrack.h create mode 100644 Engine/modules/Verve/Core/VTreeNode.cpp create mode 100644 Engine/modules/Verve/Core/VTreeNode.h create mode 100644 Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.h create mode 100644 Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.h create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraGroup.cpp create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraGroup.h create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.h create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.h create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Camera/VCameraTrack.h create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorEvent.h create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorGroup.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorGroup.h create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VDirectorTrack.h create mode 100644 Engine/modules/Verve/Extension/Director/VSceneJumpEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VSceneJumpEvent.h create mode 100644 Engine/modules/Verve/Extension/Director/VSceneJumpTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VSceneJumpTrack.h create mode 100644 Engine/modules/Verve/Extension/Director/VSlowMoEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VSlowMoEvent.h create mode 100644 Engine/modules/Verve/Extension/Director/VSlowMoTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Director/VSlowMoTrack.h create mode 100644 Engine/modules/Verve/Extension/GUI/VFadeEvent.cpp create mode 100644 Engine/modules/Verve/Extension/GUI/VFadeEvent.h create mode 100644 Engine/modules/Verve/Extension/GUI/VFadeTrack.cpp create mode 100644 Engine/modules/Verve/Extension/GUI/VFadeTrack.h create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.cpp create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.h create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.h create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.h create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.cpp create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.h create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.h create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp create mode 100644 Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.h create mode 100644 Engine/modules/Verve/Extension/Motion/VMotionEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Motion/VMotionEvent.h create mode 100644 Engine/modules/Verve/Extension/Motion/VMotionTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Motion/VMotionTrack.h create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.h create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp create mode 100644 Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h create mode 100644 Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp create mode 100644 Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.h create mode 100644 Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp create mode 100644 Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.h create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.cpp create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.h create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.cpp create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.h create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.cpp create mode 100644 Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.h create mode 100644 Engine/modules/Verve/Extension/Script/VScriptEvent.cpp create mode 100644 Engine/modules/Verve/Extension/Script/VScriptEvent.h create mode 100644 Engine/modules/Verve/Extension/Script/VScriptEventTrack.cpp create mode 100644 Engine/modules/Verve/Extension/Script/VScriptEventTrack.h create mode 100644 Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp create mode 100644 Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.h create mode 100644 Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp create mode 100644 Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.h create mode 100644 Engine/modules/Verve/GUI/VEditorButton.cpp create mode 100644 Engine/modules/Verve/GUI/VEditorButton.h create mode 100644 Engine/modules/Verve/GUI/VEditorScrollControl.cpp create mode 100644 Engine/modules/Verve/GUI/VEditorScrollControl.h create mode 100644 Engine/modules/Verve/GUI/VEditorWindow.cpp create mode 100644 Engine/modules/Verve/GUI/VEditorWindow.h create mode 100644 Engine/modules/Verve/GUI/VFadeControl.cpp create mode 100644 Engine/modules/Verve/GUI/VFadeControl.h create mode 100644 Engine/modules/Verve/GUI/VTimeLineControl.cpp create mode 100644 Engine/modules/Verve/GUI/VTimeLineControl.h create mode 100644 Engine/modules/Verve/Torque/TAnimation.h create mode 100644 Engine/modules/Verve/Torque/TCamera.h create mode 100644 Engine/modules/Verve/Torque/TLightObject.h create mode 100644 Engine/modules/Verve/Torque/TMotion.h create mode 100644 Engine/modules/Verve/Torque/TParticleEffect.h create mode 100644 Engine/modules/Verve/Torque/TPostEffect.h create mode 100644 Engine/modules/Verve/Torque/TSceneObject.h create mode 100644 Engine/modules/Verve/Torque/TSoundEffect.h create mode 100644 Engine/modules/Verve/Torque/TSpawnSphere.h create mode 100644 Engine/modules/Verve/Torque3D/VAnimation.cpp create mode 100644 Engine/modules/Verve/Torque3D/VCamera.cpp create mode 100644 Engine/modules/Verve/Torque3D/VCameraShake.cpp create mode 100644 Engine/modules/Verve/Torque3D/VCameraShake.h create mode 100644 Engine/modules/Verve/Torque3D/VLightObject.cpp create mode 100644 Engine/modules/Verve/Torque3D/VMotion.cpp create mode 100644 Engine/modules/Verve/Torque3D/VParticleEffect.cpp create mode 100644 Engine/modules/Verve/Torque3D/VPostEffect.cpp create mode 100644 Engine/modules/Verve/Torque3D/VPostEffect.h create mode 100644 Engine/modules/Verve/Torque3D/VSoundEffect.cpp create mode 100644 Engine/modules/Verve/Torque3D/VSoundEffect.h create mode 100644 Engine/modules/Verve/Torque3D/VSpawnSphere.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.h create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.h create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.h create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp create mode 100644 Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h create mode 100644 Engine/modules/Verve/VActor/Types/VEnumerators.h create mode 100644 Engine/modules/Verve/VActor/Types/VRange.h create mode 100644 Engine/modules/Verve/VActor/Types/VTypes.h create mode 100644 Engine/modules/Verve/VActor/VActor.cpp create mode 100644 Engine/modules/Verve/VActor/VActor.h create mode 100644 Engine/modules/Verve/VActor/VActorAnimationController.cpp create mode 100644 Engine/modules/Verve/VActor/VActorAnimationController.h create mode 100644 Engine/modules/Verve/VActor/VActorAnimationStates.h create mode 100644 Engine/modules/Verve/VActor/VActorData.cpp create mode 100644 Engine/modules/Verve/VActor/VActorData.h create mode 100644 Engine/modules/Verve/VActor/VActorPhysicsController.cpp create mode 100644 Engine/modules/Verve/VActor/VActorPhysicsController.h create mode 100644 Engine/modules/Verve/VActor/VActorPhysicsStates.h create mode 100644 Engine/modules/Verve/VActor/VActorStateTable.cpp create mode 100644 Engine/modules/Verve/VActor/VActorStateTable.h create mode 100644 Engine/modules/Verve/VActor/VInterpController.h create mode 100644 Engine/modules/Verve/VPath/VNetState.cpp create mode 100644 Engine/modules/Verve/VPath/VNetState.h create mode 100644 Engine/modules/Verve/VPath/VPath.cpp create mode 100644 Engine/modules/Verve/VPath/VPath.h create mode 100644 Engine/modules/Verve/VPath/VPathEditor.cpp create mode 100644 Engine/modules/Verve/VPath/VPathEditor.h create mode 100644 Engine/modules/Verve/VPath/VPathNode.cpp create mode 100644 Engine/modules/Verve/VPath/VPathNode.h create mode 100644 Engine/modules/Verve/VPath/VPathObject.cpp create mode 100644 Engine/modules/Verve/VPath/VPathObject.h create mode 100644 Engine/modules/Verve/VerveConfig.h create mode 100644 Engine/source/Verve/Core/ITreeNode.h create mode 100644 Engine/source/Verve/Core/Persistence/VPersistence.cpp create mode 100644 Engine/source/Verve/Core/Persistence/VPersistence.h create mode 100644 Engine/source/Verve/Core/Util/VSharedEnum.cpp create mode 100644 Engine/source/Verve/Core/Util/VSharedEnum.h create mode 100644 Engine/source/Verve/Core/VController.cpp create mode 100644 Engine/source/Verve/Core/VController.h create mode 100644 Engine/source/Verve/Core/VDataTable.cpp create mode 100644 Engine/source/Verve/Core/VDataTable.h create mode 100644 Engine/source/Verve/Core/VEvent.cpp create mode 100644 Engine/source/Verve/Core/VEvent.h create mode 100644 Engine/source/Verve/Core/VGroup.cpp create mode 100644 Engine/source/Verve/Core/VGroup.h create mode 100644 Engine/source/Verve/Core/VObject.cpp create mode 100644 Engine/source/Verve/Core/VObject.h create mode 100644 Engine/source/Verve/Core/VTrack.cpp create mode 100644 Engine/source/Verve/Core/VTrack.h create mode 100644 Engine/source/Verve/Core/VTreeNode.cpp create mode 100644 Engine/source/Verve/Core/VTreeNode.h create mode 100644 Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.cpp create mode 100644 Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.h create mode 100644 Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.cpp create mode 100644 Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.h create mode 100644 Engine/source/Verve/Extension/Camera/VCameraGroup.cpp create mode 100644 Engine/source/Verve/Extension/Camera/VCameraGroup.h create mode 100644 Engine/source/Verve/Extension/Camera/VCameraShakeEvent.cpp create mode 100644 Engine/source/Verve/Extension/Camera/VCameraShakeEvent.h create mode 100644 Engine/source/Verve/Extension/Camera/VCameraShakeTrack.cpp create mode 100644 Engine/source/Verve/Extension/Camera/VCameraShakeTrack.h create mode 100644 Engine/source/Verve/Extension/Camera/VCameraTrack.cpp create mode 100644 Engine/source/Verve/Extension/Camera/VCameraTrack.h create mode 100644 Engine/source/Verve/Extension/Director/VDirectorEvent.cpp create mode 100644 Engine/source/Verve/Extension/Director/VDirectorEvent.h create mode 100644 Engine/source/Verve/Extension/Director/VDirectorGroup.cpp create mode 100644 Engine/source/Verve/Extension/Director/VDirectorGroup.h create mode 100644 Engine/source/Verve/Extension/Director/VDirectorTrack.cpp create mode 100644 Engine/source/Verve/Extension/Director/VDirectorTrack.h create mode 100644 Engine/source/Verve/Extension/Director/VSceneJumpEvent.cpp create mode 100644 Engine/source/Verve/Extension/Director/VSceneJumpEvent.h create mode 100644 Engine/source/Verve/Extension/Director/VSceneJumpTrack.cpp create mode 100644 Engine/source/Verve/Extension/Director/VSceneJumpTrack.h create mode 100644 Engine/source/Verve/Extension/Director/VSlowMoEvent.cpp create mode 100644 Engine/source/Verve/Extension/Director/VSlowMoEvent.h create mode 100644 Engine/source/Verve/Extension/Director/VSlowMoTrack.cpp create mode 100644 Engine/source/Verve/Extension/Director/VSlowMoTrack.h create mode 100644 Engine/source/Verve/Extension/GUI/VFadeEvent.cpp create mode 100644 Engine/source/Verve/Extension/GUI/VFadeEvent.h create mode 100644 Engine/source/Verve/Extension/GUI/VFadeTrack.cpp create mode 100644 Engine/source/Verve/Extension/GUI/VFadeTrack.h create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereGroup.cpp create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereGroup.h create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp create mode 100644 Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.h create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.h create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectGroup.cpp create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectGroup.h create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.h create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp create mode 100644 Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.h create mode 100644 Engine/source/Verve/Extension/Motion/VMotionEvent.cpp create mode 100644 Engine/source/Verve/Extension/Motion/VMotionEvent.h create mode 100644 Engine/source/Verve/Extension/Motion/VMotionTrack.cpp create mode 100644 Engine/source/Verve/Extension/Motion/VMotionTrack.h create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.h create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp create mode 100644 Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h create mode 100644 Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp create mode 100644 Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.h create mode 100644 Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp create mode 100644 Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.h create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.cpp create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.h create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.cpp create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.h create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.cpp create mode 100644 Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.h create mode 100644 Engine/source/Verve/Extension/Script/VScriptEvent.cpp create mode 100644 Engine/source/Verve/Extension/Script/VScriptEvent.h create mode 100644 Engine/source/Verve/Extension/Script/VScriptEventTrack.cpp create mode 100644 Engine/source/Verve/Extension/Script/VScriptEventTrack.h create mode 100644 Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp create mode 100644 Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.h create mode 100644 Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp create mode 100644 Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.h create mode 100644 Engine/source/Verve/GUI/VEditorButton.cpp create mode 100644 Engine/source/Verve/GUI/VEditorButton.h create mode 100644 Engine/source/Verve/GUI/VEditorScrollControl.cpp create mode 100644 Engine/source/Verve/GUI/VEditorScrollControl.h create mode 100644 Engine/source/Verve/GUI/VEditorWindow.cpp create mode 100644 Engine/source/Verve/GUI/VEditorWindow.h create mode 100644 Engine/source/Verve/GUI/VFadeControl.cpp create mode 100644 Engine/source/Verve/GUI/VFadeControl.h create mode 100644 Engine/source/Verve/GUI/VTimeLineControl.cpp create mode 100644 Engine/source/Verve/GUI/VTimeLineControl.h create mode 100644 Engine/source/Verve/Torque/TAnimation.h create mode 100644 Engine/source/Verve/Torque/TCamera.h create mode 100644 Engine/source/Verve/Torque/TLightObject.h create mode 100644 Engine/source/Verve/Torque/TMotion.h create mode 100644 Engine/source/Verve/Torque/TParticleEffect.h create mode 100644 Engine/source/Verve/Torque/TPostEffect.h create mode 100644 Engine/source/Verve/Torque/TSceneObject.h create mode 100644 Engine/source/Verve/Torque/TSoundEffect.h create mode 100644 Engine/source/Verve/Torque/TSpawnSphere.h create mode 100644 Engine/source/Verve/Torque3D/VAnimation.cpp create mode 100644 Engine/source/Verve/Torque3D/VCamera.cpp create mode 100644 Engine/source/Verve/Torque3D/VCameraShake.cpp create mode 100644 Engine/source/Verve/Torque3D/VCameraShake.h create mode 100644 Engine/source/Verve/Torque3D/VLightObject.cpp create mode 100644 Engine/source/Verve/Torque3D/VMotion.cpp create mode 100644 Engine/source/Verve/Torque3D/VParticleEffect.cpp create mode 100644 Engine/source/Verve/Torque3D/VPostEffect.cpp create mode 100644 Engine/source/Verve/Torque3D/VPostEffect.h create mode 100644 Engine/source/Verve/Torque3D/VSoundEffect.cpp create mode 100644 Engine/source/Verve/Torque3D/VSoundEffect.h create mode 100644 Engine/source/Verve/Torque3D/VSpawnSphere.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActor.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActor.h create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.h create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.h create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp create mode 100644 Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h create mode 100644 Engine/source/Verve/VActor/Types/VEnumerators.h create mode 100644 Engine/source/Verve/VActor/Types/VRange.h create mode 100644 Engine/source/Verve/VActor/Types/VTypes.h create mode 100644 Engine/source/Verve/VActor/VActor.cpp create mode 100644 Engine/source/Verve/VActor/VActor.h create mode 100644 Engine/source/Verve/VActor/VActorAnimationController.cpp create mode 100644 Engine/source/Verve/VActor/VActorAnimationController.h create mode 100644 Engine/source/Verve/VActor/VActorAnimationStates.h create mode 100644 Engine/source/Verve/VActor/VActorData.cpp create mode 100644 Engine/source/Verve/VActor/VActorData.h create mode 100644 Engine/source/Verve/VActor/VActorPhysicsController.cpp create mode 100644 Engine/source/Verve/VActor/VActorPhysicsController.h create mode 100644 Engine/source/Verve/VActor/VActorPhysicsStates.h create mode 100644 Engine/source/Verve/VActor/VActorStateTable.cpp create mode 100644 Engine/source/Verve/VActor/VActorStateTable.h create mode 100644 Engine/source/Verve/VActor/VInterpController.h create mode 100644 Engine/source/Verve/VPath/VNetState.cpp create mode 100644 Engine/source/Verve/VPath/VNetState.h create mode 100644 Engine/source/Verve/VPath/VPath.cpp create mode 100644 Engine/source/Verve/VPath/VPath.h create mode 100644 Engine/source/Verve/VPath/VPathEditor.cpp create mode 100644 Engine/source/Verve/VPath/VPathEditor.h create mode 100644 Engine/source/Verve/VPath/VPathNode.cpp create mode 100644 Engine/source/Verve/VPath/VPathNode.h create mode 100644 Engine/source/Verve/VPath/VPathObject.cpp create mode 100644 Engine/source/Verve/VPath/VPathObject.h create mode 100644 Engine/source/Verve/VerveConfig.h create mode 100644 Templates/BaseGame/game/data/Verve/Verve.cs create mode 100644 Templates/BaseGame/game/data/Verve/Verve.module create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/BLACK.png create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/DemoRoomLrg.dae create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/Door.dae create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/ElevatorPlatform.dae create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL128X128G.png create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL64X64G.png create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/PILLAR128X128G.png create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/materials.cs create mode 100644 Templates/BaseGame/game/data/Verve/art/shapes/actors/Soldier/soldier_rigged.dts create mode 100644 Templates/BaseGame/game/data/Verve/gui/VerveCinematic.gui create mode 100644 Templates/BaseGame/game/data/Verve/scripts/datablocks/datablockExec.cs create mode 100644 Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VerveActorData.cs create mode 100644 Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VervePathTutorialData.cs create mode 100644 Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicController.cs create mode 100644 Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicTrigger.cs create mode 100644 Templates/BaseGame/game/data/Verve/scripts/server/VervePathTutorialData.cs create mode 100644 Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup0_Open+Close.vsf create mode 100644 Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup1_Open+Close.vsf create mode 100644 Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/ElevatorPlatform_Up+Down.vsf create mode 100644 Templates/BaseGame/game/data/shaderCache/76d48535f69be600_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/76d48535f69be600_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/autogenConditioners.h create mode 100644 Templates/BaseGame/game/data/shaderCache/b524839793fade4e_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/b524839793fade4e_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/c74b275969540357_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/c74b275969540357_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/d653a08573e79020_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/d653a08573e79020_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_V.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_P.hlsl create mode 100644 Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_V.hlsl create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_d.png create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_h.png create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_n.png create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/Profiles.cs create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditor.gui create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorPalette.gui create mode 100644 Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorToolbar.gui create mode 100644 Templates/BaseGame/game/tools/VPathEditor/Scripts/Editor.cs create mode 100644 Templates/BaseGame/game/tools/VPathEditor/Scripts/Plugin.cs create mode 100644 Templates/BaseGame/game/tools/VPathEditor/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/DefaultPrefs.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Buttons.psd create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/GuiProfiles.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Button.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_i.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/PropertyRollout.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar_.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Spacer.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_n.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_d.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_h.png create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/PropertyContainer.psd create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditor.gui create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorGroupBuilder.gui create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorImportPathNodes.gui create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorPreferences.gui create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/btn_AddSml.psd create mode 100644 Templates/BaseGame/game/tools/VerveEditor/GUI/btn_Palette.psd create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VController.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VControllerProperties.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorControls.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorHistory.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorMenu.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorPreferences.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorWindow.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VCameraShakeEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VDirectorEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VFadeEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectAnimationEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectToggleEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VMotionEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VParticleEffectToggleEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VPostEffectToggleEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSceneJumpEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VScriptEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VShapeAnimationEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSlowMoEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSoundEffectEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSpawnSphereSpawnTargetEvent.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VCameraGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VDirectorGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VLightObjectGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VParticleEffectGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSceneObjectGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSpawnSphereGroup.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Controls.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/CutCopyPaste.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/EventNotify.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Factory.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FactoryControls.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FieldNotify.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeBool.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeData.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeString.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeToggleEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCameraGroupEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCommandEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVControllerDataEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVGroupEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVLightAnimationDataEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPathOrientationModeEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPostEffectEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSFXProfileEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSceneEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVShapeAnimationEnum.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Lists.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Properties.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Selection.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Persistence.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Plugin.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/ScrollNotify.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VCameraShakeTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VDirectorTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VFadeTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectAnimationTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectToggleTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VMotionTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VParticleEffectToggleTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VPostEffectToggleTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSceneJumpTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VScriptEventTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VShapeAnimationTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSlowMoTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSoundEffectTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSpawnSphereSpawnTargetTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VTrack.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/Utility.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Scripts/VObject.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VCameraGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VDirectorGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VLightObjectGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VParticleEffectGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Templates/VSceneObjectGroup.vsf create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Torque/ObjectClasses.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Torque/Selection.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/Torque/main.cs create mode 100644 Templates/BaseGame/game/tools/VerveEditor/main.cs create mode 100644 Tools/CMake/modules/module_verve.cmake diff --git a/Engine/modules/Verve/Core/ITreeNode.h b/Engine/modules/Verve/Core/ITreeNode.h new file mode 100644 index 000000000..943dd554d --- /dev/null +++ b/Engine/modules/Verve/Core/ITreeNode.h @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_ITREENODE_H_ +#define _VT_ITREENODE_H_ + +//----------------------------------------------------------------------------- + +class ITreeNode +{ +public: + + ITreeNode *mParentNode; + ITreeNode *mChildNode; + + ITreeNode *mSiblingPrevNode; + ITreeNode *mSiblingNextNode; + +public: + + ITreeNode( void ) : + mParentNode( 0 ), + mChildNode( 0 ), + mSiblingPrevNode( 0 ), + mSiblingNextNode( 0 ) + { + // Void. + }; + + virtual ~ITreeNode( void ) + { + // Void. + }; + + virtual void clear( void ) = 0; // Clear the Node. + + virtual ITreeNode *getRoot( void ) = 0; // Get Root Node. + virtual ITreeNode *getParent( void ) = 0; // Get Parent Node. + virtual ITreeNode *getChild( void ) = 0; // Get Child Node. + virtual ITreeNode *getLastChild( void ) = 0; // Get Last Child Node. + + virtual ITreeNode *getPrevSibling( void ) = 0; // Get Previous Sibling Node. + virtual ITreeNode *getNextSibling( void ) = 0; // Get Next Sibling Node. + + virtual void addTo( ITreeNode *pNode ) = 0; // Add Node to target node. + virtual void remove( void ) = 0; // Remove this Node from the tree. + virtual void moveTo( ITreeNode* node ) = 0; // Move to specified Node. + + virtual void onAttach( void ) = 0; // Attach Callback. + virtual void onDetach( void ) = 0; // Detach Callback. + + virtual bool inTree( void ) = 0; // Is Node in a tree? +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_ITREENODE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/Persistence/VPersistence.cpp b/Engine/modules/Verve/Core/Persistence/VPersistence.cpp new file mode 100644 index 000000000..daf3336a9 --- /dev/null +++ b/Engine/modules/Verve/Core/Persistence/VPersistence.cpp @@ -0,0 +1,137 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/Persistence/VPersistence.h" + +#include "Verve/Core/VController.h" +#include "Verve/Core/VObject.h" + +namespace VPersistence +{ + //----------------------------------------------------------------------------- + // + // VController + // + //----------------------------------------------------------------------------- + + template <> + bool write( TiXmlElement *pElement, VController *pObject ) + { + // Write Properties. + if ( !writeProperties( pElement, pObject ) ) + { + return false; + } + + // Write Data Table. + if ( !pObject->writeDataTable( pElement ) ) + { + return false; + } + + // Write Objects. + return writeObjects( pElement, pObject ); + } + + template <> + bool read( TiXmlElement *pElement, VController *pObject ) + { + // Read Properties. + if ( !readProperties( pElement, pObject ) ) + { + // Invalid Properties. + return false; + } + + // Read Data Table. + if ( !pObject->readDataTable( pElement ) ) + { + // Invalid Data Table. + return false; + } + + // Read Objects. + if ( !readObjects( pElement, pObject ) ) + { + // Invalid Read. + return false; + } + + // Valid Read. + return true; + } + + //----------------------------------------------------------------------------- + // + // VObject + // + //----------------------------------------------------------------------------- + + template <> + bool write( TiXmlElement *pElement, VObject *pObject ) + { + // Create Element. + TiXmlElement *objectElement = new TiXmlElement( "VObject" ); + pElement->LinkEndChild( objectElement ); + + // Attributes. + objectElement->SetAttribute( "Type", pObject->getClassName() ); + + // Write Properties. + if ( !writeProperties( objectElement, pObject ) ) + { + return false; + } + + // Write Objects. + return writeObjects( objectElement, pObject ); + } + + template <> + bool read( TiXmlElement *pElement, VObject *pObject ) + { + // Read Properties. + if ( !readProperties( pElement, pObject ) ) + { + // Invalid Properties. + return false; + } + + // Set Name Unique. + pObject->setLabelUnique( pObject->getLabel() ); + + // Read Objects. + if ( !readObjects( pElement, pObject ) ) + { + // Invalid Objects. + return false; + } + +#ifdef VT_EDITOR + // Callback. + Con::executef( pObject, "onRead" ); +#endif + + // Valid Read. + return true; + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Core/Persistence/VPersistence.h b/Engine/modules/Verve/Core/Persistence/VPersistence.h new file mode 100644 index 000000000..6c357681d --- /dev/null +++ b/Engine/modules/Verve/Core/Persistence/VPersistence.h @@ -0,0 +1,286 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPERSISTENCE_H_ +#define _VT_VPERSISTENCE_H_ + +#ifndef TINYXML_INCLUDED +#include "tinyxml/tinyxml.h" +#endif + +#ifndef _SIMOBJECT_H_ +#include "console/simObject.h" +#endif + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- + +namespace VPersistence +{ + static const char *VSFVersionString = "0.0.0a"; + + // This object is used to filter fields which belong to SimObject's. + // There is no need to serialize these fields, so they are skipped + // entirely. + static SimObject DummySimObject; + + //------------------------------------------------------------------------- + + template bool writeFile( const char* pFileName, T *pObject ) + { + // Create Doc. + TiXmlDocument xmlDocument; + TiXmlDeclaration *xmlDeclaration = new TiXmlDeclaration( "1.0", "", "" ); + xmlDocument.LinkEndChild( xmlDeclaration ); + + // Create Root. + TiXmlElement *xmlRoot = new TiXmlElement( "VerveControllerSequence" ); + xmlDocument.LinkEndChild( xmlRoot ); + + // Write Version. + xmlRoot->SetAttribute( "Version", VSFVersionString ); + + // Write Object. + if ( !write( xmlRoot, pObject ) ) + { + Con::errorf( "VPersistence::writeFile() - Unable to Write Object." ); + return false; + } + + // Save File. + return xmlDocument.SaveFile( pFileName ); + }; + + template bool write( TiXmlElement *pElement, T *pObject ); + + template bool writeProperties( TiXmlElement *pElement, T *pObject ) + { + const AbstractClassRep::FieldList &fieldList = pObject->getFieldList(); + const AbstractClassRep::Field *field = NULL; + + // Create Property Root. + TiXmlElement *propertyRoot = new TiXmlElement( "Properties" ); + pElement->LinkEndChild( propertyRoot ); + + const S32 fieldCount = fieldList.size(); + for ( S32 i = 0; i < fieldCount; i++ ) + { + field = &fieldList[i]; + + if ( field->type >= AbstractClassRep::ARCFirstCustomField ) + { + // Ignore Special Fields. + continue; + } + + // Fetch the Field Name. + const char *fieldName = field->pFieldname; + // SimObject Field? + if ( DummySimObject.findField( fieldName ) != NULL ) + { + // Skip SimObject Fields. + continue; + } + + // Fetch the Field Value. + const char *fieldValue = ( *field->getDataFn )( pObject, Con::getData( field->type, ( void * ) ( ( ( const char * )pObject ) + field->offset ), 0, field->table, field->flag ) ); + + if ( fieldValue ) + { + // Create Element. + TiXmlElement *propertyElement = new TiXmlElement( fieldName ); + + // Apply Value. + propertyElement->InsertEndChild( TiXmlText( fieldValue ) ); + + // Add. + propertyRoot->LinkEndChild( propertyElement ); + } + } + + // Valid Write. + return true; + }; + + template bool writeObjects( TiXmlElement *pElement, T *pObject ) + { + for ( ITreeNode *node = pObject->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + // Write Group. + if ( !write( pElement, ( VObject* )node ) ) + { + // Invalid Write. + return false; + } + } + + // Valid Write. + return true; + } + + //------------------------------------------------------------------------- + + template bool readFile( const char* pFileName, T *pObject ) + { + TiXmlDocument xmlDocument; + if ( !xmlDocument.LoadFile( pFileName ) ) + { + Con::errorf( "VPersistence::readFile() - Unable to load file '%s'.", pFileName ); + return false; + } + + TiXmlElement *rootElement = xmlDocument.RootElement(); + if ( !rootElement ) + { + Con::errorf( "VPersistence::readFile() - Invalid Document '%s'.", pFileName ); + return false; + } + + const char *docVersion = rootElement->Attribute( "Version" ); + if ( !docVersion || dStrcmp( VSFVersionString, docVersion ) != 0 ) + { + Con::errorf( "VPersistence::readFile() - Invalid file version." ); + return false; + } + + // Read Object. + if ( !read( rootElement, pObject ) ) + { + // Invalid Read. + return false; + } + + // Valid. + return true; + }; + + template bool read( TiXmlElement *pElement, T *pObject ); + + template bool readProperties( TiXmlElement *pElement, T *pObject ) + { + TiXmlElement *propertyRoot = pElement->FirstChildElement( "Properties" ); + if ( propertyRoot ) + { + for ( TiXmlElement *child = propertyRoot->FirstChildElement(); child != NULL; child = child->NextSiblingElement() ) + { + // Get Field Data. + const char *fieldName = child->Value(); + const char *fieldValue = child->GetText(); + + if ( !fieldValue ) + { + // Clear Value. + pObject->setField( fieldName, "" ); + } + else + { + // Apply Field Value. + if ( !pObject->setField( fieldName, fieldValue ) ) + { + // Invalid. + Con::warnf( "VPersistence::readProperties() - Invalid property '%s'", fieldName ); + } + } + } + } + + // Valid Read. + return true; + }; + + template bool readObjects( TiXmlElement *pElement, T *pObject ) + { + for ( TiXmlElement *child = pElement->FirstChildElement( "VObject" ); child != NULL; child = child->NextSiblingElement( "VObject" ) ) + { + // Get Object Type. + const char *type = child->Attribute( "Type" ); + if ( !type || !AbstractClassRep::findClassRep( type ) ) + { + // Invalid Type. + Con::errorf( "VController::readObjects() - Invalid object type specified '%s'.", ( ( type ) ? type : "NULL" ) ); + + // Invalid Read. + return false; + } + + // Create Object. + VObject *object = dynamic_cast( ConsoleObject::create( type ) ); + +#ifdef VT_EDITOR + // Register SimObject. + if ( !object->registerObject() ) + { + // Delete. + delete object; + + // Invalid Read. + return false; + } +#endif + + // Add Reference. + object->addTo( pObject ); + +#ifdef VT_EDITOR + // Valid Method? + if ( object->isMethod( "onAdd" ) ) + { + // Callback. + const char *retValue = Con::executef( object, "onAdd" ); + if ( !dAtob( retValue ) ) + { + // Delete. + object->deleteObject(); + + // Invalid Read. + return false; + } + } +#endif + + // Read Object. + if ( !read( child, object ) ) + { +#ifdef VT_EDITOR + // Delete. + object->deleteObject(); +#else + // Delete. + delete object; +#endif + + // Invalid Read. + return false; + } + } + + // Valid Read. + return true; + }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPERSISTENCE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/Util/VSharedEnum.cpp b/Engine/modules/Verve/Core/Util/VSharedEnum.cpp new file mode 100644 index 000000000..b4825de3f --- /dev/null +++ b/Engine/modules/Verve/Core/Util/VSharedEnum.cpp @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VSharedEnum.h" + +//----------------------------------------------------------------------------- + +// Implement the Action enum list. +ImplementEnumType( VActionToggle, "" ) + { VSharedEnum::k_ActionTurnOn, "ON" }, + { VSharedEnum::k_ActionTurnOff, "OFF" }, +EndImplementEnumType; \ No newline at end of file diff --git a/Engine/modules/Verve/Core/Util/VSharedEnum.h b/Engine/modules/Verve/Core/Util/VSharedEnum.h new file mode 100644 index 000000000..73df682d8 --- /dev/null +++ b/Engine/modules/Verve/Core/Util/VSharedEnum.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAREDENUM_H_ +#define _VT_VSHAREDENUM_H_ + +#ifndef _DYNAMIC_CONSOLETYPES_H_ +#include "console/dynamicTypes.h" +#endif + +namespace VSharedEnum +{ + enum eActionToggle + { + k_ActionTurnOn, + k_ActionTurnOff, + }; +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VSharedEnum::eActionToggle VActionToggle; + +// Declare Enum Types. +DefineEnumType( VActionToggle ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAREDENUM_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VController.cpp b/Engine/modules/Verve/Core/VController.cpp new file mode 100644 index 000000000..5352f64cd --- /dev/null +++ b/Engine/modules/Verve/Core/VController.cpp @@ -0,0 +1,1160 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Core/VObject.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "Verve/Extension/Director/VDirectorGroup.h" + +#include "console/consoleObject.h" +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VController ); +//----------------------------------------------------------------------------- + +VController::VController( void ) : + mStatus( ( k_StatusInit | k_StatusStopped ) ), + mTime( 0 ), + mLastTime( 0 ), + mTimeScale( 1.f ), + mDuration( 5000 ), + mLoop( false ), + mLoopBackwards( false ), + mLoopCount( -1 ), + mLoopIndex( 0 ), + mLoopDelay( 0 ), + mLoopDelayTime( 0 ), + mJump( k_JumpInvalid ), + mJumpTime( 0 ), + mResetOnCompletion( true ) +{ + // Don't Process Ticks. + setProcessTicks( false ); +} + +VController::~VController( void ) +{ + // Void. +} + +void VController::initPersistFields( void ) +{ + addGroup( "Controller" ); + addProtectedField( "Time", TypeS32, Offset( mTime, VController ), &setTime, &defaultProtectedGetFn, "Current position of the Controller (in milliseconds)." ); + addProtectedField( "Duration", TypeS32, Offset( mDuration, VController ), &setDuration, &defaultProtectedGetFn, "Total length of the sequence (in milliseconds)." ); + addProtectedField( "TimeScale", TypeF32, Offset( mTimeScale, VController ), &setTimeScale, &defaultProtectedGetFn, "Speed of playback. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards. If |TimeScale| > 1.0, then playback will be faster than normal, while |TimeScale| < 1.0 will be slower." ); + + addField( "Loop", TypeBool, Offset( mLoop, VController ), "Instead of stopping once playback is complete, the Controller will reset and resume play." ); + addField( "LoopBackwards", TypeBool, Offset( mLoopBackwards, VController ), "When the sequence loops, reverse the direction of play." ); + addField( "LoopCount", TypeS32, Offset( mLoopCount, VController ), "The number of times the sequence loops before stopping. -1 will cause the sequence to loop indefinitely." ); + addField( "LoopDelay", TypeS32, Offset( mLoopDelay, VController ), "When the sequence loops, delay playback by this value (in milliseconds)." ); + + addField( "ResetOnCompletion", TypeBool, Offset( mResetOnCompletion, VController ), "When the sequence is completed, reset the state of the Controller." ); + endGroup( "Controller" ); + + // Parent Call. + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// ITickable Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::processTick(); +// +// This method controls the playback of the entire sequence. It integrates all +// of the groups and handles sequence looping and jumping. +// +//----------------------------------------------------------------------------- +void VController::processTick( void ) +{ + if ( mTimeScale == 0.f ) + { + // Pause. + pause(); + + // Exit. + return; + } + + // Calculate Delta. + const S32 time = Sim::getCurrentTime(); + S32 delta = ( time - mLastTime ); + mLastTime = time; + + // Reverse? + if ( mTimeScale < 0.f ) + { + // Negative Delta. + delta *= -1; + } + + if ( mLoopDelayTime > 0 ) + { + // Update Delay Time. + mLoopDelayTime -= getMin( mAbs( delta ), mLoopDelayTime ); + + // Exit. + return; + } + + // Jump Delta? + if ( mJump == k_JumpDelta ) + { + // Jump. + delta = mJumpTime; + + // Clear. + mJump = k_JumpInvalid; + mJumpTime = 0; + } + + if ( ( isPlayingForward() && ( mTime + delta ) > mDuration ) + || ( !isPlayingForward() && ( mTime + delta ) < 0 ) ) + { + // Clamp Delta. + delta = ( ( mTimeScale > 0.f ) * mDuration ) - mTime; + + // Note: If we are playing forwards, we're at the end of the + // sequence and we want to loop/reset the Controller, then we + // need to handle that now. + if ( delta == 0 ) + { + onPostTick(); + } + } + + // Valid Delta? + if ( delta == 0 ) + { + // Exit. + return; + } + + // Trigger Update. + mControllerUpdateSignal.trigger( mTime, delta ); + + // Update Time. + mTime += delta; + + // Perform Post Tick. + onPostTick(); +} + +//----------------------------------------------------------------------------- +// +// VController::onPostTick(); +// +// This method is called onces a tick has been processed. It will perform the +// the right checks to see if the Controller has finished playing. It also +// handles special cases like Looping or Resetting the Controller. +// +//----------------------------------------------------------------------------- +void VController::onPostTick( void ) +{ + // Jump Time? + if ( mJump == k_JumpTime ) + { + // Jump Post Update. + reset( mJumpTime ); + + // Clear. + mJump = k_JumpInvalid; + mJumpTime = 0; + } + + // Sequence Completed? + if ( isPlayingForward() && mTime >= mDuration + || !isPlayingForward() && mTime <= 0 ) + { + bool stopPlaying = true; + if ( mLoop ) + { + // Don't Stop. + stopPlaying = false; + + if ( mLoopBackwards ) + { + // Change Direction. + setTimeScale( -1.f * mTimeScale ); + } + else + { + // Reset Time. + reset(); + } + + if ( mLoopDelay > 0 ) + { + // Resume After Delay. + mLoopDelayTime = mLoopDelay; + } + + // At the Start of the Sequence? + if ( mTime <= 0 && mLoopCount >= 0 ) + { + // Stop Looping? + stopPlaying = ( ++mLoopIndex >= mLoopCount ); + } + + // Callback. + Con::executef( this, "onLoop" ); + + // Loop Signal. + postEvent( k_EventLoop ); + } + + // Stop? + if ( stopPlaying ) + { + // Stop Only. + stop( mResetOnCompletion ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::reset(); +// +// Reset the Controller to the start of the sequence. +// +//----------------------------------------------------------------------------- +void VController::reset( void ) +{ + // Reset. + reset( ( isPlayingForward() ) ? 0 : mDuration ); +} + +//----------------------------------------------------------------------------- +// +// VController::reset( pTime ); +// +// Reset the Controller to the target time. This is a very important method as +// it allows tracks and events to reset their state as well as prepare +// themselves for playback. +// +//----------------------------------------------------------------------------- +void VController::reset( const S32 &pTime ) +{ + // Reset Time. + mTime = pTime; + mLastTime = Sim::getCurrentTime(); + + // Reset Delay Time. + mLoopDelayTime = 0; + + // Post Event. + postEvent( k_EventReset ); +} + +//----------------------------------------------------------------------------- +// +// VController::play(); +// +// Start playing the sequence from the current time and execute a number of +// callbacks. +// +//----------------------------------------------------------------------------- +void VController::play( void ) +{ + if ( isPlaying() || mTime < 0 || mTime > mDuration ) + { + // Sanity! + return; + } + + // Reset Time. + mLastTime = Sim::getCurrentTime(); + + // Start Updating. + setProcessTicks( true ); + + if ( mStatus & k_StatusInit ) + { + // Init Signal. + postEvent( k_EventInit ); + + // Clear Init Status. + mStatus &= ~k_StatusInit; + } + + // Update Status. + updateStatus( k_StatusPlaying ); + + // Play Signal. + postEvent( k_EventPlay ); + + // Callback. + Con::executef( this, "onPlay" ); +} + +//----------------------------------------------------------------------------- +// +// VController::play( pTime ); +// +// Start playing the sequence from the desired time. +// +//----------------------------------------------------------------------------- +void VController::play( const S32 &pTime ) +{ + // Reset. + reset( pTime ); + + // Play. + play(); +} + +//----------------------------------------------------------------------------- +// +// VController::pause(); +// +// Cease playback of the sequence, but maintain the current time. +// +//----------------------------------------------------------------------------- +void VController::pause( void ) +{ + // Stop Updating. + setProcessTicks( false ); + + // Update Status. + updateStatus( k_StatusPaused ); + + // Pause Signal. + postEvent( k_EventPause ); + + // Callback. + Con::executef( this, "onPause" ); +} + +//----------------------------------------------------------------------------- +// +// VController::stop( pReset ); +// +// Stop playback altogether and reset the Controller to the start of the +// sequence. +// +//----------------------------------------------------------------------------- +void VController::stop( const bool &pReset ) +{ + // Stop Updating. + setProcessTicks( false ); + + // Reset Loop Index. + mLoopIndex = 0; + + // Update Status. + updateStatus( ( k_StatusInit | k_StatusStopped ) ); + + // Reset? + if ( pReset ) + { + // Reset. + reset(); + } + + // Stop Signal. + postEvent( k_EventStop ); + + // Callback. + Con::executef( this, "onStop" ); +} + +//----------------------------------------------------------------------------- +// +// VController::jump(); +// +// Jump the Controller time forward 1 tick (32ms). +// +//----------------------------------------------------------------------------- +void VController::jump( void ) +{ + // Jump 1 tick. + jump( k_JumpDelta, ( isPlayingForward() ) ? TickMs : -TickMs ); +} + +//----------------------------------------------------------------------------- +// +// VController::jump( pType, pDelta ); +// +// Jump the Controller time by the target Delta. +// +//----------------------------------------------------------------------------- +void VController::jump( const eControllerJumpType &pType, const S32 &pDelta ) +{ + // Jump. + mJump = pType; + mJumpTime = pDelta; +} + +//----------------------------------------------------------------------------- +// +// VController::updateStatus( pStatus ); +// +// Clear the regular playback states and add the updated state. +// +//----------------------------------------------------------------------------- +void VController::updateStatus( const S32 &pStatus ) +{ + // Clear Playback Status. + mStatus &= ~( k_StatusPlaying | k_StatusPaused | k_StatusStopped ); + + // Add New Status. + mStatus |= pStatus; +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::getObject( pLabel ); +// +// Returns the group with the given name. If no group belongs to the Controller +// with that name, then a NULL value is returned. +// +//----------------------------------------------------------------------------- +VGroup *VController::getObject( const String &pLabel ) +{ + VGroup *node = ( VGroup* )mChildNode; + while ( node ) + { + // Compare Names. + if ( node->getLabel().equal( pLabel, String::NoCase ) ) + { + // Valid. + return node; + } + + // Next Sibling. + node = ( VGroup* )node->mSiblingNextNode; + } + + // Invalid. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VController::getDirectorGroup(); +// +// Returns the DirectorGroup reference if the Controller has a one. +// +//----------------------------------------------------------------------------- +VDirectorGroup *VController::getDirectorGroup( void ) +{ + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + if ( VDirectorGroup *group = dynamic_cast( node ) ) + { + // Return Group. + return group; + } + } + + // Invalid Group. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VController::getDirectorTrack(); +// +// Returns the DirectorTrack reference if the DirectorGroup has one. +// +//----------------------------------------------------------------------------- +VDirectorTrack *VController::getDirectorTrack( void ) +{ + VDirectorGroup *group = getDirectorGroup(); + if ( !group ) + { + // Invalid Track. + return NULL; + } + + // Return Track. + return group->getDirectorTrack(); +} + +//----------------------------------------------------------------------------- +// +// VController::getDataValue( pFieldName, *pValue ); +// +// Returns true if the field is a DataTable member and can be correctly +// evaluated. If this is the case, then pValue will contain the result. +// +//----------------------------------------------------------------------------- +bool VController::getDataValue( const String &pFieldName, String &pValue ) +{ + return mDataTable.getValue( this, pFieldName, pValue ); +} + +//----------------------------------------------------------------------------- +// +// VController::clearData(); +// +// Clear the contents of the DataTable entirely. +// +//----------------------------------------------------------------------------- +void VController::clearData( void ) +{ + while ( mDataTable.getCount() > 0 ) + { + // Clear Item. + clearData( 0 ); + } +} + +//----------------------------------------------------------------------------- +// +// VController::clearData( pIndex ); +// +// Clear the DataTable entry with the given index. +// +//----------------------------------------------------------------------------- +void VController::clearData( const S32 &pIndex ) +{ + VDataTable::sDataItem data; + if ( mDataTable.getItem( pIndex, &data ) ) + { + // Clear Data. + clearData( data.FieldName ); + } +} + +//----------------------------------------------------------------------------- +// +// VController::clearData( pIndex ); +// +// Clear the DataTable entry with the given field name. +// +//----------------------------------------------------------------------------- +void VController::clearData( const String &pFieldName ) +{ + // Clear Dynamic Field. + setDataField( pFieldName, NULL, "" ); + + // Clear Item. + mDataTable.clear( pFieldName ); +} + +//----------------------------------------------------------------------------- +// +// VController::sort(); +// +// Sort each track in each of the child groups. +// +//----------------------------------------------------------------------------- +void VController::sort( void ) +{ + for ( ITreeNode *group = mChildNode; group != NULL; group = group->mSiblingNextNode ) + { + for ( ITreeNode *track = group->mChildNode; track != NULL; track = track->mSiblingNextNode ) + { + // Sort Track. + ( ( VTrack* )track )->sort(); + } + } +} + +//----------------------------------------------------------------------------- +// +// Write Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::writeDataTable( pElement ); +// +// Write the DataTable out to a TinyXML document. +// +//----------------------------------------------------------------------------- +bool VController::writeDataTable( TiXmlElement *pElement ) +{ + // Create Data Table Root. + TiXmlElement *dataTableRoot = new TiXmlElement( "DataTable" ); + pElement->LinkEndChild( dataTableRoot ); + + for ( VDataTable::VDataMap::Iterator itr = mDataTable.mDataMap.begin(); itr != mDataTable.mDataMap.end(); ++itr ) + { + // Fetch Data. + VDataTable::sDataItem *data = &itr->value; + + // Create Element. + TiXmlElement *dataElement = new TiXmlElement( "DataItem" ); + + // Apply Attributes. + dataElement->SetAttribute( "Type", VDataTable::getDataTypeDescription( data->Type ) ); + dataElement->SetAttribute( "Name", data->FieldName ); + dataElement->SetAttribute( "Value", getDataField( StringTable->insert( data->FieldName.c_str() ), NULL ) ); + + // Add. + dataTableRoot->LinkEndChild( dataElement ); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Read Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::readDataTable( pElement ); +// +// Read the DataTable from a TinyXML document. +// +//----------------------------------------------------------------------------- +bool VController::readDataTable( TiXmlElement *pElement ) +{ + TiXmlElement *dataTableRoot = pElement->FirstChildElement( "DataTable" ); + if ( dataTableRoot ) + { + for ( TiXmlElement *child = dataTableRoot->FirstChildElement(); child != NULL; child = child->NextSiblingElement() ) + { + // Get Field Data. + const char *fieldType = child->Attribute( "Type" ); + const char *fieldName = child->Attribute( "Name" ); + const char *fieldValue = child->Attribute( "Value" ); + + // Add Data Item. + mDataTable.insert( VDataTable::getDataTypeEnum( fieldType ), fieldName ); + + // Set Field Value. + setDataField( StringTable->insert( fieldName ), NULL, fieldValue ); + } + } + + // Valid Read. + return true; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::postEvent( pEvent ); +// +// Process an event signal to all event subscribers. This method is used to +// signal changes in the Controller's status. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +void VController::postEvent( const eControllerEventType &pEvent ) +{ + // Signal Event. + mControllerEventSignal.trigger( pEvent ); +} + +//----------------------------------------------------------------------------- +// +// VController::setTimeScale( pTimeScale ); +// +// Set the speed of playback. In effect, a value of 0.5 will double the real +// time taken to complete the playback of the sequence, while a value of 2.0 +// will halve the time needed. +// +//----------------------------------------------------------------------------- +void VController::setTimeScale( const F32 &pTimeScale ) +{ + // Need an Update? + const bool update = ( pTimeScale != 0.f && ( mTimeScale == 0.f || ( ( mTimeScale > 0.f ) != ( pTimeScale > 0.f ) ) ) ); + + // Store. + mTimeScale = pTimeScale; + + // Update $timeScale Variable. + Con::setFloatVariable( "timeScale", mFabs( mTimeScale ) ); + + if ( update ) + { + // Reset. + reset( mTime ); + } +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VController, readFile, bool, 3, 3, "( string pFileName ) - Clears the object and loads the new data from the given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Buffer the FileName. + // Note: This is done because the arg variables can be altered during any + // Callbacks or Console Methods called while clearing the Controller. + char fileName[1024]; + dStrcpy( fileName, argv[2] ); + + // Clear Sequence Lists. + object->clear(); + + // Clear Data Table. + object->clearData(); + + // Read Target File. + if ( !VPersistence::readFile( fileName, object ) ) + { + // Re-Clear. + object->clear(); + + // Invalid Read. + return false; + } + + // Initial Sort. + object->sort(); + + // Reset. + object->reset(); + + // Valid Read. + return true; +} + +ConsoleMethod( VController, clear, void, 2, 2, "( void ) - Detaches and deletes all of the child objects.\n" + "@return No return value." ) +{ + // Clear Sequence Lists. + object->clear(); + + // Clear Data Table. + object->clearData(); +} + +ConsoleMethod( VController, reset, void, 2, 3, "( [int pTime] ) - Reset the Controller's and child object's state.\n" + "@param pTime The target time to reset to.\n" + "@return No return value." ) +{ + if ( argc >= 3 ) + { + // Reset Sequence. + object->reset( dAtoi( argv[2] ) ); + return; + } + + // Default Reset. + object->reset(); +} + +ConsoleMethod( VController, isPlaying, bool, 2, 2, "( void ) - Is the sequence currently playing?\n" + "@return Returns true if the Controller is playing." ) +{ + // Is Playing? + return ( object->isPlaying() ); +} + +ConsoleMethod( VController, play, void, 2, 3, "( [int pTime] ) - Play the sequence. If a value for pTime is specified, the Controller is reset and played from that time.\n" + "@param pTime The time to start playing the sequence from.\n" + "@return No return value." ) +{ + S32 startTime = object->getTime(); + if ( argc >= 3 ) + { + startTime = dAtoi( argv[2] ); + } + + // Play From Specified Time. + object->play( startTime ); +} + +ConsoleMethod( VController, step, void, 2, 2, "( void ) - Step forward one frame.\n" + "@return No return value." ) +{ + if ( object->isPlaying() ) + { + // Sanity! + return; + } + + // Play. + object->play( object->getTime() ); + + // Jump. + object->jump(); + + // Step Forward One Frame. + object->processTick(); + + // Stop. + object->stop( false ); +} + +ConsoleMethod( VController, isPaused, bool, 2, 2, "( void ) - Is the sequence currently paused?\n" + "@return Returns true if the Controller is paused." ) +{ + // Is Paused? + return ( object->isPaused() ); +} + +ConsoleMethod( VController, pause, void, 2, 2, "( void ) - Pause the sequence. Playback can resume by calling VController::play().\n" + "@return No return value." ) +{ + // Pause Sequence. + object->pause(); +} + +ConsoleMethod( VController, isStopped, bool, 2, 2, "( void ) - Is the sequence currently stopped?\n" + "@return Returns true if the Controller is stopped." ) +{ + // Is Stopped? + return ( object->isStopped() ); +} + +ConsoleMethod( VController, stop, void, 2, 3, "( [bool pReset] ) - Stop the sequence and optionally reset it.\n" + "@param pReset Reset the Controller after stopping.\n" + "@return No return value." ) +{ + // Stop Sequence. + object->stop( ( argc == 3 ) ? dAtob( argv[2] ) : true ); +} + +ConsoleMethod( VController, getTimeScale, F32, 2, 2, "( void ) - Get the playback speed. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards.\n" + "@return Playback Speed." ) +{ + // Get Time Scale. + return object->getTimeScale(); +} + +ConsoleMethod( VController, setTimeScale, void, 3, 3, "( float pTimeScale ) - Set the playback speed. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards. If |pTimeScale| > 1.0, then playback will be faster than normal, while |pTimeScale| < 1.0 will be slower.\n" + "@param pTimeScale Playback speed.\n" + "@return No return value." ) +{ + // Set Time Scale. + object->setTimeScale( dAtof( argv[2] ) ); +} + +ConsoleMethod( VController, isDataField, bool, 3, 3, "( string pFieldName ) - Is the field a member of the Data Table?\n" + "@param pFieldName The name of the dynamic field you wish to check.\n" + "@return Returns true if the field is a member of the Data Table." ) +{ + if ( argv[2][0] == '\0' ) + { + return false; + } + + // Is Field. + return object->getDataTable().getItem( argv[2] ); +} + +ConsoleMethod( VController, getDataFieldCount, S32, 2, 2, "( void ) - Get the number of data elements in the Data Table.\n" + "@return Returns the size of the Data Table." ) +{ + // Return Count. + return object->getDataTable().getCount(); +} + +ConsoleMethod( VController, getDataFieldName, const char *, 3, 3, "( int pIndex ) - Get the name of the field given by the passed index.\n" + "@param pIndex The index of the data field you wish to check.\n" + "@return Returns the name of the field corresponding to the given index." ) +{ + VDataTable::sDataItem data; + if ( !object->getDataTable().getItem( dAtoi( argv[2] ), &data ) || data.Type == VDataTable::k_TypeInvalid ) + { + // Invalid Field. + return ""; + } + + // Return Field Name. + return data.FieldName; +} + +ConsoleMethod( VController, getDataFieldValue, const char *, 3, 3, "( string pFieldName ) - Get the evaluated data from the data field.\n" + "@param pFieldName The name of the field you wish to evaluate.\n" + "@return Returns the evaluated data from the field." ) +{ + String fieldValue; + if ( object->getDataValue( argv[2], fieldValue ) ) + { + // Create Buffer. + char *buffer = Con::getReturnBuffer( 256 ); + dStrcpy( buffer, fieldValue.c_str() ); + + // Return Value. + return buffer; + } + + // Return NULL. + return "0"; +} + +ConsoleMethod( VController, getDataFieldType, const char *, 3, 3, "( string pFieldName ) - Get the type of data for the given field.\n" + "@param pFieldName The name of the field you wish to check.\n" + "@return Returns the data type." ) +{ + VDataTable::sDataItem data; + if ( !object->getDataTable().getItem( argv[2], &data ) || data.Type == VDataTable::k_TypeInvalid ) + { + // Invalid Field. + return ""; + } + + // Return Field Type. + return VDataTable::getDataTypeDescription( data.Type ); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VController, writeFile, bool, 3, 3, "( string pFileName ) - Save to a given filename.\n" + "@param pFileName The target file to write to.\n" + "@return Returns true if the write was successful." ) +{ + // Write Target File. + return VPersistence::writeFile( argv[2], object ); +} + +ConsoleMethod( VController, readTemplate, bool, 3, 3, "( string pFileName ) - Load data from given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Read Target File. + return VPersistence::readFile( argv[2], object ); +} + +ConsoleMethod( VController, getCount, S32, 2, 2, "( void ) - Get the number of child objects.\n" + "@return Returns the number of child objects." ) +{ + // Size. + return object->size(); +} + +ConsoleMethod( VController, getObject, S32, 3, 3, "( int pIndex ) - Get the object corresponding to the given index.\n" + "@param pIndex The index of the object you wish to retrieve.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->at( dAtoi( argv[2] ) ); + + // Return Group ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +ConsoleMethod( VController, addObject, void, 3, 3, "( SimObject pObject ) - Add a child object to this node.\n" + "@param pObject The SimObjectID of the object to be added to this node.\n" + "@return No return value." ) +{ + VObject *child = dynamic_cast( Sim::findObject( argv[2] ) ); + if ( child ) + { + // Add Child. + child->addTo( object ); + } +} + +ConsoleMethod( VController, removeObject, void, 3, 3, "( SimObject pObject ) - Remove the target object from this node.\n" + "@param pObject The SimObjectID of the object to be removed from this node.\n" + "@return No return value." ) +{ + VObject *child = dynamic_cast( Sim::findObject( argv[2] ) ); + if ( child && child->getParent() == object ) + { + child->remove(); + } +} + +ConsoleMethod( VController, sortGroups, void, 2, 2, "( void ) - Sort Groups by their Labels.\n" + "@return No return value." ) +{ + // Ensure that the Director Group is the First Group. + VDirectorGroup *directorGroup = object->getDirectorGroup(); + if ( directorGroup && directorGroup != object->mChildNode ) + { + // Detach. + directorGroup->remove(); + + // Add to the Front of the Controller. + directorGroup->addToFront( object ); + } + + const S32 count = object->size(); + for ( S32 j = 0; j < count; j++ ) + { + ITreeNode *node = object->mChildNode; + if ( dynamic_cast( node ) != NULL ) + { + // Skip Director Group. + node = node->mSiblingNextNode; + } + + for ( ; node != NULL; node = node->mSiblingNextNode ) + { + VGroup *groupA = ( VGroup* )node; + VGroup *groupB = ( VGroup* )node->mSiblingNextNode; + if ( !groupB ) + { + // No Node. + break; + } + + // Swap? + if ( dStrcmp( groupA->getLabel(), groupB->getLabel() ) > 0 ) + { + // Get Outer Siblings. + ITreeNode *prevNode = groupA->mSiblingPrevNode; + ITreeNode *nextNode = groupB->mSiblingNextNode; + + if ( groupA->mParentNode && groupA->mParentNode->mChildNode == groupA ) + { + // New Child Node. + groupA->mParentNode->mChildNode = groupB; + } + + // + // Move A. + + groupA->mSiblingPrevNode = groupB; + groupA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = groupA; + } + + // + // Move B. + + groupB->mSiblingPrevNode = prevNode; + groupB->mSiblingNextNode = groupA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = groupB; + } + } + } + } +} + +ConsoleMethod( VController, sortTracks, void, 2, 2, "( void ) - Sort Tracks by their Labels.\n" + "@return No return value." ) +{ + for ( ITreeNode *group = object->mChildNode; group != NULL; group = group->mSiblingNextNode ) + { + const S32 count = ( ( VGroup* )group )->size(); + for ( S32 j = 0; j < count; j++ ) + { + for ( ITreeNode *node = group->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VTrack *trackA = ( VTrack* )node; + VTrack *trackB = ( VTrack* )node->mSiblingNextNode; + if ( !trackB ) + { + // No Node. + break; + } + + // Swap? + if ( dStrcmp( trackA->getLabel(), trackB->getLabel() ) > 0 ) + { + // Get Outer Siblings. + ITreeNode *prevNode = trackA->mSiblingPrevNode; + ITreeNode *nextNode = trackB->mSiblingNextNode; + + if ( trackA->mParentNode && trackA->mParentNode->mChildNode == trackA ) + { + // New Child Node. + trackA->mParentNode->mChildNode = trackB; + } + + // + // Move A. + + trackA->mSiblingPrevNode = trackB; + trackA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = trackA; + } + + // + // Move B. + + trackB->mSiblingPrevNode = prevNode; + trackB->mSiblingNextNode = trackA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = trackB; + } + } + } + } + } +} + +ConsoleMethod( VController, addDataField, void, 4, 4, "( string pFieldType, string pFieldName ) - Add a new data entry to the Data Table.\n" + "@param pFieldType The method of evaluating the field's data.\n" + "@param pFieldName The name of the field to be added to the Data Table.\n" + "@return No return value." ) +{ + // Insert Data. + object->getDataTable().insert( VDataTable::getDataTypeEnum( argv[2] ), argv[3] ); +} + +ConsoleMethod( VController, removeDataField, void, 3, 3, "( string pFieldName ) - Remove a data entry from the Data Table.\n" + "@param pFieldName The name of the field to be removed from the Data Table.\n" + "@return No return value." ) +{ + // Clear Data Item. + object->clearData( argv[2] ); +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VController.h b/Engine/modules/Verve/Core/VController.h new file mode 100644 index 000000000..f38a1cdf0 --- /dev/null +++ b/Engine/modules/Verve/Core/VController.h @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCONTROLLER_H_ +#define _VT_VCONTROLLER_H_ + +#ifndef _VT_VERVECONFIG_H_ +#include "Verve/VerveConfig.h" +#endif + +#ifndef _PLATFORM_H_ +#include "platform/platform.h" +#endif + +#ifndef _PROCESSLIST_H_ +#include "T3D/gameBase/processList.h" +#endif + +#ifndef _ITICKABLE_H_ +#include "core/iTickable.h" +#endif + +#ifndef _VT_VPERSISTENCE_H_ +#include "Verve/Core/Persistence/VPersistence.h" +#endif + +#ifndef _VT_VTREENODE_H_ +#include "Verve/Core/VTreeNode.h" +#endif + +#ifndef _VT_VDATATABLE_H_ +#include "Verve/Core/VDataTable.h" +#endif + +#ifndef _VT_TORQUE_CAMERA_H_ +#include "Verve/Torque/TCamera.h" +#endif + +//----------------------------------------------------------------------------- +class VObject; + +class VTrack; +class VEvent; +class VGroup; + +class VDirectorGroup; +class VDirectorTrack; + +typedef VectorPtr VTrackVector; +typedef VTrackVector::iterator VTrackIterator; + +typedef VectorPtr VEventVector; +typedef VEventVector::iterator VEventIterator; + +typedef VectorPtr VGroupVector; +typedef VGroupVector::iterator VGroupIterator; +//----------------------------------------------------------------------------- + +class VController : public SimObject, + public virtual ITickable, + public VTreeNode +{ + typedef SimObject Parent; + +public: + + enum eControllerStatus + { + k_StatusInit = BIT( 0 ), + + k_StatusPlaying = BIT( 1 ), + k_StatusPaused = BIT( 2 ), + k_StatusStopped = BIT( 3 ), + }; + + enum eControllerEventType + { + k_EventInit, + k_EventReset, + + k_EventPlay, + k_EventPause, + k_EventStop, + + k_EventLoop, + }; + + enum eControllerJumpType + { + k_JumpTime, + k_JumpDelta, + + k_JumpInvalid, + }; + + typedef Signal ControllerUpdateSignal; + typedef Signal ControllerEventSignal; + +private: + + // Data. + + VDataTable mDataTable; + + // Event Signal. + + ControllerUpdateSignal mControllerUpdateSignal; + ControllerEventSignal mControllerEventSignal; + + // Properties. + + S32 mStatus; + + S32 mTime; + U32 mLastTime; + S32 mDuration; + F32 mTimeScale; + + bool mLoop; + bool mLoopBackwards; + S32 mLoopCount; + S32 mLoopIndex; + S32 mLoopDelay; + S32 mLoopDelayTime; + + eControllerJumpType mJump; + S32 mJumpTime; + + bool mResetOnCompletion; + +public: + + VController(); + ~VController(); + + static void initPersistFields( void ); + + // ITickable. + + void interpolateTick( F32 pDelta ) { }; + void advanceTime( F32 pDelta ) { }; + void processTick( void ); + void onPostTick( void ); + + // Controller. + + void reset( void ); + void reset( const S32 &pTime ); + + void play( void ); + void play( const S32 &pTime ); + + void pause( void ); + void stop( const bool &pReset = true ); + + void jump( void ); + void jump( const eControllerJumpType &pType, const S32 &pDelta ); + + void updateStatus( const S32 &pStatus ); + + // Reference. + + VGroup *getObject( const String &pLabel ); + template inline bool getObject( const String &pLabel, T *&pObject ) + { + // Reference Group. + pObject = dynamic_cast( getObject( pLabel ) ); + + // Valid? + return ( pObject != NULL ); + } + + bool getDataValue( const String &pFieldName, String &pValue ); + void clearData( void ); + void clearData( const S32 &pIndex ); + void clearData( const String &pFieldName ); + + void sort( void ); + + // Saving. + + bool writeDataTable( TiXmlElement *pElement ); + + // Reading. + + bool readDataTable( TiXmlElement *pElement ); + + // Console Declaration. + + DECLARE_CONOBJECT( VController ); + +public: + + inline VDataTable &getDataTable( void ) { return mDataTable; }; + + inline ControllerUpdateSignal &getControllerUpdateSignal( void ) { return mControllerUpdateSignal; }; + inline ControllerEventSignal &getControllerEventSignal( void ) { return mControllerEventSignal; }; + void postEvent( const eControllerEventType &pEvent ); + + VDirectorGroup *getDirectorGroup( void ); + VDirectorTrack *getDirectorTrack( void ); + + inline void setTime( const S32 &pTime ) { mTime = pTime; }; + inline void setDuration( const S32 &pDuration ) { mDuration = pDuration; }; + void setTimeScale( const F32 &pTimeScale ); + + inline bool isLooping( void ) { return mLoop; }; + inline bool isPlaying( void ) { return ( mStatus & k_StatusPlaying ); }; + inline bool isPaused( void ) { return ( mStatus & k_StatusPaused ); }; + inline bool isStopped( void ) { return ( mStatus & k_StatusStopped ); }; + inline bool isPlayingForward( void ) { return ( mTimeScale > 0.f ); }; + + inline S32 getTime( void ) { return mTime; }; + inline S32 getDuration( void ) { return mDuration; }; + inline F32 getTimeScale( void ) { return mTimeScale; }; + inline S32 getLoopDelayTime( void ) { return mLoopDelayTime; }; + +protected: + + static bool setTime( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setTime( dAtoi( pData ) ); return false; }; + static bool setDuration( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setDuration( dAtoi( pData ) ); return false; }; + static bool setTimeScale( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setTimeScale( dAtof( pData ) ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VDataTable.cpp b/Engine/modules/Verve/Core/VDataTable.cpp new file mode 100644 index 000000000..5f9046428 --- /dev/null +++ b/Engine/modules/Verve/Core/VDataTable.cpp @@ -0,0 +1,254 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VDataTable.h" + +#include "console/simObject.h" + +//----------------------------------------------------------------------------- + +// Implement the DataType enum list. +ImplementEnumType( VDataTableDataType, "" ) + { VDataTable::k_TypeExpression, "EXPRESSION" }, + { VDataTable::k_TypeStatic, "STATIC" }, + { VDataTable::k_TypeVariable, "VARIABLE" }, +EndImplementEnumType; + +VDataTable::eDataType VDataTable::getDataTypeEnum( const char *pLabel ) +{ + VDataTable::eDataType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VDataTable::k_TypeInvalid; + } + + // Return. + return out; +} + +const char *VDataTable::getDataTypeDescription( const VDataTable::eDataType pEnum ) +{ + // Return. + return castConsoleTypeToString( pEnum ); +} + +//----------------------------------------------------------------------------- + +VDataTable::VDataTable( void ) +{ + mDataMap.clear(); +} + +VDataTable::~VDataTable( void ) +{ + mDataMap.clear(); +} + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDataTable::insert( pType, pFieldName ); +// +// Add a DataTable entry, referencing the field name and assign it the given +// data type. +// +// For a full list of possible data types, see the 'eDataType' declaration in +// VDataTable.h. +// +//----------------------------------------------------------------------------- +void VDataTable::insert( eDataType pType, const String &pFieldName ) +{ + if ( mDataMap.contains( pFieldName ) ) + { + // Change Field Type. + mDataMap.find( pFieldName )->value.Type = pType; + + // Return. + return; + } + + // Insert Item. + mDataMap.insert( pFieldName, sDataItem( pType, pFieldName ) ); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::clear( pFieldName ); +// +// Clear the DataTable entry with the given field name. +// +//----------------------------------------------------------------------------- +void VDataTable::clear( const String &pFieldName ) +{ + // Clear Item. + mDataMap.erase( pFieldName ); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::clear(); +// +// Clear the contents of the DataTable entirely. +// +//----------------------------------------------------------------------------- +void VDataTable::clear( void ) +{ + // Clear. + mDataMap.clear(); +} + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDataTable::getCount(); +// +// Return the number of DataTable entries. +// +//----------------------------------------------------------------------------- +S32 VDataTable::getCount( void ) +{ + return mDataMap.size(); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getItem( pIndex, *pDataItem ); +// +// Return the item with the given index. This method will return false if there +// is no valid data entry with that index. +// +//----------------------------------------------------------------------------- +bool VDataTable::getItem( const S32 &pIndex, sDataItem *pDataItem ) +{ + if ( pIndex < 0 || pIndex >= mDataMap.size() ) + { + // Invalid Field. + return false; + } + + S32 index = 0; + for ( VDataMap::Iterator itr = mDataMap.begin(); itr != mDataMap.end(); ++itr ) + { + if ( index == pIndex ) + { + if ( pDataItem ) + { + // Store Reference. + *pDataItem = ( itr->value ); + } + + // Valid Field. + return true; + } + + // Increment. + ++index; + } + + // Invalid Field. + return false; +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getItem( pFieldName, *pDataItem ); +// +// Return the item with the given field name. This method will return false if +// there is no valid data entry with that name. +// +//----------------------------------------------------------------------------- +bool VDataTable::getItem( const String &pFieldName, sDataItem *pDataItem ) +{ + if ( mDataMap.contains( pFieldName ) ) + { + if ( pDataItem ) + { + // Fetch Item + *pDataItem = mDataMap.find( pFieldName )->value; + } + + // Valid Field. + return true; + } + + // Invalid Field. + return false; +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getValue( pObject, pFieldName, *pValue ); +// +// Evaluate and return the expression provided in the data field. +// +//----------------------------------------------------------------------------- +bool VDataTable::getValue( SimObject *pObject, const String &pFieldName, String &pValue ) +{ + if ( !pObject || pFieldName.isEmpty() ) + { + // Sanity! + return false; + } + + // Fetch Data. + sDataItem *data = &( mDataMap.find( pFieldName )->value ); + if ( !data ) + { + // No Field. + return false; + } + + // Field Value. + const char *fieldValue = pObject->getDataField( StringTable->insert( data->FieldName ), NULL ); + + switch ( data->Type ) + { + case VDataTable::k_TypeExpression : + { + + // Evaluate. + pValue = Con::evaluate( fieldValue, false ); + + } break; + + case VDataTable::k_TypeStatic : + { + // Use Value. + pValue = fieldValue; + + } break; + + case VDataTable::k_TypeVariable : + { + + // Fetch Variable. + pValue = Con::getVariable( fieldValue ); + + } break; + } + + // Valid Field. + return true; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VDataTable.h b/Engine/modules/Verve/Core/VDataTable.h new file mode 100644 index 000000000..6b4cba90a --- /dev/null +++ b/Engine/modules/Verve/Core/VDataTable.h @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDATATABLE_H_ +#define _VT_VDATATABLE_H_ + +#ifndef CORE_TDICTIONARY_H +#include "core/util/tDictionary.h" +#endif + +#ifndef _CONSOLE_H_ +#include "console/console.h" +#endif + +#ifndef _DYNAMIC_CONSOLETYPES_H_ +#include "console/dynamicTypes.h" +#endif + +#ifndef _STRINGTABLE_H_ +#include "core/stringTable.h" +#endif + +//----------------------------------------------------------------------------- + +class VDataTable +{ +public: + + enum eDataType + { + k_TypeExpression, + k_TypeStatic, + k_TypeVariable, + + k_TypeInvalid, + }; + + struct sDataItem + { + eDataType Type; + String FieldName; + + sDataItem( void ) : + Type( k_TypeInvalid ), + FieldName( String::EmptyString ) + { + // Void. + }; + + sDataItem( eDataType pType, const String &pFieldName ) : + Type( pType ), + FieldName( pFieldName ) + { + // Void. + }; + }; + + // Enum Lookup. + static VDataTable::eDataType getDataTypeEnum( const char *pLabel ); + static const char *getDataTypeDescription( const VDataTable::eDataType pEnum ); + + // Map Type. + typedef Map VDataMap; + +public: + + VDataMap mDataMap; + +public: + + VDataTable( void ); + ~VDataTable( void ); + + // Data. + + void insert( eDataType pType, const String &pFieldName ); + void clear( const String &pFieldName ); + void clear( void ); + + // Reference. + + S32 getCount( void ); + bool getItem( const S32 &pIndex, sDataItem *pDataItem = NULL ); + bool getItem( const String &pFieldName, sDataItem *pDataItem = NULL ); + + bool getValue( SimObject *pObject, const String &pFieldName, String &pValue ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VDataTable::eDataType VDataTableDataType; + +// Declare Enum Types. +DefineEnumType( VDataTableDataType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VDATATABLE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VEvent.cpp b/Engine/modules/Verve/Core/VEvent.cpp new file mode 100644 index 000000000..6b4e8ed54 --- /dev/null +++ b/Engine/modules/Verve/Core/VEvent.cpp @@ -0,0 +1,406 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VEvent.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEvent ); +//----------------------------------------------------------------------------- + +VEvent::VEvent( void ) : + mIsPlaying( false ), + mTriggered( false ), + mTriggerTime( 0 ), + mDuration( 0 ) +{ + setLabel( "DefaultEvent" ); +} + +void VEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "TriggerTime", TypeS32, Offset( mTriggerTime, VEvent ), &setTriggerTime, &defaultProtectedGetFn, "The time that this event is triggered." ); + addProtectedField( "Duration", TypeS32, Offset( mDuration, VEvent ), &setDuration, &defaultProtectedGetFn, "The total duration that this event plays for." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::onControllerReset( pTime, pForward ); +// +// Reset the status of the event. If the given time is between the event's +// start and finish times, then the isPlaying flag will be true. This means +// that the event is free to be triggered upon playback. +// +//----------------------------------------------------------------------------- +void VEvent::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Reset Status. + mIsPlaying = ( pTime > mTriggerTime && pTime < ( mTriggerTime + mDuration ) ); + mTriggered = false; +} + +//----------------------------------------------------------------------------- +// +// VEvent::onControllerUpdate( pTime, pDelta ) +// +// Integrate is only called when this event is the Next Event for the parent +// track. For each track, there is only ever *one* event being integrated - the +// event that needs to be triggered next. +// +// If the event has a duration greater than 0, then this event will continue to +// integrate until its time is up, or the controller finishes playing +// (whichever happens first). +// +// If a value of true is returned, then this event will continue to integrate +// until a value of false is returned to the parent track. When this happens, +// this event ceases to be the track's Next Event and will not continue +// updating. +// +//----------------------------------------------------------------------------- +bool VEvent::onControllerUpdate( const S32 &pTime, const S32 &pDelta ) +{ + if ( !isEnabled() ) + { + return false; + } + + const S32 newTime = ( pTime + pDelta ); + const S32 &startTime = getStartTime(); + const S32 &finishTime = getFinishTime(); + + if ( !mIsPlaying || !mTriggered ) + { + if ( !mIsPlaying ) + { + if ( ( pDelta > 0 && newTime < startTime ) + || ( pDelta < 0 && newTime > startTime ) ) + { + // Not Time to Trigger. + return true; + } + + if ( ( pDelta > 0 && pTime > startTime ) + || ( pDelta < 0 && pTime < startTime ) ) + { + //AssertFatal( false, "VEvent::onControllerUpdate() - Event has been skipped." ); + return false; + } + } + + if ( !mTriggered ) + { + // Play and Trigger. + mIsPlaying = ( mDuration > 0 ); + mTriggered = true; + + // Callback. + onTrigger( pTime, pDelta ); + + if ( mDuration == 0 ) + { + // Stop Integrating. + return false; + } + + // Return Here. + // Note: If Duration is non-zero this event will continue to update + // so that VEvent:: onUpdate is processed for the full event + // duration. + return ( mDuration != 0 ); + } + } + + // Complete? + const bool isComplete = ( ( pDelta > 0 && newTime > finishTime ) + || ( pDelta < 0 && newTime < finishTime ) ); + + if ( !isComplete ) + { + // Callback. + onUpdate( pTime, pDelta ); + } + else + { + // Complete. + mIsPlaying = false; + + // Callback. + onComplete( pTime, pDelta ); + } + + // Continue? + return !isComplete; +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::onTrigger( pTime, pDelta ); +// +// This method is called when an event is due to be triggered. This method is +// meant to be overloaded by derived classes. +// +// For examples of what an event might do, please refer to some of the included +// events with Verve. +// +//----------------------------------------------------------------------------- +void VEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// VEvent::onUpdate( pTime, pDelta ); +// +// This method is called each tick once an event has been triggered and ceases +// to be called when it is completed. This method is meant to be overloaded by +// derived classes. +// +//----------------------------------------------------------------------------- +void VEvent::onUpdate( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// VEvent::onComplete( pTime, pDelta ); +// +// This method is called once an event has finished being updated. It is not +// called on events that have a duration of 0. This method is meant to be +// overloaded by derived classes. +// +//----------------------------------------------------------------------------- +void VEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::getGroup(); +// +// Returns the parent group. +// +//----------------------------------------------------------------------------- +VGroup *VEvent::getGroup( void ) +{ + VTrack *track = getTrack(); + if ( track ) + { + return track->getGroup(); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VEvent::getTrack(); +// +// Returns the parent track. +// +//----------------------------------------------------------------------------- +VTrack *VEvent::getTrack( void ) +{ + return dynamic_cast( mParentNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getNextEvent(); +// +// Returns the next event. +// +//----------------------------------------------------------------------------- +VEvent *VEvent::getNextEvent( void ) +{ + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( mSiblingPrevNode ); + } + + return dynamic_cast( mSiblingNextNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getPreviousEvent(); +// +// Returns the previous event. +// +//----------------------------------------------------------------------------- +VEvent *VEvent::getPreviousEvent( void ) +{ + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( mSiblingNextNode ); + } + + return dynamic_cast( mSiblingPrevNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getStartTime(); +// +// Returns the time, in milliseconds, that the event is due to trigger. +// +//----------------------------------------------------------------------------- +S32 VEvent::getStartTime( void ) +{ + return ( mTriggerTime + ( !isControllerPlayingForward() * mDuration ) ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getFinishTime(); +// +// Returns the time, in milliseconds, that the event will cease updating. +// +//----------------------------------------------------------------------------- +S32 VEvent::getFinishTime( void ) +{ + return ( mTriggerTime + ( isControllerPlayingForward() * mDuration ) ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::setTriggerTime( pTime ); +// +// Apply the given trigger time to the object. +// +// If the project was built using the VT_EDITOR preprocessor argument, then +// the validity of the passed value is verified. It also cannot be changed +// while the controller is playing. +// +//----------------------------------------------------------------------------- +void VEvent::setTriggerTime( const S32 &pTime ) +{ +#ifdef VT_EDITOR + + VTrack *track = getTrack(); + if ( !track ) + { + // Apply Time. + mTriggerTime = pTime; + + return; + } + + if ( track->isControllerPlaying() ) + { + // Don't Change While Playing. + return; + } + + /* + // Check For Overlap. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *event = ( VEvent* )node; + if ( event == this ) + { + // Skip. + continue; + } + + const U32 startTime = getStartTime(); + const U32 finishTime = getFinishTime(); + + if ( ( pTime > startTime && pTime < finishTime ) + || ( ( pTime + mDuration ) > startTime && ( pTime + mDuration ) < finishTime ) + || ( pTime < startTime && ( pTime + mDuration ) > finishTime ) ) + { + // Overlap! + return; + } + } + */ + + // Apply Time. + mTriggerTime = mClamp( pTime, 0, getControllerDuration() ); + + // Sort Events. + track->sort(); + + // Reset Track. + track->onControllerReset( getControllerTime(), isControllerPlayingForward() ); + +#else + + // Apply Time. + mTriggerTime = pTime; + +#endif +} + +//----------------------------------------------------------------------------- +// +// VEvent::setDuration( pDuration ); +// +// Apply the given duration time to the object. +// +// If the project was built using the VT_EDITOR preprocessor argument, then +// the validity of the passed value is verified. It also cannot be changed +// while the controller is playing. +// +//----------------------------------------------------------------------------- +void VEvent::setDuration( const S32 &pDuration ) +{ +#ifdef VT_EDITOR + + if ( isControllerPlaying() ) + { + // Don't Change While Playing. + return; + } + +#endif + + // Apply Duration. + mDuration = pDuration; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VEvent.h b/Engine/modules/Verve/Core/VEvent.h new file mode 100644 index 000000000..7a1914f04 --- /dev/null +++ b/Engine/modules/Verve/Core/VEvent.h @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEVENT_H_ +#define _VT_VEVENT_H_ + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- +class VGroup; +class VTrack; +//----------------------------------------------------------------------------- + +class VEvent : public VObject +{ + typedef VObject Parent; + +protected: + + bool mIsPlaying; + bool mTriggered; + + S32 mTriggerTime; + S32 mDuration; + +public: + + VEvent( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + virtual bool onControllerUpdate( const S32 &pTime, const S32 &pDelta ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onUpdate( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEvent ); + +public: + + // Property Methods. + + VGroup *getGroup( void ); + template inline bool getGroup( T *&pGroup ) + { + // Reference Group. + pGroup = dynamic_cast( getGroup() ); + // Validate. + return ( pGroup != NULL ); + } + + VTrack *getTrack( void ); + template inline bool getTrack( T *&pTrack ) + { + // Reference Track. + pTrack = dynamic_cast( getTrack() ); + // Validate. + return ( pTrack != NULL ); + } + + VEvent *getNextEvent( void ); + VEvent *getPreviousEvent( void ); + + inline bool isPlaying( void ) { return mIsPlaying; }; + inline S32 getTriggerTime( void ) { return mTriggerTime; }; + inline S32 getDuration( void ) { return mDuration; }; + + virtual S32 getStartTime( void ); + virtual S32 getFinishTime( void ); + + virtual void setTriggerTime( const S32 &pTime ); + virtual void setDuration( const S32 &pDuration ); + + static bool setTriggerTime( void *obj, const char *pArray, const char *data ) { static_cast( obj )->setTriggerTime( dAtoi( data ) ); return false; }; + static bool setDuration( void *obj, const char *pArray, const char *data ) { static_cast( obj )->setDuration( dAtoi( data ) ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VGroup.cpp b/Engine/modules/Verve/Core/VGroup.cpp new file mode 100644 index 000000000..274d93775 --- /dev/null +++ b/Engine/modules/Verve/Core/VGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VGroup ); +//----------------------------------------------------------------------------- + +VGroup::VGroup( void ) +{ + setLabel( "DefaultGroup" ); +}; \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VGroup.h b/Engine/modules/Verve/Core/VGroup.h new file mode 100644 index 000000000..35d40dc4f --- /dev/null +++ b/Engine/modules/Verve/Core/VGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VGROUP_H_ +#define _VT_VGROUP_H_ + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VGroup : public VObject +{ + typedef VObject Parent; + +public: + + VGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VObject.cpp b/Engine/modules/Verve/Core/VObject.cpp new file mode 100644 index 000000000..c10c3dcdc --- /dev/null +++ b/Engine/modules/Verve/Core/VObject.cpp @@ -0,0 +1,483 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VObject.h" +#include "Verve/Core/VController.h" +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VObject ); +//----------------------------------------------------------------------------- + +VObject::VObject( void ) : + mController( NULL ), + mLabel( String::EmptyString ), + mEnabled( true ) +{ + // Void. +}; + +VObject::~VObject( void ) +{ + // Remove. + remove(); +} + +void VObject::initPersistFields( void ) +{ + // Don't Use Parent Fields. + // Parent::initPersistFields(); + + addProtectedField( "Enabled", TypeBool, Offset( mEnabled, VObject ), &setEnabled, &defaultProtectedGetFn, "Enable or Disable the object from playback." ); + addProtectedField( "Label", TypeRealString, Offset( mLabel, VObject ), &setLabel, &defaultProtectedGetFn, "The label this object is referenced by." ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::getObject( pLabel ); +// +// Returns the object with the given label. If no object belongs to this object +// with that label, then a NULL value is returned. +// +//----------------------------------------------------------------------------- +VObject *VObject::getObject( const String &pLabel ) +{ + VObject *node = ( VObject* )mChildNode; + while ( node ) + { + // Compare Names. + if ( node->getLabel().equal( pLabel, String::NoCase ) ) + { + // Valid. + return node; + } + + // Next Sibling. + node = ( VObject* )node->mSiblingNextNode; + } + + // Invalid. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::isEnabled(); +// +// Returns whether this object is enabled. +// +//----------------------------------------------------------------------------- +bool VObject::isEnabled( void ) +{ + VObject *parent = dynamic_cast( getParent() ); + if ( parent && !parent->isEnabled() ) + { + return false; + } + + return mEnabled; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPlaying(); +// +// Returns whether the root controller is currently playing. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPlaying( void ) +{ + if ( getController() ) + { + return getController()->isPlaying(); + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPaused(); +// +// Returns whether the root controller is currently paused. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPaused( void ) +{ + if ( getController() ) + { + return getController()->isPaused(); + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerStopped(); +// +// Returns whether the root controller is currently stopped. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerStopped( void ) +{ + if ( getController() ) + { + return getController()->isStopped(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPlayingForward(); +// +// Returns whether the root controller is currently playing forward. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPlayingForward( void ) +{ + if ( getController() ) + { + return getController()->isPlayingForward(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerLooping(); +// +// Returns whether the root controller is looping the sequence. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerLooping( void ) +{ + if ( getController() ) + { + return getController()->isLooping(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerTime(); +// +// Returns the current time of the root controller. +// +//----------------------------------------------------------------------------- +S32 VObject::getControllerTime( void ) +{ + if ( getController() ) + { + return getController()->getTime(); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerTimeScale(); +// +// Returns the current timescale of the root controller. +// +//----------------------------------------------------------------------------- +F32 VObject::getControllerTimeScale( void ) +{ + if ( getController() ) + { + return getController()->getTimeScale(); + } + + return 1.f; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerDuration(); +// +// Returns the duration of the root controller. +// +//----------------------------------------------------------------------------- +S32 VObject::getControllerDuration( void ) +{ + if ( getController() ) + { + return getController()->getDuration(); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VObject::setLabel( pLabel ); +// +// Set the label property. +// +// If the project was built using the VT_EDITOR preprocessor argument, then the +// label will not be changed if the target name is already used in the parent +// object. +// +//----------------------------------------------------------------------------- +void VObject::setLabel( const String &pLabel ) +{ +#ifdef VT_EDITOR + if ( mParentNode ) + { + // Empty Label? + if ( mLabel.isEmpty() ) + { + // Set Uniqu Label. + setLabelUnique( pLabel ); + return; + } + + for ( VObject *walk = ( VObject* )mChildNode; walk != NULL; walk = ( VObject* )walk->mSiblingNextNode ) + { + if ( walk != this ) + { + if ( pLabel == walk->getLabel() ) + { + // Exit. + return; + } + } + } + } +#endif + + // Set Label. + mLabel = pLabel; +} + +//----------------------------------------------------------------------------- +// +// VObject::setLabelUnique( pLabel ); +// +// If the label that has been passed is already in use, then a new label will +// be generated by appending an index to the label. For example: MyLabel +// becomes MyLabel0 ... MyLabelN +// +//----------------------------------------------------------------------------- +void VObject::setLabelUnique( const String &pLabel ) +{ + if ( mParentNode && pLabel.isNotEmpty() ) + { + for ( VObject *walk = ( VObject* )mChildNode; walk != NULL; walk = ( VObject* )walk->mSiblingNextNode ) + { + if ( walk != this ) + { + if ( pLabel == walk->getLabel() ) + { + // Strip Trailing Number. + S32 i = -1; + String labelBase( String::GetTrailingNumber( pLabel, i ) ); + i++; + + // Construct New Name. + String labelBuffer = String::ToString( "%s%d", labelBase.c_str(), i ); + + // Set Name. + setLabelUnique( labelBuffer ); + + // Exit. + return; + } + } + } + } + + // Set Name. + mLabel = pLabel; +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::onAttach(); +// +// Callback made when this object is attached to another node. +// +//----------------------------------------------------------------------------- +void VObject::onAttach( void ) +{ + VTreeNode::onAttach(); + + // Store Controller. + mController = dynamic_cast( getRoot() ); + +#ifdef VT_EDITOR + if ( isProperlyAdded() ) + { + Con::executef( this, "onAttach" ); + } +#endif +} + +//----------------------------------------------------------------------------- +// +// VObject::onDetach(); +// +// Callback made when this object is detached from a parent node. +// +//----------------------------------------------------------------------------- +void VObject::onDetach( void ) +{ + VTreeNode::onDetach(); + + // Clear Controller. + mController = NULL; + +#ifdef VT_EDITOR + if ( isProperlyAdded() ) + { + Con::executef( this, "onDetach" ); + } +#endif +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VObject, writeFile, bool, 3, 3, "( string pFileName ) - Save to a given filename.\n" + "@param pFileName The target file to write to.\n" + "@return Returns true if the write was successful." ) +{ + // Write Target File. + return VPersistence::writeFile( argv[2], object ); +} + +ConsoleMethod( VObject, readFile, bool, 3, 3, "( string pFileName ) - Clears the object and loads the new data from the given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Read Target File. + return VPersistence::readFile( argv[2], object ); +} + +ConsoleMethod( VObject, getRoot, S32, 2, 2, "( void ) - Get the root object.\n" + "@return Returns the SimObjectId for the root object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->getRoot(); + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +ConsoleMethod( VObject, getParent, S32, 2, 2, "( void ) - Get the parent object.\n" + "@return Returns the SimObjectId for the parent object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->mParentNode; + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +ConsoleMethod( VObject, getIndex, S32, 2, 2, "( void ) - Get the index of this object relative to its siblings.\n" + "@return Returns the index of this object." ) +{ + return object->getIndex(); +} + +ConsoleMethod( VObject, getCount, S32, 2, 2, "( void ) - Get the number of child objects.\n" + "@return Returns the number of child objects." ) +{ + return object->size(); +} + +ConsoleMethod( VObject, getObject, S32, 3, 3, "( int pIndex ) - Get the object corresponding to the given index.\n" + "@param pIndex The index of the object you wish to retrieve.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->at( dAtoi( argv[2] ) ); + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +ConsoleMethod( VObject, clear, void, 2, 2, "( void ) - Detaches and deletes all of the child objects.\n" + "@return No return value." ) +{ + // Clear Sequence Lists. + object->clear(); +} + +ConsoleMethod( VObject, addObject, void, 3, 3, "( SimObject pObject ) - Add a child object to this node.\n" + "@param pObject The SimObjectID of the object to be added to this node.\n" + "@return No return value." ) +{ + VObject *child = dynamic_cast( Sim::findObject( argv[2] ) ); + if ( child ) + { + child->addTo( object ); + } +} + +ConsoleMethod( VObject, removeObject, void, 3, 3, "( SimObject pObject ) - Remove the target object from this node.\n" + "@param pObject The SimObjectID of the object to be removed from this node.\n" + "@return No return value." ) +{ + VObject *child = dynamic_cast( Sim::findObject( argv[2] ) ); + if ( child && child->getParent() == object ) + { + child->remove(); + } +} + +ConsoleMethod( VObject, setLabelUnique, void, 3, 3, "( string pLabel ) - Force this label to be unique.\n" + "@param pLabel The name you wish to reference this object by.\n" + "@return No return value." ) +{ + // Set Label. + object->setLabelUnique( argv[2] ); +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VObject.h b/Engine/modules/Verve/Core/VObject.h new file mode 100644 index 000000000..a4fe22f18 --- /dev/null +++ b/Engine/modules/Verve/Core/VObject.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VOBJECT_H_ +#define _VT_VOBJECT_H_ + +#ifndef _VT_VERVECONFIG_H_ +#include "Verve/VerveConfig.h" +#endif + +#ifdef VT_EDITOR + #ifndef _SIMOBJECT_H_ + #include "console/simObject.h" + #endif + + #define VObjectRep SimObject +#else + #ifndef _CONSOLEOBJECT_H_ + #include "console/consoleObject.h" + #endif + + #define VObjectRep ConsoleObject +#endif + +#ifndef _VT_VTREENODE_H_ +#include "Verve/Core/VTreeNode.h" +#endif + +#ifndef TINYXML_INCLUDED +#include "tinyxml/tinyxml.h" +#endif + +//----------------------------------------------------------------------------- +class VController; +//----------------------------------------------------------------------------- + +class VObject : public VObjectRep, + public VTreeNode +{ + typedef VObjectRep Parent; + +protected: + + VController *mController; + + String mLabel; + bool mEnabled; + +public: + + VObject( void ); + virtual ~VObject( void ); + + static void initPersistFields( void ); + + // Reference Methods. + + VObject *getObject( const String &pLabel ); + template inline bool getObject( const String &pLabel, T *&pObject ) + { + // Reference Object. + pObject = dynamic_cast( getObject( pLabel ) ); + + // Valid? + return ( pObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VObject ); + +public: + + // Property Methods. + + inline VController *getController( void ) { return mController; }; + + inline const String &getLabel( void ) const { return mLabel; }; + bool isEnabled( void ); + + bool isControllerPlaying( void ); + bool isControllerPaused( void ); + bool isControllerStopped( void ); + bool isControllerPlayingForward( void ); + bool isControllerLooping( void ); + S32 getControllerTime( void ); + F32 getControllerTimeScale( void ); + S32 getControllerDuration( void ); + + virtual void setLabel( const String &pLabel ); + void setLabelUnique( const String &pLabel ); + inline void setEnabled( const bool &pEnabled ) { mEnabled = pEnabled; }; + + // Callback Methods. + + virtual void onAttach( void ); + virtual void onDetach( void ); + + // Static Methods. + + static bool setEnabled( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setEnabled( dAtob( pData ) ); return false; }; + static bool setLabel( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setLabel( pData ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VOBJECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VTrack.cpp b/Engine/modules/Verve/Core/VTrack.cpp new file mode 100644 index 000000000..6783faece --- /dev/null +++ b/Engine/modules/Verve/Core/VTrack.cpp @@ -0,0 +1,448 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VTrack.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VController.h" +#include "math/mMath.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VTrack ); +//----------------------------------------------------------------------------- + +VTrack::VTrack( void ) : + mNextEvent( NULL ) +{ + setLabel( "DefaultTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::onAttach(); +// +// This callback subscribes this object to the controller's event signal. +// +//----------------------------------------------------------------------------- +void VTrack::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller? + if ( getController() ) + { + // Subscribe to Updates. + getController()->getControllerUpdateSignal().notify( this, &VTrack::onControllerUpdate ); + + // Subscribe to Events. + getController()->getControllerEventSignal().notify( this, &VTrack::onControllerEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::onAttach(); +// +// This callback removes this object from the controller's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VTrack::onDetach( void ) +{ + // Valid Controller? + if ( getController() ) + { + // Remove Update Notification. + getController()->getControllerUpdateSignal().remove( this, &VTrack::onControllerUpdate ); + + // Remove Event Notification. + getController()->getControllerEventSignal().remove( this, &VTrack::onControllerEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerUpdate( pTime, pDelta ); +// +// The Next Event is integrated until has finished its execution. Once it has +// finished, the next event to be triggered becomes the Current Event. Doing +// this means that only one event is ever checked to see if it should be +// triggered. +// +//----------------------------------------------------------------------------- +void VTrack::onControllerUpdate( const S32 &pTime, const S32 &pDelta ) +{ + if ( !isEnabled() || !mNextEvent ) + { + // Don't Update. + return; + } + + // Update Next Event. + while ( !mNextEvent->onControllerUpdate( pTime, pDelta ) ) + { + // Next Event? + if ( !updateNextEvent() ) + { + // No Valid Events. + mNextEvent = NULL; + break; + } + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is reset the virtual method, onControllerReset is called. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VTrack::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { + case VController::k_EventReset : + { + + // Reset. + onControllerReset( getControllerTime(), isControllerPlayingForward() ); + + } break; + } + + // Continue Processing Events. + return true; +} + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerReset( pTime, pForward ); +// +// Reset the status of the track. The Next Event is allocated here. +// +//----------------------------------------------------------------------------- +void VTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Clear Next Event. + mNextEvent = NULL; + + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *event = ( VEvent* )node; + + // Reset Event. + event->onControllerReset( pTime, pForward ); + + if ( ( event->isPlaying() ) + || ( pForward && event->getTriggerTime() >= pTime ) ) + { + if ( !mNextEvent ) + { + // Use as Next Event. + mNextEvent = event; + } + } + else if ( !pForward && pTime >= event->getTriggerTime() ) + { + VEvent *nextEvent = ( VEvent* )node->mSiblingNextNode; + if ( !nextEvent || pTime < nextEvent->getTriggerTime() ) + { + // Use as Next Event. + mNextEvent = event; + } + } + } +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::sort(); +// +// Sort the track's events by the event's trigger time. +// +//----------------------------------------------------------------------------- +void VTrack::sort( void ) +{ + const S32 count = size(); + for ( S32 j = 0; j < count; j++ ) + { + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *eventA = ( VEvent* )node; + VEvent *eventB = ( VEvent* )node->mSiblingNextNode; + if ( !eventB ) + { + // No Node. + break; + } + + // Swap? + if ( eventA->getTriggerTime() > eventB->getTriggerTime() ) + { + // Get Outer Siblings. + ITreeNode *prevNode = eventA->mSiblingPrevNode; + ITreeNode *nextNode = eventB->mSiblingNextNode; + + if ( eventA->mParentNode && eventA->mParentNode->mChildNode == eventA ) + { + // New Child Node. + eventA->mParentNode->mChildNode = eventB; + } + + // + // Move A. + eventA->mSiblingPrevNode = eventB; + eventA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = eventA; + } + + // + // Move B. + + eventB->mSiblingPrevNode = prevNode; + eventB->mSiblingNextNode = eventA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = eventB; + } + } + } + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::updateNextEvent( pForward ); +// +// Point mNextEvent to the next valid event in the track's sequence. +// +//----------------------------------------------------------------------------- +bool VTrack::updateNextEvent( void ) +{ + if ( !mNextEvent ) + { + // Invalid Event. + return false; + } + + while ( ( mNextEvent = mNextEvent->getNextEvent() ) != NULL ) + { + if ( mNextEvent->isEnabled() ) + { + // Valid Event. + return true; + } + } + + // Invalid Event. + return false; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::getGroup(); +// +// Returns the Track's parent group. +// +//----------------------------------------------------------------------------- +VGroup *VTrack::getGroup( void ) +{ + return dynamic_cast( mParentNode ); +} + +//----------------------------------------------------------------------------- +// +// VTrack::getNextEvent(); +// +// Returns the Event that the Track is currently observing. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getNextEvent( void ) +{ + return mNextEvent; +} + +//----------------------------------------------------------------------------- +// +// VTrack::getCurrentEvent(); +// +// Returns the Event that the Track is currently observing and playing. This +// will only ever be non-null when the track is observing an Event that has a +// non-zero duration and has been triggered. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getCurrentEvent( void ) +{ + if ( mNextEvent && mNextEvent->isPlaying() ) + { + return mNextEvent; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VTrack::getPreviousEvent(); +// +// Returns the Event that the Track was last intergrating. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getPreviousEvent( void ) +{ + if ( mNextEvent ) + { + return mNextEvent->getPreviousEvent(); + } + + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( getChild() ); + } + + return dynamic_cast( getLastChild() ); +} + +//----------------------------------------------------------------------------- +// +// VTrack::calclateInterp( pTime ); +// +// This method returns the interp time between or within events. If the given +// time is between two events, the return time is: +// +// ( pTime - last_event_finish_time ) +// / ( next_event_start_time - last_event_finish_time ) +// +// If the given time is within an event, the return time is: +// +// ( pTime - event_start_time ) / ( event_duration ) +// +// The value returned here is between 0.0 and 1.0. +// +//----------------------------------------------------------------------------- +F32 VTrack::calculateInterp( S32 pTime ) +{ + if ( !isControllerPlayingForward() ) + { + return ( 1.f - _calculateInterp( pTime ) ); + } + + return _calculateInterp( pTime ); +} + +F32 VTrack::_calculateInterp( S32 pTime ) +{ + // Fetch Duration. + const S32 sequenceDuration = getControllerDuration(); + if ( sequenceDuration == 0 || pTime == sequenceDuration ) + { + // Sanity! + return 1.f; + } + + if ( !mChildNode ) + { + // Quick Interp. + return F32( pTime / sequenceDuration ); + } + + // Last Time. + S32 lastTime = 0; + + VEvent *walk = ( VEvent* )mChildNode; + while ( walk ) + { + const S32 startTime = walk->getStartTime(); + const S32 finishTime = walk->getFinishTime(); + + if ( pTime < startTime ) + { + return ( F32( pTime - lastTime ) / F32( startTime - lastTime ) ); + } + + // Update Last Time. + lastTime = startTime; + + if ( pTime < finishTime ) + { + return ( F32( pTime - lastTime ) / F32( finishTime - lastTime ) ); + } + + // Update Last Time. + lastTime = finishTime; + + // Fetch Next Node. + walk = ( VEvent* )walk->mSiblingNextNode; + } + + // Return. + return ( F32( pTime - lastTime ) / F32( sequenceDuration - lastTime ) ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VTrack.h b/Engine/modules/Verve/Core/VTrack.h new file mode 100644 index 000000000..eb2e576ce --- /dev/null +++ b/Engine/modules/Verve/Core/VTrack.h @@ -0,0 +1,123 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTRACK_H_ +#define _VT_VTRACK_H_ + +#ifndef _VT_VCONTROLLER_H_ +#include "Verve/Core/VController.h" +#endif + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +//----------------------------------------------------------------------------- +class VGroup; +//----------------------------------------------------------------------------- + +class VTrack : public VObject +{ + typedef VObject Parent; + +public: + + // Controller Members. + + VEvent *mNextEvent; + +public: + + VTrack(); + + // Tree Methods. + + virtual void onAttach( void ); + virtual void onDetach( void ); + + // Controller Methods. + + virtual void onControllerUpdate( const S32 &pTime, const S32 &pDelta ); + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Reference Methods. + + void sort( void ); + bool updateNextEvent( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VTrack ); + +public: + + // Property Methods. + + VGroup *getGroup( void ); + template inline bool getGroup( T *&pGroup ) + { + // Reference Group. + pGroup = dynamic_cast( getGroup() ); + // Validate. + return ( pGroup != NULL ); + } + + VEvent *getNextEvent( void ); + template inline bool getNextEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getNextEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + VEvent *getCurrentEvent( void ); + template inline bool getCurrentEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getCurrentEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + VEvent *getPreviousEvent( void ); + template inline bool getPreviousEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getPreviousEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + F32 calculateInterp( S32 pTime ); + F32 _calculateInterp( S32 pTime ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VTreeNode.cpp b/Engine/modules/Verve/Core/VTreeNode.cpp new file mode 100644 index 000000000..29f4fa076 --- /dev/null +++ b/Engine/modules/Verve/Core/VTreeNode.cpp @@ -0,0 +1,471 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VTreeNode.h" +#include "console/simObject.h" +#include "platform/platform.h" + +//----------------------------------------------------------------------------- + +VTreeNode::VTreeNode( void ) +{ + mParentNode = NULL; + mChildNode = NULL; + mSiblingPrevNode = NULL; + mSiblingNextNode = NULL; +} + +VTreeNode::~VTreeNode( void ) +{ + // Delete Children. + clear(); + + // Detach. + remove(); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTreeNode::clear(); +// +// Delete all child nodes. +// +//----------------------------------------------------------------------------- +void VTreeNode::clear( void ) +{ + if ( !mChildNode ) + { + return; + } + + while ( mChildNode ) + { + // Fetch Child Node. + ITreeNode *node = mChildNode; + + // Clear It. + node->clear(); + + // Detach It. + node->remove(); + + // Delete It. + SimObject *object = dynamic_cast( node ); + if ( object ) + { + object->deleteObject(); + } + else + { + delete node; + } + } +} + +//----------------------------------------------------------------------------- +// +// ITreeNode Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTreeNode::getRoot(); +// +// Returns the root object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getRoot( void ) +{ + ITreeNode *parent = this; + while ( parent->mParentNode ) + { + parent = parent->mParentNode; + } + + return parent; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getParent(); +// +// Returns the parent object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getParent( void ) +{ + return mParentNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getChild(); +// +// Returns the first child object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getChild( void ) +{ + return mChildNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getChild(); +// +// Returns the first child object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getLastChild( void ) +{ + // Any Nodes? + if ( !mChildNode ) + { + // Null. + return NULL; + } + + // Front Node. + ITreeNode *lastNode = mChildNode; + + // Fetch Last Node. + while ( lastNode->mSiblingNextNode ) + { + lastNode = lastNode->mSiblingNextNode; + } + + // Return. + return lastNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getPrevSibling(); +// +// Returns the previous object in the linked list. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getPrevSibling( void ) +{ + return mSiblingPrevNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getNextSibling(); +// +// Returns the next object in the linked list. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getNextSibling( void ) +{ + return mSiblingNextNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::size(); +// +// Returns the number of child objects. Only includes top level. +// +//----------------------------------------------------------------------------- +int VTreeNode::size( void ) +{ + int size = 0; + + ITreeNode *node = mChildNode; + while ( node ) + { + size++; + + node = node->mSiblingNextNode; + } + + return size; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::at( pIndex ); +// +// Returns the object at the given index. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::at( const int pIndex ) +{ + int index = 0; + + ITreeNode *node = mChildNode; + while ( node ) + { + if ( index++ == pIndex ) + { + return node; + } + + node = node->mSiblingNextNode; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getIndex(); +// +// Returns the index of the object in relation to the sibling nodes. +// +//----------------------------------------------------------------------------- +int VTreeNode::getIndex( void ) +{ + if ( !inTree() ) + { + // No Index. + return 0; + } + + ITreeNode *walk = NULL; + if ( mParentNode ) + { + walk = mParentNode->mChildNode; + } + else + { + walk = this; + while ( walk->mSiblingPrevNode ) + { + // Walk Up. + walk = walk->mSiblingPrevNode; + } + } + + for ( int i = 0; walk; walk = walk->mSiblingNextNode, i++ ) + { + if ( walk == this ) + { + return i; + } + } + + AssertFatal( false, "VTreeNode::getIndex() - Node List Broken?" ); + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::addTo( pNode ); +// +// Attach this node to the back of the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::addTo( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Already In Tree. + return; + } + + // Set Parent. + mParentNode = pNode; + + if ( !pNode->mChildNode ) + { + // Store Child Node. + pNode->mChildNode = this; + } + else + { + // Front Node. + ITreeNode *headNode = pNode->mChildNode; + + // Fetch Head Node. + while ( headNode->mSiblingNextNode ) + { + headNode = headNode->mSiblingNextNode; + } + + // Reference Next Node. + headNode->mSiblingNextNode = this; + + // Reference Previous Node. + mSiblingPrevNode = headNode; + } + + // Callback. + onAttach(); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::addToFront( pNode ); +// +// Attach this node to the front of the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::addToFront( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Already In Tree. + return; + } + + // Set Parent. + mParentNode = pNode; + + if ( !pNode->mChildNode ) + { + // Store Child Node. + pNode->mChildNode = this; + } + else + { + // First Node. + ITreeNode *childNode = pNode->mChildNode; + + // Reference Previous Node. + childNode->mSiblingPrevNode = this; + + // Reference Next Node. + mSiblingNextNode = childNode; + + // Store Child Node. + pNode->mChildNode = this; + } + + // Callback. + onAttach(); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::remove(); +// +// Detach this node from the current parent node. +// +//----------------------------------------------------------------------------- +void VTreeNode::remove( void ) +{ + if ( !inTree() ) + { + return; + } + + // Callback. + onDetach(); + + if ( mParentNode && mParentNode->mChildNode == this ) + { + // Update Parent Reference. + mParentNode->mChildNode = mSiblingNextNode; + } + + if ( mSiblingNextNode ) + { + // Update Previous Node. + mSiblingNextNode->mSiblingPrevNode = mSiblingPrevNode; + } + + if ( mSiblingPrevNode ) + { + // Update Next Node. + mSiblingPrevNode->mSiblingNextNode = mSiblingNextNode; + } + + // Remove References. + mParentNode = mSiblingPrevNode = mSiblingNextNode = NULL; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::moveTo( pNode ); +// +// Detach this node and attach it to the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::moveTo( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Remove from Tree. + remove(); + } + + // Add to tree. + addTo( pNode ); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::onAttach(); +// +// This method will be called when this node, or a parent node, is attached to +// a node. +// +//----------------------------------------------------------------------------- +void VTreeNode::onAttach( void ) +{ + // Notify Children. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + node->onAttach(); + } +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::onDetach(); +// +// This method will be called when this node, or a parent node, is detached. +// +//----------------------------------------------------------------------------- +void VTreeNode::onDetach( void ) +{ + // Notify Children. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + node->onDetach(); + } +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::inTree(); +// +// Returns true if the node is the a member of a node tree. +// +//----------------------------------------------------------------------------- +bool VTreeNode::inTree( void ) +{ + return !( mParentNode == NULL && + mSiblingPrevNode == NULL && + mSiblingNextNode == NULL ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Core/VTreeNode.h b/Engine/modules/Verve/Core/VTreeNode.h new file mode 100644 index 000000000..459e972ca --- /dev/null +++ b/Engine/modules/Verve/Core/VTreeNode.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTREENODE_H_ +#define _VT_VTREENODE_H_ + +#ifndef _VT_ITREENODE_H_ +#include "Verve/Core/ITreeNode.h" +#endif + +//----------------------------------------------------------------------------- + +class VTreeNode : public ITreeNode +{ + typedef ITreeNode Parent; + +public: + + VTreeNode( void ); + ~VTreeNode( void ); + + // Reference Methods. + + virtual void clear( void ); + + // ITreeNode Methods. + + virtual ITreeNode *getRoot( void ); + virtual ITreeNode *getParent( void ); + virtual ITreeNode *getChild( void ); + virtual ITreeNode *getLastChild( void ); + + virtual ITreeNode *getPrevSibling( void ); + virtual ITreeNode *getNextSibling( void ); + + virtual ITreeNode *at( const int pIndex ); + virtual int size( void ); + + virtual int getIndex( void ); + + virtual void addTo( ITreeNode *pNode ); + virtual void addToFront( ITreeNode *pNode ); + virtual void remove( void ); + virtual void moveTo( ITreeNode *pNode ); + + virtual void onAttach( void ); + virtual void onDetach( void ); + + virtual bool inTree( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTREENODE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.cpp b/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.cpp new file mode 100644 index 000000000..b40460871 --- /dev/null +++ b/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.cpp @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Animation/VShapeAnimationEvent.h" +#include "Verve/Extension/Animation/VShapeAnimationTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VShapeAnimationEvent ); +//----------------------------------------------------------------------------- + +VShapeAnimationEvent::VShapeAnimationEvent( void ) : + mAnimationData( String::EmptyString ), + mAutoDuration( true ) +{ + setLabel( "AnimationEvent" ); +} + +//----------------------------------------------------------------------------- + +void VShapeAnimationEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "AnimationData", TypeRealString, Offset( mAnimationData, VShapeAnimationEvent ), "The name of the Animation Sequence to play upon triggering." ); + addField( "AutoDuration", TypeBool, Offset( mAutoDuration, VShapeAnimationEvent ), "Force the Event's Duration to match the length of the Animation." ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::onTrigger( pTime, pDelta ); +// +// Play the desired animation. Also account for any offet in playtime, and +// timescale. +// +//----------------------------------------------------------------------------- +void VShapeAnimationEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::SceneObjectType *object = getSceneObject(); + VShapeAnimationTrack *track; + if ( !object || !getTrack( track ) ) + { + // Sanity! + return; + } + + // Play Animation. + VTorque::playAnimation( object, track->getThreadIndex(), mAnimationData ); + + // Set Position. + VTorque::setAnimationPosition( object, track->getThreadIndex(), getAnimationPosition( pTime + pDelta ) ); + + // Set Time Scale. + VTorque::setAnimationTimeScale( object, track->getThreadIndex(), ( ( pDelta > 0 ) ? 1.f : -1.f ) ); +} + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::onComplete( pTime, pDelta ); +// +// If the animation is cyclic, then it needs to be paused once the event has +// finished playing. +// +//----------------------------------------------------------------------------- +void VShapeAnimationEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + // Fetch Object. + VTorque::SceneObjectType *object = getSceneObject(); + VShapeAnimationTrack *track; + if ( object && VTorque::isAnimationLooping( object, mAnimationData ) && getTrack( track ) ) + { + // Pause Animation. + VTorque::pauseAnimation( object, track->getThreadIndex() ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::getAnimationPosition( pTime ); +// +// Returns the time that the animation should be positioned at, at the given +// time. This method considers whether the animation is cyclic or not and will +// return the appropriate time regardless. Time is expressed in seconds and not +// milliseconds. +// +//----------------------------------------------------------------------------- +F32 VShapeAnimationEvent::getAnimationPosition( const S32 &pTime ) +{ + // Fetch Object. + VSceneObjectTrack *track; + VTorque::SceneObjectType *object = getSceneObject(); + if ( !getTrack( track ) || !object ) + { + // Null. + return 0.f; + } + + // Fetch Interp. + F32 interp = track->calculateInterp( pTime ); + if ( !isControllerPlayingForward() ) + { + // Flip. + interp = ( 1.f - interp ); + } + + // Not Looping? + if ( !VTorque::isAnimationLooping( object, mAnimationData ) ) + { + // Return Interp. + return interp; + } + + // Fetch Sequence Duration. + const S32 duration = ( S32 )( 1000 * VTorque::getAnimationDuration( object, mAnimationData ) ); + + // Fetch Loop Interp. + const S32 loopInterp = S32( mDuration * interp ) % duration; + + return ( F32 )loopInterp / ( F32 )duration; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.h b/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.h new file mode 100644 index 000000000..9146836e9 --- /dev/null +++ b/Engine/modules/Verve/Extension/Animation/VShapeAnimationEvent.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAPEANIMATIONEVENT_H_ +#define _VT_VSHAPEANIMATIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_ANIMATION_H_ +#include "Verve/Torque/TAnimation.h" +#endif + +//----------------------------------------------------------------------------- + +class VShapeAnimationEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + bool mAutoDuration; + String mAnimationData; + +public: + + VShapeAnimationEvent( void ); + + static void initPersistFields( void ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VShapeAnimationEvent ); + +public: + + // Property Methods. + + F32 getAnimationPosition( const S32 &pTime ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAPEANIMATIONEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.cpp b/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.cpp new file mode 100644 index 000000000..d6f25764b --- /dev/null +++ b/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.cpp @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Animation/VShapeAnimationTrack.h" +#include "Verve/Extension/Animation/VShapeAnimationEvent.h" +#include "Verve/Core/VGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VShapeAnimationTrack ); +//----------------------------------------------------------------------------- + +VShapeAnimationTrack::VShapeAnimationTrack( void ) : + mThreadIndex( 0 ) +{ + setLabel( "AnimationTrack" ); +} + +//----------------------------------------------------------------------------- + +void VShapeAnimationTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "ThreadIndex", TypeS32, Offset( mThreadIndex, VShapeAnimationTrack ), "The index of the Animation Thread to play." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, or stops playing, then the animation will cease to +// play. If the controller resumes play, the animation will continue. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VShapeAnimationTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Play Animation. + VTorque::setAnimationTimeScale( getSceneObject(), mThreadIndex, ( ( isControllerPlayingForward() ) ? 1.f : -1.f ) ); + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Stop Animation. + VTorque::setAnimationTimeScale( getSceneObject(), mThreadIndex, 0.f ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VShapeAnimationTrack::onControllerReset( pTime, pForward ); +// +// Reset the animation state of the target object. If there is a Next Event, +// then the animation is positioned accordingly. +// +//----------------------------------------------------------------------------- +void VShapeAnimationTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + VTorque::SceneObjectType *object = getSceneObject(); + if ( !object ) + { + // Parent Call. + Parent::onControllerReset( pTime, pForward ); + return; + } + + VShapeAnimationEvent *event; + if ( getCurrentEvent( event ) ) + { + // Stop Animation. + VTorque::stopAnimation( object, mThreadIndex ); + } + + // Parent Call. + Parent::onControllerReset( pTime, pForward ); + + if ( getCurrentEvent( event ) ) + { + // Play Animation. + VTorque::playAnimation( object, mThreadIndex, event->mAnimationData ); + + // Set Position. + VTorque::setAnimationPosition( object, mThreadIndex, event->getAnimationPosition( pTime ) ); + + // Stop Animation. + VTorque::setAnimationTimeScale( object, mThreadIndex, 0.f ); + } +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VShapeAnimationTrack, updateTrack, void, 2, 2, "( void ) - Update the Track.\n" + "@return No return value." ) +{ + for ( ITreeNode *node = object->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VShapeAnimationEvent *currEvent = ( VShapeAnimationEvent* )node; + VShapeAnimationEvent *nextEvent = ( VShapeAnimationEvent* )node->mSiblingNextNode; + if ( !currEvent->mAutoDuration ) + { + // Skip. + continue; + } + + if ( VTorque::isAnimationLooping( object->getSceneObject(), currEvent->mAnimationData ) ) + { + if ( !nextEvent ) + { + // Update Duration. + currEvent->setDuration( object->getControllerDuration() - currEvent->getTriggerTime() ); + } + else + { + // Update Duration. + currEvent->setDuration( mAbs( nextEvent->getTriggerTime() - currEvent->getTriggerTime() ) ); + } + } + else + { + // Update Duration. + currEvent->setDuration( ( S32 )( 1000 * VTorque::getAnimationDuration( object->getSceneObject(), currEvent->mAnimationData ) ) ); + } + } +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.h b/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.h new file mode 100644 index 000000000..3b9cf7bce --- /dev/null +++ b/Engine/modules/Verve/Extension/Animation/VShapeAnimationTrack.h @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAPEANIMATIONTRACK_H_ +#define _VT_VSHAPEANIMATIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_ANIMATION_H_ +#include "Verve/Torque/TAnimation.h" +#endif + +//----------------------------------------------------------------------------- + +class VShapeAnimationTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + + U32 mThreadIndex; + +public: + + VShapeAnimationTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VShapeAnimationTrack ); + +public: + + inline U32 &getThreadIndex( void ) { return mThreadIndex; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAPEANIMATIONTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraGroup.cpp b/Engine/modules/Verve/Extension/Camera/VCameraGroup.cpp new file mode 100644 index 000000000..14b2cb97c --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraGroup.cpp @@ -0,0 +1,224 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraGroup.h" +#include "Verve/Extension/Camera/VCameraTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraGroup ); +//----------------------------------------------------------------------------- + +VCameraGroup *VCameraGroup::mActiveGroup = NULL; +VCameraGroup::CameraChangeSignal VCameraGroup::mCameraChangeSignal; + +//----------------------------------------------------------------------------- + +VCameraGroup::VCameraGroup( void ) +{ + setLabel( "CameraGroup" ); +}; + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onAttach(); +// +// This callback subscribes this object to the controller's event signal. +// +//----------------------------------------------------------------------------- +void VCameraGroup::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller? + if ( getController() ) + { + // Subscribe to Events. + getController()->getControllerEventSignal().notify( this, &VCameraGroup::onControllerEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onAttach(); +// +// This callback removes this object from the controller's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VCameraGroup::onDetach( void ) +{ + // Valid Controller? + if ( getController() ) + { + // Remove Event Notification. + getController()->getControllerEventSignal().remove( this, &VCameraGroup::onControllerEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VCameraGroup::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VCameraGroup::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { +#ifdef VT_EDITOR + case VController::k_EventPause : +#endif + case VController::k_EventStop : + { + + // Clear the Camera. + clearActiveGroup(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::setActive(); +// +// Set this Group to Active. +// +//----------------------------------------------------------------------------- +void VCameraGroup::setActive( void ) +{ + // Set Active. + setActiveGroup( this ); +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::clearActiveGroup(); +// +// Clear the Active Camera. +// +//----------------------------------------------------------------------------- +void VCameraGroup::clearActiveGroup( void ) +{ + if ( mActiveGroup ) + { + // Deactivate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventDeactivate ); + } + + // Store. + mActiveGroup = NULL; + + // Clear Camera Object. + VTorque::setCamera( NULL ); + + // Change Signal. + getCameraChangeSignal().trigger( NULL ); +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::setActiveGroup( pCameraGroup ); +// +// Change the current camera group. The actual camera object is the object that +// the group references. +// +// A NULL value of pCameraGroup will clear the active camera, which generally +// reverts to the connection's control object. The camera is also cleared when +// the Controller stops playing. +// +//----------------------------------------------------------------------------- +void VCameraGroup::setActiveGroup( VCameraGroup *pCameraGroup ) +{ + // Change Camera? + if ( pCameraGroup == mActiveGroup || + pCameraGroup && !pCameraGroup->isEnabled() ) + { + // Invalid Target. + return; + } + + if ( mActiveGroup ) + { + // Deactivate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventDeactivate ); + } + + // Store. + mActiveGroup = pCameraGroup; + + if ( mActiveGroup ) + { + // Set Camera Object. + VTorque::setCamera( mActiveGroup->getSceneObject() ); + + // Activate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventActivate ); + } + else + { + // Clear Camera Object. + VTorque::setCamera( NULL ); + } + + // Change Signal. + getCameraChangeSignal().trigger( mActiveGroup ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraGroup.h b/Engine/modules/Verve/Extension/Camera/VCameraGroup.h new file mode 100644 index 000000000..eea9a2f7b --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraGroup.h @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERAGROUP_H_ +#define _VT_VCAMERAGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +#ifndef _VT_VCONTROLLER_H +#include "Verve/Core/VController.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraGroup; + +//----------------------------------------------------------------------------- + +class VCameraGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + enum eCameraEventType + { + k_EventActivate, + k_EventDeactivate, + }; + + typedef Signal CameraEventSignal; + typedef Signal CameraChangeSignal; + +protected: + + static VCameraGroup *mActiveGroup; + static CameraChangeSignal mCameraChangeSignal; + + CameraEventSignal mCameraEventSignal; + +public: + + VCameraGroup( void ); + + // Tree Methods. + + void onAttach( void ); + void onDetach( void ); + + // Controller Methods. + + bool onControllerEvent( VController::eControllerEventType pEvent ); + + // Camera Methods. + + inline bool isActive( void ) { return ( bool )( this == getActiveGroup() ); }; + inline VCameraGroup *getActiveGroup( void ) { return mActiveGroup; }; + + void setActive( void ); + + static void clearActiveGroup( void ); + static void setActiveGroup( VCameraGroup *pCameraGroup ); + + // Signal Methods. + + static inline CameraChangeSignal &getCameraChangeSignal( void ) { return mCameraChangeSignal; }; + inline CameraEventSignal &getCameraEventSignal( void ) { return mCameraEventSignal; }; + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERAGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.cpp b/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.cpp new file mode 100644 index 000000000..88c528d27 --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.cpp @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Camera/VCameraGroup.h" +#include "Verve/Extension/Camera/VCameraShakeEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraShakeEvent ); +//----------------------------------------------------------------------------- + +VCameraShakeEvent::VCameraShakeEvent( void ) : + mAmplitude( Point3F::Zero ), + mFalloff( 10.f ), + mFrequency( Point3F::Zero ) +{ + // Clear Label. + setLabel( "CameraShakeEvent" ); +} + +void VCameraShakeEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Amplitude", TypePoint3F, Offset( mAmplitude, VCameraShakeEvent ), "Amplitude of the Camera Shake event." ); + addField( "Falloff", TypeF32, Offset( mFalloff, VCameraShakeEvent ), "Falloff of the Camera Shake event." ); + addField( "Frequency", TypePoint3F, Offset( mFrequency, VCameraShakeEvent ), "Frequency of the Camera Shake event." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeEvent::onTrigger( pTime, pDelta ); +// +// Start shaking the camera. Also account for any offet in playtime, and +// timescale. +// +//----------------------------------------------------------------------------- +void VCameraShakeEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Group. + VCameraGroup *group; + if ( !getGroup( group ) || !group->isActive() ) + { + // Inactive. + return; + } + + // Duration. + //const F32 duration = ( mDuration - mAbs( pTime - getStartTime() ) ) / ( 1000.f * mFabs( getControllerTimeScale() ) ); + const F32 duration = ( mDuration - mAbs( pTime - getStartTime() ) ) / 1000.f; + + // Shake Camera. + VTorque::startCameraShake( duration, mFalloff, mAmplitude, mFrequency ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.h b/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.h new file mode 100644 index 000000000..9a8af7899 --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraShakeEvent.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERASHAKEEVENT_H_ +#define _VT_VCAMERASHAKEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraShakeEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VectorF mAmplitude; + F32 mFalloff; + VectorF mFrequency; + +public: + + VCameraShakeEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraShakeEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERASHAKEEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.cpp b/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.cpp new file mode 100644 index 000000000..4f6fb5e81 --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraShakeTrack.h" +#include "Verve/Extension/Camera/VCameraShakeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraShakeTrack ); +//----------------------------------------------------------------------------- + +VCameraShakeTrack::VCameraShakeTrack( void ) +{ + setLabel( "CameraShakeTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incoming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VCameraShakeTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + // Parent Call. + if ( !Parent::onCameraEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { + case VCameraGroup::k_EventActivate : + { + + VCameraShakeEvent *event; + if ( getCurrentEvent( event ) ) + { + // Re-Trigger Event. + event->onTrigger( getControllerTime(), 0 ); + } + + } break; + + case VCameraGroup::k_EventDeactivate : + { + + // Stop Camera Shake. + VTorque::stopCameraShake(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeTrack::onControllerReset( pTime, pForward ); +// +// Stop all camera shake events. +// +//----------------------------------------------------------------------------- +void VCameraShakeTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + // Stop Camera Shake. + VTorque::stopCameraShake(); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.h b/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.h new file mode 100644 index 000000000..2c09900bc --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraShakeTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERASHAKETRACK_H_ +#define _VT_VCAMERASHAKETRACK_H_ + +#ifndef _VT_VCAMERATRACK_H_ +#include "Verve/Extension/Camera/VCameraTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraShakeTrack : public VCameraTrack +{ + typedef VCameraTrack Parent; + +public: + + VCameraShakeTrack( void ); + + // Camera Methods. + + bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Controller Methods. + + void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraShakeTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERASHAKETRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraTrack.cpp b/Engine/modules/Verve/Extension/Camera/VCameraTrack.cpp new file mode 100644 index 000000000..47e734af9 --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraTrack.cpp @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraTrack ); +//----------------------------------------------------------------------------- + +VCameraTrack::VCameraTrack( void ) +{ + setLabel( "CameraTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onAttach(); +// +// This callback subscribes this object to the Camera Group's event signal. +// +//----------------------------------------------------------------------------- +void VCameraTrack::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller & Group? + VCameraGroup *group; + if ( getController() && getGroup( group ) ) + { + // Add Event Notification. + group->getCameraEventSignal().notify( this, &VCameraTrack::onCameraEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onAttach(); +// +// This callback removes this object from the Camera Group's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VCameraTrack::onDetach( void ) +{ + // Valid Controller & Group? + VCameraGroup *group; + if ( getController() && getGroup( group ) ) + { + // Clear Event Notification. + group->getCameraEventSignal().remove( this, &VCameraTrack::onCameraEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incomming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VCameraTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VCameraTrack::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Ok. + return true; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Camera/VCameraTrack.h b/Engine/modules/Verve/Extension/Camera/VCameraTrack.h new file mode 100644 index 000000000..6866638a2 --- /dev/null +++ b/Engine/modules/Verve/Extension/Camera/VCameraTrack.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERATRACK_H_ +#define _VT_VCAMERATRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_VCAMERAGROUP_H_ +#include "Verve/Extension/Camera/VCameraGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VCameraTrack( void ); + + // Tree Methods. + + void onAttach( void ); + void onDetach( void ); + + // Camera Methods. + + virtual bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERATRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorEvent.cpp b/Engine/modules/Verve/Extension/Director/VDirectorEvent.cpp new file mode 100644 index 000000000..9030b4018 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorEvent.cpp @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Director/VDirectorEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorEvent ); +//----------------------------------------------------------------------------- + +VDirectorEvent::VDirectorEvent( void ) : + mTarget( String::EmptyString ) +{ + // Void. +} + +void VDirectorEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Target", TypeRealString, Offset( mTarget, VDirectorEvent ), "The name of the CameraGroup that will be activated upon triggering." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDirectorEvent::onTrigger( pTime, pDelta ); +// +// Cut the camera to the target group. +// +//----------------------------------------------------------------------------- +void VDirectorEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Controller. + VController *controller = getController(); + + // Valid Target? + VCameraGroup *targetGroup = NULL; + if ( !controller->getObject( mTarget, targetGroup ) ) + { + Con::warnf( "VDirectorEvent::onTrigger() - Invalid Target Group specified." ); + return; + } + + // Change Camera. + targetGroup->setActive(); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorEvent.h b/Engine/modules/Verve/Extension/Director/VDirectorEvent.h new file mode 100644 index 000000000..e890e5a06 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorEvent.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTOREVENT_H_ +#define _VT_VDIRECTOREVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_VCAMERAGROUP_H_ +#include "Verve/Extension/Camera/VCameraGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + String mTarget; + +public: + + VDirectorEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTOREVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorGroup.cpp b/Engine/modules/Verve/Extension/Director/VDirectorGroup.cpp new file mode 100644 index 000000000..4f8934124 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorGroup.cpp @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VDirectorGroup.h" +#include "Verve/Extension/Director/VDirectorTrack.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorGroup ); +//----------------------------------------------------------------------------- + +VDirectorGroup::VDirectorGroup( void ) : + mActiveCamera( NULL ) +{ + setLabel( "DirectorGroup" ); +}; + +//----------------------------------------------------------------------------- +// +// VDirectorGroup::getDirectorTrack(); +// +// Returns the DirectorTrack reference. +// +//----------------------------------------------------------------------------- +VDirectorTrack *VDirectorGroup::getDirectorTrack( void ) +{ + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + if ( VDirectorTrack *track = dynamic_cast( node ) ) + { + // Return Track. + return track; + } + } + + // Invalid Track. + return NULL; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorGroup.h b/Engine/modules/Verve/Extension/Director/VDirectorGroup.h new file mode 100644 index 000000000..bcf9b7a44 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorGroup.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTORGROUP_H_ +#define _VT_VDIRECTORGROUP_H_ + +#ifndef _VT_VGROUP_H_ +#include "Verve/Core/VGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorTrack; +class VCameraGroup; + +//----------------------------------------------------------------------------- + +class VDirectorGroup : public VGroup +{ + typedef VGroup Parent; + +protected: + + // Camera. + VCameraGroup *mActiveCamera; + +public: + + VDirectorGroup( void ); + + VDirectorTrack *getDirectorTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTORGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorTrack.cpp b/Engine/modules/Verve/Extension/Director/VDirectorTrack.cpp new file mode 100644 index 000000000..7592b8882 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VDirectorTrack.h" + +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorTrack ); +//----------------------------------------------------------------------------- + +VDirectorTrack::VDirectorTrack( void ) +{ + setLabel( "DirectorTrack" ); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VDirectorTrack, updateTrack, void, 2, 2, "( void ) - Update the Track.\n" + "@return No return value." ) +{ + for ( ITreeNode *node = object->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *currEvent = ( VEvent* )node; + VEvent *nextEvent = ( VEvent* )node->mSiblingNextNode; + + if ( !nextEvent ) + { + // Update Duration. + currEvent->setDuration( object->getControllerDuration() - currEvent->getTriggerTime() ); + } + else + { + // Update Duration. + currEvent->setDuration( mAbs( nextEvent->getTriggerTime() - currEvent->getTriggerTime() ) ); + } + } +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VDirectorTrack.h b/Engine/modules/Verve/Extension/Director/VDirectorTrack.h new file mode 100644 index 000000000..98b36a410 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VDirectorTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTORTRACK_H_ +#define _VT_VDIRECTORTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VDirectorTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTORTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.cpp b/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.cpp new file mode 100644 index 000000000..09df231b1 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.cpp @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Extension/Director/VSceneJumpEvent.h" +#include "Verve/Extension/Director/VDirectorGroup.h" +#include "Verve/Extension/Director/VDirectorTrack.h" +#include "Verve/Extension/Director/VDirectorEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneJumpEvent ); +//----------------------------------------------------------------------------- + +VSceneJumpEvent::VSceneJumpEvent( void ) : + mTarget( String::EmptyString ) +{ + setLabel( "SceneJumpEvent" ); +} + +void VSceneJumpEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Target", TypeRealString, Offset( mTarget, VSceneJumpEvent ), "The name of the Scene that the controller will jump to upon triggering." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneJumpEvent::onTrigger( pTime, pDelta ); +// +// Tell the controller to jump to a new scene. +// +//----------------------------------------------------------------------------- +void VSceneJumpEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VDirectorTrack *track = getController()->getDirectorTrack(); + if ( !track ) + { + // Invalid Track. + return; + } + + // Get Event. + VDirectorEvent *event; + if ( !track->getObject( mTarget, event ) ) + { + // Can't Jump. + return; + } + + // Go To Scene. + getController()->jump( VController::k_JumpTime, event->getTriggerTime() ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.h b/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.h new file mode 100644 index 000000000..bf7b597bf --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSceneJumpEvent.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEJUMPEVENT_H_ +#define _VT_VSCENEJUMPEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneJumpEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + String mTarget; + +public: + + VSceneJumpEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneJumpEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEJUMPEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.cpp b/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.cpp new file mode 100644 index 000000000..2a6e290d8 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VSceneJumpTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneJumpTrack ); +//----------------------------------------------------------------------------- + +VSceneJumpTrack::VSceneJumpTrack( void ) +{ + setLabel( "SceneJumpTrack" ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.h b/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.h new file mode 100644 index 000000000..fefb4e4f6 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSceneJumpTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEJUMPTRACK_H_ +#define _VT_VSCENEJUMPTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneJumpTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSceneJumpTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneJumpTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEJUMPTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSlowMoEvent.cpp b/Engine/modules/Verve/Extension/Director/VSlowMoEvent.cpp new file mode 100644 index 000000000..3427bda43 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSlowMoEvent.cpp @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Extension/Director/VSlowMoEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSlowMoEvent ); +//----------------------------------------------------------------------------- + +VSlowMoEvent::VSlowMoEvent( void ) : + mTimeScale( 1.f ), + mTimeScaleTickDelta( 0.f ) +{ + setLabel( "SlowMoEvent" ); +} + +void VSlowMoEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "TimeScale", TypeF32, Offset( mTimeScale, VSlowMoEvent ), "The Time Scale to be applied to the Root Controller." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onTrigger( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Instant Update? + if ( getDuration() == 0 ) + { + // Apply & Return. + controller->setTimeScale( mTimeScale ); + return; + } + + // Determine the Number of Ticks. + const F32 tickCount = ( ( F32 )getDuration() ) / TickMs; + + // Determine the Tick Delta. + mTimeScaleTickDelta = ( mTimeScale - controller->getTimeScale() ) / tickCount; +} + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onUpdate( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onUpdate( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onUpdate( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Fetch Current Time Scale. + const F32 timeScale = controller->getTimeScale(); + + // Apply Update. + controller->setTimeScale( timeScale + mTimeScaleTickDelta ); +} + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onComplete( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onComplete( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Tidy Up. + controller->setTimeScale( mTimeScale ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSlowMoEvent.h b/Engine/modules/Verve/Extension/Director/VSlowMoEvent.h new file mode 100644 index 000000000..1cdf75889 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSlowMoEvent.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSLOWMOEVENT_H_ +#define _VT_VSLOWMOEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VSlowMoEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + F32 mTimeScale; + F32 mTimeScaleTickDelta; + +public: + + VSlowMoEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onUpdate( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSlowMoEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSLOWMOEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSlowMoTrack.cpp b/Engine/modules/Verve/Extension/Director/VSlowMoTrack.cpp new file mode 100644 index 000000000..094acfa5e --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSlowMoTrack.cpp @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VSlowMoTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSlowMoTrack ); +//----------------------------------------------------------------------------- + +VSlowMoTrack::VSlowMoTrack( void ) +{ + setLabel( "SlowMoTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSlowMoTrack::onControllerEvent( pEvent ); +// +// ... +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VSlowMoTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventStop : + { + + // Reset Time Scale. + getController()->setTimeScale( ( isControllerPlayingForward() ) ? 1.f : -1.f ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VSlowMoTrack::onControllerReset( pTime, pForward ); +// +// ... +// +//----------------------------------------------------------------------------- +void VSlowMoTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Parent Reset. + Parent::onControllerReset( pTime, pForward ); + + // Reset Time Scale. + getController()->setTimeScale( ( pForward ) ? 1.f : -1.f ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Director/VSlowMoTrack.h b/Engine/modules/Verve/Extension/Director/VSlowMoTrack.h new file mode 100644 index 000000000..143203c99 --- /dev/null +++ b/Engine/modules/Verve/Extension/Director/VSlowMoTrack.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSLOWMOTRACK_H_ +#define _VT_VSLOWMOTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VSlowMoTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSlowMoTrack( void ); + + // Controller Methods. + + bool onControllerEvent( VController::eControllerEventType pEvent ); + void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSlowMoTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSLOWMOTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/GUI/VFadeEvent.cpp b/Engine/modules/Verve/Extension/GUI/VFadeEvent.cpp new file mode 100644 index 000000000..c8d0db6c0 --- /dev/null +++ b/Engine/modules/Verve/Extension/GUI/VFadeEvent.cpp @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/GUI/VFadeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeEvent ); +//----------------------------------------------------------------------------- + +VFadeEvent::VFadeEvent( void ) +{ + setLabel( "FadeEvent" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeEvent::onTrigger( pTime, pDelta ); +// +// Start the fade sequence if a valid fade control can be found. +// +//----------------------------------------------------------------------------- +void VFadeEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + // Start Fade. + fadeControl->start( getFadeType(), mDuration ); + + // Set Elapsed Time. + fadeControl->mElapsedTime = mAbs( pTime - getStartTime() ); +} + +//----------------------------------------------------------------------------- +// +// VFadeEvent::onComplete( pTime, pDelta ); +// +// Tidy up the fade control once the event has finished. +// +//----------------------------------------------------------------------------- +void VFadeEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + // Set Elapsed Time. + fadeControl->mElapsedTime = mDuration; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeEvent::getFadeType(); +// +// Returns the type of fade (in or out) that this event will use. Zero and Even +// indices will Fade Out, while Odd numbers will Fade In. +// +//----------------------------------------------------------------------------- +VFadeControl::eFadeType VFadeEvent::getFadeType( void ) +{ + if ( !isControllerPlayingForward() ) + { + return ( getIndex() % 2 == 0 ) ? VFadeControl::k_TypeOut : VFadeControl::k_TypeIn; + } + + return ( getIndex() % 2 == 0 ) ? VFadeControl::k_TypeIn : VFadeControl::k_TypeOut; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/GUI/VFadeEvent.h b/Engine/modules/Verve/Extension/GUI/VFadeEvent.h new file mode 100644 index 000000000..78c8d7c5f --- /dev/null +++ b/Engine/modules/Verve/Extension/GUI/VFadeEvent.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADEEVENT_H_ +#define _VT_VFADEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_VFADECONTROL_H_ +#include "Verve/GUI/VFadeControl.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VFadeEvent( void ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeEvent ); + +public: + + VFadeControl::eFadeType getFadeType( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADEEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/GUI/VFadeTrack.cpp b/Engine/modules/Verve/Extension/GUI/VFadeTrack.cpp new file mode 100644 index 000000000..e293672db --- /dev/null +++ b/Engine/modules/Verve/Extension/GUI/VFadeTrack.cpp @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/GUI/VFadeTrack.h" +#include "Verve/Extension/GUI/VFadeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeTrack ); +//----------------------------------------------------------------------------- + +VFadeTrack::VFadeTrack( void ) +{ + setLabel( "FadeTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, or stops playing, then the fade control will cease +// playing. If the controller resumes play, the fade control will continue. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VFadeTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch the next Event. + VFadeEvent *event; + if ( !getNextEvent( event ) ) + { + // No Event. + return true; + } + + // Fetch GUI Control. + VFadeControl *fadeControl = dynamic_cast( Sim::findObject( "VFadeControlGui" ) ); + if ( !fadeControl ) + { + // No Control. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay: + { + // Play? + const S32 &time = getControllerTime(); + fadeControl->mActive = ( time > event->getTriggerTime() + && time < event->getFinishTime() ) ; + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Pause. + fadeControl->mActive = false; + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VFadeTrack::onControllerReset( pTime, pForward ); +// +// Reset the fade state of the fade control. +// +//----------------------------------------------------------------------------- +void VFadeTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + Parent::onControllerReset( pTime, pForward ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + VFadeEvent *event; + if ( !getNextEvent( event ) ) + { + // No Events. + return; + } + + // Apply Settings. + fadeControl->mActive = false; + fadeControl->mFadeType = event->getFadeType(); + fadeControl->mDuration = event->getDuration(); + fadeControl->mElapsedTime = getMax( pTime - event->getTriggerTime(), 0 ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/GUI/VFadeTrack.h b/Engine/modules/Verve/Extension/GUI/VFadeTrack.h new file mode 100644 index 000000000..87ca4b9d8 --- /dev/null +++ b/Engine/modules/Verve/Extension/GUI/VFadeTrack.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADETRACK_H_ +#define _VT_VFADETRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VFadeTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADETRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.cpp b/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.cpp new file mode 100644 index 000000000..c08156e49 --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereGroup ); +//----------------------------------------------------------------------------- + +VSpawnSphereGroup::VSpawnSphereGroup( void ) +{ + setLabel( "SpawnSphereGroup" ); +}; \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.h b/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.h new file mode 100644 index 000000000..5a92713ca --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHEREGROUP_H_ +#define _VT_VSPAWNSPHEREGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VSpawnSphereGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHEREGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp new file mode 100644 index 000000000..92218060a --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h" +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereSpawnTargetEvent ); +//----------------------------------------------------------------------------- + +VSpawnSphereSpawnTargetEvent::VSpawnSphereSpawnTargetEvent( void ) +{ + setLabel( "SpawnTargetEvent" ); +} + +void VSpawnSphereSpawnTargetEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetEvent::onTrigger( pTime, pDelta ); +// +// Spawn the Target. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Track. + VSpawnSphereSpawnTargetTrack *track; + if ( !getTrack( track ) ) + { + return; + } + + // Spawn the Target. + track->spawnTarget(); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h new file mode 100644 index 000000000..60b39952d --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ +#define _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_SPAWNSPHERE_H_ +#include "Verve/Torque/TSpawnSphere.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereSpawnTargetEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; +public: + + VSpawnSphereSpawnTargetEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereSpawnTargetEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp new file mode 100644 index 000000000..d0cc2930a --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h" +#include "Verve/Torque/TSpawnSphere.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereSpawnTargetTrack ); +//----------------------------------------------------------------------------- + +VSpawnSphereSpawnTargetTrack::VSpawnSphereSpawnTargetTrack( void ) +{ + setLabel( "SpawnTargetTrack" ); +} + +void VSpawnSphereSpawnTargetTrack::initPersistFields( void ) +{ + // Parent Call. + Parent::initPersistFields(); + + addField( "DespawnOnLoop", TypeBool, Offset( mDespawnOnLoop, VSpawnSphereSpawnTargetTrack ), "Despawn all targets when the Controller loops?" ); + addField( "DespawnOnStop", TypeBool, Offset( mDespawnOnStop, VSpawnSphereSpawnTargetTrack ), "Despawn all targets when the Controller stops playing?" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::onControllerEvent( pEvent ); +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VSpawnSphereSpawnTargetTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventLoop : + { + if ( mDespawnOnLoop ) + { + despawnTargets(); + } + + } break; + + case VController::k_EventStop : + { + if ( mDespawnOnStop ) + { + despawnTargets(); + } + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Spawn Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::spawnTarget( pTime, pForward ); +// +// Spawn an Object. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetTrack::spawnTarget( void ) +{ + VTorque::SpawnSphereType *object; + if ( !getSceneObject( object ) ) + { + return; + } + + // Spawn the Object. + SimObject *spawnedObject = object->spawnObject(); + + // Scene Object? + VTorque::SceneObjectType *sceneObject = dynamic_cast( spawnedObject ); + if ( sceneObject ) + { + sceneObject->setPosition( object->getPosition() ); + } + + // Valid? + if ( spawnedObject ) + { + // Add Reference. + mSpawnList.addObject( spawnedObject ); + } +} + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::despawnTargets(); +// +// Despawn all of the objects spawned by this track. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetTrack::despawnTargets( void ) +{ + while( mSpawnList.size() > 0 ) + { + // Fetch the Last Object + SimObject *object = mSpawnList.last(); + // Remove it. + mSpawnList.popObject(); + + // Delete the Object. + object->deleteObject(); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h new file mode 100644 index 000000000..0df6f2ae5 --- /dev/null +++ b/Engine/modules/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ +#define _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereSpawnTargetTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +protected: + + SimSet mSpawnList; + + bool mDespawnOnStop; + bool mDespawnOnLoop; + +public: + + VSpawnSphereSpawnTargetTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + + // Spawn Methods. + + virtual void spawnTarget( void ); + virtual void despawnTargets( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereSpawnTargetTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp new file mode 100644 index 000000000..94f34c350 --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectAnimationEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectAnimationEvent ); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +VLightObjectAnimationEvent::VLightObjectAnimationEvent( void ) : + mAnimationData( NULL ) +{ + setLabel( "AnimationEvent" ); +} + +void VLightObjectAnimationEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "AnimationData", TYPEID(), Offset( mAnimationData, VLightObjectAnimationEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationEvent::onTrigger( pTime, pDelta ); +// +// When this Event is triggered the light object will begin to play the target +// animation. +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Play the Animation. + VTorque::playAnimation( lightObject, mAnimationData ); + } +} + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationEvent::onComplete( pTime, pDelta ); +// +// The current animation played by the light object will be paused when this +// Event completes its updates. +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Pause the Animation. + VTorque::pauseAnimation( lightObject ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.h b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.h new file mode 100644 index 000000000..18162ff2c --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationEvent.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTANIMATIONEVENT_H_ +#define _VT_VLIGHTOBJECTANIMATIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectAnimationEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + SimObjectPtr mAnimationData; + +public: + + VLightObjectAnimationEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectAnimationEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTANIMATIONEVENT_H_ diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp new file mode 100644 index 000000000..fe2455f4f --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectAnimationTrack.h" +#include "Verve/Extension/LightObject/VLightObjectAnimationEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectAnimationTrack ); +//----------------------------------------------------------------------------- + +VLightObjectAnimationTrack::VLightObjectAnimationTrack( void ) +{ + setLabel( "AnimationTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationTrack::onControllerEvent( pEvent ); +// +// +// +//----------------------------------------------------------------------------- +bool VLightObjectAnimationTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( !getSceneObject( lightObject ) ) + { + // Skip. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Play Animation? + VLightObjectAnimationEvent *event; + if ( getCurrentEvent( event ) ) + { + // Play. + VTorque::playAnimation( lightObject ); + } + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Stop the Animation. + VTorque::pauseAnimation( lightObject ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationTrack::onControllerReset( pTime, pForward ); +// +// +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Stop the Animation. + VTorque::pauseAnimation( lightObject ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.h b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.h new file mode 100644 index 000000000..6485e8428 --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectAnimationTrack.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTANIMATIONTRACK_H_ +#define _VT_VLIGHTOBJECTANIMATIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectAnimationTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VLightObjectAnimationTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectAnimationTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTANIMATIONTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.cpp b/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.cpp new file mode 100644 index 000000000..9db010fc2 --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectGroup ); +//----------------------------------------------------------------------------- + +VLightObjectGroup::VLightObjectGroup( void ) +{ + setLabel( "LightObjectGroup" ); +}; \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.h b/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.h new file mode 100644 index 000000000..16af01bcd --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTGROUP_H_ +#define _VT_VLIGHTOBJECTGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VLightObjectGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp new file mode 100644 index 000000000..4e1475a5f --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectToggleEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectToggleEvent ); +//----------------------------------------------------------------------------- + +VLightObjectToggleEvent::VLightObjectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VLightObjectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VLightObjectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectToggleEvent::onTrigger( pTime, pDelta ); +// +// Toggle the Light Object. +// +//----------------------------------------------------------------------------- +void VLightObjectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle Light. + VTorque::setLightObjectOn( lightObject, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.h b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.h new file mode 100644 index 000000000..382aee1c7 --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTTOGGLEEVENT_H_ +#define _VT_VLIGHTOBJECTTOGGLEEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectToggleEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VLightObjectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp new file mode 100644 index 000000000..a4a5387eb --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectToggleTrack.h" +#include "Verve/Extension/LightObject/VLightObjectToggleEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectToggleTrack ); +//----------------------------------------------------------------------------- + +VLightObjectToggleTrack::VLightObjectToggleTrack( void ) +{ + setLabel( "ToggleTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectToggleTrack::onControllerReset( pTime, pForward ); +// +// Enable or Disable the light object after a reset. +// +//----------------------------------------------------------------------------- +void VLightObjectToggleTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + VLightObjectToggleEvent *event; + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) && getPreviousEvent( event ) ) + { + // Turn On? + const bool turnOn = ( event->mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle the Light. + VTorque::setLightObjectOn( lightObject, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.h b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.h new file mode 100644 index 000000000..510c290bb --- /dev/null +++ b/Engine/modules/Verve/Extension/LightObject/VLightObjectToggleTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTTOGGLETRACK_H_ +#define _VT_VLIGHTOBJECTTOGGLETRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectToggleTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VLightObjectToggleTrack( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectToggleTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Motion/VMotionEvent.cpp b/Engine/modules/Verve/Extension/Motion/VMotionEvent.cpp new file mode 100644 index 000000000..d972168ec --- /dev/null +++ b/Engine/modules/Verve/Extension/Motion/VMotionEvent.cpp @@ -0,0 +1,212 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Motion/VMotionEvent.h" +#include "Verve/Extension/Motion/VMotionTrack.h" + +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VMotionEvent ); +//----------------------------------------------------------------------------- + +VMotionEvent::VMotionEvent( void ) +{ + setLabel( "MotionEvent" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionEvent::onTrigger( pDelta, pDelta ); +// +// The path object is told to move to the next node. If this event corresponds +// to Node 0, the object will move to Node 1. If the object reaches the node +// before the next event is triggered, then the object will stop moving. +// +// The object's position is only reset when the track is reset and not when an +// event is triggered. +// +//----------------------------------------------------------------------------- +void VMotionEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Parent Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid Track. + return; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid. + return; + } + + // Valid Destination Node? + if ( !isControllerLooping() && !getNextEvent() ) + { + // Clear Active. + VTorque::setPathObjectActive( path, object, false ); + // Quit. + return; + } + + // Set Active. + VTorque::setPathObjectActive( path, object, true ); + + // Apply Speed. + VTorque::setPathObjectSpeed( path, object, getObjectSpeed() ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getPath(); +// +// Returns the path that this track is referencing. +// +//----------------------------------------------------------------------------- +VTorque::PathObjectType *VMotionEvent::getPath( void ) +{ + // Fetch Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid. + return NULL; + } + + // Return Path. + return track->getPath(); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getObjectSpeed(); +// +// Determine the Speed that an object must move at to travel over the segment +// length of the Path. +// +//----------------------------------------------------------------------------- +F32 VMotionEvent::getObjectSpeed( void ) +{ + // Fetch Parent Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid Track. + return 0.f; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return 0.f; + } + + // Fetch Node Index. + const S32 &srcNodeIndex = getNodeIndex( ( isControllerPlayingForward() ) ? 0 : -1 ); + + // Fetch the Next Event. + VEvent *nextEvent = getNextEvent(); + + // Valid Destination Node? + if ( !isControllerLooping() && !nextEvent ) + { + // No Next Node. + return 0.f; + } + + // Valid Next Node? + if ( nextEvent ) + { + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = mAbs( getTriggerTime() - nextEvent->getTriggerTime() ); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); + } + + // Playing Forwards? + if ( isControllerPlayingForward() ) + { + // Fetch the First Event. + VEvent *firstEvent = dynamic_cast( track->getChild() ); + + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = ( getControllerDuration() - getTriggerTime() ) + firstEvent->getTriggerTime(); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); + } + + // Fetch the Last Event. + VEvent *lastEvent = dynamic_cast( track->getLastChild() ); + + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = ( getControllerDuration() - lastEvent->getTriggerTime() ) + getTriggerTime(); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); +} + +//----------------------------------------------------------------------------- +// +// VMotionEvent::getNodeIndex( pDelta ); +// +// Returns the index of the path node associated with this event object. +// +//----------------------------------------------------------------------------- +S32 VMotionEvent::getNodeIndex( const S32 &pDelta ) +{ + // Fetch Event Count. + const S32 eventCount = ( ( VTreeNode* )getParent() )->size(); + + // Return Index. + return ( getIndex() + pDelta ) % eventCount; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Motion/VMotionEvent.h b/Engine/modules/Verve/Extension/Motion/VMotionEvent.h new file mode 100644 index 000000000..2ef710e06 --- /dev/null +++ b/Engine/modules/Verve/Extension/Motion/VMotionEvent.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VMOTIONEVENT_H_ +#define _VT_VMOTIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_MOTION_H_ +#include "Verve/Torque/TMotion.h" +#endif + +//----------------------------------------------------------------------------- + +class VMotionEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + VMotionEvent( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Reference Methods. + + virtual VTorque::PathObjectType *getPath( void ); + F32 getObjectSpeed( void ); + S32 getNodeIndex( const S32 &pDelta = 0 ); + + // Console Declaration. + + DECLARE_CONOBJECT( VMotionEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VMOTIONEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Motion/VMotionTrack.cpp b/Engine/modules/Verve/Extension/Motion/VMotionTrack.cpp new file mode 100644 index 000000000..bce52f93f --- /dev/null +++ b/Engine/modules/Verve/Extension/Motion/VMotionTrack.cpp @@ -0,0 +1,442 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Motion/VMotionTrack.h" +#include "Verve/Extension/Motion/VMotionEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VMotionTrack ); +//----------------------------------------------------------------------------- + +VMotionTrack::VMotionTrack( void ) : + mDataReference( String::EmptyString ), + mOrientationMode( "FREE" ), + mOrientationData( String::EmptyString ), + mRelative( false ) +{ + setLabel( "MotionTrack" ); +} + +void VMotionTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Reference", TypeRealString, Offset( mDataReference, VMotionTrack ), "The name of the data field referencing the object to be attached to the path." ); + + addProtectedField( "OrientationMode", TypeRealString, Offset( mOrientationMode, VMotionTrack ), &setOrientationMode, &defaultProtectedGetFn, "The orientation mode of the object attached to the path." ); + addProtectedField( "OrientationData", TypeRealString, Offset( mOrientationData, VMotionTrack ), &setOrientationData, &defaultProtectedGetFn, "The name of the data field holding the orientation data (used for Orientation Modes, ToObject & ToPoint)." ); + addField( "Relative", TypeBool, Offset( mRelative, VMotionTrack ), "Attach the object with an offset based on its initial position." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, then the path object will cease to move. If the +// controller resumes play, the object will continue on its path. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VMotionTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object || !VTorque::isPathObjectAttached( path, object ) ) + { + // Invalid. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Continue Advancing. + VTorque::setPathObjectActive( path, object, true ); + + } break; + + case VController::k_EventPause : + { + + // Stop Advancing. + VTorque::setPathObjectActive( path, object, false ); + + } break; + + case VController::k_EventStop : + { + + // Detach the Object. + detachObject(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::onControllerReset( pTime, pForward ); +// +// Reposition the path object on the path appropriately. The position is +// interpolated between two nodes, the last node and the next node. These +// correspond to the last and current events. +// +//----------------------------------------------------------------------------- +void VMotionTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Parent Reset. + Parent::onControllerReset( pTime, pForward ); + + // Valid Track? + // Note: We must have at least 2 Events/Nodes to path. + if ( size() < 2 ) + { + // Invalid. + return; + } + + // Get Object References. + VController *controller = getController(); + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !controller || !path || !object ) + { + // Invalid Object(s). + return; + } + + // Attached? + if ( !VTorque::isPathObjectAttached( path, object ) ) + { + // No, Attach Now. + attachObject(); + } + + // Reset Object. + resetObject( pTime ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getPath(); +// +// Returns the path that this track is referencing. +// +//----------------------------------------------------------------------------- +VTorque::PathObjectType *VMotionTrack::getPath( void ) +{ + // Fetch the Controller. + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return NULL; + } + + // Evalulate the Data Field. + String fieldValue; + if ( controller->getDataValue( mDataReference, fieldValue ) ) + { + // Return Object. + return dynamic_cast( Sim::findObject( fieldValue ) ); + } + + // No Data! + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::attachObject(); +// +// Attach the underlying Scene Object to the target Path at the first Node. +// Default settings are applied and must be updated after the object is +// attached. +// +//----------------------------------------------------------------------------- +void VMotionTrack::attachObject( void ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Object Attached? + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Already Attached. + return; + } + + // Fetch Forwards. + const bool &forward = isControllerPlayingForward(); + // Select the Node. + const S32 node = ( forward ) ? 0 : ( size() - 1 ); + + // Fetch the value from the controller data table. + String orientationDataValue = String::EmptyString; + if ( mOrientationData != String::EmptyString + && !getController()->getDataValue( mOrientationData, orientationDataValue ) ) + { + // Sanity! + Con::warnf( "Unable to located the value for the given orientation data key, '%s'", mOrientationData ); + // Clear. + orientationDataValue = String::EmptyString; + } + + // Attach Object. + VTorque::attachPathObject( path, object, forward, mRelative, node, -1, mOrientationMode, orientationDataValue ); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::detachObject( void ); +// +// +// +//----------------------------------------------------------------------------- +void VMotionTrack::detachObject( void ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Object Attached? + if ( !VTorque::isPathObjectAttached( path, object ) ) + { + // Not Attached. + return; + } + + // Detach. + VTorque::detachPathObject( path, object ); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::resetObject( pTime ); +// +// +// +//----------------------------------------------------------------------------- +void VMotionTrack::resetObject( const S32 &pTime ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Fetch Controller Info. + const bool &isPlaying = isControllerPlaying(); + const bool &isPlayingForward = isControllerPlayingForward(); + const bool &isLooping = isControllerLooping(); + + // Init Variables. + bool objectActive = false; + F32 objectInterp = 0.f; + F32 objectSpeed = 0.f; + S32 srcNodeIndex = 0; + S32 dstNodeIndex = 0; + + VMotionEvent *event; + if ( !getNextEvent( event ) || event->getTriggerTime() == pTime ) + { + // Note: This case deals with a target time that is greater than the + // trigger time of the Last Event on this track. It will clamp + // the position of the object to the corresponding node of the + // Last Event. + + // Note: If pTime is exactly equal to the Next Event's trigger time, + // then it will set the Source Node to the Last Node and + // set its Interp to 0.f - which is incorrect! + if ( !event || event->getTriggerTime() != pTime ) + { + // Fetch the Last Event. + getPreviousEvent( event ); + } + + // Set the Info. + objectInterp = 0.f; + objectSpeed = event->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex(); + dstNodeIndex = srcNodeIndex; + } + else if ( !event->getPreviousEvent() ) + { + // Note: This case deals with a target time that is less than the + // trigger time of the First Event on this track. It will clamp + // the position of the object to the corresponding node of the + // First Event. + + // Set the Info. + objectInterp = 0.f; + objectSpeed = event->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex(); + dstNodeIndex = srcNodeIndex; + } + else + { + // Note: This case deals with a target time that is between two Events + // on this track. It will position the object on the path, + // between the two nodes corresponding to the Events. + + // Fetch the Last Event. + VMotionEvent *lastEvent; + getPreviousEvent( lastEvent ); + + // Set the Info. + objectActive = isPlaying; + objectInterp = calculateInterp( pTime ); + objectSpeed = lastEvent->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex( ( isPlayingForward ) ? -1 : 1 ); + dstNodeIndex = event->getNodeIndex(); + } + + // Set Active. + VTorque::setPathObjectActive( path, object, objectActive ); + + // Set Forward. + VTorque::setPathObjectForward( path, object, isPlayingForward ); + + // Set Speed. + VTorque::setPathObjectSpeed( path, object, objectSpeed ); + + // Set Current Node. + VTorque::setPathObjectNode( path, object, srcNodeIndex ); + + // Set End Node. + VTorque::setPathObjectEndNode( path, object, ( ( isLooping ) ? -1 : ( size() - 1 ) ) ); + + // Set Interp. + VTorque::setPathObjectInterp( path, object, objectInterp ); +} + +//----------------------------------------------------------------------------- +// +// Static Field Methods. +// +//----------------------------------------------------------------------------- + +bool VMotionTrack::setOrientationMode( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Track. + VMotionTrack *track = static_cast( pObject ); + + // Store Data. + track->mOrientationMode = pData; + + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = track->getSceneObject(); + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Set Orientation Mode. + VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData ); + } + + return false; +} + +bool VMotionTrack::setOrientationData( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Track. + VMotionTrack *track = static_cast( pObject ); + + // Store Data. + track->mOrientationData = pData; + + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = track->getSceneObject(); + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Set Orientation Mode. + VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData ); + } + + return false; +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VMotionTrack, getPath, S32, 2, 2, "( void ) - Get the path object this track references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Path. + SimObject *pathReference = object->getPath(); + + // Return. + return ( pathReference ) ? pathReference->getId() : 0; +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Motion/VMotionTrack.h b/Engine/modules/Verve/Extension/Motion/VMotionTrack.h new file mode 100644 index 000000000..b0fc25c34 --- /dev/null +++ b/Engine/modules/Verve/Extension/Motion/VMotionTrack.h @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VMOTIONTRACK_H_ +#define _VT_VMOTIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_MOTION_H_ +#include "Verve/Torque/TMotion.h" +#endif + +//----------------------------------------------------------------------------- + +class VMotionTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + // Reference Members. + + String mDataReference; + + // Path Members. + + String mOrientationMode; + String mOrientationData; + bool mRelative; + +public: + + VMotionTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Reference Methods. + + VTorque::PathObjectType *getPath( void ); + void attachObject( void ); + void detachObject( void ); + + void resetObject( const S32 &pTime ); + + // Console Declaration. + + DECLARE_CONOBJECT( VMotionTrack ); + +protected: + + // Static Field Methods. + + static bool setOrientationMode( void *pObject, const char *pArray, const char *pData ); + static bool setOrientationData( void *pObject, const char *pArray, const char *pData ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VMOTIONTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp new file mode 100644 index 000000000..00c30388c --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectGroup ); +//----------------------------------------------------------------------------- + +VParticleEffectGroup::VParticleEffectGroup( void ) +{ + setLabel( "ParticleEffectGroup" ); +}; \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.h b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.h new file mode 100644 index 000000000..aa7806366 --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEEFFECTGROUP_H_ +#define _VT_VPARTICLEEFFECTGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VParticleEffectGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEEFFECTGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp new file mode 100644 index 000000000..658f3b5d0 --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectToggleEvent ); +//----------------------------------------------------------------------------- + +VParticleEffectToggleEvent::VParticleEffectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VParticleEffectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VParticleEffectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VParticleEffectToggleEvent::onTrigger( pTime, pDelta ); +// +// Toggle the Particle Effect. +// +//----------------------------------------------------------------------------- +void VParticleEffectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::ParticleEffectType *particleEffect; + if ( getSceneObject( particleEffect ) ) + { + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle Particle Effect. + VTorque::setParticleEffectOn( particleEffect, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h new file mode 100644 index 000000000..e4028413a --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEFFECTTOGGLEEVENT_H_ +#define _VT_VPARTICLEFFECTTOGGLEEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#include "Verve/Torque/TParticleEffect.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectToggleEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VParticleEffectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEFFECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp new file mode 100644 index 000000000..30ce242f5 --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h" +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectToggleTrack ); +//----------------------------------------------------------------------------- + +VParticleEffectToggleTrack::VParticleEffectToggleTrack( void ) +{ + setLabel( "ToggleTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VParticleEffectToggleTrack::onControllerReset( pTime, pForward ); +// +// Enable or Disable the particle effect after a reset. +// +//----------------------------------------------------------------------------- +void VParticleEffectToggleTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + VParticleEffectToggleEvent *event; + VTorque::ParticleEffectType *particleEffect; + if ( getSceneObject( particleEffect ) && getPreviousEvent( event ) ) + { + // Turn On? + const bool turnOn = ( event->mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle the Particle Effect. + VTorque::setParticleEffectOn( particleEffect, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h new file mode 100644 index 000000000..5974dbeb8 --- /dev/null +++ b/Engine/modules/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEEFFECTTOGGLETRACK_H_ +#define _VT_VPARTICLEEFFECTTOGGLETRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#include "Verve/Torque/TParticleEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectToggleTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VParticleEffectToggleTrack( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectToggleTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEEFFECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp new file mode 100644 index 000000000..5e5d65d40 --- /dev/null +++ b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/PostEffect/VPostEffectToggleEvent.h" +#include "Verve/Extension/PostEffect/VPostEffectToggleTrack.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPostEffectToggleEvent ); +//----------------------------------------------------------------------------- + +VPostEffectToggleEvent::VPostEffectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VPostEffectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VPostEffectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VPostEffectToggleEvent::onTrigger( pTime, pDelta ); +// +// Only enable this effect if the parent group is currently active. +// +//----------------------------------------------------------------------------- +void VPostEffectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Parent Objects. + VCameraGroup *group; + VPostEffectToggleTrack *track; + if ( ( !getGroup( group ) || !group->isActive() ) || !getTrack( track ) ) + { + // Quit. + return; + } + + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Enable Effect. + VTorque::setPostEffectOn( track->getPostEffect(), turnOn ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.h b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.h new file mode 100644 index 000000000..66668307b --- /dev/null +++ b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPOSTEFFECTTOGGLEEVENT_H_ +#define _VT_VPOSTEFFECTTOGGLEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VPostEffectToggleEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VPostEffectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VPostEffectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPOSTEFFECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp new file mode 100644 index 000000000..ff2dd52a5 --- /dev/null +++ b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/PostEffect/VPostEffectToggleTrack.h" +#include "Verve/Extension/PostEffect/VPostEffectToggleEvent.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPostEffectToggleTrack ); +//----------------------------------------------------------------------------- + +VPostEffectToggleTrack::VPostEffectToggleTrack( void ) : + mPostEffect( NULL ) +{ + setLabel( "PostEffectTrack" ); +} + +void VPostEffectToggleTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "PostEffect", TYPEID(), Offset( mPostEffect, VPostEffectToggleTrack ), "The name of the PostEffect object to be triggered." ); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VPostEffectToggleTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incoming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VPostEffectToggleTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + // Parent Call. + if ( !Parent::onCameraEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() || !mPostEffect.isValid() ) + { + // Quit Now. + return true; + } + + switch( pEvent ) + { + case VCameraGroup::k_EventActivate : + { + + VPostEffectToggleEvent *event; + if ( getPreviousEvent( event ) && event->mEventType == VSharedEnum::k_ActionTurnOn ) + { + // Toggle Post Effect On. + VTorque::setPostEffectOn( mPostEffect, true ); + } + + } break; + + case VCameraGroup::k_EventDeactivate : + { + + // Turn Post Effect Off. + VTorque::setPostEffectOn( mPostEffect, false ); + + } break; + } + + return true; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.h b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.h new file mode 100644 index 000000000..24a531684 --- /dev/null +++ b/Engine/modules/Verve/Extension/PostEffect/VPostEffectToggleTrack.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPOSTEFFECTTOGGLETRACK_H_ +#define _VT_VPOSTEFFECTTOGGLETRACK_H_ + +#ifndef _VT_VCAMERATRACK_H_ +#include "Verve/Extension/Camera/VCameraTrack.h" +#endif + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VPostEffectToggleTrack : public VCameraTrack +{ + typedef VCameraTrack Parent; + +protected: + + SimObjectPtr mPostEffect; + +public: + + VPostEffectToggleTrack( void ); + + static void initPersistFields( void ); + + // Camera Methods. + + bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Console Declaration. + + DECLARE_CONOBJECT( VPostEffectToggleTrack ); + +public: + + VTorque::PostEffectType *getPostEffect( void ) { return mPostEffect; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPOSTEFFECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.cpp b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.cpp new file mode 100644 index 000000000..7be35e944 --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectEvent ); +//----------------------------------------------------------------------------- + +VSceneObjectEvent::VSceneObjectEvent( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectEvent::getSceneObject(); +// +// Returns the parent group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectEvent::getSceneObject( void ) +{ + VSceneObjectGroup *group; + if ( !getGroup( group ) ) + { + // No Group! + return NULL; + } + + // Return Object. + return group->getSceneObject(); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VSceneObjectEvent, getSceneObject, S32, 2, 2, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.h b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.h new file mode 100644 index 000000000..5dd4bc7df --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectEvent.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#define _VT_VSCENEOBJECTEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VSceneObjectEvent( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.cpp b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.cpp new file mode 100644 index 000000000..1b07a32b9 --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.cpp @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Core/VController.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectGroup ); +//----------------------------------------------------------------------------- + +VSceneObjectGroup::VSceneObjectGroup( void ) : + mDataReference( String::EmptyString ), + mSceneObject( NULL ) +{ + setLabel( "SceneObjectGroup" ); +}; + +void VSceneObjectGroup::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Reference", TypeRealString, Offset( mDataReference, VSceneObjectGroup ), "The name of the data field referencing the targeted object." ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectGroup::getObject(); +// +// Returns the group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectGroup::getSceneObject( void ) +{ +#ifndef VT_EDITOR + // Already Referenced? + if ( mSceneObject ) + { + // Return Object. + return mSceneObject; + } +#endif + + VController *controller = getController(); + if ( !controller ) + { + // No Controller! + return NULL; + } + + String fieldValue; + if ( controller->getDataValue( mDataReference, fieldValue ) ) + { + // Store Object. + mSceneObject = dynamic_cast( Sim::findObject( fieldValue ) ); + } + + // Return. + return mSceneObject; +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VSceneObjectGroup, getSceneObject, S32, 2, 2, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.h b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.h new file mode 100644 index 000000000..9af52eef6 --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectGroup.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#define _VT_VSCENEOBJECTGROUP_H_ + +#ifndef _VT_VGROUP_H_ +#include "Verve/Core/VGroup.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectGroup : public VGroup +{ + typedef VGroup Parent; + +public: + + // Reference Members. + + String mDataReference; + VTorque::SceneObjectType *mSceneObject; + +public: + + VSceneObjectGroup( void ); + + static void initPersistFields( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTGROUP_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.cpp b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.cpp new file mode 100644 index 000000000..adb58d029 --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectTrack ); +//----------------------------------------------------------------------------- + +VSceneObjectTrack::VSceneObjectTrack( void ) +{ + setLabel( "SceneObjectTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectTrack::getSceneObject(); +// +// Returns the parent group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectTrack::getSceneObject( void ) +{ + VSceneObjectGroup *group; + if ( !getGroup( group ) ) + { + // No Group! + return NULL; + } + + // Return Object. + return group->getSceneObject(); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VSceneObjectTrack, getSceneObject, S32, 2, 2, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.h b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.h new file mode 100644 index 000000000..d07517862 --- /dev/null +++ b/Engine/modules/Verve/Extension/SceneObject/VSceneObjectTrack.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#define _VT_VSCENEOBJECTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSceneObjectTrack( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Script/VScriptEvent.cpp b/Engine/modules/Verve/Extension/Script/VScriptEvent.cpp new file mode 100644 index 000000000..48b78a7e4 --- /dev/null +++ b/Engine/modules/Verve/Extension/Script/VScriptEvent.cpp @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "Verve/Extension/Script/VScriptEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VScriptEvent ); +//----------------------------------------------------------------------------- + +// Implement the Command Type enum list. +ImplementEnumType( VScriptEventCommandType, "" ) + { VScriptEvent::k_TypeExpression, "EXPRESSION" }, + { VScriptEvent::k_TypeMethod, "METHOD" }, +EndImplementEnumType; + +//----------------------------------------------------------------------------- + +VScriptEvent::VScriptEvent( void ) : + mCommandType( k_TypeMethod ), + mCommand( String::EmptyString ) +{ + setLabel( "ScriptEvent" ); +} + +void VScriptEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "CommandType", TYPEID(), Offset( mCommandType, VScriptEvent ), "The type of command to be evaluated." ); + addField( "Command", TypeRealString, Offset( mCommand, VScriptEvent ), "The command to be evaluated." ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VScriptEvet::onTrigger( pTime, pDelta ); +// +// Execute a method or evaluate a command. +// +//----------------------------------------------------------------------------- +void VScriptEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + switch ( mCommandType ) + { + case k_TypeExpression : + { + + // Evaluate Expression. + Con::evaluate( mCommand, false, NULL ); + + } break; + + case k_TypeMethod : + { + + SimObject *object = getSceneObject(); + if ( object ) + { + // Execute Method. + Con::executef( object, mCommand ); + } + else + { + // Execute Function. + Con::executef( mCommand ); + } + + } break; + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Script/VScriptEvent.h b/Engine/modules/Verve/Extension/Script/VScriptEvent.h new file mode 100644 index 000000000..ee0b139ca --- /dev/null +++ b/Engine/modules/Verve/Extension/Script/VScriptEvent.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCRIPTEVENT_H_ +#define _VT_VSCRIPTEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VScriptEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + enum eCommandType + { + k_TypeExpression, + k_TypeMethod, + + k_TypeInvalid, + }; + + eCommandType mCommandType; + String mCommand; + +public: + + VScriptEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VScriptEvent ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VScriptEvent::eCommandType VScriptEventCommandType; + +// Declare Enum Types. +DefineEnumType( VScriptEventCommandType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCRIPTEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Script/VScriptEventTrack.cpp b/Engine/modules/Verve/Extension/Script/VScriptEventTrack.cpp new file mode 100644 index 000000000..142d7bc1b --- /dev/null +++ b/Engine/modules/Verve/Extension/Script/VScriptEventTrack.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Script/VScriptEventTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VScriptEventTrack ); +//----------------------------------------------------------------------------- + +VScriptEventTrack::VScriptEventTrack( void ) +{ + setLabel( "ScriptEventTrack" ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/Script/VScriptEventTrack.h b/Engine/modules/Verve/Extension/Script/VScriptEventTrack.h new file mode 100644 index 000000000..e0360ab4f --- /dev/null +++ b/Engine/modules/Verve/Extension/Script/VScriptEventTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCRIPTEVENTTRACK_H_ +#define _VT_VSCRIPTEVENTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VScriptEventTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VScriptEventTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VScriptEventTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCRIPTEVENTTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp new file mode 100644 index 000000000..92c352427 --- /dev/null +++ b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp @@ -0,0 +1,131 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/SoundEffect/VSoundEffectEvent.h" +#include "Verve/Extension/SoundEffect/VSoundEffectTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSoundEffectEvent ); +//----------------------------------------------------------------------------- + +VSoundEffectEvent::VSoundEffectEvent( void ) : + mSoundEffect( NULL ) +{ + setLabel( "SoundEvent" ); +} + +void VSoundEffectEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "SoundEffect", TYPEID(), Offset( mSoundEffect, VSoundEffectEvent ), &setSoundData, &defaultProtectedGetFn, "" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectEvent::onTrigger( pTime, pDelta ); +// +// Play the target sound effect. If this track belongs to a SceneObjectGroup, +// then the sound will play with the reference object's transform. If this is +// not the case, then a 2D sound will be played. +// +//----------------------------------------------------------------------------- +void VSoundEffectEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Track. + VSoundEffectTrack *track; + if ( !getTrack( track ) ) + { + return; + } + + // Position & Pitch. + U32 position = mAbs( ( pTime + pDelta ) - getStartTime() ); + F32 pitch = mFabs( getControllerTimeScale() ); + if ( position < SFXStartBuffer ) + { + // Zero. + position = 0; + } + + VSceneObjectGroup *group; + if ( getGroup( group ) ) + { + // Play Sound With Reference. + track->mSource = VTorque::playSound( mSoundEffect, group->getSceneObject(), position, pitch ); + } + else + { + // Play Sound. + track->mSource = VTorque::playSound( mSoundEffect, position, pitch ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectEvent::setDuration( pDuration ); +// +// This event's duration is always set to the sound object's duration. +// +//----------------------------------------------------------------------------- +void VSoundEffectEvent::setDuration( const S32 &pDuration ) +{ + // Clear Duration. + mDuration = VTorque::getSoundDuration( mSoundEffect ); +} + +//----------------------------------------------------------------------------- +// +// Static Field Methods. +// +//----------------------------------------------------------------------------- + +bool VSoundEffectEvent::setSoundData( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Event. + VSoundEffectEvent *event = static_cast( pObject ); + + // Use Object. + event->mSoundEffect = dynamic_cast( Sim::findObject( pData ) ); + + // Set Duration. + event->setDuration( 0 ); + + return false; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.h b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.h new file mode 100644 index 000000000..79ea79d65 --- /dev/null +++ b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectEvent.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSOUNDEFFECTEVENT_H_ +#define _VT_VSOUNDEFFECTEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VSoundEffectEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + + enum + { + SFXStartBuffer = 100, + }; + +public: + + SimObjectPtr mSoundEffect; + +public: + + VSoundEffectEvent( void ); + + static void initPersistFields( void ); + + static bool setSoundData( void *pObject, const char *pArray, const char *pData ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSoundEffectEvent ); + +public: + + // Property Methods. + + virtual void setDuration( const S32 &pDuration ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSOUNDEFFECTEVENT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp new file mode 100644 index 000000000..040040d31 --- /dev/null +++ b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SoundEffect/VSoundEffectTrack.h" +#include "Verve/Extension/SoundEffect/VSoundEffectEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSoundEffectTrack ); +//----------------------------------------------------------------------------- + +VSoundEffectTrack::VSoundEffectTrack( void ) : + mSource( NULL ) +{ + setLabel( "SoundTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectTrack::onControllerEvent( pEvent ); +// +// If the controller ceases playback and the track has a valid reference to a +// source provider, then the sound is stopped. +// +//----------------------------------------------------------------------------- +bool VSoundEffectTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPause : + case VController::k_EventStop : + { +#ifdef VT_EDITOR + + if ( mSource ) + { + // Stop Sound. + VTorque::stopSound( mSource ); + + // Clear Source. + mSource = NULL; + } + +#endif + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VSoundEffectTrack::onControllerReset( pTime, pForward ); +// +// If the track is reset and it has a valid reference to a source provider, +// then the sound is stopped. +// +//----------------------------------------------------------------------------- +void VSoundEffectTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + if ( mSource ) + { + // Stop Sound. + VTorque::stopSound( mSource ); + } + + // Clear Source. + mSource = NULL; +} \ No newline at end of file diff --git a/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.h b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.h new file mode 100644 index 000000000..1b4eccb24 --- /dev/null +++ b/Engine/modules/Verve/Extension/SoundEffect/VSoundEffectTrack.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSOUNDEFFECTTRACK_H_ +#define _VT_VSOUNDEFFECTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VSoundEffectTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VTorque::SoundSourceType *mSource; + +public: + + VSoundEffectTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSoundEffectTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSOUNDEFFECTTRACK_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorButton.cpp b/Engine/modules/Verve/GUI/VEditorButton.cpp new file mode 100644 index 000000000..1e548280c --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorButton.cpp @@ -0,0 +1,216 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorButton.h" +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gui/core/guiCanvas.h" +#include "gui/core/guiDefaultControlRender.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorButton ); +//----------------------------------------------------------------------------- + +VEditorButton::VEditorButton( void ) : + mIsDraggable( false ) +{ + // Void. +} + +void VEditorButton::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "IsDraggable", TypeBool, Offset( mIsDraggable, VEditorButton ) ); +} + +//----------------------------------------------------------------------------- + +void VEditorButton::onMouseDown( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseDown( pEvent ); + + onMouseEvent( "onMouseDown", pEvent ); +} + +void VEditorButton::onMouseUp( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseUp( pEvent ); + + if ( mIsDraggable && isMouseLocked() ) + { + // Unlock. + mouseUnlock(); + } + + onMouseEvent( "onMouseUp", pEvent ); +} + +void VEditorButton::onMouseDragged( const GuiEvent &pEvent ) +{ + if ( !mActive || !mIsDraggable ) + { + return; + } + + Parent::onMouseDragged( pEvent ); + + if ( !isMouseLocked() ) + { + GuiCanvas *canvas = getRoot(); + if ( canvas->getMouseLockedControl() ) + { + GuiEvent event; + canvas->getMouseLockedControl()->onMouseLeave( event ); + canvas->mouseUnlock( canvas->getMouseLockedControl() ); + } + + // Lock. + mouseLock(); + } + + onMouseEvent( "onMouseDragged", pEvent ); +} + +void VEditorButton::onRightMouseDown( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onRightMouseDown( pEvent ); + + onMouseEvent( "onRightMouseDown", pEvent ); +} + +void VEditorButton::onRightMouseUp( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onRightMouseUp( pEvent ); + + onMouseEvent( "onRightMouseUp", pEvent ); +} + +void VEditorButton::onMouseEnter( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseEnter( pEvent ); + + onMouseEvent( "onMouseEnter", pEvent ); +} + +void VEditorButton::onMouseLeave( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseLeave( pEvent ); + + onMouseEvent( "onMouseLeave", pEvent ); +} + +void VEditorButton::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- + +void VEditorButton::onRender( Point2I offset, const RectI& updateRect ) +{ + // Fetch Texture. + GFXTexHandle texture = getTextureForCurrentState(); + + // Valid? + if ( texture ) + { + GFX->getDrawUtil()->clearBitmapModulation(); + GFX->getDrawUtil()->drawBitmapStretch( texture, RectI( offset, getExtent() ) ); + } + else + { + if ( mProfile->mBorder != 0 ) + { + RectI boundsRect( offset, getExtent() ); + + if ( mDepressed || mStateOn || mMouseOver ) + { + renderFilledBorder( boundsRect, mProfile->mBorderColorHL, mProfile->mFillColorHL ); + } + else + { + renderFilledBorder( boundsRect, mProfile->mBorderColor, mProfile->mFillColor ); + } + } + } + + // Render Text. + GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor ); + renderJustifiedText( offset + mProfile->mTextOffset, getExtent(), mButtonText ); + + renderChildControls( offset, updateRect); +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VEditorButton, getState, bool, 2, 2, "()" ) +{ + return object->getStateOn(); +} \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorButton.h b/Engine/modules/Verve/GUI/VEditorButton.h new file mode 100644 index 000000000..15b3e0dfa --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorButton.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORBUTTON_H_ +#define _VT_VEDITORBUTTON_H_ + +#ifndef _GUIBITMAPBUTTON_H_ +#include "gui/buttons/guiBitmapButtonCtrl.h" +#endif + +class VEditorButton : public GuiBitmapButtonTextCtrl +{ + typedef GuiBitmapButtonTextCtrl Parent; + +public: + + bool mIsDraggable; + +public: + + VEditorButton(); + + static void initPersistFields( void ); + + void onMouseDown( const GuiEvent &pEvent ); + void onMouseUp( const GuiEvent &pEvent ); + void onMouseDragged( const GuiEvent &pEvent ); + + void onRightMouseDown( const GuiEvent &pEvent ); + void onRightMouseUp( const GuiEvent &pEvent ); + + void onMouseEnter( const GuiEvent &pEvent ); + void onMouseLeave( const GuiEvent &pEvent ); + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + void onRender( Point2I offset, const RectI &updateRect ); + +public: + + DECLARE_CONOBJECT( VEditorButton ); +}; + +#endif //_VT_VEDITORBUTTON_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorScrollControl.cpp b/Engine/modules/Verve/GUI/VEditorScrollControl.cpp new file mode 100644 index 000000000..b503ed0d6 --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorScrollControl.cpp @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorScrollControl.h" +#include "gfx/gfxDrawUtil.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorScrollControl ); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Mouse Methods. +// +//----------------------------------------------------------------------------- + +void VEditorScrollControl::onMouseUp( const GuiEvent &pEvent ) +{ + Parent::onMouseUp( pEvent ); + + // Event. + onMouseEvent( "onMouseUp", pEvent ); +} + +void VEditorScrollControl::onRightMouseUp( const GuiEvent &pEvent ) +{ + Parent::onMouseUp( pEvent ); + + // Event. + onMouseEvent( "onRightMouseUp", pEvent ); +} + +void VEditorScrollControl::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + const S32 offsetX = ( mHasVScrollBar ) ? mScrollBarThickness : 0; + const S32 offsetY = ( mHasHScrollBar ) ? mScrollBarThickness : 0; + + const RectI contentRect( 2, 2, getWidth() - offsetX - 4 - 1, getHeight() - offsetY - 4 - ( mHasHScrollBar ) ); + if ( !contentRect.pointInRect( pEvent.mousePoint ) ) + { + // Return! + return; + } + + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VEditorScrollControl::onRender( Point2I pOffset, const RectI &pUpdateRect ) +{ + Parent::onRender( pOffset, pUpdateRect ); + + const S32 offsetX = ( mHasVScrollBar ) ? mScrollBarThickness : 1; + const S32 offsetY = ( mHasHScrollBar ) ? mScrollBarThickness : 1; + + RectI contentRect( pOffset.x + 1, pOffset.y + 1, getWidth() - offsetX - 1, getHeight() - offsetY - 1 ); + contentRect.intersect( pUpdateRect ); + + GFX->getDrawUtil()->drawRect( contentRect, mProfile->mBorderColor ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorScrollControl.h b/Engine/modules/Verve/GUI/VEditorScrollControl.h new file mode 100644 index 000000000..5d3e1d72e --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorScrollControl.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORSCROLLCONTROL_H_ +#define _VT_VEDITORSCROLLCONTROL_H_ + +#ifndef _GUISCROLLCTRL_H_ +#include "gui/containers/guiScrollCtrl.h" +#endif + +//----------------------------------------------------------------------------- + +class VEditorScrollControl : public GuiScrollCtrl +{ + typedef GuiScrollCtrl Parent; + +public: + + // Mouse. + + virtual void onMouseUp( const GuiEvent &pEvent ); + virtual void onRightMouseUp( const GuiEvent &pEvent ); + + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + // Rendering. + + void onRender( Point2I pOffset, const RectI &pUpdateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEditorScrollControl ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEDITORSCROLLCONTROL_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorWindow.cpp b/Engine/modules/Verve/GUI/VEditorWindow.cpp new file mode 100644 index 000000000..fe7a2e859 --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorWindow.cpp @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorWindow.h" +#include "gfx/gfxInit.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorWindow ); +//----------------------------------------------------------------------------- + +bool VEditorWindow::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + GFXAdapter *adapter = GFXInit::getBestAdapterChoice(); + if ( adapter && adapter->mType != NullDevice ) + { + mPlatformWindow->setMinimumWindowSize( Point2I( 904, 287 ) ); + } + + return true; +} + +//----------------------------------------------------------------------------- + +ConsoleMethod( VEditorWindow, resetCursor, void, 2, 2, "( )" ) +{ + S32 currCursor = PlatformCursorController::curArrow; + if ( object->mCursorChanged == currCursor ) + { + return; + } + + PlatformWindow *window = object->getPlatformWindow(); + PlatformCursorController *controller = window->getCursorController(); + + if( object->mCursorChanged != -1) + { + controller->popCursor(); + } + + controller->pushCursor(currCursor); + object->mCursorChanged = currCursor; + + Platform::setWindowLocked( false ); +} + +ConsoleMethod( VEditorWindow, setVideoMode, void, 5, 8, + "(int width, int height, bool fullscreen, [int bitDepth], [int refreshRate])\n" + "Change the video mode of this canvas. This method has the side effect of setting the $pref::Video::mode to the new values.\n\n" + "\\param width The screen width to set.\n" + "\\param height The screen height to set.\n" + "\\param fullscreen Specify true to run fullscreen or false to run in a window\n" + "\\param bitDepth [optional] The desired bit-depth. Defaults to the current setting. This parameter is ignored if you are running in a window.\n" + "\\param refreshRate [optional] The desired refresh rate. Defaults to the current setting. This parameter is ignored if you are running in a window" + "\\param antialiasLevel [optional] The level of anti-aliasing to apply 0 = none" ) +{ + if (!object->getPlatformWindow()) + return; + + // Update the video mode and tell the window to reset. + GFXVideoMode vm = object->getPlatformWindow()->getVideoMode(); + + U32 width = dAtoi(argv[2]); + U32 height = dAtoi(argv[3]); + + bool changed = false; + if (width == 0 && height > 0) + { + // Our width is 0 but our height isn't... + // Try to find a matching width + for(S32 i=0; igetPlatformWindow()->getGFXDevice()->getVideoModeList()->size(); i++) + { + const GFXVideoMode &newVm = (*(object->getPlatformWindow()->getGFXDevice()->getVideoModeList()))[i]; + + if(newVm.resolution.y == height) + { + width = newVm.resolution.x; + changed = true; + break; + } + } + } + else if (height == 0 && width > 0) + { + // Our height is 0 but our width isn't... + // Try to find a matching height + for(S32 i=0; igetPlatformWindow()->getGFXDevice()->getVideoModeList()->size(); i++) + { + const GFXVideoMode &newVm = (*(object->getPlatformWindow()->getGFXDevice()->getVideoModeList()))[i]; + + if(newVm.resolution.x == width) + { + height = newVm.resolution.y; + changed = true; + break; + } + } + } + + if (width == 0 || height == 0) + { + // Got a bad size for both of our dimensions or one of our dimensions and + // didn't get a match for the other default back to our current resolution + width = vm.resolution.x; + height = vm.resolution.y; + + changed = true; + } + + if (changed) + Con::errorf("GuiCanvas::setVideoMode(): Error - Invalid resolution of (%d, %d) - attempting (%d, %d)", dAtoi(argv[2]), dAtoi(argv[3]), width, height); + + vm.resolution = Point2I(width, height); + vm.fullScreen = dAtob(argv[4]); + + // These optional params are set to default at construction of vm. If they + // aren't specified, just leave them at whatever they were set to. + if ((argc > 5) && (dStrlen(argv[5]) > 0)) + { + vm.bitDepth = dAtoi(argv[5]); + } + if ((argc > 6) && (dStrlen(argv[6]) > 0)) + { + vm.refreshRate = dAtoi(argv[6]); + } + + if ((argc > 7) && (dStrlen(argv[7]) > 0)) + { + vm.antialiasLevel = dAtoi(argv[7]); + } + +#ifndef TORQUE_OS_XENON + object->getPlatformWindow()->setVideoMode(vm); +#endif +} \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VEditorWindow.h b/Engine/modules/Verve/GUI/VEditorWindow.h new file mode 100644 index 000000000..938c909e9 --- /dev/null +++ b/Engine/modules/Verve/GUI/VEditorWindow.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORWINDOW_H_ +#define _VT_VEDITORWINDOW_H_ + +#ifndef _GUICANVAS_H_ +#include "gui/core/guiCanvas.h" +#endif + +//----------------------------------------------------------------------------- + +class VEditorWindow : public GuiCanvas +{ + typedef GuiCanvas Parent; + +public: + + // Properties. + + virtual bool onAdd( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEditorWindow ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEDITORWINDOW_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VFadeControl.cpp b/Engine/modules/Verve/GUI/VFadeControl.cpp new file mode 100644 index 000000000..5854ac4f2 --- /dev/null +++ b/Engine/modules/Verve/GUI/VFadeControl.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VFadeControl.h" + +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeControl ); +//----------------------------------------------------------------------------- + +VFadeControl::VFadeControl( void ) : + mActive( false ), + mFadeType( k_TypeInvalid ), + mElapsedTime( 0 ), + mDuration( 1000 ), + mLastTime( 0 ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VFadeControl::onRender( Point2I pOffset, const RectI &pUpdateRect ) +{ + Parent::onRender( pOffset, pUpdateRect ); + + if ( mFadeType == k_TypeInvalid ) + { + // Invalid Fade State. + return; + } + + // Fetch Time. + const U32 time = Platform::getRealMilliseconds(); + // Fetch Delta. + const U32 delta = ( time - mLastTime ); + // Store Time. + mLastTime = time; + + if ( mActive ) + { + // Update Elapsed Time. + mElapsedTime += delta; + } + + F32 alpha = 1.f - mClampF( F32( mElapsedTime ) / F32( mDuration ), 0.f, 1.f ); + + if ( mFadeType == k_TypeOut ) + { + // Flip. + alpha = 1.f - alpha; + } + + if ( alpha > 0.f ) + { + // Render. + GFX->getDrawUtil()->drawRectFill( pOffset, pOffset + getExtent(), ColorF( 0, 0, 0, alpha ) ); + } + + if ( mElapsedTime >= mDuration ) + { + // Stop. + mActive = false; + } +} + +//----------------------------------------------------------------------------- +// +// Control Methods. +// +//----------------------------------------------------------------------------- + +void VFadeControl::start( eFadeType pType, S32 pDuration ) +{ + mActive = true; + + mFadeType = pType; + + mElapsedTime = 0; + mDuration = pDuration; + + mLastTime = Platform::getRealMilliseconds(); +} + +void VFadeControl::pause( void ) +{ + mActive = false; +} \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VFadeControl.h b/Engine/modules/Verve/GUI/VFadeControl.h new file mode 100644 index 000000000..d26cdb97f --- /dev/null +++ b/Engine/modules/Verve/GUI/VFadeControl.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADECONTROL_H_ +#define _VT_VFADECONTROL_H_ + +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeControl : public GuiControl +{ + typedef GuiControl Parent; + +public: + + enum eFadeType + { + k_TypeIn, + k_TypeOut, + + k_TypeInvalid, + }; + + bool mActive; + eFadeType mFadeType; + + S32 mElapsedTime; + S32 mDuration; + S32 mLastTime; + +public: + + VFadeControl( void ); + + // Render Methods. + + virtual void onRender( Point2I pOffset, const RectI &pUpdateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeControl ); + +public: + + void start( eFadeType pType, S32 pDuration ); + void pause( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADECONTROL_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VTimeLineControl.cpp b/Engine/modules/Verve/GUI/VTimeLineControl.cpp new file mode 100644 index 000000000..100f8d2de --- /dev/null +++ b/Engine/modules/Verve/GUI/VTimeLineControl.cpp @@ -0,0 +1,476 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VTimeLineControl.h" +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gui/core/guiCanvas.h" + +//----------------------------------------------------------------------------- + +const S32 gUnitsPerSec = 200; + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VTimeLineControl ); +//----------------------------------------------------------------------------- + +VTimeLineControl::VTimeLineControl( void ) : + mIsController( true ), + mController( NULL ), + mDurationOffset( 50 ) +{ + mSelection.Active = false; + mSelection.StartTime = 0; + mSelection.EndTime = 0; +} + +void VTimeLineControl::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "IsController", TypeBool, Offset( mIsController, VTimeLineControl ) ); + addField( "Controller", TYPEID(), Offset( mController, VTimeLineControl ) ); + addField( "DurationOffset", TypeS32, Offset( mDurationOffset, VTimeLineControl ) ); +} + +//----------------------------------------------------------------------------- +// +// Mouse Methods. +// +//----------------------------------------------------------------------------- + +void VTimeLineControl::onMouseDown( const GuiEvent &pEvent ) +{ + Parent::onMouseDown( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + if ( !isMouseLocked() ) + { + GuiCanvas *canvas = getRoot(); + if ( canvas->getMouseLockedControl() ) + { + GuiEvent event; + canvas->getMouseLockedControl()->onMouseLeave( event ); + canvas->mouseUnlock( canvas->getMouseLockedControl() ); + } + + // Lock. + mouseLock(); + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + // Selection? + if ( pEvent.modifier & SI_SHIFT ) + { + if ( !mSelection.Active ) + { + // Selection Active. + mSelection.Active = true; + mSelection.StartTime = mController->getTime(); + mSelection.EndTime = time; + } + else + { + // Update Selection. + mSelection.EndTime = time; + } + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + + // Set First Responder. + setFirstResponder(); + + if ( pEvent.modifier & SI_CTRL ) + { + // Set Time, No Reset. + mController->setTime( time ); + } + else + { + // Reset. + mController->reset( time ); + } +} + +void VTimeLineControl::onMouseUp( const GuiEvent &pEvent ) +{ + if ( isMouseLocked() ) + { + // Unlock. + mouseUnlock(); + } + + if ( mIsController && mController && !mController->isPlaying() ) + { + // Stop without Reset. + mController->stop( false ); + } +} + +void VTimeLineControl::onMouseDragged( const GuiEvent &pEvent ) +{ + Parent::onMouseDragged( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + if ( pEvent.modifier & SI_SHIFT ) + { + if ( mSelection.Active ) + { + // Update Selection. + mSelection.EndTime = time; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + + if ( pEvent.modifier & SI_CTRL ) + { + // Set Time, No Reset. + mController->setTime( time ); + } + else if ( !mSelection.Active ) + { + // Reset. + mController->reset( time ); + } +} + +void VTimeLineControl::onRightMouseDown( const GuiEvent &pEvent ) +{ + Parent::onRightMouseDown( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + // Set First Responder. + setFirstResponder(); + + if ( mSelection.Active ) + { + const S32 minTime = getMin( mSelection.StartTime, mSelection.EndTime ); + const S32 maxTime = getMax( mSelection.StartTime, mSelection.EndTime ); + if ( time >= minTime && time <= maxTime ) + { + // Callback. + onMouseEvent( "onSelectionRightClick", pEvent ); + + // Don't Update Time. + return; + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + } + + // Reset. + mController->reset( time ); +} + +void VTimeLineControl::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VTimeLineControl::onPreRender( void ) +{ + setUpdate(); +} + +void VTimeLineControl::onRender( Point2I offset, const RectI &updateRect ) +{ + if ( !mController ) + { + // Default Render. + Parent::onRender( offset, updateRect ); + + // Quit. + return; + } + + // Render Properties. + const S32 tickOffset = toPoint( 0 ); + const S32 timeLineWidth = toPoint( mController->getDuration() ) - tickOffset; + const F32 tickStep = 0.5f; + const S32 tickInterval = ( mIsController ) ? getWidth() : timeLineWidth; + const S32 tickIntervalCount = ( S32 )mFloor( tickInterval / ( gUnitsPerSec * tickStep ) ) + 1; + + // Tick Render Proeprties. + const Point2I tickExtent( 0, getHeight() - 1 ); + + // Text Render Properties. + const Point2I textExtent( gUnitsPerSec, mProfile->mFontSize ); + const Point2I textOffset( 4, -mProfile->mFontSize ); + + // Render Border. + GFX->getDrawUtil()->drawRectFill( RectI( offset + Point2I( tickOffset + 1, 1 ), Point2I( timeLineWidth - 1, getHeight() - 1 ) ), mProfile->mFillColorHL ); + + // Font Color. + GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor ); + + for ( S32 i = 0; i < tickIntervalCount; i++ ) + { + // Tick Position. + const Point2I tickPosition = offset + Point2I( tickOffset + i * ( gUnitsPerSec * tickStep ), 0 ); + + // Line Color. + const ColorI lineColor = ( ( i % 2 ) ) ? mProfile->mBorderColorHL : mProfile->mBorderColor; + + // Draw Line. + GFX->getDrawUtil()->drawLine( tickPosition, tickPosition + tickExtent, lineColor ); + + if ( mIsController ) + { + // Render Times. + renderJustifiedText( tickPosition + tickExtent + textOffset, textExtent, avar( "%.2f", ( F32 )( i * tickStep ) ) ); + } + } + + // Render Children + renderChildControls( offset, updateRect ); + + if ( mSelection.Active ) + { + // Selection Width. + const S32 selectionWidth = mCeil( mAbs( toPoint( mSelection.EndTime ) - toPoint( mSelection.StartTime ) ) ); + + // Selection Position. + const S32 selectionPositionX = toPoint( getMin( mSelection.StartTime, mSelection.EndTime ) ); + + // Selection Properties. + const Point2I selectionExtent( selectionWidth, getHeight() ); + const Point2I selectionPosition = offset + Point2I( selectionPositionX, 0 ); + + // Render Time Cue. + GFX->getDrawUtil()->drawRectFill( RectI( selectionPosition, selectionExtent ), ColorF( 0.f, 0.f, 0.f, 0.5f ) ); + + if ( mIsController ) + { + // Buffer. + char buffer[2][128]; + dSprintf( buffer[0], 128, "%.2f", ( F32 )( mSelection.StartTime / 1000.f ) ); + dSprintf( buffer[1], 128, "%.2f", ( F32 )( mSelection.EndTime / 1000.f ) ); + + if ( mSelection.StartTime < mSelection.EndTime ) + { + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer[0] ); + + // Text Position. + const Point2I startText = Point2I( getMax( ( S32 )( selectionPosition.x - ( textWidth + 2 ) ), updateRect.point.x + 4 ), selectionPosition.y + 2 ); + const Point2I endText = Point2I( getMin( ( S32 )( selectionPosition.x + selectionWidth + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), selectionPosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( startText, textExtent, buffer[0] ); + renderJustifiedText( endText, textExtent, buffer[1] ); + } + else + { + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer[1] ); + + // Text Position. + const Point2I startText = Point2I( getMax( ( S32 )( selectionPosition.x - ( textWidth + 2 ) ), updateRect.point.x + 4 ), selectionPosition.y + 2 ); + const Point2I endText = Point2I( getMin( ( S32 )( selectionPosition.x + selectionWidth + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), selectionPosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( startText, textExtent, buffer[1] ); + renderJustifiedText( endText, textExtent, buffer[0] ); + } + } + } + + if ( mController && !mSelection.Active ) + { + // Time Cue Properties. + const Point2I timeCueExtent( ( mIsController ) ? 4 : 2, getHeight() ); + const Point2I timeCuePosition = offset + Point2I( toPoint( mController->getTime() ) - ( timeCueExtent.x / 2 ), 0 ); + + // Render Time Cue. + GFX->getDrawUtil()->drawRectFill( RectI( timeCuePosition, timeCueExtent ), ColorF( 0.f, 0.f, 0.f, 0.5f ) ); + + if ( mIsController ) + { + // Buffer. + char buffer[128]; + dSprintf( buffer, 128, "%.2f", ( F32 )( mController->getTime() / 1000.f ) ); + + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer ); + + // Text Position. + const Point2I textPosition( getMin( getMax( timeCuePosition.x + 6, updateRect.point.x + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), timeCuePosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( textPosition, textExtent, buffer ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VTimeLineControl, toPoint, S32, 3, 3, "( pTime )" ) +{ + return object->toPoint( dAtoi( argv[2] ) ); +} + +S32 VTimeLineControl::toTime( const S32 &pPoint ) +{ + return ( ( S32 )( 1000.f * ( F32 )pPoint / gUnitsPerSec ) - mDurationOffset ); +} + +ConsoleMethod( VTimeLineControl, toTime, S32, 3, 3, "( pPoint )" ) +{ + return object->toTime( dAtoi( argv[2] ) ); +} + +S32 VTimeLineControl::toPoint( const S32 &pTime ) +{ + return ( S32 )( gUnitsPerSec * ( ( F32 )( pTime + mDurationOffset ) / 1000.f ) ); +} + +ConsoleMethod( VTimeLineControl, getSelection, const char *, 2, 2, "( )" ) +{ + const S32 minTime = getMin( object->mSelection.StartTime, object->mSelection.EndTime ); + const S32 maxTime = getMax( object->mSelection.StartTime, object->mSelection.EndTime ); + + // Fetch Return Buffer. + char *retBuffer = Con::getReturnBuffer( 256 ); + + // Write. + dSprintf( retBuffer, 256, "%d %d %d", object->mSelection.Active, minTime, maxTime - minTime ); + + // Return. + return retBuffer; +} + +ConsoleMethod( VTimeLineControl, setSelection, void, 3, 5, "( pActive, [pTime, pDuration] )" ) +{ + object->mSelection.Active = dAtob( argv[2] ); + if ( argc > 3 ) + { + object->mSelection.StartTime = dAtoi( argv[3] ); + object->mSelection.EndTime = object->mSelection.StartTime + dAtoi( argv[4] ); + } +} + +ConsoleMethod( VTimeLineControl, updateDuration, void, 2, 2, "( )" ) +{ + object->updateDuration(); +} + +void VTimeLineControl::updateDuration( void ) +{ + if ( !mController ) + { + // No Controller. + return; + } + + // Add 500ms. + const S32 length = toPoint( mController->getDuration() + 500 ); + + // Set Min Extent. + setMinExtent( Point2I( length, getHeight() ) ); + + if ( getWidth() < length ) + { + // Conform to Min Extent. + setExtent( length, getHeight() ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/GUI/VTimeLineControl.h b/Engine/modules/Verve/GUI/VTimeLineControl.h new file mode 100644 index 000000000..1dd1b9851 --- /dev/null +++ b/Engine/modules/Verve/GUI/VTimeLineControl.h @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTIMELINECONTROL_H_ +#define _VT_VTIMELINECONTROL_H_ + +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif + +#ifndef _VT_VCONTROLLER_H_ +#include "Verve/Core/VController.h" +#endif + +//----------------------------------------------------------------------------- + +class VTimeLineControl : public GuiControl +{ + typedef GuiControl Parent; + +public: + + struct sSelection + { + bool Active; + S32 StartTime; + S32 EndTime; + }; + + bool mIsController; + VController *mController; + + S32 mDurationOffset; + + sSelection mSelection; + +public: + + VTimeLineControl( void ); + + static void initPersistFields( void ); + + // Mouse. + + virtual void onMouseDown( const GuiEvent &pEvent ); + virtual void onMouseUp( const GuiEvent &pEvent ); + virtual void onMouseDragged( const GuiEvent &pEvent ); + + virtual void onRightMouseDown( const GuiEvent &pEvent ); + + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + // Rendering. + + void onPreRender( void ); + void onRender( Point2I offset, const RectI &updateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VTimeLineControl ); + +public: + + S32 toTime( const S32 &pPoint ); + S32 toPoint( const S32 &pTime ); + + void updateDuration( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTIMELINECONTROL_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TAnimation.h b/Engine/modules/Verve/Torque/TAnimation.h new file mode 100644 index 000000000..4c5307bec --- /dev/null +++ b/Engine/modules/Verve/Torque/TAnimation.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_ANIMATION_H_ +#define _VT_TORQUE_ANIMATION_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + bool isAnimationLooping( SceneObjectType *pObject, const char *pData ); + + String getAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + F32 getAnimationDuration( SceneObjectType *pObject, const char *pData ); + void setAnimationPosition( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pPosition ); + void setAnimationTimeScale( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pTimeScale ); + + void playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex, const char *pData ); + void playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + void stopAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + void pauseAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); +}; + +#endif // _VT_TORQUE_ANIMATION_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TCamera.h b/Engine/modules/Verve/Torque/TCamera.h new file mode 100644 index 000000000..329bf093b --- /dev/null +++ b/Engine/modules/Verve/Torque/TCamera.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_CAMERA_H_ +#define _VT_TORQUE_CAMERA_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +#ifndef _CAMERAFXMGR_H_ +#include "T3D/fx/cameraFXMgr.h" +#endif + +namespace VTorque +{ + bool isCamera( SceneObjectType *pObject ); + void setCamera( SceneObjectType *pObject ); + + void startCameraShake( const F32 &pDuration, const F32 &pFalloff, const VectorF &pAmplitude, const VectorF &pFrequency ); + void stopCameraShake( void ); +}; + +#endif // _VT_TORQUE_CAMERA_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TLightObject.h b/Engine/modules/Verve/Torque/TLightObject.h new file mode 100644 index 000000000..0b44cd607 --- /dev/null +++ b/Engine/modules/Verve/Torque/TLightObject.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#define _VT_TORQUE_LIGHTOBJECT_H_ + +#ifndef _LIGHTBASE_H_ +#include "T3D/lightBase.h" +#endif + +#ifndef _LIGHTANIMDATA_H_ +#include "T3D/lightAnimData.h" +#endif + +namespace VTorque +{ + + typedef LightBase LightObjectType; + typedef LightAnimData LightAnimationDataType; + + bool isLightObjectEnabled( LightObjectType *pLightObject ); + void setLightObjectOn( LightObjectType *pLightObject, const bool &pStatus ); + + void playAnimation( LightObjectType *pLightObject, LightAnimationDataType *pLightAnimationData ); + void playAnimation( LightObjectType *pLightObject ); + void pauseAnimation( LightObjectType *pLightObject ); +}; + +#endif // _VT_TORQUE_LIGHTOBJECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TMotion.h b/Engine/modules/Verve/Torque/TMotion.h new file mode 100644 index 000000000..d77118945 --- /dev/null +++ b/Engine/modules/Verve/Torque/TMotion.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_MOTION_H_ +#define _VT_TORQUE_MOTION_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +#ifndef _VT_VPATH_H_ +#include "Verve/VPath/VPath.h" +#endif + +namespace VTorque +{ + typedef VPath PathObjectType; + + bool isMovable( SimObject *pObject ); + bool isPath( SimObject *pObject ); + bool isPathObjectAttached( PathObjectType *pPath, SceneObjectType *pObject ); + + F32 getPathNodeLength( PathObjectType *pPath, const S32 &pNode ); + + void attachPathObject( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ); + void detachPathObject( PathObjectType *pPath, SceneObjectType *pObject ); + + void setPathObjectActive( PathObjectType *pPath, SceneObjectType *pObject, const bool &pActive ); + void setPathObjectInterp( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pInterp ); + void setPathObjectOffset( PathObjectType *pPath, SceneObjectType *pObject, const Point3F &pOffset ); + void setPathObjectSpeed( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pSpeed ); + void setPathObjectOrientation( PathObjectType *pPath, SceneObjectType *pObject, const String &pOrientation, const String &pOrientationData = String::EmptyString ); + void setPathObjectForward( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward ); + void setPathObjectNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ); + void setPathObjectEndNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ); +}; + +#endif // _VT_TORQUE_MOTION_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TParticleEffect.h b/Engine/modules/Verve/Torque/TParticleEffect.h new file mode 100644 index 000000000..c1350af0e --- /dev/null +++ b/Engine/modules/Verve/Torque/TParticleEffect.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#define _VT_TORQUE_PARTICLEEFFECT_H_ + +#ifndef _H_PARTICLE_EMITTER +#include "T3D/fx/particleEmitter.h" +#endif + +#ifndef _PARTICLEEMITTERDUMMY_H_ +#include "T3D/fx/particleEmitterNode.h" +#endif + +namespace VTorque +{ + + typedef ParticleEmitterNode ParticleEffectType; + + bool isParticleEffectEnabled( ParticleEffectType *pParticleEffect ); + void setParticleEffectOn( ParticleEffectType *pParticleEffect, const bool &pStatus ); +}; + +#endif // _VT_TORQUE_PARTICLEEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TPostEffect.h b/Engine/modules/Verve/Torque/TPostEffect.h new file mode 100644 index 000000000..58edcf43e --- /dev/null +++ b/Engine/modules/Verve/Torque/TPostEffect.h @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#define _VT_TORQUE_POSTEFFECT_H_ + +#ifndef _POST_EFFECT_H_ +#include "postFx/postEffect.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef PostEffect PostEffectType; + + bool isPostEffectEnabled( PostEffectType *pPostEffect ); + void setPostEffectOn( PostEffectType *pPostEffect, const bool &pStatus ); +}; + +#endif // _VT_TORQUE_POSTEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TSceneObject.h b/Engine/modules/Verve/Torque/TSceneObject.h new file mode 100644 index 000000000..8f487b3b0 --- /dev/null +++ b/Engine/modules/Verve/Torque/TSceneObject.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#define _VT_TORQUE_SCENEOBJECT_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif + +namespace VTorque +{ + typedef SceneObject SceneObjectType; +}; + +#endif // _VT_TORQUE_SCENEOBJECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TSoundEffect.h b/Engine/modules/Verve/Torque/TSoundEffect.h new file mode 100644 index 000000000..3c3aa9fbc --- /dev/null +++ b/Engine/modules/Verve/Torque/TSoundEffect.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#define _VT_TORQUE_SOUNDEFFECT_H_ + +#ifndef _SFXPROFILE_H_ +#include "sfx/sfxProfile.h" +#endif + +#ifndef _SFXSOUND_H_ +#include "sfx/sfxSound.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef SFXProfile SoundEffectType; + typedef SFXSound SoundSourceType; + + bool isSoundLooping( SoundEffectType *pSoundProfile ); + S32 getSoundDuration( SoundEffectType *pSoundProfile ); + + SoundSourceType *playSound( SoundEffectType *pSoundProfile, const U32 &pPosition, const F32 &pPitch ); + SoundSourceType *playSound( SoundEffectType *pSoundProfile, SceneObjectType *pObject, const U32 &pPosition, const F32 &pPitch ); + + void playSound( SoundSourceType *pSource ); + void pauseSound( SoundSourceType *pSource ); + void stopSound( SoundSourceType *pSource ); + + void setSoundPosition( SoundSourceType *pSource, const U32 &pPosition ); + void setSoundPitch( SoundSourceType *pSource, const F32 &pPitch ); +}; + +#endif // _VT_TORQUE_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque/TSpawnSphere.h b/Engine/modules/Verve/Torque/TSpawnSphere.h new file mode 100644 index 000000000..e9899d87d --- /dev/null +++ b/Engine/modules/Verve/Torque/TSpawnSphere.h @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SPAWNSPHERE_H_ +#define _VT_TORQUE_SPAWNSPHERE_H_ + +#ifndef _MISSIONMARKER_H_ +#include "T3D/missionMarker.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef SpawnSphere SpawnSphereType; +}; + +#endif // _VT_TORQUE_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VAnimation.cpp b/Engine/modules/Verve/Torque3D/VAnimation.cpp new file mode 100644 index 000000000..38eaf983e --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VAnimation.cpp @@ -0,0 +1,172 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TAnimation.h" + +#include "T3D/shapeBase.h" + +//----------------------------------------------------------------------------- +// +// Animation Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isAnimationLooping( SceneObjectType *pObject, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return false; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return false; + } + + // Return Cyclic. + return shape->getShape()->sequences[sequenceIndex].isCyclic(); +} + +String VTorque::getAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return ""; + } + + // Return Name. + return shape->getThreadSequenceName( pThreadIndex ); +} + +F32 VTorque::getAnimationDuration( SceneObjectType *pObject, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return 0.f; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return 0.f; + } + + // Return Duration. + return shape->getShape()->sequences[sequenceIndex].duration; +} + +void VTorque::setAnimationPosition( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pPosition ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Set Position. + shape->setThreadPosition( 0, pPosition ); +} + +void VTorque::setAnimationTimeScale( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pTimeScale ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Set TimeScale. + shape->setThreadTimeScale( pThreadIndex, pTimeScale ); +} + +void VTorque::playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return; + } + + // Play Sequence. + shape->setThreadSequence( pThreadIndex, sequenceIndex ); +} + +void VTorque::playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Play Sequence. + shape->playThread( pThreadIndex ); +} + +void VTorque::stopAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Pause Thread. + shape->stopThread( pThreadIndex ); +} + +void VTorque::pauseAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Pause Thread. + shape->pauseThread( pThreadIndex ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VCamera.cpp b/Engine/modules/Verve/Torque3D/VCamera.cpp new file mode 100644 index 000000000..4e01e5516 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VCamera.cpp @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque/TCamera.h" +#include "Verve/Torque3D/VCameraShake.h" + +#include "T3D/gameBase/gameConnection.h" + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isCamera( SceneObjectType *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +void VTorque::setCamera( SceneObjectType *pObject ) +{ + // Fetch Game Base. + GameBase *object = dynamic_cast( pObject ); + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + GameConnection *connection = dynamic_cast( *itr ); + if ( connection ) + { + // Set Camera Object. + connection->setCameraObject( object ); + } + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VCameraShake.cpp b/Engine/modules/Verve/Torque3D/VCameraShake.cpp new file mode 100644 index 000000000..774715340 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VCameraShake.cpp @@ -0,0 +1,245 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque3D/VCameraShake.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VCameraShakeNetEvent ); +//----------------------------------------------------------------------------- + +// ShakeCamera( 1, 10, "1 0 0", "1 0 0" ); +ConsoleFunction( ShakeCamera, void, 5, 5, "( pDuration, pFalloff, pAmplitude, pFrequency )" ) +{ + // Duration. + const F32 duration = dAtof( argv[1] ); + + // Falloff. + const F32 falloff = dAtof( argv[2] ); + + // Amplitude. + VectorF amplitude; + dSscanf( argv[3], "%g %g %g", &litude.x, &litude.y, &litude.z ); + + // Frequency. + VectorF frequency; + dSscanf( argv[4], "%g %g %g", &frequency.x, &frequency.y, &frequency.z ); + + // Shake Camera. + VTorque::startCameraShake( duration, falloff, amplitude, frequency ); +} + +void VTorque::startCameraShake( const F32 &pDuration, const F32 &pFalloff, const VectorF &pAmplitude, const VectorF &pFrequency ) +{ +#ifdef VT_EDITOR + + // Create FX Event + CameraShake *camShake = new CameraShake(); + + // Set Duration. + camShake->setDuration( pDuration ); + + // Set Falloff. + camShake->setFalloff( pFalloff ); + + // Set Amplitude. + VectorF amp = pAmplitude; + camShake->setAmplitude( amp ); + + // Set Frequency. + VectorF freq = pFrequency; + camShake->setFrequency( freq ); + + // Initialise. + camShake->init(); + + // Add to Manager. + gCamFXMgr.addFX( camShake ); + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VCameraShakeNetEvent *event = new VCameraShakeNetEvent(); + + // Setup Event. + event->mEventType |= ( VCameraShakeNetEvent::k_TypeClear | VCameraShakeNetEvent::k_TypeMake ); + event->mDuration = pDuration; + event->mFalloff = pFalloff; + event->mAmplitude = pAmplitude; + event->mFrequency = pFrequency; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +void VTorque::stopCameraShake( void ) +{ +#ifdef VT_EDITOR + + // Clear Manager. + gCamFXMgr.clear(); + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VCameraShakeNetEvent *event = new VCameraShakeNetEvent(); + + // Setup Event. + event->mEventType |= VCameraShakeNetEvent::k_TypeClear; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +//----------------------------------------------------------------------------- + +VCameraShakeNetEvent::VCameraShakeNetEvent( void ) : mEventType( 0 ), + mDuration( 0.f ), + mFalloff( 10.f ), + mAmplitude( Point3F::Zero ), + mFrequency( Point3F::Zero ) +{ + // Void. +} + +void VCameraShakeNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VCameraShakeNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Clear Manager? + pStream->write( mEventType & k_TypeClear ); + + // Make Event? + if ( pStream->write( mEventType & k_TypeMake ) ) + { + // Duration. + pStream->write( mDuration ); + + // Falloff. + pStream->write( mFalloff ); + + // Amplitude. + pStream->write( mAmplitude.x ); + pStream->write( mAmplitude.y ); + pStream->write( mAmplitude.z ); + + // Frequency. + pStream->write( mFrequency.x ); + pStream->write( mFrequency.y ); + pStream->write( mFrequency.z ); + } +} + +void VCameraShakeNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Clear Manager? + if ( pStream->readFlag() ) + { + // Update State. + mEventType |= k_TypeClear; + } + + // Make Event? + if ( pStream->readFlag() ) + { + // Update State. + mEventType |= k_TypeMake; + + // Duration. + pStream->read( &mDuration ); + + // Falloff. + pStream->read( &mFalloff ); + + // Amplitude. + pStream->read( &mAmplitude.x ); + pStream->read( &mAmplitude.y ); + pStream->read( &mAmplitude.z ); + + // Frequency. + pStream->read( &mFrequency.x ); + pStream->read( &mFrequency.y ); + pStream->read( &mFrequency.z ); + } +} + +void VCameraShakeNetEvent::process( NetConnection *pConnection ) +{ + if ( mEventType & k_TypeClear ) + { + // Clear Manager. + gCamFXMgr.clear(); + } + + if ( mEventType & k_TypeMake ) + { + // Create FX Event + CameraShake *camShake = new CameraShake(); + + // Set Duration. + camShake->setDuration( mDuration ); + + // Set Falloff. + camShake->setFalloff( mFalloff ); + + // Set Amplitude. + camShake->setAmplitude( mAmplitude ); + + // Set Frequency. + camShake->setFrequency( mFrequency ); + + // Initialise. + camShake->init(); + + // Add to Manager. + gCamFXMgr.addFX( camShake ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VCameraShake.h b/Engine/modules/Verve/Torque3D/VCameraShake.h new file mode 100644 index 000000000..2e40359d1 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VCameraShake.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_CAMERASHAKE_H_ +#define _VT_VTORQUE3D_CAMERASHAKE_H_ + +#ifndef _VT_TORQUE_CAMERA_H_ +#include "Verve/Torque/TCamera.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VCameraShakeNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + enum eEventType + { + k_TypeClear = BIT( 0 ), + k_TypeMake = BIT( 1 ), + }; + + U32 mEventType; + + F32 mDuration; + F32 mFalloff; + VectorF mAmplitude; + VectorF mFrequency; + +public: + + VCameraShakeNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VCameraShakeNetEvent ); +}; + +#endif // _VT_VTORQUE3D_CAMERASHAKE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VLightObject.cpp b/Engine/modules/Verve/Torque3D/VLightObject.cpp new file mode 100644 index 000000000..dcf1d016e --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VLightObject.cpp @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TLightObject.h" + +//----------------------------------------------------------------------------- +// +// Light Object Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isLightObjectEnabled( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return false; + } + + // Get Enabled. + return pLightObject->getLightEnabled(); +} + +void VTorque::setLightObjectOn( LightObjectType *pLightObject, const bool &pStatus ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Set Enabled. + pLightObject->setLightEnabled( pStatus ); +} + +void VTorque::playAnimation( LightObjectType *pLightObject, LightAnimationDataType *pLightAnimationData ) +{ + if ( !pLightObject || !pLightAnimationData ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->playAnimation( pLightAnimationData ); +} + +void VTorque::playAnimation( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->playAnimation(); +} + +void VTorque::pauseAnimation( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->pauseAnimation(); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VMotion.cpp b/Engine/modules/Verve/Torque3D/VMotion.cpp new file mode 100644 index 000000000..54bff56e5 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VMotion.cpp @@ -0,0 +1,458 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TMotion.h" +#include "Verve/VPath/VPath.h" + +//----------------------------------------------------------------------------- + +// Sync the local connection when editing path objects? +// Note: This was originally done so that editing was very smooth, but it turns +// out that any lag was due to errors in the pathing operations +// themselves. If issues persist, then uncomment this definition and you +// might see a marked improvement in performance while editing in Verve. +//#define VT_SYNC_LOCALCLIENT + +//----------------------------------------------------------------------------- +// +// Utility Methods. +// +//----------------------------------------------------------------------------- + +NetObject *getClientObject( NetObject *pObject ) +{ + if ( !pObject ) + { + return NULL; + } + + NetConnection *toServer = NetConnection::getConnectionToServer(); + NetConnection *toClient = NetConnection::getLocalClientConnection(); + if ( !toServer || !toClient ) + { + return NULL; + } + + const S32 ghostIndex = toClient->getGhostIndex( pObject ); + if ( ghostIndex == -1 ) + { + return NULL; + } + + return toServer->resolveGhost( ghostIndex ); +} + +void _attachPathObject( VPath *pPath, SceneObject *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ) +{ + if ( pOrientation == String::EmptyString ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex ); + // Quit. + return; + } + + // Fetch Orientation. + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, NULL ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Object. + SceneObject *lookAtObject = dynamic_cast( Sim::findObject( pOrientationData ) ); + // Valid Object? + if ( lookAtObject != NULL ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtObject ); + } + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + if ( dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ) == 3 ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtPoint ); + } + + } break; + } +} + +//----------------------------------------------------------------------------- +// +// Path Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isMovable( SimObject *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +bool VTorque::isPath( SimObject *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +bool VTorque::isPathObjectAttached( PathObjectType *pPath, SceneObjectType *pObject ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return false; + } + + // Return. + return pPath->isObjectAttached( pObject ); +} + +F32 VTorque::getPathNodeLength( PathObjectType *pPath, const S32 &pNode ) +{ + if ( !pPath ) + { + // Sanity! + return false; + } + + // Normalize Node Index. + S32 nodeIndex = pNode; + pPath->normalizeNodeIndex( nodeIndex ); + + // Fetch Node. + VPathNode *node = pPath->getNode( nodeIndex ); + + // Return Length. + return node->getLength(); +} + +void VTorque::attachPathObject( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Attach Object. + _attachPathObject( pPath, pObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Attach Object. + _attachPathObject( clientPath, clientObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData ); + } + +#endif +} + +void VTorque::detachPathObject( PathObjectType *pPath, SceneObjectType *pObject ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Detach Object. + pPath->detachObject( pObject ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Detach Object. + clientPath->detachObject( clientObject ); + } + +#endif +} + +void VTorque::setPathObjectActive( PathObjectType *pPath, SceneObjectType *pObject, const bool &pActive ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object State. + pPath->setPathObjectActive( pObject, pActive ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object State. + clientPath->setPathObjectActive( clientObject, pActive ); + } + +#endif +} + +void VTorque::setPathObjectInterp( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pInterp ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Interp. + pPath->setPathObjectInterp( pObject, pInterp ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectInterp( clientObject, pInterp ); + } + +#endif +} + +void VTorque::setPathObjectOffset( PathObjectType *pPath, SceneObjectType *pObject, const Point3F &pOffset ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Offset. + pPath->setPathObjectOffset( pObject, pOffset ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectOffset( clientObject, pOffset ); + } + +#endif +} + +void VTorque::setPathObjectSpeed( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pSpeed ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Speed. + pPath->setPathObjectSpeed( pObject, pSpeed ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectSpeed( clientObject, pSpeed ); + } + +#endif +} + +void VTorque::setPathObjectOrientation( PathObjectType *pPath, SceneObjectType *pObject, const String &pOrientation, const String &pOrientationData ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Set the orientation mode. + // Note: Call the console method so we don't have to handle all the different modes here. + Con::executef( pPath, "setPathObjectOrientationMode", pObject->getIdString(), pOrientation, pOrientationData ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // TODO: Handle synching the client path immediately. + +#endif + + /* + // Set the Default Mode. + if ( pOrientation == String::EmptyString ) + { + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, VPathObject::k_OrientationToPath ); + return; + } + + // Fetch Orientation. + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + + // Fetch Object. + SceneObjectType *lookAtObject; + if ( !Sim::findObject( pOrientationData, lookAtObject ) ) + { + // Invalid Object. + return; + } + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type, lookAtObject ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type, lookAtPoint ); + + } break; + } + */ +} + +void VTorque::setPathObjectForward( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Forward. + pPath->setPathObjectForward( pObject, pForward ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectForward( clientObject, pForward ); + } + +#endif +} + +void VTorque::setPathObjectNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object Current Node. + pPath->setPathObjectNode( pObject, pNode ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object Current Node. + clientPath->setPathObjectNode( clientObject, pNode ); + } + +#endif +} + +void VTorque::setPathObjectEndNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object End Node. + pPath->setPathObjectEndNode( pObject, pNode ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object End Node. + clientPath->setPathObjectEndNode( clientObject, pNode ); + } + +#endif +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VParticleEffect.cpp b/Engine/modules/Verve/Torque3D/VParticleEffect.cpp new file mode 100644 index 000000000..b1e35b5a1 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VParticleEffect.cpp @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TParticleEffect.h" + +//----------------------------------------------------------------------------- +// +// Particle Effect Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isParticleEffectEnabled( ParticleEffectType *pParticleEffect ) +{ + if ( !pParticleEffect ) + { + // Sanity! + return false; + } + + // Get Active. + return pParticleEffect->getActive(); +} + +void VTorque::setParticleEffectOn( ParticleEffectType *pParticleEffect, const bool &pStatus ) +{ + if ( !pParticleEffect ) + { + // Sanity! + return; + } + + // Set Active. + pParticleEffect->setActive( pStatus ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VPostEffect.cpp b/Engine/modules/Verve/Torque3D/VPostEffect.cpp new file mode 100644 index 000000000..e9f245790 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VPostEffect.cpp @@ -0,0 +1,152 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque3D/VPostEffect.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +// +// Post Effect Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isPostEffectEnabled( PostEffectType *pPostEffect ) +{ + if ( !pPostEffect ) + { + // Sanity! + return false; + } + + return pPostEffect->isEnabled(); +} + +void VTorque::setPostEffectOn( PostEffectType *pPostEffect, const bool &pStatus ) +{ + if ( !pPostEffect ) + { + // Sanity! + return; + } + +#ifdef VT_EDITOR + + if ( pStatus ) + { + // Enable Effect. + pPostEffect->enable(); + } + else + { + // Disable Effect. + pPostEffect->disable(); + } + +#else + + // Fetch Name. + StringTableEntry name = pPostEffect->getName(); + if ( !name || name == StringTable->insert( "" ) ) + { + Con::warnf( "VTorque::setPostEffectOn() - Invalid Object Name." ); + return; + } + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VPostEffectNetEvent *event = new VPostEffectNetEvent(); + + // Setup Event. + event->mPostEffect = name; + event->mEnabled = pStatus; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VPostEffectNetEvent ); +//----------------------------------------------------------------------------- + +VPostEffectNetEvent::VPostEffectNetEvent( void ) : mPostEffect( StringTable->insert( "" ) ), + mEnabled( false ) +{ + // Void. +} + +void VPostEffectNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VPostEffectNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Object Name. + pStream->writeString( mPostEffect ); + + // Status. + pStream->writeFlag( mEnabled ); +} + +void VPostEffectNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Object Name. + mPostEffect = pStream->readSTString(); + + // Status. + mEnabled = pStream->readFlag(); +} + +void VPostEffectNetEvent::process( NetConnection *pConnection ) +{ + PostEffect *postEffect; + if ( !Sim::findObject( mPostEffect, postEffect ) ) + { + Con::warnf( "VPostEffectNetEvent::process() - Unable to find PostEffect Object '%s'", mPostEffect ); + return; + } + + if ( mEnabled ) + { + // Enable Effect. + postEffect->enable(); + } + else + { + // Disable Effect. + postEffect->disable(); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VPostEffect.h b/Engine/modules/Verve/Torque3D/VPostEffect.h new file mode 100644 index 000000000..bbb64aecc --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VPostEffect.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_POSTEFFECT_H_ +#define _VT_VTORQUE3D_POSTEFFECT_H_ + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VPostEffectNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + StringTableEntry mPostEffect; + bool mEnabled; + +public: + + VPostEffectNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VPostEffectNetEvent ); +}; + +#endif // _VT_VTORQUE3D_POSTEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VSoundEffect.cpp b/Engine/modules/Verve/Torque3D/VSoundEffect.cpp new file mode 100644 index 000000000..8dda926c3 --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VSoundEffect.cpp @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque3D/VSoundEffect.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" +#include "math/mathIO.h" +#include "sfx/sfxSystem.h" +#include "sfx/sfxDescription.h" + +//----------------------------------------------------------------------------- +// +// Sound Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isSoundLooping( SoundEffectType *pSoundProfile ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return false; + } + + // Return Looping. + return pSoundProfile->getDescription()->mIsLooping; +} + +S32 VTorque::getSoundDuration( SoundEffectType *pSoundProfile ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return 0; + } + + // Return Duration. + return pSoundProfile->getSoundDuration(); +} + +VTorque::SoundSourceType *VTorque::playSound( SoundEffectType *pSoundProfile, const U32 &pPosition, const F32 &pPitch ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return NULL; + } + +#ifdef VT_EDITOR + + // Play Sound. + SFXSound *source = ( SFXSound* )SFX->playOnce( pSoundProfile ); + + if ( source ) + { + // Set Position. + source->setPosition( pPosition ); + + // Set Pitch. + source->setPitch( pPitch ); + } + + // Return Source. + return source; + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VSoundEffectNetEvent *event = new VSoundEffectNetEvent(); + + // Setup Event. + event->mProfile = pSoundProfile; + event->mPosition = pPosition; + event->mPitch = pPitch; + event->mIs3D = false; + + // Post Event. + connection->postNetEvent( event ); + } + } + + return NULL; + +#endif +} + +VTorque::SoundSourceType *VTorque::playSound( SoundEffectType *pSoundProfile, SceneObjectType *pObject, const U32 &pPosition, const F32 &pPitch ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return NULL; + } + +#ifdef VT_EDITOR + + // Fetch Reference Transform. + const MatrixF &transform = pObject->getTransform(); + + // Play Sound. + SFXSound *source = ( SFXSound* )SFX->playOnce( pSoundProfile, &transform ); + + if ( source ) + { + // Set Position. + source->setPosition( pPosition ); + + // Set Pitch. + source->setPitch( pPitch ); + } + + // Return Source. + return source; + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VSoundEffectNetEvent *event = new VSoundEffectNetEvent(); + + // Setup Event. + event->mProfile = pSoundProfile; + event->mPosition = pPosition; + event->mPitch = pPitch; + event->mIs3D = true; + event->mTransform = pObject->getTransform(); + + // Post Event. + connection->postNetEvent( event ); + } + } + + return NULL; + +#endif +} + +void VTorque::playSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Play. + pSource->play(); +} + +void VTorque::pauseSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Pause. + pSource->pause(); +} + +void VTorque::stopSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Stop. + pSource->stop(); +} + +void VTorque::setSoundPosition( SoundSourceType *pSource, const U32 &pPosition ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Set Position. + pSource->setPosition( pPosition ); +} + +void VTorque::setSoundPitch( SoundSourceType *pSource, const F32 &pPitch ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Set Pitch. + pSource->setPitch( pPitch ); +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VSoundEffectNetEvent ); +//----------------------------------------------------------------------------- + +VSoundEffectNetEvent::VSoundEffectNetEvent( void ) : mProfile( NULL ), + mPosition( 0.f ), + mPitch( 1.f ), + mIs3D( false ), + mTransform( MatrixF::Identity ) +{ + // Void. +} + +void VSoundEffectNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VSoundEffectNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid? + if ( !pStream->writeFlag( mProfile != NULL ) ) + { + return; + } + + // Profile. + pStream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize ); + + // Position. + pStream->write( mPosition ); + + // Pitch. + pStream->write( mPitch ); + + // 3D? + if ( pStream->writeFlag( mIs3D ) ) + { + // Rotation. + SFXDescription* description = mProfile->getDescription(); + if ( pStream->writeFlag( description->mConeInsideAngle || description->mConeOutsideAngle ) ) + { + // Entire Transform. + pStream->writeAffineTransform( mTransform ); + } + else + { + // Position. + mathWrite( *pStream, mTransform.getColumn3F( 3 ) ); + } + } +} + +void VSoundEffectNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid? + if ( !pStream->readFlag() ) + { + return; + } + + // Profile. + Sim::findObject( pStream->readInt( DataBlockObjectIdBitSize ) + DataBlockObjectIdFirst, mProfile ); + + // Position. + pStream->read( &mPosition ); + + // Pitch. + pStream->read( &mPitch ); + + // 3D? + if ( pStream->readFlag() ) + { + // Yup! + mIs3D = true; + + // Rotation? + if ( pStream->readFlag() ) + { + // Transform. + pStream->readAffineTransform( &mTransform ); + } + else + { + // Position. + Point3F pos; + mathRead( *pStream, &pos ); + mTransform.setColumn( 3, pos ); + } + } +} + +void VSoundEffectNetEvent::process( NetConnection *pConnection ) +{ + // Valid? + if ( !mProfile ) + { + return; + } + + SFXSound *source = NULL; + if ( mIs3D ) + { + // Play 3D Sound. + source = ( SFXSound* )SFX->playOnce( mProfile, &mTransform ); + } + else + { + // Play 2D Sound. + source = ( SFXSound* )SFX->playOnce( mProfile ); + } + + if ( source ) + { + // Set Position. + source->setPosition( mPosition ); + + // Set Pitch. + source->setPitch( mPitch ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VSoundEffect.h b/Engine/modules/Verve/Torque3D/VSoundEffect.h new file mode 100644 index 000000000..812f8f89c --- /dev/null +++ b/Engine/modules/Verve/Torque3D/VSoundEffect.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_SOUNDEFFECT_H_ +#define _VT_VTORQUE3D_SOUNDEFFECT_H_ + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VSoundEffectNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + SFXProfile *mProfile; + + F32 mPosition; + F32 mPitch; + + bool mIs3D; + MatrixF mTransform; + +public: + + VSoundEffectNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VSoundEffectNetEvent ); +}; + +#endif // _VT_VTORQUE3D_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/Torque3D/VSpawnSphere.cpp b/Engine/modules/Verve/Torque3D/VSpawnSphere.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.cpp new file mode 100644 index 000000000..240c4d0b0 --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.cpp @@ -0,0 +1,259 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActor.h" + +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VHumanoidActor ); +//----------------------------------------------------------------------------- + +VHumanoidActor::VHumanoidActor( void ) +{ + // Void. +} + +VHumanoidActor::~VHumanoidActor( void ) +{ + // Void. +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::onNewDataBlock( pDataBlock ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::onNewDataBlock( GameBaseData *pDataBlock, bool pReload ) +{ + // Store DataBlock Reference. + mDataBlock = dynamic_cast( pDataBlock ); + + // Valid Data? + if ( !mDataBlock || !Parent::onNewDataBlock( pDataBlock, pReload ) ) + { + // Invalid Data. + return false; + } + + // Initialise the Controllers. + if ( !initAnimationController() || !initPhysicsController() ) + { + // Invalid. + return false; + } + + // Initialise the Base Animation Thread. + mAnimationController.initBaseAnimation( VHumanoidActorData::k_IdleAnimation, 0.f, 1.f ); + // Initialise the Arm Animation Thread. + mAnimationController.initArmAnimation( VHumanoidActorData::k_ArmsUpDownAnimation, 0.5f, 1.f ); + + /* + // Initialise Head Threads. + initAnimationSequence( VHumanoidActorData::k_HeadHorizontalAnimation, mHeadAnimation.HThread, 0.5f ); + initAnimationSequence( VHumanoidActorData::k_HeadVerticalAnimation, mHeadAnimation.VThread, 0.5f ); + */ + + // Valid Data. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::processTick( pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::processTick( const Move *pMove ) +{ + // Parent Call. + Parent::processTick( pMove ); + + // Update Physics. + mPhysicsController.update( TickSec, pMove ); + + // Update Container. + updateContainer(); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::interpolateTick( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::interpolateTick( F32 pDelta ) +{ + // Parent Call. + Parent::interpolateTick( pDelta ); + + // Update Physics. + mPhysicsController.interpolateTick( pDelta ); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::advanceTime( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::advanceTime( F32 pDelta ) +{ + // Parent Call. + Parent::advanceTime( pDelta ); + + // Valid Animation Controller? + if ( getAnimationController() ) + { + // Update Animations. + getAnimationController()->update( pDelta ); + } +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VHumanoidActor::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Parent Call. + U32 retMask = Parent::packUpdate( pConnection, pMask, pStream ); + + // Physics Controller? + if ( pStream->writeFlag( pMask & PhysicsMask ) ) + { + // Pack Physics. + retMask &= mPhysicsController.packUpdate( pConnection, pMask, pStream ); + } + + return retMask; +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Parent Call. + Parent::unpackUpdate( pConnection, pStream ); + + // Physics Controller? + if ( pStream->readFlag() ) + { + // Unpack Physics. + mPhysicsController.unpackUpdate( pConnection, pStream ); + } +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::initAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::initAnimationController( void ) +{ + // Reference Object. + mAnimationController.setObject( this ); + // Initialise. + return mAnimationController.initAnimationTable(); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::getAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +VActorAnimationController *VHumanoidActor::getAnimationController( void ) +{ + return &mAnimationController; +} + + + + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::initPhysicsController(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::initPhysicsController( void ) +{ + // Initialise. + return mPhysicsController.initPhysicsController( this ); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::getAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +VActorPhysicsController *VHumanoidActor::getPhysicsController( void ) +{ + return &mPhysicsController; +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.h new file mode 100644 index 000000000..65ecb22bf --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActor.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTOR_H_ +#define _VT_VHUMANOIDACTOR_H_ + +#ifndef _VT_VACTOR_H_ +#include "../VActor.h" +#endif + +#ifndef _VT_VHUMANOIDACTORDATA_H_ +#include "VHumanoidActorData.h" +#endif + +#ifndef _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ +#include "VHumanoidActorAnimationController.h" +#endif + +#ifndef _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ +#include "VHumanoidActorPhysicsController.h" +#endif + +//----------------------------------------------------------------------------- + +class VHumanoidActor : public VActor +{ + typedef VActor Parent; + +protected: + + VHumanoidActorAnimationController mAnimationController; + VHumanoidActorPhysicsController mPhysicsController; + +public: + + VHumanoidActor( void ); + ~VHumanoidActor( void ); + + // Initialisation Methods. + + bool onNewDataBlock( GameBaseData *pDataBlock, bool pReload ); + + // Update Methods. + + void processTick( const Move *pMove ); + void interpolateTick( F32 pDelta ); + void advanceTime( F32 pDelta ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + // Animation Methods. + + bool initAnimationController( void ); + VActorAnimationController *getAnimationController( void ); + + // Physics Methods. + + bool initPhysicsController( void ); + VActorPhysicsController *getPhysicsController( void ); + + DECLARE_CONOBJECT( VHumanoidActor ); +}; + +#endif // _VT_VHUMANOIDACTOR_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp new file mode 100644 index 000000000..e6a1e4521 --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorAnimationController.h" + +//----------------------------------------------------------------------------- + +VHumanoidActorAnimationController::VHumanoidActorAnimationController( void ) +{ + // Void. +} + +VHumanoidActorAnimationController::~VHumanoidActorAnimationController( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- + +bool VHumanoidActorAnimationController::initArmAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Initialise Animation Ref. + return initAnimation( mArmAnimation, pIndex, pPosition, pTimeScale ); +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods +// +//----------------------------------------------------------------------------- + +void VHumanoidActorAnimationController::update( const F32 &pDelta ) +{ + // Parent Call. + VActorAnimationController::update( pDelta ); + + // Update the Look Thread. + if ( mArmAnimation.Thread ) + { + // Set Position. + getShapeInstance()->setPos( mArmAnimation.Thread, 0.5f ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h new file mode 100644 index 000000000..adf77fc0d --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ +#define _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ + +#ifndef _VT_VACTORANIMATIONCONTROLLER_H_ +#include "../VActorAnimationController.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VHumanoidActorAnimationController : public VActorAnimationController +{ +public: + + /* + struct sHeadAnimation + { + S32 HSequence; + TSThread *HThread; + Range HRange; + + S32 VSequence; + TSThread *VThread; + Range VRange; + + S32 FaceSequence; + TSThread *FaceThread; + + sHeadAnimation( void ) : + HSequence( -1 ), + HThread( NULL ), + HRange( 0.f, 1.f ), + VSequence( -1 ), + VThread( NULL ), + VRange( 0.f, 1.f ) + { + // Void. + } + }; + */ + +protected: + + //sHeadAnimation mHeadAnimation; + + sAnimationRef mHeadHAnimation; + sAnimationRef mHeadVAnimation; + sAnimationRef mArmAnimation; + +public: + + VHumanoidActorAnimationController( void ); + virtual ~VHumanoidActorAnimationController( void ); + + // Initialisation Methods. + + bool initArmAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + // Animation Methods. + + void update( const F32 &pDelta ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.cpp new file mode 100644 index 000000000..46a9eb448 --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.cpp @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorData.h" +#include "VHumanoidAnimationStates.h" +#include "VHumanoidPhysicsStates.h" + +//----------------------------------------------------------------------------- +// Animation Table. +//----------------------------------------------------------------------------- + +static VActorData::sAnimationSequence animSequenceLookup[] = + { + // State Based Animations. + { VHumanoidActorData::k_IdleAnimation, "root", 0.0f, ActorAnimationStateInstance( HumanoidIdle ) }, + + { VHumanoidActorData::k_WalkForwardAnimation, "walk", 0.1f, ActorAnimationStateInstance( HumanoidWalkForward ) }, + { VHumanoidActorData::k_WalkBackwardAnimation, "walkback", 0.1f, ActorAnimationStateInstance( HumanoidWalkBackward ) }, + + { VHumanoidActorData::k_RunForwardAnimation, "run", 0.1f, ActorAnimationStateInstance( HumanoidRunForward ) }, + { VHumanoidActorData::k_RunBackwardAnimation, "runback", 0.1f, ActorAnimationStateInstance( HumanoidRunBackward ) }, + + { VHumanoidActorData::k_SwimIdleAnimation, "swimroot", 1.0f, ActorAnimationStateInstance( HumanoidSwimIdle ) }, + { VHumanoidActorData::k_SwimForwardAnimation, "swim", 1.0f, ActorAnimationStateInstance( HumanoidSwimForward ) }, + { VHumanoidActorData::k_SwimBackwardAnimation, "swimback", 1.0f, ActorAnimationStateInstance( HumanoidSwimBackward ) }, + + // Support Animations. + { VHumanoidActorData::k_HeadHorizontalAnimation, "headside" }, + { VHumanoidActorData::k_HeadVerticalAnimation, "head" }, + + { VHumanoidActorData::k_ArmsUpDownAnimation, "look" }, + }; + +//----------------------------------------------------------------------------- +// Physics Table. +//----------------------------------------------------------------------------- + +static VActorData::sPhysicsState physStateLookup[] = + { + { VHumanoidActorData::k_OnGroundPhysics, 0.f, ActorPhysicsStateInstance( HumanoidOnGround ) }, + { VHumanoidActorData::k_InAirPhysics, 0.f, ActorPhysicsStateInstance( HumanoidInAir ) }, + { VHumanoidActorData::k_InWaterPhysics, 0.f, ActorPhysicsStateInstance( HumanoidInWater ) }, + }; + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_DATABLOCK_V1( VHumanoidActorData ); +//----------------------------------------------------------------------------- + +VHumanoidActorData::VHumanoidActorData( void ) +{ + // Void. +}; + +bool VHumanoidActorData::preload( bool pServer, String &pErrorStr ) +{ + if ( !Parent::preload( pServer, pErrorStr ) ) + { + return false; + } + + // Initialise Animation List. + if ( !initAnimationSequenceList( sizeof( animSequenceLookup ) / sizeof( VActorData::sAnimationSequence ), &animSequenceLookup[0] ) ) + { + Con::errorf( "VHumanoidActorData::preload() - Failed to Initialise Actor Animations." ); + return false; + } + + // Initialise Physics State List. + if ( !initPhysicsStateList( sizeof( physStateLookup ) / sizeof( VActorData::sPhysicsState ), &physStateLookup[0] ) ) + { + Con::errorf( "VHumanoidActorData::preload() - Failed to Initialise Actor Physics States." ); + return false; + } + + // Valid Load. + return true; +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.h new file mode 100644 index 000000000..0a5aa4b8c --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorData.h @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORDATA_H_ +#define _VT_VHUMANOIDACTORDATA_H_ + +#ifndef _VT_VACTORDATA_H_ +#include "../VActorData.h" +#endif + +//----------------------------------------------------------------------------- + +struct VHumanoidActorData : public VActorData +{ +private: + + typedef VActorData Parent; + friend class VHumanoidActor; + +public: + + enum eAnimationList + { + k_IdleAnimation = Parent::k_NextAnimation + 0, + + k_WalkForwardAnimation = Parent::k_NextAnimation + 1, + k_WalkBackwardAnimation = Parent::k_NextAnimation + 2, + + k_RunForwardAnimation = Parent::k_NextAnimation + 3, + k_RunBackwardAnimation = Parent::k_NextAnimation + 4, + + k_SwimIdleAnimation = Parent::k_NextAnimation + 5, + k_SwimForwardAnimation = Parent::k_NextAnimation + 6, + k_SwimBackwardAnimation = Parent::k_NextAnimation + 7, + + k_HeadHorizontalAnimation = Parent::k_NextAnimation + 8, + k_HeadVerticalAnimation = Parent::k_NextAnimation + 9, + + k_ArmsUpDownAnimation = Parent::k_NextAnimation + 10, + + k_NextAnimation = Parent::k_NextAnimation + 11, + }; + + enum ePhysicsStateList + { + k_OnGroundPhysics = Parent::k_NextPhysicsState + 0, + k_InAirPhysics = Parent::k_NextPhysicsState + 1, + k_InWaterPhysics = Parent::k_NextPhysicsState + 2, + + k_NextPhysicsState = Parent::k_NextPhysicsState + 3, + }; + +public: + + VHumanoidActorData( void ); + + virtual bool preload( bool pServer, String &pErrorStr ); + + DECLARE_CONOBJECT( VHumanoidActorData ); +}; + +#endif // _VT_VHUMANOIDACTORDATA_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp new file mode 100644 index 000000000..ae205c5cf --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorPhysicsController.h" + +//----------------------------------------------------------------------------- + +VHumanoidActorPhysicsController::VHumanoidActorPhysicsController( void ) +{ + // Void. +} + +VHumanoidActorPhysicsController::~VHumanoidActorPhysicsController( void ) +{ + // Void. +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h new file mode 100644 index 000000000..ef984210a --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ +#define _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ + +#ifndef _VT_VACTORPHYSICSCONTROLLER_H_ +#include "../VActorPhysicsController.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VHumanoidActorPhysicsController : public VActorPhysicsController +{ +public: + + VHumanoidActorPhysicsController( void ); + ~VHumanoidActorPhysicsController( void ); +}; + +#endif // _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp new file mode 100644 index 000000000..3ca29f7ce --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp @@ -0,0 +1,213 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidAnimationStates.h" +#include "VHumanoidActor.h" + +#include "../VActorAnimationController.h" +#include "../VActorPhysicsController.h" + +//----------------------------------------------------------------------------- +// +// Implement Animation States. +// +//----------------------------------------------------------------------------- + +ImplementActorAnimationState( HumanoidIdle, VHumanoidActorData::k_IdleAnimation ); + +ImplementActorAnimationState( HumanoidWalkForward, VHumanoidActorData::k_WalkForwardAnimation ); +ImplementActorAnimationState( HumanoidWalkBackward, VHumanoidActorData::k_WalkBackwardAnimation ); + +ImplementActorAnimationState( HumanoidRunForward, VHumanoidActorData::k_RunForwardAnimation ); +ImplementActorAnimationState( HumanoidRunBackward, VHumanoidActorData::k_RunBackwardAnimation ); + +ImplementActorAnimationState( HumanoidSwimIdle, VHumanoidActorData::k_SwimIdleAnimation ); +ImplementActorAnimationState( HumanoidSwimForward, VHumanoidActorData::k_SwimForwardAnimation ); +ImplementActorAnimationState( HumanoidSwimBackward, VHumanoidActorData::k_SwimBackwardAnimation ); + + + + +//----------------------------------------------------------------------------- +// +// Execute Animation States. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// OnGround Animation States +// +//----------------------------------------------------------------------------- + +ExecuteActorAnimationState( HumanoidIdle ) +{ + // Always Enter. + return true; +} + +ExecuteActorAnimationState( HumanoidWalkForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Forward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Forward & Slow Enough? + return ( ( physicsController->getMoveState() & k_ForwardMove ) && + ( moveSpeed < pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidWalkBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Backward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Backward? + return ( ( physicsController->getMoveState() & k_BackwardMove ) && + ( moveSpeed < pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidRunForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Forward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Forward? + return ( ( physicsController->getMoveState() & k_ForwardMove ) && + ( moveSpeed >= pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidRunBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Backward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Backward? + return ( ( physicsController->getMoveState() & k_BackwardMove ) && + ( moveSpeed >= pObject->getDataBlock()->getRunSpeed() ) ); +} + + + + +//----------------------------------------------------------------------------- +// +// InWater Animation States +// +//----------------------------------------------------------------------------- + +ExecuteActorAnimationState( HumanoidSwimIdle ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Idle? + return ( physicsController->getMoveState() & k_NullMove ); +} + +ExecuteActorAnimationState( HumanoidSwimForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Moving Around? + return ( physicsController->getMoveState() & ( k_ForwardMove | + k_UpMove | + k_DownMove ) ); +} + +ExecuteActorAnimationState( HumanoidSwimBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Moving Backward? + return ( physicsController->getMoveState() & k_BackwardMove ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.h new file mode 100644 index 000000000..d71967d54 --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidAnimationStates.h @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDANIMATIONSTATES_H_ +#define _VT_VHUMANOIDANIMATIONSTATES_H_ + +#ifndef _VT_VACTORANIMATIONSTATES_H_ +#include "../VActorAnimationStates.h" +#endif + +//----------------------------------------------------------------------------- + +DeclareActorAnimationState( HumanoidIdle ); + +DeclareActorAnimationState( HumanoidWalkForward ); +DeclareActorAnimationState( HumanoidWalkBackward ); + +DeclareActorAnimationState( HumanoidRunForward ); +DeclareActorAnimationState( HumanoidRunBackward ); + +DeclareActorAnimationState( HumanoidSwimIdle ); +DeclareActorAnimationState( HumanoidSwimForward ); +DeclareActorAnimationState( HumanoidSwimBackward ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VHUMANOIDANIMATIONSTATES_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp b/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp new file mode 100644 index 000000000..c2b8492ba --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidPhysicsStates.h" +#include "VHumanoidActor.h" + +#include "../VActorPhysicsController.h" + +//----------------------------------------------------------------------------- +// +// Implement Physics States. +// +//----------------------------------------------------------------------------- + +ImplementActorPhysicsState( HumanoidOnGround, VHumanoidActorData::k_OnGroundPhysics ); +ImplementActorPhysicsState( HumanoidInAir, VHumanoidActorData::k_InAirPhysics ); +ImplementActorPhysicsState( HumanoidInWater, VHumanoidActorData::k_InWaterPhysics ); + + + + +//----------------------------------------------------------------------------- +// +// Execute Animation States. +// +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidOnGround ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( !physicsController->isOnGround() ) + { + // No. + return false; + } + + // On Ground. + return true; +} + +ProcessActorPhysicsState( HumanoidOnGround ) +{ + // Void. +} + +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidInAir ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Air? + if ( !physicsController->isInAir() ) + { + // No. + return false; + } + + // In Air. + return true; +} + +ProcessActorPhysicsState( HumanoidInAir ) +{ + // Apply Gravity for the Tick. + pObject->getPhysicsController()->applyGravity( pElapsedTime ); +} + +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidInWater ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // Sumberged? + if ( !physicsController->isInWater() ) + { + // No. + return false; + } + + // Swimming + return true; +} + +ProcessActorPhysicsState( HumanoidInWater ) +{ + // Void. +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h b/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h new file mode 100644 index 000000000..8020d53f5 --- /dev/null +++ b/Engine/modules/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDPHYSICSSTATES_H_ +#define _VT_VHUMANOIDPHYSICSSTATES_H_ + +#ifndef _VT_VACTORPHYSICSSTATES_H_ +#include "../VActorPhysicsStates.h" +#endif + +//----------------------------------------------------------------------------- + +DeclareActorPhysicsState( HumanoidOnGround ); +DeclareActorPhysicsState( HumanoidInAir ); +DeclareActorPhysicsState( HumanoidInWater ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VHUMANOIDPHYSICSSTATES_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Types/VEnumerators.h b/Engine/modules/Verve/VActor/Types/VEnumerators.h new file mode 100644 index 000000000..2300330db --- /dev/null +++ b/Engine/modules/Verve/VActor/Types/VEnumerators.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_ENUMERATORS_H_ +#define _VT_ENUMERATORS_H_ + +//----------------------------------------------------------------------------- + +enum eMove +{ + k_NullMove = 0, + + k_ForwardMove = ( 1 << 0 ), + k_BackwardMove = ( 1 << 1 ), + k_LeftMove = ( 1 << 2 ), + k_RightMove = ( 1 << 3 ), + k_UpMove = ( 1 << 4 ), + k_DownMove = ( 1 << 5 ), + + k_XMove = ( k_LeftMove | k_RightMove ), + k_YMove = ( k_ForwardMove | k_BackwardMove ), + k_ZMove = ( k_UpMove | k_DownMove ), +}; + +enum eControlState +{ + k_NullControlState = 0, + + k_PathControlState, + k_GoToControlState, +}; + +#endif // _VT_ENUMERATORS_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Types/VRange.h b/Engine/modules/Verve/VActor/Types/VRange.h new file mode 100644 index 000000000..bb28a27e5 --- /dev/null +++ b/Engine/modules/Verve/VActor/Types/VRange.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TYPERANGE_H_ +#define _VT_TYPERANGE_H_ + +#ifndef _TORQUE_TYPES_H_ +#include "platform/types.h" +#endif + +class Range +{ +public: + + Range( void ) : + Min( 0.f ), + Max( 1.f ), + Delta( 1.f ) + { + // Void. + }; + + Range( F32 pMin, F32 pMax ) : + Min( pMin ), + Max( pMax ), + Delta( pMax - pMin ) + { + // Void. + }; + + F32 Min; + F32 Max; + F32 Delta; +}; + +#endif // _VT_TYPERANGE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/Types/VTypes.h b/Engine/modules/Verve/VActor/Types/VTypes.h new file mode 100644 index 000000000..cc6c4918d --- /dev/null +++ b/Engine/modules/Verve/VActor/Types/VTypes.h @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TYPES_H_ +#define _VT_TYPES_H_ + +#ifndef _VT_ENUMERATORS_H_ +#include "VEnumerators.h" +#endif + +#ifndef _VT_TYPERANGE_H_ +#include "VRange.h" +#endif + +#endif // _VT_TYPES_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActor.cpp b/Engine/modules/Verve/VActor/VActor.cpp new file mode 100644 index 000000000..97dcb0257 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActor.cpp @@ -0,0 +1,232 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActor.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VActor ); +//----------------------------------------------------------------------------- + +VActor::VActor( void ) : + mDataBlock( NULL ) +{ + // Void. +} + +VActor::~VActor( void ) +{ + // Void. +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::onAdd(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActor::onAdd( void ) +{ + if ( !Parent::onAdd() || !mDataBlock ) + { + return false; + } + + // Add to Scene. + addToScene(); + + if ( isServerObject() ) + { + // Script Callback. + scriptOnAdd(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VActor::onRemove(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onRemove( void ) +{ + // Script Callback. + scriptOnRemove(); + + // Remove From Scene. + removeFromScene(); + + Parent::onRemove(); +} + +//----------------------------------------------------------------------------- +// +// VActor::onNewDataBlock( pDataBlock ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActor::onNewDataBlock( GameBaseData *pDataBlock, bool pReload ) +{ + // Store DataBlock Reference. + mDataBlock = dynamic_cast( pDataBlock ); + + if ( !mDataBlock ) + { + // Invalid Data. + return false; + } + + // Parent Call. + return Parent::onNewDataBlock( pDataBlock, pReload ); +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::processTick( pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::processTick( const Move *pMove ) +{ + // Parent Call. + Parent::processTick( pMove ); + + // Triggers? + if ( pMove && mDamageState == Enabled ) + { + // Handle each Image Trigger. + const U32 imageCount = getMin( ShapeBase::MaxMountedImages, MaxTriggerKeys ); + for ( U32 i = 0; i < imageCount; i++ ) + { + setImageTriggerState( i, pMove->trigger[i] ); + } + } +} + +//----------------------------------------------------------------------------- +// +// VActor::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActor::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Parent Call. + return Parent::packUpdate( pConnection, pMask, pStream ); +} + +//----------------------------------------------------------------------------- +// +// VActor::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Parent Call. + Parent::unpackUpdate( pConnection, pStream ); +} + + + + +//----------------------------------------------------------------------------- +// +// Physics Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::setTransform( pMatrix ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::setTransform( const MatrixF &pMatrix ) +{ + Parent::setTransform( pMatrix ); + + // Server Object? + if ( isServerObject() ) + { + // Move Object. + setMaskBits( MoveMask ); + } +} + +//----------------------------------------------------------------------------- +// +// VActor::onMount( pObject, pNode ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onMount( SceneObject *pObject, S32 pNode ) +{ + // Parent Call. + Parent::onMount( pObject, pNode ); + + // Post Event. + mEventSignal.trigger( k_MountEvent ); +} + +//----------------------------------------------------------------------------- +// +// VActor::onUnmount( pObject, pNode ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onUnmount( SceneObject *pObject, S32 pNode ) +{ + // Parent Call. + Parent::onUnmount( pObject, pNode ); + + // Post Event. + mEventSignal.trigger( k_UnmountEvent ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActor.h b/Engine/modules/Verve/VActor/VActor.h new file mode 100644 index 000000000..3b0446f18 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActor.h @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTOR_H_ +#define _VT_VACTOR_H_ + +#ifndef _VT_VACTORDATA_H_ +#include "VActorData.h" +#endif + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +//----------------------------------------------------------------------------- +class VActorAnimationController; +class VActorPhysicsController; +//----------------------------------------------------------------------------- + +class VActor : public ShapeBase +{ + typedef ShapeBase Parent; + +public: + + enum eMaskBits + { + // Physics Bits. + MoveMask = Parent::NextFreeMask << 0, + PhysicsMask = ( MoveMask ), + + NextFreeMask = Parent::NextFreeMask << 1, + }; + + enum eEventType + { + k_MountEvent, + k_UnmountEvent, + }; + + typedef Signal tEventSignal; + +protected: + + VActorData *mDataBlock; + + // Event Signal. + tEventSignal mEventSignal; + +public: + + VActor( void ); + ~VActor( void ); + + // Initialisation Methods. + + bool onAdd( void ); + void onRemove( void ); + + bool onNewDataBlock( GameBaseData *pDataBlock, bool pReload ); + + // Update Methods. + + virtual void processTick( const Move *pMove ); + + virtual U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + virtual void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + DECLARE_CONOBJECT( VActor ); + +public: + + // Accessor Methods. + + inline VActorData *getDataBlock( void ) { return mDataBlock; }; + inline tEventSignal &getEventSignal( void ) { return mEventSignal; }; + + // Animation Methods. + + /// Get Animation Controller. + virtual VActorAnimationController *getAnimationController( void ) { return NULL; }; + + // Physics Methods. + + /// Set Transform. + virtual void setTransform( const MatrixF &pMatrix ); + + /// Get Physics Controller. + virtual VActorPhysicsController *getPhysicsController( void ) { return NULL; }; + + /// On Mount. + virtual void onMount( SceneObject *pObject, S32 pNode ); + /// On Unmount. + virtual void onUnmount( SceneObject *pObject, S32 pNode ); +}; + +#endif // _VT_VACTOR_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorAnimationController.cpp b/Engine/modules/Verve/VActor/VActorAnimationController.cpp new file mode 100644 index 000000000..b740c566a --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorAnimationController.cpp @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorAnimationController.h" + +#include "VActor.h" +#include "VActorData.h" +#include "VActorAnimationStates.h" + +//----------------------------------------------------------------------------- + +VActorAnimationController::VActorAnimationController( void ) : + mObject( NULL ) +{ + // Void. +} + +VActorAnimationController::~VActorAnimationController( void ) +{ + // Clear Table. + mAnimationTable.clear(); +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimationTable(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimationTable( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No, Quit Now. + return false; + } + + // Clear the Table. + mAnimationTable.clear(); + + // Fetch Sequence List. + VActorData::tAnimationSequenceVector *sequenceList = getObject()->getDataBlock()->getAnimationList(); + + // Initialise the Animation States. + for ( VActorData::tAnimationSequenceVector::iterator itr = sequenceList->begin(); + itr != sequenceList->end(); + itr++ ) + { + // Fetch Sequence Definition. + const VActorData::sAnimationSequence &animSequence = ( *itr ); + + // Valid State? + if ( animSequence.State ) + { + // Register Animation. + mAnimationTable.registerState( animSequence.State, animSequence.Priority ); + } + } + + // Sort the Table. + mAnimationTable.sort(); + + // Valid. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimation( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimation( sAnimationRef &pAnimation, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Valid Object & Sequence? + if ( !isValidObject() || !isAnimationSequence( pIndex ) ) + { + // No, Quit Now. + return false; + } + + // Store as Current Animation. + pAnimation.Index = pIndex; + + // Initialise Thread. + return initAnimationThread( pAnimation.Thread, pAnimation.Index, pPosition, pTimeScale ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimationThread( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimationThread( TSThread *&pThread, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Valid Object & Sequence? + if ( !isValidObject() || !isAnimationSequence( pIndex ) ) + { + // No, Quit Now. + return false; + } + + // Valid Thread? + if ( !pThread ) + { + // Create a Thread. + pThread = getShapeInstance()->addThread(); + } + + // Init the Sequence. + getShapeInstance()->setSequence( pThread, getAnimationSequence( pIndex ), pPosition ); + + // Set Initial Time Scale. + getShapeInstance()->setTimeScale( pThread, pTimeScale ); + + // Valid. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initBaseAnimation( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initBaseAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + return initAnimation( mBaseAnimation, pIndex, pPosition, pTimeScale ); +} + + + + +//----------------------------------------------------------------------------- +// +// Accessor Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::isValidObject(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::isValidObject( void ) +{ + return ( mObject != NULL && mObject->getDataBlock() != NULL ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getObject(); +// +// ... +// +//----------------------------------------------------------------------------- +VActor *VActorAnimationController::getObject( void ) +{ + return mObject; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::setObject( pObject ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorAnimationController::setObject( VActor *pObject ) +{ + // Set Object. + mObject = pObject; + + // Set Table's Reference. + mAnimationTable.setObject( pObject ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getShape(); +// +// ... +// +//----------------------------------------------------------------------------- +const TSShape *VActorAnimationController::getShape( void ) +{ + if ( !isValidObject() ) + { + return NULL; + } + + return mObject->getShape(); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getShapeInstance(); +// +// ... +// +//----------------------------------------------------------------------------- +TSShapeInstance *VActorAnimationController::getShapeInstance( void ) +{ + if ( !isValidObject() ) + { + return NULL; + } + + return mObject->getShapeInstance(); +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods +// +//----------------------------------------------------------------------------- + +void VActorAnimationController::update( const F32 &pDelta ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No, Quit Now. + return; + } + + // Update Animation State. + mAnimationTable.execute(); + + // Advance Threads. + getShapeInstance()->advanceTime( pDelta, mBaseAnimation.Thread ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::isAnimationSequence( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::isAnimationSequence( const U32 &pIndex ) +{ + return ( getAnimationSequence( pIndex ) != -1 ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getAnimationSequence( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +S32 VActorAnimationController::getAnimationSequence( const U32 &pIndex ) +{ + // Valid Object? + if ( !mObject || !mObject->getDataBlock() ) + { + // No, Invalid Sequence. + return -1; + } + + // Return Sequence. + return mObject->getDataBlock()->getAnimationSequence( pIndex ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getAnimation( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActorAnimationController::getAnimation( void ) +{ + // Base Animation Initialised? + if ( !mBaseAnimation.Thread ) + { + // Null. + return U32_MAX; + } + + // Return Current Animation. + return mBaseAnimation.Index; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::setAnimation( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorAnimationController::setAnimation( const U32 &pIndex ) +{ + // Base Animation Initialised? + if ( !mBaseAnimation.Thread || mBaseAnimation.Index == pIndex ) + { + // Don't Update. + return; + } + + // Store as Current Animation. + mBaseAnimation.Index = pIndex; + + // Fetch the Sequence. + const S32 &sequence = getAnimationSequence( pIndex ); + + // Valid? + if ( sequence != -1 ) + { + // Play the Sequence. + getShapeInstance()->transitionToSequence( mBaseAnimation.Thread, sequence, 0.f, 0.15f, true ); + //getShapeInstance()->setSequence( mBaseAnimation.Thread, sequence, 0.f ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorAnimationController.h b/Engine/modules/Verve/VActor/VActorAnimationController.h new file mode 100644 index 000000000..660248b8b --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorAnimationController.h @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORANIMATIONCONTROLLER_H_ +#define _VT_VACTORANIMATIONCONTROLLER_H_ + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSSHAPEINSTANCE_H_ +#include "ts/tsShapeInstance.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VActorAnimationController +{ +public: + + struct sAnimationRef + { + U32 Index; + TSThread *Thread; + + sAnimationRef( void ) : + Index( U32_MAX ), + Thread( NULL ) + { + // Void. + } + }; + +protected: + + VActor *mObject; + + VActorStateTable mAnimationTable; + sAnimationRef mBaseAnimation; + +public: + + VActorAnimationController( void ); + virtual ~VActorAnimationController( void ); + + // Initialisation Methods. + + bool initAnimationTable( void ); + bool initAnimation( sAnimationRef &pAnimation, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + bool initAnimationThread( TSThread *&pThread, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + bool initBaseAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + // Accessor Methods. + + bool isValidObject( void ); + VActor *getObject( void ); + void setObject( VActor *pObject ); + + const TSShape *getShape( void ); + TSShapeInstance *getShapeInstance( void ); + + // Animation Methods. + + virtual void update( const F32 &pDelta ); + + bool isAnimationSequence( const U32 &pIndex ); + S32 getAnimationSequence( const U32 &pIndex ); + + U32 getAnimation( void ); + void setAnimation( const U32 &pIndex ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorAnimationStates.h b/Engine/modules/Verve/VActor/VActorAnimationStates.h new file mode 100644 index 000000000..f1e0c44a6 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorAnimationStates.h @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORANIMATIONSTATES_H_ +#define _VT_VACTORANIMATIONSTATES_H_ + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSINGLETON_H_ +#include "core/util/tSingleton.h" +#endif + +//----------------------------------------------------------------------------- + +class VActorAnimationState : public VActorState +{ +public: + + virtual void exit( VActor *pObject ) {}; +}; + +//----------------------------------------------------------------------------- + +#define DeclareActorAnimationState( name ) \ + class VActor##name##AnimationState : public VActorAnimationState \ + { \ + public: \ + void enter( VActor *pObject ); \ + bool execute( VActor *pObject ); \ + } + +#define ActorAnimationStateInstance( name ) \ + Singleton::instance() + +#define ImplementActorAnimationState( name, sequence ) \ + void VActor##name##AnimationState::enter( VActor *pObject ) { pObject->getAnimationController()->setAnimation( sequence ); } + +#define ExecuteActorAnimationState( name ) \ + bool VActor##name##AnimationState::execute( VActor *pObject ) + +//----------------------------------------------------------------------------- + +#endif // _VT_VACTORANIMATIONSTATES_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorData.cpp b/Engine/modules/Verve/VActor/VActorData.cpp new file mode 100644 index 000000000..24d3b54d1 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorData.cpp @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorData.h" + +#include "console/consoleTypes.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_DATABLOCK_V1( VActorData ); +//----------------------------------------------------------------------------- + +VActorData::VActorData( void ) : + mMaxStepHeight( 1.f ), + mRunSpeed( 6.f ), + mSubmergeCoverage( 0.25f ) +{ + // Setup Shadowing. + shadowEnable = true; + shadowSize = 256; + shadowProjectionDistance = 14.0f; + + VECTOR_SET_ASSOCIATION( mAnimationSequenceList ); + VECTOR_SET_ASSOCIATION( mPhysicsList ); +} + +VActorData::~VActorData( void ) +{ + // Void. +} + +void VActorData::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "MaxStepHeight", TypeF32, Offset( mMaxStepHeight, VActorData ) ); + addField( "RunSpeed", TypeF32, Offset( mRunSpeed, VActorData ) ); + + addField( "SubmergeCoverage", TypeF32, Offset( mSubmergeCoverage, VActorData ) ); +} + +//----------------------------------------------------------------------------- + +bool VActorData::initAnimationSequenceList( const S32 &pSize, const sAnimationSequence *pTable ) +{ + if ( !mShape ) + { + // Sanity! + return false; + } + + // Clear the List. + mAnimationSequenceList.clear(); + + // Initialise each Animation Sequence. + for ( U32 i = 0; i < pSize; i++ ) + { + // Fetch Sequence Definition. + const sAnimationSequence &animSequenceDef = pTable[i]; + + // Update Animation Details. + sAnimationSequence animSequence = animSequenceDef; + // Find Sequence. + animSequence.Sequence = mShape->findSequence( animSequenceDef.Name ); + + // Store. + mAnimationSequenceList.push_back( animSequence ); + } + + return true; +} + +bool VActorData::initAnimationTransitionList( const S32 &pSize, const sAnimationTransition *pTable ) +{ + if ( !mShape ) + { + // Sanity! + return false; + } + + // Clear the List. + mAnimationTransitionList.clear(); + + // Store each Animation Transition. + for ( U32 i = 0; i < pSize; i++ ) + { + // Store. + mAnimationTransitionList.push_back( pTable[i] ); + } + + return true; +} + +bool VActorData::initPhysicsStateList( const S32 &pSize, const sPhysicsState *pTable ) +{ + // Clear the List. + mPhysicsList.clear(); + + // Initialise each Animation Sequence. + for ( U32 i = 0; i < pSize; i++ ) + { + // Store. + mPhysicsList.push_back( pTable[i] ); + } + + return true; +} + +//----------------------------------------------------------------------------- + +void VActorData::packData( BitStream *pStream ) +{ + Parent::packData( pStream ); + + pStream->write( mMaxStepHeight ); + pStream->write( mRunSpeed ); + + pStream->write( mSubmergeCoverage ); +} + +void VActorData::unpackData( BitStream *pStream ) +{ + Parent::unpackData( pStream ); + + pStream->read( &mMaxStepHeight ); + pStream->read( &mRunSpeed ); + + pStream->read( &mSubmergeCoverage ); +} + +//----------------------------------------------------------------------------- + +S32 VActorData::getAnimationSequence( const U32 &pIndex ) +{ + // Iterate over the Registered Animations. + for ( tAnimationSequenceVector::iterator itr = mAnimationSequenceList.begin(); itr != mAnimationSequenceList.end(); itr++ ) + { + // Fetch Sequence Defintion. + const sAnimationSequence &animSequence = ( *itr ); + + // Target Index? + if ( animSequence.Index == pIndex ) + { + // Return Sequence ID. + return animSequence.Sequence; + } + } + + // Invalid Sequence. + return -1; +}; \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorData.h b/Engine/modules/Verve/VActor/VActorData.h new file mode 100644 index 000000000..2aaf0fc58 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorData.h @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORDATA_H_ +#define _VT_VACTORDATA_H_ + +#ifndef _SHAPEBASE_H_ +#include "T3D/shapeBase.h" +#endif + +//----------------------------------------------------------------------------- +class VActor; +class VActorStateTable; +class VActorAnimationState; +class VActorPhysicsState; +//----------------------------------------------------------------------------- + +struct VActorData : public ShapeBaseData +{ +private: + + typedef ShapeBaseData Parent; + friend class VActor; + +public: + + // Animation Data. + + enum eAnimationList + { + k_NextAnimation = 0, + }; + + struct sAnimationSequence + { + U32 Index; + const char *Name; + F32 Priority; + + VActorAnimationState *State; + S32 Sequence; + }; + + struct sAnimationTransition + { + U32 FromIndex; + U32 ToIndex; + + F32 Duration; + + bool Ordered; + U32 Sequence; + }; + + typedef Vector tAnimationSequenceVector; + typedef Vector tAnimationTransitionVector; + + // Physics Data. + + enum ePhysicsStateList + { + k_NextPhysicsState = 0, + }; + + struct sPhysicsState + { + U32 Index; + F32 Priority; + + VActorPhysicsState *State; + }; + typedef Vector tPhysicsStateVector; + +protected: + + tAnimationSequenceVector mAnimationSequenceList; + tAnimationTransitionVector mAnimationTransitionList; + tPhysicsStateVector mPhysicsList; + + F32 mMaxStepHeight; + F32 mRunSpeed; + + F32 mSubmergeCoverage; + +public: + + VActorData( void ); + ~VActorData( void ); + + static void initPersistFields( void ); + + virtual bool initAnimationSequenceList( const S32 &pSize, const sAnimationSequence *pTable ); + virtual bool initAnimationTransitionList( const S32 &pSize, const sAnimationTransition *pTable ); + virtual bool initPhysicsStateList( const S32 &pSize, const sPhysicsState *pTable ); + + virtual void packData( BitStream *pStream ); + virtual void unpackData( BitStream *pStream ); + + DECLARE_CONOBJECT( VActorData ); + +public: + + tAnimationSequenceVector *getAnimationList( void ) { return &mAnimationSequenceList; }; + S32 getAnimationSequence( const U32 &pIndex ); + + tPhysicsStateVector *getPhysicsStateList( void ) { return &mPhysicsList; }; + + inline const F32 &getMaxStepHeight( void ) const { return mMaxStepHeight; }; + inline const F32 &getRunSpeed( void ) const { return mRunSpeed; }; + inline const F32 &getSumbergeCoverage( void ) const { return mSubmergeCoverage; }; +}; + +#endif // _VT_VACTORDATA_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorPhysicsController.cpp b/Engine/modules/Verve/VActor/VActorPhysicsController.cpp new file mode 100644 index 000000000..5e3332d59 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorPhysicsController.cpp @@ -0,0 +1,1277 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorPhysicsController.h" + +#include "VActor.h" +#include "VActorData.h" +#include "VActorPhysicsStates.h" + +#include "Verve/VPath/VPath.h" + +#include "collision/clippedPolyList.h" +#include "collision/earlyOutPolyList.h" +#include "collision/extrudedPolyList.h" +#include "core/stream/bitStream.h" +#include "environment/waterObject.h" + +//----------------------------------------------------------------------------- + +static const U32 sGroundCollisionMask = ( StaticObjectType | StaticShapeObjectType | TerrainObjectType ); +static const U32 sMoveCollisionMask = ( PlayerObjectType | VehicleObjectType ); +static const U32 sCollisionMask = ( sGroundCollisionMask | sMoveCollisionMask ); + +//----------------------------------------------------------------------------- + +VActorPhysicsController::VActorPhysicsController( void ) : + mObject( NULL ), + mMountedPath( NULL ), + mPhysicsState( 0 ), + mControlState( k_NullControlState ), + mMoveState( k_NullMove ), + mVelocity( VectorF::Zero ), + mGravity( 0.f, 0.f, -9.8f ) +{ + // Void. +} + +VActorPhysicsController::~VActorPhysicsController( void ) +{ + // Clear Object. + clearObject(); +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::initPhysicsController(); +// +// Initialise the physics table and setup the interface between the Controller +// and the reference object. +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::initPhysicsController( VActor *pObject ) +{ + // Valid Object? + if ( !pObject ) + { + // Assert & Quit. + AssertFatal( false, "VActorPhysicsController::initPhysicsController() - Invalid Object Specified." ); + return false; + } + + // Set Object. + mObject = pObject; + // Register for Actor Events. + mObject->getEventSignal().notify( this, &VActorPhysicsController::onActorEvent ); + + // Set Table's Reference. + mPhysicsStateTable.setObject( pObject ); + + // Init the Convex Box. + mConvex.init( pObject ); + + // Reset Interp. + mInterpController.resetDelta( pObject->getTransform() ); + + // Validate. + return initPhysicsTable(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::initPhysicsTable(); +// +// Register the available physics states which this controller may utilize. +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::initPhysicsTable( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No, Quit Now. + return false; + } + + // Clear the Table. + mPhysicsStateTable.clear(); + + // Fetch Sequence List. + VActorData::tPhysicsStateVector *stateList = getObjectDataBlock()->getPhysicsStateList(); + + // Initialise the Physics States. + for ( VActorData::tPhysicsStateVector::iterator itr = stateList->begin(); + itr != stateList->end(); + itr++ ) + { + // Fetch Sequence Definition. + const VActorData::sPhysicsState &physState = ( *itr ); + + // Valid State? + if ( physState.State ) + { + // Register State. + mPhysicsStateTable.registerState( physState.State, physState.Priority ); + } + } + + // Sort the Table. + mPhysicsStateTable.sort(); + + // Valid. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// Accessor Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isValidObject(); +// +// Do we have a valid reference object? +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::isValidObject( void ) +{ + return ( mObject && mObject->getDataBlock() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getObject(); +// +// Return the reference object. +// +//----------------------------------------------------------------------------- +VActor *VActorPhysicsController::getObject( void ) +{ + return mObject; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getObjectDataBlock(); +// +// Get the Actor Data for the reference object. +// +//----------------------------------------------------------------------------- +VActorData *VActorPhysicsController::getObjectDataBlock( void ) +{ + // Valid Object? + if ( !mObject ) + { + // No. + return NULL; + } + + // Return DataBlock. + return mObject->getDataBlock(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearObject(); +// +// Clear the reference object. Note that this should *never* be called outside +// of the controller's destructor! +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearObject( void ) +{ + // Valid Object? + if ( !mObject ) + { + // No. + return; + } + + // Clear Notify. + mObject->getEventSignal().remove( this, &VActorPhysicsController::onActorEvent ); + + // Clear Object. + mObject = NULL; + + // Clear Table. + mPhysicsStateTable.setObject( NULL ); + mPhysicsStateTable.clear(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getControlState(); +// +// Get the current Control State. +// +//----------------------------------------------------------------------------- +const U32 VActorPhysicsController::getControlState( void ) +{ + return mControlState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearControlState( pControlState ); +// +// Clear the Control State of a particular mask. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearControlState( const U32 &pControlState ) +{ + mControlState &= ( ~pControlState ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setControlState( pControlState ); +// +// Set the Control State. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setControlState( const U32 &pControlState ) +{ + mControlState = pControlState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isMoving(); +// +// Is the Actor currently Moving? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isMoving( void ) +{ + return ( !mIsZero( getVelocity().lenSquared() ) ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isMoving( pMoveState ); +// +// Is the Actor currently moving with the desired state? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isMoving( const U32 &pMoveState ) +{ + // Moving? + return ( ( getMoveState() & pMoveState ) && isMoving() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getMoveState(); +// +// Get the current Move State. +// +//----------------------------------------------------------------------------- +const U32 VActorPhysicsController::getMoveState( void ) +{ + // Return Move State. + return mMoveState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearMoveState( pMoveState ); +// +// Clear the Move State of a particular mask. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearMoveState( const U32 &pMoveState ) +{ + // Set Move State. + mMoveState &= ( ~pMoveState ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setMoveState( pMoveState ); +// +// Set the Move State. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setMoveState( const U32 &pMoveState ) +{ + // Set Move State. + mMoveState = pMoveState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isPathing(); +// +// Is the Actor Pathing? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isPathing( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return false; + } + + return ( mMountedPath != NULL ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getPathObject(); +// +// Get the Path Object the Actor is mounted to. +// +//----------------------------------------------------------------------------- +VPath *VActorPhysicsController::getPathObject( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return NULL; + } + + return mMountedPath; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isOnGround(); +// +// Is the Actor On the Ground? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isOnGround( void ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No. + return false; + } + + // On Ground? + return ( mOnGround && mGroundObject && !isInWater() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isInAir(); +// +// Is the Actor in the Air? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isInAir( void ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No. + return false; + } + + // In Air? + return ( !isOnGround() && !isInWater() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isInWater(); +// +// Is the Actor in the Water? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isInWater( void ) +{ + // Valid Objects? + if ( !isValidObject() || !getWaterObject() ) + { + // No. + return false; + } + + // Submerged? + return ( ( mObject->getWaterCoverage() + POINT_EPSILON ) >= mObject->getDataBlock()->getSumbergeCoverage() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getWaterObject(); +// +// Get the current Water Object the Actor is in. +// +//----------------------------------------------------------------------------- +WaterObject *VActorPhysicsController::getWaterObject( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return NULL; + } + + return mObject->getCurrentWaterObject(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getTransform(); +// +// Get the Actor's Transform. +// +//----------------------------------------------------------------------------- +MatrixF VActorPhysicsController::getTransform( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return MatrixF::Identity; + } + + // Return Transform. + return mObject->getTransform(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setTransform( pTransform ); +// +// Set the Actor's Transform. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setTransform( const MatrixF &pTransform ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return; + } + + // Apply Transform. + mObject->setTransform( pTransform ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getPosition(); +// +// Get the Actor's Position. +// +//----------------------------------------------------------------------------- +Point3F VActorPhysicsController::getPosition( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return Point3F::Zero; + } + + // Return Position. + return mObject->getPosition(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setPosition( pPosition ); +// +// Set the Actor's Position. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setPosition( const Point3F &pPosition ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return; + } + + // Apply Position. + mObject->setPosition( pPosition ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::applyGravity( pElapsedTime ); +// +// Apply gravity for the elapsed period. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::applyGravity( const F32 &pElapsedTime ) +{ + // Get Velocity. + VectorF velocity = getVelocity(); + // Add Tick Gravity. + velocity += getGravity() * pElapsedTime; + // Apply. + setVelocity( velocity ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getVelocity(); +// +// Get the Actor's Velocity. +// +//----------------------------------------------------------------------------- +VectorF VActorPhysicsController::getVelocity( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return VectorF::Zero; + } + + // Return Velocity. + return mVelocity; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setVelocity( pVelocity ); +// +// Set the Actor's Velocity. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setVelocity( const VectorF &pVelocity ) +{ + // Set Velocity. + mVelocity = pVelocity; +} + + + + +//----------------------------------------------------------------------------- +// +// Physics Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::update( pDelta, pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::update( const F32 &pDelta, const Move *pMove ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No, Quit Now. + return; + } + + // Pre-tick Update. + preTickUpdate( pDelta ); + + // Integrate Tick Update. + integrateTickUpdate( pDelta, pMove ); + + // Post-tick Update. + postTickUpdate( pDelta ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::preTickUpdate( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::preTickUpdate( const F32 &pDelta ) +{ + // Pop Delta. + mInterpController.popDelta(); + + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::preTickUpdate() - Invalid Path State." ); + + // Fetch Mount Velocity. + const VectorF &mountVelocity = mMountedPath->getMountVelocity( mObject->getMountNode() ); + + // Use X & Y Velocity. + VectorF velocity = getVelocity(); + velocity.x = mountVelocity.x; + velocity.y = mountVelocity.y; + + // Apply Updates. + setVelocity( velocity ); + + } break; + } + + // Update Move State. + updateMoveState(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::integrateTickUpdate( pDelta, pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::integrateTickUpdate( const F32 &pDelta, const Move *pMove ) +{ + // Update Collision Set. + updateWorkingCollisionSet(); + // Ground Ground Status. + updateGroundStatus(); + + // Execute Physics Table. + VActorPhysicsState *physState = dynamic_cast( mPhysicsStateTable.execute() ); + // Assert. + AssertFatal( physState, "VActorPhysicsController::update() - Invalid Physics State in the Table." ); + + // Process the State. + physState->processTick( mObject, pDelta, pMove ); + + // Process Collisions. + processCollisions(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::postTickUpdate( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::postTickUpdate( const F32 &pDelta ) +{ + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::postTickUpdate() - Invalid Path State." ); + + // Fetch Mount Transform. + MatrixF transform; + mMountedPath->getMountTransform( mObject->getMountNode(), getTransform(), &transform ); + // Fetch Mount Position. + const Point3F &mountPosition = transform.getPosition(); + + // Update X & Y Position. + Point3F position = getPosition(); + position.x = mountPosition.x; + position.y = mountPosition.y; + + // In Water? + bool underWater = false; + if ( isInWater() ) + { + // Fetch Body of Water. + WaterObject *waterBody = getWaterObject(); + + // Fetch Surface Position. + const F32 &waterSurfacePosition = waterBody->getSurfaceHeight( Point2F( position.x, position.y ) ); + // Fetch Submersion Position. + const F32 sumbersionPosition = waterSurfacePosition - ( mObject->getWorldBox().len_z() * mObject->getDataBlock()->getSumbergeCoverage() ); + + // Choose a Z Value. + // Note: This is done so that the Actor will either path under the + // water, or it will swim along the water's surface. + position.z = getMin( mountPosition.z, sumbersionPosition ); + + // Under Water? + underWater = ( position.z < sumbersionPosition ); + } + + // Under Water? + if ( !underWater ) + { + // Fetch Y Column. + VectorF forwardVector; + transform.getColumn( 1, &forwardVector ); + + // Determine Angle. + const F32 &angle = -mAtan2( -forwardVector.x, forwardVector.y ); + + // Reset Transform. + transform.set( EulerF( 0.f, 0.f, angle ) ); + + // In the air? + if ( !isOnGround() ) + { + // Apply z-axis force. + position.z += ( getVelocity().z * pDelta ); + } + } + + // Update Transform. + transform.setPosition( position ); + + // Apply Update. + setTransform( transform ); + + } break; + + default : + { + // Fetch Transform. + MatrixF transform = getTransform(); + + // Determine the Post-Tick Position. + Point3F postTickPosition = getPosition() + ( getVelocity() * pDelta ); + // Set the Post Tick Position. + transform.setPosition( postTickPosition ); + + // Apply the Transform. + setTransform( transform ); + + } break; + } + + // Push Delta. + mInterpController.pushDelta( getTransform() ); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::interpolateTick( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::interpolateTick( const F32 &pDelta ) +{ + // Fetch Interpolated Transform. + const MatrixF transform = mInterpController.getTransform( pDelta ); + // Apply Render Transform. + mObject->setRenderTransform( transform ); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateWorkingCollisionSet(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateWorkingCollisionSet() +{ + // Contstruct Bounding Box. + const Box3F boundingBox = mConvex.getBoundingBox( getTransform(), mObject->getScale() ); + + // Determine Sweep Vector. + const VectorF sweepVector = ( getVelocity() * TickSec ); + + // Construct Swept Box. + Box3F sweptBox = boundingBox; + sweptBox.minExtents.setMin( boundingBox.minExtents + sweepVector ); + sweptBox.maxExtents.setMax( boundingBox.maxExtents + sweepVector ); + + // Update Collision List. + mObject->disableCollision(); + mConvex.updateWorkingList( sweptBox, sCollisionMask ); + mObject->enableCollision(); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateMoveState(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateMoveState( void ) +{ + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::updateMoveState() - Invalid Path State." ); + + // Update Move State. + VPathObject *pathObject = mMountedPath->getPathObject( mObject ); + if ( !pathObject->isActive() ) + { + // Idle. + setMoveState( k_NullMove ); + } + else + { + // Set Movement Direction. + setMoveState( ( pathObject->isForward() ) ? k_ForwardMove : k_BackwardMove ); + } + + } break; + + default : + { + // Set Idle. + setMoveState( k_NullMove ); + + } break; + } +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearGroundStatus(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearGroundStatus( void ) +{ + // Clear Grounding. + mOnGround = false; + mGroundObject = NULL; + mGroundNormal.zero(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateGroundStatus(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateGroundStatus( void ) +{ + // Submerged? + if ( isInWater() ) + { + // Clear Ground Status. + clearGroundStatus(); + return; + } + + // Check for Grounding. + SceneObject *groundObject; + Point3F groundPoint; + VectorF groundNormal; + if ( !findGroundContact( groundObject, groundPoint, groundNormal ) ) + { + // Clear Ground Status. + clearGroundStatus(); + return; + } + + // Tidy up the Contact Position. + // Note: This basically "clamps" the Actor to the surface of the ground + // object. + const Point3F objPosition = getPosition(); + setPosition( objPosition - Point3F( 0.f, 0.f, ( objPosition.z - groundPoint.z ) ) ); + + // Clear Z-Axis Velocity. + mVelocity.z = 0.f; + + // Store Details. + mOnGround = true; + mGroundObject = groundObject; + mGroundNormal = groundNormal; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::findGroundContact( pContactObject, pContactPoint, pContactNormal ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal ) +{ + // Setup Collision List. + static CollisionList sCollisionList; + sCollisionList.clear(); + + static Polyhedron sBoxPolyhedron; + static ExtrudedPolyList sExtrudedPolyList; + + // Fetch Max Step Height. + const F32 stepHeight = mObject->getDataBlock()->getMaxStepHeight(); + + // Determine Positions. + const Point3F preTickPosition = getPosition() + Point3F( 0.f, 0.f, stepHeight ); + const VectorF preTickVelocity = getVelocity() + mGravity - VectorF( 0.f, 0.f, stepHeight / TickSec ); + const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); + const VectorF postTickVector = postTickPosition - preTickPosition; + + // Construct Scaled Box. + Box3F scaledBox = mObject->getObjBox(); + scaledBox.minExtents.convolve( mObject->getScale() ); + scaledBox.maxExtents.convolve( mObject->getScale() ); + + // Setup Polyherdron. + MatrixF collisionMatrix( true ); + collisionMatrix.setPosition( preTickPosition ); + sBoxPolyhedron.buildBox( collisionMatrix, scaledBox ); + + // Setup Extruded Poly List. + sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); + sExtrudedPolyList.setVelocity( preTickVelocity ); + sExtrudedPolyList.setCollisionList( &sCollisionList ); + + // Construct World Convex Box & Adjust for Sweep. + Box3F convexBox = scaledBox; + getTransform().mul( convexBox ); + convexBox.minExtents += postTickVector; + convexBox.maxExtents += postTickVector; + + // Build List of Contacts. + CollisionWorkingList &rList = mConvex.getWorkingList(); + for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) + { + Convex *convexShape = pList->mConvex; + + // Ground Object? + if ( !( convexShape->getObject()->getTypeMask() & sGroundCollisionMask ) ) + { + // No, Continue. + continue; + } + + // Overlap? + const Box3F &collisionConvexBox = convexShape->getBoundingBox(); + if ( convexBox.isOverlapped( collisionConvexBox ) ) + { + // Build Contact Information. + convexShape->getPolyList( &sExtrudedPolyList ); + } + } + + // Valid Collision? + if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() < 0.f || sCollisionList.getTime() > 1.f ) + { + // No, Quit Now. + return false; + } + + // Use First Collision. + Collision *collision = &sCollisionList[0]; + + // More Collisions? + if ( sCollisionList.getCount() > 1 ) + { + // Check for Better Contacts. + for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) + { + if ( cp->faceDot > collision->faceDot ) + { + // Use this One. + collision = cp; + } + } + } + + // Set Properties. + pContactObject = collision->object; + //pContactPoint = collision->point; + pContactPoint = ( preTickPosition + ( preTickVelocity * TickSec * sCollisionList.getTime() ) ); + pContactNormal = collision->normal; + + // Valid Contact. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::processCollisions(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::processCollisions( void ) +{ + // Find & Resolve Collisions. + Collision *collision; + if ( findCollision( collision ) ) + { + // Solve the Collision. + solveCollision( collision ); + } +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::findCollision( pCollision ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::findCollision( Collision *&pCollision ) +{ + // Setup Collision List. + static CollisionList sCollisionList; + sCollisionList.clear(); + + static Polyhedron sBoxPolyhedron; + static ExtrudedPolyList sExtrudedPolyList; + + // Determine Positions. + const Point3F preTickPosition = getPosition(); + const VectorF preTickVelocity = getVelocity(); + const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); + const VectorF postTickVector = postTickPosition - preTickPosition; + + // Construct Scaled Box. + Box3F scaledBox = mObject->getObjBox(); + scaledBox.minExtents.convolve( mObject->getScale() ); + scaledBox.maxExtents.convolve( mObject->getScale() ); + + // Setup Polyherdron. + MatrixF collisionMatrix( true ); + collisionMatrix.setPosition( preTickPosition ); + sBoxPolyhedron.buildBox( collisionMatrix, scaledBox ); + + // Setup Extruded Poly List. + sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); + sExtrudedPolyList.setVelocity( preTickVelocity ); + sExtrudedPolyList.setCollisionList( &sCollisionList ); + + // Construct World Convex Box & Adjust for Sweep. + Box3F convexBox = scaledBox; + getTransform().mul( convexBox ); + convexBox.minExtents += postTickVector; + convexBox.maxExtents += postTickVector; + + // Determine the Collision Mask. + const U32 collisionMask = ( isInWater() ) ? ( sGroundCollisionMask | sMoveCollisionMask ) : sMoveCollisionMask; + + // Build List of Contacts. + CollisionWorkingList &rList = mConvex.getWorkingList(); + for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) + { + Convex *convexShape = pList->mConvex; + + // Valid Collision Target? + if ( !( convexShape->getObject()->getTypeMask() & collisionMask ) ) + { + // No, Continue. + continue; + } + + // Overlap? + const Box3F &collisionConvexBox = convexShape->getBoundingBox(); + if ( convexBox.isOverlapped( collisionConvexBox ) ) + { + // Build Contact Information. + convexShape->getPolyList( &sExtrudedPolyList ); + } + } + + // Valid Collision? + if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() > 1.f ) + { + // No, Quit Now. + return false; + } + + // Use First Collision. + Collision *collision = &sCollisionList[0]; + + // More Collisions? + if ( sCollisionList.getCount() > 1 ) + { + // Check for Better Contacts. + for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) + { + if ( cp->faceDot > collision->faceDot ) + { + // Use this One. + collision = cp; + } + } + } + + // Store Reference. + pCollision = collision; + + // Valid Collision. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::solveCollision( pCollision ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::solveCollision( Collision *pCollision ) +{ + // Fetch Velocity. + VectorF velocity = getVelocity(); + // Resolve Collision. + velocity -= ( pCollision->normal * mDot( getVelocity(), pCollision->normal ) ); + + // Pathing? + if ( isPathing() ) + { + // Clear X & Y Velocity Adjustments. + // Note: This means that any collisions made during pathing will not + // be solved, unless they only affect Z position. It is up to the + // user to construct Paths which avoid obsticles! + velocity.x = velocity.y = 0.f; + } + + // Set Velocity. + setVelocity( velocity ); +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::onActorEvent( pEvent ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::onActorEvent( const VActor::eEventType &pEvent ) +{ + switch( pEvent ) + { + case VActor::k_MountEvent : + { + // Set Control State. + setControlState( k_PathControlState ); + + // Store Path. + mMountedPath = dynamic_cast( mObject->getObjectMount() ); + + } break; + + case VActor::k_UnmountEvent : + { + // Clear Control State. + clearControlState( k_PathControlState ); + + // Clear Path. + mMountedPath = NULL; + // Clear X & Y Velocity. + setVelocity( VectorF( 0.f, 0.f, mVelocity.z ) ); + + } break; + } +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActorPhysicsController::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Return Mask. + U32 retMask = 0; + + // Valid Object? + if ( !pStream->writeFlag( isValidObject() ) ) + { + return retMask; + } + + // Write Move? + const bool writeMove = ( pMask & VActor::MoveMask ) && !isPathing(); + if ( pStream->writeFlag( writeMove ) ) + { + // Write Position. + const Point3F &position = getPosition(); + pStream->write( position.x ); + pStream->write( position.y ); + pStream->write( position.z ); + } + + return retMask; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid Object? + if ( !pStream->readFlag() ) + { + return; + } + + // Read Move? + if ( pStream->readFlag() ) + { + // Read Position. + Point3F position; + pStream->read( &position.x ); + pStream->read( &position.y ); + pStream->read( &position.z ); + + // Apply. + setPosition( position ); + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorPhysicsController.h b/Engine/modules/Verve/VActor/VActorPhysicsController.h new file mode 100644 index 000000000..3e4a2912e --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorPhysicsController.h @@ -0,0 +1,160 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORPHYSICSCONTROLLER_H_ +#define _VT_VACTORPHYSICSCONTROLLER_H_ + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _VT_VACTOR_H_ +#include "VActor.h" +#endif + +#ifndef _VT_VINTERPCONTROLLER_H_ +#include "VInterpController.h" +#endif + +#ifndef _BOXCONVEX_H_ +#include "collision/boxConvex.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; + +//----------------------------------------------------------------------------- + +class VActorPhysicsController +{ +protected: + + SimObjectPtr mObject; + SimObjectPtr mMountedPath; + + VActorStateTable mPhysicsStateTable; + + VInterpController mInterpController; + + U32 mPhysicsState; + U32 mControlState; + U32 mMoveState; + + OrthoBoxConvex mConvex; + + VectorF mGravity; + VectorF mVelocity; + + bool mOnGround; + SimObjectPtr mGroundObject; + VectorF mGroundNormal; + +public: + + VActorPhysicsController( void ); + virtual ~VActorPhysicsController( void ); + + // Initialisation Methods. + + bool initPhysicsController( VActor *pObject ); + bool initPhysicsTable( void ); + + // Accessor Methods. + + bool isValidObject( void ); + VActor *getObject( void ); + VActorData *getObjectDataBlock( void ); + void clearObject( void ); + + virtual const U32 getControlState( void ); + virtual void clearControlState( const U32 &pControlState ); + virtual void setControlState( const U32 &pControlState ); + + virtual const bool isMoving( void ); + virtual const bool isMoving( const U32 &pMoveState ); + virtual const U32 getMoveState( void ); + virtual void clearMoveState( const U32 &pMoveState ); + virtual void setMoveState( const U32 &pMoveState ); + + virtual const bool isPathing( void ); + virtual VPath *getPathObject( void ); + + virtual const bool isInWater( void ); + virtual WaterObject *getWaterObject( void ); + + virtual const bool isOnGround( void ); + virtual const bool isInAir( void ); + inline SceneObject *getGroundObject( void ) { return mGroundObject; }; + inline const VectorF &getGroundNormal( void ) { return mGroundNormal; }; + + inline const U32 &getPhysicsState( void ) { return mPhysicsState; }; + inline void setPhysicsState( const U32 &pState ) { mPhysicsState = pState; }; + + virtual MatrixF getTransform( void ); + virtual void setTransform( const MatrixF &pTransform ); + + virtual Point3F getPosition( void ); + virtual void setPosition( const Point3F &pPosition ); + + inline VectorF getGravity( void ) { return mGravity; }; + inline void setGravity( VectorF &pGravity ) { mGravity = pGravity; }; + virtual void applyGravity( const F32 &pElapsedTime ); + + virtual VectorF getVelocity( void ); + virtual void setVelocity( const VectorF &pVelocity ); + + // Physics Methods. + + void update( const F32 &pDelta, const Move *pMove ); + + virtual void preTickUpdate( const F32 &pDelta ); + virtual void integrateTickUpdate( const F32 &pDelta, const Move *pMove ); + virtual void postTickUpdate( const F32 &pDelta ); + + void interpolateTick( const F32 &pDelta ); + + void updateWorkingCollisionSet( void ); + + void updateMoveState( void ); + + void clearGroundStatus( void ); + void updateGroundStatus( void ); + bool findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal ); + + void processCollisions( void ); + bool findCollision( Collision *&pCollision ); + void solveCollision( Collision *pCollision ); + + // Updates Methods. + + void onActorEvent( const VActor::eEventType &pEvent ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorPhysicsStates.h b/Engine/modules/Verve/VActor/VActorPhysicsStates.h new file mode 100644 index 000000000..24585b07a --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorPhysicsStates.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORPHYSICSSTATES_H_ +#define _VT_VACTORPHYSICSSTATES_H_ + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSINGLETON_H_ +#include "core/util/tSingleton.h" +#endif + +//----------------------------------------------------------------------------- +struct Move; +//----------------------------------------------------------------------------- + +class VActorPhysicsState : public VActorState +{ +public: + + virtual void exit( VActor *pObject ) {}; + + virtual void processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ) = 0; +}; + +//----------------------------------------------------------------------------- + +#define DeclareActorPhysicsState( name ) \ + class VActor##name##PhysicsState : public VActorPhysicsState \ + { \ + public: \ + void enter( VActor *pObject ); \ + bool execute( VActor *pObject ); \ + void processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ); \ + } + +#define ActorPhysicsStateInstance( name ) \ + Singleton::instance() + +#define ImplementActorPhysicsState( name, state ) \ + void VActor##name##PhysicsState::enter( VActor *pObject ) { pObject->getPhysicsController()->setPhysicsState( state ); } + +#define ExecuteActorPhysicsState( name ) \ + bool VActor##name##PhysicsState::execute( VActor *pObject ) + +#define ProcessActorPhysicsState( name ) \ + void VActor##name##PhysicsState::processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ) + +//----------------------------------------------------------------------------- + +#endif // _VT_VACTORPHYSICSSTATES_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorStateTable.cpp b/Engine/modules/Verve/VActor/VActorStateTable.cpp new file mode 100644 index 000000000..a2c065ce7 --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorStateTable.cpp @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorStateTable.h" +#include "VActor.h" + +//----------------------------------------------------------------------------- + +bool VActorStateTable::isRegisteredState( VActorState *pState ) +{ + for ( tStateConstIterator itr = mStateVector.begin(); itr != mStateVector.end(); itr++ ) + { + // Target State? + if ( ( *itr ).State == pState ) + { + // Yes. + return true; + } + } + + // No. + return false; +} + +void VActorStateTable::clear( void ) +{ + // Clear the States. + mLastState = NULL; + mCurrentState = NULL; + + // Clear the State Vector. + mStateVector.clear(); +}; + +void VActorStateTable::sort( void ) +{ + mStateVector.sort( &_onSortCallback ); +} + +void VActorStateTable::registerState( VActorState *pState, const F32 &pPriority ) +{ + // Already a State? + if ( isRegisteredState( pState ) ) + { + // Exit Now. + return; + } + + // Create the Reference. + sStateRef entry; + entry.State = pState; + entry.Priority = pPriority; + + // Push to Back. + mStateVector.push_back( entry ); + + // Set Current? + if ( mStateVector.size() == 1 ) + { + // Set State. + setState( pState ); + } +}; + +void VActorStateTable::setState( VActorState *pState ) +{ + if ( !mObject || !pState || pState == mCurrentState ) + { + // Invalid. + return; + } + + if ( mCurrentState ) + { + // Exit. + exit(); + + // Exit the Old State. + mCurrentState->exit( mObject ); + } + + // Update States. + mLastState = mCurrentState; + mCurrentState = pState; + + // Enter. + enter(); + + // Enter the New State. + pState->enter( mObject ); +}; + +VActorState *VActorStateTable::execute( void ) +{ + if ( !mObject || !mCurrentState ) + { + // Invalid. + return NULL; + } + + for ( tStateConstIterator itr = mStateVector.begin(); itr != mStateVector.end(); itr++ ) + { + // Fetch State Reference. + const sStateRef &stateRef = ( *itr ); + + // Enter State? + if ( stateRef.State->execute( mObject ) ) + { + // Set the State. + setState( stateRef.State ); + + // Return. + return stateRef.State; + } + } + + // No Valid Entries, Ouch! + Con::warnf( "VActorStateTable::execute() - No Valid Entries." ); + + // Return Current State. + return mCurrentState; +} + +S32 QSORT_CALLBACK VActorStateTable::_onSortCallback( const VActorStateTable::sStateRef *pA, const VActorStateTable::sStateRef *pB ) +{ + if ( pB->Priority > pA->Priority ) + { + return 1; + } + else if ( pB->Priority < pA->Priority ) + { + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VActorStateTable.h b/Engine/modules/Verve/VActor/VActorStateTable.h new file mode 100644 index 000000000..6a514a2fc --- /dev/null +++ b/Engine/modules/Verve/VActor/VActorStateTable.h @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORSTATETABLE_H_ +#define _VT_VACTORSTATETABLE_H_ + +#ifndef _TVECTOR_H +#include "core/util/tVector.h" +#endif + +//----------------------------------------------------------------------------- +class VActor; +class VActorStateTable; +//----------------------------------------------------------------------------- + +class VActorState +{ +public: + + VActorState( void ) { }; + virtual ~VActorState( void ) { }; + + virtual void enter( VActor *pObject ) = 0; + virtual bool execute( VActor *pObject ) = 0; + virtual void exit( VActor *pObject ) = 0; +}; + +//----------------------------------------------------------------------------- + +class VActorStateTable +{ +public: + + struct sStateRef + { + VActorState *State; + F32 Priority; + }; + + typedef Vector tStateVector; + typedef tStateVector::iterator tStateIterator; + typedef tStateVector::const_iterator tStateConstIterator; + +protected: + + tStateVector mStateVector; + + VActor *mObject; + + VActorState *mLastState; + VActorState *mCurrentState; + +public: + + VActorStateTable( void ) : + mObject( NULL ), + mLastState( NULL ), + mCurrentState( NULL ) + { + VECTOR_SET_ASSOCIATION( mStateVector ); + }; + + virtual ~VActorStateTable( void ) + { + // Clear Table. + clear(); + }; + + void registerState( VActorState *pState, const F32 &pPriority = 0.5f ); + + virtual void enter( void ) { }; + virtual VActorState *execute( void ); + virtual void exit( void ) { }; + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline VActor *getObject( void ) { return mObject; }; + + bool isRegisteredState( VActorState *pState ); + + inline VActorState *getCurrentState( void ) { return mCurrentState; }; + inline VActorState *getLastState( void ) { return mLastState; }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + void clear( void ); + void sort( void ); + + inline void setObject( VActor *pObject ) { mObject = pObject; }; + void setState( VActorState *pState ); + + //------------------------------------------------------------------------- + // + // Accessors + // + //------------------------------------------------------------------------- + + tStateConstIterator begin( void ) const { return mStateVector.begin(); }; + tStateConstIterator end( void ) const { return mStateVector.end(); }; + S32 size( void ) const { return mStateVector.size(); }; + +protected: + + static S32 QSORT_CALLBACK _onSortCallback( const VActorStateTable::sStateRef *pA, const VActorStateTable::sStateRef *pB ); +}; + +#endif // _VT_VACTORSTATETABLE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VActor/VInterpController.h b/Engine/modules/Verve/VActor/VInterpController.h new file mode 100644 index 000000000..3b9f34a1c --- /dev/null +++ b/Engine/modules/Verve/VActor/VInterpController.h @@ -0,0 +1,207 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VINTERPCONTROLLER_H_ +#define _VT_VINTERPCONTROLLER_H_ + +#ifndef _MATH_H_ +#include "math/mMath.h" +#endif + +//----------------------------------------------------------------------------- + +class VInterpController +{ +protected: + + Point3F mPosition[2]; + QuatF mRotation[2]; + +public: + + //------------------------------------------------------------------------- + // Interpolation Methods. + //------------------------------------------------------------------------- + + /// Get Position. + Point3F getPosition( const F32 &pDelta ) + { + // Interpolate Position. + Point3F interpPosition; + interpPosition.interpolate( mPosition[1], mPosition[0], pDelta ); + // Return Interpolated Point. + return interpPosition; + }; + + /// Get Rotation. + QuatF getRotation( const F32 &pDelta ) + { + // Interpolate Rotation. + QuatF interpRotation; + interpRotation.interpolate( mRotation[1], mRotation[0], pDelta ); + // Return Interpolated Quat. + return interpRotation; + }; + + /// Get Transform. + MatrixF getTransform( const F32 &pDelta ) + { + // Get Position. + const Point3F interpPosition = getPosition( pDelta ); + // Get Rotation. + const QuatF interpRotation = getRotation( pDelta ); + + // Setup Matrix. + MatrixF transform; + interpRotation.setMatrix( &transform ); + // Set Position. + transform.setPosition( interpPosition ); + + // Return Matrix. + return transform; + }; + + //------------------------------------------------------------------------- + // Delta Methods. + //------------------------------------------------------------------------- + + /// Reset Delta. + void resetDelta( const Point3F &pPosition, const QuatF &pRotation ) + { + mPosition[0] = mPosition[1] = pPosition; + mRotation[0] = mRotation[1] = pRotation; + }; + + /// Reset Delta. + void resetDelta( const MatrixF &pMatrix ) + { + // Setup Quat. + QuatF rotationQuat( pMatrix ); + // Reset Delta. + resetDelta( pMatrix.getPosition(), rotationQuat ); + }; + + /// Reset Delta (Vector) + void resetDelta( const Point3F &pPosition, const VectorF &pForwardVector ) + { + // Assert. + AssertFatal( pForwardVector.isUnitLength(), "VInterpController::resetDelta() - Forward Vector hasn't been Normalized." ); + + // Static Up Vector. + static const VectorF sUpVector( 0.f, 0.f, 1.f ); + + // X-Axis. + VectorF xVec = mCross( pForwardVector, sUpVector ); + xVec.normalize(); + // Z-Axis. + VectorF zVec = mCross( xVec, pForwardVector ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF transform; + transform.setColumn( 0, xVec ); + transform.setColumn( 1, pForwardVector ); + transform.setColumn( 2, zVec ); + transform.setColumn( 3, pPosition ); + + // Reset Delta. + resetDelta( transform ); + }; + + /// Reset Delta (AngAxis) + void resetDelta( const Point3F &pPosition, const AngAxisF &pAngAxis ) + { + // Setup Matrix. + MatrixF transform; + pAngAxis.setMatrix( &transform ); + // Set Position. + transform.setPosition( pPosition ); + + // Reset Delta. + resetDelta( transform ); + }; + + /// Push Delta. + void pushDelta( const Point3F &pPosition, const QuatF &pRotation ) + { + mPosition[1] = pPosition; + mRotation[1] = pRotation; + }; + + /// Push Delta (Matrix) + void pushDelta( const MatrixF &pMatrix ) + { + // Setup Quat. + QuatF rotationQuat( pMatrix ); + // Push Delta. + pushDelta( pMatrix.getPosition(), rotationQuat ); + }; + + /// Push Delta (Vector) + void pushDelta( const Point3F &pPosition, const VectorF &pForwardVector ) + { + // Assert. + AssertFatal( pForwardVector.isUnitLength(), "VInterpController::pushDelta() - Forward Vector hasn't been Normalized." ); + + // Static Up Vector. + static const VectorF sUpVector( 0.f, 0.f, 1.f ); + + // X-Axis. + VectorF xVec = mCross( pForwardVector, sUpVector ); + xVec.normalize(); + // Z-Axis. + VectorF zVec = mCross( xVec, pForwardVector ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF transform; + transform.setColumn( 0, xVec ); + transform.setColumn( 1, pForwardVector ); + transform.setColumn( 2, zVec ); + transform.setColumn( 3, pPosition ); + + // Push Delta. + pushDelta( transform ); + }; + + /// Push Delta (AngAxis) + void pushDelta( const Point3F &pPosition, const AngAxisF &pAngAxis ) + { + // Setup Matrix. + MatrixF transform; + pAngAxis.setMatrix( &transform ); + // Set Position. + transform.setPosition( pPosition ); + + // Push Delta. + pushDelta( transform ); + }; + + /// Pop Delta. + void popDelta( void ) + { + mPosition[0] = mPosition[1]; + mRotation[0] = mRotation[1]; + }; +}; + +#endif // _VT_VINTERPCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VNetState.cpp b/Engine/modules/Verve/VPath/VNetState.cpp new file mode 100644 index 000000000..d08c2ea0d --- /dev/null +++ b/Engine/modules/Verve/VPath/VNetState.cpp @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VNetState.h" + +//----------------------------------------------------------------------------- + +U32 VNetState::gInvalidMask = 0; + +//----------------------------------------------------------------------------- + +VNetState::VNetState() : + mMask( 0 ) +{ +} + +VNetState::~VNetState( void ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Delete State. + delete state; + } + + // Clear. + clear(); +} + +//----------------------------------------------------------------------------- +// +// Connection Methods. +// +//----------------------------------------------------------------------------- + +bool VNetState::isConnection( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + // Valid. + return true; + } + } + + // Invalid. + return false; +} + +void VNetState::addConnection( NetConnection *pConnection ) +{ + // Init State. + VNetStateInfo *state = new VNetStateInfo( pConnection, mMask ); + // Add. + push_back( state ); +} + +void VNetState::clearConnection( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + // Delete. + delete state; + // Erase. + erase( itr ); + // Quit. + return; + } + } +} + +//----------------------------------------------------------------------------- +// +// Mask Methods. +// +//----------------------------------------------------------------------------- + +VNetStateInfo *VNetState::getState( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + return state; + } + } + + return NULL; +} + +void VNetState::setMaskBits( const U32 &pMask ) +{ + // Apply Mask. + mMask |= pMask; + + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Apply Mask. + state->Mask |= pMask; + } +} + +void VNetState::clearMaskBits( const U32 &pMask ) +{ + // Clear Mask. + mMask &= ~pMask; + + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Clear Mask. + state->Mask &= ~pMask; + } +} \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VNetState.h b/Engine/modules/Verve/VPath/VNetState.h new file mode 100644 index 000000000..9cecef0a7 --- /dev/null +++ b/Engine/modules/Verve/VPath/VNetState.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VNETSTATE_H_ +#define _VT_VNETSTATE_H_ + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif + +//----------------------------------------------------------------------------- + +struct VNetStateInfo +{ + SimObjectPtr Connection; + U32 Mask; + + VNetStateInfo( void ) : + Connection( NULL ), + Mask( 0 ) + { + // Void. + }; + + VNetStateInfo( NetConnection *pConnection, U32 pMask ) + { + Connection = pConnection; + Mask = pMask; + }; +}; + +//----------------------------------------------------------------------------- + +class VNetState : public Vector +{ +protected: + + static U32 gInvalidMask; + + U32 mMask; + +public: + + VNetState( void ); + virtual ~VNetState( void ); + + // Connection Methods. + + bool isConnection( NetConnection *pConnection ); + void addConnection( NetConnection *pConnection ); + void clearConnection( NetConnection *pConnection ); + + // Property Methods. + + VNetStateInfo *getState( NetConnection *pConnection ); + + void setMaskBits( const U32 &pMask ); + void clearMaskBits( const U32 &pMask ); +}; + +#endif // _VT_VNETSTATE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPath.cpp b/Engine/modules/Verve/VPath/VPath.cpp new file mode 100644 index 000000000..762055cca --- /dev/null +++ b/Engine/modules/Verve/VPath/VPath.cpp @@ -0,0 +1,3452 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPath.h" + +#include "console/consoleTypes.h" +#include "core/iTickable.h" +#include "core/stream/bitStream.h" +#include "math/mMathFn.h" +#include "math/mathIO.h" + +//----------------------------------------------------------------------------- + +// Uncomment this definition to debug the network information. +//#define VPATH_DEBUG_NET + +// Uncomment this definition to debug the time step information +//#define VPATH_DEBUG_STEP + +//----------------------------------------------------------------------------- + +SimObjectPtr VPath::gServerSet = NULL; + +U32 VPath::gMaxNodeTransmit = 16; +U32 VPath::gMaxNodeBits = 8; +U32 VPath::gMaxNodeCount = 1 << gMaxNodeBits; // 256 + +U32 VPath::gMaxObjectTransmit = 4; +U32 VPath::gMaxObjectBits = 4; +U32 VPath::gMaxObjectCount = 1 << gMaxObjectBits; // 16 + +Point3F VPath::gBezierAxis( 0.f, 1.f, 0.f ); +Point3F VPath::gBezierUp( 0.f, 0.f, 1.f ); + +//----------------------------------------------------------------------------- + +static U32 gPathTypeBits = getBinLog2( getNextPow2( VPath::k_PathTypeSize ) ); +static F32 gBezierInterpStep = 0.0001f; + +//----------------------------------------------------------------------------- +// Path Type Table. +//----------------------------------------------------------------------------- + +// Implement the Path Type enum list. +ImplementEnumType( VPathType, "" ) + { VPath::k_PathBezier, "BEZIER" }, + { VPath::k_PathLinear, "LINEAR" }, +EndImplementEnumType; + +static VPath::ePathType getPathTypeEnum( const char *pLabel ) +{ + VPath::ePathType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPath::k_PathInvalid; + } + + // Return. + return out; +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VPath ); +//----------------------------------------------------------------------------- + +VPath::VPath( void ) : + mPathType( k_PathBezier ) +{ + // Marker Type. + mTypeMask = MarkerObjectType; + + // Ghost & Scope. + mNetFlags.set( Ghostable | ScopeAlways ); + + // Process Ticks. + setProcessTick( true ); + + VECTOR_SET_ASSOCIATION( mNodeList ); + VECTOR_SET_ASSOCIATION( mObjectList ); +} + +VPath::~VPath( void ) +{ + // Void. +} + +bool VPath::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + // Add to Scene. + addToScene(); + + if ( isServerObject() ) + { + // Read Fields. + readFields(); + + // Add to Set. + getServerSet()->addObject( this ); + } + + return true; +} + +void VPath::onDeleteNotify( SimObject *pObject ) +{ + // Parent Notify. + Parent::onDeleteNotify( pObject ); + + if ( SceneObject *sceneObject = dynamic_cast( pObject ) ) + { + // Detach Object. + detachObject( sceneObject ); + + // Exit. + return; + } + + if ( NetConnection *connection = dynamic_cast( pObject ) ) + { + // Clear Connection References. + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Erase Connection. + ( *itr )->clearConnection( connection ); + } + + // Exit. + return; + } +} + +void VPath::onRemove( void ) +{ + // Remove From Scene. + removeFromScene(); + + // Clear Everything. + clear(); + + Parent::onRemove(); +} + +void VPath::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "PathType", TYPEID(), Offset( mPathType, VPath ), &setPathType, &defaultProtectedGetFn, "The type of path this is." ); +} + +SimSet *VPath::getServerSet( void ) +{ + if ( !gServerSet ) + { + gServerSet = new SimSet(); + gServerSet->registerObject( "ServerPathSet" ); + Sim::getRootGroup()->addObject( gServerSet ); + } + + return gServerSet; +} + +ConsoleFunction( getServerPathSet, int, 1, 1, "( void )" ) +{ + return VPath::getServerSet()->getId(); +} + +//----------------------------------------------------------------------------- +// +// Editor Methods. +// +//----------------------------------------------------------------------------- + +bool VPath::collideBox( const Point3F &pStart, const Point3F &pEnd, RayInfo* pInfo ) +{ + if ( mObjBox.isContained( pStart ) ) + { + pInfo->t = 0.f; + pInfo->object = this; + pInfo->normal = VectorF( 0.f, 0.f, 1.f ); + pInfo->material = NULL; + + return true; + } + + return Parent::collideBox( pStart, pEnd, pInfo ); +} + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +F32 VPath::getUpdatePriority( CameraScopeQuery *pFocusObject, U32 pUpdateMask, S32 pUpdateSkips ) +{ + if ( mObjectList.size() > 0 ) + { + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Fetch Object. + VPathObject *pathObject = ( *itr ); + if ( pathObject->isActive() ) + { + // High Priority. + return 100.f; + } + } + } + + // Normal Priority. + return 0.f; +} + +void VPath::updateContainer( void ) +{ + if ( mNodeList.size() == 0 ) + { + // Sanity!. + return; + } + + // Init Min / Max. + mObjBox.minExtents = ( mNodeList[0]->getLocalPosition() ); + mObjBox.maxExtents = mObjBox.minExtents; + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Node Position. + const Point3F &nodeLocalPosition = node->getLocalPosition(); + + // Update Object Box. + mObjBox.minExtents.setMin( nodeLocalPosition ); + mObjBox.maxExtents.setMax( nodeLocalPosition ); + } + + // Adjust. + mObjBox.minExtents -= Point3F( 1.f, 1.f, 1.f ); + mObjBox.maxExtents += Point3F( 1.f, 1.f, 1.f ); + + // Reset Box. + resetWorldBox(); + resetRenderWorldBox(); +} + +void VPath::updateNodeTransforms( void ) +{ + // Fetch Transform Details. + const MatrixF &pathTransform = getTransform(); + const QuatF &pathRotation( pathTransform ); + const VectorF &pathScale = getScale(); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Fetch Node Spatials. + const Point3F &nodePosition = node->getLocalPosition(); + const QuatF &nodeRotation = node->getLocalRotation(); + + // Calculate the new Position. + Point3F newPosition = nodePosition; + newPosition.convolve( pathScale ); + pathTransform.mulP( newPosition ); + + // Calculate the new Rotation. + QuatF newRotation; + newRotation.mul( nodeRotation, pathRotation ); + + // Apply. + node->setWorldPosition( newPosition ); + node->setWorldRotation( newRotation ); + } +} + +void VPath::setTransform( const MatrixF &pMatrix ) +{ + // Parent Call. + Parent::setTransform( pMatrix ); + + // Update Nodes. + updateNodeTransforms(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +void VPath::setScale( const VectorF &pScale ) +{ + // Parent Call. + Parent::setScale( pScale ); + + // Update Nodes. + updateNodeTransforms(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +ConsoleMethod( VPath, setPathType, void, 3, 3, "( string pPathType ) - The path type dictates how attached objects move between nodes. There are currently two supported path types, \"BEZIER\" and \"LINEAR\".\n" + "@return No return value." ) +{ + // Fetch Enum. + const VPath::ePathType &type = getPathTypeEnum( argv[2] ); + + // Update. + object->setPathType( type ); +} + +void VPath::setPathType( const ePathType &pType ) +{ + // Apply Value. + mPathType = pType; + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +bool VPath::setPathType( void *pObject, const char *pArray, const char *pData ) +{ + // Apply Type. + static_cast( pObject )->setPathType( getPathTypeEnum( pData ) ); + return false; +} + +//----------------------------------------------------------------------------- +// +// Mounting Methods. +// +//----------------------------------------------------------------------------- + +bool VPath::isMountIndex( const U32 &pIndex ) +{ + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + // Yes. + return true; + } + } + + // No. + return false; +} + +U32 VPath::getAvailableMountIndex( void ) +{ + U32 i = 0; + while( isMountIndex( i ) ) + { + // Increment. + i++; + } + + // Return Index. + return i; +} + +void VPath::mountObject( SceneObject *pObject, S32 pIndex, const MatrixF &pTransform ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::mountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), isObjectAttached( pObject ) ); +#endif + + // Attached? + if ( !isObjectAttached( pObject ) ) + { + if ( isServerObject() ) + { + // Shouldn't Use this Method. + Con::warnf( "VPath::mountObject() - Use 'attachObject' instead." ); + } + + // Not Attached. + return; + } + + // Parent Call. + Parent::mountObject( pObject, pIndex, pTransform ); + + // Clear the mounted mask. + // Note: This is so that we send the mounting information via the VPath + // packets instead of letting T3D handle it. + pObject->clearMaskBits( SceneObject::MountedMask ); +} + +void VPath::unmountObject( SceneObject *pObject ) +{ + // Fetch Path Object. + VPathObject *pathObject = getPathObject( pObject ); + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::unmountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), pathObject != NULL ); +#endif + + // Valid? + if ( !pathObject || pObject->getObjectMount() != this ) + { + // Warn. + Con::warnf( "VPath::unmountObject() - Object is not attached to this Path. %d", pObject->getId() ); + // Not Mounted Here! + return; + } + + // Parent Call. + Parent::unmountObject( pObject ); + + // Clear the mounted mask. + // Note: This is so that we send the mounting information via the VPath + // packets instead of letting T3D handle it. + pObject->clearMaskBits( SceneObject::MountedMask ); +} + +void VPath::getMountTransform( S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Reset Transform. + *pTransform = pInTransform; + // Sanity! + return; + } + + // Advance the Object. + advanceObject( pathObject, TickSec ); + + // Apply Transform. + *pTransform = pathObject->getTransform(); +} + +void VPath::getRenderMountTransform( F32 pDelta, S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Reset Transform. + *pTransform = pInTransform; + // Sanity! + return; + } + + // Apply Transform. + *pTransform = pathObject->getRenderTransform( pDelta ); +} + +VectorF VPath::getMountVelocity( const U32 &pIndex ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Sanity! + return VectorF::Zero; + } + + // Determine Velocity. + return ( pathObject->getOrientation() * pathObject->getSpeed() ); +} + +//----------------------------------------------------------------------------- +// +// Persistence Methods. +// +//----------------------------------------------------------------------------- + +void VPath::readFields( void ) +{ + const char *nodeData = ""; + for ( S32 nodeIndex = 0; dStrcmp( nodeData = getDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL ), "" ) != 0; nodeIndex++ ) + { + // Create Node. + VPathNode *node = createNode(); + // Deserialize the Node. + node->fromString( nodeData ); + // Add the Node. + addNode( node ); + + // Clear Field. + setDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL, "" ); + } + + // Update Transforms. + updateNodeTransforms(); + + // Update Size. + updateContainer(); + + // Calculate Path. + calculatePath(); +} + +void VPath::writeFields( Stream &pStream, U32 pTabStop ) +{ + // Field Name. + StringTableEntry fieldName = StringTable->insert( "node" ); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Set Field. + setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), ( *itr )->toString().c_str() ); + } + + // Write Fields. + Parent::writeFields( pStream, pTabStop ); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Clear Field. + setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), "" ); + } +} + +U32 VPath::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + U32 retMask = Parent::packUpdate( pConnection, pMask, pStream ); + + if ( pMask & InitialUpdateMask ) + { + // Delete Notify. + deleteNotify( pConnection ); + } + + if ( pStream->writeFlag( pMask & PathUpdateMask ) ) + { + // Write Path Type. + pStream->writeInt( mPathType, gPathTypeBits ); + + // Write Transform. + mathWrite( *pStream, mObjToWorld ); + // Write Scale. + mathWrite( *pStream, mObjScale ); + } + + if ( pStream->writeFlag( pMask & NodeUpdateMask ) ) + { + // Path needs recalculating? + bool needsCalculating = false; + + // Delete Vector. + Vector deleteVector; + // Update Vector. + Vector updateVector; + + for ( U32 i = 0; i < mNodeList.size(); i++ ) + { + // Fetch Node. + VPathNode *node = mNodeList[i]; + + // Already In Map? + if ( !node->isConnection( pConnection ) ) + { + // Insert. + node->addConnection( pConnection ); + } + + // Fetch State. + VNetStateInfo *state = node->getState( pConnection ); + + // Delete new node? + if ( state->Mask & VPathNode::k_StateDelete + && state->Mask & VPathNode::k_StateCreate ) + { + // Remove Node. + removeNode( i-- ); + // Flag true. + needsCalculating = true; + } + + // Delete? + else if ( state->Mask & VPathNode::k_StateDelete ) + { + // Add To List. + deleteVector.push_front( i ); + } + + // Update? + else if ( state->Mask & VPathNode::k_StateUpdate ) + { + if ( updateVector.size() < gMaxNodeTransmit ) + { + // Add To List. + updateVector.push_back( i ); + } + } + } + + // More Updates? + if ( updateVector.size() == gMaxNodeTransmit ) + { + // More Updates. + retMask |= NodeUpdateMask; + } + + // Write Count. + pStream->writeInt( updateVector.size(), gMaxNodeBits + 1 ); + + for ( Vector::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxNodeBits ); + // Pack Update. + retMask |= mNodeList[index]->packNode( pConnection, pStream ); + } + + // Write Count. + pStream->writeInt( deleteVector.size(), gMaxNodeBits + 1 ); + + if ( deleteVector.size() > 0 ) + { + for ( Vector::iterator itr = deleteVector.begin(); itr != deleteVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxNodeBits ); + // Remove Node. + removeNode( index ); + } + + // Flag true. + needsCalculating = true; + // Clear Vector. + deleteVector.clear(); + } + + // Recalculate path? + if ( needsCalculating ) + { + // Update Size. + updateContainer(); + // Calculate Path. + calculatePath(); + } + } + + if ( pStream->writeFlag( pMask & ObjectUpdateMask ) ) + { + // Detach Vector. + Vector detachVector; + // Update Vector. + Vector updateVector; + + for ( U32 i = 0; i < mObjectList.size(); i++ ) + { + // Fetch Node. + VPathObject *pathObject = mObjectList[i]; + + // Already In Map? + if ( !pathObject->isConnection( pConnection ) ) + { + // Insert. + pathObject->addConnection( pConnection ); + } + + // Fetch State. + VNetStateInfo *state = pathObject->getState( pConnection ); + + // Detach newly attached object? + if ( state->Mask & VPathObject::k_StateAttach + && state->Mask & VPathObject::k_StateDetach ) + { + // Process Detach. + onDetachObject( pathObject ); + // Decrease index. + i -= 1; + + // Skip. + continue; + } + + // Update? + if ( state->Mask & VPathObject::k_StateUpdate ) + { + if ( updateVector.size() < gMaxObjectTransmit ) + { + // Add To List. + updateVector.push_back( i ); + } + } + + // Detach? + if ( state->Mask & VPathObject::k_StateDetach ) + { + // Add To List. + detachVector.push_front( i ); + } + } + + // More Updates? + if ( updateVector.size() == gMaxObjectTransmit ) + { + // More Updates. + retMask |= ObjectUpdateMask; + } + + // Write Count. + pStream->writeInt( updateVector.size(), gMaxObjectBits + 1 ); + + for ( Vector::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxObjectBits ); + + // Fetch the object. + VPathObject *pathObject = mObjectList[index]; + // Fetch State. + VNetStateInfo *state = pathObject->getState( pConnection ); + + // Was the Object Attached? + if ( pStream->writeFlag( state->Mask & VPathObject::k_StateAttach ) ) + { +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::packUpdate() - Attached - %d | %d", isServerObject(), index ); +#endif + + // Clear Update. + state->Mask &= ~VPathObject::k_StateAttach; + } + + // Pack Object. + retMask |= mObjectList[index]->packUpdate( pConnection, pStream ); + } + + // Write Count. + pStream->writeInt( detachVector.size(), gMaxObjectBits + 1 ); + + if ( detachVector.size() > 0 ) + { + for ( Vector::iterator itr = detachVector.begin(); itr != detachVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + // Write Index. + pStream->writeInt( index, gMaxObjectBits ); + // Process Detach. + onDetachObject( mObjectList[index] ); + } + + // Clear Vector. + detachVector.clear(); + } + } + + // Return. + return retMask; +} + +void VPath::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + Parent::unpackUpdate( pConnection, pStream ); + + // Update Path? + if ( pStream->readFlag() ) + { + // Read Path Type. + mPathType = pStream->readInt( gPathTypeBits ); + + // Read Transform. + mathRead( *pStream, &mObjToWorld ); + // Read Scale. + mathRead( *pStream, &mObjScale ); + + // Update Nodes. + updateNodeTransforms(); + // Calculate Path. + calculatePath(); + } + + // Update Nodes? + if ( pStream->readFlag() ) + { + // Number To Update. + const U32 updateCount = pStream->readInt( gMaxNodeBits + 1 ); + + for ( U32 i = 0; i < updateCount; i++ ) + { + // Read Index. + const U32 nodeIndex = pStream->readInt( gMaxNodeBits ); + + // Was the Node Created? + if ( pStream->readFlag() ) + { + // Create Node. + VPathNode *node = createNode(); + // Add the Node. + addNode( node, nodeIndex ); + } + + // Reference Node. + VPathNode *node = mNodeList[nodeIndex]; + // Apply Update. + node->unpackNode( pConnection, pStream ); + } + + // Number To Delete. + const U32 deleteCount = pStream->readInt( gMaxNodeBits + 1 ); + + for ( U32 i = 0; i < deleteCount; i++ ) + { + // Remove Node. + removeNode( pStream->readInt( gMaxNodeBits ) ); + } + + // Update Size. + updateContainer(); + // Calculate Path. + calculatePath(); + } + + // Update Objects? + if ( pStream->readFlag() ) + { + // Number To Update. + const U32 updateCount = pStream->readInt( gMaxObjectBits + 1 ); + + for ( U32 i = 0; i < updateCount; i++ ) + { + // Read Index. + const U32 objectIndex = pStream->readInt( gMaxObjectBits ); + + // Read Attached. + // Note: The editor handles the both the server and client side attachment calls. + // This is dangerous because there could be a mix up in indices, but it is + // needed to ensure the editor runs smoothly :( + const bool wasAttached = pStream->readFlag(); + if ( wasAttached && objectIndex >= mObjectList.size() ) + { +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::unpackUpdate() - WasAttached - %d | %d", isServerObject(), objectIndex ); +#endif + + // Create & Add to the List. + attachObject( new VPathObject() ); + } + + // Reference Node. + VPathObject *pathObject = mObjectList[objectIndex]; + + // Unpack Update. + pathObject->unpackUpdate( pConnection, pStream ); + + // Object Attached this Unpack? + if ( wasAttached ) + { + // Reset. + setPathObjectInterp( pathObject, pathObject->getTimeInterp() ); + } + } + + // Number To Detach. + const U32 detachCount = pStream->readInt( gMaxObjectBits + 1 ); + + for ( U32 i = 0; i < detachCount; i++ ) + { + // Fetch the path object. + VPathObject *pathObject = mObjectList[pStream->readInt( gMaxObjectBits )]; + // Detach callback. + onDetachObject( pathObject ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Node Methods. +// +//----------------------------------------------------------------------------- + +VPathNode *VPath::createNode( void ) +{ + return new VPathNode(); +} + +void VPath::deleteNode( VPathNode *pNode ) +{ + delete pNode; +} + +void VPath::clear( void ) +{ + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + VPathObject *pathObject = ( *itr ); + + // Fetch the attached object. + SceneObject *refObject = pathObject->getObject(); + // Unmount Object. + unmountObject( refObject ); + + // Delete the Path Object. + delete pathObject; + } + + // Clear Object List. + mObjectList.clear(); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + deleteNode( ( *itr ) ); + } + + // Clear Node List. + mNodeList.clear(); + + if ( isServerObject() ) + { + // Update. + setMaskBits( NodeUpdateMask ); + } +} + +VPathNode *VPath::getNode( const S32 &pNodeIndex ) +{ + // Sanity! + AssertFatal( pNodeIndex >= 0 && pNodeIndex < mNodeList.size(), "VPath::getNode() - Invalid Index" ); + + // Return Node. + return mNodeList[pNodeIndex]; +} + +ConsoleMethod( VPath, addNode, void, 4, 5, "( transform pTransform, float pWeight, [int pLocation] ) - Add a node with the given properties. Nodes represent physical points that attached objects move towards or between, but the PathType determines \"how\" they move between them.\n" + "@param pTransform The position and rotation of the new node.\n" + "@param pWeight The weight of the new node.\n" + "@param pLocation The index of the new node.\n" + "@return No return value.") +{ + // Fetch Invers Path Transform. + MatrixF pathTransformInv = object->getTransform(); + pathTransformInv.setPosition( Point3F::Zero ); + pathTransformInv.inverse(); + + Point3F pos; + QuatF rot; + AngAxisF aa; + + // Scan. + dSscanf( argv[2], "%g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z, &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle ); + + // Set Rotation. + rot.set( aa ); + + // Weight. + F32 weight = dAtof( argv[3] ); + + // World to Local Position. + Point3F nodePosition = ( pos - object->getPosition() ); + pathTransformInv.mulP( nodePosition ); + + // World to Local Rotation. + MatrixF nodeRotationMat; + rot.setMatrix( &nodeRotationMat ); + pathTransformInv.mul( nodeRotationMat ); + + // Set Quat. + QuatF nodeRotation; + nodeRotation.set( nodeRotationMat ); + + S32 location = -1; + if ( argc >= 5 ) + { + // Target Location. + location = dAtoi( argv[4] ); + } + + // Add Node. + VPathNode *node = object->addNode( nodePosition, nodeRotation, weight, location ); + + // Valid Node? + if ( node ) + { + // Update Size. + object->updateContainer(); + + // Calculate Path. + object->calculatePath(); + } +} + +VPathNode *VPath::addNode( const Point3F &pPosition, const QuatF &pRotation, const F32 &pWeight, const S32 &pLocation ) +{ + // Reference Object. + VPathNode *pathNode = createNode(); + + // Store Properties. + pathNode->setLocalPosition( pPosition ); + pathNode->setLocalRotation( pRotation ); + pathNode->setWeight( pWeight ); + + // Add Node. + return addNode( pathNode, pLocation ); +} + +VPathNode *VPath::addNode( VPathNode *pNode, const S32 &pLocation ) +{ + if ( pNode->getPath() ) + { + // Error. + Con::errorf( "VPath::addNode() - Node already belongs to a Path, '%d'", pNode->getPath()->getId() ); + + return NULL; + } + else if ( mNodeList.size() == gMaxNodeCount ) + { + // Error. + Con::errorf( "VPath::addNode() - Reached Max Nodes (%d)", gMaxNodeCount ); + + // Delete Node. + deleteNode( pNode ); + + return NULL; + } + + // Set Path. + pNode->setPath( this ); + + // Update World Data. + pNode->updateWorldData(); + + if ( pLocation < 0 ) + { + // Push Back. + mNodeList.push_back( pNode ); + } + else + { + // Fetch Size. + const S32 nodeCount = mNodeList.size(); + + if ( pLocation >= nodeCount ) + { + // Push Back. + mNodeList.push_back( pNode ); + } + else + { + // Insert. + mNodeList.insert( ( mNodeList.address() + pLocation ), pNode ); + } + } + + if ( isServerObject() ) + { + // Update. + setMaskBits( NodeUpdateMask ); + } + + // Return Node. + return pNode; +} + +ConsoleMethod( VPath, deleteNode, void, 3, 3, "( int pNodeIndex ) - Delete the node with the given index. If you delete a node that an attached object is moving to, or from then the object's movement will adjust so that it has a valid path.\n" + "@param pNodeIndex The index of the node to be deleted.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Apply Update. + object->deleteNode( nodeIndex ); +} + +void VPath::deleteNode( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::deleteNode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Remove Node References. + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Fetch Object. + VPathObject *pathObject = ( *itr ); + + if ( ( pathObject->getSourceNode() >= pNodeIndex ) || ( pathObject->getDestinationNode() >= pNodeIndex ) ) + { + S32 srcNode = pathObject->getSourceNode(); + S32 dstNode = pathObject->getDestinationNode(); + + if ( pathObject->isForward() ) + { + if ( srcNode >= pNodeIndex ) + { + srcNode -= 1; + } + + if ( dstNode > pNodeIndex ) + { + dstNode -= 1; + } + } + else + { + if ( srcNode > pNodeIndex ) + { + srcNode -= 1; + } + + if ( dstNode >= pNodeIndex ) + { + dstNode -= 1; + } + } + + // Normalize indices. + normalizeNodeIndex( srcNode, ( mNodeList.size() - 1 ) ); + normalizeNodeIndex( dstNode, ( mNodeList.size() - 1 ) ); + + // Apply Update. + pathObject->setNode( srcNode, dstNode ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + } + } + } + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + + // Flag for Deletion. + node->setMaskBits( VPathNode::k_StateDelete ); + } +} + +void VPath::removeNode( const S32 &pNodeIndex ) +{ + // Fetch the node. + VPathNode *node = getNode( pNodeIndex ); + if ( !node ) + { + // Quit. + return; + } + + // Delete Node. + deleteNode( node ); + // Erase Node. + mNodeList.erase( pNodeIndex ); +} + +S32 VPath::normalizeNodeIndex( S32 &pNodeIndex ) +{ + const S32 nodeCount = mNodeList.size(); + if ( nodeCount == 0 ) + { + // No Nodex. + pNodeIndex = 0; + } + else + { + while ( pNodeIndex < 0 ) + { + // Wrap Backwards. + pNodeIndex += nodeCount; + } + + // Wrap Forwards. + pNodeIndex %= nodeCount; + } + + // Return Index. + return pNodeIndex; +} + +S32 VPath::normalizeNodeIndex( const S32 &pNodeIndex ) +{ + // Temp. + S32 nodeIndex = pNodeIndex; + + // Return Index. + return normalizeNodeIndex( nodeIndex ); +} + +S32 VPath::normalizeNodeIndex( S32 &pNodeIndex, const S32 &pNodeCount ) +{ + if ( pNodeCount == 0 ) + { + // No Nodex. + pNodeIndex = 0; + } + else + { + while ( pNodeIndex < 0 ) + { + // Wrap Backwards. + pNodeIndex += pNodeCount; + } + + // Wrap Forwards. + pNodeIndex %= pNodeCount; + } + + // Return Index. + return pNodeIndex; +} + +//----------------------------------------------------------------------------- +// +// Object Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VPath, isObjectAttached, bool, 3, 3, "( SimObject pObject ) - Is the object attached to this path?\n" + "@param pObject The SimObjectID of the object you wish to check.\n" + "@return Returns true if the object is attached to this path." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::isObjectAttached() - Invalid Target Object." ); + return false; + } + + // Attached? + return object->isObjectAttached( sceneObject ); +} + +bool VPath::isObjectAttached( SceneObject *pObject ) +{ + // Valid Object? + return ( getPathObject( pObject ) != NULL ); +} + +VPathObject *VPath::getPathObject( SceneObject *pObject ) +{ + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Correct Object? + if ( ( *itr )->getObject() == pObject ) + { + // Yes. + return ( *itr ); + } + } + + return NULL; +} + +ConsoleMethod( VPath, attachObject, void, 7, 8, "( SimObject pObject, bool pForward, float pSpeed, bool pRelative, int pStartNode, [int pEndNode] ) - Attach an object to this path with the given properties. If the object is already attached to a path, then a warning will be displayed and the object will *not* be attached to this path.\n" + "@param pObject The SimObjectID of the object to be attached.\n" + "@param pForward Should the object be moving forward?\n" + "@param pSpeed The speed that the object will travel around the path.\n" + "@param pRelative Offset the object based on the difference between the start node and its current position.\n" + "@param pStartNode The index of the node this object starts pathing from.\n" + "@param pEndNode The index of the node this object will stop pathing at." + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::attachObject() - Invalid Target Object." ); + return; + } + + // Fetch Direction. + const bool forward = dAtob( argv[3] ); + // Fetch Speed. + const F32 speed = dAtof( argv[4] ); + // Fetch Relativity. + const bool relative = dAtob( argv[5] ); + // Fetch Start Node. + const S32 startNode = dAtoi( argv[6] ); + // Fetch End Node. + const S32 endNode = ( argc >= 8 ) ? dAtoi( argv[7] ) : -1; + + // Attach Object. + object->attachObject( sceneObject, forward, speed, relative, startNode, endNode ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode ) +{ + attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, VPathObject::k_OrientationToPath, NULL ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode ) +{ + attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, pOrientationMode, NULL ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode, void *pOrientationData ) +{ + // Already Pathing? + if ( isObjectAttached( pObject ) ) + { + Con::warnf( "VPath::attachObject() - Object Already Attached to a Path." ); + return; + } + + // Determine Target Nodes. + const S32 srcNode = normalizeNodeIndex( pStartNode ); + const S32 dstNode = normalizeNodeIndex( ( pForward ) ? pStartNode + 1 : pStartNode - 1 ); + const S32 endNode = ( pEndNode == -1 ) ? pEndNode : normalizeNodeIndex( pEndNode ); + + // Valid Source Node? + if ( getNodeCount() == 0 || !getNode( srcNode ) ) + { + Con::warnf( "VPath::attachObject() - Invalid Start Node." ); + return; + } + + VPathObject *pathObject = new VPathObject(); + + // Init Properties. + pathObject->setActive( true ); + pathObject->setObject( pObject ); + + pathObject->setForward( pForward ); + + pathObject->setTimeInterp( 0.f ); + pathObject->setPathInterp( 0.f ); + pathObject->setOffset( Point3F::Zero ); + pathObject->setSpeed( pSpeed ); + + switch( pOrientationMode ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + pathObject->setOrientationMode( pOrientationMode ); + + } break; + + case VPathObject::k_OrientationToObject : + { + pathObject->setOrientationMode( pOrientationMode, (SceneObject*)pOrientationData ); + + } break; + + case VPathObject::k_OrientationToPoint : + { + pathObject->setOrientationMode( pOrientationMode, ( *(Point3F*)pOrientationData ) ); + + } break; + } + + pathObject->setNode( srcNode, dstNode ); + pathObject->setStartNode( srcNode ); + pathObject->setEndNode( endNode ); + + // Fetch Init Node. + VPathNode *node = mNodeList[srcNode]; + + // Relative Position? + if ( pRelative ) + { + // Set Position Offset. + pathObject->setOffset( pObject->getPosition() - node->getWorldPosition() ); + } + + // Set info. + setPathObjectInterp( pathObject, 0.f ); + + // Attach. + attachObject( pathObject ); +} + +void VPath::attachObject( VPathObject *pPathObject ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::attachObject() - %d", isServerObject() ); +#endif + + if ( mObjectList.size() == gMaxObjectCount ) + { + Con::errorf( "VPath::attachObject() - Reached Max Objects (%d)", gMaxObjectCount ); + return; + } + + // Add to List. + mObjectList.push_back( pPathObject ); + + // Callback. + onAttachObject( pPathObject ); + + if ( isServerObject() ) + { + // Update. + setMaskBits( ObjectUpdateMask ); + } +} + +void VPath::onAttachObject( VPathObject *pPathObject ) +{ + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject ) + { + return; + } + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::onAttachObject() - %d | %d", isServerObject(), refObject->getId() ); +#endif + + // Delete Notify. + deleteNotify( refObject ); + + if ( isServerObject() ) + { + // Fetch the Available Mount Index. + U32 mountIndex = getAvailableMountIndex(); + // Mount the Object to this Path. + mountObject( refObject, mountIndex ); + + // Return Buffer. + char buffer[1][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + + // Callback. + // VPath::onAttachObject( %object ); + Con::executef( this, "onAttachObject", buffer[0] ); + } +} + +ConsoleMethod( VPath, detachObject, void, 3, 3, "( SimObject pObject ) - Detach the object from this path in place.\n" + "@param pObject The SimObjectID of the object to be detached.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::detachObject() - Invalid Target Object." ); + return; + } + + // Detach Object. + object->detachObject( sceneObject ); +} + +void VPath::detachObject( SceneObject *pObject ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::detachObject() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Detach. + detachObject( pathObject ); +} + +void VPath::detachObject( VPathObject *pPathObject ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::detachObject() - %d", isServerObject() ); +#endif + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Detach. + pPathObject->setMaskBits( VPathObject::k_StateDetach ); + } + + /* + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( refObject ) + { + // Unmount Object. + unmountObject( refObject ); + } + */ +} + +void VPath::onDetachObject( VPathObject *pPathObject ) +{ + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject ) + { + return; + } + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::onDetachObject() - %d | %d", isServerObject(), refObject->getId() ); +#endif + + // Reset. + setPathObjectInterp( pPathObject, pPathObject->getTimeInterp() ); + // Unmount Object. + unmountObject( refObject ); + + // Delete the Path Object. + delete pPathObject; + // Remove from the Set. + mObjectList.erase( mObjectList.find_next( pPathObject ) ); + + // Clear Delete Notify. + clearNotify( refObject ); + + if ( isServerObject() ) + { + // Return Buffer. + char buffer[1][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + + // Callback. + // VPath::onDetachObject( %object ); + Con::executef( this, "onDetachObject", buffer[0] ); + } +} + +void VPath::processTick( const Move *pMove ) +{ +} + +void VPath::advanceObject( VPathObject *pPathObject, const F32 &pDelta ) +{ + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject || mIsZero( pDelta ) ) + { + // Ignore. + return; + } + + // Spatial Delta. + pPathObject->popDelta(); + + // Active and Moving? + if ( !pPathObject->isActive() || mIsZero( pPathObject->getSpeed() ) ) + { + // Update Delta. + pPathObject->pushDelta( refObject->getPosition(), refObject->getTransform().getForwardVector() ); + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + VPathNode *lenNode = ( pPathObject->isForward() ) ? srcNode : dstNode; + + // Calculate Interp Delta. + const F32 stepDistance = ( pPathObject->getSpeed() * pDelta ); + const F32 speedMod = ( pPathObject->getSpeed() / lenNode->getLength() ); + F32 timeInterp = pPathObject->getTimeInterp(); + F32 timeInterpDelta = ( speedMod * pDelta ); + F32 pathInterp = pPathObject->getPathInterp(); + F32 pathInterpDelta = 0.f; + + // Fetch the old position. + const Point3F oldPosition = pPathObject->getPosition(); + // Calculate the new position and path delta. + Point3F newPosition = getAdvancedPathPosition( pPathObject, stepDistance, pathInterpDelta ); + + // Finished? + if ( ( timeInterp + timeInterpDelta ) >= 1.f ) + { + // Finished? + if ( pPathObject->getDestinationNode() == pPathObject->getEndNode() ) + { + // Stop Updates. + pPathObject->setActive( false ); + } + else + { + // Update Nodes. + const S32 srcNodeIndex = pPathObject->getDestinationNode(); + const S32 dstNodeIndex = normalizeNodeIndex( ( pPathObject->isForward() ) ? srcNodeIndex + 1 : srcNodeIndex - 1 ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::errorf( "Change Node:\n Source, %d\n Destination, %d", srcNodeIndex, dstNodeIndex ); +#endif + + // Apply Changes. + pPathObject->setNode( srcNodeIndex, dstNodeIndex ); + pPathObject->setTimeInterp( 0.f ); + pPathObject->setPathInterp( 0.f ); + pPathObject->setPosition( newPosition ); + + // Reset local interp information. + timeInterp = 0.f; + timeInterpDelta = 0.f; + pathInterp = 0.f; + pathInterpDelta = 0.f; + + // Fetch the distance we've travelled. + const F32 &advanceDistance = ( newPosition - oldPosition ).len(); + // Any remaining distance? + if ( ( stepDistance - advanceDistance ) > 0.0001f ) + { + // Determine how much more we need to move. + Point3F newPosition0 = newPosition; + newPosition = getAdvancedPathPosition( pPathObject, ( stepDistance - advanceDistance ), pathInterpDelta ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::errorf( "Transition Step: %f\nTransition Distance: %f + %f = %f", pathInterpDelta, advanceDistance, ( newPosition - newPosition0 ).len(), advanceDistance + ( newPosition - newPosition0 ).len() ); +#endif + } + } + + if ( isServerObject() ) + { + // Return Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pPathObject->isActive() ? pPathObject->getSourceNode() : pPathObject->getDestinationNode() ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", !pPathObject->isActive() ); + + // Callback. + // VPath::onReachNode( %object, %node, %finished ); + Con::executef( this, "onReachNode", buffer[0], buffer[1], buffer[2] ); + } + } + + // Update Object Interp. + timeInterp = mClampF( timeInterp + timeInterpDelta, 0.f, 1.f ); + pathInterp = mClampF( pathInterp + pathInterpDelta, 0.f, 1.f ); + + // Apply Changes. + pPathObject->setTimeInterp( timeInterp ); + pPathObject->setPathInterp( pathInterp ); + pPathObject->setPosition( newPosition ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::printf( "Time / Distance: %f %f / %f %f", timeInterp, pathInterp, stepDistance, ( newPosition - oldPosition ).len() ); +#endif + + switch ( pPathObject->getOrientationMode().Type ) + { + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToObject : + case VPathObject::k_OrientationToPoint : + { + // Update Orientation. + updateOrientation( pPathObject ); + + } break; + + case VPathObject::k_OrientationToPath : + { + // Determine the path orientation. + VectorF pathOrientation = ( newPosition - oldPosition ); + pathOrientation.normalize(); + + // Update Orientation. + updateOrientation( pPathObject, pathOrientation ); + + } break; + } + + // Update Delta. + pPathObject->pushDelta( pPathObject->getPosition(), pPathObject->getOrientation() ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Update This Object. + pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); + } +} + +void VPath::updatePosition( VPathObject *pPathObject ) +{ + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Fetch Position. + F32 pathInterp = 0.f; + const Point3F newPosition = getPathPosition( srcNode, dstNode, pPathObject->getTimeInterp(), pPathObject->isForward(), pathInterp ); + + // Apply Position. + pPathObject->setPosition( newPosition ); + pPathObject->setPathInterp( pathInterp ); +} + +void VPath::updateOrientation( VPathObject *pPathObject ) +{ + // Update Orientation? + if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) + { + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Determine Path Orientation. + VectorF pathOrientation; + switch ( pPathObject->getOrientationMode().Type ) + { + case VPathObject::k_OrientationInterpolate : + { + // Interpolate Between Transforms. + QuatF rot; + rot.interpolate( srcNode->getWorldRotation(), dstNode->getWorldRotation(), pPathObject->getPathInterp() ); + + // Set Matrix. + MatrixF mat; + rot.setMatrix( &mat ); + + // Fetch Orientation. + pathOrientation = mat.getColumn3F( 1 ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Orientation. + pathOrientation = ( pPathObject->getOrientationMode().Object->getPosition() - pPathObject->getWorldPosition() ); + pathOrientation.normalizeSafe(); + + } break; + + case VPathObject::k_OrientationToPoint : + { + // Fetch Orientation. + pathOrientation = ( pPathObject->getOrientationMode().Point - pPathObject->getWorldPosition() ); + pathOrientation.normalizeSafe(); + + } break; + + case VPathObject::k_OrientationToPath : + { + // Fetch Orientation. + pathOrientation = getPathOrientation( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward() ); + + } break; + } + + // Update. + updateOrientation( pPathObject, pathOrientation ); +} + +void VPath::updateOrientation( VPathObject *pPathObject, const Point3F &pPathOrientation ) +{ + // Update Orientation? + if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) + { + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Determine Source Orientation. + VectorF srcOrientation; + switch ( srcNode->getOrientationMode().Type ) + { + case VPathNode::k_OrientationToPoint : + { + // Fetch Orientation. + srcOrientation = ( srcNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); + srcOrientation.normalize(); + + } break; + + default : + { + // Use Path Orientation. + srcOrientation = pPathOrientation; + + } break; + } + + // Determine Destination Orientation. + VectorF dstOrientation; + switch ( dstNode->getOrientationMode().Type ) + { + case VPathNode::k_OrientationToPoint : + { + // Fetch Orientation. + dstOrientation = ( dstNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); + dstOrientation.normalize(); + + } break; + + default : + { + // Use Path Orientation. + dstOrientation = pPathOrientation; + + } break; + } + + // Determine Actual Orientation. + VectorF orientation; + orientation.interpolate( srcOrientation, dstOrientation, pPathObject->getTimeInterp() ); + + // Apply. + pPathObject->setOrientation( orientation ); +} + +//----------------------------------------------------------------------------- +// +// Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculatePath( void ) +{ + if ( mNodeList.size() < 2 ) + { + // No Path. + return; + } + + switch ( mPathType ) + { + case k_PathLinear : + { + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + if ( itr == ( mNodeList.end() - 1 ) ) + { + // Head, Front. + calculateLinearPath( ( *itr ), ( *( mNodeList.begin() ) ) ); + } + else + { + // Head, Next. + calculateLinearPath( ( *itr ), ( *( itr + 1 ) ) ); + } + } + + } break; + + case k_PathBezier : + { + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + if ( itr == ( mNodeList.end() - 1 ) ) + { + // Head, Prev, Front. + calculateBezierPath( ( *itr ), ( *( mNodeList.begin() ) ) ); + } + else + { + // Head, Prev, Next. + calculateBezierPath( ( *itr ), ( *( itr + 1 ) ) ); + } + } + + } break; + } +} + +Point3F VPath::getAdvancedPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + switch( mPathType ) + { + case k_PathLinear : + { + return getAdvancedLinearPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); + + } break; + + case k_PathBezier : + { + return getAdvancedBezierPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); + + } break; + } + + // Sanity! + AssertFatal( false, "Invalid path type!" ); + return Point3F::Zero; +} + +ConsoleMethod( VPath, getPathTransform, const char *, 5, 5, "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the transform of the path at the interp point between two nodes.\n" + "@param pSrcNodeIndex The first node.\n" + "@param pDstNodeIndex The second node.\n" + "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" + "@return Returns the transform of the interp time between the two given nodes." ) +{ + // Fetch Nodes. + VPathNode *srcNode = object->getNode( dAtoi( argv[2] ) ); + VPathNode *dstNode = object->getNode( dAtoi( argv[3] ) ); + + // Interp Time. + const F32 &interp = dAtof( argv[4] ); + + // Fetch Position & Orientation. + const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); + const VectorF orientation = object->getPathOrientation( srcNode, dstNode, interp, true ); + + // Y-Axis. + VectorF yVec = orientation; + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF mat( true ); + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + + // AngAxis. + AngAxisF aa( mat ); + + // Return Buffer; + char *buffer = Con::getReturnBuffer( 256 ); + dSprintf( buffer, 256, "%g %g %g %g %g %g %g", position.x, position.y, position.z, + aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + // Return. + return buffer; +} + +ConsoleMethod( VPath, getPathPosition, const char *, 5, 5, "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the world position of the path at the interp point between two nodes.\n" + "@param pSrcNodeIndex The first node.\n" + "@param pDstNodeIndex The second node.\n" + "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" + "@return Returns the world position of the interp time between the two given nodes." ) +{ + // Fetch Nodes. + VPathNode *srcNode = object->getNode( dAtoi( argv[2] ) ); + VPathNode *dstNode = object->getNode( dAtoi( argv[3] ) ); + + // Interp Time. + const F32 &interp = dAtof( argv[4] ); + + // Find Position. + const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); + + // Return Buffer; + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%g %g %g", position.x, position.y, position.z ); + + // Return. + return buffer; +} + +Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + F32 pathInterp = 0.f; + return getPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pathInterp ); +} + +Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + switch( mPathType ) + { + case k_PathBezier : + { + return getBezierPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); + + } break; + + case k_PathLinear : + { + return getLinearPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); + + } break; + } + + // NULL. + return Point3F::Zero; +} + +VectorF VPath::getPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + switch( mPathType ) + { + case k_PathBezier : + { + return getBezierPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); + + } break; + + case k_PathLinear : + { + return getLinearPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); + + } break; + } + + // NULL. + return VectorF::Zero; +} + +//----------------------------------------------------------------------------- +// +// Linear Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculateLinearPath( VPathNode *pNode, VPathNode *pNextNode ) +{ + // Calculate Segment Length. + pNode->setLength( ( pNextNode->getWorldPosition() - pNode->getWorldPosition() ).len() ); +} + +Point3F VPath::getAdvancedLinearPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + + // Fetch the length of the segment. + const F32 length = ( pPathObject->isForward() ) ? srcNode->getLength() : dstNode->getLength(); + + // Set the interp delta. + pPathInterpDelta = ( pTargetDistance / length ); + + // Return the position. + F32 pathInterp = 0.f; + return getLinearPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward(), pathInterp ); +} + +Point3F VPath::getLinearPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + // Set path interp to the time interp. + pPathInterp = pTimeInterp; + + if ( pTimeInterp <= 0.f ) + { + // Source Node. + return pSourceNode->getWorldPosition(); + } + else if ( pTimeInterp >= 1.f ) + { + // Destination Node. + return pDestinationNode->getWorldPosition(); + } + + // Calculate Position. + Point3F position; + position.interpolate( pSourceNode->getWorldPosition(), pDestinationNode->getWorldPosition(), pTimeInterp ); + + // Return. + return position; +} + +VectorF VPath::getLinearPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + // Calculate Orientation. + VectorF newOrientation = ( pDestinationNode->getWorldPosition() - pSourceNode->getWorldPosition() ); + newOrientation.normalizeSafe(); + + // Return. + return newOrientation; +} + +//----------------------------------------------------------------------------- +// +// Bezier Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculateBezierPath( VPathNode *pNode, VPathNode *pNextNode ) +{ + // Reset Length. + F32 segmentLength = 0.f; + + // Positions. + const Point3F &pt0 = pNode->getWorldPosition(); + const Point3F &pt3 = pNextNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pNode->getWorldRotation().setMatrix( &mat0 ); + pNextNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pNode->getWeight() ); + Point3F pt2( -gBezierAxis * pNextNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Initial Position. + Point3F ptA = pt0; + const F32 i = gBezierInterpStep; + for ( F32 t = 0.f, it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F ptB = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + + // Add Segment. + segmentLength += ( ptB - ptA ).len(); + + // Store Position. + ptA = ptB; + } + + // Apply Update. + pNode->setLength( segmentLength ); +} + +Point3F VPath::getAdvancedBezierPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + + // Fetch the delta position. + return getBezierPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->getPosition(), pTargetDistance, pPathObject->isForward(), true, pPathInterpDelta ); +} + +Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + // Fetch the length of the segment. + const F32 length = ( pForward ) ? pSourceNode->getLength() : pDestinationNode->getLength(); + + // Determine the real interp time for the distance fraction. + return getBezierPathPosition( pSourceNode, pDestinationNode, 0.f, pSourceNode->getWorldPosition(), ( length * pTimeInterp ), pForward, false, pPathInterp ); +} + +Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const Point3F &pReferencePosition, const F32 &pTargetDistance, const bool &pForward, const bool &pRelativeToReference, F32 &pPathInterpDelta ) +{ + // Positions. + const Point3F &pt0 = pSourceNode->getWorldPosition(); + const Point3F &pt3 = pDestinationNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pSourceNode->getWorldRotation().setMatrix( &mat0 ); + pDestinationNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); + Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); + + if ( !pForward ) + { + pt1 *= -1.f; + pt2 *= -1.f; + } + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Move Position. + Point3F movePosition = pReferencePosition; + // Movement Distance. + F32 moveDistance = 0.f; + + // Determine the Real Delta. + const F32 i = gBezierInterpStep; + for ( F32 t = ( pTimeInterp + i ), it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) + { + // Calculate Step. + const Point3F stepPosition = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + // Step Length. + const F32 &stepDistance = ( stepPosition - movePosition ).len(); + + if ( pRelativeToReference ) + { + // Calculate Distance. + moveDistance = ( pReferencePosition - stepPosition ).len(); + + // Moved Target Distance? + if ( moveDistance >= pTargetDistance ) + { + // Interpolate Step. + const F32 stepInterp = ( moveDistance - pTargetDistance ) / moveDistance; + // Store Interp Delta. + pPathInterpDelta = ( t - pTimeInterp ) * ( 1.f - stepInterp ); + + // Interpolate the step. + Point3F outPosition; + outPosition.interpolate( pReferencePosition, stepPosition, ( 1.f - stepInterp ) ); + // Return the position. + return outPosition; + } + } + else + { + // Calculate Distance. + moveDistance += stepDistance; + + // Moved Target Distance? + if ( moveDistance >= pTargetDistance ) + { + // Interpolate Step. + const F32 stepInterp = ( moveDistance - pTargetDistance ) / stepDistance; + // Store Interp Delta. + pPathInterpDelta = ( t - pTimeInterp ) - ( stepInterp * i ); + + // Interpolate the step. + Point3F outPosition; + outPosition.interpolate( movePosition, stepPosition, ( 1.f - stepInterp ) ); + // Return the position. + return outPosition; + } + } + + // Apply New Position. + movePosition = stepPosition; + } + + // Update. + pPathInterpDelta = ( 1.f - pTimeInterp ); + // At the destination node? + return pt3; +} + +VectorF VPath::getBezierPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + // Positions. + const Point3F &pt0 = pSourceNode->getWorldPosition(); + const Point3F &pt3 = pDestinationNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pSourceNode->getWorldRotation().setMatrix( &mat0 ); + pDestinationNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); + Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); + + if ( !pForward ) + { + pt1 *= -1.f; + pt2 *= -1.f; + } + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + const F32 halfStep = ( gBezierInterpStep / 2.f ); + if ( ( pTimeInterp - halfStep ) <= 0.f ) + { + // Orientation From Node Tangent. + pt1.normalize(); + + // Return. + return pt1; + } + else if ( ( pTimeInterp + halfStep ) >= 1.f ) + { + // Orientation From Node Tangent. + pt2.normalize(); + + // Return. + return -pt2; + } + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Interp Times. + const F32 t0 = ( pTimeInterp - halfStep ); + const F32 it0 = ( 1.f - t0 ); + + const F32 t1 = ( pTimeInterp + halfStep ); + const F32 it1 = ( 1.f - t1 ); + + // Calculate Position. + Point3F d0 = ( pt0 * it0 * it0 * it0 ) + ( 3 * pt1 * it0 * it0 * t0 ) + ( 3 * pt2 * it0 * t0 * t0 ) + ( pt3 * t0 * t0 * t0 ); + Point3F d1 = ( pt0 * it1 * it1 * it1 ) + ( 3 * pt1 * it1 * it1 * t1 ) + ( 3 * pt2 * it1 * t1 * t1 ) + ( pt3 * t1 * t1 * t1 ); + + // Set Orientation. + Point3F orientation = ( d1 - d0 ); + orientation.normalizeSafe(); + + // Return. + return orientation; +} + +//----------------------------------------------------------------------------- +// +// Path Node Property Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VPath, getNodeCount, S32, 2, 2, "() - Get the number of nodes in this path.\n" + "@return Returns the number of nodes." ) +{ + // Return Count. + return object->getNodeCount(); +} + +S32 VPath::getNodeCount( void ) +{ + // Return the Size of the Node List. + return mNodeList.size(); +} + +ConsoleMethod( VPath, getNodeLocalTransform, const char *, 3, 3, "( int pNodeIndex ) - Get the local transform (local position and rotation) of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the transform of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeLocalPosition( dAtoi( argv[2] ) ); + + // Fetch Rotation. + const QuatF &rotation = object->getNodeLocalRotation( dAtoi( argv[2] ) ); + + // Angle & Axis. + AngAxisF aa( rotation ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 256 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g %.3g %.3g %.3g", position.x, position.y, position.z, aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + return buffer; +} + +ConsoleMethod( VPath, getNodeLocalPosition, const char *, 3, 3, "( int pNodeIndex ) - Get the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + " @return Returns the Local Position of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeLocalPosition( dAtoi( argv[2] ) ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g", position.x, position.y, position.z ); + + return buffer; +} + +Point3F VPath::getNodeLocalPosition( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLocalPosition() - Invalid Index Specified (%d).", pNodeIndex ); + return Point3F::Zero; + } + + return mNodeList[pNodeIndex]->getLocalPosition(); +} + +ConsoleMethod( VPath, getNodeLocalRotation, const char *, 3, 3, "( int pNodeIndex ) - Get the Local Rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the Local Rotation of the given node." ) +{ + // Fetch Rotation. + const QuatF &rotation = object->getNodeLocalRotation( dAtoi( argv[2] ) ); + + // Angle & Axis. + AngAxisF aa( rotation ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g", aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + return buffer; +} + +QuatF VPath::getNodeLocalRotation( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLocalRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return QuatF( Point3F::Zero, 0.f ); + } + + return mNodeList[pNodeIndex]->getLocalRotation(); +} + +ConsoleMethod( VPath, getNodeWorldTransform, const char *, 3, 3, "( int pNodeIndex ) - Get the World Transform (position and rotation) of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the transform of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeWorldPosition( dAtoi( argv[2] ) ); + + // Fetch Rotation. + const QuatF &rotation = object->getNodeWorldRotation( dAtoi( argv[2] ) ); + + // Angle & Axis. + AngAxisF aa( rotation ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 256 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g %.3g %.3g %.3g", position.x, position.y, position.z, aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + return buffer; +} + +ConsoleMethod( VPath, getNodeWorldPosition, const char *, 3, 3, "( int pNodeIndex ) - Get the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the World Position of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeWorldPosition( dAtoi( argv[2] ) ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g", position.x, position.y, position.z ); + + return buffer; +} + +Point3F VPath::getNodeWorldPosition( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWorldPosition() - Invalid Index Specified (%d).", pNodeIndex ); + return Point3F::Zero; + } + + return mNodeList[pNodeIndex]->getWorldPosition(); +} + +ConsoleMethod( VPath, getNodeWorldRotation, const char *, 3, 3, "( int pNodeIndex ) - Get the World Rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the World Rotation of the given node." ) +{ + // Fetch Rotation. + const QuatF &rotation = object->getNodeWorldRotation( dAtoi( argv[2] ) ); + + // Angle & Axis. + AngAxisF aa( rotation ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g", aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + return buffer; +} + +QuatF VPath::getNodeWorldRotation( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWorldRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return QuatF( Point3F::Zero, 0.f ); + } + + return mNodeList[pNodeIndex]->getWorldRotation(); +} + +ConsoleMethod( VPath, getNodeWeight, F32, 3, 3, "( int pNodeIndex ) - Get the weight of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the weight of the given node." ) +{ + // Fetch Weight. + return object->getNodeWeight( dAtoi( argv[2] ) ); +} + +F32 VPath::getNodeWeight( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); + return 0.f; + } + + return mNodeList[pNodeIndex]->getWeight(); +} + +ConsoleMethod( VPath, getNodeLength, F32, 3, 3, "( int pNodeIndex ) - Get the length of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the length of the given node." ) +{ + // Fetch Length. + return object->getNodeLength( dAtoi( argv[2] ) ); +} + +F32 VPath::getNodeLength( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLength() - Invalid Index Specified (%d).", pNodeIndex ); + return 0.f; + } + + return mNodeList[pNodeIndex]->getLength(); +} + +ConsoleMethod( VPath, setNodeTransform, void, 4, 4, "( int pNodeIndex, matrix pTransform ) - Set the transform of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pTransform The new transform to be applied to the node.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Fetch Position & Rotation. + Point3F position; + AngAxisF aa; + QuatF rotation; + dSscanf( argv[3], "%g %g %g %g %g %g %g", &position.x, &position.y, &position.z, + &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle ); + + // Set Rotation. + rotation.set( aa ); + + // Apply Update. + object->setNodePosition( nodeIndex, position ); + object->setNodeRotation( nodeIndex, rotation ); +} + +ConsoleMethod( VPath, setNodePosition, void, 4, 4, "( int pNodeIndex, vector pPosition ) - Set the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pPosition The new position to be applied to the node.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Fetch Position. + Point3F position; + dSscanf( argv[3], "%g %g %g", &position.x, &position.y, &position.z ); + + // Apply Update. + object->setNodePosition( nodeIndex, position ); +} + +void VPath::setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodePosition() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setLocalPosition( pPosition ); + + // Update Size. + updateContainer(); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +ConsoleMethod( VPath, setNodeRotation, void, 4, 4, "( int pNodeIndex, angAxis pRotation ) - Set the rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pRotation The new rotation to be applied to the node.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Fetch Rotation. + AngAxisF aa; + QuatF rotation; + dSscanf( argv[3], "%g %g %g %g", &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle ); + + // Set Rotation. + rotation.set( aa ); + + // Apply Update. + object->setNodeRotation( nodeIndex, rotation ); +} + +void VPath::setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setLocalRotation( pRotation ); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +ConsoleMethod( VPath, setNodeWeight, void, 4, 4, "( int pNodeIndex, float pWeight ) - Set the weight of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pWeight The new weight to be applied to the node.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Fetch Weight. + const F32 nodeWeight = dAtof( argv[3] ); + + // Apply Update. + object->setNodeWeight( nodeIndex, nodeWeight ); +} + +void VPath::setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setWeight( pWeight ); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +ConsoleMethod( VPath, getNodeOrientationMode, const char *, 3, 3, "( int pNodeIndex ) - Gets the current orientation mode of the node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns a string indicating the orientation mode and its properties." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + if ( nodeIndex < 0 || nodeIndex >= object->getNodeCount() ) + { + // Woops! + Con::warnf( "VPath::getNodeOrientationMode() - Invalid Index Specified (%d).", nodeIndex ); + return ""; + } + + // Fetch Object + VPathNode *node = object->getNode( nodeIndex ); + + // Fetch Orientation Mode. + const VPathNode::sOrientation &orientation = node->getOrientationMode(); + + // Determine the Type. + StringTableEntry type = VPathNode::getOrientationTypeLabel( orientation.Type ); + + // Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + + switch( orientation.Type ) + { + case VPathNode::k_OrientationFree : + { + // Buffer String. + dSprintf( buffer, 128, "%s", type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = orientation.Point; + // Buffer String. + dSprintf( buffer, 128, "%s\t%.2f %.2f %.2f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return Buffer. + return buffer; +} + +ConsoleMethod( VPath, setNodeOrientationMode, void, 4, 5, "( int pNodeIndex, string pOrientationType, [vector pPoint] ) - Set the orientation mode of the node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pOrientationType The new orientation type of the object.\n" + "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Orient? + const VPathNode::eOrientationType type = VPathNode::getOrientationTypeEnum( argv[3] ); + + switch ( type ) + { + case VPathNode::k_OrientationFree : + { + // Apply Mode. + object->setNodeOrientationMode( nodeIndex, type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + object->setNodeOrientationMode( nodeIndex, type, lookAtPoint ); + + } break; + + default : + { + AssertFatal( false, "VPath::setNodeOrientationMode() - Invalid Orientation Mode Specified." ); + + } break; + } +} + +void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply. + node->setOrientationMode( pType ); + + // Network Flags. + setMaskBits( NodeUpdateMask ); +} + +void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F pPoint ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply. + node->setOrientationMode( pType, pPoint ); + + // Network Flags. + setMaskBits( NodeUpdateMask ); +} + +//----------------------------------------------------------------------------- +// +// Path Object Property Methods. +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VPath, isPathObjectActive, bool, 3, 3, "( SimObject pObject ) - Is the object actively traveling around this path?\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns true of the object is active." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::isPathObjectActive() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->isActive(); +} + +ConsoleMethod( VPath, setPathObjectActive, void, 4, 4, "( SimObject pObject, bool pActive ) - Enable or disable the object from traveling around this path. Inactive objects are still attached to the path, but are not updated.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pActive The new status of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectActive() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectActive( sceneObject, dAtob( argv[3] ) ); +} + +void VPath::setPathObjectActive( SceneObject *pObject, const bool &pActive ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectActive() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setActive( pActive ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, getPathObjectInterp, F32, 3, 3, "( SimObject pObject ) - Get the current interp position of the path object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the current interp position." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectInterp() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getTimeInterp(); +} + +ConsoleMethod( VPath, setPathObjectInterp, void, 4, 4, "( SimObject pObject, float pTimeInterp ) - Set the interp position of the object between its current nodes.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pTimeInterp The new interp position of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectInterp() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectInterp( sceneObject, dAtof( argv[3] ) ); +} + +void VPath::setPathObjectInterp( SceneObject *pObject, const F32 &pTimeInterp ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectInterp() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Update. + setPathObjectInterp( pathObject, pTimeInterp ); +} + +void VPath::setPathObjectInterp( VPathObject *pPathObject, const F32 &pTimeInterp ) +{ + // Set Interp Time. + pPathObject->setTimeInterp( pTimeInterp ); + + // Update Position. + updatePosition( pPathObject ); + // Update Orientation. + updateOrientation( pPathObject ); + // Reset the delta. + pPathObject->resetDelta(); + + // Set the object transform. + pPathObject->getObject()->setTransform( pPathObject->getTransform() ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Update This Object. + pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); + } +} + +ConsoleMethod( VPath, getPathObjectOffset, const char *, 3, 3, "( SimObject pObject ) - Get the position offset assigned to this object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the position offset." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectOffset() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Fetch Offset. + const Point3F &offset = pathObject->getOffset(); + + // Buffer. + char *buffer = Con::getReturnBuffer( 64 ); + dSprintf( buffer, 64, "%f %f %f", offset.x, offset.y, offset.z ); + return buffer; +} + +ConsoleMethod( VPath, setPathObjectOffset, void, 4, 4, "( SimObject pObject, vector pOffset ) - Set the position offset of the object. As the object is moving along the path, its position is offset by this value. Setting the \"Relative\" parameter while attaching an object will automatically apply an offset value.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pOffset The new position offset of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectOffset() - Invalid Target Object." ); + return; + } + + // Relative Offset. + Point3F offset( 0.f, 0.f, 0.f ); + // Scan. + dSscanf( argv[3], "%g %g %g", &offset.x, &offset.y, &offset.z ); + + // Apply. + object->setPathObjectOffset( sceneObject, offset ); +} + +void VPath::setPathObjectOffset( SceneObject *pObject, const Point3F &pOffset ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOffset() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOffset( pOffset ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, getPathObjectSpeed, F32, 3, 3, "( SimObject pObject ) - Get the speed this object is traveling along the path at.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the speed of the object." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectSpeed() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getSpeed(); +} + +ConsoleMethod( VPath, setPathObjectSpeed, void, 4, 4, "( SimObject pObject, float pSpeed ) - Set the speed of the object.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pSpeed The new speed of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectSpeed() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectSpeed( sceneObject, dAtof( argv[3] ) ); +} + +void VPath::setPathObjectSpeed( SceneObject *pObject, const F32 &pSpeed ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectSpeed() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setSpeed( mFabs( pSpeed ) ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, getPathObjectOrientationMode, const char *, 3, 3, "( SimObject pObject ) - Gets the current orientation mode of the object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns a string indicating the orientation mode and its properties." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectOrientationMode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Fetch Orientation Mode. + const VPathObject::sOrientation &orientation = pathObject->getOrientationMode(); + + // Determine the Type. + StringTableEntry type = VPathObject::getOrientationTypeLabel( orientation.Type ); + + // Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + + switch( orientation.Type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Buffer String. + dSprintf( buffer, 128, "%s", type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch the Object ID. + const S32 objId = ( ( orientation.Object ) ? orientation.Object->getId() : 0 ); + // Buffer String. + dSprintf( buffer, 128, "%s %d", type, objId ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = orientation.Point; + // Buffer String. + dSprintf( buffer, 128, "%s %f %f %f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return Buffer. + return buffer; +} + +ConsoleMethod( VPath, setPathObjectOrientationMode, void, 4, 5, "( SimObject pObject, string pOrientationType, [SimObject pObject / vector pPoint] ) - Set the orientation mode of the object. This property affects the rotation of the object. If you wish to ignore the object's rotation altogether, set the mode to \"FREE\".\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pOrientationType The new orientation type of the object.\n" + "@param pObject If the orientation type is set to OBJECT, this parameter must be the SimObjectID of a scene object.\n" + "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid Target Object." ); + return; + } + + // Orient? + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( argv[3] ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Object. + SceneObject *lookAtObject = dynamic_cast( Sim::findObject( argv[4] ) ); + if ( !lookAtObject ) + { + Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid LookAt Object." ); + return; + } + + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type, lookAtObject ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type, lookAtPoint ); + + } break; + + default : + { + AssertFatal( false, "VPath::setPathObjectOrientationMode() - Invalid Orientation Mode Specified." ); + + } break; + } +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, SceneObject *pLookAtObject ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType, pLookAtObject ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, const Point3F pPoint ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType, pPoint ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, isPathObjectForward, bool, 3, 3, "( SimObject pObject ) - Get if this object is traveling forwards along the path.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns true if the object is traveling forwards." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::isPathObjectForward() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->isForward(); +} + +ConsoleMethod( VPath, setPathObjectForward, void, 4, 4, "( SimObject pObject, bool pForward ) - Set the travel direction of the object.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pForward The direction of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectForward() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectForward( sceneObject, dAtob( argv[3] ) ); +} + +void VPath::setPathObjectForward( SceneObject *pObject, const bool &pForward ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectForward() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setForward( pForward ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, getPathObjectNode, S32, 3, 3, "( SimObject pObject ) - Gets the last node of the object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the node index." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectNode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getSourceNode(); +} + +ConsoleMethod( VPath, setPathObjectNode, void, 4, 4, "( SimObject pObject, bool pNodeIndex ) - Move the object to the node's position. You may also want to observe the \"setPathObjectInterp\" method.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pNodeIndex The index of the node that the object will reposition to.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectNode() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectNode( sceneObject, dAtoi( argv[3] ) ); +} + +void VPath::setPathObjectNode( SceneObject *pObject, const S32 &pNodeIndex ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectNode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Source & Destination Nodes. + const S32 srcNode = pNodeIndex; + const S32 dstNode = ( pathObject->isForward() ) ? ( pNodeIndex + 1 ) : ( pNodeIndex - 1 ); + + // Set Current Node. + pathObject->setNode( normalizeNodeIndex( srcNode ), normalizeNodeIndex( dstNode ) ); + + // Reset Interp. + pathObject->setTimeInterp( 0.f ); + pathObject->setPathInterp( 0.f ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +ConsoleMethod( VPath, getPathObjectEndNode, S32, 3, 3, "( SimObject pObject ) - Get the index of the node this object is meant to stop upon reaching.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the node index." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::getPathObjectEndNode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getEndNode(); +} + +ConsoleMethod( VPath, setPathObjectEndNode, void, 4, 4, "( SimObject pObject, bool pNodeIndex ) - Set end node of the path object. If a value of \"-1\" is applied, the object will path indefinitely.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pNodeIndex The index of the node that the object will cease pathing upon reaching.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectEndNode() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectEndNode( sceneObject, dAtoi( argv[3] ) ); +} + +void VPath::setPathObjectEndNode( SceneObject *pObject, const S32 &pNodeIndex ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectEndNode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Set index. + S32 index = pNodeIndex; + + if ( index != -1 ) + { + // Normalize index. + normalizeNodeIndex( index ); + } + + // Apply. + pathObject->setEndNode( index ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPath.h b/Engine/modules/Verve/VPath/VPath.h new file mode 100644 index 000000000..925d88d78 --- /dev/null +++ b/Engine/modules/Verve/VPath/VPath.h @@ -0,0 +1,271 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATH_H_ +#define _VT_VPATH_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif + +#ifndef _VT_PATHNODE_H_ +#include "VPathNode.h" +#endif + +#ifndef _VT_PATHOBJECT_H_ +#include "VPathObject.h" +#endif + +//----------------------------------------------------------------------------- + +typedef Vector VPathNodeVector; +typedef VPathNodeVector::iterator VPathNodeIterator; + +typedef Vector VPathObjectVector; +typedef VPathObjectVector::iterator VPathObjectIterator; + +//----------------------------------------------------------------------------- + +class VPath : public SceneObject +{ + typedef SceneObject Parent; + + friend class VPathEditor; + +public: + + // Static Members. + + static SimObjectPtr gServerSet; + + static U32 gMaxNodeTransmit; + static U32 gMaxNodeBits; + static U32 gMaxNodeCount; + + static U32 gMaxObjectTransmit; + static U32 gMaxObjectBits; + static U32 gMaxObjectCount; + + static Point3F gBezierAxis; + static Point3F gBezierUp; + + enum eMaskBits + { + InitialUpdateMask = Parent::NextFreeMask << 0, + PathUpdateMask = Parent::NextFreeMask << 1, + NodeUpdateMask = Parent::NextFreeMask << 2, + ObjectUpdateMask = Parent::NextFreeMask << 3, + NextFreeMask = Parent::NextFreeMask << 4, + }; + + enum ePathType + { + k_PathLinear, + k_PathBezier, + + k_PathInvalid, + + k_PathTypeSize, + }; + +private: + + U32 mPathType; + + VPathNodeVector mNodeList; + + VPathObjectVector mObjectList; + +public: + + VPath( void ); + ~VPath( void ); + + bool onAdd( void ); + void onDeleteNotify( SimObject *pObject ); + void onRemove( void ); + + static void initPersistFields( void ); + + static SimSet *getServerSet( void ); + + // Editor Methods. + + bool collideBox( const Point3F &pStart, const Point3F &pEnd, RayInfo* pInfo ); + + // Update Methods. + + F32 getUpdatePriority( CameraScopeQuery *pFocusObject, U32 pUpdateMask, S32 pUpdateSkips ); + + void updateContainer( void ); + void updateNodeTransforms( void ); + + void setTransform( const MatrixF &pMatrix ); + void setScale( const VectorF &pScale ); + + void setPathType( const ePathType &pType ); + static bool setPathType( void *pObject, const char *pArray, const char *pData ); + + // Mounting Methods. + + U32 getAvailableMountIndex( void ); + bool isMountIndex( const U32 &pIndex ); + + void mountObject( SceneObject *pObject, S32 pIndex, const MatrixF &pTransform = MatrixF::Identity ); + void unmountObject( SceneObject *pObject ); + + void getMountTransform( S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ); + void getRenderMountTransform( F32 pDelta, S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ); + + VectorF getMountVelocity( const U32 &pIndex ); + + // Persistence Methods. + + void readFields( void ); + void writeFields( Stream &pStream, U32 pTabStop ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + DECLARE_CONOBJECT( VPath ); + +public: + + // Node Methods. + + static VPathNode *createNode( void ); + static void deleteNode( VPathNode *pNode ); + + void clear( void ); + + VPathNode *getNode( const S32 &pNodeIndex ); + + VPathNode *addNode( const Point3F &pPosition, const QuatF &pRotation, const F32 &pWeight, const S32 &pLocation = -1 ); + VPathNode *addNode( VPathNode *pNode, const S32 &pLocation = -1 ); + + void deleteNode( const S32 &pNodeIndex ); + void removeNode( const S32 &pNodeIndex ); + + S32 normalizeNodeIndex( S32 &pNodeIndex ); + S32 normalizeNodeIndex( const S32 &pNodeIndex ); + S32 normalizeNodeIndex( S32 &pNodeIndex, const S32 &pNodeCount ); + + // Object Methods. + + bool isObjectAttached( SceneObject *pObject ); + VPathObject *getPathObject( SceneObject *pObject ); + + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode ); + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode ); + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode, void *pOrientationData ); + void attachObject( VPathObject *pPathObject ); + void onAttachObject( VPathObject *pPathObject ); + + void detachObject( SceneObject *pObject ); + void detachObject( VPathObject *pPathObject ); + void onDetachObject( VPathObject *pPathObject ); + + void processTick( const Move *pMove ); + void advanceObject( VPathObject *pPathObject, const F32 &pDelta ); + + void updatePosition( VPathObject *pPathObject ); + void updateOrientation( VPathObject *pPathObject ); + void updateOrientation( VPathObject *pPathObject, const Point3F &pPathOrientation ); + + // Path Methods. + + void calculatePath( void ); + + Point3F getAdvancedPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ); + Point3F getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ); + VectorF getPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ); + + // + // Linear Path Methods. + + void calculateLinearPath( VPathNode *pNode, VPathNode *pNextNode ); + + Point3F getAdvancedLinearPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getLinearPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward, F32 &pPathInterp ); + VectorF getLinearPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward ); + + // + // Bezier Path Methods. + + void calculateBezierPath( VPathNode *pNode, VPathNode *pNextNode ); + + Point3F getAdvancedBezierPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward, F32 &pPathInterp ); + Point3F getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const Point3F &pReferencePosition, const F32 &pTargetDistance, const bool &pForward, const bool &pRelativeToReference, F32 &pPathInterpDelta ); + VectorF getBezierPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward ); + +public: + + // Node Property Methods. + + S32 getNodeCount( void ); + + Point3F getNodeLocalPosition( const S32 &pNodeIndex ); + Point3F getNodeWorldPosition( const S32 &pNodeIndex ); + QuatF getNodeLocalRotation( const S32 &pNodeIndex ); + QuatF getNodeWorldRotation( const S32 &pNodeIndex ); + F32 getNodeWeight( const S32 &pNodeIndex ); + F32 getNodeLength( const S32 &pNodeIndex ); + + void setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ); + void setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ); + void setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ); + + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F pPoint ); + + // Path Object Property Methods. + + void setPathObjectActive( SceneObject *pObject, const bool &pActive ); + void setPathObjectInterp( SceneObject *pObject, const F32 &pTimeInterp ); + void setPathObjectOffset( SceneObject *pObject, const Point3F &pOffset ); + void setPathObjectSpeed( SceneObject *pObject, const F32 &pSpeed ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, SceneObject *pLookAtObject ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, const Point3F pPoint ); + void setPathObjectForward( SceneObject *pObject, const bool &pForward ); + void setPathObjectNode( SceneObject *pObject, const S32 &pNodeIndex ); + void setPathObjectEndNode( SceneObject *pObject, const S32 &pNodeIndex ); + + void setPathObjectInterp( VPathObject *pPathObject, const F32 &pTimeInterp ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPath::ePathType VPathType; + +// Declare Enum Types. +DefineEnumType( VPathType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATH_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathEditor.cpp b/Engine/modules/Verve/VPath/VPathEditor.cpp new file mode 100644 index 000000000..3ab2f8282 --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathEditor.cpp @@ -0,0 +1,2205 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathEditor.h" + +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gfx/primBuilder.h" +#include "gui/worldEditor/worldEditor.h" +#include "math/mathUtils.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static F32 gProjectDistance = 2000.f; +static F32 gSelectionDistance = 2.f; + +static ColorI gPathColor( 255, 255, 255 ); +static ColorI gPathColorSel( 0, 255, 255 ); +static ColorI gNodeLookAtPointColor( 255, 127, 39 ); + +//----------------------------------------------------------------------------- + +// Implement the Edit Mode enum list. +ImplementEnumType( VPathEditorMode, "" ) + { VPathEditor::k_Gizmo, "GIZMO" }, + { VPathEditor::k_AddNode, "ADDNODE" }, + { VPathEditor::k_DeleteNode, "DELETENODE" }, +EndImplementEnumType; + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPathEditor ); +//----------------------------------------------------------------------------- + +VPathEditor::VPathEditor( void ) : + mIsDirty( false ), + mEditMode( k_Gizmo ), + mEditWeight( false ), + mEditWeightHandle( -1 ) +{ + // Void. +} + +bool VPathEditor::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + // Assign Gizmo Name. + mGizmo->assignName( "VPathEditorGizmo" ); + + return true; +} + +bool VPathEditor::onWake( void ) +{ + // Clear Selection. + updateSelection( NULL, -1 ); + + // Return Parent Value. + return Parent::onWake(); +} + +void VPathEditor::initPersistFields( void ) +{ + addField( "IsDirty", TypeBool, Offset( mIsDirty, VPathEditor ) ); + addField( "EditMode", TYPEID(), Offset( mEditMode, VPathEditor ) ); + + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// Gui Events +// +//----------------------------------------------------------------------------- + +void VPathEditor::on3DMouseDown( const Gui3DMouseEvent &pEvent ) +{ + // Using the Gizmo? + if ( mEditMode != k_Gizmo ) + { + // No, Quit Now. + return; + } + + // Gizmo Event. + mGizmo->on3DMouseDown( pEvent ); + + if ( isValidSelection() ) + { + // Store Node Information. + pushNodeEdit(); + + switch( mGizmoProfile->mode ) + { + case MoveMode: + case RotateMode: + { + if ( mGizmo->getSelection() != Gizmo::None ) + { + // Using Gizmo. + return; + } + + } break; + + case ScaleMode: + { + if ( isEditingWeight( pEvent ) ) + { + // Editing Weights. + return; + } + + } break; + } + } + else if ( mSelection.Path ) + { + // Store Path Information. + pushPathEdit(); + + if ( mGizmo->getSelection() != Gizmo::None ) + { + // Using Gizmo. + return; + } + } + + // Update Selection. + if ( !updateSelection( pEvent ) ) + { + // Clear Selection. + updateSelection( NULL, -1 ); + } +} + +void VPathEditor::on3DMouseUp( const Gui3DMouseEvent &pEvent ) +{ + switch ( mEditMode ) + { + case k_Gizmo : + { + // Gizmo Event. + mGizmo->on3DMouseUp( pEvent ); + + // Handle History Actions. + popPathEdit(); + popNodeEdit(); + + // Clear Editing. + mEditWeight = false; + + } break; + + case k_AddNode : + { + if ( mSelection.Path != NULL ) + { + // Add New! + addNode( pEvent ); + + // Dirty. + mIsDirty = true; + } + + } break; + + case k_DeleteNode : + { + // Update Selection. + if ( updateSelection( pEvent ) ) + { + if ( isValidSelection() ) + { + // Delete Node. + deleteNode( mSelection.Node ); + + // Dirty. + mIsDirty = true; + } + + // Clear Node Selection. + updateSelection( mSelection.Path, -1 ); + } + + } break; + } +} + +void VPathEditor::on3DMouseMove( const Gui3DMouseEvent &pEvent ) +{ + // Update? + if ( mEditMode != k_Gizmo || !mSelection.Path ) + { + return; + } + + // Update Gizmo? + if ( mSelection.Node == -1 || mGizmoProfile->mode != ScaleMode ) + { + // Gizmo Event. + mGizmo->on3DMouseMove( pEvent ); + } +} + +void VPathEditor::on3DMouseDragged( const Gui3DMouseEvent &pEvent ) +{ + // Update? + if ( mEditMode != k_Gizmo || !mSelection.Path ) + { + return; + } + + // Update Gizmo? + if ( mSelection.Node == -1 || mGizmoProfile->mode != ScaleMode ) + { + // Gizmo Event. + mGizmo->on3DMouseDragged( pEvent ); + + // Handle Gizmo? + if ( mGizmo->getSelection() == Gizmo::None ) + { + // Return. + return; + } + } + + // Editing the Path? + if ( mSelection.Node == -1 ) + { + switch ( mGizmoProfile->mode ) + { + case MoveMode : + { + // Fetch Node Position. + const Point3F oldPosition = mSelection.Path->getPosition(); + // Determine New Position. + const Point3F newPosition = ( oldPosition + mGizmo->getOffset() ); + + // Apply New Position. + setPathPosition( newPosition ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + /* + case RotateMode : + { + + // Rotation Delta. + MatrixF deltaRotation( EulerF( mGizmo->getDeltaRot() ) ); + + // Fetch Current Transform. + MatrixF mat = mSelection.Path->getTransform(); + mat.mul( deltaRotation ); + + // Apply New Transform. + setPathTransform( mat ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + + case ScaleMode : + { + + // Apply New Scale. + setPathScale( mGizmo->getScale() ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + */ + } + } + + // No, Editing a Node + else + { + switch ( mGizmoProfile->mode ) + { + case MoveMode : + { + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Fetch Node Position. + const Point3F oldPosition = node->getLocalPosition(); + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + Point3F deltaPosition = mGizmo->getOffset(); + pathTransform.mulP( deltaPosition ); + + // Apply New Position. + setNodePosition( mSelection.Node, ( oldPosition + deltaPosition ) ); + + } break; + + case RotateMode : + { + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + // Rotation Delta. + MatrixF deltaRotation( EulerF( mGizmo->getDeltaRot() ) ); + pathTransform.mul( deltaRotation ); + + // Fetch Current Transform. + MatrixF mat = node->getWorldTransform(); + mat.mul( deltaRotation ); + + // Construct Quat. + QuatF newRotation; + newRotation.set( mat ); + + // Apply New Rotation. + setNodeRotation( mSelection.Node, newRotation ); + + } break; + + case ScaleMode : + { + + if ( isEditingWeight() ) + { + // Edit Weight. + updateWeight( pEvent ); + } + + } break; + } + } +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +VPath *VPathEditor::getClientPath( VPath *pPath ) +{ + if ( !pPath ) + { + return NULL; + } + + NetConnection *toServer = NetConnection::getConnectionToServer(); + NetConnection *toClient = NetConnection::getLocalClientConnection(); + if ( !toServer || !toClient ) + { + return NULL; + } + + const S32 ghostIndex = toClient->getGhostIndex( pPath ); + if ( ghostIndex == -1 ) + { + return NULL; + } + + return dynamic_cast( toServer->resolveGhost( ghostIndex ) ); +} + +//----------------------------------------------------------------------------- +// +// Selection Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::updateSelection( const Gui3DMouseEvent &pEvent ) +{ + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + RayInfo ri; + if ( !gServerContainer.collideBox( pt0, pt1, MarkerObjectType, &ri ) ) + { + // No Object. + return false; + } + + VPath *path = dynamic_cast( ri.object ); + if ( !path ) + { + // No Path Object. + return false; + } + + // No Node. + S32 nodeIndex = -1; + + for ( VPathNodeIterator itr = path->mNodeList.begin(); itr != path->mNodeList.end(); itr++ ) + { + VPathNode *node = ( *itr ); + + Point3F projPosition; + project( node->getWorldPosition(), &projPosition ); + + if ( projPosition.z <= 0.0f ) + { + continue; + } + + const Point2I rectHalfSize( 8, 8 ); + const Point2I screenPosition( ( S32 )projPosition.x, ( S32 )projPosition.y ); + const RectI screenRect( screenPosition - rectHalfSize, 2 * rectHalfSize ); + + // Mouse Close Enough? + if ( screenRect.pointInRect( pEvent.mousePoint ) ) + { + // Select Node. + nodeIndex = ( itr - path->mNodeList.begin() ); + } + } + + // Set Selection. + updateSelection( path, nodeIndex ); + + // Valid Selection. + return true; +} + +void VPathEditor::updateSelection( VPath *pPathObject, const S32 &pNodeIndex ) +{ + // Store Selection. + mSelection.Path = pPathObject; + mSelection.Node = pNodeIndex; + + // Quick Update. + updateSelection(); + + // Return Buffer. + char buffer[2][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", ( pPathObject ) ? pPathObject->getId() : 0 ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + + // Callback. + Con::executef( this, "onUpdateSelection", buffer[0], buffer[1] ); +} + +void VPathEditor::updateSelection( void ) +{ + if ( !isValidSelection() ) + { + // No Further Updates. + return; + } + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Fetch Node Rotation Matrix. + MatrixF mat; + node->getWorldRotation().setMatrix( &mat ); + + // Determine Tangent Axis. + Point3F pt0( VPath::gBezierAxis * node->getWeight() ); + Point3F pt1( -VPath::gBezierAxis * node->getWeight() ); + + // Rotate Axis. + mat.mulP( pt0 ); + mat.mulP( pt1 ); + + // Offset Points. + pt0 += node->getWorldPosition(); + pt1 += node->getWorldPosition(); + + // Store Points. + mSelection.TangentHandle[0] = pt0; + mSelection.TangentHandle[1] = pt1; +} + +ConsoleMethod( VPathEditor, clearSelection, void, 2, 2, "( void )" ) +{ + // Clear Selection. + object->updateSelection( NULL, -1 ); +} + +ConsoleMethod( VPathEditor, setSelection, void, 3, 4, "( pObject, [pNodeIndex] )" ) +{ + // Fetch Path. + VPath *path = dynamic_cast( Sim::findObject( argv[2] ) ); + if ( !path ) + { + Con::errorf( "VPathEditor::setSelection() - Unable to select target Object." ); + return; + } + + if ( argc == 3 ) + { + // Select Path. + object->updateSelection( path, -1 ); + return; + } + + // Select Path & Node. + object->updateSelection( path, dAtoi( argv[3] ) ); +} + +ConsoleMethod( VPathEditor, isValidSelection, bool, 2, 2, "( void )" ) +{ + return object->isValidSelection(); +} + +ConsoleMethod( VPathEditor, getSelectedPath, S32, 2, 2, "( void )" ) +{ + // Fetch Path. + VPath *path = object->mSelection.Path; + + // Return ID. + return ( path ) ? path->getId() : 0; +} + +ConsoleMethod( VPathEditor, getSelectedNode, S32, 2, 2, "( void )" ) +{ + // Return Node Index. + return ( object->mSelection.Path ) ? object->mSelection.Node : -1; +} + +ConsoleMethod( VPathEditor, deleteSelection, void, 2, 2, "( void )" ) +{ + // Valid Selection? + if ( object->isValidSelection() ) + { + object->deleteNode( object->mSelection.Node ); + } +} + +//----------------------------------------------------------------------------- +// +// Weight Editing Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::isEditingWeight( const Gui3DMouseEvent &pEvent ) +{ + if ( !isValidSelection() || mSelection.Path->mPathType != VPath::k_PathBezier ) + { + // False. + mEditWeight = false; + + // Invalid Selection. + return false; + } + + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + // Min Index. + S32 minNode = -1; + F32 minDistance = F32_MAX; + + for ( S32 i = 0; i < 2; i++ ) + { + Point3F pt; + if ( !Utility::FindNearestPointOnLine( mSelection.TangentHandle[i], pt0, pt1, &pt ) ) + { + // Skip. + continue; + } + + // Distance. + const F32 ptDistance = ( pt - mSelection.TangentHandle[i] ).len(); + if ( ptDistance < minDistance ) + { + // Store Index. + minNode = i; + + // Store Distance. + minDistance = ptDistance; + } + } + + if ( minDistance > gSelectionDistance ) + { + // False. + mEditWeight = false; + + // Too Far Away. + return false; + } + + // True. + mEditWeight = true; + mEditWeightHandle = minNode; + + return true; +} + +void VPathEditor::updateWeight( const Gui3DMouseEvent &pEvent ) +{ + if ( !isEditingWeight() ) + { + // Woops! + return; + } + + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + Point3F nodePos = node->getWorldPosition(); + + // Fetch Node Transform. + MatrixF mat = node->getWorldTransform(); + + // Fetch the Normal. + const VectorF planeNormal = mat.getColumn3F( 0 ); + + // Construct Plane. + const PlaneF plane( nodePos, planeNormal ); + + Point3F iPt; + if ( plane.intersect( pEvent.pos, pEvent.vec, &iPt ) ) + { +/* + // Fetch Edit Vector. + VectorF tangentVect( mSelection.TangentHandle[mEditWeightHandle] - nodePos ); + tangentVect.normalize(); + + // Fetch Mouse Vector. + VectorF mouseVec( iPt - nodePos ); + F32 mouseDist = mouseVec.len(); + mouseVec.normalize(); + + // Find the Angles. + F32 tangentAngle = mAtan2( -tangentVect.z, tangentVect.x ); + F32 mouseAngle = mAtan2( -mouseVec.z, mouseVec.x ); + + // Determine Sign. + const S32 sign = ( planeNormal.y > 0.f ) ? -1.f : 1.f; + + // Delta Rotation.. + const QuatF deltaRotation( AngAxisF( planeNormal, sign * ( mouseAngle - tangentAngle ) ) ); + + // Calculate New Rotation. + QuatF newRotation; + newRotation.mul( nodePos, deltaRotation ); + + // Apply Rotation. + setNodeRotation( mSelection.Node, newRotation ); +*/ +/* + // Fetch Edit Vector. + VectorF handleVec( mSelection.TangentHandle[mEditWeightHandle] - nodePos ); + handleVec.normalize(); + + // Fetch Mouse Vector. + VectorF mouseVec( iPt - nodePos ); + mouseVec.normalize(); + + // Find the Angles. + F32 handleAngle = Utility::GetPitch( handleVec ); //mAtan2( -handleVec.z, handleVec.x ); + F32 mouseAngle = Utility::GetPitch( mouseVec ); //mAtan2( -mouseVec.z, mouseVec.x ); + + // Determine Sign. + const S32 sign = ( planeNormal.y > 0.f ) ? -1.f : 1.f; + + // Delta Rotation. + MatrixF rotMat; + AngAxisF::RotateY( sign * ( mouseAngle - handleAngle ), &rotMat ); + + // Rotate. + mat.mul( rotMat ); + + QuatF newRotation; + newRotation.set( mat ); + + // Apply Rotation. + setNodeRotation( mSelection.Node, newRotation ); +*/ + // Apply Weight. + setNodeWeight( mSelection.Node, ( iPt - nodePos ).len() ); + } +} + +//----------------------------------------------------------------------------- +// +// Path Editing Methods. +// +//----------------------------------------------------------------------------- + +void VPathEditor::setPathPosition( const Point3F &pPosition ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Update Position. + serverPath->setPosition( pPosition ); + clientPath->setPosition( pPosition ); + + // Update Selection. + updateSelection(); +} + +void VPathEditor::setPathRotation( const QuatF &pRotation ) +{ + // Determine the Matrix. + MatrixF mat; + pRotation.setMatrix( &mat ); + mat.setPosition( mSelection.Path->getPosition() ); + + // Update Transform. + setPathTransform( mat ); +} + +void VPathEditor::setPathTransform( const MatrixF &pTransform ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Update Transform. + serverPath->setTransform( pTransform ); + clientPath->setTransform( pTransform ); + + // Update Selection. + updateSelection(); +} + +void VPathEditor::setPathScale( const VectorF &pScale ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Fetch Current Scale. + VectorF scale = serverPath->getScale(); + scale.convolve( pScale ); + + // Update Scale. + serverPath->setScale( scale ); + clientPath->setScale( scale ); + + // Update Selection. + updateSelection(); +} + +//----------------------------------------------------------------------------- +// +// Node Editing Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::getPointOnPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + if ( pPath->getNodeCount() < 2 ) + { + // Start / End Points. + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + // Create Intersection Plane. + const PlaneF plane( pPath->getPosition(), VPath::gBezierUp ); + + // Intersection Point. + Point3F intersectionPoint; + if ( !plane.intersect( pEvent.pos, pEvent.vec, &intersectionPoint ) ) + { + // No Intersection. + return false; + } + + // I'th Node. + pNode = pPath->getNodeCount(); + // Set Identity. + pTransform.identity(); + // Set Position. + pTransform.setPosition( intersectionPoint ); + + // Return. + return true; + } + + switch ( pPath->mPathType ) + { + case VPath::k_PathLinear : + { + + return getPointOnLinearPath( pPath, pEvent, pNode, pTransform ); + + } break; + + case VPath::k_PathBezier : + { + + return getPointOnBezierPath( pPath, pEvent, pNode, pTransform ); + + } break; + } + + return false; +} + +bool VPathEditor::getPointOnLinearPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + // Start / End Points. + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + S32 minNode = -1; + F32 minDistance = F32_MAX; + Point3F minPoint( 0.f, 0.f, 0.f ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Project to Screen. + Point3F srcNodeScreenPosition, dstNodeScreenPosition; + project( srcNode->getWorldPosition(), &srcNodeScreenPosition ); + project( dstNode->getWorldPosition(), &dstNodeScreenPosition ); + + // Skip? + if ( srcNodeScreenPosition.z > 1.f && dstNodeScreenPosition.z > 1.f ) + { + continue; + } + + Point3F ptOut0, ptOut1; + F32 ptOutDistance; + if ( !Utility::FindNearestDistanceBetweenLines( pt0, pt1, + srcNode->getWorldPosition(), dstNode->getWorldPosition(), + &ptOut0, &ptOut1, &ptOutDistance ) ) + { + continue; + } + + if ( ptOutDistance < minDistance ) + { + minDistance = ptOutDistance; + minPoint = ptOut1; + minNode = ( itr - pPath->mNodeList.begin() ); + } + } + + // Distance too Large? + if ( minDistance > 0.25f ) + { + // Invalid. + return false; + } + + // Setup. + pTransform.identity(); + pTransform.setPosition( minPoint ); + + // Store Node. + pNode = minNode; + + return true; +} + +bool VPathEditor::getPointOnBezierPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + S32 minNode = -1; + F32 minInterp = 0.f; + F32 minDistance = F32_MAX; + Point3F minPoint( 0.f, 0.f, 0.f ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Project to Screen. + Point3F srcNodeScreenPosition, dstNodeScreenPosition; + project( srcNode->getWorldPosition(), &srcNodeScreenPosition ); + project( dstNode->getWorldPosition(), &dstNodeScreenPosition ); + + // Skip? + if ( srcNodeScreenPosition.z > 1.f && dstNodeScreenPosition.z > 1.f ) + { + continue; + } + + // Positions. + const Point3F &pt0 = srcNode->getWorldPosition(); + const Point3F &pt3 = dstNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + srcNode->getWorldRotation().setMatrix( &mat0 ); + dstNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( VPath::gBezierAxis * srcNode->getWeight() ); + Point3F pt2( -VPath::gBezierAxis * dstNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + for ( F32 t = 0.f, it = 1.f; t <= 1.f; t += 0.1f, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F pos = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + + // Determine the Screen Position. + Point3F screenPos; + project( pos, &screenPos ); + // Behind? + if ( screenPos.z > 1.f ) + { + // Skip Point. + continue; + } + + // Determine the Distance. + F32 screenDistance = Point2F( screenPos.x - pEvent.mousePoint.x, screenPos.y - pEvent.mousePoint.y ).lenSquared(); + // Min Distance? + if ( screenDistance < minDistance ) + { + // Store. + minDistance = screenDistance; + minInterp = t; + minPoint = pos; + minNode = ( itr - pPath->mNodeList.begin() ); + } + } + } + + // Distance too Large? + if ( minDistance > 1000.f ) + { + // Invalid. + return false; + } + + // Fetch Orientation. + const VectorF &orientation = pPath->getPathOrientation( pPath->getNode( minNode ), + pPath->getNode( ( minNode + 1 ) % pPath->getNodeCount() ), + minInterp, true ); + + // Z-Axis. + VectorF zVec = -orientation; + zVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( VPath::gBezierUp, zVec ); + xVec.normalize(); + + // Y-Axis. + VectorF yVec = mCross( zVec, xVec ); + yVec.normalize(); + + // Setup Object Transform. + pTransform.identity(); + pTransform.setColumn( 0, xVec ); + pTransform.setColumn( 1, -zVec ); + pTransform.setColumn( 2, yVec ); + // Set the Position. + pTransform.setPosition( minPoint ); + + // Store Node. + pNode = minNode; + + return true; +} + +void VPathEditor::addNode( const Gui3DMouseEvent &pEvent ) +{ + VPath *path = mSelection.Path; + if ( !path ) + { + // Woops! + return; + } + + // Min Index. + S32 nodeIndex = -1; + MatrixF nodeTransform( true ); + if ( !getPointOnPath( path, pEvent, nodeIndex, nodeTransform ) ) + { + // Can't Add. + return; + } + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + Point3F nodePosition = ( nodeTransform.getPosition() - mSelection.Path->getPosition() ); + pathTransform.mulP( nodePosition ); + + // Node Rotation. + nodeTransform.mul( pathTransform ); + QuatF nodeRotation( nodeTransform ); + + // Node Weights. + F32 nodeWeight = 10.f; + + // Add New Node. + VPathNode *node = path->addNode( nodePosition, nodeRotation, nodeWeight, ++nodeIndex ); + + // Valid Node? + if ( !node ) + { + return; + } + + // Update Size. + path->updateContainer(); + + // Calculate Path. + path->calculatePath(); + + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor::addNode() - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorAddNodeAction *editAction = new VPathEditorAddNodeAction(); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = path; + editAction->mNodeIndex = nodeIndex; + + editAction->mNodePosition = nodePosition; + editAction->mNodeRotation = nodeRotation; + editAction->mNodeWeight = nodeWeight; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Set World Editor Dirty. + setWorldEditorDirty(); +} + +void VPathEditor::deleteNode( const S32 &pNodeIndex ) +{ + VPath *path = mSelection.Path; + if ( !path ) + { + // Woops! + return; + } + + // Fetch Node Properites. + VPathNode *node = path->getNode( pNodeIndex ); + const Point3F position = node->getLocalPosition(); + const QuatF rotation = node->getLocalRotation(); + const F32 weight = node->getWeight(); + + // Delete Node. + path->deleteNode( pNodeIndex ); + + // Update Path. + path->updateContainer(); + + // Calculate Path. + path->calculatePath(); + + // Selected Node? + const S32 _nodeIndex = pNodeIndex; + if ( pNodeIndex == mSelection.Node ) + { + // Update Selection. + updateSelection( mSelection.Path, -1 ); + } + + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor::deleteNode() - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorDeleteNodeAction *editAction = new VPathEditorDeleteNodeAction(); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = path; + editAction->mNodeIndex = _nodeIndex; + + editAction->mNodePosition = position; + editAction->mNodeRotation = rotation; + editAction->mNodeWeight = weight; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Set World Editor Dirty. + setWorldEditorDirty(); +} + +void VPathEditor::setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeLocalPosition( pNodeIndex ) == pPosition ) + { + return; + } + + // Set Position. + serverPath->setNodePosition( pNodeIndex, pPosition ); + clientPath->setNodePosition( pNodeIndex, pPosition ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodePosition", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeLocalRotation( pNodeIndex ) == pRotation ) + { + return; + } + + // Set Position. + serverPath->setNodeRotation( pNodeIndex, pRotation ); + clientPath->setNodeRotation( pNodeIndex, pRotation ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeRotation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeWeight( pNodeIndex ) == pWeight ) + { + return; + } + + // Set Weight. + serverPath->setNodeWeight( pNodeIndex, pWeight ); + clientPath->setNodeWeight( pNodeIndex, pWeight ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeWeight", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Set Orientation Mode. + serverPath->setNodeOrientationMode( pNodeIndex, pType ); + clientPath->setNodeOrientationMode( pNodeIndex, pType ); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeOrientation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F &pPoint ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Set Orientation Mode. + serverPath->setNodeOrientationMode( pNodeIndex, pType, pPoint ); + clientPath->setNodeOrientationMode( pNodeIndex, pType, pPoint ); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeOrientation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::pushPathEdit( void ) +{ + // Clear Current Edit Dirty. + mPathEdit.Dirty = false; + + if ( mSelection.Path != NULL ) + { + // Store Node Details. + mPathEdit.Transform = mSelection.Path->getTransform(); + } +} + +void VPathEditor::popPathEdit( void ) +{ + // Did Edit? + if ( mPathEdit.Dirty && mSelection.Path != NULL ) + { + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorEditPathAction *editAction = new VPathEditorEditPathAction( "Edit Path" ); + + // Store Editor. + editAction->mEditor = this; + + // Store Path Details. + editAction->mPath = mSelection.Path; + editAction->mTransform = mPathEdit.Transform; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Clear Dirty. + mPathEdit.Dirty = false; + + // Set World Editor Dirty. + setWorldEditorDirty(); + } +} + +void VPathEditor::pushNodeEdit( void ) +{ + // Clear Current Edit Dirty. + mNodeEdit.Dirty = false; + + if ( isValidSelection() ) + { + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Store Node Details. + mNodeEdit.Position = node->getLocalPosition(); + mNodeEdit.Rotation = node->getLocalRotation(); + mNodeEdit.Weight = node->getWeight(); + } +} + +void VPathEditor::popNodeEdit( void ) +{ + // Did Edit? + if ( mNodeEdit.Dirty && isValidSelection() ) + { + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorEditNodeAction *editAction = new VPathEditorEditNodeAction( "Edit Node" ); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = mSelection.Path; + editAction->mNodeIndex = mSelection.Node; + + editAction->mNodePosition = mNodeEdit.Position; + editAction->mNodeRotation = mNodeEdit.Rotation; + editAction->mNodeWeight = mNodeEdit.Weight; + + editAction->mNodeOrientation = mSelection.Path->getNode( mSelection.Node )->getOrientationMode(); + + // Add To Manager. + historyManager->addAction( editAction ); + + // Clear Dirty. + mNodeEdit.Dirty = false; + + // Set World Editor Dirty. + setWorldEditorDirty(); + } +} + +void VPathEditor::setWorldEditorDirty( void ) +{ + WorldEditor *worldEditor; + if ( Sim::findObject( "EWorldEditor", worldEditor ) ) + { + worldEditor->setDirty(); + } +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VPathEditor::setStateBlock( void ) +{ + // Valid State Block? + if ( !mStateBlock ) + { + // Setup Definition. + GFXStateBlockDesc def; + def.blendDefined = true; + def.blendEnable = true; + def.blendSrc = GFXBlendSrcAlpha; + def.blendDest = GFXBlendInvSrcAlpha; + def.zDefined = true; + def.cullDefined = false; + + // Create State Block. + mStateBlock = GFX->createStateBlock( def ); + } + + // Set State Block. + GFX->setStateBlock( mStateBlock ); +} + +void VPathEditor::renderScene( const RectI &pUpdateRect ) +{ + // Setup State Block. + setStateBlock(); + + if ( isValidSelection() ) + { + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Render Gizmo? + if ( mEditMode == k_Gizmo && mGizmoProfile->mode != ScaleMode ) + { + // Fetch Node Transform. + MatrixF mat= node->getWorldTransform(); + + // Move Gizmo. + mGizmo->set( mat, node->getWorldPosition(), Point3F( 1.0f, 1.0f, 1.0f ) ); + + // Render Gizmo. + mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix ); + } + + // Render Handles? + if ( mSelection.Path->mPathType == VPath::k_PathBezier ) + { + // Fetch Tangent Handles. + const Point3F &pt0 = mSelection.TangentHandle[0]; + const Point3F &pt1 = mSelection.TangentHandle[1]; + + // State Block. + GFXStateBlockDesc desc; + desc.setZReadWrite( true, true ); + desc.fillMode = GFXFillSolid; + + // Set Color. + PrimBuild::color( gPathColorSel ); + + // Render Line. + PrimBuild::begin( GFXLineList, 2 ); + PrimBuild::vertex3fv( pt0 ); + PrimBuild::vertex3fv( pt1 ); + PrimBuild::end(); + + // Render Handles. + GFX->getDrawUtil()->drawSphere( desc, 0.1f, pt0, gPathColorSel ); + GFX->getDrawUtil()->drawSphere( desc, 0.1f, pt1, gPathColorSel ); + } + + // ToPoint Node? + if ( node->getOrientationMode().Type == VPathNode::k_OrientationToPoint ) + { + PrimBuild::color( gNodeLookAtPointColor ); + PrimBuild::begin( GFXLineStrip, 2 ); + + PrimBuild::vertex3fv( node->getWorldPosition() ); + PrimBuild::vertex3fv( node->getOrientationMode().Point ); + + PrimBuild::end(); + } + } + else if ( mSelection.Path && mEditMode == k_Gizmo ) + { + switch ( mGizmoProfile->mode ) + { + case MoveMode: + { + // Fetch Path Transform. + const MatrixF &mat = mSelection.Path->getTransform(); + + // Fetch the Path's Box Center. + const Point3F &pos = mSelection.Path->getWorldBox().getCenter(); + + // Move Gizmo. + mGizmo->set( mat, pos, Point3F( 1.0f, 1.0f, 1.0f ) ); + + // Render Gizmo. + mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix ); + + } break; + } + } + + // Render Path Segments. + renderPaths( k_RenderSegments ); + + // Set Clip Rect. + GFX->setClipRect( pUpdateRect ); + + // Render Path Nodes. + renderPaths( k_RenderNodes ); + + if ( isValidSelection() ) + { + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // ToPoint Node? + if ( node->getOrientationMode().Type == VPathNode::k_OrientationToPoint ) + { + // Project to Screen. + Point3F screenPosition; + project( node->getOrientationMode().Point, &screenPosition ); + if ( screenPosition.z <= 1.0f ) + { + // Determine the center & size of the node rectangle. + Point2I nodeCenter = Point2I( screenPosition.x, screenPosition.y ); + Point2I nodeHalfSize = Point2I( 8, 8 ); + // Determine Render Rectangle. + RectI nodeRect; + nodeRect.point = nodeCenter - nodeHalfSize; + nodeRect.extent = ( 2 * nodeHalfSize ); + + // Draw? + if ( getBounds().overlaps( nodeRect ) ) + { + // Render the Point. + GFX->getDrawUtil()->drawRectFill( nodeRect, gNodeLookAtPointColor ); + } + } + } + } +} + +void VPathEditor::renderPaths( const RenderType &pRenderType ) +{ + SimSet *objectSet = VPath::getServerSet(); + for ( SimSetIterator itr( objectSet ); *itr; ++itr ) + { + VPath *path = dynamic_cast( *itr ); + if ( path ) + { + // Render Path. + renderPath( pRenderType, path, ( path == mSelection.Path ) ? gPathColorSel : gPathColor ); + } + } +} + +void VPathEditor::renderPath( const RenderType &pRenderType, VPath *pPath, const ColorI &pColor ) +{ + if ( !pPath ) + { + // Sanity! + return; + } + + switch ( pRenderType ) + { + case k_RenderSegments : + { + switch ( pPath->mPathType ) + { + case VPath::k_PathLinear : + { + renderLinearPath( pPath, pColor ); + + } break; + + case VPath::k_PathBezier : + { + renderBezierPath( pPath, pColor ); + + } break; + } + + } break; + + case k_RenderNodes : + { + // Fetch Draw Util. + GFXDrawUtil *drawUtil = GFX->getDrawUtil(); + + // Fetch Bounds. + RectI bounds = getBounds(); + + const Point2I nodeMinHalfSize( 8, 8 ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Project to Screen. + Point3F screenPosition; + project( node->getWorldPosition(), &screenPosition ); + if ( screenPosition.z > 1.0f ) + { + continue; + } + + // Determine the node text information. + const char *nodeText = avar( "%d", ( itr - pPath->mNodeList.begin() ) ); + const Point2I nodeTextHalfSize = Point2I( 0.5f * (F32)getControlProfile()->mFont->getStrWidth( nodeText ), + 0.5f * (F32)getControlProfile()->mFont->getHeight() ); + + // Determine the center & size of the node rectangle. + Point2I nodeCenter = Point2I( screenPosition.x, screenPosition.y ); + Point2I nodeHalfSize = Point2I( nodeTextHalfSize.x + 3, nodeTextHalfSize.y + 3 ); + nodeHalfSize.setMax( nodeMinHalfSize ); + // Determine Render Rectangle. + RectI nodeRect; + nodeRect.point = nodeCenter - nodeHalfSize; + nodeRect.extent = ( 2 * nodeHalfSize ); + + // Draw? + if ( !bounds.overlaps( nodeRect ) ) + { + continue; + } + + // Render the Point. + drawUtil->drawRectFill( nodeRect, pColor ); + + // Draw the node index text. + drawUtil->setBitmapModulation( getControlProfile()->mFontColor ); + drawUtil->drawText( getControlProfile()->mFont, nodeCenter - nodeTextHalfSize, nodeText ); + } + + } break; + } +} + +void VPathEditor::renderLinearPath( VPath *pPath, const ColorI &pColor ) +{ + if ( pPath->mNodeList.size() < 2 ) + { + // No Lines. + return; + } + + PrimBuild::color( pColor ); + PrimBuild::begin( GFXLineStrip, ( pPath->mNodeList.size() + 1 ) ); + + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Apply Vertex. + PrimBuild::vertex3fv( ( *itr )->getWorldPosition() ); + } + + // Loop Back. + PrimBuild::vertex3fv( pPath->mNodeList.front()->getWorldPosition() ); + + PrimBuild::end(); +} + +void VPathEditor::renderBezierPath( VPath *pPath, const ColorI &pColor ) +{ + if ( pPath->mNodeList.size() < 2 ) + { + // No Lines. + return; + } + + PrimBuild::color( pColor ); + PrimBuild::begin( GFXLineStrip, U32( ( ( 1.01f / 0.01f ) + 1 ) * pPath->mNodeList.size() ) ); + + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Positions. + const Point3F &pt0 = srcNode->getWorldPosition(); + const Point3F &pt3 = dstNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + srcNode->getWorldRotation().setMatrix( &mat0 ); + dstNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( VPath::gBezierAxis * srcNode->getWeight() ); + Point3F pt2( -VPath::gBezierAxis * dstNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + for ( F32 t = 0.f, it = 1.f; t <= 1.f; t += 0.01f, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F pos = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + // Apply Vertex. + PrimBuild::vertex3fv( pos ); + } + } + + PrimBuild::end(); +} + +//----------------------------------------------------------------------------- +// +// History Events +// +//----------------------------------------------------------------------------- + +void VPathEditor::VPathEditorEditPathAction::undo( void ) +{ + const MatrixF oldTransform = mTransform; + const MatrixF newTransform = mPath->getTransform(); + + // Apply Old Values. + mEditor->setPathTransform( oldTransform ); + + // The ol' Switcheroo. + mTransform = newTransform; + + // Update Selection. + mEditor->updateSelection(); + + if ( mPath == mEditor->mSelection.Path ) + { + // Arg Buffer. + char buffer[32]; + dSprintf( buffer, sizeof( buffer ), "%d", mPath->getId() ); + + // Callback. + Con::executef( mEditor, "onUpdatePath", buffer ); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorEditPathAction::redo( void ) +{ + // Undo. + undo(); +} + +void VPathEditor::VPathEditorEditNodeAction::undo( void ) +{ + // Fetch Properties. + const Point3F oldPosition = mNodePosition; + const QuatF oldRotation = mNodeRotation; + const F32 oldWeight = mNodeWeight; + const VPathNode::sOrientation oldOrientation = mNodeOrientation; + + VPathNode *node = mPath->getNode( mNodeIndex ); + const Point3F newPosition = node->getLocalPosition(); + const QuatF newRotation = node->getLocalRotation(); + const F32 newWeight = node->getWeight(); + const VPathNode::sOrientation newOrientation = node->getOrientationMode(); + + // Apply Old Values. + mPath->setNodePosition( mNodeIndex, oldPosition ); + mPath->setNodeRotation( mNodeIndex, oldRotation ); + mPath->setNodeWeight( mNodeIndex, oldWeight ); + + switch( oldOrientation.Type ) + { + case VPathNode::k_OrientationFree : + { + + // Orient Free. + mPath->setNodeOrientationMode( mNodeIndex, oldOrientation.Type ); + + } break; + + case VPathNode::k_OrientationToPoint : + { + + // Orient To Point. + mPath->setNodeOrientationMode( mNodeIndex, oldOrientation.Type, oldOrientation.Point ); + + } break; + } + + // The ol' Switcheroo. + mNodePosition = newPosition; + mNodeRotation = newRotation; + mNodeWeight = newWeight; + mNodeOrientation = newOrientation; + + // Update Selection. + mEditor->updateSelection(); + + if ( mPath == mEditor->mSelection.Path ) + { + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mPath->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", mNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mEditor->mSelection.Node == mNodeIndex ) ); + + // Callback. + Con::executef( mEditor, "onUpdateNode", buffer[0], buffer[1], buffer[2] ); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorEditNodeAction::redo( void ) +{ + // Undo. + undo(); +} + +void VPathEditor::VPathEditorAddNodeAction::undo( void ) +{ + // Selected Node? + if ( mNodeIndex == mEditor->mSelection.Node ) + { + // Update Selection. + mEditor->updateSelection( mEditor->mSelection.Path, -1 ); + } + + // Delete Node. + mPath->deleteNode( mNodeIndex ); + + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorAddNodeAction::redo( void ) +{ + // Add Node. + VPathNode *node = mPath->addNode( mNodePosition, mNodeRotation, mNodeWeight, mNodeIndex ); + + // Valid Node? + if ( node ) + { + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorDeleteNodeAction::undo( void ) +{ + // Add Node. + VPathNode *node = mPath->addNode( mNodePosition, mNodeRotation, mNodeWeight, mNodeIndex ); + + // Valid Node? + if ( node ) + { + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorDeleteNodeAction::redo( void ) +{ + // Delete Node. + mPath->deleteNode( mNodeIndex ); + + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +//----------------------------------------------------------------------------- +// +// Script Edit Methods +// +//----------------------------------------------------------------------------- + +ConsoleMethod( VPathEditor, setNodePosition, void, 3, 3, "( pPosition )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodePosition() - Invalid Node Selection." ); + return; + } + + // Fetch Position. + Point3F position; + dSscanf( argv[2], "%g %g %g", &position.x, &position.y, &position.z ); + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodePosition( object->mSelection.Node, position ); + + // Create Undo Action. + object->popNodeEdit(); +} + +ConsoleMethod( VPathEditor, setNodeRotation, void, 3, 3, "( pRotation )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeRotation() - Invalid Node Selection." ); + return; + } + + // Fetch Rotation. + AngAxisF aa; + QuatF rotation; + dSscanf( argv[2], "%g %g %g %g", &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle ); + + // Set Rotation. + rotation.set( aa ); + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodeRotation( object->mSelection.Node, rotation ); + + // Create Undo Action. + object->popNodeEdit(); +} + +ConsoleMethod( VPathEditor, setNodeWeight, void, 3, 3, "( pWeight )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeWeight() - Invalid Node Selection." ); + return; + } + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodeWeight( object->mSelection.Node, dAtof( argv[2] ) ); + + // Create Undo Action. + object->popNodeEdit(); +} + +ConsoleMethod( VPathEditor, setNodeOrientationMode, void, 3, 4, "( string pOrientationType, [vector pPoint] )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeOrientationMode() - Invalid Node Selection." ); + return; + } + + // Store. + object->pushNodeEdit(); + + // Orient? + const VPathNode::eOrientationType type = VPathNode::getOrientationTypeEnum( argv[2] ); + + switch ( type ) + { + case VPathNode::k_OrientationFree : + { + + // Apply Mode. + object->setNodeOrientationMode( object->mSelection.Node, type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( argv[3], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + object->setNodeOrientationMode( object->mSelection.Node, type, lookAtPoint ); + + } break; + } + + // Create Undo Action. + object->popNodeEdit(); +} + +//----------------------------------------------------------------------------- +// +// Utility +// +//----------------------------------------------------------------------------- + +bool Utility::FindNearestDistanceBetweenLines( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, Point3F *pOutA, Point3F *pOutB, F32 *pDist ) +{ + const Point3F pA1A0 = ( pA1 - pA0 ); + if ( pA1A0.isZero() ) + { + return false; + } + + const Point3F pB1B0 = ( pB1 - pB0 ); + if ( pB1B0.isZero() ) + { + return false; + } + + const Point3F pA0B0 = ( pA0 - pB0 ); + + const F32 &d1343 = pA0B0.x * pB1B0.x + pA0B0.y * pB1B0.y + pA0B0.z * pB1B0.z; + const F32 &d4321 = pB1B0.x * pA1A0.x + pB1B0.y * pA1A0.y + pB1B0.z * pA1A0.z; + const F32 &d1321 = pA0B0.x * pA1A0.x + pA0B0.y * pA1A0.y + pA0B0.z * pA1A0.z; + const F32 &d4343 = pB1B0.x * pB1B0.x + pB1B0.y * pB1B0.y + pB1B0.z * pB1B0.z; + const F32 &d2121 = pA1A0.x * pA1A0.x + pA1A0.y * pA1A0.y + pA1A0.z * pA1A0.z; + + const F32 &denom = d2121 * d4343 - d4321 * d4321; + if ( mIsZero( denom ) ) + { + return false; + } + + const F32 &mua = ( d1343 * d4321 - d1321 * d4343 ) / denom; + const F32 &mub = ( d1343 + d4321 * mua ) / d4343; + + *pOutA = pA0 + mua *pA1A0; + *pOutB = pB0 + mub *pB1B0; + + // Store Distance. + *pDist = ( ( *pOutA ) - ( *pOutB ) ).len(); + + return true; +} + +bool Utility::IntersectLineSegment( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, const bool pSnap, Point3F *pX ) +{ + // + // Finding the intersection with the following method: + // We have line a going from P1 to P2: + // Pa = P1 + ua( P2 - P1 ) + // and line b going from P3 to P4: + // Pb = P3 + ub( P4 - P3 ) + // + // Solving for Pa = Pb: + // x1 + ua( x2 - x1 ) = x3 + ub( x4 - x3 ) + // y1 + ua( y2 - y1 ) = y3 + ub( y4 - y3 ) + // + // Solving for ua and ub: + // ua = ( ( x4 - x3 )( y1 - y3 ) - ( y4 - y3 )( x1 - x3 ) ) / d + // ub = ( ( x2 - x1 )( y1 - y3 ) - ( y2 - y1 )( x1 - x3 ) ) / d + // denom = ( y4 - y3 )( x2 - x1 ) - ( x4 - x3 )( y2 - y1 ) + // + // x = x1 + ua( x2 - x1 ) + // y = y1 + ua( y2 - y1 ) + // + + const F32 d = ( ( pB1.y - pB0.y ) * ( pA1.x - pA0.x ) ) - ( ( pB1.x - pB0.x ) * ( pA1.y - pA0.y ) ); + + if ( d == 0.0f ) + { + // Lines are parallel + return false; + } + + // Find the point of intersection + const F32 uA = ( ( ( pB1.x - pB0.x ) * ( pA0.y - pB0.y ) ) - ( ( pB1.y - pB0.y ) * ( pA0.x - pB0.x ) ) ) / d; + const F32 uB = ( ( ( pA1.x - pA0.x ) * ( pA0.y - pB0.y ) ) - ( ( pA1.y - pA0.y ) * ( pA0.x - pB0.x ) ) ) / d; + + if ( !pSnap + && ( ( uA < 0.0f ) || ( uA > 1.0f ) + || ( uB < 0.0f ) || ( uB > 1.0f ) ) ) + { + return false; + } + + if ( pX ) + { + if ( uA < 0.0f ) + { + *pX = pA0; + } + else if ( uA > 1.f ) + { + *pX = pA1; + } + else + { + // The path intersects the segment + *pX = pA0 + uA * ( pA1 - pA0 ); + } + } + + return true; +} + +bool Utility::FindNearestPointOnLine( const Point3F &pSrcPosition, const Point3F &pA0, const Point3F &pA1, Point3F *pDstPosition ) +{ + const Point3F up( 0.0f, 0.0f, 1.0f ); + + Point3F dir = ( pA1 - pA0 ); + dir.normalize(); + + Point3F normal = mCross( dir, up ); + normal.normalize(); + + // Find the nearest intersection point between the point and the line + + const Point3F b0 = pSrcPosition + ( normal * 100000.0f ); + const Point3F b1 = pSrcPosition - ( normal * 100000.0f ); + + return IntersectLineSegment( pA0, pA1, b0, b1, true, pDstPosition ); +} + +F32 Utility::GetPitch( const VectorF &pVec ) +{ + F32 pitch; + if ( mFabs( pVec.x ) > mFabs( pVec.y ) ) + { + pitch = mAtan2( mFabs( pVec.z ), mFabs( pVec.x ) ); + } + else + { + pitch = mAtan2( mFabs( pVec.z ), mFabs( pVec.y ) ); + } + + if ( pVec.z < 0.f ) + { + pitch = -pitch; + } + + return pitch; +} + +F32 Utility::GetYaw( const VectorF &pVec ) +{ + F32 yaw = mAtan2( pVec.x, pVec.y ); + if ( yaw < 0.f ) + { + yaw += M_2PI_F; + } + + return yaw; +} \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathEditor.h b/Engine/modules/Verve/VPath/VPathEditor.h new file mode 100644 index 000000000..c337edd0c --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathEditor.h @@ -0,0 +1,293 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHEDITOR_H_ +#define _VT_VPATHEDITOR_H_ + +#ifndef _EDITTSCTRL_H_ +#include "gui/worldEditor/editTSCtrl.h" +#endif + +#ifndef _VT_VPATH_H_ +#include "VPath.h" +#endif + +#ifndef _UNDO_H_ +#include "util/undo.h" +#endif + +//----------------------------------------------------------------------------- + +class VPathEditor : public EditTSCtrl +{ + typedef EditTSCtrl Parent; + +public: + + enum RenderType + { + k_RenderSegments, + k_RenderNodes, + }; + + enum EditMode + { + k_Gizmo, + k_AddNode, + k_DeleteNode + }; + + struct Selection + { + Selection( void ) : + Path( NULL ), + Node( -1 ) + { + TangentHandle[0].zero(); + TangentHandle[1].zero(); + }; + + VPath *Path; + S32 Node; + Point3F TangentHandle[2]; + }; + + struct PathEditAction + { + PathEditAction( void ) : + Dirty( false ), + Transform( true ) + { + // Void. + }; + + bool Dirty; + MatrixF Transform; + }; + + struct NodeEditAction + { + NodeEditAction( void ) : + Dirty( false ), + Position( 0.f, 0.f, 0.f ), + Rotation( 0.f, 0.f, 0.f, 0.f ), + Weight( 0.f ) + { + // Void. + }; + + bool Dirty; + Point3F Position; + QuatF Rotation; + F32 Weight; + }; + + bool mIsDirty; + EditMode mEditMode; + + Selection mSelection; + PathEditAction mPathEdit; + NodeEditAction mNodeEdit; + + bool mEditWeight; + S32 mEditWeightHandle; + + GFXStateBlockRef mStateBlock; + +public: + + VPathEditor( void ); + + virtual bool onAdd( void ); + virtual bool onWake( void ); + + static void initPersistFields( void ); + + // Gui Events. + + virtual void on3DMouseDown( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseUp( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseMove( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseDragged( const Gui3DMouseEvent &pEvent ); + + // Render Methods. + + virtual void setStateBlock( void ); + virtual void renderScene( const RectI &pUpdateRect ); + void renderPaths( const RenderType &pRenderType ); + + void renderPath( const RenderType &pRenderType, VPath *pPath, const ColorI &pColor ); + void renderLinearPath( VPath *pPath, const ColorI &pColor ); + void renderBezierPath( VPath *pPath, const ColorI &pColor ); + + DECLARE_CONOBJECT( VPathEditor ); + +public: + + // Reference Methods. + + VPath *getClientPath( VPath *pPath ); + + // Selection Methods. + + inline bool isValidSelection( void ) { return ( mSelection.Path != NULL && mSelection.Node != -1 ); }; + + bool updateSelection( const Gui3DMouseEvent &pEvent ); + void updateSelection( VPath *pPathObject, const S32 &pNodeIndex ); + void updateSelection( void ); + + // Weight Editing. + + bool isEditingWeight( const Gui3DMouseEvent &pEvent ); + inline bool isEditingWeight( void ) { return mEditWeight; }; + + void updateWeight( const Gui3DMouseEvent &pEvent ); + + // Path Editor. + + bool getPointOnPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + bool getPointOnLinearPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + bool getPointOnBezierPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + + void setPathPosition( const Point3F &pPosition ); + void setPathRotation( const QuatF &pRotation ); + void setPathTransform( const MatrixF &pTransform ); + void setPathScale( const VectorF &pScale ); + + // Node Editing. + + void addNode( const Gui3DMouseEvent &pEvent ); + void deleteNode( const S32 &pNodeIndex ); + + void setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ); + void setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ); + void setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F &pPoint ); + + void pushPathEdit( void ); + void popPathEdit( void ); + + void pushNodeEdit( void ); + void popNodeEdit( void ); + + void setWorldEditorDirty( void ); + +private: + + class VPathEditorEditPathAction : public UndoAction + { + public: + + VPathEditorEditPathAction( const UTF8 *pName = "" ) : + UndoAction( pName ) + { + // Void. + }; + + VPathEditor *mEditor; + + VPath *mPath; + MatrixF mTransform; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorEditNodeAction : public UndoAction + { + public: + + VPathEditorEditNodeAction( const UTF8 *pName = "" ) : + UndoAction( pName ) + { + // Void. + }; + + VPathEditor *mEditor; + + VPath *mPath; + S32 mNodeIndex; + + Point3F mNodePosition; + QuatF mNodeRotation; + F32 mNodeWeight; + + VPathNode::sOrientation mNodeOrientation; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorAddNodeAction : public VPathEditorEditNodeAction + { + public: + + VPathEditorAddNodeAction( const UTF8 *pName = "" ) : + VPathEditorEditNodeAction( "Add Node" ) + { + // Void. + }; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorDeleteNodeAction : public VPathEditorEditNodeAction + { + public: + + VPathEditorDeleteNodeAction( const UTF8 *pName = "" ) : + VPathEditorEditNodeAction( "Delete Node" ) + { + // Void. + }; + + virtual void undo( void ); + virtual void redo( void ); + }; +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathEditor::EditMode VPathEditorMode; + +// Declare Enum Types. +DefineEnumType( VPathEditorMode ); + +//----------------------------------------------------------------------------- + +namespace Utility +{ + bool FindNearestDistanceBetweenLines( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, Point3F *pOutA, Point3F *pOutB, F32 *pDist ); + + bool IntersectLineSegment( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, const bool pSnap, Point3F *pX ); + bool FindNearestPointOnLine( const Point3F &pSrcPosition, const Point3F &pA0, const Point3F &pA1, Point3F *pDstPosition ); + + F32 GetPitch( const VectorF &pVec ); + F32 GetYaw( const VectorF &pVec ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHEDITOR_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathNode.cpp b/Engine/modules/Verve/VPath/VPathNode.cpp new file mode 100644 index 000000000..d18794c4e --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathNode.cpp @@ -0,0 +1,470 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathNode.h" +#include "VPath.h" + +#include "core/stream/bitStream.h" +#include "core/strings/stringUnit.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathNode::k_OrientationTypeSize ) ); + +//----------------------------------------------------------------------------- + +VPathNode::VPathNode( void ) : + mPath( NULL ), + mLocalPosition( Point3F( 0.f, 0.f, 0.f ) ), + mLocalRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), + mWorldPosition( Point3F( 0.f, 0.f, 0.f ) ), + mWorldRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), + mWeight( 10.f ), + mLength( 0.f ) +{ + // Init. + mOrientationMode.Type = k_OrientationFree; + mOrientationMode.Point = Point3F::Zero; + + // Set the initial mask. + mNetState.setMaskBits( k_StateInit ); + + VECTOR_SET_ASSOCIATION( mNetState ); +} + +VPathNode::~VPathNode( void ) +{ + mNetState.clear(); +} + +//----------------------------------------------------------------------------- +// +// Network Methods. +// +//----------------------------------------------------------------------------- + +U32 VPathNode::packNode( NetConnection *pConnection, BitStream *pStream ) +{ + // Init Return Mask. + U32 retMask = 0; + + // Fetch State. + VNetStateInfo *state = getState( pConnection ); + + // Note: This is out of sync with VPathNode::unpackUpdate(). + // If you're ever going to use these methods outside of VPath, you + // will need to read a flag *before* calling unpack! + + // Was the Node Created? + if ( pStream->writeFlag( state->Mask & k_StateCreate ) ) + { + // Clear Update. + state->Mask &= ~k_StateCreate; + } + + // Send mLocalPosition? + if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) + { + // Write mLocalPosition. + pStream->write( mLocalPosition.x ); + pStream->write( mLocalPosition.y ); + pStream->write( mLocalPosition.z ); + + // Clear Update. + state->Mask &= ~k_StateUpdatePosition; + } + + // Send mLocalRotation? + if ( pStream->writeFlag( state->Mask & k_StateUpdateRotation ) ) + { + // Write mLocalRotation. + pStream->write( mLocalRotation.x ); + pStream->write( mLocalRotation.y ); + pStream->write( mLocalRotation.z ); + pStream->write( mLocalRotation.w ); + + // Clear Update. + state->Mask &= ~k_StateUpdateRotation; + } + + // Send mWeight? + if ( pStream->writeFlag( state->Mask & k_StateUpdateWeight ) ) + { + // Write mWeight. + pStream->write( mWeight ); + + // Clear Update. + state->Mask &= ~k_StateUpdateWeight; + } + + // Send Orientation Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateOrientation ) ) + { + // Clear Update? + bool clearUpdate = true; + + // Write State. + pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToPoint : + { + // Write Point. + pStream->write( mOrientationMode.Point.x ); + pStream->write( mOrientationMode.Point.y ); + pStream->write( mOrientationMode.Point.z ); + + } break; + } + + if ( clearUpdate ) + { + // Clear Update. + state->Mask &= ~k_StateUpdateOrientation; + } + } + + // Return Mask. + return retMask; +} + +void VPathNode::unpackNode( NetConnection *pConnection, BitStream *pStream ) +{ + // Note: This is out of sync with VPathNode::packUpdate(). + // If you're ever going to use these methods outside of VPath, you + // will need to read a flag *before* calling unpack! + + // Update World Data. + bool updateWorld = false; + + // Update Local Position? + if ( pStream->readFlag() ) + { + // Read Local Position. + pStream->read( &mLocalPosition.x ); + pStream->read( &mLocalPosition.y ); + pStream->read( &mLocalPosition.z ); + + updateWorld = true; + } + + // Update Local Rotation? + if ( pStream->readFlag() ) + { + // Read Local Rotation. + pStream->read( &mLocalRotation.x ); + pStream->read( &mLocalRotation.y ); + pStream->read( &mLocalRotation.z ); + pStream->read( &mLocalRotation.w ); + + updateWorld = true; + } + + // Update Weight? + if ( pStream->readFlag() ) + { + // Read Weight. + pStream->read( &mWeight ); + } + + // Update Orientation? + if ( pStream->readFlag() ) + { + // Read Orientation Mode. + mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToPoint : + { + // Read Point. + pStream->read( &mOrientationMode.Point.x ); + pStream->read( &mOrientationMode.Point.y ); + pStream->read( &mOrientationMode.Point.z ); + + } break; + } + } + + if ( updateWorld ) + { + // Update World Position. + updateWorldData(); + } +} + +String VPathNode::toString( void ) +{ + String retBuffer; + + // Buffer Node Properties. + // {Position} {Rotation} {Weight} + const AngAxisF aa( mLocalRotation ); + retBuffer = String::ToString( "%f %f %f %f %f %f %f %f", mLocalPosition.x, mLocalPosition.y, mLocalPosition.z, + aa.axis.x, aa.axis.y, aa.axis.z, aa.angle, + mWeight ); + + // Add Tab. + retBuffer += "\t"; + + // Determine the Type. + StringTableEntry typeString = getOrientationTypeLabel( mOrientationMode.Type ); + switch( mOrientationMode.Type ) + { + case k_OrientationFree : + { + // Buffer String. + retBuffer += typeString; + + } break; + + case k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = mOrientationMode.Point; + + // Buffer String. + retBuffer += String::ToString( "%s %f %f %f", typeString, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return String. + return retBuffer; +} + +bool VPathNode::fromString( const String &pString ) +{ + // Split Data. + // {Position} {Rotation} {Weight} + const char *baseData = StringUnit::getUnit( pString.c_str(), 0, "\t" ); + + Point3F pos; + AngAxisF aa; + F32 weight; + + // Scan Base. + dSscanf( baseData, "%g %g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z, + &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle, + &weight ); + + // Apply Changes. + setLocalPosition( pos ); + setLocalRotation( QuatF( aa ) ); + setWeight( weight ); + + // Fetch Orientation Data. + String orientationData = StringUnit::getUnit( pString.c_str(), 1, "\t" ); + + // Fetch Orientation Type. + String orientationTypeString = orientationData; + if ( orientationData.find( " " ) ) + { + // Use First Word. + orientationTypeString = orientationData.substr( 0, orientationData.find( " " ) ); + } + + // Set Orientation Type. + const eOrientationType &orientationType = getOrientationTypeEnum( orientationTypeString.c_str() ); + switch( orientationType ) + { + case k_OrientationFree : + { + // Apply Mode. + setOrientationMode( orientationType ); + + } break; + + case k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint; + // Buffer String. + dSscanf( orientationData.c_str(), "%*s %f %f %f", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + setOrientationMode( orientationType, lookAtPoint ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +Point3F VPathNode::getWorldPosition( void ) const +{ + return mWorldPosition; +} + +QuatF VPathNode::getWorldRotation( void ) const +{ + return mWorldRotation; +} + +MatrixF VPathNode::getWorldTransform( void ) const +{ + MatrixF mat; + getWorldRotation().setMatrix( &mat ); + mat.setPosition( getWorldPosition() ); + + return mat; +} + +void VPathNode::setLocalPosition( const Point3F &pPosition ) +{ + // Update? + if ( mLocalPosition != pPosition ) + { + // Apply. + mLocalPosition = pPosition; + + // Update World Position. + updateWorldData(); + + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathNode::setLocalRotation( const QuatF &pRotation ) +{ + // Update? + if ( mLocalRotation != pRotation ) + { + // Apply. + mLocalRotation = pRotation; + + // Update World Rotation. + updateWorldData(); + + // Flag Update. + setMaskBits( k_StateUpdateRotation ); + } +} + +void VPathNode::setWeight( const F32 &pWeight ) +{ + // Update? + if ( mWeight != pWeight ) + { + // Apply. + mWeight = pWeight; + + // Flag Update. + setMaskBits( k_StateUpdateWeight ); + } +} + +void VPathNode::setOrientationMode( const eOrientationType &pType ) +{ + // Update? + if ( mOrientationMode.Type != pType ) + { + // Update. + mOrientationMode.Type = pType; + + // Flag Update. + setMaskBits( k_StateUpdateOrientation ); + } +} + +void VPathNode::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) +{ + AssertFatal( pType == k_OrientationToPoint, "VPathNode::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Point = pPoint; + + // Flag Update. + setMaskBits( k_StateUpdateOrientation ); + } +} + +void VPathNode::updateWorldData( void ) +{ + if ( !mPath ) + { + setWorldPosition( getLocalPosition() ); + setWorldRotation( getLocalRotation() ); + return; + } + + // Fetch Path Details. + const MatrixF &pathTransform = mPath->getTransform(); + const QuatF &pathRotation( pathTransform ); + + // Calculate the World Position. + Point3F newPosition = getLocalPosition(); + newPosition.convolve( mPath->getScale() ); + pathTransform.mulP( newPosition ); + + // Calculate the new Rotation. + QuatF newRotation; + newRotation.mul( getLocalRotation(), pathRotation ); + + // Apply. + setWorldPosition( newPosition ); + setWorldRotation( newRotation ); +} + +//----------------------------------------------------------------------------- +// +// Enumeration Methods. +// +//----------------------------------------------------------------------------- + +// Implement the Orientation Type enum list. +ImplementEnumType( VPathNodeOrientationType,"" ) + { VPathNode::k_OrientationFree, "FREE" }, + { VPathNode::k_OrientationToPoint, "TOPOINT" }, +EndImplementEnumType; + +VPathNode::eOrientationType VPathNode::getOrientationTypeEnum( const char *pLabel ) +{ + VPathNode::eOrientationType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPathNode::k_OrientationFree; + } + + // Return. + return out; +} + +StringTableEntry VPathNode::getOrientationTypeLabel( const eOrientationType &pType ) +{ + // Return. + return castConsoleTypeToString( pType ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathNode.h b/Engine/modules/Verve/VPath/VPathNode.h new file mode 100644 index 000000000..dd829c5b5 --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathNode.h @@ -0,0 +1,172 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHNODE_H_ +#define _VT_VPATHNODE_H_ + +#ifndef _GAMEBASE_H_ +#include "T3D/gameBase/gameBase.h" +#endif + +#ifndef _VNETSTATE_H_ +#include "VNetState.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; +class VPathNode +{ +public: + + enum eState + { + k_StateUpdatePosition = BIT( 0 ), + k_StateUpdateRotation = BIT( 1 ), + k_StateUpdateWeight = BIT( 2 ), + + k_StateUpdateOrientation = BIT( 3 ), + + k_StateCreate = BIT( 4 ), + k_StateDelete = BIT( 5 ), + + k_StateUpdate = ( k_StateUpdatePosition | k_StateUpdateRotation | k_StateUpdateWeight | k_StateUpdateOrientation ), + + k_StateInit = ( k_StateCreate | k_StateUpdate ), + }; + + enum eOrientationType + { + k_OrientationFree, + k_OrientationToPoint, + + k_OrientationTypeSize, + }; + + struct sOrientation + { + eOrientationType Type; + + // k_OrientationToPoint + Point3F Point; + }; + +protected: + + VPath *mPath; + + VNetState mNetState; + + sOrientation mOrientationMode; + + Point3F mLocalPosition; + QuatF mLocalRotation; + + Point3F mWorldPosition; + QuatF mWorldRotation; + + F32 mWeight; + F32 mLength; + +public: + + VPathNode( void ); + virtual ~VPathNode( void ); + + // Serialisation Methods. + + virtual U32 packNode( NetConnection *pConnection, BitStream *pStream ); + virtual void unpackNode( NetConnection *pConnection, BitStream *pStream ); + + virtual String toString( void ); + virtual bool fromString( const String &pString ); + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline VPath *getPath( void ) const { return mPath; }; + + inline const Point3F &getLocalPosition( void ) const { return mLocalPosition; }; + inline const QuatF &getLocalRotation( void ) const { return mLocalRotation; }; + + virtual Point3F getWorldPosition( void ) const; + virtual QuatF getWorldRotation( void ) const; + virtual MatrixF getWorldTransform( void ) const; + + inline const F32 &getWeight( void ) const { return mWeight; }; + inline const F32 &getLength( void ) const { return mLength; }; + + inline const sOrientation &getOrientationMode( void ) const { return mOrientationMode; }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + inline void setPath( VPath *pPath ) { mPath = pPath; }; + + void setLocalPosition( const Point3F &pPosition ); + void setLocalRotation( const QuatF &pRotation ); + + inline void setWorldPosition( const Point3F &pPosition ) { mWorldPosition = pPosition; }; + inline void setWorldRotation( const QuatF &pRotation ) { mWorldRotation = pRotation; }; + + void setWeight( const F32 &pWeight ); + inline void setLength( const F32 &pLength ) { mLength = pLength; }; + + void setOrientationMode( const eOrientationType &pType ); + void setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ); + + void updateWorldData( void ); + + // Net State Methods. + + inline VNetStateInfo *getState( NetConnection *pConnection ) { return mNetState.getState( pConnection ); }; + + inline void setMaskBits( const U32 &pMask ) { mNetState.setMaskBits( pMask ); }; + inline void clearMaskBits( const U32 &pMask ) { mNetState.clearMaskBits( pMask ); }; + + inline bool isConnection( NetConnection *pConnection ) { return mNetState.isConnection( pConnection ); }; + inline void addConnection( NetConnection *pConnection ) { mNetState.addConnection( pConnection ); }; + inline void clearConnection( NetConnection *pConnection ) { mNetState.clearConnection( pConnection ); }; + + // Enum Methods. + + static eOrientationType getOrientationTypeEnum( const char *pLabel ); + static StringTableEntry getOrientationTypeLabel( const eOrientationType &pType ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathNode::eOrientationType VPathNodeOrientationType; + +// Declare Enum Types. +DefineEnumType( VPathNodeOrientationType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHNODE_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathObject.cpp b/Engine/modules/Verve/VPath/VPathObject.cpp new file mode 100644 index 000000000..5d1116b78 --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathObject.cpp @@ -0,0 +1,731 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathObject.h" +#include "VPath.h" + +#include "core/stream/bitStream.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathObject::k_OrientationTypeSize ) ); + +//----------------------------------------------------------------------------- + +VPathObject::VPathObject( void ) : + mActive( false ), + mLastTime( 0 ), + mLastDelta( 0.f ), + mObject( NULL ), + mTimeInterp( 0.f ), + mPathInterp( 0.f ), + mPosition( 0.f, 0.f, 0.f ), + mOffset( 0.f, 0.f, 0.f ), + mOrientation( 0.f, 1.f, 0.f ), + mForward( true ), + mSpeed( 10.f ), + mSourceNode( 0 ), + mDestinationNode( 0 ), + mStartNode( 0 ), + mEndNode( 0 ) +{ + // Init. + mOrientationMode.Type = k_OrientationToPath; + mOrientationMode.Object = NULL; + mOrientationMode.Point = Point3F::Zero; + + // Set the initial mask. + mNetState.setMaskBits( k_StateInit ); + + // Reset Time. + resetTime(); + + // Reset Delta. + resetDelta(); + + VECTOR_SET_ASSOCIATION( mNetState ); +} + +VPathObject::~VPathObject( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Network Methods. +// +//----------------------------------------------------------------------------- + +U32 VPathObject::packUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Init Return Mask. + U32 retMask = 0; + + // Fetch State. + VNetStateInfo *state = getState( pConnection ); + + // Write Active. + pStream->writeFlag( mActive ); + + // Send Object Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateObject ) ) + { + // Successful Send? + bool success = false; + + // Valid Object? + if ( !mObject ) + { + // No Object. + pStream->writeFlag( false ); + } + else + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mObject ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + // Write Ghost Id. + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + + // Success! + success = true; + // Clear Update. + state->Mask &= ~k_StateUpdateObject; + } + } + + if ( !success ) + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Send Mount Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateMount ) ) + { + // Successful Send? + bool success = false; + + // Valid Objects? + if ( !mObject || !mObject->getObjectMount() || ( state->Mask & k_StateUpdateObject ) ) + { + // No Object. + pStream->writeFlag( false ); + } + else + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mObject->getObjectMount() ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + // Write Ghost Id. + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + // Write Mount Node. + pStream->writeInt( mObject->getMountNode(), SceneObject::NumMountPointBits ); + + // Success! + success = true; + // Clear Update. + state->Mask &= ~k_StateUpdateMount; + } + } + + if ( !success ) + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Send Position Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) + { + // Write Position. + pStream->write( mTimeInterp ); + pStream->write( mPathInterp ); + + pStream->write( mPosition.x ); + pStream->write( mPosition.y ); + pStream->write( mPosition.z ); + + pStream->write( mOrientation.x ); + pStream->write( mOrientation.y ); + pStream->write( mOrientation.z ); + + pStream->writeInt( mSourceNode, VPath::gMaxNodeBits ); + pStream->writeInt( mDestinationNode, VPath::gMaxNodeBits ); + + // Clear Update. + state->Mask &= ~k_StateUpdatePosition; + } + + // Send State Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateState ) ) + { + // Successful Send? + bool success = true; + + // Write State. + pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToObject : + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mOrientationMode.Object ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + } + else + { + // Failed. + success = false; + } + + } break; + + case k_OrientationToPoint : + { + // Write Point. + pStream->write( mOrientationMode.Point.x ); + pStream->write( mOrientationMode.Point.y ); + pStream->write( mOrientationMode.Point.z ); + + } break; + } + + pStream->writeFlag( mForward ); + pStream->write( mSpeed ); + + // Write Offset. + pStream->write( mOffset.x ); + pStream->write( mOffset.y ); + pStream->write( mOffset.z ); + + pStream->writeInt( mStartNode, VPath::gMaxNodeBits ); + pStream->writeInt( mEndNode, VPath::gMaxNodeBits ); + + if ( success ) + { + // Clear Update. + state->Mask &= ~k_StateUpdateState; + } + else + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Return Mask. + return retMask; +} + +void VPathObject::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Read Active. + setActive( pStream->readFlag() ); + + // Update Object? + if ( pStream->readFlag() ) + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + + // Resolve Object. + setObject( static_cast( pConnection->resolveGhost( ghostIndex ) ) ); + + // Reset Delta. + resetDelta(); + } + else + { + // Clear Object. + mObject = NULL; + } + } + + // Update Mount? + if ( pStream->readFlag() ) + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + // Read Mount Node. + const S32 nodeIndex = pStream->readInt( SceneObject::NumMountPointBits ); + + // Resolve Object. + SceneObject *mountObject = static_cast( pConnection->resolveGhost( ghostIndex ) ); + // Mount Object. + mountObject->mountObject( mObject, nodeIndex ); + } + else + { + // ... unmount? + } + } + + // Update Position? + if ( pStream->readFlag() ) + { + // Read Updates. + pStream->read( &mTimeInterp ); + pStream->read( &mPathInterp ); + + pStream->read( &mPosition.x ); + pStream->read( &mPosition.y ); + pStream->read( &mPosition.z ); + + pStream->read( &mOrientation.x ); + pStream->read( &mOrientation.y ); + pStream->read( &mOrientation.z ); + + mSourceNode = pStream->readInt( VPath::gMaxNodeBits ); + mDestinationNode = pStream->readInt( VPath::gMaxNodeBits ); + } + + // Update Heading? + if ( pStream->readFlag() ) + { + // Read Orientation Mode. + mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case VPathObject::k_OrientationToObject : + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + // Resolve Object. + mOrientationMode.Object = static_cast( pConnection->resolveGhost( ghostIndex ) ); + } + + } break; + + case VPathObject::k_OrientationToPoint : + { + // Read Point. + pStream->read( &mOrientationMode.Point.x ); + pStream->read( &mOrientationMode.Point.y ); + pStream->read( &mOrientationMode.Point.z ); + + } break; + } + + // Read Updates. + mForward = pStream->readFlag(); + + pStream->read( &mSpeed ); + + pStream->read( &mOffset.x ); + pStream->read( &mOffset.y ); + pStream->read( &mOffset.z ); + + mStartNode = pStream->readInt( VPath::gMaxNodeBits ); + mEndNode = pStream->readInt( VPath::gMaxNodeBits ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +Point3F VPathObject::getWorldPosition( void ) +{ + return ( mPosition + mOffset ); +} + +Point3F VPathObject::getRenderWorldPosition( const F32 &pDelta ) +{ + return ( getPositionDelta( pDelta ) + mOffset ); +} + +MatrixF VPathObject::getTransform( void ) +{ + MatrixF mat( true ); + switch ( mOrientationMode.Type ) + { + case k_OrientationInterpolate : + case k_OrientationToObject : + case k_OrientationToPoint : + case k_OrientationToPath : + { + // Y-Axis. + VectorF yVec = mOrientation; + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + mat.setColumn( 3, getWorldPosition() ); + + } break; + + case k_OrientationFree : + { + // Fetch Current Transform. + mat = mObject->getTransform(); + mat.setPosition( getWorldPosition() ); + + } break; + } + + // Return. + return mat; +} + +MatrixF VPathObject::getRenderTransform( const F32 &pDelta ) +{ + MatrixF mat( true ); + switch ( mOrientationMode.Type ) + { + case k_OrientationInterpolate : + case k_OrientationToObject : + case k_OrientationToPoint : + case k_OrientationToPath : + { + // Y-Axis. + VectorF yVec = getOrientationDelta( pDelta ); + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + mat.setColumn( 3, getRenderWorldPosition( pDelta ) ); + + } break; + + case k_OrientationFree : + { + // Fetch Current Transform. + mat = mObject->getRenderTransform(); + mat.setPosition( getRenderWorldPosition( pDelta ) ); + + } break; + } + + // Return. + return mat; +} + +void VPathObject::setActive( const bool &pActive ) +{ + // Update? + if ( pActive != mActive ) + { + // Apply. + mActive = pActive; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setObject( SceneObject *pObject ) +{ + // Update? + if ( pObject != mObject ) + { + // Apply. + mObject = pObject; + // Flag Update. + setMaskBits( k_StateUpdateObject ); + } +} + +void VPathObject::setTimeInterp( const F32 &pInterp ) +{ + // Update? + if ( mTimeInterp != pInterp ) + { + // Apply. + mTimeInterp = pInterp; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setPathInterp( const F32 &pInterp ) +{ + // Update? + if ( mPathInterp != pInterp ) + { + // Apply. + mPathInterp = pInterp; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setPosition( const Point3F &pPosition ) +{ + // Update? + if ( mPosition != pPosition ) + { + // Update. + mPosition = pPosition; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setOffset( const Point3F &pOffset ) +{ + // Update? + if ( mOffset != pOffset ) + { + // Update. + mOffset = pOffset; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientation( const VectorF &pOrientation ) +{ + // Update? + if ( mOrientation != pOrientation ) + { + // Update. + mOrientation = pOrientation; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType ) +{ + // Update? + if ( mOrientationMode.Type != pType ) + { + // Update. + mOrientationMode.Type = pType; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType, SceneObject *pObject ) +{ + AssertFatal( ( pType == k_OrientationToObject ) && ( pObject != NULL ), "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Object != pObject ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Object = pObject; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) +{ + AssertFatal( pType == k_OrientationToPoint, "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Point = pPoint; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setForward( const bool &pForward ) +{ + // Update? + if ( mForward != pForward ) + { + // Update. + mForward = pForward; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setSpeed( const F32 &pSpeed ) +{ + // Update? + if ( mSpeed != pSpeed ) + { + // Update. + mSpeed = pSpeed; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setNode( const S32 &pSourceNodeIndex, const S32 &pDestinationNodeIndex ) +{ + // Update? + if ( ( mSourceNode != pSourceNodeIndex ) || ( mDestinationNode != pDestinationNodeIndex ) ) + { + // Update. + mSourceNode = pSourceNodeIndex; + mDestinationNode = pDestinationNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setStartNode( const S32 &pNodeIndex ) +{ + // Update? + if ( mStartNode != pNodeIndex ) + { + // Update. + mStartNode = pNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setEndNode( const S32 &pNodeIndex ) +{ + // Update? + if ( mEndNode != pNodeIndex ) + { + // Update. + mEndNode = pNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +//----------------------------------------------------------------------------- +// +// Delta Methods. +// +//----------------------------------------------------------------------------- + +void VPathObject::resetDelta( void ) +{ + mDelta.Position[0] = mPosition; + mDelta.Position[1] = mPosition; + mDelta.Orientation[0] = mOrientation; + mDelta.Orientation[1] = mOrientation; +} + +void VPathObject::resetDelta( const Point3F &pPosition, const VectorF &pOrientation ) +{ + mDelta.Position[0] = pPosition; + mDelta.Position[1] = pPosition; + mDelta.Orientation[0] = pOrientation; + mDelta.Orientation[1] = pOrientation; +} + +void VPathObject::popDelta( void ) +{ + mDelta.Position[0] = mDelta.Position[1]; + mDelta.Orientation[0] = mDelta.Orientation[1]; +} + +void VPathObject::pushDelta( const Point3F &pPosition, const VectorF &pOrientation ) +{ + mDelta.Position[1] = pPosition; + mDelta.Orientation[1] = pOrientation; +} + +Point3F VPathObject::getPositionDelta( const F32 &pInterp ) +{ + Point3F interpPosition; + interpPosition.interpolate( mDelta.Position[1], mDelta.Position[0], pInterp ); + + return interpPosition; +} + +VectorF VPathObject::getOrientationDelta( const F32 &pInterp ) +{ + VectorF interpOrientation; + interpOrientation.interpolate( mDelta.Orientation[1], mDelta.Orientation[0], pInterp ); + interpOrientation.normalize(); + + return interpOrientation; +} + +//----------------------------------------------------------------------------- +// +// Enumeration Methods. +// +//----------------------------------------------------------------------------- + +// Implement the Orientation Type enum list. +ImplementEnumType( VPathObjectOrientationType, "" ) + { VPathObject::k_OrientationFree, "FREE" }, + { VPathObject::k_OrientationInterpolate, "INTERPOLATE" }, + { VPathObject::k_OrientationToPath, "TOPATH" }, + { VPathObject::k_OrientationToObject, "TOOBJECT" }, + { VPathObject::k_OrientationToPoint, "TOPOINT" }, +EndImplementEnumType; + +VPathObject::eOrientationType VPathObject::getOrientationTypeEnum( const char *pLabel ) +{ + VPathObject::eOrientationType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPathObject::k_OrientationFree; + } + + // Return. + return out; +} + +StringTableEntry VPathObject::getOrientationTypeLabel( const eOrientationType &pType ) +{ + // Return. + return castConsoleTypeToString( pType ); +} \ No newline at end of file diff --git a/Engine/modules/Verve/VPath/VPathObject.h b/Engine/modules/Verve/VPath/VPathObject.h new file mode 100644 index 000000000..72153021d --- /dev/null +++ b/Engine/modules/Verve/VPath/VPathObject.h @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHOBJECT_H_ +#define _VT_VPATHOBJECT_H_ + +#ifndef _GAMEBASE_H_ +#include "T3D/gameBase/gameBase.h" +#endif + +#ifndef _VNETSTATE_H_ +#include "VNetState.h" +#endif + +#ifndef _MOVEMANAGER_H_ +#include "T3D/gameBase/moveManager.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; +class NetConnection; + +struct VPathObject +{ +public: + + enum eState + { + k_StateUpdateObject = BIT( 0 ), + k_StateUpdateMount = BIT( 1 ), + k_StateUpdatePosition = BIT( 2 ), + k_StateUpdateState = BIT( 3 ), + + k_StateAttach = BIT( 4 ), + k_StateDetach = BIT( 5 ), + + k_StateUpdate = ( k_StateUpdateObject | k_StateUpdateMount | k_StateUpdatePosition | k_StateUpdateState ), + + k_StateInit = ( k_StateAttach | k_StateUpdate ), + }; + + enum eOrientationType + { + k_OrientationFree, + k_OrientationInterpolate, + + k_OrientationToPath, + k_OrientationToObject, + k_OrientationToPoint, + + k_OrientationTypeSize, + }; + + struct sOrientation + { + eOrientationType Type; + + // k_OrientationToObject + SceneObject *Object; + // k_OrientationToPoint + Point3F Point; + }; + + struct sDelta + { + Point3F Position[2]; + VectorF Orientation[2]; + }; + +protected: + + bool mActive; + + U32 mLastTime; + F32 mLastDelta; + + SceneObject *mObject; + + VNetState mNetState; + sDelta mDelta; + + F32 mTimeInterp; + F32 mPathInterp; + Point3F mPosition; + Point3F mOffset; + sOrientation mOrientationMode; + VectorF mOrientation; + bool mForward; + F32 mSpeed; + + S32 mSourceNode; + S32 mDestinationNode; + + S32 mStartNode; + S32 mEndNode; + +public: + + VPathObject( void ); + ~VPathObject( void ); + + // Network Methods. + + U32 packUpdate( NetConnection *pConnection, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline const bool &isActive( void ) { return mActive; }; + + inline SceneObject *getObject( void ) { return mObject; }; + + inline const F32 &getTimeInterp( void ) { return mTimeInterp; }; + inline const F32 &getPathInterp( void ) { return mPathInterp; }; + inline const Point3F &getPosition( void ) { return mPosition; }; + inline const Point3F &getOffset( void ) { return mOffset; }; + inline const VectorF &getOrientation( void ) { return mOrientation; }; + inline const sOrientation &getOrientationMode( void ) { return mOrientationMode; }; + + inline const bool &isForward( void ) { return mForward; }; + inline const F32 &getSpeed( void ) { return mSpeed; }; + + inline const S32 &getSourceNode( void ) { return mSourceNode; }; + inline const S32 &getDestinationNode( void ) { return mDestinationNode; }; + inline const S32 &getStartNode( void ) { return mStartNode; }; + inline const S32 &getEndNode( void ) { return mEndNode; }; + + Point3F getWorldPosition( void ); + Point3F getRenderWorldPosition( const F32 &pDelta ); + + MatrixF getTransform( void ); + MatrixF getRenderTransform( const F32 &pDelta ); + + inline F32 getTimeDelta( const bool &pUpdate = true ) + { + if ( !pUpdate ) + { + return mLastDelta; + } + + // Calculate Delta. + const S32 time = Sim::getCurrentTime(); + const F32 delta = ( time - mLastTime ) / 1000.f; + + // Store Time. + mLastTime = time; + mLastDelta = delta; + + // Return Delta. + return delta; + }; + + inline void resetTime( void ) + { + mLastTime = Sim::getCurrentTime(); + }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + void setActive( const bool &pActive ); + + void setObject( SceneObject *pObject ); + + void setTimeInterp( const F32 &pInterp ); + void setPathInterp( const F32 &pInterp ); + void setPosition( const Point3F &pPosition ); + void setOffset( const Point3F &pOffset ); + void setOrientation( const VectorF &pOrientation ); + void setOrientationMode( const eOrientationType &pType ); + void setOrientationMode( const eOrientationType &pType, SceneObject *pObject ); + void setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ); + + void setForward( const bool &pForward ); + void setSpeed( const F32 &pSpeed ); + + void setNode( const S32 &pSourceNodeIndex, const S32 &pDestinationNodeIndex ); + void setStartNode( const S32 &pNodeIndex ); + void setEndNode( const S32 &pNodeIndex ); + + // Delta Methods. + + void resetDelta( void ); + void resetDelta( const Point3F &pPosition, const VectorF &pOrientation ); + + void popDelta( void ); + void pushDelta( const Point3F &pPosition, const VectorF &pOrientation ); + + Point3F getPositionDelta( const F32 &pInterp ); + VectorF getOrientationDelta( const F32 &pInterp ); + + // Net State Methods. + + inline VNetStateInfo *getState( NetConnection *pConnection ) { return mNetState.getState( pConnection ); }; + + inline void setMaskBits( const U32 &pMask ) { mNetState.setMaskBits( pMask ); }; + inline void clearMaskBits( const U32 &pMask ) { mNetState.clearMaskBits( pMask ); }; + + inline bool isConnection( NetConnection *pConnection ) { return mNetState.isConnection( pConnection ); }; + inline void addConnection( NetConnection *pConnection ) { mNetState.addConnection( pConnection ); }; + inline void clearConnection( NetConnection *pConnection ) { mNetState.clearConnection( pConnection ); }; + + // Enum Methods. + + static eOrientationType getOrientationTypeEnum( const char *pLabel ); + static StringTableEntry getOrientationTypeLabel( const eOrientationType &pType ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathObject::eOrientationType VPathObjectOrientationType; + +// Declare Enum Types. +DefineEnumType( VPathObjectOrientationType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHOBJECT_H_ \ No newline at end of file diff --git a/Engine/modules/Verve/VerveConfig.h b/Engine/modules/Verve/VerveConfig.h new file mode 100644 index 000000000..deaf8f831 --- /dev/null +++ b/Engine/modules/Verve/VerveConfig.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VERVECONFIG_H_ +#define _VT_VERVECONFIG_H_ + +//----------------------------------------------------------------------------- + +//#define VT_EDITOR + +//----------------------------------------------------------------------------- + +#endif // _VT_VERVECONFIG_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/ITreeNode.h b/Engine/source/Verve/Core/ITreeNode.h new file mode 100644 index 000000000..943dd554d --- /dev/null +++ b/Engine/source/Verve/Core/ITreeNode.h @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_ITREENODE_H_ +#define _VT_ITREENODE_H_ + +//----------------------------------------------------------------------------- + +class ITreeNode +{ +public: + + ITreeNode *mParentNode; + ITreeNode *mChildNode; + + ITreeNode *mSiblingPrevNode; + ITreeNode *mSiblingNextNode; + +public: + + ITreeNode( void ) : + mParentNode( 0 ), + mChildNode( 0 ), + mSiblingPrevNode( 0 ), + mSiblingNextNode( 0 ) + { + // Void. + }; + + virtual ~ITreeNode( void ) + { + // Void. + }; + + virtual void clear( void ) = 0; // Clear the Node. + + virtual ITreeNode *getRoot( void ) = 0; // Get Root Node. + virtual ITreeNode *getParent( void ) = 0; // Get Parent Node. + virtual ITreeNode *getChild( void ) = 0; // Get Child Node. + virtual ITreeNode *getLastChild( void ) = 0; // Get Last Child Node. + + virtual ITreeNode *getPrevSibling( void ) = 0; // Get Previous Sibling Node. + virtual ITreeNode *getNextSibling( void ) = 0; // Get Next Sibling Node. + + virtual void addTo( ITreeNode *pNode ) = 0; // Add Node to target node. + virtual void remove( void ) = 0; // Remove this Node from the tree. + virtual void moveTo( ITreeNode* node ) = 0; // Move to specified Node. + + virtual void onAttach( void ) = 0; // Attach Callback. + virtual void onDetach( void ) = 0; // Detach Callback. + + virtual bool inTree( void ) = 0; // Is Node in a tree? +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_ITREENODE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/Persistence/VPersistence.cpp b/Engine/source/Verve/Core/Persistence/VPersistence.cpp new file mode 100644 index 000000000..daf3336a9 --- /dev/null +++ b/Engine/source/Verve/Core/Persistence/VPersistence.cpp @@ -0,0 +1,137 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/Persistence/VPersistence.h" + +#include "Verve/Core/VController.h" +#include "Verve/Core/VObject.h" + +namespace VPersistence +{ + //----------------------------------------------------------------------------- + // + // VController + // + //----------------------------------------------------------------------------- + + template <> + bool write( TiXmlElement *pElement, VController *pObject ) + { + // Write Properties. + if ( !writeProperties( pElement, pObject ) ) + { + return false; + } + + // Write Data Table. + if ( !pObject->writeDataTable( pElement ) ) + { + return false; + } + + // Write Objects. + return writeObjects( pElement, pObject ); + } + + template <> + bool read( TiXmlElement *pElement, VController *pObject ) + { + // Read Properties. + if ( !readProperties( pElement, pObject ) ) + { + // Invalid Properties. + return false; + } + + // Read Data Table. + if ( !pObject->readDataTable( pElement ) ) + { + // Invalid Data Table. + return false; + } + + // Read Objects. + if ( !readObjects( pElement, pObject ) ) + { + // Invalid Read. + return false; + } + + // Valid Read. + return true; + } + + //----------------------------------------------------------------------------- + // + // VObject + // + //----------------------------------------------------------------------------- + + template <> + bool write( TiXmlElement *pElement, VObject *pObject ) + { + // Create Element. + TiXmlElement *objectElement = new TiXmlElement( "VObject" ); + pElement->LinkEndChild( objectElement ); + + // Attributes. + objectElement->SetAttribute( "Type", pObject->getClassName() ); + + // Write Properties. + if ( !writeProperties( objectElement, pObject ) ) + { + return false; + } + + // Write Objects. + return writeObjects( objectElement, pObject ); + } + + template <> + bool read( TiXmlElement *pElement, VObject *pObject ) + { + // Read Properties. + if ( !readProperties( pElement, pObject ) ) + { + // Invalid Properties. + return false; + } + + // Set Name Unique. + pObject->setLabelUnique( pObject->getLabel() ); + + // Read Objects. + if ( !readObjects( pElement, pObject ) ) + { + // Invalid Objects. + return false; + } + +#ifdef VT_EDITOR + // Callback. + Con::executef( pObject, "onRead" ); +#endif + + // Valid Read. + return true; + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Core/Persistence/VPersistence.h b/Engine/source/Verve/Core/Persistence/VPersistence.h new file mode 100644 index 000000000..6c357681d --- /dev/null +++ b/Engine/source/Verve/Core/Persistence/VPersistence.h @@ -0,0 +1,286 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPERSISTENCE_H_ +#define _VT_VPERSISTENCE_H_ + +#ifndef TINYXML_INCLUDED +#include "tinyxml/tinyxml.h" +#endif + +#ifndef _SIMOBJECT_H_ +#include "console/simObject.h" +#endif + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- + +namespace VPersistence +{ + static const char *VSFVersionString = "0.0.0a"; + + // This object is used to filter fields which belong to SimObject's. + // There is no need to serialize these fields, so they are skipped + // entirely. + static SimObject DummySimObject; + + //------------------------------------------------------------------------- + + template bool writeFile( const char* pFileName, T *pObject ) + { + // Create Doc. + TiXmlDocument xmlDocument; + TiXmlDeclaration *xmlDeclaration = new TiXmlDeclaration( "1.0", "", "" ); + xmlDocument.LinkEndChild( xmlDeclaration ); + + // Create Root. + TiXmlElement *xmlRoot = new TiXmlElement( "VerveControllerSequence" ); + xmlDocument.LinkEndChild( xmlRoot ); + + // Write Version. + xmlRoot->SetAttribute( "Version", VSFVersionString ); + + // Write Object. + if ( !write( xmlRoot, pObject ) ) + { + Con::errorf( "VPersistence::writeFile() - Unable to Write Object." ); + return false; + } + + // Save File. + return xmlDocument.SaveFile( pFileName ); + }; + + template bool write( TiXmlElement *pElement, T *pObject ); + + template bool writeProperties( TiXmlElement *pElement, T *pObject ) + { + const AbstractClassRep::FieldList &fieldList = pObject->getFieldList(); + const AbstractClassRep::Field *field = NULL; + + // Create Property Root. + TiXmlElement *propertyRoot = new TiXmlElement( "Properties" ); + pElement->LinkEndChild( propertyRoot ); + + const S32 fieldCount = fieldList.size(); + for ( S32 i = 0; i < fieldCount; i++ ) + { + field = &fieldList[i]; + + if ( field->type >= AbstractClassRep::ARCFirstCustomField ) + { + // Ignore Special Fields. + continue; + } + + // Fetch the Field Name. + const char *fieldName = field->pFieldname; + // SimObject Field? + if ( DummySimObject.findField( fieldName ) != NULL ) + { + // Skip SimObject Fields. + continue; + } + + // Fetch the Field Value. + const char *fieldValue = ( *field->getDataFn )( pObject, Con::getData( field->type, ( void * ) ( ( ( const char * )pObject ) + field->offset ), 0, field->table, field->flag ) ); + + if ( fieldValue ) + { + // Create Element. + TiXmlElement *propertyElement = new TiXmlElement( fieldName ); + + // Apply Value. + propertyElement->InsertEndChild( TiXmlText( fieldValue ) ); + + // Add. + propertyRoot->LinkEndChild( propertyElement ); + } + } + + // Valid Write. + return true; + }; + + template bool writeObjects( TiXmlElement *pElement, T *pObject ) + { + for ( ITreeNode *node = pObject->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + // Write Group. + if ( !write( pElement, ( VObject* )node ) ) + { + // Invalid Write. + return false; + } + } + + // Valid Write. + return true; + } + + //------------------------------------------------------------------------- + + template bool readFile( const char* pFileName, T *pObject ) + { + TiXmlDocument xmlDocument; + if ( !xmlDocument.LoadFile( pFileName ) ) + { + Con::errorf( "VPersistence::readFile() - Unable to load file '%s'.", pFileName ); + return false; + } + + TiXmlElement *rootElement = xmlDocument.RootElement(); + if ( !rootElement ) + { + Con::errorf( "VPersistence::readFile() - Invalid Document '%s'.", pFileName ); + return false; + } + + const char *docVersion = rootElement->Attribute( "Version" ); + if ( !docVersion || dStrcmp( VSFVersionString, docVersion ) != 0 ) + { + Con::errorf( "VPersistence::readFile() - Invalid file version." ); + return false; + } + + // Read Object. + if ( !read( rootElement, pObject ) ) + { + // Invalid Read. + return false; + } + + // Valid. + return true; + }; + + template bool read( TiXmlElement *pElement, T *pObject ); + + template bool readProperties( TiXmlElement *pElement, T *pObject ) + { + TiXmlElement *propertyRoot = pElement->FirstChildElement( "Properties" ); + if ( propertyRoot ) + { + for ( TiXmlElement *child = propertyRoot->FirstChildElement(); child != NULL; child = child->NextSiblingElement() ) + { + // Get Field Data. + const char *fieldName = child->Value(); + const char *fieldValue = child->GetText(); + + if ( !fieldValue ) + { + // Clear Value. + pObject->setField( fieldName, "" ); + } + else + { + // Apply Field Value. + if ( !pObject->setField( fieldName, fieldValue ) ) + { + // Invalid. + Con::warnf( "VPersistence::readProperties() - Invalid property '%s'", fieldName ); + } + } + } + } + + // Valid Read. + return true; + }; + + template bool readObjects( TiXmlElement *pElement, T *pObject ) + { + for ( TiXmlElement *child = pElement->FirstChildElement( "VObject" ); child != NULL; child = child->NextSiblingElement( "VObject" ) ) + { + // Get Object Type. + const char *type = child->Attribute( "Type" ); + if ( !type || !AbstractClassRep::findClassRep( type ) ) + { + // Invalid Type. + Con::errorf( "VController::readObjects() - Invalid object type specified '%s'.", ( ( type ) ? type : "NULL" ) ); + + // Invalid Read. + return false; + } + + // Create Object. + VObject *object = dynamic_cast( ConsoleObject::create( type ) ); + +#ifdef VT_EDITOR + // Register SimObject. + if ( !object->registerObject() ) + { + // Delete. + delete object; + + // Invalid Read. + return false; + } +#endif + + // Add Reference. + object->addTo( pObject ); + +#ifdef VT_EDITOR + // Valid Method? + if ( object->isMethod( "onAdd" ) ) + { + // Callback. + const char *retValue = Con::executef( object, "onAdd" ); + if ( !dAtob( retValue ) ) + { + // Delete. + object->deleteObject(); + + // Invalid Read. + return false; + } + } +#endif + + // Read Object. + if ( !read( child, object ) ) + { +#ifdef VT_EDITOR + // Delete. + object->deleteObject(); +#else + // Delete. + delete object; +#endif + + // Invalid Read. + return false; + } + } + + // Valid Read. + return true; + }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPERSISTENCE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/Util/VSharedEnum.cpp b/Engine/source/Verve/Core/Util/VSharedEnum.cpp new file mode 100644 index 000000000..b4825de3f --- /dev/null +++ b/Engine/source/Verve/Core/Util/VSharedEnum.cpp @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VSharedEnum.h" + +//----------------------------------------------------------------------------- + +// Implement the Action enum list. +ImplementEnumType( VActionToggle, "" ) + { VSharedEnum::k_ActionTurnOn, "ON" }, + { VSharedEnum::k_ActionTurnOff, "OFF" }, +EndImplementEnumType; \ No newline at end of file diff --git a/Engine/source/Verve/Core/Util/VSharedEnum.h b/Engine/source/Verve/Core/Util/VSharedEnum.h new file mode 100644 index 000000000..73df682d8 --- /dev/null +++ b/Engine/source/Verve/Core/Util/VSharedEnum.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAREDENUM_H_ +#define _VT_VSHAREDENUM_H_ + +#ifndef _DYNAMIC_CONSOLETYPES_H_ +#include "console/dynamicTypes.h" +#endif + +namespace VSharedEnum +{ + enum eActionToggle + { + k_ActionTurnOn, + k_ActionTurnOff, + }; +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VSharedEnum::eActionToggle VActionToggle; + +// Declare Enum Types. +DefineEnumType( VActionToggle ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAREDENUM_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VController.cpp b/Engine/source/Verve/Core/VController.cpp new file mode 100644 index 000000000..d9c9daafd --- /dev/null +++ b/Engine/source/Verve/Core/VController.cpp @@ -0,0 +1,1160 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Core/VObject.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "Verve/Extension/Director/VDirectorGroup.h" + +#include "console/consoleObject.h" +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VController ); +//----------------------------------------------------------------------------- + +VController::VController( void ) : + mStatus( ( k_StatusInit | k_StatusStopped ) ), + mTime( 0 ), + mLastTime( 0 ), + mTimeScale( 1.f ), + mDuration( 5000 ), + mLoop( false ), + mLoopBackwards( false ), + mLoopCount( -1 ), + mLoopIndex( 0 ), + mLoopDelay( 0 ), + mLoopDelayTime( 0 ), + mJump( k_JumpInvalid ), + mJumpTime( 0 ), + mResetOnCompletion( true ) +{ + // Don't Process Ticks. + setProcessTicks( false ); +} + +VController::~VController( void ) +{ + // Void. +} + +void VController::initPersistFields( void ) +{ + addGroup( "Controller" ); + addProtectedField( "Time", TypeS32, Offset( mTime, VController ), &setTime, &defaultProtectedGetFn, "Current position of the Controller (in milliseconds)." ); + addProtectedField( "Duration", TypeS32, Offset( mDuration, VController ), &setDuration, &defaultProtectedGetFn, "Total length of the sequence (in milliseconds)." ); + addProtectedField( "TimeScale", TypeF32, Offset( mTimeScale, VController ), &setTimeScale, &defaultProtectedGetFn, "Speed of playback. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards. If |TimeScale| > 1.0, then playback will be faster than normal, while |TimeScale| < 1.0 will be slower." ); + + addField( "Loop", TypeBool, Offset( mLoop, VController ), "Instead of stopping once playback is complete, the Controller will reset and resume play." ); + addField( "LoopBackwards", TypeBool, Offset( mLoopBackwards, VController ), "When the sequence loops, reverse the direction of play." ); + addField( "LoopCount", TypeS32, Offset( mLoopCount, VController ), "The number of times the sequence loops before stopping. -1 will cause the sequence to loop indefinitely." ); + addField( "LoopDelay", TypeS32, Offset( mLoopDelay, VController ), "When the sequence loops, delay playback by this value (in milliseconds)." ); + + addField( "ResetOnCompletion", TypeBool, Offset( mResetOnCompletion, VController ), "When the sequence is completed, reset the state of the Controller." ); + endGroup( "Controller" ); + + // Parent Call. + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// ITickable Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::processTick(); +// +// This method controls the playback of the entire sequence. It integrates all +// of the groups and handles sequence looping and jumping. +// +//----------------------------------------------------------------------------- +void VController::processTick( void ) +{ + if ( mTimeScale == 0.f ) + { + // Pause. + pause(); + + // Exit. + return; + } + + // Calculate Delta. + const S32 time = Sim::getCurrentTime(); + S32 delta = ( time - mLastTime ); + mLastTime = time; + + // Reverse? + if ( mTimeScale < 0.f ) + { + // Negative Delta. + delta *= -1; + } + + if ( mLoopDelayTime > 0 ) + { + // Update Delay Time. + mLoopDelayTime -= getMin( mAbs( delta ), mLoopDelayTime ); + + // Exit. + return; + } + + // Jump Delta? + if ( mJump == k_JumpDelta ) + { + // Jump. + delta = mJumpTime; + + // Clear. + mJump = k_JumpInvalid; + mJumpTime = 0; + } + + if ( ( isPlayingForward() && ( mTime + delta ) > mDuration ) + || ( !isPlayingForward() && ( mTime + delta ) < 0 ) ) + { + // Clamp Delta. + delta = ( ( mTimeScale > 0.f ) * mDuration ) - mTime; + + // Note: If we are playing forwards, we're at the end of the + // sequence and we want to loop/reset the Controller, then we + // need to handle that now. + if ( delta == 0 ) + { + onPostTick(); + } + } + + // Valid Delta? + if ( delta == 0 ) + { + // Exit. + return; + } + + // Trigger Update. + mControllerUpdateSignal.trigger( mTime, delta ); + + // Update Time. + mTime += delta; + + // Perform Post Tick. + onPostTick(); +} + +//----------------------------------------------------------------------------- +// +// VController::onPostTick(); +// +// This method is called onces a tick has been processed. It will perform the +// the right checks to see if the Controller has finished playing. It also +// handles special cases like Looping or Resetting the Controller. +// +//----------------------------------------------------------------------------- +void VController::onPostTick( void ) +{ + // Jump Time? + if ( mJump == k_JumpTime ) + { + // Jump Post Update. + reset( mJumpTime ); + + // Clear. + mJump = k_JumpInvalid; + mJumpTime = 0; + } + + // Sequence Completed? + if ( isPlayingForward() && mTime >= mDuration + || !isPlayingForward() && mTime <= 0 ) + { + bool stopPlaying = true; + if ( mLoop ) + { + // Don't Stop. + stopPlaying = false; + + if ( mLoopBackwards ) + { + // Change Direction. + setTimeScale( -1.f * mTimeScale ); + } + else + { + // Reset Time. + reset(); + } + + if ( mLoopDelay > 0 ) + { + // Resume After Delay. + mLoopDelayTime = mLoopDelay; + } + + // At the Start of the Sequence? + if ( mTime <= 0 && mLoopCount >= 0 ) + { + // Stop Looping? + stopPlaying = ( ++mLoopIndex >= mLoopCount ); + } + + // Callback. + Con::executef( this, "onLoop" ); + + // Loop Signal. + postEvent( k_EventLoop ); + } + + // Stop? + if ( stopPlaying ) + { + // Stop Only. + stop( mResetOnCompletion ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::reset(); +// +// Reset the Controller to the start of the sequence. +// +//----------------------------------------------------------------------------- +void VController::reset( void ) +{ + // Reset. + reset( ( isPlayingForward() ) ? 0 : mDuration ); +} + +//----------------------------------------------------------------------------- +// +// VController::reset( pTime ); +// +// Reset the Controller to the target time. This is a very important method as +// it allows tracks and events to reset their state as well as prepare +// themselves for playback. +// +//----------------------------------------------------------------------------- +void VController::reset( const S32 &pTime ) +{ + // Reset Time. + mTime = pTime; + mLastTime = Sim::getCurrentTime(); + + // Reset Delay Time. + mLoopDelayTime = 0; + + // Post Event. + postEvent( k_EventReset ); +} + +//----------------------------------------------------------------------------- +// +// VController::play(); +// +// Start playing the sequence from the current time and execute a number of +// callbacks. +// +//----------------------------------------------------------------------------- +void VController::play( void ) +{ + if ( isPlaying() || mTime < 0 || mTime > mDuration ) + { + // Sanity! + return; + } + + // Reset Time. + mLastTime = Sim::getCurrentTime(); + + // Start Updating. + setProcessTicks( true ); + + if ( mStatus & k_StatusInit ) + { + // Init Signal. + postEvent( k_EventInit ); + + // Clear Init Status. + mStatus &= ~k_StatusInit; + } + + // Update Status. + updateStatus( k_StatusPlaying ); + + // Play Signal. + postEvent( k_EventPlay ); + + // Callback. + Con::executef( this, "onPlay" ); +} + +//----------------------------------------------------------------------------- +// +// VController::play( pTime ); +// +// Start playing the sequence from the desired time. +// +//----------------------------------------------------------------------------- +void VController::play( const S32 &pTime ) +{ + // Reset. + reset( pTime ); + + // Play. + play(); +} + +//----------------------------------------------------------------------------- +// +// VController::pause(); +// +// Cease playback of the sequence, but maintain the current time. +// +//----------------------------------------------------------------------------- +void VController::pause( void ) +{ + // Stop Updating. + setProcessTicks( false ); + + // Update Status. + updateStatus( k_StatusPaused ); + + // Pause Signal. + postEvent( k_EventPause ); + + // Callback. + Con::executef( this, "onPause" ); +} + +//----------------------------------------------------------------------------- +// +// VController::stop( pReset ); +// +// Stop playback altogether and reset the Controller to the start of the +// sequence. +// +//----------------------------------------------------------------------------- +void VController::stop( const bool &pReset ) +{ + // Stop Updating. + setProcessTicks( false ); + + // Reset Loop Index. + mLoopIndex = 0; + + // Update Status. + updateStatus( ( k_StatusInit | k_StatusStopped ) ); + + // Reset? + if ( pReset ) + { + // Reset. + reset(); + } + + // Stop Signal. + postEvent( k_EventStop ); + + // Callback. + Con::executef( this, "onStop" ); +} + +//----------------------------------------------------------------------------- +// +// VController::jump(); +// +// Jump the Controller time forward 1 tick (32ms). +// +//----------------------------------------------------------------------------- +void VController::jump( void ) +{ + // Jump 1 tick. + jump( k_JumpDelta, ( isPlayingForward() ) ? TickMs : -TickMs ); +} + +//----------------------------------------------------------------------------- +// +// VController::jump( pType, pDelta ); +// +// Jump the Controller time by the target Delta. +// +//----------------------------------------------------------------------------- +void VController::jump( const eControllerJumpType &pType, const S32 &pDelta ) +{ + // Jump. + mJump = pType; + mJumpTime = pDelta; +} + +//----------------------------------------------------------------------------- +// +// VController::updateStatus( pStatus ); +// +// Clear the regular playback states and add the updated state. +// +//----------------------------------------------------------------------------- +void VController::updateStatus( const S32 &pStatus ) +{ + // Clear Playback Status. + mStatus &= ~( k_StatusPlaying | k_StatusPaused | k_StatusStopped ); + + // Add New Status. + mStatus |= pStatus; +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::getObject( pLabel ); +// +// Returns the group with the given name. If no group belongs to the Controller +// with that name, then a NULL value is returned. +// +//----------------------------------------------------------------------------- +VGroup *VController::getObject( const String &pLabel ) +{ + VGroup *node = ( VGroup* )mChildNode; + while ( node ) + { + // Compare Names. + if ( node->getLabel().equal( pLabel, String::NoCase ) ) + { + // Valid. + return node; + } + + // Next Sibling. + node = ( VGroup* )node->mSiblingNextNode; + } + + // Invalid. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VController::getDirectorGroup(); +// +// Returns the DirectorGroup reference if the Controller has a one. +// +//----------------------------------------------------------------------------- +VDirectorGroup *VController::getDirectorGroup( void ) +{ + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + if ( VDirectorGroup *group = dynamic_cast( node ) ) + { + // Return Group. + return group; + } + } + + // Invalid Group. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VController::getDirectorTrack(); +// +// Returns the DirectorTrack reference if the DirectorGroup has one. +// +//----------------------------------------------------------------------------- +VDirectorTrack *VController::getDirectorTrack( void ) +{ + VDirectorGroup *group = getDirectorGroup(); + if ( !group ) + { + // Invalid Track. + return NULL; + } + + // Return Track. + return group->getDirectorTrack(); +} + +//----------------------------------------------------------------------------- +// +// VController::getDataValue( pFieldName, *pValue ); +// +// Returns true if the field is a DataTable member and can be correctly +// evaluated. If this is the case, then pValue will contain the result. +// +//----------------------------------------------------------------------------- +bool VController::getDataValue( const String &pFieldName, String &pValue ) +{ + return mDataTable.getValue( this, pFieldName, pValue ); +} + +//----------------------------------------------------------------------------- +// +// VController::clearData(); +// +// Clear the contents of the DataTable entirely. +// +//----------------------------------------------------------------------------- +void VController::clearData( void ) +{ + while ( mDataTable.getCount() > 0 ) + { + // Clear Item. + clearData( 0 ); + } +} + +//----------------------------------------------------------------------------- +// +// VController::clearData( pIndex ); +// +// Clear the DataTable entry with the given index. +// +//----------------------------------------------------------------------------- +void VController::clearData( const S32 &pIndex ) +{ + VDataTable::sDataItem data; + if ( mDataTable.getItem( pIndex, &data ) ) + { + // Clear Data. + clearData( data.FieldName ); + } +} + +//----------------------------------------------------------------------------- +// +// VController::clearData( pIndex ); +// +// Clear the DataTable entry with the given field name. +// +//----------------------------------------------------------------------------- +void VController::clearData( const String &pFieldName ) +{ + // Clear Dynamic Field. + setDataField( pFieldName, NULL, "" ); + + // Clear Item. + mDataTable.clear( pFieldName ); +} + +//----------------------------------------------------------------------------- +// +// VController::sort(); +// +// Sort each track in each of the child groups. +// +//----------------------------------------------------------------------------- +void VController::sort( void ) +{ + for ( ITreeNode *group = mChildNode; group != NULL; group = group->mSiblingNextNode ) + { + for ( ITreeNode *track = group->mChildNode; track != NULL; track = track->mSiblingNextNode ) + { + // Sort Track. + ( ( VTrack* )track )->sort(); + } + } +} + +//----------------------------------------------------------------------------- +// +// Write Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::writeDataTable( pElement ); +// +// Write the DataTable out to a TinyXML document. +// +//----------------------------------------------------------------------------- +bool VController::writeDataTable( TiXmlElement *pElement ) +{ + // Create Data Table Root. + TiXmlElement *dataTableRoot = new TiXmlElement( "DataTable" ); + pElement->LinkEndChild( dataTableRoot ); + + for ( VDataTable::VDataMap::Iterator itr = mDataTable.mDataMap.begin(); itr != mDataTable.mDataMap.end(); ++itr ) + { + // Fetch Data. + VDataTable::sDataItem *data = &itr->value; + + // Create Element. + TiXmlElement *dataElement = new TiXmlElement( "DataItem" ); + + // Apply Attributes. + dataElement->SetAttribute( "Type", VDataTable::getDataTypeDescription( data->Type ) ); + dataElement->SetAttribute( "Name", data->FieldName ); + dataElement->SetAttribute( "Value", getDataField( StringTable->insert( data->FieldName.c_str() ), NULL ) ); + + // Add. + dataTableRoot->LinkEndChild( dataElement ); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Read Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::readDataTable( pElement ); +// +// Read the DataTable from a TinyXML document. +// +//----------------------------------------------------------------------------- +bool VController::readDataTable( TiXmlElement *pElement ) +{ + TiXmlElement *dataTableRoot = pElement->FirstChildElement( "DataTable" ); + if ( dataTableRoot ) + { + for ( TiXmlElement *child = dataTableRoot->FirstChildElement(); child != NULL; child = child->NextSiblingElement() ) + { + // Get Field Data. + const char *fieldType = child->Attribute( "Type" ); + const char *fieldName = child->Attribute( "Name" ); + const char *fieldValue = child->Attribute( "Value" ); + + // Add Data Item. + mDataTable.insert( VDataTable::getDataTypeEnum( fieldType ), fieldName ); + + // Set Field Value. + setDataField( StringTable->insert( fieldName ), NULL, fieldValue ); + } + } + + // Valid Read. + return true; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VController::postEvent( pEvent ); +// +// Process an event signal to all event subscribers. This method is used to +// signal changes in the Controller's status. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +void VController::postEvent( const eControllerEventType &pEvent ) +{ + // Signal Event. + mControllerEventSignal.trigger( pEvent ); +} + +//----------------------------------------------------------------------------- +// +// VController::setTimeScale( pTimeScale ); +// +// Set the speed of playback. In effect, a value of 0.5 will double the real +// time taken to complete the playback of the sequence, while a value of 2.0 +// will halve the time needed. +// +//----------------------------------------------------------------------------- +void VController::setTimeScale( const F32 &pTimeScale ) +{ + // Need an Update? + const bool update = ( pTimeScale != 0.f && ( mTimeScale == 0.f || ( ( mTimeScale > 0.f ) != ( pTimeScale > 0.f ) ) ) ); + + // Store. + mTimeScale = pTimeScale; + + // Update $timeScale Variable. + Con::setFloatVariable( "timeScale", mFabs( mTimeScale ) ); + + if ( update ) + { + // Reset. + reset( mTime ); + } +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VController, readFile, bool, (String fileName), (""), "( string pFileName ) - Clears the object and loads the new data from the given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Clear Sequence Lists. + object->clear(); + + // Clear Data Table. + object->clearData(); + + // Read Target File. + if ( !VPersistence::readFile( fileName, object ) ) + { + // Re-Clear. + object->clear(); + + // Invalid Read. + return false; + } + + // Initial Sort. + object->sort(); + + // Reset. + object->reset(); + + // Valid Read. + return true; +} + +DefineEngineMethod( VController, clear, void, (), , "( void ) - Detaches and deletes all of the child objects.\n" + "@return No return value." ) +{ + // Clear Sequence Lists. + object->clear(); + + // Clear Data Table. + object->clearData(); +} + +DefineEngineMethod( VController, reset, void, (S32 time), (-1), "( [int pTime] ) - Reset the Controller's and child object's state.\n" + "@param pTime The target time to reset to.\n" + "@return No return value." ) +{ + if (time != -1) + { + // Reset Sequence. + object->reset(time); + return; + } + + // Default Reset. + object->reset(); +} + +DefineEngineMethod( VController, isPlaying, bool, (), , "( void ) - Is the sequence currently playing?\n" + "@return Returns true if the Controller is playing." ) +{ + // Is Playing? + return ( object->isPlaying() ); +} + +DefineEngineMethod( VController, play, void, (S32 time), (-1), "( [int pTime] ) - Play the sequence. If a value for pTime is specified, the Controller is reset and played from that time.\n" + "@param pTime The time to start playing the sequence from.\n" + "@return No return value." ) +{ + S32 startTime = object->getTime(); + if (time != -1) + { + startTime = time; + } + + // Play From Specified Time. + object->play( startTime ); +} + +DefineEngineMethod( VController, step, void, (),, "( void ) - Step forward one frame.\n" + "@return No return value." ) +{ + if ( object->isPlaying() ) + { + // Sanity! + return; + } + + // Play. + object->play( object->getTime() ); + + // Jump. + object->jump(); + + // Step Forward One Frame. + object->processTick(); + + // Stop. + object->stop( false ); +} + +DefineEngineMethod( VController, isPaused, bool, (), , "( void ) - Is the sequence currently paused?\n" + "@return Returns true if the Controller is paused." ) +{ + // Is Paused? + return ( object->isPaused() ); +} + +DefineEngineMethod( VController, pause, void, (), , "( void ) - Pause the sequence. Playback can resume by calling VController::play().\n" + "@return No return value." ) +{ + // Pause Sequence. + object->pause(); +} + +DefineEngineMethod( VController, isStopped, bool, (), , "( void ) - Is the sequence currently stopped?\n" + "@return Returns true if the Controller is stopped." ) +{ + // Is Stopped? + return ( object->isStopped() ); +} + +DefineEngineMethod( VController, stop, void, (bool reset), (true), "( [bool pReset] ) - Stop the sequence and optionally reset it.\n" + "@param pReset Reset the Controller after stopping.\n" + "@return No return value." ) +{ + // Stop Sequence. + object->stop(reset); +} + +DefineEngineMethod( VController, getTimeScale, F32, (), , "( void ) - Get the playback speed. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards.\n" + "@return Playback Speed." ) +{ + // Get Time Scale. + return object->getTimeScale(); +} + +DefineEngineMethod( VController, setTimeScale, void, (float timeScale), (1), "( float pTimeScale ) - Set the playback speed. A value > 0.0 will enable the Controller to play forwards, while a value < 0.0 will play backwards. If |pTimeScale| > 1.0, then playback will be faster than normal, while |pTimeScale| < 1.0 will be slower.\n" + "@param pTimeScale Playback speed.\n" + "@return No return value." ) +{ + // Set Time Scale. + object->setTimeScale(timeScale); +} + +DefineEngineMethod( VController, isDataField, bool, (String fieldName), (""), "( string pFieldName ) - Is the field a member of the Data Table?\n" + "@param pFieldName The name of the dynamic field you wish to check.\n" + "@return Returns true if the field is a member of the Data Table." ) +{ + if (fieldName.isEmpty()) + { + return false; + } + + // Is Field. + return object->getDataTable().getItem(fieldName); +} + +DefineEngineMethod( VController, getDataFieldCount, S32, (), , "( void ) - Get the number of data elements in the Data Table.\n" + "@return Returns the size of the Data Table." ) +{ + // Return Count. + return object->getDataTable().getCount(); +} + +DefineEngineMethod( VController, getDataFieldName, const char *, (S32 index), (0), "( int pIndex ) - Get the name of the field given by the passed index.\n" + "@param pIndex The index of the data field you wish to check.\n" + "@return Returns the name of the field corresponding to the given index." ) +{ + VDataTable::sDataItem data; + if ( !object->getDataTable().getItem(index, &data ) || data.Type == VDataTable::k_TypeInvalid ) + { + // Invalid Field. + return ""; + } + + // Return Field Name. + return data.FieldName; +} + +DefineEngineMethod( VController, getDataFieldValue, const char *, (String fieldName), (""), "( string pFieldName ) - Get the evaluated data from the data field.\n" + "@param pFieldName The name of the field you wish to evaluate.\n" + "@return Returns the evaluated data from the field." ) +{ + String fieldValue; + if ( object->getDataValue(fieldName, fieldValue ) ) + { + // Create Buffer. + char *buffer = Con::getReturnBuffer( 256 ); + dStrcpy( buffer, fieldValue.c_str(), 256 ); + + // Return Value. + return buffer; + } + + // Return NULL. + return "0"; +} + +DefineEngineMethod( VController, getDataFieldType, const char *, (String fieldName), (""), "( string pFieldName ) - Get the type of data for the given field.\n" + "@param pFieldName The name of the field you wish to check.\n" + "@return Returns the data type." ) +{ + VDataTable::sDataItem data; + if ( !object->getDataTable().getItem(fieldName, &data ) || data.Type == VDataTable::k_TypeInvalid ) + { + // Invalid Field. + return ""; + } + + // Return Field Type. + return VDataTable::getDataTypeDescription( data.Type ); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VController, writeFile, bool, (String fileName), (""), "( string pFileName ) - Save to a given filename.\n" + "@param pFileName The target file to write to.\n" + "@return Returns true if the write was successful." ) +{ + // Write Target File. + return VPersistence::writeFile(fileName.c_str(), object ); +} + +DefineEngineMethod( VController, readTemplate, bool, (String fileName), (""), "( string pFileName ) - Load data from given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Read Target File. + return VPersistence::readFile(fileName.c_str(), object ); +} + +DefineEngineMethod( VController, getCount, S32, (),, "( void ) - Get the number of child objects.\n" + "@return Returns the number of child objects." ) +{ + // Size. + return object->size(); +} + +DefineEngineMethod( VController, getObject, S32, (S32 index), (0), "( int pIndex ) - Get the object corresponding to the given index.\n" + "@param pIndex The index of the object you wish to retrieve.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->at(index); + + // Return Group ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +DefineEngineMethod( VController, addObject, void, (SimObject* simObj), (nullAsType()), "( SimObject pObject ) - Add a child object to this node.\n" + "@param pObject The SimObjectID of the object to be added to this node.\n" + "@return No return value." ) +{ + if (simObj == nullptr) + return; + + VObject *child = dynamic_cast(simObj); + if ( child ) + { + // Add Child. + child->addTo( object ); + } +} + +DefineEngineMethod( VController, removeObject, void, (SimObject* simObj), (nullAsType()), "( SimObject pObject ) - Remove the target object from this node.\n" + "@param pObject The SimObjectID of the object to be removed from this node.\n" + "@return No return value." ) +{ + if (simObj == nullptr) + return; + + VObject *child = dynamic_cast(simObj); + if ( child && child->getParent() == object ) + { + child->remove(); + } +} + +DefineEngineMethod( VController, sortGroups, void, (),, "( void ) - Sort Groups by their Labels.\n" + "@return No return value." ) +{ + // Ensure that the Director Group is the First Group. + VDirectorGroup *directorGroup = object->getDirectorGroup(); + if ( directorGroup && directorGroup != object->mChildNode ) + { + // Detach. + directorGroup->remove(); + + // Add to the Front of the Controller. + directorGroup->addToFront( object ); + } + + const S32 count = object->size(); + for ( S32 j = 0; j < count; j++ ) + { + ITreeNode *node = object->mChildNode; + if ( dynamic_cast( node ) != NULL ) + { + // Skip Director Group. + node = node->mSiblingNextNode; + } + + for ( ; node != NULL; node = node->mSiblingNextNode ) + { + VGroup *groupA = ( VGroup* )node; + VGroup *groupB = ( VGroup* )node->mSiblingNextNode; + if ( !groupB ) + { + // No Node. + break; + } + + // Swap? + if ( dStrcmp( groupA->getLabel(), groupB->getLabel() ) > 0 ) + { + // Get Outer Siblings. + ITreeNode *prevNode = groupA->mSiblingPrevNode; + ITreeNode *nextNode = groupB->mSiblingNextNode; + + if ( groupA->mParentNode && groupA->mParentNode->mChildNode == groupA ) + { + // New Child Node. + groupA->mParentNode->mChildNode = groupB; + } + + // + // Move A. + + groupA->mSiblingPrevNode = groupB; + groupA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = groupA; + } + + // + // Move B. + + groupB->mSiblingPrevNode = prevNode; + groupB->mSiblingNextNode = groupA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = groupB; + } + } + } + } +} + +DefineEngineMethod( VController, sortTracks, void, (),, "( void ) - Sort Tracks by their Labels.\n" + "@return No return value." ) +{ + for ( ITreeNode *group = object->mChildNode; group != NULL; group = group->mSiblingNextNode ) + { + const S32 count = ( ( VGroup* )group )->size(); + for ( S32 j = 0; j < count; j++ ) + { + for ( ITreeNode *node = group->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VTrack *trackA = ( VTrack* )node; + VTrack *trackB = ( VTrack* )node->mSiblingNextNode; + if ( !trackB ) + { + // No Node. + break; + } + + // Swap? + if ( dStrcmp( trackA->getLabel(), trackB->getLabel() ) > 0 ) + { + // Get Outer Siblings. + ITreeNode *prevNode = trackA->mSiblingPrevNode; + ITreeNode *nextNode = trackB->mSiblingNextNode; + + if ( trackA->mParentNode && trackA->mParentNode->mChildNode == trackA ) + { + // New Child Node. + trackA->mParentNode->mChildNode = trackB; + } + + // + // Move A. + + trackA->mSiblingPrevNode = trackB; + trackA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = trackA; + } + + // + // Move B. + + trackB->mSiblingPrevNode = prevNode; + trackB->mSiblingNextNode = trackA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = trackB; + } + } + } + } + } +} + +DefineEngineMethod( VController, addDataField, void, (String fieldType, String fieldName), ("", ""), "( string pFieldType, string pFieldName ) - Add a new data entry to the Data Table.\n" + "@param pFieldType The method of evaluating the field's data.\n" + "@param pFieldName The name of the field to be added to the Data Table.\n" + "@return No return value." ) +{ + // Insert Data. + object->getDataTable().insert( VDataTable::getDataTypeEnum(fieldType), fieldName); +} + +DefineEngineMethod( VController, removeDataField, void, (String fieldName), (""), "( string pFieldName ) - Remove a data entry from the Data Table.\n" + "@param pFieldName The name of the field to be removed from the Data Table.\n" + "@return No return value." ) +{ + // Clear Data Item. + object->clearData(fieldName); +} +#endif diff --git a/Engine/source/Verve/Core/VController.h b/Engine/source/Verve/Core/VController.h new file mode 100644 index 000000000..f38a1cdf0 --- /dev/null +++ b/Engine/source/Verve/Core/VController.h @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCONTROLLER_H_ +#define _VT_VCONTROLLER_H_ + +#ifndef _VT_VERVECONFIG_H_ +#include "Verve/VerveConfig.h" +#endif + +#ifndef _PLATFORM_H_ +#include "platform/platform.h" +#endif + +#ifndef _PROCESSLIST_H_ +#include "T3D/gameBase/processList.h" +#endif + +#ifndef _ITICKABLE_H_ +#include "core/iTickable.h" +#endif + +#ifndef _VT_VPERSISTENCE_H_ +#include "Verve/Core/Persistence/VPersistence.h" +#endif + +#ifndef _VT_VTREENODE_H_ +#include "Verve/Core/VTreeNode.h" +#endif + +#ifndef _VT_VDATATABLE_H_ +#include "Verve/Core/VDataTable.h" +#endif + +#ifndef _VT_TORQUE_CAMERA_H_ +#include "Verve/Torque/TCamera.h" +#endif + +//----------------------------------------------------------------------------- +class VObject; + +class VTrack; +class VEvent; +class VGroup; + +class VDirectorGroup; +class VDirectorTrack; + +typedef VectorPtr VTrackVector; +typedef VTrackVector::iterator VTrackIterator; + +typedef VectorPtr VEventVector; +typedef VEventVector::iterator VEventIterator; + +typedef VectorPtr VGroupVector; +typedef VGroupVector::iterator VGroupIterator; +//----------------------------------------------------------------------------- + +class VController : public SimObject, + public virtual ITickable, + public VTreeNode +{ + typedef SimObject Parent; + +public: + + enum eControllerStatus + { + k_StatusInit = BIT( 0 ), + + k_StatusPlaying = BIT( 1 ), + k_StatusPaused = BIT( 2 ), + k_StatusStopped = BIT( 3 ), + }; + + enum eControllerEventType + { + k_EventInit, + k_EventReset, + + k_EventPlay, + k_EventPause, + k_EventStop, + + k_EventLoop, + }; + + enum eControllerJumpType + { + k_JumpTime, + k_JumpDelta, + + k_JumpInvalid, + }; + + typedef Signal ControllerUpdateSignal; + typedef Signal ControllerEventSignal; + +private: + + // Data. + + VDataTable mDataTable; + + // Event Signal. + + ControllerUpdateSignal mControllerUpdateSignal; + ControllerEventSignal mControllerEventSignal; + + // Properties. + + S32 mStatus; + + S32 mTime; + U32 mLastTime; + S32 mDuration; + F32 mTimeScale; + + bool mLoop; + bool mLoopBackwards; + S32 mLoopCount; + S32 mLoopIndex; + S32 mLoopDelay; + S32 mLoopDelayTime; + + eControllerJumpType mJump; + S32 mJumpTime; + + bool mResetOnCompletion; + +public: + + VController(); + ~VController(); + + static void initPersistFields( void ); + + // ITickable. + + void interpolateTick( F32 pDelta ) { }; + void advanceTime( F32 pDelta ) { }; + void processTick( void ); + void onPostTick( void ); + + // Controller. + + void reset( void ); + void reset( const S32 &pTime ); + + void play( void ); + void play( const S32 &pTime ); + + void pause( void ); + void stop( const bool &pReset = true ); + + void jump( void ); + void jump( const eControllerJumpType &pType, const S32 &pDelta ); + + void updateStatus( const S32 &pStatus ); + + // Reference. + + VGroup *getObject( const String &pLabel ); + template inline bool getObject( const String &pLabel, T *&pObject ) + { + // Reference Group. + pObject = dynamic_cast( getObject( pLabel ) ); + + // Valid? + return ( pObject != NULL ); + } + + bool getDataValue( const String &pFieldName, String &pValue ); + void clearData( void ); + void clearData( const S32 &pIndex ); + void clearData( const String &pFieldName ); + + void sort( void ); + + // Saving. + + bool writeDataTable( TiXmlElement *pElement ); + + // Reading. + + bool readDataTable( TiXmlElement *pElement ); + + // Console Declaration. + + DECLARE_CONOBJECT( VController ); + +public: + + inline VDataTable &getDataTable( void ) { return mDataTable; }; + + inline ControllerUpdateSignal &getControllerUpdateSignal( void ) { return mControllerUpdateSignal; }; + inline ControllerEventSignal &getControllerEventSignal( void ) { return mControllerEventSignal; }; + void postEvent( const eControllerEventType &pEvent ); + + VDirectorGroup *getDirectorGroup( void ); + VDirectorTrack *getDirectorTrack( void ); + + inline void setTime( const S32 &pTime ) { mTime = pTime; }; + inline void setDuration( const S32 &pDuration ) { mDuration = pDuration; }; + void setTimeScale( const F32 &pTimeScale ); + + inline bool isLooping( void ) { return mLoop; }; + inline bool isPlaying( void ) { return ( mStatus & k_StatusPlaying ); }; + inline bool isPaused( void ) { return ( mStatus & k_StatusPaused ); }; + inline bool isStopped( void ) { return ( mStatus & k_StatusStopped ); }; + inline bool isPlayingForward( void ) { return ( mTimeScale > 0.f ); }; + + inline S32 getTime( void ) { return mTime; }; + inline S32 getDuration( void ) { return mDuration; }; + inline F32 getTimeScale( void ) { return mTimeScale; }; + inline S32 getLoopDelayTime( void ) { return mLoopDelayTime; }; + +protected: + + static bool setTime( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setTime( dAtoi( pData ) ); return false; }; + static bool setDuration( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setDuration( dAtoi( pData ) ); return false; }; + static bool setTimeScale( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setTimeScale( dAtof( pData ) ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VDataTable.cpp b/Engine/source/Verve/Core/VDataTable.cpp new file mode 100644 index 000000000..f338c5ac4 --- /dev/null +++ b/Engine/source/Verve/Core/VDataTable.cpp @@ -0,0 +1,253 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VDataTable.h" + +#include "console/simObject.h" + +//----------------------------------------------------------------------------- + +// Implement the DataType enum list. +ImplementEnumType( VDataTableDataType, "" ) + { VDataTable::k_TypeExpression, "EXPRESSION" }, + { VDataTable::k_TypeStatic, "STATIC" }, + { VDataTable::k_TypeVariable, "VARIABLE" }, +EndImplementEnumType; + +VDataTable::eDataType VDataTable::getDataTypeEnum( const char *pLabel ) +{ + VDataTable::eDataType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VDataTable::k_TypeInvalid; + } + + // Return. + return out; +} + +const char *VDataTable::getDataTypeDescription( const VDataTable::eDataType pEnum ) +{ + // Return. + return castConsoleTypeToString( pEnum ); +} + +//----------------------------------------------------------------------------- + +VDataTable::VDataTable( void ) +{ + mDataMap.clear(); +} + +VDataTable::~VDataTable( void ) +{ + mDataMap.clear(); +} + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDataTable::insert( pType, pFieldName ); +// +// Add a DataTable entry, referencing the field name and assign it the given +// data type. +// +// For a full list of possible data types, see the 'eDataType' declaration in +// VDataTable.h. +// +//----------------------------------------------------------------------------- +void VDataTable::insert( eDataType pType, const String &pFieldName ) +{ + if ( mDataMap.contains( pFieldName ) ) + { + // Change Field Type. + mDataMap.find( pFieldName )->value.Type = pType; + + // Return. + return; + } + + // Insert Item. + mDataMap.insert( pFieldName, sDataItem( pType, pFieldName ) ); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::clear( pFieldName ); +// +// Clear the DataTable entry with the given field name. +// +//----------------------------------------------------------------------------- +void VDataTable::clear( const String &pFieldName ) +{ + // Clear Item. + mDataMap.erase( pFieldName ); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::clear(); +// +// Clear the contents of the DataTable entirely. +// +//----------------------------------------------------------------------------- +void VDataTable::clear( void ) +{ + // Clear. + mDataMap.clear(); +} + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDataTable::getCount(); +// +// Return the number of DataTable entries. +// +//----------------------------------------------------------------------------- +S32 VDataTable::getCount( void ) +{ + return mDataMap.size(); +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getItem( pIndex, *pDataItem ); +// +// Return the item with the given index. This method will return false if there +// is no valid data entry with that index. +// +//----------------------------------------------------------------------------- +bool VDataTable::getItem( const S32 &pIndex, sDataItem *pDataItem ) +{ + if ( pIndex < 0 || pIndex >= mDataMap.size() ) + { + // Invalid Field. + return false; + } + + S32 index = 0; + for ( VDataMap::Iterator itr = mDataMap.begin(); itr != mDataMap.end(); ++itr ) + { + if ( index == pIndex ) + { + if ( pDataItem ) + { + // Store Reference. + *pDataItem = ( itr->value ); + } + + // Valid Field. + return true; + } + + // Increment. + ++index; + } + + // Invalid Field. + return false; +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getItem( pFieldName, *pDataItem ); +// +// Return the item with the given field name. This method will return false if +// there is no valid data entry with that name. +// +//----------------------------------------------------------------------------- +bool VDataTable::getItem( const String &pFieldName, sDataItem *pDataItem ) +{ + if ( mDataMap.contains( pFieldName ) ) + { + if ( pDataItem ) + { + // Fetch Item + *pDataItem = mDataMap.find( pFieldName )->value; + } + + // Valid Field. + return true; + } + + // Invalid Field. + return false; +} + +//----------------------------------------------------------------------------- +// +// VDataTable::getValue( pObject, pFieldName, *pValue ); +// +// Evaluate and return the expression provided in the data field. +// +//----------------------------------------------------------------------------- +bool VDataTable::getValue( SimObject *pObject, const String &pFieldName, String &pValue ) +{ + if ( !pObject || pFieldName.isEmpty() ) + { + // Sanity! + return false; + } + + // Fetch Data. + sDataItem *data = &( mDataMap.find( pFieldName )->value ); + if ( !data ) + { + // No Field. + return false; + } + + // Field Value. + const char *fieldValue = pObject->getDataField( StringTable->insert( data->FieldName ), NULL ); + + switch ( data->Type ) + { + case VDataTable::k_TypeExpression : + { + // Evaluate. + pValue = Con::evaluate( fieldValue, false ).getStringValue(); + + } break; + + case VDataTable::k_TypeStatic : + { + // Use Value. + pValue = fieldValue; + + } break; + + case VDataTable::k_TypeVariable : + { + + // Fetch Variable. + pValue = Con::getVariable( fieldValue ); + + } break; + } + + // Valid Field. + return true; +} diff --git a/Engine/source/Verve/Core/VDataTable.h b/Engine/source/Verve/Core/VDataTable.h new file mode 100644 index 000000000..6b4cba90a --- /dev/null +++ b/Engine/source/Verve/Core/VDataTable.h @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDATATABLE_H_ +#define _VT_VDATATABLE_H_ + +#ifndef CORE_TDICTIONARY_H +#include "core/util/tDictionary.h" +#endif + +#ifndef _CONSOLE_H_ +#include "console/console.h" +#endif + +#ifndef _DYNAMIC_CONSOLETYPES_H_ +#include "console/dynamicTypes.h" +#endif + +#ifndef _STRINGTABLE_H_ +#include "core/stringTable.h" +#endif + +//----------------------------------------------------------------------------- + +class VDataTable +{ +public: + + enum eDataType + { + k_TypeExpression, + k_TypeStatic, + k_TypeVariable, + + k_TypeInvalid, + }; + + struct sDataItem + { + eDataType Type; + String FieldName; + + sDataItem( void ) : + Type( k_TypeInvalid ), + FieldName( String::EmptyString ) + { + // Void. + }; + + sDataItem( eDataType pType, const String &pFieldName ) : + Type( pType ), + FieldName( pFieldName ) + { + // Void. + }; + }; + + // Enum Lookup. + static VDataTable::eDataType getDataTypeEnum( const char *pLabel ); + static const char *getDataTypeDescription( const VDataTable::eDataType pEnum ); + + // Map Type. + typedef Map VDataMap; + +public: + + VDataMap mDataMap; + +public: + + VDataTable( void ); + ~VDataTable( void ); + + // Data. + + void insert( eDataType pType, const String &pFieldName ); + void clear( const String &pFieldName ); + void clear( void ); + + // Reference. + + S32 getCount( void ); + bool getItem( const S32 &pIndex, sDataItem *pDataItem = NULL ); + bool getItem( const String &pFieldName, sDataItem *pDataItem = NULL ); + + bool getValue( SimObject *pObject, const String &pFieldName, String &pValue ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VDataTable::eDataType VDataTableDataType; + +// Declare Enum Types. +DefineEnumType( VDataTableDataType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VDATATABLE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VEvent.cpp b/Engine/source/Verve/Core/VEvent.cpp new file mode 100644 index 000000000..6b4e8ed54 --- /dev/null +++ b/Engine/source/Verve/Core/VEvent.cpp @@ -0,0 +1,406 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VEvent.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEvent ); +//----------------------------------------------------------------------------- + +VEvent::VEvent( void ) : + mIsPlaying( false ), + mTriggered( false ), + mTriggerTime( 0 ), + mDuration( 0 ) +{ + setLabel( "DefaultEvent" ); +} + +void VEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "TriggerTime", TypeS32, Offset( mTriggerTime, VEvent ), &setTriggerTime, &defaultProtectedGetFn, "The time that this event is triggered." ); + addProtectedField( "Duration", TypeS32, Offset( mDuration, VEvent ), &setDuration, &defaultProtectedGetFn, "The total duration that this event plays for." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::onControllerReset( pTime, pForward ); +// +// Reset the status of the event. If the given time is between the event's +// start and finish times, then the isPlaying flag will be true. This means +// that the event is free to be triggered upon playback. +// +//----------------------------------------------------------------------------- +void VEvent::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Reset Status. + mIsPlaying = ( pTime > mTriggerTime && pTime < ( mTriggerTime + mDuration ) ); + mTriggered = false; +} + +//----------------------------------------------------------------------------- +// +// VEvent::onControllerUpdate( pTime, pDelta ) +// +// Integrate is only called when this event is the Next Event for the parent +// track. For each track, there is only ever *one* event being integrated - the +// event that needs to be triggered next. +// +// If the event has a duration greater than 0, then this event will continue to +// integrate until its time is up, or the controller finishes playing +// (whichever happens first). +// +// If a value of true is returned, then this event will continue to integrate +// until a value of false is returned to the parent track. When this happens, +// this event ceases to be the track's Next Event and will not continue +// updating. +// +//----------------------------------------------------------------------------- +bool VEvent::onControllerUpdate( const S32 &pTime, const S32 &pDelta ) +{ + if ( !isEnabled() ) + { + return false; + } + + const S32 newTime = ( pTime + pDelta ); + const S32 &startTime = getStartTime(); + const S32 &finishTime = getFinishTime(); + + if ( !mIsPlaying || !mTriggered ) + { + if ( !mIsPlaying ) + { + if ( ( pDelta > 0 && newTime < startTime ) + || ( pDelta < 0 && newTime > startTime ) ) + { + // Not Time to Trigger. + return true; + } + + if ( ( pDelta > 0 && pTime > startTime ) + || ( pDelta < 0 && pTime < startTime ) ) + { + //AssertFatal( false, "VEvent::onControllerUpdate() - Event has been skipped." ); + return false; + } + } + + if ( !mTriggered ) + { + // Play and Trigger. + mIsPlaying = ( mDuration > 0 ); + mTriggered = true; + + // Callback. + onTrigger( pTime, pDelta ); + + if ( mDuration == 0 ) + { + // Stop Integrating. + return false; + } + + // Return Here. + // Note: If Duration is non-zero this event will continue to update + // so that VEvent:: onUpdate is processed for the full event + // duration. + return ( mDuration != 0 ); + } + } + + // Complete? + const bool isComplete = ( ( pDelta > 0 && newTime > finishTime ) + || ( pDelta < 0 && newTime < finishTime ) ); + + if ( !isComplete ) + { + // Callback. + onUpdate( pTime, pDelta ); + } + else + { + // Complete. + mIsPlaying = false; + + // Callback. + onComplete( pTime, pDelta ); + } + + // Continue? + return !isComplete; +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::onTrigger( pTime, pDelta ); +// +// This method is called when an event is due to be triggered. This method is +// meant to be overloaded by derived classes. +// +// For examples of what an event might do, please refer to some of the included +// events with Verve. +// +//----------------------------------------------------------------------------- +void VEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// VEvent::onUpdate( pTime, pDelta ); +// +// This method is called each tick once an event has been triggered and ceases +// to be called when it is completed. This method is meant to be overloaded by +// derived classes. +// +//----------------------------------------------------------------------------- +void VEvent::onUpdate( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// VEvent::onComplete( pTime, pDelta ); +// +// This method is called once an event has finished being updated. It is not +// called on events that have a duration of 0. This method is meant to be +// overloaded by derived classes. +// +//----------------------------------------------------------------------------- +void VEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VEvent::getGroup(); +// +// Returns the parent group. +// +//----------------------------------------------------------------------------- +VGroup *VEvent::getGroup( void ) +{ + VTrack *track = getTrack(); + if ( track ) + { + return track->getGroup(); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VEvent::getTrack(); +// +// Returns the parent track. +// +//----------------------------------------------------------------------------- +VTrack *VEvent::getTrack( void ) +{ + return dynamic_cast( mParentNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getNextEvent(); +// +// Returns the next event. +// +//----------------------------------------------------------------------------- +VEvent *VEvent::getNextEvent( void ) +{ + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( mSiblingPrevNode ); + } + + return dynamic_cast( mSiblingNextNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getPreviousEvent(); +// +// Returns the previous event. +// +//----------------------------------------------------------------------------- +VEvent *VEvent::getPreviousEvent( void ) +{ + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( mSiblingNextNode ); + } + + return dynamic_cast( mSiblingPrevNode ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getStartTime(); +// +// Returns the time, in milliseconds, that the event is due to trigger. +// +//----------------------------------------------------------------------------- +S32 VEvent::getStartTime( void ) +{ + return ( mTriggerTime + ( !isControllerPlayingForward() * mDuration ) ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::getFinishTime(); +// +// Returns the time, in milliseconds, that the event will cease updating. +// +//----------------------------------------------------------------------------- +S32 VEvent::getFinishTime( void ) +{ + return ( mTriggerTime + ( isControllerPlayingForward() * mDuration ) ); +} + +//----------------------------------------------------------------------------- +// +// VEvent::setTriggerTime( pTime ); +// +// Apply the given trigger time to the object. +// +// If the project was built using the VT_EDITOR preprocessor argument, then +// the validity of the passed value is verified. It also cannot be changed +// while the controller is playing. +// +//----------------------------------------------------------------------------- +void VEvent::setTriggerTime( const S32 &pTime ) +{ +#ifdef VT_EDITOR + + VTrack *track = getTrack(); + if ( !track ) + { + // Apply Time. + mTriggerTime = pTime; + + return; + } + + if ( track->isControllerPlaying() ) + { + // Don't Change While Playing. + return; + } + + /* + // Check For Overlap. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *event = ( VEvent* )node; + if ( event == this ) + { + // Skip. + continue; + } + + const U32 startTime = getStartTime(); + const U32 finishTime = getFinishTime(); + + if ( ( pTime > startTime && pTime < finishTime ) + || ( ( pTime + mDuration ) > startTime && ( pTime + mDuration ) < finishTime ) + || ( pTime < startTime && ( pTime + mDuration ) > finishTime ) ) + { + // Overlap! + return; + } + } + */ + + // Apply Time. + mTriggerTime = mClamp( pTime, 0, getControllerDuration() ); + + // Sort Events. + track->sort(); + + // Reset Track. + track->onControllerReset( getControllerTime(), isControllerPlayingForward() ); + +#else + + // Apply Time. + mTriggerTime = pTime; + +#endif +} + +//----------------------------------------------------------------------------- +// +// VEvent::setDuration( pDuration ); +// +// Apply the given duration time to the object. +// +// If the project was built using the VT_EDITOR preprocessor argument, then +// the validity of the passed value is verified. It also cannot be changed +// while the controller is playing. +// +//----------------------------------------------------------------------------- +void VEvent::setDuration( const S32 &pDuration ) +{ +#ifdef VT_EDITOR + + if ( isControllerPlaying() ) + { + // Don't Change While Playing. + return; + } + +#endif + + // Apply Duration. + mDuration = pDuration; +} \ No newline at end of file diff --git a/Engine/source/Verve/Core/VEvent.h b/Engine/source/Verve/Core/VEvent.h new file mode 100644 index 000000000..7a1914f04 --- /dev/null +++ b/Engine/source/Verve/Core/VEvent.h @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEVENT_H_ +#define _VT_VEVENT_H_ + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- +class VGroup; +class VTrack; +//----------------------------------------------------------------------------- + +class VEvent : public VObject +{ + typedef VObject Parent; + +protected: + + bool mIsPlaying; + bool mTriggered; + + S32 mTriggerTime; + S32 mDuration; + +public: + + VEvent( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + virtual bool onControllerUpdate( const S32 &pTime, const S32 &pDelta ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onUpdate( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEvent ); + +public: + + // Property Methods. + + VGroup *getGroup( void ); + template inline bool getGroup( T *&pGroup ) + { + // Reference Group. + pGroup = dynamic_cast( getGroup() ); + // Validate. + return ( pGroup != NULL ); + } + + VTrack *getTrack( void ); + template inline bool getTrack( T *&pTrack ) + { + // Reference Track. + pTrack = dynamic_cast( getTrack() ); + // Validate. + return ( pTrack != NULL ); + } + + VEvent *getNextEvent( void ); + VEvent *getPreviousEvent( void ); + + inline bool isPlaying( void ) { return mIsPlaying; }; + inline S32 getTriggerTime( void ) { return mTriggerTime; }; + inline S32 getDuration( void ) { return mDuration; }; + + virtual S32 getStartTime( void ); + virtual S32 getFinishTime( void ); + + virtual void setTriggerTime( const S32 &pTime ); + virtual void setDuration( const S32 &pDuration ); + + static bool setTriggerTime( void *obj, const char *pArray, const char *data ) { static_cast( obj )->setTriggerTime( dAtoi( data ) ); return false; }; + static bool setDuration( void *obj, const char *pArray, const char *data ) { static_cast( obj )->setDuration( dAtoi( data ) ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VGroup.cpp b/Engine/source/Verve/Core/VGroup.cpp new file mode 100644 index 000000000..274d93775 --- /dev/null +++ b/Engine/source/Verve/Core/VGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VGroup ); +//----------------------------------------------------------------------------- + +VGroup::VGroup( void ) +{ + setLabel( "DefaultGroup" ); +}; \ No newline at end of file diff --git a/Engine/source/Verve/Core/VGroup.h b/Engine/source/Verve/Core/VGroup.h new file mode 100644 index 000000000..35d40dc4f --- /dev/null +++ b/Engine/source/Verve/Core/VGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VGROUP_H_ +#define _VT_VGROUP_H_ + +#ifndef _VT_VOBJECT_H_ +#include "Verve/Core/VObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VGroup : public VObject +{ + typedef VObject Parent; + +public: + + VGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VObject.cpp b/Engine/source/Verve/Core/VObject.cpp new file mode 100644 index 000000000..248ed5032 --- /dev/null +++ b/Engine/source/Verve/Core/VObject.cpp @@ -0,0 +1,489 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VObject.h" +#include "Verve/Core/VController.h" +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VObject ); +//----------------------------------------------------------------------------- + +VObject::VObject( void ) : + mController( NULL ), + mLabel( String::EmptyString ), + mEnabled( true ) +{ + // Void. +}; + +VObject::~VObject( void ) +{ + // Remove. + remove(); +} + +void VObject::initPersistFields( void ) +{ + // Don't Use Parent Fields. + // Parent::initPersistFields(); + + addProtectedField( "Enabled", TypeBool, Offset( mEnabled, VObject ), &setEnabled, &defaultProtectedGetFn, "Enable or Disable the object from playback." ); + addProtectedField( "Label", TypeRealString, Offset( mLabel, VObject ), &setLabel, &defaultProtectedGetFn, "The label this object is referenced by." ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::getObject( pLabel ); +// +// Returns the object with the given label. If no object belongs to this object +// with that label, then a NULL value is returned. +// +//----------------------------------------------------------------------------- +VObject *VObject::getObject( const String &pLabel ) +{ + VObject *node = ( VObject* )mChildNode; + while ( node ) + { + // Compare Names. + if ( node->getLabel().equal( pLabel, String::NoCase ) ) + { + // Valid. + return node; + } + + // Next Sibling. + node = ( VObject* )node->mSiblingNextNode; + } + + // Invalid. + return NULL; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::isEnabled(); +// +// Returns whether this object is enabled. +// +//----------------------------------------------------------------------------- +bool VObject::isEnabled( void ) +{ + VObject *parent = dynamic_cast( getParent() ); + if ( parent && !parent->isEnabled() ) + { + return false; + } + + return mEnabled; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPlaying(); +// +// Returns whether the root controller is currently playing. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPlaying( void ) +{ + if ( getController() ) + { + return getController()->isPlaying(); + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPaused(); +// +// Returns whether the root controller is currently paused. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPaused( void ) +{ + if ( getController() ) + { + return getController()->isPaused(); + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerStopped(); +// +// Returns whether the root controller is currently stopped. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerStopped( void ) +{ + if ( getController() ) + { + return getController()->isStopped(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerPlayingForward(); +// +// Returns whether the root controller is currently playing forward. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerPlayingForward( void ) +{ + if ( getController() ) + { + return getController()->isPlayingForward(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::isControllerLooping(); +// +// Returns whether the root controller is looping the sequence. +// +//----------------------------------------------------------------------------- +bool VObject::isControllerLooping( void ) +{ + if ( getController() ) + { + return getController()->isLooping(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerTime(); +// +// Returns the current time of the root controller. +// +//----------------------------------------------------------------------------- +S32 VObject::getControllerTime( void ) +{ + if ( getController() ) + { + return getController()->getTime(); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerTimeScale(); +// +// Returns the current timescale of the root controller. +// +//----------------------------------------------------------------------------- +F32 VObject::getControllerTimeScale( void ) +{ + if ( getController() ) + { + return getController()->getTimeScale(); + } + + return 1.f; +} + +//----------------------------------------------------------------------------- +// +// VObject::getControllerDuration(); +// +// Returns the duration of the root controller. +// +//----------------------------------------------------------------------------- +S32 VObject::getControllerDuration( void ) +{ + if ( getController() ) + { + return getController()->getDuration(); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VObject::setLabel( pLabel ); +// +// Set the label property. +// +// If the project was built using the VT_EDITOR preprocessor argument, then the +// label will not be changed if the target name is already used in the parent +// object. +// +//----------------------------------------------------------------------------- +void VObject::setLabel( const String &pLabel ) +{ +#ifdef VT_EDITOR + if ( mParentNode ) + { + // Empty Label? + if ( mLabel.isEmpty() ) + { + // Set Uniqu Label. + setLabelUnique( pLabel ); + return; + } + + for ( VObject *walk = ( VObject* )mChildNode; walk != NULL; walk = ( VObject* )walk->mSiblingNextNode ) + { + if ( walk != this ) + { + if ( pLabel == walk->getLabel() ) + { + // Exit. + return; + } + } + } + } +#endif + + // Set Label. + mLabel = pLabel; +} + +//----------------------------------------------------------------------------- +// +// VObject::setLabelUnique( pLabel ); +// +// If the label that has been passed is already in use, then a new label will +// be generated by appending an index to the label. For example: MyLabel +// becomes MyLabel0 ... MyLabelN +// +//----------------------------------------------------------------------------- +void VObject::setLabelUnique( const String &pLabel ) +{ + if ( mParentNode && pLabel.isNotEmpty() ) + { + for ( VObject *walk = ( VObject* )mChildNode; walk != NULL; walk = ( VObject* )walk->mSiblingNextNode ) + { + if ( walk != this ) + { + if ( pLabel == walk->getLabel() ) + { + // Strip Trailing Number. + S32 i = -1; + String labelBase( String::GetTrailingNumber( pLabel, i ) ); + i++; + + // Construct New Name. + String labelBuffer = String::ToString( "%s%d", labelBase.c_str(), i ); + + // Set Name. + setLabelUnique( labelBuffer ); + + // Exit. + return; + } + } + } + } + + // Set Name. + mLabel = pLabel; +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VObject::onAttach(); +// +// Callback made when this object is attached to another node. +// +//----------------------------------------------------------------------------- +void VObject::onAttach( void ) +{ + VTreeNode::onAttach(); + + // Store Controller. + mController = dynamic_cast( getRoot() ); + +#ifdef VT_EDITOR + if ( isProperlyAdded() ) + { + Con::executef( this, "onAttach" ); + } +#endif +} + +//----------------------------------------------------------------------------- +// +// VObject::onDetach(); +// +// Callback made when this object is detached from a parent node. +// +//----------------------------------------------------------------------------- +void VObject::onDetach( void ) +{ + VTreeNode::onDetach(); + + // Clear Controller. + mController = NULL; + +#ifdef VT_EDITOR + if ( isProperlyAdded() ) + { + Con::executef( this, "onDetach" ); + } +#endif +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VObject, writeFile, bool, (String fileName), (""), "( string pFileName ) - Save to a given filename.\n" + "@param pFileName The target file to write to.\n" + "@return Returns true if the write was successful." ) +{ + // Write Target File. + return VPersistence::writeFile(fileName.c_str(), object ); +} + +DefineEngineMethod( VObject, readFile, bool, (String fileName), (""), "( string pFileName ) - Clears the object and loads the new data from the given filename.\n" + "@param pFileName The target file to read from.\n" + "@return Returns true if the read was successful." ) +{ + // Read Target File. + return VPersistence::readFile(fileName.c_str(), object ); +} + +DefineEngineMethod( VObject, getRoot, S32, (),, "( void ) - Get the root object.\n" + "@return Returns the SimObjectId for the root object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->getRoot(); + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +DefineEngineMethod( VObject, getParent, S32, (),, "( void ) - Get the parent object.\n" + "@return Returns the SimObjectId for the parent object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->mParentNode; + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +DefineEngineMethod( VObject, getIndex, S32, (),, "( void ) - Get the index of this object relative to its siblings.\n" + "@return Returns the index of this object." ) +{ + return object->getIndex(); +} + +DefineEngineMethod( VObject, getCount, S32, (),, "( void ) - Get the number of child objects.\n" + "@return Returns the number of child objects." ) +{ + return object->size(); +} + +DefineEngineMethod( VObject, getObject, S32, (S32 index), (0), "( int pIndex ) - Get the object corresponding to the given index.\n" + "@param pIndex The index of the object you wish to retrieve.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VObject *objectRef = ( VObject* )object->at(index); + + // Return Object ID. + return ( objectRef ) ? objectRef->getId() : 0; +} + +DefineEngineMethod( VObject, clear, void, (),, "( void ) - Detaches and deletes all of the child objects.\n" + "@return No return value." ) +{ + // Clear Sequence Lists. + object->clear(); +} + +DefineEngineMethod( VObject, addObject, void, (SimObject* simObj), (nullAsType()), "( SimObject pObject ) - Add a child object to this node.\n" + "@param pObject The SimObjectID of the object to be added to this node.\n" + "@return No return value." ) +{ + if (simObj == nullptr) + return; + + VObject *child = dynamic_cast(simObj); + if ( child ) + { + child->addTo( object ); + } +} + +DefineEngineMethod( VObject, removeObject, void, (SimObject* simObj), (nullAsType()), "( SimObject pObject ) - Remove the target object from this node.\n" + "@param pObject The SimObjectID of the object to be removed from this node.\n" + "@return No return value." ) +{ + if (simObj == nullptr) + return; + + VObject *child = dynamic_cast(simObj); + if ( child && child->getParent() == object ) + { + child->remove(); + } +} + +DefineEngineMethod( VObject, setLabelUnique, void, (String label), (""), "( string pLabel ) - Force this label to be unique.\n" + "@param pLabel The name you wish to reference this object by.\n" + "@return No return value." ) +{ + // Set Label. + object->setLabelUnique(label); +} +#endif diff --git a/Engine/source/Verve/Core/VObject.h b/Engine/source/Verve/Core/VObject.h new file mode 100644 index 000000000..a4fe22f18 --- /dev/null +++ b/Engine/source/Verve/Core/VObject.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VOBJECT_H_ +#define _VT_VOBJECT_H_ + +#ifndef _VT_VERVECONFIG_H_ +#include "Verve/VerveConfig.h" +#endif + +#ifdef VT_EDITOR + #ifndef _SIMOBJECT_H_ + #include "console/simObject.h" + #endif + + #define VObjectRep SimObject +#else + #ifndef _CONSOLEOBJECT_H_ + #include "console/consoleObject.h" + #endif + + #define VObjectRep ConsoleObject +#endif + +#ifndef _VT_VTREENODE_H_ +#include "Verve/Core/VTreeNode.h" +#endif + +#ifndef TINYXML_INCLUDED +#include "tinyxml/tinyxml.h" +#endif + +//----------------------------------------------------------------------------- +class VController; +//----------------------------------------------------------------------------- + +class VObject : public VObjectRep, + public VTreeNode +{ + typedef VObjectRep Parent; + +protected: + + VController *mController; + + String mLabel; + bool mEnabled; + +public: + + VObject( void ); + virtual ~VObject( void ); + + static void initPersistFields( void ); + + // Reference Methods. + + VObject *getObject( const String &pLabel ); + template inline bool getObject( const String &pLabel, T *&pObject ) + { + // Reference Object. + pObject = dynamic_cast( getObject( pLabel ) ); + + // Valid? + return ( pObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VObject ); + +public: + + // Property Methods. + + inline VController *getController( void ) { return mController; }; + + inline const String &getLabel( void ) const { return mLabel; }; + bool isEnabled( void ); + + bool isControllerPlaying( void ); + bool isControllerPaused( void ); + bool isControllerStopped( void ); + bool isControllerPlayingForward( void ); + bool isControllerLooping( void ); + S32 getControllerTime( void ); + F32 getControllerTimeScale( void ); + S32 getControllerDuration( void ); + + virtual void setLabel( const String &pLabel ); + void setLabelUnique( const String &pLabel ); + inline void setEnabled( const bool &pEnabled ) { mEnabled = pEnabled; }; + + // Callback Methods. + + virtual void onAttach( void ); + virtual void onDetach( void ); + + // Static Methods. + + static bool setEnabled( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setEnabled( dAtob( pData ) ); return false; }; + static bool setLabel( void *pObject, const char *pArray, const char *pData ) { static_cast( pObject )->setLabel( pData ); return false; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VOBJECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VTrack.cpp b/Engine/source/Verve/Core/VTrack.cpp new file mode 100644 index 000000000..6783faece --- /dev/null +++ b/Engine/source/Verve/Core/VTrack.cpp @@ -0,0 +1,448 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VTrack.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VController.h" +#include "math/mMath.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VTrack ); +//----------------------------------------------------------------------------- + +VTrack::VTrack( void ) : + mNextEvent( NULL ) +{ + setLabel( "DefaultTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::onAttach(); +// +// This callback subscribes this object to the controller's event signal. +// +//----------------------------------------------------------------------------- +void VTrack::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller? + if ( getController() ) + { + // Subscribe to Updates. + getController()->getControllerUpdateSignal().notify( this, &VTrack::onControllerUpdate ); + + // Subscribe to Events. + getController()->getControllerEventSignal().notify( this, &VTrack::onControllerEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::onAttach(); +// +// This callback removes this object from the controller's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VTrack::onDetach( void ) +{ + // Valid Controller? + if ( getController() ) + { + // Remove Update Notification. + getController()->getControllerUpdateSignal().remove( this, &VTrack::onControllerUpdate ); + + // Remove Event Notification. + getController()->getControllerEventSignal().remove( this, &VTrack::onControllerEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerUpdate( pTime, pDelta ); +// +// The Next Event is integrated until has finished its execution. Once it has +// finished, the next event to be triggered becomes the Current Event. Doing +// this means that only one event is ever checked to see if it should be +// triggered. +// +//----------------------------------------------------------------------------- +void VTrack::onControllerUpdate( const S32 &pTime, const S32 &pDelta ) +{ + if ( !isEnabled() || !mNextEvent ) + { + // Don't Update. + return; + } + + // Update Next Event. + while ( !mNextEvent->onControllerUpdate( pTime, pDelta ) ) + { + // Next Event? + if ( !updateNextEvent() ) + { + // No Valid Events. + mNextEvent = NULL; + break; + } + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is reset the virtual method, onControllerReset is called. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VTrack::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { + case VController::k_EventReset : + { + + // Reset. + onControllerReset( getControllerTime(), isControllerPlayingForward() ); + + } break; + } + + // Continue Processing Events. + return true; +} + +//----------------------------------------------------------------------------- +// +// VTrack::onControllerReset( pTime, pForward ); +// +// Reset the status of the track. The Next Event is allocated here. +// +//----------------------------------------------------------------------------- +void VTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Clear Next Event. + mNextEvent = NULL; + + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *event = ( VEvent* )node; + + // Reset Event. + event->onControllerReset( pTime, pForward ); + + if ( ( event->isPlaying() ) + || ( pForward && event->getTriggerTime() >= pTime ) ) + { + if ( !mNextEvent ) + { + // Use as Next Event. + mNextEvent = event; + } + } + else if ( !pForward && pTime >= event->getTriggerTime() ) + { + VEvent *nextEvent = ( VEvent* )node->mSiblingNextNode; + if ( !nextEvent || pTime < nextEvent->getTriggerTime() ) + { + // Use as Next Event. + mNextEvent = event; + } + } + } +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::sort(); +// +// Sort the track's events by the event's trigger time. +// +//----------------------------------------------------------------------------- +void VTrack::sort( void ) +{ + const S32 count = size(); + for ( S32 j = 0; j < count; j++ ) + { + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *eventA = ( VEvent* )node; + VEvent *eventB = ( VEvent* )node->mSiblingNextNode; + if ( !eventB ) + { + // No Node. + break; + } + + // Swap? + if ( eventA->getTriggerTime() > eventB->getTriggerTime() ) + { + // Get Outer Siblings. + ITreeNode *prevNode = eventA->mSiblingPrevNode; + ITreeNode *nextNode = eventB->mSiblingNextNode; + + if ( eventA->mParentNode && eventA->mParentNode->mChildNode == eventA ) + { + // New Child Node. + eventA->mParentNode->mChildNode = eventB; + } + + // + // Move A. + eventA->mSiblingPrevNode = eventB; + eventA->mSiblingNextNode = nextNode; + + if ( nextNode ) + { + // Update Outer Sibling. + nextNode->mSiblingPrevNode = eventA; + } + + // + // Move B. + + eventB->mSiblingPrevNode = prevNode; + eventB->mSiblingNextNode = eventA; + + if ( prevNode ) + { + // Update Outer Sibling. + prevNode->mSiblingNextNode = eventB; + } + } + } + } +} + +//----------------------------------------------------------------------------- +// +// VTrack::updateNextEvent( pForward ); +// +// Point mNextEvent to the next valid event in the track's sequence. +// +//----------------------------------------------------------------------------- +bool VTrack::updateNextEvent( void ) +{ + if ( !mNextEvent ) + { + // Invalid Event. + return false; + } + + while ( ( mNextEvent = mNextEvent->getNextEvent() ) != NULL ) + { + if ( mNextEvent->isEnabled() ) + { + // Valid Event. + return true; + } + } + + // Invalid Event. + return false; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTrack::getGroup(); +// +// Returns the Track's parent group. +// +//----------------------------------------------------------------------------- +VGroup *VTrack::getGroup( void ) +{ + return dynamic_cast( mParentNode ); +} + +//----------------------------------------------------------------------------- +// +// VTrack::getNextEvent(); +// +// Returns the Event that the Track is currently observing. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getNextEvent( void ) +{ + return mNextEvent; +} + +//----------------------------------------------------------------------------- +// +// VTrack::getCurrentEvent(); +// +// Returns the Event that the Track is currently observing and playing. This +// will only ever be non-null when the track is observing an Event that has a +// non-zero duration and has been triggered. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getCurrentEvent( void ) +{ + if ( mNextEvent && mNextEvent->isPlaying() ) + { + return mNextEvent; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VTrack::getPreviousEvent(); +// +// Returns the Event that the Track was last intergrating. +// +//----------------------------------------------------------------------------- +VEvent *VTrack::getPreviousEvent( void ) +{ + if ( mNextEvent ) + { + return mNextEvent->getPreviousEvent(); + } + + if ( !isControllerPlayingForward() ) + { + return dynamic_cast( getChild() ); + } + + return dynamic_cast( getLastChild() ); +} + +//----------------------------------------------------------------------------- +// +// VTrack::calclateInterp( pTime ); +// +// This method returns the interp time between or within events. If the given +// time is between two events, the return time is: +// +// ( pTime - last_event_finish_time ) +// / ( next_event_start_time - last_event_finish_time ) +// +// If the given time is within an event, the return time is: +// +// ( pTime - event_start_time ) / ( event_duration ) +// +// The value returned here is between 0.0 and 1.0. +// +//----------------------------------------------------------------------------- +F32 VTrack::calculateInterp( S32 pTime ) +{ + if ( !isControllerPlayingForward() ) + { + return ( 1.f - _calculateInterp( pTime ) ); + } + + return _calculateInterp( pTime ); +} + +F32 VTrack::_calculateInterp( S32 pTime ) +{ + // Fetch Duration. + const S32 sequenceDuration = getControllerDuration(); + if ( sequenceDuration == 0 || pTime == sequenceDuration ) + { + // Sanity! + return 1.f; + } + + if ( !mChildNode ) + { + // Quick Interp. + return F32( pTime / sequenceDuration ); + } + + // Last Time. + S32 lastTime = 0; + + VEvent *walk = ( VEvent* )mChildNode; + while ( walk ) + { + const S32 startTime = walk->getStartTime(); + const S32 finishTime = walk->getFinishTime(); + + if ( pTime < startTime ) + { + return ( F32( pTime - lastTime ) / F32( startTime - lastTime ) ); + } + + // Update Last Time. + lastTime = startTime; + + if ( pTime < finishTime ) + { + return ( F32( pTime - lastTime ) / F32( finishTime - lastTime ) ); + } + + // Update Last Time. + lastTime = finishTime; + + // Fetch Next Node. + walk = ( VEvent* )walk->mSiblingNextNode; + } + + // Return. + return ( F32( pTime - lastTime ) / F32( sequenceDuration - lastTime ) ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Core/VTrack.h b/Engine/source/Verve/Core/VTrack.h new file mode 100644 index 000000000..eb2e576ce --- /dev/null +++ b/Engine/source/Verve/Core/VTrack.h @@ -0,0 +1,123 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTRACK_H_ +#define _VT_VTRACK_H_ + +#ifndef _VT_VCONTROLLER_H_ +#include "Verve/Core/VController.h" +#endif + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +//----------------------------------------------------------------------------- +class VGroup; +//----------------------------------------------------------------------------- + +class VTrack : public VObject +{ + typedef VObject Parent; + +public: + + // Controller Members. + + VEvent *mNextEvent; + +public: + + VTrack(); + + // Tree Methods. + + virtual void onAttach( void ); + virtual void onDetach( void ); + + // Controller Methods. + + virtual void onControllerUpdate( const S32 &pTime, const S32 &pDelta ); + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Reference Methods. + + void sort( void ); + bool updateNextEvent( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VTrack ); + +public: + + // Property Methods. + + VGroup *getGroup( void ); + template inline bool getGroup( T *&pGroup ) + { + // Reference Group. + pGroup = dynamic_cast( getGroup() ); + // Validate. + return ( pGroup != NULL ); + } + + VEvent *getNextEvent( void ); + template inline bool getNextEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getNextEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + VEvent *getCurrentEvent( void ); + template inline bool getCurrentEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getCurrentEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + VEvent *getPreviousEvent( void ); + template inline bool getPreviousEvent( T *&pEvent ) + { + // Reference Object. + pEvent = dynamic_cast( getPreviousEvent() ); + // Validate. + return ( pEvent != NULL ); + } + + F32 calculateInterp( S32 pTime ); + F32 _calculateInterp( S32 pTime ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Core/VTreeNode.cpp b/Engine/source/Verve/Core/VTreeNode.cpp new file mode 100644 index 000000000..29f4fa076 --- /dev/null +++ b/Engine/source/Verve/Core/VTreeNode.cpp @@ -0,0 +1,471 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VTreeNode.h" +#include "console/simObject.h" +#include "platform/platform.h" + +//----------------------------------------------------------------------------- + +VTreeNode::VTreeNode( void ) +{ + mParentNode = NULL; + mChildNode = NULL; + mSiblingPrevNode = NULL; + mSiblingNextNode = NULL; +} + +VTreeNode::~VTreeNode( void ) +{ + // Delete Children. + clear(); + + // Detach. + remove(); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTreeNode::clear(); +// +// Delete all child nodes. +// +//----------------------------------------------------------------------------- +void VTreeNode::clear( void ) +{ + if ( !mChildNode ) + { + return; + } + + while ( mChildNode ) + { + // Fetch Child Node. + ITreeNode *node = mChildNode; + + // Clear It. + node->clear(); + + // Detach It. + node->remove(); + + // Delete It. + SimObject *object = dynamic_cast( node ); + if ( object ) + { + object->deleteObject(); + } + else + { + delete node; + } + } +} + +//----------------------------------------------------------------------------- +// +// ITreeNode Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VTreeNode::getRoot(); +// +// Returns the root object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getRoot( void ) +{ + ITreeNode *parent = this; + while ( parent->mParentNode ) + { + parent = parent->mParentNode; + } + + return parent; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getParent(); +// +// Returns the parent object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getParent( void ) +{ + return mParentNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getChild(); +// +// Returns the first child object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getChild( void ) +{ + return mChildNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getChild(); +// +// Returns the first child object. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getLastChild( void ) +{ + // Any Nodes? + if ( !mChildNode ) + { + // Null. + return NULL; + } + + // Front Node. + ITreeNode *lastNode = mChildNode; + + // Fetch Last Node. + while ( lastNode->mSiblingNextNode ) + { + lastNode = lastNode->mSiblingNextNode; + } + + // Return. + return lastNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getPrevSibling(); +// +// Returns the previous object in the linked list. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getPrevSibling( void ) +{ + return mSiblingPrevNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getNextSibling(); +// +// Returns the next object in the linked list. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::getNextSibling( void ) +{ + return mSiblingNextNode; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::size(); +// +// Returns the number of child objects. Only includes top level. +// +//----------------------------------------------------------------------------- +int VTreeNode::size( void ) +{ + int size = 0; + + ITreeNode *node = mChildNode; + while ( node ) + { + size++; + + node = node->mSiblingNextNode; + } + + return size; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::at( pIndex ); +// +// Returns the object at the given index. +// +//----------------------------------------------------------------------------- +ITreeNode *VTreeNode::at( const int pIndex ) +{ + int index = 0; + + ITreeNode *node = mChildNode; + while ( node ) + { + if ( index++ == pIndex ) + { + return node; + } + + node = node->mSiblingNextNode; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::getIndex(); +// +// Returns the index of the object in relation to the sibling nodes. +// +//----------------------------------------------------------------------------- +int VTreeNode::getIndex( void ) +{ + if ( !inTree() ) + { + // No Index. + return 0; + } + + ITreeNode *walk = NULL; + if ( mParentNode ) + { + walk = mParentNode->mChildNode; + } + else + { + walk = this; + while ( walk->mSiblingPrevNode ) + { + // Walk Up. + walk = walk->mSiblingPrevNode; + } + } + + for ( int i = 0; walk; walk = walk->mSiblingNextNode, i++ ) + { + if ( walk == this ) + { + return i; + } + } + + AssertFatal( false, "VTreeNode::getIndex() - Node List Broken?" ); + + return 0; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::addTo( pNode ); +// +// Attach this node to the back of the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::addTo( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Already In Tree. + return; + } + + // Set Parent. + mParentNode = pNode; + + if ( !pNode->mChildNode ) + { + // Store Child Node. + pNode->mChildNode = this; + } + else + { + // Front Node. + ITreeNode *headNode = pNode->mChildNode; + + // Fetch Head Node. + while ( headNode->mSiblingNextNode ) + { + headNode = headNode->mSiblingNextNode; + } + + // Reference Next Node. + headNode->mSiblingNextNode = this; + + // Reference Previous Node. + mSiblingPrevNode = headNode; + } + + // Callback. + onAttach(); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::addToFront( pNode ); +// +// Attach this node to the front of the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::addToFront( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Already In Tree. + return; + } + + // Set Parent. + mParentNode = pNode; + + if ( !pNode->mChildNode ) + { + // Store Child Node. + pNode->mChildNode = this; + } + else + { + // First Node. + ITreeNode *childNode = pNode->mChildNode; + + // Reference Previous Node. + childNode->mSiblingPrevNode = this; + + // Reference Next Node. + mSiblingNextNode = childNode; + + // Store Child Node. + pNode->mChildNode = this; + } + + // Callback. + onAttach(); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::remove(); +// +// Detach this node from the current parent node. +// +//----------------------------------------------------------------------------- +void VTreeNode::remove( void ) +{ + if ( !inTree() ) + { + return; + } + + // Callback. + onDetach(); + + if ( mParentNode && mParentNode->mChildNode == this ) + { + // Update Parent Reference. + mParentNode->mChildNode = mSiblingNextNode; + } + + if ( mSiblingNextNode ) + { + // Update Previous Node. + mSiblingNextNode->mSiblingPrevNode = mSiblingPrevNode; + } + + if ( mSiblingPrevNode ) + { + // Update Next Node. + mSiblingPrevNode->mSiblingNextNode = mSiblingNextNode; + } + + // Remove References. + mParentNode = mSiblingPrevNode = mSiblingNextNode = NULL; +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::moveTo( pNode ); +// +// Detach this node and attach it to the target node. +// +//----------------------------------------------------------------------------- +void VTreeNode::moveTo( ITreeNode *pNode ) +{ + if ( inTree() ) + { + // Remove from Tree. + remove(); + } + + // Add to tree. + addTo( pNode ); +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::onAttach(); +// +// This method will be called when this node, or a parent node, is attached to +// a node. +// +//----------------------------------------------------------------------------- +void VTreeNode::onAttach( void ) +{ + // Notify Children. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + node->onAttach(); + } +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::onDetach(); +// +// This method will be called when this node, or a parent node, is detached. +// +//----------------------------------------------------------------------------- +void VTreeNode::onDetach( void ) +{ + // Notify Children. + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + node->onDetach(); + } +} + +//----------------------------------------------------------------------------- +// +// VTreeNode::inTree(); +// +// Returns true if the node is the a member of a node tree. +// +//----------------------------------------------------------------------------- +bool VTreeNode::inTree( void ) +{ + return !( mParentNode == NULL && + mSiblingPrevNode == NULL && + mSiblingNextNode == NULL ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Core/VTreeNode.h b/Engine/source/Verve/Core/VTreeNode.h new file mode 100644 index 000000000..459e972ca --- /dev/null +++ b/Engine/source/Verve/Core/VTreeNode.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTREENODE_H_ +#define _VT_VTREENODE_H_ + +#ifndef _VT_ITREENODE_H_ +#include "Verve/Core/ITreeNode.h" +#endif + +//----------------------------------------------------------------------------- + +class VTreeNode : public ITreeNode +{ + typedef ITreeNode Parent; + +public: + + VTreeNode( void ); + ~VTreeNode( void ); + + // Reference Methods. + + virtual void clear( void ); + + // ITreeNode Methods. + + virtual ITreeNode *getRoot( void ); + virtual ITreeNode *getParent( void ); + virtual ITreeNode *getChild( void ); + virtual ITreeNode *getLastChild( void ); + + virtual ITreeNode *getPrevSibling( void ); + virtual ITreeNode *getNextSibling( void ); + + virtual ITreeNode *at( const int pIndex ); + virtual int size( void ); + + virtual int getIndex( void ); + + virtual void addTo( ITreeNode *pNode ); + virtual void addToFront( ITreeNode *pNode ); + virtual void remove( void ); + virtual void moveTo( ITreeNode *pNode ); + + virtual void onAttach( void ); + virtual void onDetach( void ); + + virtual bool inTree( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTREENODE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.cpp b/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.cpp new file mode 100644 index 000000000..b40460871 --- /dev/null +++ b/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.cpp @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Animation/VShapeAnimationEvent.h" +#include "Verve/Extension/Animation/VShapeAnimationTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VShapeAnimationEvent ); +//----------------------------------------------------------------------------- + +VShapeAnimationEvent::VShapeAnimationEvent( void ) : + mAnimationData( String::EmptyString ), + mAutoDuration( true ) +{ + setLabel( "AnimationEvent" ); +} + +//----------------------------------------------------------------------------- + +void VShapeAnimationEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "AnimationData", TypeRealString, Offset( mAnimationData, VShapeAnimationEvent ), "The name of the Animation Sequence to play upon triggering." ); + addField( "AutoDuration", TypeBool, Offset( mAutoDuration, VShapeAnimationEvent ), "Force the Event's Duration to match the length of the Animation." ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::onTrigger( pTime, pDelta ); +// +// Play the desired animation. Also account for any offet in playtime, and +// timescale. +// +//----------------------------------------------------------------------------- +void VShapeAnimationEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::SceneObjectType *object = getSceneObject(); + VShapeAnimationTrack *track; + if ( !object || !getTrack( track ) ) + { + // Sanity! + return; + } + + // Play Animation. + VTorque::playAnimation( object, track->getThreadIndex(), mAnimationData ); + + // Set Position. + VTorque::setAnimationPosition( object, track->getThreadIndex(), getAnimationPosition( pTime + pDelta ) ); + + // Set Time Scale. + VTorque::setAnimationTimeScale( object, track->getThreadIndex(), ( ( pDelta > 0 ) ? 1.f : -1.f ) ); +} + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::onComplete( pTime, pDelta ); +// +// If the animation is cyclic, then it needs to be paused once the event has +// finished playing. +// +//----------------------------------------------------------------------------- +void VShapeAnimationEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + // Fetch Object. + VTorque::SceneObjectType *object = getSceneObject(); + VShapeAnimationTrack *track; + if ( object && VTorque::isAnimationLooping( object, mAnimationData ) && getTrack( track ) ) + { + // Pause Animation. + VTorque::pauseAnimation( object, track->getThreadIndex() ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationEvent::getAnimationPosition( pTime ); +// +// Returns the time that the animation should be positioned at, at the given +// time. This method considers whether the animation is cyclic or not and will +// return the appropriate time regardless. Time is expressed in seconds and not +// milliseconds. +// +//----------------------------------------------------------------------------- +F32 VShapeAnimationEvent::getAnimationPosition( const S32 &pTime ) +{ + // Fetch Object. + VSceneObjectTrack *track; + VTorque::SceneObjectType *object = getSceneObject(); + if ( !getTrack( track ) || !object ) + { + // Null. + return 0.f; + } + + // Fetch Interp. + F32 interp = track->calculateInterp( pTime ); + if ( !isControllerPlayingForward() ) + { + // Flip. + interp = ( 1.f - interp ); + } + + // Not Looping? + if ( !VTorque::isAnimationLooping( object, mAnimationData ) ) + { + // Return Interp. + return interp; + } + + // Fetch Sequence Duration. + const S32 duration = ( S32 )( 1000 * VTorque::getAnimationDuration( object, mAnimationData ) ); + + // Fetch Loop Interp. + const S32 loopInterp = S32( mDuration * interp ) % duration; + + return ( F32 )loopInterp / ( F32 )duration; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.h b/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.h new file mode 100644 index 000000000..9146836e9 --- /dev/null +++ b/Engine/source/Verve/Extension/Animation/VShapeAnimationEvent.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAPEANIMATIONEVENT_H_ +#define _VT_VSHAPEANIMATIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_ANIMATION_H_ +#include "Verve/Torque/TAnimation.h" +#endif + +//----------------------------------------------------------------------------- + +class VShapeAnimationEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + bool mAutoDuration; + String mAnimationData; + +public: + + VShapeAnimationEvent( void ); + + static void initPersistFields( void ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VShapeAnimationEvent ); + +public: + + // Property Methods. + + F32 getAnimationPosition( const S32 &pTime ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAPEANIMATIONEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.cpp b/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.cpp new file mode 100644 index 000000000..caeff5b38 --- /dev/null +++ b/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.cpp @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Animation/VShapeAnimationTrack.h" +#include "Verve/Extension/Animation/VShapeAnimationEvent.h" +#include "Verve/Core/VGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VShapeAnimationTrack ); +//----------------------------------------------------------------------------- + +VShapeAnimationTrack::VShapeAnimationTrack( void ) : + mThreadIndex( 0 ) +{ + setLabel( "AnimationTrack" ); +} + +//----------------------------------------------------------------------------- + +void VShapeAnimationTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "ThreadIndex", TypeS32, Offset( mThreadIndex, VShapeAnimationTrack ), "The index of the Animation Thread to play." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VShapeAnimationTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, or stops playing, then the animation will cease to +// play. If the controller resumes play, the animation will continue. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VShapeAnimationTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Play Animation. + VTorque::setAnimationTimeScale( getSceneObject(), mThreadIndex, ( ( isControllerPlayingForward() ) ? 1.f : -1.f ) ); + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Stop Animation. + VTorque::setAnimationTimeScale( getSceneObject(), mThreadIndex, 0.f ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VShapeAnimationTrack::onControllerReset( pTime, pForward ); +// +// Reset the animation state of the target object. If there is a Next Event, +// then the animation is positioned accordingly. +// +//----------------------------------------------------------------------------- +void VShapeAnimationTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + VTorque::SceneObjectType *object = getSceneObject(); + if ( !object ) + { + // Parent Call. + Parent::onControllerReset( pTime, pForward ); + return; + } + + VShapeAnimationEvent *event; + if ( getCurrentEvent( event ) ) + { + // Stop Animation. + VTorque::stopAnimation( object, mThreadIndex ); + } + + // Parent Call. + Parent::onControllerReset( pTime, pForward ); + + if ( getCurrentEvent( event ) ) + { + // Play Animation. + VTorque::playAnimation( object, mThreadIndex, event->mAnimationData ); + + // Set Position. + VTorque::setAnimationPosition( object, mThreadIndex, event->getAnimationPosition( pTime ) ); + + // Stop Animation. + VTorque::setAnimationTimeScale( object, mThreadIndex, 0.f ); + } +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VShapeAnimationTrack, updateTrack, void, (),, "( void ) - Update the Track.\n" + "@return No return value." ) +{ + for ( ITreeNode *node = object->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VShapeAnimationEvent *currEvent = ( VShapeAnimationEvent* )node; + VShapeAnimationEvent *nextEvent = ( VShapeAnimationEvent* )node->mSiblingNextNode; + if ( !currEvent->mAutoDuration ) + { + // Skip. + continue; + } + + if ( VTorque::isAnimationLooping( object->getSceneObject(), currEvent->mAnimationData ) ) + { + if ( !nextEvent ) + { + // Update Duration. + currEvent->setDuration( object->getControllerDuration() - currEvent->getTriggerTime() ); + } + else + { + // Update Duration. + currEvent->setDuration( mAbs( nextEvent->getTriggerTime() - currEvent->getTriggerTime() ) ); + } + } + else + { + // Update Duration. + currEvent->setDuration( ( S32 )( 1000 * VTorque::getAnimationDuration( object->getSceneObject(), currEvent->mAnimationData ) ) ); + } + } +} +#endif diff --git a/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.h b/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.h new file mode 100644 index 000000000..3b9cf7bce --- /dev/null +++ b/Engine/source/Verve/Extension/Animation/VShapeAnimationTrack.h @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSHAPEANIMATIONTRACK_H_ +#define _VT_VSHAPEANIMATIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_ANIMATION_H_ +#include "Verve/Torque/TAnimation.h" +#endif + +//----------------------------------------------------------------------------- + +class VShapeAnimationTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + + U32 mThreadIndex; + +public: + + VShapeAnimationTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VShapeAnimationTrack ); + +public: + + inline U32 &getThreadIndex( void ) { return mThreadIndex; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSHAPEANIMATIONTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraGroup.cpp b/Engine/source/Verve/Extension/Camera/VCameraGroup.cpp new file mode 100644 index 000000000..14b2cb97c --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraGroup.cpp @@ -0,0 +1,224 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraGroup.h" +#include "Verve/Extension/Camera/VCameraTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraGroup ); +//----------------------------------------------------------------------------- + +VCameraGroup *VCameraGroup::mActiveGroup = NULL; +VCameraGroup::CameraChangeSignal VCameraGroup::mCameraChangeSignal; + +//----------------------------------------------------------------------------- + +VCameraGroup::VCameraGroup( void ) +{ + setLabel( "CameraGroup" ); +}; + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onAttach(); +// +// This callback subscribes this object to the controller's event signal. +// +//----------------------------------------------------------------------------- +void VCameraGroup::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller? + if ( getController() ) + { + // Subscribe to Events. + getController()->getControllerEventSignal().notify( this, &VCameraGroup::onControllerEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onAttach(); +// +// This callback removes this object from the controller's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VCameraGroup::onDetach( void ) +{ + // Valid Controller? + if ( getController() ) + { + // Remove Event Notification. + getController()->getControllerEventSignal().remove( this, &VCameraGroup::onControllerEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VCameraGroup::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VCameraGroup::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { +#ifdef VT_EDITOR + case VController::k_EventPause : +#endif + case VController::k_EventStop : + { + + // Clear the Camera. + clearActiveGroup(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraGroup::setActive(); +// +// Set this Group to Active. +// +//----------------------------------------------------------------------------- +void VCameraGroup::setActive( void ) +{ + // Set Active. + setActiveGroup( this ); +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::clearActiveGroup(); +// +// Clear the Active Camera. +// +//----------------------------------------------------------------------------- +void VCameraGroup::clearActiveGroup( void ) +{ + if ( mActiveGroup ) + { + // Deactivate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventDeactivate ); + } + + // Store. + mActiveGroup = NULL; + + // Clear Camera Object. + VTorque::setCamera( NULL ); + + // Change Signal. + getCameraChangeSignal().trigger( NULL ); +} + +//----------------------------------------------------------------------------- +// +// VCameraGroup::setActiveGroup( pCameraGroup ); +// +// Change the current camera group. The actual camera object is the object that +// the group references. +// +// A NULL value of pCameraGroup will clear the active camera, which generally +// reverts to the connection's control object. The camera is also cleared when +// the Controller stops playing. +// +//----------------------------------------------------------------------------- +void VCameraGroup::setActiveGroup( VCameraGroup *pCameraGroup ) +{ + // Change Camera? + if ( pCameraGroup == mActiveGroup || + pCameraGroup && !pCameraGroup->isEnabled() ) + { + // Invalid Target. + return; + } + + if ( mActiveGroup ) + { + // Deactivate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventDeactivate ); + } + + // Store. + mActiveGroup = pCameraGroup; + + if ( mActiveGroup ) + { + // Set Camera Object. + VTorque::setCamera( mActiveGroup->getSceneObject() ); + + // Activate Signal. + mActiveGroup->getCameraEventSignal().trigger( k_EventActivate ); + } + else + { + // Clear Camera Object. + VTorque::setCamera( NULL ); + } + + // Change Signal. + getCameraChangeSignal().trigger( mActiveGroup ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraGroup.h b/Engine/source/Verve/Extension/Camera/VCameraGroup.h new file mode 100644 index 000000000..eea9a2f7b --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraGroup.h @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERAGROUP_H_ +#define _VT_VCAMERAGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +#ifndef _VT_VCONTROLLER_H +#include "Verve/Core/VController.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraGroup; + +//----------------------------------------------------------------------------- + +class VCameraGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + enum eCameraEventType + { + k_EventActivate, + k_EventDeactivate, + }; + + typedef Signal CameraEventSignal; + typedef Signal CameraChangeSignal; + +protected: + + static VCameraGroup *mActiveGroup; + static CameraChangeSignal mCameraChangeSignal; + + CameraEventSignal mCameraEventSignal; + +public: + + VCameraGroup( void ); + + // Tree Methods. + + void onAttach( void ); + void onDetach( void ); + + // Controller Methods. + + bool onControllerEvent( VController::eControllerEventType pEvent ); + + // Camera Methods. + + inline bool isActive( void ) { return ( bool )( this == getActiveGroup() ); }; + inline VCameraGroup *getActiveGroup( void ) { return mActiveGroup; }; + + void setActive( void ); + + static void clearActiveGroup( void ); + static void setActiveGroup( VCameraGroup *pCameraGroup ); + + // Signal Methods. + + static inline CameraChangeSignal &getCameraChangeSignal( void ) { return mCameraChangeSignal; }; + inline CameraEventSignal &getCameraEventSignal( void ) { return mCameraEventSignal; }; + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERAGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.cpp b/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.cpp new file mode 100644 index 000000000..88c528d27 --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.cpp @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Camera/VCameraGroup.h" +#include "Verve/Extension/Camera/VCameraShakeEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraShakeEvent ); +//----------------------------------------------------------------------------- + +VCameraShakeEvent::VCameraShakeEvent( void ) : + mAmplitude( Point3F::Zero ), + mFalloff( 10.f ), + mFrequency( Point3F::Zero ) +{ + // Clear Label. + setLabel( "CameraShakeEvent" ); +} + +void VCameraShakeEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Amplitude", TypePoint3F, Offset( mAmplitude, VCameraShakeEvent ), "Amplitude of the Camera Shake event." ); + addField( "Falloff", TypeF32, Offset( mFalloff, VCameraShakeEvent ), "Falloff of the Camera Shake event." ); + addField( "Frequency", TypePoint3F, Offset( mFrequency, VCameraShakeEvent ), "Frequency of the Camera Shake event." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeEvent::onTrigger( pTime, pDelta ); +// +// Start shaking the camera. Also account for any offet in playtime, and +// timescale. +// +//----------------------------------------------------------------------------- +void VCameraShakeEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Group. + VCameraGroup *group; + if ( !getGroup( group ) || !group->isActive() ) + { + // Inactive. + return; + } + + // Duration. + //const F32 duration = ( mDuration - mAbs( pTime - getStartTime() ) ) / ( 1000.f * mFabs( getControllerTimeScale() ) ); + const F32 duration = ( mDuration - mAbs( pTime - getStartTime() ) ) / 1000.f; + + // Shake Camera. + VTorque::startCameraShake( duration, mFalloff, mAmplitude, mFrequency ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.h b/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.h new file mode 100644 index 000000000..9a8af7899 --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraShakeEvent.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERASHAKEEVENT_H_ +#define _VT_VCAMERASHAKEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraShakeEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VectorF mAmplitude; + F32 mFalloff; + VectorF mFrequency; + +public: + + VCameraShakeEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraShakeEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERASHAKEEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.cpp b/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.cpp new file mode 100644 index 000000000..4f6fb5e81 --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraShakeTrack.h" +#include "Verve/Extension/Camera/VCameraShakeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraShakeTrack ); +//----------------------------------------------------------------------------- + +VCameraShakeTrack::VCameraShakeTrack( void ) +{ + setLabel( "CameraShakeTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incoming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VCameraShakeTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + // Parent Call. + if ( !Parent::onCameraEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch( pEvent ) + { + case VCameraGroup::k_EventActivate : + { + + VCameraShakeEvent *event; + if ( getCurrentEvent( event ) ) + { + // Re-Trigger Event. + event->onTrigger( getControllerTime(), 0 ); + } + + } break; + + case VCameraGroup::k_EventDeactivate : + { + + // Stop Camera Shake. + VTorque::stopCameraShake(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraShakeTrack::onControllerReset( pTime, pForward ); +// +// Stop all camera shake events. +// +//----------------------------------------------------------------------------- +void VCameraShakeTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + // Stop Camera Shake. + VTorque::stopCameraShake(); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.h b/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.h new file mode 100644 index 000000000..2c09900bc --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraShakeTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERASHAKETRACK_H_ +#define _VT_VCAMERASHAKETRACK_H_ + +#ifndef _VT_VCAMERATRACK_H_ +#include "Verve/Extension/Camera/VCameraTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraShakeTrack : public VCameraTrack +{ + typedef VCameraTrack Parent; + +public: + + VCameraShakeTrack( void ); + + // Camera Methods. + + bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Controller Methods. + + void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraShakeTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERASHAKETRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraTrack.cpp b/Engine/source/Verve/Extension/Camera/VCameraTrack.cpp new file mode 100644 index 000000000..47e734af9 --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraTrack.cpp @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Camera/VCameraTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VCameraTrack ); +//----------------------------------------------------------------------------- + +VCameraTrack::VCameraTrack( void ) +{ + setLabel( "CameraTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Tree Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onAttach(); +// +// This callback subscribes this object to the Camera Group's event signal. +// +//----------------------------------------------------------------------------- +void VCameraTrack::onAttach( void ) +{ + Parent::onAttach(); + + // Valid Controller & Group? + VCameraGroup *group; + if ( getController() && getGroup( group ) ) + { + // Add Event Notification. + group->getCameraEventSignal().notify( this, &VCameraTrack::onCameraEvent ); + } +} + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onAttach(); +// +// This callback removes this object from the Camera Group's event signal +// notification list. +// +//----------------------------------------------------------------------------- +void VCameraTrack::onDetach( void ) +{ + // Valid Controller & Group? + VCameraGroup *group; + if ( getController() && getGroup( group ) ) + { + // Clear Event Notification. + group->getCameraEventSignal().remove( this, &VCameraTrack::onCameraEvent ); + } + + Parent::onDetach(); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VCameraTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incomming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VCameraTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + if ( !getController() ) + { + AssertFatal( false, "VCameraTrack::onControllerEvent() - Invalid Controller." ); + return false; + } + + // Ok. + return true; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Camera/VCameraTrack.h b/Engine/source/Verve/Extension/Camera/VCameraTrack.h new file mode 100644 index 000000000..6866638a2 --- /dev/null +++ b/Engine/source/Verve/Extension/Camera/VCameraTrack.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VCAMERATRACK_H_ +#define _VT_VCAMERATRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_VCAMERAGROUP_H_ +#include "Verve/Extension/Camera/VCameraGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VCameraTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VCameraTrack( void ); + + // Tree Methods. + + void onAttach( void ); + void onDetach( void ); + + // Camera Methods. + + virtual bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Console Declaration. + + DECLARE_CONOBJECT( VCameraTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VCAMERATRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VDirectorEvent.cpp b/Engine/source/Verve/Extension/Director/VDirectorEvent.cpp new file mode 100644 index 000000000..9030b4018 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorEvent.cpp @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Director/VDirectorEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorEvent ); +//----------------------------------------------------------------------------- + +VDirectorEvent::VDirectorEvent( void ) : + mTarget( String::EmptyString ) +{ + // Void. +} + +void VDirectorEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Target", TypeRealString, Offset( mTarget, VDirectorEvent ), "The name of the CameraGroup that will be activated upon triggering." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VDirectorEvent::onTrigger( pTime, pDelta ); +// +// Cut the camera to the target group. +// +//----------------------------------------------------------------------------- +void VDirectorEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Controller. + VController *controller = getController(); + + // Valid Target? + VCameraGroup *targetGroup = NULL; + if ( !controller->getObject( mTarget, targetGroup ) ) + { + Con::warnf( "VDirectorEvent::onTrigger() - Invalid Target Group specified." ); + return; + } + + // Change Camera. + targetGroup->setActive(); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VDirectorEvent.h b/Engine/source/Verve/Extension/Director/VDirectorEvent.h new file mode 100644 index 000000000..e890e5a06 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorEvent.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTOREVENT_H_ +#define _VT_VDIRECTOREVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_VCAMERAGROUP_H_ +#include "Verve/Extension/Camera/VCameraGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + String mTarget; + +public: + + VDirectorEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTOREVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VDirectorGroup.cpp b/Engine/source/Verve/Extension/Director/VDirectorGroup.cpp new file mode 100644 index 000000000..4f8934124 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorGroup.cpp @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VDirectorGroup.h" +#include "Verve/Extension/Director/VDirectorTrack.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorGroup ); +//----------------------------------------------------------------------------- + +VDirectorGroup::VDirectorGroup( void ) : + mActiveCamera( NULL ) +{ + setLabel( "DirectorGroup" ); +}; + +//----------------------------------------------------------------------------- +// +// VDirectorGroup::getDirectorTrack(); +// +// Returns the DirectorTrack reference. +// +//----------------------------------------------------------------------------- +VDirectorTrack *VDirectorGroup::getDirectorTrack( void ) +{ + for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + if ( VDirectorTrack *track = dynamic_cast( node ) ) + { + // Return Track. + return track; + } + } + + // Invalid Track. + return NULL; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VDirectorGroup.h b/Engine/source/Verve/Extension/Director/VDirectorGroup.h new file mode 100644 index 000000000..bcf9b7a44 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorGroup.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTORGROUP_H_ +#define _VT_VDIRECTORGROUP_H_ + +#ifndef _VT_VGROUP_H_ +#include "Verve/Core/VGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorTrack; +class VCameraGroup; + +//----------------------------------------------------------------------------- + +class VDirectorGroup : public VGroup +{ + typedef VGroup Parent; + +protected: + + // Camera. + VCameraGroup *mActiveCamera; + +public: + + VDirectorGroup( void ); + + VDirectorTrack *getDirectorTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTORGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VDirectorTrack.cpp b/Engine/source/Verve/Extension/Director/VDirectorTrack.cpp new file mode 100644 index 000000000..0867ac1f1 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VDirectorTrack.h" + +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VDirectorTrack ); +//----------------------------------------------------------------------------- + +VDirectorTrack::VDirectorTrack( void ) +{ + setLabel( "DirectorTrack" ); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VDirectorTrack, updateTrack, void, (),, "( void ) - Update the Track.\n" + "@return No return value." ) +{ + for ( ITreeNode *node = object->mChildNode; node != NULL; node = node->mSiblingNextNode ) + { + VEvent *currEvent = ( VEvent* )node; + VEvent *nextEvent = ( VEvent* )node->mSiblingNextNode; + + if ( !nextEvent ) + { + // Update Duration. + currEvent->setDuration( object->getControllerDuration() - currEvent->getTriggerTime() ); + } + else + { + // Update Duration. + currEvent->setDuration( mAbs( nextEvent->getTriggerTime() - currEvent->getTriggerTime() ) ); + } + } +} +#endif diff --git a/Engine/source/Verve/Extension/Director/VDirectorTrack.h b/Engine/source/Verve/Extension/Director/VDirectorTrack.h new file mode 100644 index 000000000..98b36a410 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VDirectorTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VDIRECTORTRACK_H_ +#define _VT_VDIRECTORTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VDirectorTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VDirectorTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VDirectorTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VDIRECTORTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSceneJumpEvent.cpp b/Engine/source/Verve/Extension/Director/VSceneJumpEvent.cpp new file mode 100644 index 000000000..09df231b1 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSceneJumpEvent.cpp @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Extension/Director/VSceneJumpEvent.h" +#include "Verve/Extension/Director/VDirectorGroup.h" +#include "Verve/Extension/Director/VDirectorTrack.h" +#include "Verve/Extension/Director/VDirectorEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneJumpEvent ); +//----------------------------------------------------------------------------- + +VSceneJumpEvent::VSceneJumpEvent( void ) : + mTarget( String::EmptyString ) +{ + setLabel( "SceneJumpEvent" ); +} + +void VSceneJumpEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Target", TypeRealString, Offset( mTarget, VSceneJumpEvent ), "The name of the Scene that the controller will jump to upon triggering." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneJumpEvent::onTrigger( pTime, pDelta ); +// +// Tell the controller to jump to a new scene. +// +//----------------------------------------------------------------------------- +void VSceneJumpEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VDirectorTrack *track = getController()->getDirectorTrack(); + if ( !track ) + { + // Invalid Track. + return; + } + + // Get Event. + VDirectorEvent *event; + if ( !track->getObject( mTarget, event ) ) + { + // Can't Jump. + return; + } + + // Go To Scene. + getController()->jump( VController::k_JumpTime, event->getTriggerTime() ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSceneJumpEvent.h b/Engine/source/Verve/Extension/Director/VSceneJumpEvent.h new file mode 100644 index 000000000..bf7b597bf --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSceneJumpEvent.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEJUMPEVENT_H_ +#define _VT_VSCENEJUMPEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneJumpEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + String mTarget; + +public: + + VSceneJumpEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneJumpEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEJUMPEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSceneJumpTrack.cpp b/Engine/source/Verve/Extension/Director/VSceneJumpTrack.cpp new file mode 100644 index 000000000..2a6e290d8 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSceneJumpTrack.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VSceneJumpTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneJumpTrack ); +//----------------------------------------------------------------------------- + +VSceneJumpTrack::VSceneJumpTrack( void ) +{ + setLabel( "SceneJumpTrack" ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSceneJumpTrack.h b/Engine/source/Verve/Extension/Director/VSceneJumpTrack.h new file mode 100644 index 000000000..fefb4e4f6 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSceneJumpTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEJUMPTRACK_H_ +#define _VT_VSCENEJUMPTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneJumpTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSceneJumpTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneJumpTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEJUMPTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSlowMoEvent.cpp b/Engine/source/Verve/Extension/Director/VSlowMoEvent.cpp new file mode 100644 index 000000000..3427bda43 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSlowMoEvent.cpp @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Extension/Director/VSlowMoEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSlowMoEvent ); +//----------------------------------------------------------------------------- + +VSlowMoEvent::VSlowMoEvent( void ) : + mTimeScale( 1.f ), + mTimeScaleTickDelta( 0.f ) +{ + setLabel( "SlowMoEvent" ); +} + +void VSlowMoEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "TimeScale", TypeF32, Offset( mTimeScale, VSlowMoEvent ), "The Time Scale to be applied to the Root Controller." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onTrigger( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Instant Update? + if ( getDuration() == 0 ) + { + // Apply & Return. + controller->setTimeScale( mTimeScale ); + return; + } + + // Determine the Number of Ticks. + const F32 tickCount = ( ( F32 )getDuration() ) / TickMs; + + // Determine the Tick Delta. + mTimeScaleTickDelta = ( mTimeScale - controller->getTimeScale() ) / tickCount; +} + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onUpdate( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onUpdate( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onUpdate( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Fetch Current Time Scale. + const F32 timeScale = controller->getTimeScale(); + + // Apply Update. + controller->setTimeScale( timeScale + mTimeScaleTickDelta ); +} + +//----------------------------------------------------------------------------- +// +// VSlowMoEvent::onComplete( pTime, pDelta ); +// +// +// +//----------------------------------------------------------------------------- +void VSlowMoEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onComplete( pTime, pDelta ); + + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return; + } + + // Tidy Up. + controller->setTimeScale( mTimeScale ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSlowMoEvent.h b/Engine/source/Verve/Extension/Director/VSlowMoEvent.h new file mode 100644 index 000000000..1cdf75889 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSlowMoEvent.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSLOWMOEVENT_H_ +#define _VT_VSLOWMOEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VSlowMoEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + F32 mTimeScale; + F32 mTimeScaleTickDelta; + +public: + + VSlowMoEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onUpdate( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSlowMoEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSLOWMOEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSlowMoTrack.cpp b/Engine/source/Verve/Extension/Director/VSlowMoTrack.cpp new file mode 100644 index 000000000..094acfa5e --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSlowMoTrack.cpp @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Director/VSlowMoTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSlowMoTrack ); +//----------------------------------------------------------------------------- + +VSlowMoTrack::VSlowMoTrack( void ) +{ + setLabel( "SlowMoTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSlowMoTrack::onControllerEvent( pEvent ); +// +// ... +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VSlowMoTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventStop : + { + + // Reset Time Scale. + getController()->setTimeScale( ( isControllerPlayingForward() ) ? 1.f : -1.f ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VSlowMoTrack::onControllerReset( pTime, pForward ); +// +// ... +// +//----------------------------------------------------------------------------- +void VSlowMoTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Parent Reset. + Parent::onControllerReset( pTime, pForward ); + + // Reset Time Scale. + getController()->setTimeScale( ( pForward ) ? 1.f : -1.f ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Director/VSlowMoTrack.h b/Engine/source/Verve/Extension/Director/VSlowMoTrack.h new file mode 100644 index 000000000..143203c99 --- /dev/null +++ b/Engine/source/Verve/Extension/Director/VSlowMoTrack.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSLOWMOTRACK_H_ +#define _VT_VSLOWMOTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VSlowMoTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSlowMoTrack( void ); + + // Controller Methods. + + bool onControllerEvent( VController::eControllerEventType pEvent ); + void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSlowMoTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSLOWMOTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/GUI/VFadeEvent.cpp b/Engine/source/Verve/Extension/GUI/VFadeEvent.cpp new file mode 100644 index 000000000..c8d0db6c0 --- /dev/null +++ b/Engine/source/Verve/Extension/GUI/VFadeEvent.cpp @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/GUI/VFadeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeEvent ); +//----------------------------------------------------------------------------- + +VFadeEvent::VFadeEvent( void ) +{ + setLabel( "FadeEvent" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeEvent::onTrigger( pTime, pDelta ); +// +// Start the fade sequence if a valid fade control can be found. +// +//----------------------------------------------------------------------------- +void VFadeEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + // Start Fade. + fadeControl->start( getFadeType(), mDuration ); + + // Set Elapsed Time. + fadeControl->mElapsedTime = mAbs( pTime - getStartTime() ); +} + +//----------------------------------------------------------------------------- +// +// VFadeEvent::onComplete( pTime, pDelta ); +// +// Tidy up the fade control once the event has finished. +// +//----------------------------------------------------------------------------- +void VFadeEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + // Set Elapsed Time. + fadeControl->mElapsedTime = mDuration; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeEvent::getFadeType(); +// +// Returns the type of fade (in or out) that this event will use. Zero and Even +// indices will Fade Out, while Odd numbers will Fade In. +// +//----------------------------------------------------------------------------- +VFadeControl::eFadeType VFadeEvent::getFadeType( void ) +{ + if ( !isControllerPlayingForward() ) + { + return ( getIndex() % 2 == 0 ) ? VFadeControl::k_TypeOut : VFadeControl::k_TypeIn; + } + + return ( getIndex() % 2 == 0 ) ? VFadeControl::k_TypeIn : VFadeControl::k_TypeOut; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/GUI/VFadeEvent.h b/Engine/source/Verve/Extension/GUI/VFadeEvent.h new file mode 100644 index 000000000..78c8d7c5f --- /dev/null +++ b/Engine/source/Verve/Extension/GUI/VFadeEvent.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADEEVENT_H_ +#define _VT_VFADEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_VFADECONTROL_H_ +#include "Verve/GUI/VFadeControl.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VFadeEvent( void ); + + // Callback Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeEvent ); + +public: + + VFadeControl::eFadeType getFadeType( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADEEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/GUI/VFadeTrack.cpp b/Engine/source/Verve/Extension/GUI/VFadeTrack.cpp new file mode 100644 index 000000000..e293672db --- /dev/null +++ b/Engine/source/Verve/Extension/GUI/VFadeTrack.cpp @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/GUI/VFadeTrack.h" +#include "Verve/Extension/GUI/VFadeEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeTrack ); +//----------------------------------------------------------------------------- + +VFadeTrack::VFadeTrack( void ) +{ + setLabel( "FadeTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VFadeTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, or stops playing, then the fade control will cease +// playing. If the controller resumes play, the fade control will continue. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VFadeTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch the next Event. + VFadeEvent *event; + if ( !getNextEvent( event ) ) + { + // No Event. + return true; + } + + // Fetch GUI Control. + VFadeControl *fadeControl = dynamic_cast( Sim::findObject( "VFadeControlGui" ) ); + if ( !fadeControl ) + { + // No Control. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay: + { + // Play? + const S32 &time = getControllerTime(); + fadeControl->mActive = ( time > event->getTriggerTime() + && time < event->getFinishTime() ) ; + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Pause. + fadeControl->mActive = false; + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VFadeTrack::onControllerReset( pTime, pForward ); +// +// Reset the fade state of the fade control. +// +//----------------------------------------------------------------------------- +void VFadeTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + Parent::onControllerReset( pTime, pForward ); + + // Fetch GUI Control. + VFadeControl *fadeControl; + if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) ) + { + // Invalid. + return; + } + + VFadeEvent *event; + if ( !getNextEvent( event ) ) + { + // No Events. + return; + } + + // Apply Settings. + fadeControl->mActive = false; + fadeControl->mFadeType = event->getFadeType(); + fadeControl->mDuration = event->getDuration(); + fadeControl->mElapsedTime = getMax( pTime - event->getTriggerTime(), 0 ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/GUI/VFadeTrack.h b/Engine/source/Verve/Extension/GUI/VFadeTrack.h new file mode 100644 index 000000000..87ca4b9d8 --- /dev/null +++ b/Engine/source/Verve/Extension/GUI/VFadeTrack.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADETRACK_H_ +#define _VT_VFADETRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VFadeTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADETRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.cpp b/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.cpp new file mode 100644 index 000000000..c08156e49 --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereGroup ); +//----------------------------------------------------------------------------- + +VSpawnSphereGroup::VSpawnSphereGroup( void ) +{ + setLabel( "SpawnSphereGroup" ); +}; \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.h b/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.h new file mode 100644 index 000000000..5a92713ca --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHEREGROUP_H_ +#define _VT_VSPAWNSPHEREGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VSpawnSphereGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHEREGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp new file mode 100644 index 000000000..92218060a --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.cpp @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h" +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereSpawnTargetEvent ); +//----------------------------------------------------------------------------- + +VSpawnSphereSpawnTargetEvent::VSpawnSphereSpawnTargetEvent( void ) +{ + setLabel( "SpawnTargetEvent" ); +} + +void VSpawnSphereSpawnTargetEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetEvent::onTrigger( pTime, pDelta ); +// +// Spawn the Target. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Track. + VSpawnSphereSpawnTargetTrack *track; + if ( !getTrack( track ) ) + { + return; + } + + // Spawn the Target. + track->spawnTarget(); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h new file mode 100644 index 000000000..60b39952d --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetEvent.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ +#define _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_SPAWNSPHERE_H_ +#include "Verve/Torque/TSpawnSphere.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereSpawnTargetEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; +public: + + VSpawnSphereSpawnTargetEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereSpawnTargetEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHERESPAWNTARGETEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp new file mode 100644 index 000000000..d0cc2930a --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.cpp @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h" +#include "Verve/Torque/TSpawnSphere.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSpawnSphereSpawnTargetTrack ); +//----------------------------------------------------------------------------- + +VSpawnSphereSpawnTargetTrack::VSpawnSphereSpawnTargetTrack( void ) +{ + setLabel( "SpawnTargetTrack" ); +} + +void VSpawnSphereSpawnTargetTrack::initPersistFields( void ) +{ + // Parent Call. + Parent::initPersistFields(); + + addField( "DespawnOnLoop", TypeBool, Offset( mDespawnOnLoop, VSpawnSphereSpawnTargetTrack ), "Despawn all targets when the Controller loops?" ); + addField( "DespawnOnStop", TypeBool, Offset( mDespawnOnStop, VSpawnSphereSpawnTargetTrack ), "Despawn all targets when the Controller stops playing?" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::onControllerEvent( pEvent ); +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VSpawnSphereSpawnTargetTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventLoop : + { + if ( mDespawnOnLoop ) + { + despawnTargets(); + } + + } break; + + case VController::k_EventStop : + { + if ( mDespawnOnStop ) + { + despawnTargets(); + } + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Spawn Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::spawnTarget( pTime, pForward ); +// +// Spawn an Object. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetTrack::spawnTarget( void ) +{ + VTorque::SpawnSphereType *object; + if ( !getSceneObject( object ) ) + { + return; + } + + // Spawn the Object. + SimObject *spawnedObject = object->spawnObject(); + + // Scene Object? + VTorque::SceneObjectType *sceneObject = dynamic_cast( spawnedObject ); + if ( sceneObject ) + { + sceneObject->setPosition( object->getPosition() ); + } + + // Valid? + if ( spawnedObject ) + { + // Add Reference. + mSpawnList.addObject( spawnedObject ); + } +} + +//----------------------------------------------------------------------------- +// +// VSpawnSphereSpawnTargetTrack::despawnTargets(); +// +// Despawn all of the objects spawned by this track. +// +//----------------------------------------------------------------------------- +void VSpawnSphereSpawnTargetTrack::despawnTargets( void ) +{ + while( mSpawnList.size() > 0 ) + { + // Fetch the Last Object + SimObject *object = mSpawnList.last(); + // Remove it. + mSpawnList.popObject(); + + // Delete the Object. + object->deleteObject(); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h new file mode 100644 index 000000000..0df6f2ae5 --- /dev/null +++ b/Engine/source/Verve/Extension/Game/VSpawnSphereSpawnTargetTrack.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ +#define _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VSpawnSphereSpawnTargetTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +protected: + + SimSet mSpawnList; + + bool mDespawnOnStop; + bool mDespawnOnLoop; + +public: + + VSpawnSphereSpawnTargetTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + + // Spawn Methods. + + virtual void spawnTarget( void ); + virtual void despawnTargets( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSpawnSphereSpawnTargetTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSPAWNSPHERESPAWNTARGETTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp new file mode 100644 index 000000000..94f34c350 --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.cpp @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectAnimationEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectAnimationEvent ); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +VLightObjectAnimationEvent::VLightObjectAnimationEvent( void ) : + mAnimationData( NULL ) +{ + setLabel( "AnimationEvent" ); +} + +void VLightObjectAnimationEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "AnimationData", TYPEID(), Offset( mAnimationData, VLightObjectAnimationEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationEvent::onTrigger( pTime, pDelta ); +// +// When this Event is triggered the light object will begin to play the target +// animation. +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Play the Animation. + VTorque::playAnimation( lightObject, mAnimationData ); + } +} + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationEvent::onComplete( pTime, pDelta ); +// +// The current animation played by the light object will be paused when this +// Event completes its updates. +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationEvent::onComplete( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Pause the Animation. + VTorque::pauseAnimation( lightObject ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.h b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.h new file mode 100644 index 000000000..18162ff2c --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationEvent.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTANIMATIONEVENT_H_ +#define _VT_VLIGHTOBJECTANIMATIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectAnimationEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + SimObjectPtr mAnimationData; + +public: + + VLightObjectAnimationEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + virtual void onComplete( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectAnimationEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTANIMATIONEVENT_H_ diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp new file mode 100644 index 000000000..fe2455f4f --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.cpp @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectAnimationTrack.h" +#include "Verve/Extension/LightObject/VLightObjectAnimationEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectAnimationTrack ); +//----------------------------------------------------------------------------- + +VLightObjectAnimationTrack::VLightObjectAnimationTrack( void ) +{ + setLabel( "AnimationTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationTrack::onControllerEvent( pEvent ); +// +// +// +//----------------------------------------------------------------------------- +bool VLightObjectAnimationTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( !getSceneObject( lightObject ) ) + { + // Skip. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Play Animation? + VLightObjectAnimationEvent *event; + if ( getCurrentEvent( event ) ) + { + // Play. + VTorque::playAnimation( lightObject ); + } + + } break; + + case VController::k_EventPause : + case VController::k_EventStop : + { + + // Stop the Animation. + VTorque::pauseAnimation( lightObject ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VLightObjectAnimationTrack::onControllerReset( pTime, pForward ); +// +// +// +//----------------------------------------------------------------------------- +void VLightObjectAnimationTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + // Fetch the Light Object. + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Stop the Animation. + VTorque::pauseAnimation( lightObject ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.h b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.h new file mode 100644 index 000000000..6485e8428 --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectAnimationTrack.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTANIMATIONTRACK_H_ +#define _VT_VLIGHTOBJECTANIMATIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectAnimationTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VLightObjectAnimationTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectAnimationTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTANIMATIONTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.cpp b/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.cpp new file mode 100644 index 000000000..9db010fc2 --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectGroup ); +//----------------------------------------------------------------------------- + +VLightObjectGroup::VLightObjectGroup( void ) +{ + setLabel( "LightObjectGroup" ); +}; \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.h b/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.h new file mode 100644 index 000000000..16af01bcd --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTGROUP_H_ +#define _VT_VLIGHTOBJECTGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VLightObjectGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp new file mode 100644 index 000000000..4e1475a5f --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectToggleEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectToggleEvent ); +//----------------------------------------------------------------------------- + +VLightObjectToggleEvent::VLightObjectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VLightObjectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VLightObjectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectToggleEvent::onTrigger( pTime, pDelta ); +// +// Toggle the Light Object. +// +//----------------------------------------------------------------------------- +void VLightObjectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) ) + { + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle Light. + VTorque::setLightObjectOn( lightObject, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.h b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.h new file mode 100644 index 000000000..382aee1c7 --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTTOGGLEEVENT_H_ +#define _VT_VLIGHTOBJECTTOGGLEEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectToggleEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VLightObjectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp new file mode 100644 index 000000000..a4a5387eb --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/LightObject/VLightObjectToggleTrack.h" +#include "Verve/Extension/LightObject/VLightObjectToggleEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VLightObjectToggleTrack ); +//----------------------------------------------------------------------------- + +VLightObjectToggleTrack::VLightObjectToggleTrack( void ) +{ + setLabel( "ToggleTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VLightObjectToggleTrack::onControllerReset( pTime, pForward ); +// +// Enable or Disable the light object after a reset. +// +//----------------------------------------------------------------------------- +void VLightObjectToggleTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + VLightObjectToggleEvent *event; + VTorque::LightObjectType *lightObject; + if ( getSceneObject( lightObject ) && getPreviousEvent( event ) ) + { + // Turn On? + const bool turnOn = ( event->mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle the Light. + VTorque::setLightObjectOn( lightObject, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.h b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.h new file mode 100644 index 000000000..510c290bb --- /dev/null +++ b/Engine/source/Verve/Extension/LightObject/VLightObjectToggleTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VLIGHTOBJECTTOGGLETRACK_H_ +#define _VT_VLIGHTOBJECTTOGGLETRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#include "Verve/Torque/TLightObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VLightObjectToggleTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VLightObjectToggleTrack( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VLightObjectToggleTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VLIGHTOBJECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Motion/VMotionEvent.cpp b/Engine/source/Verve/Extension/Motion/VMotionEvent.cpp new file mode 100644 index 000000000..d972168ec --- /dev/null +++ b/Engine/source/Verve/Extension/Motion/VMotionEvent.cpp @@ -0,0 +1,212 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VController.h" +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Motion/VMotionEvent.h" +#include "Verve/Extension/Motion/VMotionTrack.h" + +#include "console/consoleTypes.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VMotionEvent ); +//----------------------------------------------------------------------------- + +VMotionEvent::VMotionEvent( void ) +{ + setLabel( "MotionEvent" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionEvent::onTrigger( pDelta, pDelta ); +// +// The path object is told to move to the next node. If this event corresponds +// to Node 0, the object will move to Node 1. If the object reaches the node +// before the next event is triggered, then the object will stop moving. +// +// The object's position is only reset when the track is reset and not when an +// event is triggered. +// +//----------------------------------------------------------------------------- +void VMotionEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Parent Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid Track. + return; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid. + return; + } + + // Valid Destination Node? + if ( !isControllerLooping() && !getNextEvent() ) + { + // Clear Active. + VTorque::setPathObjectActive( path, object, false ); + // Quit. + return; + } + + // Set Active. + VTorque::setPathObjectActive( path, object, true ); + + // Apply Speed. + VTorque::setPathObjectSpeed( path, object, getObjectSpeed() ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getPath(); +// +// Returns the path that this track is referencing. +// +//----------------------------------------------------------------------------- +VTorque::PathObjectType *VMotionEvent::getPath( void ) +{ + // Fetch Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid. + return NULL; + } + + // Return Path. + return track->getPath(); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getObjectSpeed(); +// +// Determine the Speed that an object must move at to travel over the segment +// length of the Path. +// +//----------------------------------------------------------------------------- +F32 VMotionEvent::getObjectSpeed( void ) +{ + // Fetch Parent Track. + VMotionTrack *track; + if ( !getTrack( track ) ) + { + // Invalid Track. + return 0.f; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return 0.f; + } + + // Fetch Node Index. + const S32 &srcNodeIndex = getNodeIndex( ( isControllerPlayingForward() ) ? 0 : -1 ); + + // Fetch the Next Event. + VEvent *nextEvent = getNextEvent(); + + // Valid Destination Node? + if ( !isControllerLooping() && !nextEvent ) + { + // No Next Node. + return 0.f; + } + + // Valid Next Node? + if ( nextEvent ) + { + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = mAbs( getTriggerTime() - nextEvent->getTriggerTime() ); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); + } + + // Playing Forwards? + if ( isControllerPlayingForward() ) + { + // Fetch the First Event. + VEvent *firstEvent = dynamic_cast( track->getChild() ); + + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = ( getControllerDuration() - getTriggerTime() ) + firstEvent->getTriggerTime(); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); + } + + // Fetch the Last Event. + VEvent *lastEvent = dynamic_cast( track->getLastChild() ); + + // Fetch Segment Length & Duration. + const F32 &length = VTorque::getPathNodeLength( path, srcNodeIndex ); + const F32 &duration = ( getControllerDuration() - lastEvent->getTriggerTime() ) + getTriggerTime(); + + // Speed = Distance / Duration. + return ( length / ( duration / 1000.f ) ); +} + +//----------------------------------------------------------------------------- +// +// VMotionEvent::getNodeIndex( pDelta ); +// +// Returns the index of the path node associated with this event object. +// +//----------------------------------------------------------------------------- +S32 VMotionEvent::getNodeIndex( const S32 &pDelta ) +{ + // Fetch Event Count. + const S32 eventCount = ( ( VTreeNode* )getParent() )->size(); + + // Return Index. + return ( getIndex() + pDelta ) % eventCount; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Motion/VMotionEvent.h b/Engine/source/Verve/Extension/Motion/VMotionEvent.h new file mode 100644 index 000000000..2ef710e06 --- /dev/null +++ b/Engine/source/Verve/Extension/Motion/VMotionEvent.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VMOTIONEVENT_H_ +#define _VT_VMOTIONEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_MOTION_H_ +#include "Verve/Torque/TMotion.h" +#endif + +//----------------------------------------------------------------------------- + +class VMotionEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + VMotionEvent( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Reference Methods. + + virtual VTorque::PathObjectType *getPath( void ); + F32 getObjectSpeed( void ); + S32 getNodeIndex( const S32 &pDelta = 0 ); + + // Console Declaration. + + DECLARE_CONOBJECT( VMotionEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VMOTIONEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Motion/VMotionTrack.cpp b/Engine/source/Verve/Extension/Motion/VMotionTrack.cpp new file mode 100644 index 000000000..1042f5461 --- /dev/null +++ b/Engine/source/Verve/Extension/Motion/VMotionTrack.cpp @@ -0,0 +1,442 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/Motion/VMotionTrack.h" +#include "Verve/Extension/Motion/VMotionEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VMotionTrack ); +//----------------------------------------------------------------------------- + +VMotionTrack::VMotionTrack( void ) : + mDataReference( String::EmptyString ), + mOrientationMode( "FREE" ), + mOrientationData( String::EmptyString ), + mRelative( false ) +{ + setLabel( "MotionTrack" ); +} + +void VMotionTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Reference", TypeRealString, Offset( mDataReference, VMotionTrack ), "The name of the data field referencing the object to be attached to the path." ); + + addProtectedField( "OrientationMode", TypeRealString, Offset( mOrientationMode, VMotionTrack ), &setOrientationMode, &defaultProtectedGetFn, "The orientation mode of the object attached to the path." ); + addProtectedField( "OrientationData", TypeRealString, Offset( mOrientationData, VMotionTrack ), &setOrientationData, &defaultProtectedGetFn, "The name of the data field holding the orientation data (used for Orientation Modes, ToObject & ToPoint)." ); + addField( "Relative", TypeBool, Offset( mRelative, VMotionTrack ), "Attach the object with an offset based on its initial position." ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::onControllerEvent( pEvent ); +// +// When the controller's state changes, this method is called. If the +// controller is paused, then the path object will cease to move. If the +// controller resumes play, the object will continue on its path. +// +// For a full list of possible events, see the 'eControllerEventType' +// declaration in VController.h. +// +//----------------------------------------------------------------------------- +bool VMotionTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + // Fetch Path & Reference Object. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object || !VTorque::isPathObjectAttached( path, object ) ) + { + // Invalid. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPlay : + { + + // Continue Advancing. + VTorque::setPathObjectActive( path, object, true ); + + } break; + + case VController::k_EventPause : + { + + // Stop Advancing. + VTorque::setPathObjectActive( path, object, false ); + + } break; + + case VController::k_EventStop : + { + + // Detach the Object. + detachObject(); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::onControllerReset( pTime, pForward ); +// +// Reposition the path object on the path appropriately. The position is +// interpolated between two nodes, the last node and the next node. These +// correspond to the last and current events. +// +//----------------------------------------------------------------------------- +void VMotionTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Parent Reset. + Parent::onControllerReset( pTime, pForward ); + + // Valid Track? + // Note: We must have at least 2 Events/Nodes to path. + if ( size() < 2 ) + { + // Invalid. + return; + } + + // Get Object References. + VController *controller = getController(); + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !controller || !path || !object ) + { + // Invalid Object(s). + return; + } + + // Attached? + if ( !VTorque::isPathObjectAttached( path, object ) ) + { + // No, Attach Now. + attachObject(); + } + + // Reset Object. + resetObject( pTime ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VMotionTrack::getPath(); +// +// Returns the path that this track is referencing. +// +//----------------------------------------------------------------------------- +VTorque::PathObjectType *VMotionTrack::getPath( void ) +{ + // Fetch the Controller. + VController *controller = getController(); + if ( !controller ) + { + // Invalid Controller. + return NULL; + } + + // Evalulate the Data Field. + String fieldValue; + if ( controller->getDataValue( mDataReference, fieldValue ) ) + { + // Return Object. + return dynamic_cast( Sim::findObject( fieldValue ) ); + } + + // No Data! + return NULL; +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::attachObject(); +// +// Attach the underlying Scene Object to the target Path at the first Node. +// Default settings are applied and must be updated after the object is +// attached. +// +//----------------------------------------------------------------------------- +void VMotionTrack::attachObject( void ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Object Attached? + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Already Attached. + return; + } + + // Fetch Forwards. + const bool &forward = isControllerPlayingForward(); + // Select the Node. + const S32 node = ( forward ) ? 0 : ( size() - 1 ); + + // Fetch the value from the controller data table. + String orientationDataValue = String::EmptyString; + if ( mOrientationData != String::EmptyString + && !getController()->getDataValue( mOrientationData, orientationDataValue ) ) + { + // Sanity! + Con::warnf( "Unable to located the value for the given orientation data key, '%s'", mOrientationData ); + // Clear. + orientationDataValue = String::EmptyString; + } + + // Attach Object. + VTorque::attachPathObject( path, object, forward, mRelative, node, -1, mOrientationMode, orientationDataValue ); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::detachObject( void ); +// +// +// +//----------------------------------------------------------------------------- +void VMotionTrack::detachObject( void ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Object Attached? + if ( !VTorque::isPathObjectAttached( path, object ) ) + { + // Not Attached. + return; + } + + // Detach. + VTorque::detachPathObject( path, object ); +} + +//----------------------------------------------------------------------------- +// +// VMotionTrack::resetObject( pTime ); +// +// +// +//----------------------------------------------------------------------------- +void VMotionTrack::resetObject( const S32 &pTime ) +{ + // Get Object References. + VTorque::PathObjectType *path = getPath(); + VTorque::SceneObjectType *object = getSceneObject(); + if ( !path || !object ) + { + // Invalid Object(s). + return; + } + + // Fetch Controller Info. + const bool &isPlaying = isControllerPlaying(); + const bool &isPlayingForward = isControllerPlayingForward(); + const bool &isLooping = isControllerLooping(); + + // Init Variables. + bool objectActive = false; + F32 objectInterp = 0.f; + F32 objectSpeed = 0.f; + S32 srcNodeIndex = 0; + S32 dstNodeIndex = 0; + + VMotionEvent *event; + if ( !getNextEvent( event ) || event->getTriggerTime() == pTime ) + { + // Note: This case deals with a target time that is greater than the + // trigger time of the Last Event on this track. It will clamp + // the position of the object to the corresponding node of the + // Last Event. + + // Note: If pTime is exactly equal to the Next Event's trigger time, + // then it will set the Source Node to the Last Node and + // set its Interp to 0.f - which is incorrect! + if ( !event || event->getTriggerTime() != pTime ) + { + // Fetch the Last Event. + getPreviousEvent( event ); + } + + // Set the Info. + objectInterp = 0.f; + objectSpeed = event->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex(); + dstNodeIndex = srcNodeIndex; + } + else if ( !event->getPreviousEvent() ) + { + // Note: This case deals with a target time that is less than the + // trigger time of the First Event on this track. It will clamp + // the position of the object to the corresponding node of the + // First Event. + + // Set the Info. + objectInterp = 0.f; + objectSpeed = event->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex(); + dstNodeIndex = srcNodeIndex; + } + else + { + // Note: This case deals with a target time that is between two Events + // on this track. It will position the object on the path, + // between the two nodes corresponding to the Events. + + // Fetch the Last Event. + VMotionEvent *lastEvent; + getPreviousEvent( lastEvent ); + + // Set the Info. + objectActive = isPlaying; + objectInterp = calculateInterp( pTime ); + objectSpeed = lastEvent->getObjectSpeed(); + srcNodeIndex = event->getNodeIndex( ( isPlayingForward ) ? -1 : 1 ); + dstNodeIndex = event->getNodeIndex(); + } + + // Set Active. + VTorque::setPathObjectActive( path, object, objectActive ); + + // Set Forward. + VTorque::setPathObjectForward( path, object, isPlayingForward ); + + // Set Speed. + VTorque::setPathObjectSpeed( path, object, objectSpeed ); + + // Set Current Node. + VTorque::setPathObjectNode( path, object, srcNodeIndex ); + + // Set End Node. + VTorque::setPathObjectEndNode( path, object, ( ( isLooping ) ? -1 : ( size() - 1 ) ) ); + + // Set Interp. + VTorque::setPathObjectInterp( path, object, objectInterp ); +} + +//----------------------------------------------------------------------------- +// +// Static Field Methods. +// +//----------------------------------------------------------------------------- + +bool VMotionTrack::setOrientationMode( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Track. + VMotionTrack *track = static_cast( pObject ); + + // Store Data. + track->mOrientationMode = pData; + + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = track->getSceneObject(); + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Set Orientation Mode. + VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData ); + } + + return false; +} + +bool VMotionTrack::setOrientationData( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Track. + VMotionTrack *track = static_cast( pObject ); + + // Store Data. + track->mOrientationData = pData; + + VTorque::PathObjectType *path = track->getPath(); + VTorque::SceneObjectType *object = track->getSceneObject(); + if ( VTorque::isPathObjectAttached( path, object ) ) + { + // Set Orientation Mode. + VTorque::setPathObjectOrientation( path, object, track->mOrientationMode, track->mOrientationData ); + } + + return false; +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VMotionTrack, getPath, S32, (),, "( void ) - Get the path object this track references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Path. + SimObject *pathReference = object->getPath(); + + // Return. + return ( pathReference ) ? pathReference->getId() : 0; +} +#endif diff --git a/Engine/source/Verve/Extension/Motion/VMotionTrack.h b/Engine/source/Verve/Extension/Motion/VMotionTrack.h new file mode 100644 index 000000000..b0fc25c34 --- /dev/null +++ b/Engine/source/Verve/Extension/Motion/VMotionTrack.h @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VMOTIONTRACK_H_ +#define _VT_VMOTIONTRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_MOTION_H_ +#include "Verve/Torque/TMotion.h" +#endif + +//----------------------------------------------------------------------------- + +class VMotionTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + // Reference Members. + + String mDataReference; + + // Path Members. + + String mOrientationMode; + String mOrientationData; + bool mRelative; + +public: + + VMotionTrack( void ); + + static void initPersistFields( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Reference Methods. + + VTorque::PathObjectType *getPath( void ); + void attachObject( void ); + void detachObject( void ); + + void resetObject( const S32 &pTime ); + + // Console Declaration. + + DECLARE_CONOBJECT( VMotionTrack ); + +protected: + + // Static Field Methods. + + static bool setOrientationMode( void *pObject, const char *pArray, const char *pData ); + static bool setOrientationData( void *pObject, const char *pArray, const char *pData ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VMOTIONTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp new file mode 100644 index 000000000..00c30388c --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectGroup.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectGroup ); +//----------------------------------------------------------------------------- + +VParticleEffectGroup::VParticleEffectGroup( void ) +{ + setLabel( "ParticleEffectGroup" ); +}; \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.h b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.h new file mode 100644 index 000000000..aa7806366 --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectGroup.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEEFFECTGROUP_H_ +#define _VT_VPARTICLEEFFECTGROUP_H_ + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectGroup : public VSceneObjectGroup +{ + typedef VSceneObjectGroup Parent; + +public: + + VParticleEffectGroup( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEEFFECTGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp new file mode 100644 index 000000000..658f3b5d0 --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectToggleEvent ); +//----------------------------------------------------------------------------- + +VParticleEffectToggleEvent::VParticleEffectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VParticleEffectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VParticleEffectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VParticleEffectToggleEvent::onTrigger( pTime, pDelta ); +// +// Toggle the Particle Effect. +// +//----------------------------------------------------------------------------- +void VParticleEffectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + VTorque::ParticleEffectType *particleEffect; + if ( getSceneObject( particleEffect ) ) + { + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle Particle Effect. + VTorque::setParticleEffectOn( particleEffect, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h new file mode 100644 index 000000000..e4028413a --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEFFECTTOGGLEEVENT_H_ +#define _VT_VPARTICLEFFECTTOGGLEEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#include "Verve/Torque/TParticleEffect.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectToggleEvent : public VSceneObjectEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VParticleEffectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEFFECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp new file mode 100644 index 000000000..30ce242f5 --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h" +#include "Verve/Extension/ParticleEffect/VParticleEffectToggleEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VParticleEffectToggleTrack ); +//----------------------------------------------------------------------------- + +VParticleEffectToggleTrack::VParticleEffectToggleTrack( void ) +{ + setLabel( "ToggleTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VParticleEffectToggleTrack::onControllerReset( pTime, pForward ); +// +// Enable or Disable the particle effect after a reset. +// +//----------------------------------------------------------------------------- +void VParticleEffectToggleTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + VParticleEffectToggleEvent *event; + VTorque::ParticleEffectType *particleEffect; + if ( getSceneObject( particleEffect ) && getPreviousEvent( event ) ) + { + // Turn On? + const bool turnOn = ( event->mEventType == VSharedEnum::k_ActionTurnOn ); + + // Toggle the Particle Effect. + VTorque::setParticleEffectOn( particleEffect, turnOn ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h new file mode 100644 index 000000000..5974dbeb8 --- /dev/null +++ b/Engine/source/Verve/Extension/ParticleEffect/VParticleEffectToggleTrack.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPARTICLEEFFECTTOGGLETRACK_H_ +#define _VT_VPARTICLEEFFECTTOGGLETRACK_H_ + +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" +#endif + +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#include "Verve/Torque/TParticleEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VParticleEffectToggleTrack : public VSceneObjectTrack +{ + typedef VSceneObjectTrack Parent; + +public: + + VParticleEffectToggleTrack( void ); + + // Controller Methods. + + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VParticleEffectToggleTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPARTICLEEFFECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp new file mode 100644 index 000000000..5e5d65d40 --- /dev/null +++ b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/PostEffect/VPostEffectToggleEvent.h" +#include "Verve/Extension/PostEffect/VPostEffectToggleTrack.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPostEffectToggleEvent ); +//----------------------------------------------------------------------------- + +VPostEffectToggleEvent::VPostEffectToggleEvent( void ) : + mEventType( VSharedEnum::k_ActionTurnOn ) +{ + setLabel( "ToggleEvent" ); +} + +void VPostEffectToggleEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Action", TYPEID(), Offset( mEventType, VPostEffectToggleEvent ) ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VPostEffectToggleEvent::onTrigger( pTime, pDelta ); +// +// Only enable this effect if the parent group is currently active. +// +//----------------------------------------------------------------------------- +void VPostEffectToggleEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Parent Objects. + VCameraGroup *group; + VPostEffectToggleTrack *track; + if ( ( !getGroup( group ) || !group->isActive() ) || !getTrack( track ) ) + { + // Quit. + return; + } + + // Turn On? + const bool turnOn = ( mEventType == VSharedEnum::k_ActionTurnOn ); + + // Enable Effect. + VTorque::setPostEffectOn( track->getPostEffect(), turnOn ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.h b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.h new file mode 100644 index 000000000..66668307b --- /dev/null +++ b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleEvent.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPOSTEFFECTTOGGLEEVENT_H_ +#define _VT_VPOSTEFFECTTOGGLEEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VEvent.h" +#endif + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +#ifndef _VT_VSHAREDENUM_H_ +#include "Verve/Core/Util/VSharedEnum.h" +#endif + +//----------------------------------------------------------------------------- + +class VPostEffectToggleEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VSharedEnum::eActionToggle mEventType; + +public: + + VPostEffectToggleEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VPostEffectToggleEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPOSTEFFECTTOGGLEEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp new file mode 100644 index 000000000..ff2dd52a5 --- /dev/null +++ b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.cpp @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/PostEffect/VPostEffectToggleTrack.h" +#include "Verve/Extension/PostEffect/VPostEffectToggleEvent.h" +#include "Verve/Extension/Camera/VCameraGroup.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPostEffectToggleTrack ); +//----------------------------------------------------------------------------- + +VPostEffectToggleTrack::VPostEffectToggleTrack( void ) : + mPostEffect( NULL ) +{ + setLabel( "PostEffectTrack" ); +} + +void VPostEffectToggleTrack::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "PostEffect", TYPEID(), Offset( mPostEffect, VPostEffectToggleTrack ), "The name of the PostEffect object to be triggered." ); +} + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VPostEffectToggleTrack::onCameraEvent( pEvent ); +// +// When the Camera changes, this method is called on both the outgoing and +// incoming Camera Groups. +// +// For a full list of possible events, see the 'eCameraEventType' declaration +// in VCameraGroup.h. +// +//----------------------------------------------------------------------------- +bool VPostEffectToggleTrack::onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ) +{ + // Parent Call. + if ( !Parent::onCameraEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() || !mPostEffect.isValid() ) + { + // Quit Now. + return true; + } + + switch( pEvent ) + { + case VCameraGroup::k_EventActivate : + { + + VPostEffectToggleEvent *event; + if ( getPreviousEvent( event ) && event->mEventType == VSharedEnum::k_ActionTurnOn ) + { + // Toggle Post Effect On. + VTorque::setPostEffectOn( mPostEffect, true ); + } + + } break; + + case VCameraGroup::k_EventDeactivate : + { + + // Turn Post Effect Off. + VTorque::setPostEffectOn( mPostEffect, false ); + + } break; + } + + return true; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.h b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.h new file mode 100644 index 000000000..24a531684 --- /dev/null +++ b/Engine/source/Verve/Extension/PostEffect/VPostEffectToggleTrack.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPOSTEFFECTTOGGLETRACK_H_ +#define _VT_VPOSTEFFECTTOGGLETRACK_H_ + +#ifndef _VT_VCAMERATRACK_H_ +#include "Verve/Extension/Camera/VCameraTrack.h" +#endif + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VPostEffectToggleTrack : public VCameraTrack +{ + typedef VCameraTrack Parent; + +protected: + + SimObjectPtr mPostEffect; + +public: + + VPostEffectToggleTrack( void ); + + static void initPersistFields( void ); + + // Camera Methods. + + bool onCameraEvent( const VCameraGroup::eCameraEventType &pEvent ); + + // Console Declaration. + + DECLARE_CONOBJECT( VPostEffectToggleTrack ); + +public: + + VTorque::PostEffectType *getPostEffect( void ) { return mPostEffect; }; +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPOSTEFFECTTOGGLETRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.cpp b/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.cpp new file mode 100644 index 000000000..11662508e --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectEvent ); +//----------------------------------------------------------------------------- + +VSceneObjectEvent::VSceneObjectEvent( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectEvent::getSceneObject(); +// +// Returns the parent group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectEvent::getSceneObject( void ) +{ + VSceneObjectGroup *group; + if ( !getGroup( group ) ) + { + // No Group! + return NULL; + } + + // Return Object. + return group->getSceneObject(); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VSceneObjectEvent, getSceneObject, S32, (),, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.h b/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.h new file mode 100644 index 000000000..5dd4bc7df --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectEvent.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#define _VT_VSCENEOBJECTEVENT_H_ + +#ifndef _VT_VEVENT_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectEvent : public VEvent +{ + typedef VEvent Parent; + +public: + + VSceneObjectEvent( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectEvent ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.cpp b/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.cpp new file mode 100644 index 000000000..83307cc7b --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.cpp @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Core/VController.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectGroup ); +//----------------------------------------------------------------------------- + +VSceneObjectGroup::VSceneObjectGroup( void ) : + mDataReference( String::EmptyString ), + mSceneObject( NULL ) +{ + setLabel( "SceneObjectGroup" ); +}; + +void VSceneObjectGroup::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "Reference", TypeRealString, Offset( mDataReference, VSceneObjectGroup ), "The name of the data field referencing the targeted object." ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectGroup::getObject(); +// +// Returns the group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectGroup::getSceneObject( void ) +{ +#ifndef VT_EDITOR + // Already Referenced? + if ( mSceneObject ) + { + // Return Object. + return mSceneObject; + } +#endif + + VController *controller = getController(); + if ( !controller ) + { + // No Controller! + return NULL; + } + + String fieldValue; + if ( controller->getDataValue( mDataReference, fieldValue ) ) + { + // Store Object. + mSceneObject = dynamic_cast( Sim::findObject( fieldValue ) ); + } + + // Return. + return mSceneObject; +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VSceneObjectGroup, getSceneObject, S32, (),, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.h b/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.h new file mode 100644 index 000000000..9af52eef6 --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectGroup.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#define _VT_VSCENEOBJECTGROUP_H_ + +#ifndef _VT_VGROUP_H_ +#include "Verve/Core/VGroup.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectGroup : public VGroup +{ + typedef VGroup Parent; + +public: + + // Reference Members. + + String mDataReference; + VTorque::SceneObjectType *mSceneObject; + +public: + + VSceneObjectGroup( void ); + + static void initPersistFields( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectGroup ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTGROUP_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.cpp b/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.cpp new file mode 100644 index 000000000..24052658e --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.cpp @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#include "Verve/Extension/SceneObject/VSceneObjectTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSceneObjectTrack ); +//----------------------------------------------------------------------------- + +VSceneObjectTrack::VSceneObjectTrack( void ) +{ + setLabel( "SceneObjectTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSceneObjectTrack::getSceneObject(); +// +// Returns the parent group's object reference. +// +//----------------------------------------------------------------------------- +VTorque::SceneObjectType *VSceneObjectTrack::getSceneObject( void ) +{ + VSceneObjectGroup *group; + if ( !getGroup( group ) ) + { + // No Group! + return NULL; + } + + // Return Object. + return group->getSceneObject(); +} + +#ifdef VT_EDITOR +//----------------------------------------------------------------------------- +// +// Debug Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VSceneObjectTrack, getSceneObject, S32, (),, "( void ) - Get the object this group references.\n" + "@return Returns the SimObjectID for the object." ) +{ + // Fetch Object. + VTorque::SceneObjectType *objReference = object->getSceneObject(); + + // Return. + return ( objReference ) ? objReference->getId() : 0; +} +#endif diff --git a/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.h b/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.h new file mode 100644 index 000000000..d07517862 --- /dev/null +++ b/Engine/source/Verve/Extension/SceneObject/VSceneObjectTrack.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCENEOBJECTTRACK_H_ +#define _VT_VSCENEOBJECTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_VSCENEOBJECTGROUP_H_ +#include "Verve/Extension/SceneObject/VSceneObjectGroup.h" +#endif + +//----------------------------------------------------------------------------- + +class VSceneObjectTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VSceneObjectTrack( void ); + + // Reference Methods. + + VTorque::SceneObjectType *getSceneObject( void ); + template inline bool getSceneObject( T *&pSceneObject ) + { + // Reference Scene Object. + pSceneObject = dynamic_cast( getSceneObject() ); + + // Valid? + return ( pSceneObject != NULL ); + } + + // Console Declaration. + + DECLARE_CONOBJECT( VSceneObjectTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCENEOBJECTTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Script/VScriptEvent.cpp b/Engine/source/Verve/Extension/Script/VScriptEvent.cpp new file mode 100644 index 000000000..69b477466 --- /dev/null +++ b/Engine/source/Verve/Extension/Script/VScriptEvent.cpp @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Core/VTrack.h" + +#include "Verve/Extension/Script/VScriptEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VScriptEvent ); +//----------------------------------------------------------------------------- + +// Implement the Command Type enum list. +ImplementEnumType( VScriptEventCommandType, "" ) + { VScriptEvent::k_TypeExpression, "EXPRESSION" }, + { VScriptEvent::k_TypeMethod, "METHOD" }, +EndImplementEnumType; + +//----------------------------------------------------------------------------- + +VScriptEvent::VScriptEvent( void ) : + mCommandType( k_TypeMethod ), + mCommand( String::EmptyString ) +{ + setLabel( "ScriptEvent" ); +} + +void VScriptEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "CommandType", TYPEID(), Offset( mCommandType, VScriptEvent ), "The type of command to be evaluated." ); + addField( "Command", TypeRealString, Offset( mCommand, VScriptEvent ), "The command to be evaluated." ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VScriptEvet::onTrigger( pTime, pDelta ); +// +// Execute a method or evaluate a command. +// +//----------------------------------------------------------------------------- +void VScriptEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + switch ( mCommandType ) + { + case k_TypeExpression : + { + + // Evaluate Expression. + Con::evaluate( mCommand, false, NULL ); + + } break; + + case k_TypeMethod : + { + + SimObject *object = getSceneObject(); + if ( object ) + { + // Execute Method. + Con::executef( object, mCommand.c_str() ); + } + else + { + // Execute Function. + Con::executef( mCommand.c_str()); + } + + } break; + } +} diff --git a/Engine/source/Verve/Extension/Script/VScriptEvent.h b/Engine/source/Verve/Extension/Script/VScriptEvent.h new file mode 100644 index 000000000..ee0b139ca --- /dev/null +++ b/Engine/source/Verve/Extension/Script/VScriptEvent.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCRIPTEVENT_H_ +#define _VT_VSCRIPTEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +//----------------------------------------------------------------------------- + +class VScriptEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + +public: + + enum eCommandType + { + k_TypeExpression, + k_TypeMethod, + + k_TypeInvalid, + }; + + eCommandType mCommandType; + String mCommand; + +public: + + VScriptEvent( void ); + + static void initPersistFields( void ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VScriptEvent ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VScriptEvent::eCommandType VScriptEventCommandType; + +// Declare Enum Types. +DefineEnumType( VScriptEventCommandType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCRIPTEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Script/VScriptEventTrack.cpp b/Engine/source/Verve/Extension/Script/VScriptEventTrack.cpp new file mode 100644 index 000000000..142d7bc1b --- /dev/null +++ b/Engine/source/Verve/Extension/Script/VScriptEventTrack.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/Script/VScriptEventTrack.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VScriptEventTrack ); +//----------------------------------------------------------------------------- + +VScriptEventTrack::VScriptEventTrack( void ) +{ + setLabel( "ScriptEventTrack" ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/Script/VScriptEventTrack.h b/Engine/source/Verve/Extension/Script/VScriptEventTrack.h new file mode 100644 index 000000000..e0360ab4f --- /dev/null +++ b/Engine/source/Verve/Extension/Script/VScriptEventTrack.h @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSCRIPTEVENTTRACK_H_ +#define _VT_VSCRIPTEVENTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +//----------------------------------------------------------------------------- + +class VScriptEventTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VScriptEventTrack( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VScriptEventTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSCRIPTEVENTTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp new file mode 100644 index 000000000..92c352427 --- /dev/null +++ b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.cpp @@ -0,0 +1,131 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Core/VGroup.h" +#include "Verve/Extension/SoundEffect/VSoundEffectEvent.h" +#include "Verve/Extension/SoundEffect/VSoundEffectTrack.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSoundEffectEvent ); +//----------------------------------------------------------------------------- + +VSoundEffectEvent::VSoundEffectEvent( void ) : + mSoundEffect( NULL ) +{ + setLabel( "SoundEvent" ); +} + +void VSoundEffectEvent::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "SoundEffect", TYPEID(), Offset( mSoundEffect, VSoundEffectEvent ), &setSoundData, &defaultProtectedGetFn, "" ); +} + +//----------------------------------------------------------------------------- +// +// Callback Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectEvent::onTrigger( pTime, pDelta ); +// +// Play the target sound effect. If this track belongs to a SceneObjectGroup, +// then the sound will play with the reference object's transform. If this is +// not the case, then a 2D sound will be played. +// +//----------------------------------------------------------------------------- +void VSoundEffectEvent::onTrigger( const S32 &pTime, const S32 &pDelta ) +{ + Parent::onTrigger( pTime, pDelta ); + + // Fetch Track. + VSoundEffectTrack *track; + if ( !getTrack( track ) ) + { + return; + } + + // Position & Pitch. + U32 position = mAbs( ( pTime + pDelta ) - getStartTime() ); + F32 pitch = mFabs( getControllerTimeScale() ); + if ( position < SFXStartBuffer ) + { + // Zero. + position = 0; + } + + VSceneObjectGroup *group; + if ( getGroup( group ) ) + { + // Play Sound With Reference. + track->mSource = VTorque::playSound( mSoundEffect, group->getSceneObject(), position, pitch ); + } + else + { + // Play Sound. + track->mSource = VTorque::playSound( mSoundEffect, position, pitch ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectEvent::setDuration( pDuration ); +// +// This event's duration is always set to the sound object's duration. +// +//----------------------------------------------------------------------------- +void VSoundEffectEvent::setDuration( const S32 &pDuration ) +{ + // Clear Duration. + mDuration = VTorque::getSoundDuration( mSoundEffect ); +} + +//----------------------------------------------------------------------------- +// +// Static Field Methods. +// +//----------------------------------------------------------------------------- + +bool VSoundEffectEvent::setSoundData( void *pObject, const char *pArray, const char *pData ) +{ + // Fetch Event. + VSoundEffectEvent *event = static_cast( pObject ); + + // Use Object. + event->mSoundEffect = dynamic_cast( Sim::findObject( pData ) ); + + // Set Duration. + event->setDuration( 0 ); + + return false; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.h b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.h new file mode 100644 index 000000000..79ea79d65 --- /dev/null +++ b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectEvent.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSOUNDEFFECTEVENT_H_ +#define _VT_VSOUNDEFFECTEVENT_H_ + +#ifndef _VT_VSCENEOBJECTEVENT_H_ +#include "Verve/Extension/SceneObject/VSceneObjectEvent.h" +#endif + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VSoundEffectEvent : public VSceneObjectEvent +{ + typedef VSceneObjectEvent Parent; + + enum + { + SFXStartBuffer = 100, + }; + +public: + + SimObjectPtr mSoundEffect; + +public: + + VSoundEffectEvent( void ); + + static void initPersistFields( void ); + + static bool setSoundData( void *pObject, const char *pArray, const char *pData ); + + // Event Methods. + + virtual void onTrigger( const S32 &pTime, const S32 &pDelta ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSoundEffectEvent ); + +public: + + // Property Methods. + + virtual void setDuration( const S32 &pDuration ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSOUNDEFFECTEVENT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp new file mode 100644 index 000000000..040040d31 --- /dev/null +++ b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.cpp @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Extension/SoundEffect/VSoundEffectTrack.h" +#include "Verve/Extension/SoundEffect/VSoundEffectEvent.h" + +#include "console/consoleTypes.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VSoundEffectTrack ); +//----------------------------------------------------------------------------- + +VSoundEffectTrack::VSoundEffectTrack( void ) : + mSource( NULL ) +{ + setLabel( "SoundTrack" ); +} + +//----------------------------------------------------------------------------- +// +// Controller Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VSoundEffectTrack::onControllerEvent( pEvent ); +// +// If the controller ceases playback and the track has a valid reference to a +// source provider, then the sound is stopped. +// +//----------------------------------------------------------------------------- +bool VSoundEffectTrack::onControllerEvent( VController::eControllerEventType pEvent ) +{ + if ( !Parent::onControllerEvent( pEvent ) ) + { + // Skip. + return false; + } + + // Enabled? + if ( !isEnabled() ) + { + // Continue Processing Events. + return true; + } + + switch ( pEvent ) + { + case VController::k_EventPause : + case VController::k_EventStop : + { +#ifdef VT_EDITOR + + if ( mSource ) + { + // Stop Sound. + VTorque::stopSound( mSource ); + + // Clear Source. + mSource = NULL; + } + +#endif + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VSoundEffectTrack::onControllerReset( pTime, pForward ); +// +// If the track is reset and it has a valid reference to a source provider, +// then the sound is stopped. +// +//----------------------------------------------------------------------------- +void VSoundEffectTrack::onControllerReset( const S32 &pTime, const bool &pForward ) +{ + // Default Reset. + Parent::onControllerReset( pTime, pForward ); + + if ( mSource ) + { + // Stop Sound. + VTorque::stopSound( mSource ); + } + + // Clear Source. + mSource = NULL; +} \ No newline at end of file diff --git a/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.h b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.h new file mode 100644 index 000000000..1b4eccb24 --- /dev/null +++ b/Engine/source/Verve/Extension/SoundEffect/VSoundEffectTrack.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VSOUNDEFFECTTRACK_H_ +#define _VT_VSOUNDEFFECTTRACK_H_ + +#ifndef _VT_VTRACK_H_ +#include "Verve/Core/VTrack.h" +#endif + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +//----------------------------------------------------------------------------- + +class VSoundEffectTrack : public VTrack +{ + typedef VTrack Parent; + +public: + + VTorque::SoundSourceType *mSource; + +public: + + VSoundEffectTrack( void ); + + // Controller Methods. + + virtual bool onControllerEvent( VController::eControllerEventType pEvent ); + virtual void onControllerReset( const S32 &pTime, const bool &pForward ); + + // Console Declaration. + + DECLARE_CONOBJECT( VSoundEffectTrack ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VSOUNDEFFECTTRACK_H_ \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VEditorButton.cpp b/Engine/source/Verve/GUI/VEditorButton.cpp new file mode 100644 index 000000000..3c32424b4 --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorButton.cpp @@ -0,0 +1,216 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorButton.h" +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gui/core/guiCanvas.h" +#include "gui/core/guiDefaultControlRender.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorButton ); +//----------------------------------------------------------------------------- + +VEditorButton::VEditorButton( void ) : + mIsDraggable( false ) +{ + // Void. +} + +void VEditorButton::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "IsDraggable", TypeBool, Offset( mIsDraggable, VEditorButton ) ); +} + +//----------------------------------------------------------------------------- + +void VEditorButton::onMouseDown( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseDown( pEvent ); + + onMouseEvent( "onMouseDown", pEvent ); +} + +void VEditorButton::onMouseUp( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseUp( pEvent ); + + if ( mIsDraggable && isMouseLocked() ) + { + // Unlock. + mouseUnlock(); + } + + onMouseEvent( "onMouseUp", pEvent ); +} + +void VEditorButton::onMouseDragged( const GuiEvent &pEvent ) +{ + if ( !mActive || !mIsDraggable ) + { + return; + } + + Parent::onMouseDragged( pEvent ); + + if ( !isMouseLocked() ) + { + GuiCanvas *canvas = getRoot(); + if ( canvas->getMouseLockedControl() ) + { + GuiEvent event; + canvas->getMouseLockedControl()->onMouseLeave( event ); + canvas->mouseUnlock( canvas->getMouseLockedControl() ); + } + + // Lock. + mouseLock(); + } + + onMouseEvent( "onMouseDragged", pEvent ); +} + +void VEditorButton::onRightMouseDown( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onRightMouseDown( pEvent ); + + onMouseEvent( "onRightMouseDown", pEvent ); +} + +void VEditorButton::onRightMouseUp( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onRightMouseUp( pEvent ); + + onMouseEvent( "onRightMouseUp", pEvent ); +} + +void VEditorButton::onMouseEnter( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseEnter( pEvent ); + + onMouseEvent( "onMouseEnter", pEvent ); +} + +void VEditorButton::onMouseLeave( const GuiEvent &pEvent ) +{ + if ( !mActive ) + { + return; + } + + Parent::onMouseLeave( pEvent ); + + onMouseEvent( "onMouseLeave", pEvent ); +} + +void VEditorButton::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- + +void VEditorButton::onRender( Point2I offset, const RectI& updateRect ) +{ + // Fetch Texture. + GFXTexHandle texture = getTextureForCurrentState(); + + // Valid? + if ( texture ) + { + GFX->getDrawUtil()->clearBitmapModulation(); + GFX->getDrawUtil()->drawBitmapStretch( texture, RectI( offset, getExtent() ) ); + } + else + { + if ( mProfile->mBorder != 0 ) + { + RectI boundsRect( offset, getExtent() ); + + if ( mDepressed || mStateOn || mMouseOver ) + { + renderFilledBorder( boundsRect, mProfile->mBorderColorHL, mProfile->mFillColorHL ); + } + else + { + renderFilledBorder( boundsRect, mProfile->mBorderColor, mProfile->mFillColor ); + } + } + } + + // Render Text. + GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor ); + renderJustifiedText( offset + mProfile->mTextOffset, getExtent(), mButtonText ); + + renderChildControls( offset, updateRect); +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VEditorButton, getState, bool, (), , "()" ) +{ + return object->getStateOn(); +} diff --git a/Engine/source/Verve/GUI/VEditorButton.h b/Engine/source/Verve/GUI/VEditorButton.h new file mode 100644 index 000000000..15b3e0dfa --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorButton.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORBUTTON_H_ +#define _VT_VEDITORBUTTON_H_ + +#ifndef _GUIBITMAPBUTTON_H_ +#include "gui/buttons/guiBitmapButtonCtrl.h" +#endif + +class VEditorButton : public GuiBitmapButtonTextCtrl +{ + typedef GuiBitmapButtonTextCtrl Parent; + +public: + + bool mIsDraggable; + +public: + + VEditorButton(); + + static void initPersistFields( void ); + + void onMouseDown( const GuiEvent &pEvent ); + void onMouseUp( const GuiEvent &pEvent ); + void onMouseDragged( const GuiEvent &pEvent ); + + void onRightMouseDown( const GuiEvent &pEvent ); + void onRightMouseUp( const GuiEvent &pEvent ); + + void onMouseEnter( const GuiEvent &pEvent ); + void onMouseLeave( const GuiEvent &pEvent ); + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + void onRender( Point2I offset, const RectI &updateRect ); + +public: + + DECLARE_CONOBJECT( VEditorButton ); +}; + +#endif //_VT_VEDITORBUTTON_H_ \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VEditorScrollControl.cpp b/Engine/source/Verve/GUI/VEditorScrollControl.cpp new file mode 100644 index 000000000..b503ed0d6 --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorScrollControl.cpp @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorScrollControl.h" +#include "gfx/gfxDrawUtil.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorScrollControl ); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Mouse Methods. +// +//----------------------------------------------------------------------------- + +void VEditorScrollControl::onMouseUp( const GuiEvent &pEvent ) +{ + Parent::onMouseUp( pEvent ); + + // Event. + onMouseEvent( "onMouseUp", pEvent ); +} + +void VEditorScrollControl::onRightMouseUp( const GuiEvent &pEvent ) +{ + Parent::onMouseUp( pEvent ); + + // Event. + onMouseEvent( "onRightMouseUp", pEvent ); +} + +void VEditorScrollControl::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + const S32 offsetX = ( mHasVScrollBar ) ? mScrollBarThickness : 0; + const S32 offsetY = ( mHasHScrollBar ) ? mScrollBarThickness : 0; + + const RectI contentRect( 2, 2, getWidth() - offsetX - 4 - 1, getHeight() - offsetY - 4 - ( mHasHScrollBar ) ); + if ( !contentRect.pointInRect( pEvent.mousePoint ) ) + { + // Return! + return; + } + + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VEditorScrollControl::onRender( Point2I pOffset, const RectI &pUpdateRect ) +{ + Parent::onRender( pOffset, pUpdateRect ); + + const S32 offsetX = ( mHasVScrollBar ) ? mScrollBarThickness : 1; + const S32 offsetY = ( mHasHScrollBar ) ? mScrollBarThickness : 1; + + RectI contentRect( pOffset.x + 1, pOffset.y + 1, getWidth() - offsetX - 1, getHeight() - offsetY - 1 ); + contentRect.intersect( pUpdateRect ); + + GFX->getDrawUtil()->drawRect( contentRect, mProfile->mBorderColor ); +} \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VEditorScrollControl.h b/Engine/source/Verve/GUI/VEditorScrollControl.h new file mode 100644 index 000000000..5d3e1d72e --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorScrollControl.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORSCROLLCONTROL_H_ +#define _VT_VEDITORSCROLLCONTROL_H_ + +#ifndef _GUISCROLLCTRL_H_ +#include "gui/containers/guiScrollCtrl.h" +#endif + +//----------------------------------------------------------------------------- + +class VEditorScrollControl : public GuiScrollCtrl +{ + typedef GuiScrollCtrl Parent; + +public: + + // Mouse. + + virtual void onMouseUp( const GuiEvent &pEvent ); + virtual void onRightMouseUp( const GuiEvent &pEvent ); + + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + // Rendering. + + void onRender( Point2I pOffset, const RectI &pUpdateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEditorScrollControl ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEDITORSCROLLCONTROL_H_ \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VEditorWindow.cpp b/Engine/source/Verve/GUI/VEditorWindow.cpp new file mode 100644 index 000000000..b5e9c1e07 --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorWindow.cpp @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VEditorWindow.h" +#include "gfx/gfxInit.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VEditorWindow ); +//----------------------------------------------------------------------------- + +bool VEditorWindow::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + GFXAdapter *adapter = GFXInit::getBestAdapterChoice(); + if ( adapter && adapter->mType != NullDevice ) + { + mPlatformWindow->setMinimumWindowSize( Point2I( 904, 287 ) ); + } + + return true; +} + +//----------------------------------------------------------------------------- + +DefineEngineMethod( VEditorWindow, resetCursor, void, (),, "( )" ) +{ + S32 currCursor = PlatformCursorController::curArrow; + if ( object->mCursorChanged == currCursor ) + { + return; + } + + PlatformWindow *window = object->getPlatformWindow(); + PlatformCursorController *controller = window->getCursorController(); + + if( object->mCursorChanged != -1) + { + controller->popCursor(); + } + + controller->pushCursor(currCursor); + object->mCursorChanged = currCursor; + + Platform::setWindowLocked( false ); +} + +DefineEngineMethod( VEditorWindow, setVideoMode, void, (S32 width, S32 height, bool fullscreen, S32 bitDepth, S32 refreshRate, S32 antiAliasLevel), + (800,600,false,32,60, 0), + "(int width, int height, bool fullscreen, [int bitDepth], [int refreshRate])\n" + "Change the video mode of this canvas. This method has the side effect of setting the $pref::Video::mode to the new values.\n\n" + "\\param width The screen width to set.\n" + "\\param height The screen height to set.\n" + "\\param fullscreen Specify true to run fullscreen or false to run in a window\n" + "\\param bitDepth [optional] The desired bit-depth. Defaults to the current setting. This parameter is ignored if you are running in a window.\n" + "\\param refreshRate [optional] The desired refresh rate. Defaults to the current setting. This parameter is ignored if you are running in a window" + "\\param antialiasLevel [optional] The level of anti-aliasing to apply 0 = none" ) +{ + if (!object->getPlatformWindow()) + return; + + // Update the video mode and tell the window to reset. + GFXVideoMode vm = object->getPlatformWindow()->getVideoMode(); + + bool changed = false; + if (width == 0 && height > 0) + { + // Our width is 0 but our height isn't... + // Try to find a matching width + for(S32 i=0; igetPlatformWindow()->getGFXDevice()->getVideoModeList()->size(); i++) + { + const GFXVideoMode &newVm = (*(object->getPlatformWindow()->getGFXDevice()->getVideoModeList()))[i]; + + if(newVm.resolution.y == height) + { + width = newVm.resolution.x; + changed = true; + break; + } + } + } + else if (height == 0 && width > 0) + { + // Our height is 0 but our width isn't... + // Try to find a matching height + for(S32 i=0; igetPlatformWindow()->getGFXDevice()->getVideoModeList()->size(); i++) + { + const GFXVideoMode &newVm = (*(object->getPlatformWindow()->getGFXDevice()->getVideoModeList()))[i]; + + if(newVm.resolution.x == width) + { + height = newVm.resolution.y; + changed = true; + break; + } + } + } + + if (width == 0 || height == 0) + { + // Got a bad size for both of our dimensions or one of our dimensions and + // didn't get a match for the other default back to our current resolution + width = vm.resolution.x; + height = vm.resolution.y; + + changed = true; + } + + if (changed) + Con::errorf("GuiCanvas::setVideoMode(): Error - Invalid resolution of (%d, %d) - attempting (%d, %d)", width, height, width, height); + + vm.resolution = Point2I(width, height); + vm.fullScreen = fullscreen; + + vm.bitDepth = bitDepth; + vm.refreshRate = refreshRate; + + vm.antialiasLevel = antiAliasLevel; + +#ifndef TORQUE_OS_XENON + object->getPlatformWindow()->setVideoMode(vm); +#endif +} diff --git a/Engine/source/Verve/GUI/VEditorWindow.h b/Engine/source/Verve/GUI/VEditorWindow.h new file mode 100644 index 000000000..938c909e9 --- /dev/null +++ b/Engine/source/Verve/GUI/VEditorWindow.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VEDITORWINDOW_H_ +#define _VT_VEDITORWINDOW_H_ + +#ifndef _GUICANVAS_H_ +#include "gui/core/guiCanvas.h" +#endif + +//----------------------------------------------------------------------------- + +class VEditorWindow : public GuiCanvas +{ + typedef GuiCanvas Parent; + +public: + + // Properties. + + virtual bool onAdd( void ); + + // Console Declaration. + + DECLARE_CONOBJECT( VEditorWindow ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VEDITORWINDOW_H_ \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VFadeControl.cpp b/Engine/source/Verve/GUI/VFadeControl.cpp new file mode 100644 index 000000000..16ea3af2f --- /dev/null +++ b/Engine/source/Verve/GUI/VFadeControl.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VFadeControl.h" + +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "math/mMathFn.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VFadeControl ); +//----------------------------------------------------------------------------- + +VFadeControl::VFadeControl( void ) : + mActive( false ), + mFadeType( k_TypeInvalid ), + mElapsedTime( 0 ), + mDuration( 1000 ), + mLastTime( 0 ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VFadeControl::onRender( Point2I pOffset, const RectI &pUpdateRect ) +{ + Parent::onRender( pOffset, pUpdateRect ); + + if ( mFadeType == k_TypeInvalid ) + { + // Invalid Fade State. + return; + } + + // Fetch Time. + const U32 time = Platform::getRealMilliseconds(); + // Fetch Delta. + const U32 delta = ( time - mLastTime ); + // Store Time. + mLastTime = time; + + if ( mActive ) + { + // Update Elapsed Time. + mElapsedTime += delta; + } + + F32 alpha = 1.f - mClampF( F32( mElapsedTime ) / F32( mDuration ), 0.f, 1.f ); + + if ( mFadeType == k_TypeOut ) + { + // Flip. + alpha = 1.f - alpha; + } + + if ( alpha > 0.f ) + { + // Render. + GFX->getDrawUtil()->drawRectFill( pOffset, pOffset + getExtent(), ColorI( 0, 0, 0, alpha * 255 ) ); + } + + if ( mElapsedTime >= mDuration ) + { + // Stop. + mActive = false; + } +} + +//----------------------------------------------------------------------------- +// +// Control Methods. +// +//----------------------------------------------------------------------------- + +void VFadeControl::start( eFadeType pType, S32 pDuration ) +{ + mActive = true; + + mFadeType = pType; + + mElapsedTime = 0; + mDuration = pDuration; + + mLastTime = Platform::getRealMilliseconds(); +} + +void VFadeControl::pause( void ) +{ + mActive = false; +} diff --git a/Engine/source/Verve/GUI/VFadeControl.h b/Engine/source/Verve/GUI/VFadeControl.h new file mode 100644 index 000000000..d26cdb97f --- /dev/null +++ b/Engine/source/Verve/GUI/VFadeControl.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VFADECONTROL_H_ +#define _VT_VFADECONTROL_H_ + +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif + +//----------------------------------------------------------------------------- + +class VFadeControl : public GuiControl +{ + typedef GuiControl Parent; + +public: + + enum eFadeType + { + k_TypeIn, + k_TypeOut, + + k_TypeInvalid, + }; + + bool mActive; + eFadeType mFadeType; + + S32 mElapsedTime; + S32 mDuration; + S32 mLastTime; + +public: + + VFadeControl( void ); + + // Render Methods. + + virtual void onRender( Point2I pOffset, const RectI &pUpdateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VFadeControl ); + +public: + + void start( eFadeType pType, S32 pDuration ); + void pause( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VFADECONTROL_H_ \ No newline at end of file diff --git a/Engine/source/Verve/GUI/VTimeLineControl.cpp b/Engine/source/Verve/GUI/VTimeLineControl.cpp new file mode 100644 index 000000000..9bfc7ccfc --- /dev/null +++ b/Engine/source/Verve/GUI/VTimeLineControl.cpp @@ -0,0 +1,476 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/GUI/VTimeLineControl.h" +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gui/core/guiCanvas.h" + +//----------------------------------------------------------------------------- + +const S32 gUnitsPerSec = 200; + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VTimeLineControl ); +//----------------------------------------------------------------------------- + +VTimeLineControl::VTimeLineControl( void ) : + mIsController( true ), + mController( NULL ), + mDurationOffset( 50 ) +{ + mSelection.Active = false; + mSelection.StartTime = 0; + mSelection.EndTime = 0; +} + +void VTimeLineControl::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "IsController", TypeBool, Offset( mIsController, VTimeLineControl ) ); + addField( "Controller", TYPEID(), Offset( mController, VTimeLineControl ) ); + addField( "DurationOffset", TypeS32, Offset( mDurationOffset, VTimeLineControl ) ); +} + +//----------------------------------------------------------------------------- +// +// Mouse Methods. +// +//----------------------------------------------------------------------------- + +void VTimeLineControl::onMouseDown( const GuiEvent &pEvent ) +{ + Parent::onMouseDown( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + if ( !isMouseLocked() ) + { + GuiCanvas *canvas = getRoot(); + if ( canvas->getMouseLockedControl() ) + { + GuiEvent event; + canvas->getMouseLockedControl()->onMouseLeave( event ); + canvas->mouseUnlock( canvas->getMouseLockedControl() ); + } + + // Lock. + mouseLock(); + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + // Selection? + if ( pEvent.modifier & SI_SHIFT ) + { + if ( !mSelection.Active ) + { + // Selection Active. + mSelection.Active = true; + mSelection.StartTime = mController->getTime(); + mSelection.EndTime = time; + } + else + { + // Update Selection. + mSelection.EndTime = time; + } + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + + // Set First Responder. + setFirstResponder(); + + if ( pEvent.modifier & SI_CTRL ) + { + // Set Time, No Reset. + mController->setTime( time ); + } + else + { + // Reset. + mController->reset( time ); + } +} + +void VTimeLineControl::onMouseUp( const GuiEvent &pEvent ) +{ + if ( isMouseLocked() ) + { + // Unlock. + mouseUnlock(); + } + + if ( mIsController && mController && !mController->isPlaying() ) + { + // Stop without Reset. + mController->stop( false ); + } +} + +void VTimeLineControl::onMouseDragged( const GuiEvent &pEvent ) +{ + Parent::onMouseDragged( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + if ( pEvent.modifier & SI_SHIFT ) + { + if ( mSelection.Active ) + { + // Update Selection. + mSelection.EndTime = time; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + + if ( pEvent.modifier & SI_CTRL ) + { + // Set Time, No Reset. + mController->setTime( time ); + } + else if ( !mSelection.Active ) + { + // Reset. + mController->reset( time ); + } +} + +void VTimeLineControl::onRightMouseDown( const GuiEvent &pEvent ) +{ + Parent::onRightMouseDown( pEvent ); + + if ( !mIsController || !mController || mController->isPlaying() ) + { + return; + } + + // Calculate Time. + const Point2I hitPoint = globalToLocalCoord( pEvent.mousePoint ); + const S32 time = mClamp( toTime( hitPoint.x ), 0, mController->getDuration() ); + + // Set First Responder. + setFirstResponder(); + + if ( mSelection.Active ) + { + const S32 minTime = getMin( mSelection.StartTime, mSelection.EndTime ); + const S32 maxTime = getMax( mSelection.StartTime, mSelection.EndTime ); + if ( time >= minTime && time <= maxTime ) + { + // Callback. + onMouseEvent( "onSelectionRightClick", pEvent ); + + // Don't Update Time. + return; + } + else + { + if ( mSelection.Active ) + { + // Selection Invalid. + mSelection.Active = false; + + // Callback. + Con::executef( this, "onSelectionUpdate" ); + } + } + } + + // Reset. + mController->reset( time ); +} + +void VTimeLineControl::onMouseEvent( const char *pEventName, const GuiEvent &pEvent ) +{ + // Argument Buffers. + char argBuffer[3][32]; + + // Format Event-Position Buffer. + dSprintf( argBuffer[0], 32, "%d %d", pEvent.mousePoint.x, pEvent.mousePoint.y ); + + // Format Event-Modifier Buffer. + dSprintf( argBuffer[1], 32, "%d", pEvent.modifier ); + + // Format Mouse-Click Count Buffer. + dSprintf( argBuffer[2], 32, "%d", pEvent.mouseClickCount ); + + // Call Scripts. + Con::executef( this, pEventName, argBuffer[0], argBuffer[1], argBuffer[2] ); +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VTimeLineControl::onPreRender( void ) +{ + setUpdate(); +} + +void VTimeLineControl::onRender( Point2I offset, const RectI &updateRect ) +{ + if ( !mController ) + { + // Default Render. + Parent::onRender( offset, updateRect ); + + // Quit. + return; + } + + // Render Properties. + const S32 tickOffset = toPoint( 0 ); + const S32 timeLineWidth = toPoint( mController->getDuration() ) - tickOffset; + const F32 tickStep = 0.5f; + const S32 tickInterval = ( mIsController ) ? getWidth() : timeLineWidth; + const S32 tickIntervalCount = ( S32 )mFloor( tickInterval / ( gUnitsPerSec * tickStep ) ) + 1; + + // Tick Render Proeprties. + const Point2I tickExtent( 0, getHeight() - 1 ); + + // Text Render Properties. + const Point2I textExtent( gUnitsPerSec, mProfile->mFontSize ); + const Point2I textOffset( 4, -mProfile->mFontSize ); + + // Render Border. + GFX->getDrawUtil()->drawRectFill( RectI( offset + Point2I( tickOffset + 1, 1 ), Point2I( timeLineWidth - 1, getHeight() - 1 ) ), mProfile->mFillColorHL ); + + // Font Color. + GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor ); + + for ( S32 i = 0; i < tickIntervalCount; i++ ) + { + // Tick Position. + const Point2I tickPosition = offset + Point2I( tickOffset + i * ( gUnitsPerSec * tickStep ), 0 ); + + // Line Color. + const ColorI lineColor = ( ( i % 2 ) ) ? mProfile->mBorderColorHL : mProfile->mBorderColor; + + // Draw Line. + GFX->getDrawUtil()->drawLine( tickPosition, tickPosition + tickExtent, lineColor ); + + if ( mIsController ) + { + // Render Times. + renderJustifiedText( tickPosition + tickExtent + textOffset, textExtent, avar( "%.2f", ( F32 )( i * tickStep ) ) ); + } + } + + // Render Children + renderChildControls( offset, updateRect ); + + if ( mSelection.Active ) + { + // Selection Width. + const S32 selectionWidth = mCeil( mAbs( toPoint( mSelection.EndTime ) - toPoint( mSelection.StartTime ) ) ); + + // Selection Position. + const S32 selectionPositionX = toPoint( getMin( mSelection.StartTime, mSelection.EndTime ) ); + + // Selection Properties. + const Point2I selectionExtent( selectionWidth, getHeight() ); + const Point2I selectionPosition = offset + Point2I( selectionPositionX, 0 ); + + // Render Time Cue. + GFX->getDrawUtil()->drawRectFill( RectI( selectionPosition, selectionExtent ), ColorI( 0, 0, 0, 128 ) ); + + if ( mIsController ) + { + // Buffer. + char buffer[2][128]; + dSprintf( buffer[0], 128, "%.2f", ( F32 )( mSelection.StartTime / 1000.f ) ); + dSprintf( buffer[1], 128, "%.2f", ( F32 )( mSelection.EndTime / 1000.f ) ); + + if ( mSelection.StartTime < mSelection.EndTime ) + { + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer[0] ); + + // Text Position. + const Point2I startText = Point2I( getMax( ( S32 )( selectionPosition.x - ( textWidth + 2 ) ), updateRect.point.x + 4 ), selectionPosition.y + 2 ); + const Point2I endText = Point2I( getMin( ( S32 )( selectionPosition.x + selectionWidth + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), selectionPosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( startText, textExtent, buffer[0] ); + renderJustifiedText( endText, textExtent, buffer[1] ); + } + else + { + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer[1] ); + + // Text Position. + const Point2I startText = Point2I( getMax( ( S32 )( selectionPosition.x - ( textWidth + 2 ) ), updateRect.point.x + 4 ), selectionPosition.y + 2 ); + const Point2I endText = Point2I( getMin( ( S32 )( selectionPosition.x + selectionWidth + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), selectionPosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( startText, textExtent, buffer[1] ); + renderJustifiedText( endText, textExtent, buffer[0] ); + } + } + } + + if ( mController && !mSelection.Active ) + { + // Time Cue Properties. + const Point2I timeCueExtent( ( mIsController ) ? 4 : 2, getHeight() ); + const Point2I timeCuePosition = offset + Point2I( toPoint( mController->getTime() ) - ( timeCueExtent.x / 2 ), 0 ); + + // Render Time Cue. + GFX->getDrawUtil()->drawRectFill( RectI( timeCuePosition, timeCueExtent ), ColorI( 0,0,0,128 ) ); + + if ( mIsController ) + { + // Buffer. + char buffer[128]; + dSprintf( buffer, 128, "%.2f", ( F32 )( mController->getTime() / 1000.f ) ); + + // Fetch Width. + const S32 textWidth = mProfile->mFont->getStrWidth( buffer ); + + // Text Position. + const Point2I textPosition( getMin( getMax( timeCuePosition.x + 6, updateRect.point.x + 4 ), updateRect.point.x + updateRect.extent.x - ( textWidth + 2 ) ), timeCuePosition.y + 2 ); + + // Render Time Text. + renderJustifiedText( textPosition, textExtent, buffer ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Console Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VTimeLineControl, toPoint, S32, (S32 time), (0), "( pTime )" ) +{ + return object->toPoint(time); +} + +S32 VTimeLineControl::toTime( const S32 &pPoint ) +{ + return ( ( S32 )( 1000.f * ( F32 )pPoint / gUnitsPerSec ) - mDurationOffset ); +} + +DefineEngineMethod( VTimeLineControl, toTime, S32, (S32 point), (0), "( pPoint )" ) +{ + return object->toTime(point); +} + +S32 VTimeLineControl::toPoint( const S32 &pTime ) +{ + return ( S32 )( gUnitsPerSec * ( ( F32 )( pTime + mDurationOffset ) / 1000.f ) ); +} + +DefineEngineMethod( VTimeLineControl, getSelection, const char *, (),, "( )" ) +{ + const S32 minTime = getMin( object->mSelection.StartTime, object->mSelection.EndTime ); + const S32 maxTime = getMax( object->mSelection.StartTime, object->mSelection.EndTime ); + + // Fetch Return Buffer. + char *retBuffer = Con::getReturnBuffer( 256 ); + + // Write. + dSprintf( retBuffer, 256, "%d %d %d", object->mSelection.Active, minTime, maxTime - minTime ); + + // Return. + return retBuffer; +} + +DefineEngineMethod( VTimeLineControl, setSelection, void, (bool active, S32 time, S32 duration), (true, -1, 1), "( pActive, [pTime, pDuration] )" ) +{ + object->mSelection.Active = active; + if (time != -1) + { + object->mSelection.StartTime = time; + object->mSelection.EndTime = object->mSelection.StartTime + duration; + } +} + +DefineEngineMethod( VTimeLineControl, updateDuration, void, (),, "( )" ) +{ + object->updateDuration(); +} + +void VTimeLineControl::updateDuration( void ) +{ + if ( !mController ) + { + // No Controller. + return; + } + + // Add 500ms. + const S32 length = toPoint( mController->getDuration() + 500 ); + + // Set Min Extent. + setMinExtent( Point2I( length, getHeight() ) ); + + if ( getWidth() < length ) + { + // Conform to Min Extent. + setExtent( length, getHeight() ); + } +} diff --git a/Engine/source/Verve/GUI/VTimeLineControl.h b/Engine/source/Verve/GUI/VTimeLineControl.h new file mode 100644 index 000000000..1dd1b9851 --- /dev/null +++ b/Engine/source/Verve/GUI/VTimeLineControl.h @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTIMELINECONTROL_H_ +#define _VT_VTIMELINECONTROL_H_ + +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif + +#ifndef _VT_VCONTROLLER_H_ +#include "Verve/Core/VController.h" +#endif + +//----------------------------------------------------------------------------- + +class VTimeLineControl : public GuiControl +{ + typedef GuiControl Parent; + +public: + + struct sSelection + { + bool Active; + S32 StartTime; + S32 EndTime; + }; + + bool mIsController; + VController *mController; + + S32 mDurationOffset; + + sSelection mSelection; + +public: + + VTimeLineControl( void ); + + static void initPersistFields( void ); + + // Mouse. + + virtual void onMouseDown( const GuiEvent &pEvent ); + virtual void onMouseUp( const GuiEvent &pEvent ); + virtual void onMouseDragged( const GuiEvent &pEvent ); + + virtual void onRightMouseDown( const GuiEvent &pEvent ); + + void onMouseEvent( const char *pEventName, const GuiEvent &pEvent ); + + // Rendering. + + void onPreRender( void ); + void onRender( Point2I offset, const RectI &updateRect ); + + // Console Declaration. + + DECLARE_CONOBJECT( VTimeLineControl ); + +public: + + S32 toTime( const S32 &pPoint ); + S32 toPoint( const S32 &pTime ); + + void updateDuration( void ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VTIMELINECONTROL_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TAnimation.h b/Engine/source/Verve/Torque/TAnimation.h new file mode 100644 index 000000000..4c5307bec --- /dev/null +++ b/Engine/source/Verve/Torque/TAnimation.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_ANIMATION_H_ +#define _VT_TORQUE_ANIMATION_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + bool isAnimationLooping( SceneObjectType *pObject, const char *pData ); + + String getAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + F32 getAnimationDuration( SceneObjectType *pObject, const char *pData ); + void setAnimationPosition( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pPosition ); + void setAnimationTimeScale( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pTimeScale ); + + void playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex, const char *pData ); + void playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + void stopAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); + void pauseAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ); +}; + +#endif // _VT_TORQUE_ANIMATION_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TCamera.h b/Engine/source/Verve/Torque/TCamera.h new file mode 100644 index 000000000..329bf093b --- /dev/null +++ b/Engine/source/Verve/Torque/TCamera.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_CAMERA_H_ +#define _VT_TORQUE_CAMERA_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +#ifndef _CAMERAFXMGR_H_ +#include "T3D/fx/cameraFXMgr.h" +#endif + +namespace VTorque +{ + bool isCamera( SceneObjectType *pObject ); + void setCamera( SceneObjectType *pObject ); + + void startCameraShake( const F32 &pDuration, const F32 &pFalloff, const VectorF &pAmplitude, const VectorF &pFrequency ); + void stopCameraShake( void ); +}; + +#endif // _VT_TORQUE_CAMERA_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TLightObject.h b/Engine/source/Verve/Torque/TLightObject.h new file mode 100644 index 000000000..0b44cd607 --- /dev/null +++ b/Engine/source/Verve/Torque/TLightObject.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_LIGHTOBJECT_H_ +#define _VT_TORQUE_LIGHTOBJECT_H_ + +#ifndef _LIGHTBASE_H_ +#include "T3D/lightBase.h" +#endif + +#ifndef _LIGHTANIMDATA_H_ +#include "T3D/lightAnimData.h" +#endif + +namespace VTorque +{ + + typedef LightBase LightObjectType; + typedef LightAnimData LightAnimationDataType; + + bool isLightObjectEnabled( LightObjectType *pLightObject ); + void setLightObjectOn( LightObjectType *pLightObject, const bool &pStatus ); + + void playAnimation( LightObjectType *pLightObject, LightAnimationDataType *pLightAnimationData ); + void playAnimation( LightObjectType *pLightObject ); + void pauseAnimation( LightObjectType *pLightObject ); +}; + +#endif // _VT_TORQUE_LIGHTOBJECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TMotion.h b/Engine/source/Verve/Torque/TMotion.h new file mode 100644 index 000000000..d77118945 --- /dev/null +++ b/Engine/source/Verve/Torque/TMotion.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_MOTION_H_ +#define _VT_TORQUE_MOTION_H_ + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +#ifndef _VT_VPATH_H_ +#include "Verve/VPath/VPath.h" +#endif + +namespace VTorque +{ + typedef VPath PathObjectType; + + bool isMovable( SimObject *pObject ); + bool isPath( SimObject *pObject ); + bool isPathObjectAttached( PathObjectType *pPath, SceneObjectType *pObject ); + + F32 getPathNodeLength( PathObjectType *pPath, const S32 &pNode ); + + void attachPathObject( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ); + void detachPathObject( PathObjectType *pPath, SceneObjectType *pObject ); + + void setPathObjectActive( PathObjectType *pPath, SceneObjectType *pObject, const bool &pActive ); + void setPathObjectInterp( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pInterp ); + void setPathObjectOffset( PathObjectType *pPath, SceneObjectType *pObject, const Point3F &pOffset ); + void setPathObjectSpeed( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pSpeed ); + void setPathObjectOrientation( PathObjectType *pPath, SceneObjectType *pObject, const String &pOrientation, const String &pOrientationData = String::EmptyString ); + void setPathObjectForward( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward ); + void setPathObjectNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ); + void setPathObjectEndNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ); +}; + +#endif // _VT_TORQUE_MOTION_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TParticleEffect.h b/Engine/source/Verve/Torque/TParticleEffect.h new file mode 100644 index 000000000..c1350af0e --- /dev/null +++ b/Engine/source/Verve/Torque/TParticleEffect.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_PARTICLEEFFECT_H_ +#define _VT_TORQUE_PARTICLEEFFECT_H_ + +#ifndef _H_PARTICLE_EMITTER +#include "T3D/fx/particleEmitter.h" +#endif + +#ifndef _PARTICLEEMITTERDUMMY_H_ +#include "T3D/fx/particleEmitterNode.h" +#endif + +namespace VTorque +{ + + typedef ParticleEmitterNode ParticleEffectType; + + bool isParticleEffectEnabled( ParticleEffectType *pParticleEffect ); + void setParticleEffectOn( ParticleEffectType *pParticleEffect, const bool &pStatus ); +}; + +#endif // _VT_TORQUE_PARTICLEEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TPostEffect.h b/Engine/source/Verve/Torque/TPostEffect.h new file mode 100644 index 000000000..58edcf43e --- /dev/null +++ b/Engine/source/Verve/Torque/TPostEffect.h @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#define _VT_TORQUE_POSTEFFECT_H_ + +#ifndef _POST_EFFECT_H_ +#include "postFx/postEffect.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef PostEffect PostEffectType; + + bool isPostEffectEnabled( PostEffectType *pPostEffect ); + void setPostEffectOn( PostEffectType *pPostEffect, const bool &pStatus ); +}; + +#endif // _VT_TORQUE_POSTEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TSceneObject.h b/Engine/source/Verve/Torque/TSceneObject.h new file mode 100644 index 000000000..8f487b3b0 --- /dev/null +++ b/Engine/source/Verve/Torque/TSceneObject.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#define _VT_TORQUE_SCENEOBJECT_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif + +namespace VTorque +{ + typedef SceneObject SceneObjectType; +}; + +#endif // _VT_TORQUE_SCENEOBJECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TSoundEffect.h b/Engine/source/Verve/Torque/TSoundEffect.h new file mode 100644 index 000000000..3c3aa9fbc --- /dev/null +++ b/Engine/source/Verve/Torque/TSoundEffect.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#define _VT_TORQUE_SOUNDEFFECT_H_ + +#ifndef _SFXPROFILE_H_ +#include "sfx/sfxProfile.h" +#endif + +#ifndef _SFXSOUND_H_ +#include "sfx/sfxSound.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef SFXProfile SoundEffectType; + typedef SFXSound SoundSourceType; + + bool isSoundLooping( SoundEffectType *pSoundProfile ); + S32 getSoundDuration( SoundEffectType *pSoundProfile ); + + SoundSourceType *playSound( SoundEffectType *pSoundProfile, const U32 &pPosition, const F32 &pPitch ); + SoundSourceType *playSound( SoundEffectType *pSoundProfile, SceneObjectType *pObject, const U32 &pPosition, const F32 &pPitch ); + + void playSound( SoundSourceType *pSource ); + void pauseSound( SoundSourceType *pSource ); + void stopSound( SoundSourceType *pSource ); + + void setSoundPosition( SoundSourceType *pSource, const U32 &pPosition ); + void setSoundPitch( SoundSourceType *pSource, const F32 &pPitch ); +}; + +#endif // _VT_TORQUE_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque/TSpawnSphere.h b/Engine/source/Verve/Torque/TSpawnSphere.h new file mode 100644 index 000000000..e9899d87d --- /dev/null +++ b/Engine/source/Verve/Torque/TSpawnSphere.h @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TORQUE_SPAWNSPHERE_H_ +#define _VT_TORQUE_SPAWNSPHERE_H_ + +#ifndef _MISSIONMARKER_H_ +#include "T3D/missionMarker.h" +#endif + +#ifndef _VT_TORQUE_SCENEOBJECT_H_ +#include "Verve/Torque/TSceneObject.h" +#endif + +namespace VTorque +{ + typedef SpawnSphere SpawnSphereType; +}; + +#endif // _VT_TORQUE_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VAnimation.cpp b/Engine/source/Verve/Torque3D/VAnimation.cpp new file mode 100644 index 000000000..38eaf983e --- /dev/null +++ b/Engine/source/Verve/Torque3D/VAnimation.cpp @@ -0,0 +1,172 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TAnimation.h" + +#include "T3D/shapeBase.h" + +//----------------------------------------------------------------------------- +// +// Animation Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isAnimationLooping( SceneObjectType *pObject, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return false; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return false; + } + + // Return Cyclic. + return shape->getShape()->sequences[sequenceIndex].isCyclic(); +} + +String VTorque::getAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return ""; + } + + // Return Name. + return shape->getThreadSequenceName( pThreadIndex ); +} + +F32 VTorque::getAnimationDuration( SceneObjectType *pObject, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return 0.f; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return 0.f; + } + + // Return Duration. + return shape->getShape()->sequences[sequenceIndex].duration; +} + +void VTorque::setAnimationPosition( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pPosition ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Set Position. + shape->setThreadPosition( 0, pPosition ); +} + +void VTorque::setAnimationTimeScale( SceneObjectType *pObject, const U32 &pThreadIndex, const F32 &pTimeScale ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Set TimeScale. + shape->setThreadTimeScale( pThreadIndex, pTimeScale ); +} + +void VTorque::playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex, const char *pData ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape || !shape->getShape() ) + { + // Sanity! + return; + } + + // Find Sequence. + const S32 sequenceIndex = shape->getShape()->findSequence( pData ); + if ( sequenceIndex == -1 ) + { + // Invalid Sequence. + return; + } + + // Play Sequence. + shape->setThreadSequence( pThreadIndex, sequenceIndex ); +} + +void VTorque::playAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Play Sequence. + shape->playThread( pThreadIndex ); +} + +void VTorque::stopAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Pause Thread. + shape->stopThread( pThreadIndex ); +} + +void VTorque::pauseAnimation( SceneObjectType *pObject, const U32 &pThreadIndex ) +{ + ShapeBase *shape = dynamic_cast( pObject ); + if ( !shape ) + { + // Sanity! + return; + } + + // Pause Thread. + shape->pauseThread( pThreadIndex ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VCamera.cpp b/Engine/source/Verve/Torque3D/VCamera.cpp new file mode 100644 index 000000000..4e01e5516 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VCamera.cpp @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque/TCamera.h" +#include "Verve/Torque3D/VCameraShake.h" + +#include "T3D/gameBase/gameConnection.h" + +//----------------------------------------------------------------------------- +// +// Camera Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isCamera( SceneObjectType *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +void VTorque::setCamera( SceneObjectType *pObject ) +{ + // Fetch Game Base. + GameBase *object = dynamic_cast( pObject ); + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + GameConnection *connection = dynamic_cast( *itr ); + if ( connection ) + { + // Set Camera Object. + connection->setCameraObject( object ); + } + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VCameraShake.cpp b/Engine/source/Verve/Torque3D/VCameraShake.cpp new file mode 100644 index 000000000..233bf8ca4 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VCameraShake.cpp @@ -0,0 +1,231 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque3D/VCameraShake.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VCameraShakeNetEvent ); +//----------------------------------------------------------------------------- + +// ShakeCamera( 1, 10, "1 0 0", "1 0 0" ); +DefineEngineFunction( ShakeCamera, void, (F32 duration, F32 falloff, VectorF amplitude, VectorF frequency), (0,0,VectorF::Zero, VectorF::Zero), "( pDuration, pFalloff, pAmplitude, pFrequency )" ) +{ + // Shake Camera. + VTorque::startCameraShake( duration, falloff, amplitude, frequency ); +} + +void VTorque::startCameraShake( const F32 &pDuration, const F32 &pFalloff, const VectorF &pAmplitude, const VectorF &pFrequency ) +{ +#ifdef VT_EDITOR + + // Create FX Event + CameraShake *camShake = new CameraShake(); + + // Set Duration. + camShake->setDuration( pDuration ); + + // Set Falloff. + camShake->setFalloff( pFalloff ); + + // Set Amplitude. + VectorF amp = pAmplitude; + camShake->setAmplitude( amp ); + + // Set Frequency. + VectorF freq = pFrequency; + camShake->setFrequency( freq ); + + // Initialise. + camShake->init(); + + // Add to Manager. + gCamFXMgr.addFX( camShake ); + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VCameraShakeNetEvent *event = new VCameraShakeNetEvent(); + + // Setup Event. + event->mEventType |= ( VCameraShakeNetEvent::k_TypeClear | VCameraShakeNetEvent::k_TypeMake ); + event->mDuration = pDuration; + event->mFalloff = pFalloff; + event->mAmplitude = pAmplitude; + event->mFrequency = pFrequency; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +void VTorque::stopCameraShake( void ) +{ +#ifdef VT_EDITOR + + // Clear Manager. + gCamFXMgr.clear(); + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VCameraShakeNetEvent *event = new VCameraShakeNetEvent(); + + // Setup Event. + event->mEventType |= VCameraShakeNetEvent::k_TypeClear; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +//----------------------------------------------------------------------------- + +VCameraShakeNetEvent::VCameraShakeNetEvent( void ) : mEventType( 0 ), + mDuration( 0.f ), + mFalloff( 10.f ), + mAmplitude( Point3F::Zero ), + mFrequency( Point3F::Zero ) +{ + // Void. +} + +void VCameraShakeNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VCameraShakeNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Clear Manager? + pStream->write( mEventType & k_TypeClear ); + + // Make Event? + if ( pStream->write( mEventType & k_TypeMake ) ) + { + // Duration. + pStream->write( mDuration ); + + // Falloff. + pStream->write( mFalloff ); + + // Amplitude. + pStream->write( mAmplitude.x ); + pStream->write( mAmplitude.y ); + pStream->write( mAmplitude.z ); + + // Frequency. + pStream->write( mFrequency.x ); + pStream->write( mFrequency.y ); + pStream->write( mFrequency.z ); + } +} + +void VCameraShakeNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Clear Manager? + if ( pStream->readFlag() ) + { + // Update State. + mEventType |= k_TypeClear; + } + + // Make Event? + if ( pStream->readFlag() ) + { + // Update State. + mEventType |= k_TypeMake; + + // Duration. + pStream->read( &mDuration ); + + // Falloff. + pStream->read( &mFalloff ); + + // Amplitude. + pStream->read( &mAmplitude.x ); + pStream->read( &mAmplitude.y ); + pStream->read( &mAmplitude.z ); + + // Frequency. + pStream->read( &mFrequency.x ); + pStream->read( &mFrequency.y ); + pStream->read( &mFrequency.z ); + } +} + +void VCameraShakeNetEvent::process( NetConnection *pConnection ) +{ + if ( mEventType & k_TypeClear ) + { + // Clear Manager. + gCamFXMgr.clear(); + } + + if ( mEventType & k_TypeMake ) + { + // Create FX Event + CameraShake *camShake = new CameraShake(); + + // Set Duration. + camShake->setDuration( mDuration ); + + // Set Falloff. + camShake->setFalloff( mFalloff ); + + // Set Amplitude. + camShake->setAmplitude( mAmplitude ); + + // Set Frequency. + camShake->setFrequency( mFrequency ); + + // Initialise. + camShake->init(); + + // Add to Manager. + gCamFXMgr.addFX( camShake ); + } +} diff --git a/Engine/source/Verve/Torque3D/VCameraShake.h b/Engine/source/Verve/Torque3D/VCameraShake.h new file mode 100644 index 000000000..2e40359d1 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VCameraShake.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_CAMERASHAKE_H_ +#define _VT_VTORQUE3D_CAMERASHAKE_H_ + +#ifndef _VT_TORQUE_CAMERA_H_ +#include "Verve/Torque/TCamera.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VCameraShakeNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + enum eEventType + { + k_TypeClear = BIT( 0 ), + k_TypeMake = BIT( 1 ), + }; + + U32 mEventType; + + F32 mDuration; + F32 mFalloff; + VectorF mAmplitude; + VectorF mFrequency; + +public: + + VCameraShakeNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VCameraShakeNetEvent ); +}; + +#endif // _VT_VTORQUE3D_CAMERASHAKE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VLightObject.cpp b/Engine/source/Verve/Torque3D/VLightObject.cpp new file mode 100644 index 000000000..dcf1d016e --- /dev/null +++ b/Engine/source/Verve/Torque3D/VLightObject.cpp @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TLightObject.h" + +//----------------------------------------------------------------------------- +// +// Light Object Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isLightObjectEnabled( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return false; + } + + // Get Enabled. + return pLightObject->getLightEnabled(); +} + +void VTorque::setLightObjectOn( LightObjectType *pLightObject, const bool &pStatus ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Set Enabled. + pLightObject->setLightEnabled( pStatus ); +} + +void VTorque::playAnimation( LightObjectType *pLightObject, LightAnimationDataType *pLightAnimationData ) +{ + if ( !pLightObject || !pLightAnimationData ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->playAnimation( pLightAnimationData ); +} + +void VTorque::playAnimation( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->playAnimation(); +} + +void VTorque::pauseAnimation( LightObjectType *pLightObject ) +{ + if ( !pLightObject ) + { + // Sanity! + return; + } + + // Play Animation. + pLightObject->pauseAnimation(); +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VMotion.cpp b/Engine/source/Verve/Torque3D/VMotion.cpp new file mode 100644 index 000000000..54bff56e5 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VMotion.cpp @@ -0,0 +1,458 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TMotion.h" +#include "Verve/VPath/VPath.h" + +//----------------------------------------------------------------------------- + +// Sync the local connection when editing path objects? +// Note: This was originally done so that editing was very smooth, but it turns +// out that any lag was due to errors in the pathing operations +// themselves. If issues persist, then uncomment this definition and you +// might see a marked improvement in performance while editing in Verve. +//#define VT_SYNC_LOCALCLIENT + +//----------------------------------------------------------------------------- +// +// Utility Methods. +// +//----------------------------------------------------------------------------- + +NetObject *getClientObject( NetObject *pObject ) +{ + if ( !pObject ) + { + return NULL; + } + + NetConnection *toServer = NetConnection::getConnectionToServer(); + NetConnection *toClient = NetConnection::getLocalClientConnection(); + if ( !toServer || !toClient ) + { + return NULL; + } + + const S32 ghostIndex = toClient->getGhostIndex( pObject ); + if ( ghostIndex == -1 ) + { + return NULL; + } + + return toServer->resolveGhost( ghostIndex ); +} + +void _attachPathObject( VPath *pPath, SceneObject *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ) +{ + if ( pOrientation == String::EmptyString ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex ); + // Quit. + return; + } + + // Fetch Orientation. + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, NULL ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Object. + SceneObject *lookAtObject = dynamic_cast( Sim::findObject( pOrientationData ) ); + // Valid Object? + if ( lookAtObject != NULL ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtObject ); + } + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + if ( dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ) == 3 ) + { + // Attach Object. + pPath->attachObject( pObject, pForward, 0.f, pRelative, pStartNodeIndex, pEndNodeIndex, type, (void*)lookAtPoint ); + } + + } break; + } +} + +//----------------------------------------------------------------------------- +// +// Path Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isMovable( SimObject *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +bool VTorque::isPath( SimObject *pObject ) +{ + return ( dynamic_cast( pObject ) != NULL ); +} + +bool VTorque::isPathObjectAttached( PathObjectType *pPath, SceneObjectType *pObject ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return false; + } + + // Return. + return pPath->isObjectAttached( pObject ); +} + +F32 VTorque::getPathNodeLength( PathObjectType *pPath, const S32 &pNode ) +{ + if ( !pPath ) + { + // Sanity! + return false; + } + + // Normalize Node Index. + S32 nodeIndex = pNode; + pPath->normalizeNodeIndex( nodeIndex ); + + // Fetch Node. + VPathNode *node = pPath->getNode( nodeIndex ); + + // Return Length. + return node->getLength(); +} + +void VTorque::attachPathObject( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward, const bool &pRelative, const S32 &pStartNodeIndex, const S32 &pEndNodeIndex, const String &pOrientation, const String &pOrientationData ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Attach Object. + _attachPathObject( pPath, pObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Attach Object. + _attachPathObject( clientPath, clientObject, pForward, pRelative, pStartNodeIndex, pEndNodeIndex, pOrientation, pOrientationData ); + } + +#endif +} + +void VTorque::detachPathObject( PathObjectType *pPath, SceneObjectType *pObject ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Detach Object. + pPath->detachObject( pObject ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Detach Object. + clientPath->detachObject( clientObject ); + } + +#endif +} + +void VTorque::setPathObjectActive( PathObjectType *pPath, SceneObjectType *pObject, const bool &pActive ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object State. + pPath->setPathObjectActive( pObject, pActive ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object State. + clientPath->setPathObjectActive( clientObject, pActive ); + } + +#endif +} + +void VTorque::setPathObjectInterp( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pInterp ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Interp. + pPath->setPathObjectInterp( pObject, pInterp ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectInterp( clientObject, pInterp ); + } + +#endif +} + +void VTorque::setPathObjectOffset( PathObjectType *pPath, SceneObjectType *pObject, const Point3F &pOffset ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Offset. + pPath->setPathObjectOffset( pObject, pOffset ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectOffset( clientObject, pOffset ); + } + +#endif +} + +void VTorque::setPathObjectSpeed( PathObjectType *pPath, SceneObjectType *pObject, const F32 &pSpeed ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Speed. + pPath->setPathObjectSpeed( pObject, pSpeed ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectSpeed( clientObject, pSpeed ); + } + +#endif +} + +void VTorque::setPathObjectOrientation( PathObjectType *pPath, SceneObjectType *pObject, const String &pOrientation, const String &pOrientationData ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Set the orientation mode. + // Note: Call the console method so we don't have to handle all the different modes here. + Con::executef( pPath, "setPathObjectOrientationMode", pObject->getIdString(), pOrientation, pOrientationData ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // TODO: Handle synching the client path immediately. + +#endif + + /* + // Set the Default Mode. + if ( pOrientation == String::EmptyString ) + { + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, VPathObject::k_OrientationToPath ); + return; + } + + // Fetch Orientation. + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( pOrientation ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + + // Fetch Object. + SceneObjectType *lookAtObject; + if ( !Sim::findObject( pOrientationData, lookAtObject ) ) + { + // Invalid Object. + return; + } + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type, lookAtObject ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( pOrientationData, "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + pPath->setPathObjectOrientationMode( pObject, type, lookAtPoint ); + + } break; + } + */ +} + +void VTorque::setPathObjectForward( PathObjectType *pPath, SceneObjectType *pObject, const bool &pForward ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Path Object Forward. + pPath->setPathObjectForward( pObject, pForward ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Apply the same action. + clientPath->setPathObjectForward( clientObject, pForward ); + } + +#endif +} + +void VTorque::setPathObjectNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object Current Node. + pPath->setPathObjectNode( pObject, pNode ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object Current Node. + clientPath->setPathObjectNode( clientObject, pNode ); + } + +#endif +} + +void VTorque::setPathObjectEndNode( PathObjectType *pPath, SceneObjectType *pObject, const S32 &pNode ) +{ + if ( !pPath || !pObject ) + { + // Sanity! + return; + } + + // Update Object End Node. + pPath->setPathObjectEndNode( pObject, pNode ); + +#if defined( VT_EDITOR ) && defined( VT_SYNC_LOCALCLIENT ) + + // Fetch the client Path. + VPath *clientPath = dynamic_cast( getClientObject( pPath ) ); + SceneObjectType *clientObject = dynamic_cast( getClientObject( pObject ) ); + if ( clientPath && clientObject ) + { + // Update Object End Node. + clientPath->setPathObjectEndNode( clientObject, pNode ); + } + +#endif +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VParticleEffect.cpp b/Engine/source/Verve/Torque3D/VParticleEffect.cpp new file mode 100644 index 000000000..b1e35b5a1 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VParticleEffect.cpp @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/Torque/TParticleEffect.h" + +//----------------------------------------------------------------------------- +// +// Particle Effect Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isParticleEffectEnabled( ParticleEffectType *pParticleEffect ) +{ + if ( !pParticleEffect ) + { + // Sanity! + return false; + } + + // Get Active. + return pParticleEffect->getActive(); +} + +void VTorque::setParticleEffectOn( ParticleEffectType *pParticleEffect, const bool &pStatus ) +{ + if ( !pParticleEffect ) + { + // Sanity! + return; + } + + // Set Active. + pParticleEffect->setActive( pStatus ); +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VPostEffect.cpp b/Engine/source/Verve/Torque3D/VPostEffect.cpp new file mode 100644 index 000000000..e9f245790 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VPostEffect.cpp @@ -0,0 +1,152 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque3D/VPostEffect.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +// +// Post Effect Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isPostEffectEnabled( PostEffectType *pPostEffect ) +{ + if ( !pPostEffect ) + { + // Sanity! + return false; + } + + return pPostEffect->isEnabled(); +} + +void VTorque::setPostEffectOn( PostEffectType *pPostEffect, const bool &pStatus ) +{ + if ( !pPostEffect ) + { + // Sanity! + return; + } + +#ifdef VT_EDITOR + + if ( pStatus ) + { + // Enable Effect. + pPostEffect->enable(); + } + else + { + // Disable Effect. + pPostEffect->disable(); + } + +#else + + // Fetch Name. + StringTableEntry name = pPostEffect->getName(); + if ( !name || name == StringTable->insert( "" ) ) + { + Con::warnf( "VTorque::setPostEffectOn() - Invalid Object Name." ); + return; + } + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VPostEffectNetEvent *event = new VPostEffectNetEvent(); + + // Setup Event. + event->mPostEffect = name; + event->mEnabled = pStatus; + + // Post Event. + connection->postNetEvent( event ); + } + } + +#endif +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VPostEffectNetEvent ); +//----------------------------------------------------------------------------- + +VPostEffectNetEvent::VPostEffectNetEvent( void ) : mPostEffect( StringTable->insert( "" ) ), + mEnabled( false ) +{ + // Void. +} + +void VPostEffectNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VPostEffectNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Object Name. + pStream->writeString( mPostEffect ); + + // Status. + pStream->writeFlag( mEnabled ); +} + +void VPostEffectNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Object Name. + mPostEffect = pStream->readSTString(); + + // Status. + mEnabled = pStream->readFlag(); +} + +void VPostEffectNetEvent::process( NetConnection *pConnection ) +{ + PostEffect *postEffect; + if ( !Sim::findObject( mPostEffect, postEffect ) ) + { + Con::warnf( "VPostEffectNetEvent::process() - Unable to find PostEffect Object '%s'", mPostEffect ); + return; + } + + if ( mEnabled ) + { + // Enable Effect. + postEffect->enable(); + } + else + { + // Disable Effect. + postEffect->disable(); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VPostEffect.h b/Engine/source/Verve/Torque3D/VPostEffect.h new file mode 100644 index 000000000..bbb64aecc --- /dev/null +++ b/Engine/source/Verve/Torque3D/VPostEffect.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_POSTEFFECT_H_ +#define _VT_VTORQUE3D_POSTEFFECT_H_ + +#ifndef _VT_TORQUE_POSTEFFECT_H_ +#include "Verve/Torque/TPostEffect.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VPostEffectNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + StringTableEntry mPostEffect; + bool mEnabled; + +public: + + VPostEffectNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VPostEffectNetEvent ); +}; + +#endif // _VT_VTORQUE3D_POSTEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VSoundEffect.cpp b/Engine/source/Verve/Torque3D/VSoundEffect.cpp new file mode 100644 index 000000000..8dda926c3 --- /dev/null +++ b/Engine/source/Verve/Torque3D/VSoundEffect.cpp @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "Verve/VerveConfig.h" +#include "Verve/Torque3D/VSoundEffect.h" + +#include "T3D/gameBase/gameConnection.h" +#include "core/stream/bitStream.h" +#include "math/mathIO.h" +#include "sfx/sfxSystem.h" +#include "sfx/sfxDescription.h" + +//----------------------------------------------------------------------------- +// +// Sound Methods. +// +//----------------------------------------------------------------------------- + +bool VTorque::isSoundLooping( SoundEffectType *pSoundProfile ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return false; + } + + // Return Looping. + return pSoundProfile->getDescription()->mIsLooping; +} + +S32 VTorque::getSoundDuration( SoundEffectType *pSoundProfile ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return 0; + } + + // Return Duration. + return pSoundProfile->getSoundDuration(); +} + +VTorque::SoundSourceType *VTorque::playSound( SoundEffectType *pSoundProfile, const U32 &pPosition, const F32 &pPitch ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return NULL; + } + +#ifdef VT_EDITOR + + // Play Sound. + SFXSound *source = ( SFXSound* )SFX->playOnce( pSoundProfile ); + + if ( source ) + { + // Set Position. + source->setPosition( pPosition ); + + // Set Pitch. + source->setPitch( pPitch ); + } + + // Return Source. + return source; + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VSoundEffectNetEvent *event = new VSoundEffectNetEvent(); + + // Setup Event. + event->mProfile = pSoundProfile; + event->mPosition = pPosition; + event->mPitch = pPitch; + event->mIs3D = false; + + // Post Event. + connection->postNetEvent( event ); + } + } + + return NULL; + +#endif +} + +VTorque::SoundSourceType *VTorque::playSound( SoundEffectType *pSoundProfile, SceneObjectType *pObject, const U32 &pPosition, const F32 &pPitch ) +{ + if ( !pSoundProfile ) + { + // Sanity! + return NULL; + } + +#ifdef VT_EDITOR + + // Fetch Reference Transform. + const MatrixF &transform = pObject->getTransform(); + + // Play Sound. + SFXSound *source = ( SFXSound* )SFX->playOnce( pSoundProfile, &transform ); + + if ( source ) + { + // Set Position. + source->setPosition( pPosition ); + + // Set Pitch. + source->setPitch( pPitch ); + } + + // Return Source. + return source; + +#else + + // Fetch Client Group. + SimGroup* clientGroup = Sim::getClientGroup(); + + for ( SimGroup::iterator itr = clientGroup->begin(); itr != clientGroup->end(); itr++ ) + { + NetConnection *connection = static_cast( *itr ); + if ( connection ) + { + // Create Event. + VSoundEffectNetEvent *event = new VSoundEffectNetEvent(); + + // Setup Event. + event->mProfile = pSoundProfile; + event->mPosition = pPosition; + event->mPitch = pPitch; + event->mIs3D = true; + event->mTransform = pObject->getTransform(); + + // Post Event. + connection->postNetEvent( event ); + } + } + + return NULL; + +#endif +} + +void VTorque::playSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Play. + pSource->play(); +} + +void VTorque::pauseSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Pause. + pSource->pause(); +} + +void VTorque::stopSound( SoundSourceType *pSource ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Stop. + pSource->stop(); +} + +void VTorque::setSoundPosition( SoundSourceType *pSource, const U32 &pPosition ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Set Position. + pSource->setPosition( pPosition ); +} + +void VTorque::setSoundPitch( SoundSourceType *pSource, const F32 &pPitch ) +{ + if ( !pSource ) + { + // Sanity! + return; + } + + // Set Pitch. + pSource->setPitch( pPitch ); +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_CLIENTEVENT_V1( VSoundEffectNetEvent ); +//----------------------------------------------------------------------------- + +VSoundEffectNetEvent::VSoundEffectNetEvent( void ) : mProfile( NULL ), + mPosition( 0.f ), + mPitch( 1.f ), + mIs3D( false ), + mTransform( MatrixF::Identity ) +{ + // Void. +} + +void VSoundEffectNetEvent::write( NetConnection *pConnection, BitStream *pStream ) +{ + // Void. +} + +void VSoundEffectNetEvent::pack( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid? + if ( !pStream->writeFlag( mProfile != NULL ) ) + { + return; + } + + // Profile. + pStream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize ); + + // Position. + pStream->write( mPosition ); + + // Pitch. + pStream->write( mPitch ); + + // 3D? + if ( pStream->writeFlag( mIs3D ) ) + { + // Rotation. + SFXDescription* description = mProfile->getDescription(); + if ( pStream->writeFlag( description->mConeInsideAngle || description->mConeOutsideAngle ) ) + { + // Entire Transform. + pStream->writeAffineTransform( mTransform ); + } + else + { + // Position. + mathWrite( *pStream, mTransform.getColumn3F( 3 ) ); + } + } +} + +void VSoundEffectNetEvent::unpack( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid? + if ( !pStream->readFlag() ) + { + return; + } + + // Profile. + Sim::findObject( pStream->readInt( DataBlockObjectIdBitSize ) + DataBlockObjectIdFirst, mProfile ); + + // Position. + pStream->read( &mPosition ); + + // Pitch. + pStream->read( &mPitch ); + + // 3D? + if ( pStream->readFlag() ) + { + // Yup! + mIs3D = true; + + // Rotation? + if ( pStream->readFlag() ) + { + // Transform. + pStream->readAffineTransform( &mTransform ); + } + else + { + // Position. + Point3F pos; + mathRead( *pStream, &pos ); + mTransform.setColumn( 3, pos ); + } + } +} + +void VSoundEffectNetEvent::process( NetConnection *pConnection ) +{ + // Valid? + if ( !mProfile ) + { + return; + } + + SFXSound *source = NULL; + if ( mIs3D ) + { + // Play 3D Sound. + source = ( SFXSound* )SFX->playOnce( mProfile, &mTransform ); + } + else + { + // Play 2D Sound. + source = ( SFXSound* )SFX->playOnce( mProfile ); + } + + if ( source ) + { + // Set Position. + source->setPosition( mPosition ); + + // Set Pitch. + source->setPitch( mPitch ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VSoundEffect.h b/Engine/source/Verve/Torque3D/VSoundEffect.h new file mode 100644 index 000000000..812f8f89c --- /dev/null +++ b/Engine/source/Verve/Torque3D/VSoundEffect.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VTORQUE3D_SOUNDEFFECT_H_ +#define _VT_VTORQUE3D_SOUNDEFFECT_H_ + +#ifndef _VT_TORQUE_SOUNDEFFECT_H_ +#include "Verve/Torque/TSoundEffect.h" +#endif + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +class VSoundEffectNetEvent : public NetEvent +{ + typedef NetEvent Parent; + +public: + + SFXProfile *mProfile; + + F32 mPosition; + F32 mPitch; + + bool mIs3D; + MatrixF mTransform; + +public: + + VSoundEffectNetEvent( void ); + + void write( NetConnection *pConnection, BitStream *pStream ); + void pack( NetConnection *pConnection, BitStream *pStream ); + void unpack( NetConnection *pConnection, BitStream *pStream ); + void process( NetConnection *pConnection ); + + DECLARE_CONOBJECT( VSoundEffectNetEvent ); +}; + +#endif // _VT_VTORQUE3D_SOUNDEFFECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/Torque3D/VSpawnSphere.cpp b/Engine/source/Verve/Torque3D/VSpawnSphere.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.cpp new file mode 100644 index 000000000..240c4d0b0 --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.cpp @@ -0,0 +1,259 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActor.h" + +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VHumanoidActor ); +//----------------------------------------------------------------------------- + +VHumanoidActor::VHumanoidActor( void ) +{ + // Void. +} + +VHumanoidActor::~VHumanoidActor( void ) +{ + // Void. +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::onNewDataBlock( pDataBlock ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::onNewDataBlock( GameBaseData *pDataBlock, bool pReload ) +{ + // Store DataBlock Reference. + mDataBlock = dynamic_cast( pDataBlock ); + + // Valid Data? + if ( !mDataBlock || !Parent::onNewDataBlock( pDataBlock, pReload ) ) + { + // Invalid Data. + return false; + } + + // Initialise the Controllers. + if ( !initAnimationController() || !initPhysicsController() ) + { + // Invalid. + return false; + } + + // Initialise the Base Animation Thread. + mAnimationController.initBaseAnimation( VHumanoidActorData::k_IdleAnimation, 0.f, 1.f ); + // Initialise the Arm Animation Thread. + mAnimationController.initArmAnimation( VHumanoidActorData::k_ArmsUpDownAnimation, 0.5f, 1.f ); + + /* + // Initialise Head Threads. + initAnimationSequence( VHumanoidActorData::k_HeadHorizontalAnimation, mHeadAnimation.HThread, 0.5f ); + initAnimationSequence( VHumanoidActorData::k_HeadVerticalAnimation, mHeadAnimation.VThread, 0.5f ); + */ + + // Valid Data. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::processTick( pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::processTick( const Move *pMove ) +{ + // Parent Call. + Parent::processTick( pMove ); + + // Update Physics. + mPhysicsController.update( TickSec, pMove ); + + // Update Container. + updateContainer(); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::interpolateTick( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::interpolateTick( F32 pDelta ) +{ + // Parent Call. + Parent::interpolateTick( pDelta ); + + // Update Physics. + mPhysicsController.interpolateTick( pDelta ); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::advanceTime( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::advanceTime( F32 pDelta ) +{ + // Parent Call. + Parent::advanceTime( pDelta ); + + // Valid Animation Controller? + if ( getAnimationController() ) + { + // Update Animations. + getAnimationController()->update( pDelta ); + } +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VHumanoidActor::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Parent Call. + U32 retMask = Parent::packUpdate( pConnection, pMask, pStream ); + + // Physics Controller? + if ( pStream->writeFlag( pMask & PhysicsMask ) ) + { + // Pack Physics. + retMask &= mPhysicsController.packUpdate( pConnection, pMask, pStream ); + } + + return retMask; +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VHumanoidActor::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Parent Call. + Parent::unpackUpdate( pConnection, pStream ); + + // Physics Controller? + if ( pStream->readFlag() ) + { + // Unpack Physics. + mPhysicsController.unpackUpdate( pConnection, pStream ); + } +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::initAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::initAnimationController( void ) +{ + // Reference Object. + mAnimationController.setObject( this ); + // Initialise. + return mAnimationController.initAnimationTable(); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::getAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +VActorAnimationController *VHumanoidActor::getAnimationController( void ) +{ + return &mAnimationController; +} + + + + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::initPhysicsController(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VHumanoidActor::initPhysicsController( void ) +{ + // Initialise. + return mPhysicsController.initPhysicsController( this ); +} + +//----------------------------------------------------------------------------- +// +// VHumanoidActor::getAnimationController(); +// +// ... +// +//----------------------------------------------------------------------------- +VActorPhysicsController *VHumanoidActor::getPhysicsController( void ) +{ + return &mPhysicsController; +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.h new file mode 100644 index 000000000..65ecb22bf --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActor.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTOR_H_ +#define _VT_VHUMANOIDACTOR_H_ + +#ifndef _VT_VACTOR_H_ +#include "../VActor.h" +#endif + +#ifndef _VT_VHUMANOIDACTORDATA_H_ +#include "VHumanoidActorData.h" +#endif + +#ifndef _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ +#include "VHumanoidActorAnimationController.h" +#endif + +#ifndef _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ +#include "VHumanoidActorPhysicsController.h" +#endif + +//----------------------------------------------------------------------------- + +class VHumanoidActor : public VActor +{ + typedef VActor Parent; + +protected: + + VHumanoidActorAnimationController mAnimationController; + VHumanoidActorPhysicsController mPhysicsController; + +public: + + VHumanoidActor( void ); + ~VHumanoidActor( void ); + + // Initialisation Methods. + + bool onNewDataBlock( GameBaseData *pDataBlock, bool pReload ); + + // Update Methods. + + void processTick( const Move *pMove ); + void interpolateTick( F32 pDelta ); + void advanceTime( F32 pDelta ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + // Animation Methods. + + bool initAnimationController( void ); + VActorAnimationController *getAnimationController( void ); + + // Physics Methods. + + bool initPhysicsController( void ); + VActorPhysicsController *getPhysicsController( void ); + + DECLARE_CONOBJECT( VHumanoidActor ); +}; + +#endif // _VT_VHUMANOIDACTOR_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp new file mode 100644 index 000000000..e6a1e4521 --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.cpp @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorAnimationController.h" + +//----------------------------------------------------------------------------- + +VHumanoidActorAnimationController::VHumanoidActorAnimationController( void ) +{ + // Void. +} + +VHumanoidActorAnimationController::~VHumanoidActorAnimationController( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- + +bool VHumanoidActorAnimationController::initArmAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Initialise Animation Ref. + return initAnimation( mArmAnimation, pIndex, pPosition, pTimeScale ); +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods +// +//----------------------------------------------------------------------------- + +void VHumanoidActorAnimationController::update( const F32 &pDelta ) +{ + // Parent Call. + VActorAnimationController::update( pDelta ); + + // Update the Look Thread. + if ( mArmAnimation.Thread ) + { + // Set Position. + getShapeInstance()->setPos( mArmAnimation.Thread, 0.5f ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h new file mode 100644 index 000000000..adf77fc0d --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorAnimationController.h @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ +#define _VT_VHUMANOIDACTORANIMATIONCONTROLLER_H_ + +#ifndef _VT_VACTORANIMATIONCONTROLLER_H_ +#include "../VActorAnimationController.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VHumanoidActorAnimationController : public VActorAnimationController +{ +public: + + /* + struct sHeadAnimation + { + S32 HSequence; + TSThread *HThread; + Range HRange; + + S32 VSequence; + TSThread *VThread; + Range VRange; + + S32 FaceSequence; + TSThread *FaceThread; + + sHeadAnimation( void ) : + HSequence( -1 ), + HThread( NULL ), + HRange( 0.f, 1.f ), + VSequence( -1 ), + VThread( NULL ), + VRange( 0.f, 1.f ) + { + // Void. + } + }; + */ + +protected: + + //sHeadAnimation mHeadAnimation; + + sAnimationRef mHeadHAnimation; + sAnimationRef mHeadVAnimation; + sAnimationRef mArmAnimation; + +public: + + VHumanoidActorAnimationController( void ); + virtual ~VHumanoidActorAnimationController( void ); + + // Initialisation Methods. + + bool initArmAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + // Animation Methods. + + void update( const F32 &pDelta ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.cpp new file mode 100644 index 000000000..46a9eb448 --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.cpp @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorData.h" +#include "VHumanoidAnimationStates.h" +#include "VHumanoidPhysicsStates.h" + +//----------------------------------------------------------------------------- +// Animation Table. +//----------------------------------------------------------------------------- + +static VActorData::sAnimationSequence animSequenceLookup[] = + { + // State Based Animations. + { VHumanoidActorData::k_IdleAnimation, "root", 0.0f, ActorAnimationStateInstance( HumanoidIdle ) }, + + { VHumanoidActorData::k_WalkForwardAnimation, "walk", 0.1f, ActorAnimationStateInstance( HumanoidWalkForward ) }, + { VHumanoidActorData::k_WalkBackwardAnimation, "walkback", 0.1f, ActorAnimationStateInstance( HumanoidWalkBackward ) }, + + { VHumanoidActorData::k_RunForwardAnimation, "run", 0.1f, ActorAnimationStateInstance( HumanoidRunForward ) }, + { VHumanoidActorData::k_RunBackwardAnimation, "runback", 0.1f, ActorAnimationStateInstance( HumanoidRunBackward ) }, + + { VHumanoidActorData::k_SwimIdleAnimation, "swimroot", 1.0f, ActorAnimationStateInstance( HumanoidSwimIdle ) }, + { VHumanoidActorData::k_SwimForwardAnimation, "swim", 1.0f, ActorAnimationStateInstance( HumanoidSwimForward ) }, + { VHumanoidActorData::k_SwimBackwardAnimation, "swimback", 1.0f, ActorAnimationStateInstance( HumanoidSwimBackward ) }, + + // Support Animations. + { VHumanoidActorData::k_HeadHorizontalAnimation, "headside" }, + { VHumanoidActorData::k_HeadVerticalAnimation, "head" }, + + { VHumanoidActorData::k_ArmsUpDownAnimation, "look" }, + }; + +//----------------------------------------------------------------------------- +// Physics Table. +//----------------------------------------------------------------------------- + +static VActorData::sPhysicsState physStateLookup[] = + { + { VHumanoidActorData::k_OnGroundPhysics, 0.f, ActorPhysicsStateInstance( HumanoidOnGround ) }, + { VHumanoidActorData::k_InAirPhysics, 0.f, ActorPhysicsStateInstance( HumanoidInAir ) }, + { VHumanoidActorData::k_InWaterPhysics, 0.f, ActorPhysicsStateInstance( HumanoidInWater ) }, + }; + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_DATABLOCK_V1( VHumanoidActorData ); +//----------------------------------------------------------------------------- + +VHumanoidActorData::VHumanoidActorData( void ) +{ + // Void. +}; + +bool VHumanoidActorData::preload( bool pServer, String &pErrorStr ) +{ + if ( !Parent::preload( pServer, pErrorStr ) ) + { + return false; + } + + // Initialise Animation List. + if ( !initAnimationSequenceList( sizeof( animSequenceLookup ) / sizeof( VActorData::sAnimationSequence ), &animSequenceLookup[0] ) ) + { + Con::errorf( "VHumanoidActorData::preload() - Failed to Initialise Actor Animations." ); + return false; + } + + // Initialise Physics State List. + if ( !initPhysicsStateList( sizeof( physStateLookup ) / sizeof( VActorData::sPhysicsState ), &physStateLookup[0] ) ) + { + Con::errorf( "VHumanoidActorData::preload() - Failed to Initialise Actor Physics States." ); + return false; + } + + // Valid Load. + return true; +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.h new file mode 100644 index 000000000..0a5aa4b8c --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorData.h @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORDATA_H_ +#define _VT_VHUMANOIDACTORDATA_H_ + +#ifndef _VT_VACTORDATA_H_ +#include "../VActorData.h" +#endif + +//----------------------------------------------------------------------------- + +struct VHumanoidActorData : public VActorData +{ +private: + + typedef VActorData Parent; + friend class VHumanoidActor; + +public: + + enum eAnimationList + { + k_IdleAnimation = Parent::k_NextAnimation + 0, + + k_WalkForwardAnimation = Parent::k_NextAnimation + 1, + k_WalkBackwardAnimation = Parent::k_NextAnimation + 2, + + k_RunForwardAnimation = Parent::k_NextAnimation + 3, + k_RunBackwardAnimation = Parent::k_NextAnimation + 4, + + k_SwimIdleAnimation = Parent::k_NextAnimation + 5, + k_SwimForwardAnimation = Parent::k_NextAnimation + 6, + k_SwimBackwardAnimation = Parent::k_NextAnimation + 7, + + k_HeadHorizontalAnimation = Parent::k_NextAnimation + 8, + k_HeadVerticalAnimation = Parent::k_NextAnimation + 9, + + k_ArmsUpDownAnimation = Parent::k_NextAnimation + 10, + + k_NextAnimation = Parent::k_NextAnimation + 11, + }; + + enum ePhysicsStateList + { + k_OnGroundPhysics = Parent::k_NextPhysicsState + 0, + k_InAirPhysics = Parent::k_NextPhysicsState + 1, + k_InWaterPhysics = Parent::k_NextPhysicsState + 2, + + k_NextPhysicsState = Parent::k_NextPhysicsState + 3, + }; + +public: + + VHumanoidActorData( void ); + + virtual bool preload( bool pServer, String &pErrorStr ); + + DECLARE_CONOBJECT( VHumanoidActorData ); +}; + +#endif // _VT_VHUMANOIDACTORDATA_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp new file mode 100644 index 000000000..ae205c5cf --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.cpp @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidActorPhysicsController.h" + +//----------------------------------------------------------------------------- + +VHumanoidActorPhysicsController::VHumanoidActorPhysicsController( void ) +{ + // Void. +} + +VHumanoidActorPhysicsController::~VHumanoidActorPhysicsController( void ) +{ + // Void. +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h new file mode 100644 index 000000000..ef984210a --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidActorPhysicsController.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ +#define _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ + +#ifndef _VT_VACTORPHYSICSCONTROLLER_H_ +#include "../VActorPhysicsController.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VHumanoidActorPhysicsController : public VActorPhysicsController +{ +public: + + VHumanoidActorPhysicsController( void ); + ~VHumanoidActorPhysicsController( void ); +}; + +#endif // _VT_VHUMANOIDACTORPHYSICSCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp new file mode 100644 index 000000000..3ca29f7ce --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.cpp @@ -0,0 +1,213 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidAnimationStates.h" +#include "VHumanoidActor.h" + +#include "../VActorAnimationController.h" +#include "../VActorPhysicsController.h" + +//----------------------------------------------------------------------------- +// +// Implement Animation States. +// +//----------------------------------------------------------------------------- + +ImplementActorAnimationState( HumanoidIdle, VHumanoidActorData::k_IdleAnimation ); + +ImplementActorAnimationState( HumanoidWalkForward, VHumanoidActorData::k_WalkForwardAnimation ); +ImplementActorAnimationState( HumanoidWalkBackward, VHumanoidActorData::k_WalkBackwardAnimation ); + +ImplementActorAnimationState( HumanoidRunForward, VHumanoidActorData::k_RunForwardAnimation ); +ImplementActorAnimationState( HumanoidRunBackward, VHumanoidActorData::k_RunBackwardAnimation ); + +ImplementActorAnimationState( HumanoidSwimIdle, VHumanoidActorData::k_SwimIdleAnimation ); +ImplementActorAnimationState( HumanoidSwimForward, VHumanoidActorData::k_SwimForwardAnimation ); +ImplementActorAnimationState( HumanoidSwimBackward, VHumanoidActorData::k_SwimBackwardAnimation ); + + + + +//----------------------------------------------------------------------------- +// +// Execute Animation States. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// OnGround Animation States +// +//----------------------------------------------------------------------------- + +ExecuteActorAnimationState( HumanoidIdle ) +{ + // Always Enter. + return true; +} + +ExecuteActorAnimationState( HumanoidWalkForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Forward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Forward & Slow Enough? + return ( ( physicsController->getMoveState() & k_ForwardMove ) && + ( moveSpeed < pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidWalkBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Backward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Backward? + return ( ( physicsController->getMoveState() & k_BackwardMove ) && + ( moveSpeed < pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidRunForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Forward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Forward? + return ( ( physicsController->getMoveState() & k_ForwardMove ) && + ( moveSpeed >= pObject->getDataBlock()->getRunSpeed() ) ); +} + +ExecuteActorAnimationState( HumanoidRunBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_OnGroundPhysics ) + { + // Can't Run Backward. + return false; + } + + // Fetch Velocity. + const VectorF &velocity = physicsController->getVelocity(); + // Determine Move Speed. + const F32 moveSpeed = mSqrt( velocity.x * velocity.x + velocity.y * velocity.y ); + + // Moving Backward? + return ( ( physicsController->getMoveState() & k_BackwardMove ) && + ( moveSpeed >= pObject->getDataBlock()->getRunSpeed() ) ); +} + + + + +//----------------------------------------------------------------------------- +// +// InWater Animation States +// +//----------------------------------------------------------------------------- + +ExecuteActorAnimationState( HumanoidSwimIdle ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Idle? + return ( physicsController->getMoveState() & k_NullMove ); +} + +ExecuteActorAnimationState( HumanoidSwimForward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Moving Around? + return ( physicsController->getMoveState() & ( k_ForwardMove | + k_UpMove | + k_DownMove ) ); +} + +ExecuteActorAnimationState( HumanoidSwimBackward ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Water? + if ( physicsController->getPhysicsState() != VHumanoidActorData::k_InWaterPhysics ) + { + // Can't Swim. + return false; + } + + // Moving Backward? + return ( physicsController->getMoveState() & k_BackwardMove ); +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.h new file mode 100644 index 000000000..d71967d54 --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidAnimationStates.h @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDANIMATIONSTATES_H_ +#define _VT_VHUMANOIDANIMATIONSTATES_H_ + +#ifndef _VT_VACTORANIMATIONSTATES_H_ +#include "../VActorAnimationStates.h" +#endif + +//----------------------------------------------------------------------------- + +DeclareActorAnimationState( HumanoidIdle ); + +DeclareActorAnimationState( HumanoidWalkForward ); +DeclareActorAnimationState( HumanoidWalkBackward ); + +DeclareActorAnimationState( HumanoidRunForward ); +DeclareActorAnimationState( HumanoidRunBackward ); + +DeclareActorAnimationState( HumanoidSwimIdle ); +DeclareActorAnimationState( HumanoidSwimForward ); +DeclareActorAnimationState( HumanoidSwimBackward ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VHUMANOIDANIMATIONSTATES_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp b/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp new file mode 100644 index 000000000..c2b8492ba --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.cpp @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VHumanoidPhysicsStates.h" +#include "VHumanoidActor.h" + +#include "../VActorPhysicsController.h" + +//----------------------------------------------------------------------------- +// +// Implement Physics States. +// +//----------------------------------------------------------------------------- + +ImplementActorPhysicsState( HumanoidOnGround, VHumanoidActorData::k_OnGroundPhysics ); +ImplementActorPhysicsState( HumanoidInAir, VHumanoidActorData::k_InAirPhysics ); +ImplementActorPhysicsState( HumanoidInWater, VHumanoidActorData::k_InWaterPhysics ); + + + + +//----------------------------------------------------------------------------- +// +// Execute Animation States. +// +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidOnGround ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // On the Ground? + if ( !physicsController->isOnGround() ) + { + // No. + return false; + } + + // On Ground. + return true; +} + +ProcessActorPhysicsState( HumanoidOnGround ) +{ + // Void. +} + +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidInAir ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // In the Air? + if ( !physicsController->isInAir() ) + { + // No. + return false; + } + + // In Air. + return true; +} + +ProcessActorPhysicsState( HumanoidInAir ) +{ + // Apply Gravity for the Tick. + pObject->getPhysicsController()->applyGravity( pElapsedTime ); +} + +//----------------------------------------------------------------------------- + +ExecuteActorPhysicsState( HumanoidInWater ) +{ + // Fetch Controller. + VActorPhysicsController *physicsController = pObject->getPhysicsController(); + + // Sumberged? + if ( !physicsController->isInWater() ) + { + // No. + return false; + } + + // Swimming + return true; +} + +ProcessActorPhysicsState( HumanoidInWater ) +{ + // Void. +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h b/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h new file mode 100644 index 000000000..8020d53f5 --- /dev/null +++ b/Engine/source/Verve/VActor/Humanoid/VHumanoidPhysicsStates.h @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VHUMANOIDPHYSICSSTATES_H_ +#define _VT_VHUMANOIDPHYSICSSTATES_H_ + +#ifndef _VT_VACTORPHYSICSSTATES_H_ +#include "../VActorPhysicsStates.h" +#endif + +//----------------------------------------------------------------------------- + +DeclareActorPhysicsState( HumanoidOnGround ); +DeclareActorPhysicsState( HumanoidInAir ); +DeclareActorPhysicsState( HumanoidInWater ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VHUMANOIDPHYSICSSTATES_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Types/VEnumerators.h b/Engine/source/Verve/VActor/Types/VEnumerators.h new file mode 100644 index 000000000..2300330db --- /dev/null +++ b/Engine/source/Verve/VActor/Types/VEnumerators.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_ENUMERATORS_H_ +#define _VT_ENUMERATORS_H_ + +//----------------------------------------------------------------------------- + +enum eMove +{ + k_NullMove = 0, + + k_ForwardMove = ( 1 << 0 ), + k_BackwardMove = ( 1 << 1 ), + k_LeftMove = ( 1 << 2 ), + k_RightMove = ( 1 << 3 ), + k_UpMove = ( 1 << 4 ), + k_DownMove = ( 1 << 5 ), + + k_XMove = ( k_LeftMove | k_RightMove ), + k_YMove = ( k_ForwardMove | k_BackwardMove ), + k_ZMove = ( k_UpMove | k_DownMove ), +}; + +enum eControlState +{ + k_NullControlState = 0, + + k_PathControlState, + k_GoToControlState, +}; + +#endif // _VT_ENUMERATORS_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Types/VRange.h b/Engine/source/Verve/VActor/Types/VRange.h new file mode 100644 index 000000000..bb28a27e5 --- /dev/null +++ b/Engine/source/Verve/VActor/Types/VRange.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TYPERANGE_H_ +#define _VT_TYPERANGE_H_ + +#ifndef _TORQUE_TYPES_H_ +#include "platform/types.h" +#endif + +class Range +{ +public: + + Range( void ) : + Min( 0.f ), + Max( 1.f ), + Delta( 1.f ) + { + // Void. + }; + + Range( F32 pMin, F32 pMax ) : + Min( pMin ), + Max( pMax ), + Delta( pMax - pMin ) + { + // Void. + }; + + F32 Min; + F32 Max; + F32 Delta; +}; + +#endif // _VT_TYPERANGE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/Types/VTypes.h b/Engine/source/Verve/VActor/Types/VTypes.h new file mode 100644 index 000000000..cc6c4918d --- /dev/null +++ b/Engine/source/Verve/VActor/Types/VTypes.h @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_TYPES_H_ +#define _VT_TYPES_H_ + +#ifndef _VT_ENUMERATORS_H_ +#include "VEnumerators.h" +#endif + +#ifndef _VT_TYPERANGE_H_ +#include "VRange.h" +#endif + +#endif // _VT_TYPES_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActor.cpp b/Engine/source/Verve/VActor/VActor.cpp new file mode 100644 index 000000000..97dcb0257 --- /dev/null +++ b/Engine/source/Verve/VActor/VActor.cpp @@ -0,0 +1,232 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActor.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VActor ); +//----------------------------------------------------------------------------- + +VActor::VActor( void ) : + mDataBlock( NULL ) +{ + // Void. +} + +VActor::~VActor( void ) +{ + // Void. +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::onAdd(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActor::onAdd( void ) +{ + if ( !Parent::onAdd() || !mDataBlock ) + { + return false; + } + + // Add to Scene. + addToScene(); + + if ( isServerObject() ) + { + // Script Callback. + scriptOnAdd(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// VActor::onRemove(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onRemove( void ) +{ + // Script Callback. + scriptOnRemove(); + + // Remove From Scene. + removeFromScene(); + + Parent::onRemove(); +} + +//----------------------------------------------------------------------------- +// +// VActor::onNewDataBlock( pDataBlock ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActor::onNewDataBlock( GameBaseData *pDataBlock, bool pReload ) +{ + // Store DataBlock Reference. + mDataBlock = dynamic_cast( pDataBlock ); + + if ( !mDataBlock ) + { + // Invalid Data. + return false; + } + + // Parent Call. + return Parent::onNewDataBlock( pDataBlock, pReload ); +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::processTick( pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::processTick( const Move *pMove ) +{ + // Parent Call. + Parent::processTick( pMove ); + + // Triggers? + if ( pMove && mDamageState == Enabled ) + { + // Handle each Image Trigger. + const U32 imageCount = getMin( ShapeBase::MaxMountedImages, MaxTriggerKeys ); + for ( U32 i = 0; i < imageCount; i++ ) + { + setImageTriggerState( i, pMove->trigger[i] ); + } + } +} + +//----------------------------------------------------------------------------- +// +// VActor::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActor::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Parent Call. + return Parent::packUpdate( pConnection, pMask, pStream ); +} + +//----------------------------------------------------------------------------- +// +// VActor::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Parent Call. + Parent::unpackUpdate( pConnection, pStream ); +} + + + + +//----------------------------------------------------------------------------- +// +// Physics Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActor::setTransform( pMatrix ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::setTransform( const MatrixF &pMatrix ) +{ + Parent::setTransform( pMatrix ); + + // Server Object? + if ( isServerObject() ) + { + // Move Object. + setMaskBits( MoveMask ); + } +} + +//----------------------------------------------------------------------------- +// +// VActor::onMount( pObject, pNode ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onMount( SceneObject *pObject, S32 pNode ) +{ + // Parent Call. + Parent::onMount( pObject, pNode ); + + // Post Event. + mEventSignal.trigger( k_MountEvent ); +} + +//----------------------------------------------------------------------------- +// +// VActor::onUnmount( pObject, pNode ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActor::onUnmount( SceneObject *pObject, S32 pNode ) +{ + // Parent Call. + Parent::onUnmount( pObject, pNode ); + + // Post Event. + mEventSignal.trigger( k_UnmountEvent ); +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActor.h b/Engine/source/Verve/VActor/VActor.h new file mode 100644 index 000000000..3b0446f18 --- /dev/null +++ b/Engine/source/Verve/VActor/VActor.h @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTOR_H_ +#define _VT_VACTOR_H_ + +#ifndef _VT_VACTORDATA_H_ +#include "VActorData.h" +#endif + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +//----------------------------------------------------------------------------- +class VActorAnimationController; +class VActorPhysicsController; +//----------------------------------------------------------------------------- + +class VActor : public ShapeBase +{ + typedef ShapeBase Parent; + +public: + + enum eMaskBits + { + // Physics Bits. + MoveMask = Parent::NextFreeMask << 0, + PhysicsMask = ( MoveMask ), + + NextFreeMask = Parent::NextFreeMask << 1, + }; + + enum eEventType + { + k_MountEvent, + k_UnmountEvent, + }; + + typedef Signal tEventSignal; + +protected: + + VActorData *mDataBlock; + + // Event Signal. + tEventSignal mEventSignal; + +public: + + VActor( void ); + ~VActor( void ); + + // Initialisation Methods. + + bool onAdd( void ); + void onRemove( void ); + + bool onNewDataBlock( GameBaseData *pDataBlock, bool pReload ); + + // Update Methods. + + virtual void processTick( const Move *pMove ); + + virtual U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + virtual void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + DECLARE_CONOBJECT( VActor ); + +public: + + // Accessor Methods. + + inline VActorData *getDataBlock( void ) { return mDataBlock; }; + inline tEventSignal &getEventSignal( void ) { return mEventSignal; }; + + // Animation Methods. + + /// Get Animation Controller. + virtual VActorAnimationController *getAnimationController( void ) { return NULL; }; + + // Physics Methods. + + /// Set Transform. + virtual void setTransform( const MatrixF &pMatrix ); + + /// Get Physics Controller. + virtual VActorPhysicsController *getPhysicsController( void ) { return NULL; }; + + /// On Mount. + virtual void onMount( SceneObject *pObject, S32 pNode ); + /// On Unmount. + virtual void onUnmount( SceneObject *pObject, S32 pNode ); +}; + +#endif // _VT_VACTOR_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorAnimationController.cpp b/Engine/source/Verve/VActor/VActorAnimationController.cpp new file mode 100644 index 000000000..b740c566a --- /dev/null +++ b/Engine/source/Verve/VActor/VActorAnimationController.cpp @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorAnimationController.h" + +#include "VActor.h" +#include "VActorData.h" +#include "VActorAnimationStates.h" + +//----------------------------------------------------------------------------- + +VActorAnimationController::VActorAnimationController( void ) : + mObject( NULL ) +{ + // Void. +} + +VActorAnimationController::~VActorAnimationController( void ) +{ + // Clear Table. + mAnimationTable.clear(); +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimationTable(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimationTable( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No, Quit Now. + return false; + } + + // Clear the Table. + mAnimationTable.clear(); + + // Fetch Sequence List. + VActorData::tAnimationSequenceVector *sequenceList = getObject()->getDataBlock()->getAnimationList(); + + // Initialise the Animation States. + for ( VActorData::tAnimationSequenceVector::iterator itr = sequenceList->begin(); + itr != sequenceList->end(); + itr++ ) + { + // Fetch Sequence Definition. + const VActorData::sAnimationSequence &animSequence = ( *itr ); + + // Valid State? + if ( animSequence.State ) + { + // Register Animation. + mAnimationTable.registerState( animSequence.State, animSequence.Priority ); + } + } + + // Sort the Table. + mAnimationTable.sort(); + + // Valid. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimation( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimation( sAnimationRef &pAnimation, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Valid Object & Sequence? + if ( !isValidObject() || !isAnimationSequence( pIndex ) ) + { + // No, Quit Now. + return false; + } + + // Store as Current Animation. + pAnimation.Index = pIndex; + + // Initialise Thread. + return initAnimationThread( pAnimation.Thread, pAnimation.Index, pPosition, pTimeScale ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initAnimationThread( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initAnimationThread( TSThread *&pThread, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + // Valid Object & Sequence? + if ( !isValidObject() || !isAnimationSequence( pIndex ) ) + { + // No, Quit Now. + return false; + } + + // Valid Thread? + if ( !pThread ) + { + // Create a Thread. + pThread = getShapeInstance()->addThread(); + } + + // Init the Sequence. + getShapeInstance()->setSequence( pThread, getAnimationSequence( pIndex ), pPosition ); + + // Set Initial Time Scale. + getShapeInstance()->setTimeScale( pThread, pTimeScale ); + + // Valid. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::initBaseAnimation( pThread, pIndex, pPosition, pTimeScale ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::initBaseAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ) +{ + return initAnimation( mBaseAnimation, pIndex, pPosition, pTimeScale ); +} + + + + +//----------------------------------------------------------------------------- +// +// Accessor Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::isValidObject(); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::isValidObject( void ) +{ + return ( mObject != NULL && mObject->getDataBlock() != NULL ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getObject(); +// +// ... +// +//----------------------------------------------------------------------------- +VActor *VActorAnimationController::getObject( void ) +{ + return mObject; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::setObject( pObject ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorAnimationController::setObject( VActor *pObject ) +{ + // Set Object. + mObject = pObject; + + // Set Table's Reference. + mAnimationTable.setObject( pObject ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getShape(); +// +// ... +// +//----------------------------------------------------------------------------- +const TSShape *VActorAnimationController::getShape( void ) +{ + if ( !isValidObject() ) + { + return NULL; + } + + return mObject->getShape(); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getShapeInstance(); +// +// ... +// +//----------------------------------------------------------------------------- +TSShapeInstance *VActorAnimationController::getShapeInstance( void ) +{ + if ( !isValidObject() ) + { + return NULL; + } + + return mObject->getShapeInstance(); +} + + + + +//----------------------------------------------------------------------------- +// +// Animation Methods +// +//----------------------------------------------------------------------------- + +void VActorAnimationController::update( const F32 &pDelta ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No, Quit Now. + return; + } + + // Update Animation State. + mAnimationTable.execute(); + + // Advance Threads. + getShapeInstance()->advanceTime( pDelta, mBaseAnimation.Thread ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::isAnimationSequence( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorAnimationController::isAnimationSequence( const U32 &pIndex ) +{ + return ( getAnimationSequence( pIndex ) != -1 ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getAnimationSequence( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +S32 VActorAnimationController::getAnimationSequence( const U32 &pIndex ) +{ + // Valid Object? + if ( !mObject || !mObject->getDataBlock() ) + { + // No, Invalid Sequence. + return -1; + } + + // Return Sequence. + return mObject->getDataBlock()->getAnimationSequence( pIndex ); +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::getAnimation( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActorAnimationController::getAnimation( void ) +{ + // Base Animation Initialised? + if ( !mBaseAnimation.Thread ) + { + // Null. + return U32_MAX; + } + + // Return Current Animation. + return mBaseAnimation.Index; +} + +//----------------------------------------------------------------------------- +// +// VActorAnimationController::setAnimation( pIndex ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorAnimationController::setAnimation( const U32 &pIndex ) +{ + // Base Animation Initialised? + if ( !mBaseAnimation.Thread || mBaseAnimation.Index == pIndex ) + { + // Don't Update. + return; + } + + // Store as Current Animation. + mBaseAnimation.Index = pIndex; + + // Fetch the Sequence. + const S32 &sequence = getAnimationSequence( pIndex ); + + // Valid? + if ( sequence != -1 ) + { + // Play the Sequence. + getShapeInstance()->transitionToSequence( mBaseAnimation.Thread, sequence, 0.f, 0.15f, true ); + //getShapeInstance()->setSequence( mBaseAnimation.Thread, sequence, 0.f ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorAnimationController.h b/Engine/source/Verve/VActor/VActorAnimationController.h new file mode 100644 index 000000000..660248b8b --- /dev/null +++ b/Engine/source/Verve/VActor/VActorAnimationController.h @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORANIMATIONCONTROLLER_H_ +#define _VT_VACTORANIMATIONCONTROLLER_H_ + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSSHAPEINSTANCE_H_ +#include "ts/tsShapeInstance.h" +#endif + +//----------------------------------------------------------------------------- + +class VActor; +class VActorStateTable; + +//----------------------------------------------------------------------------- + +class VActorAnimationController +{ +public: + + struct sAnimationRef + { + U32 Index; + TSThread *Thread; + + sAnimationRef( void ) : + Index( U32_MAX ), + Thread( NULL ) + { + // Void. + } + }; + +protected: + + VActor *mObject; + + VActorStateTable mAnimationTable; + sAnimationRef mBaseAnimation; + +public: + + VActorAnimationController( void ); + virtual ~VActorAnimationController( void ); + + // Initialisation Methods. + + bool initAnimationTable( void ); + bool initAnimation( sAnimationRef &pAnimation, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + bool initAnimationThread( TSThread *&pThread, const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + bool initBaseAnimation( const U32 &pIndex, const F32 &pPosition, const F32 &pTimeScale ); + + // Accessor Methods. + + bool isValidObject( void ); + VActor *getObject( void ); + void setObject( VActor *pObject ); + + const TSShape *getShape( void ); + TSShapeInstance *getShapeInstance( void ); + + // Animation Methods. + + virtual void update( const F32 &pDelta ); + + bool isAnimationSequence( const U32 &pIndex ); + S32 getAnimationSequence( const U32 &pIndex ); + + U32 getAnimation( void ); + void setAnimation( const U32 &pIndex ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorAnimationStates.h b/Engine/source/Verve/VActor/VActorAnimationStates.h new file mode 100644 index 000000000..f1e0c44a6 --- /dev/null +++ b/Engine/source/Verve/VActor/VActorAnimationStates.h @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORANIMATIONSTATES_H_ +#define _VT_VACTORANIMATIONSTATES_H_ + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSINGLETON_H_ +#include "core/util/tSingleton.h" +#endif + +//----------------------------------------------------------------------------- + +class VActorAnimationState : public VActorState +{ +public: + + virtual void exit( VActor *pObject ) {}; +}; + +//----------------------------------------------------------------------------- + +#define DeclareActorAnimationState( name ) \ + class VActor##name##AnimationState : public VActorAnimationState \ + { \ + public: \ + void enter( VActor *pObject ); \ + bool execute( VActor *pObject ); \ + } + +#define ActorAnimationStateInstance( name ) \ + Singleton::instance() + +#define ImplementActorAnimationState( name, sequence ) \ + void VActor##name##AnimationState::enter( VActor *pObject ) { pObject->getAnimationController()->setAnimation( sequence ); } + +#define ExecuteActorAnimationState( name ) \ + bool VActor##name##AnimationState::execute( VActor *pObject ) + +//----------------------------------------------------------------------------- + +#endif // _VT_VACTORANIMATIONSTATES_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorData.cpp b/Engine/source/Verve/VActor/VActorData.cpp new file mode 100644 index 000000000..24d3b54d1 --- /dev/null +++ b/Engine/source/Verve/VActor/VActorData.cpp @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorData.h" + +#include "console/consoleTypes.h" +#include "core/stream/bitStream.h" + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_DATABLOCK_V1( VActorData ); +//----------------------------------------------------------------------------- + +VActorData::VActorData( void ) : + mMaxStepHeight( 1.f ), + mRunSpeed( 6.f ), + mSubmergeCoverage( 0.25f ) +{ + // Setup Shadowing. + shadowEnable = true; + shadowSize = 256; + shadowProjectionDistance = 14.0f; + + VECTOR_SET_ASSOCIATION( mAnimationSequenceList ); + VECTOR_SET_ASSOCIATION( mPhysicsList ); +} + +VActorData::~VActorData( void ) +{ + // Void. +} + +void VActorData::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addField( "MaxStepHeight", TypeF32, Offset( mMaxStepHeight, VActorData ) ); + addField( "RunSpeed", TypeF32, Offset( mRunSpeed, VActorData ) ); + + addField( "SubmergeCoverage", TypeF32, Offset( mSubmergeCoverage, VActorData ) ); +} + +//----------------------------------------------------------------------------- + +bool VActorData::initAnimationSequenceList( const S32 &pSize, const sAnimationSequence *pTable ) +{ + if ( !mShape ) + { + // Sanity! + return false; + } + + // Clear the List. + mAnimationSequenceList.clear(); + + // Initialise each Animation Sequence. + for ( U32 i = 0; i < pSize; i++ ) + { + // Fetch Sequence Definition. + const sAnimationSequence &animSequenceDef = pTable[i]; + + // Update Animation Details. + sAnimationSequence animSequence = animSequenceDef; + // Find Sequence. + animSequence.Sequence = mShape->findSequence( animSequenceDef.Name ); + + // Store. + mAnimationSequenceList.push_back( animSequence ); + } + + return true; +} + +bool VActorData::initAnimationTransitionList( const S32 &pSize, const sAnimationTransition *pTable ) +{ + if ( !mShape ) + { + // Sanity! + return false; + } + + // Clear the List. + mAnimationTransitionList.clear(); + + // Store each Animation Transition. + for ( U32 i = 0; i < pSize; i++ ) + { + // Store. + mAnimationTransitionList.push_back( pTable[i] ); + } + + return true; +} + +bool VActorData::initPhysicsStateList( const S32 &pSize, const sPhysicsState *pTable ) +{ + // Clear the List. + mPhysicsList.clear(); + + // Initialise each Animation Sequence. + for ( U32 i = 0; i < pSize; i++ ) + { + // Store. + mPhysicsList.push_back( pTable[i] ); + } + + return true; +} + +//----------------------------------------------------------------------------- + +void VActorData::packData( BitStream *pStream ) +{ + Parent::packData( pStream ); + + pStream->write( mMaxStepHeight ); + pStream->write( mRunSpeed ); + + pStream->write( mSubmergeCoverage ); +} + +void VActorData::unpackData( BitStream *pStream ) +{ + Parent::unpackData( pStream ); + + pStream->read( &mMaxStepHeight ); + pStream->read( &mRunSpeed ); + + pStream->read( &mSubmergeCoverage ); +} + +//----------------------------------------------------------------------------- + +S32 VActorData::getAnimationSequence( const U32 &pIndex ) +{ + // Iterate over the Registered Animations. + for ( tAnimationSequenceVector::iterator itr = mAnimationSequenceList.begin(); itr != mAnimationSequenceList.end(); itr++ ) + { + // Fetch Sequence Defintion. + const sAnimationSequence &animSequence = ( *itr ); + + // Target Index? + if ( animSequence.Index == pIndex ) + { + // Return Sequence ID. + return animSequence.Sequence; + } + } + + // Invalid Sequence. + return -1; +}; \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorData.h b/Engine/source/Verve/VActor/VActorData.h new file mode 100644 index 000000000..2aaf0fc58 --- /dev/null +++ b/Engine/source/Verve/VActor/VActorData.h @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORDATA_H_ +#define _VT_VACTORDATA_H_ + +#ifndef _SHAPEBASE_H_ +#include "T3D/shapeBase.h" +#endif + +//----------------------------------------------------------------------------- +class VActor; +class VActorStateTable; +class VActorAnimationState; +class VActorPhysicsState; +//----------------------------------------------------------------------------- + +struct VActorData : public ShapeBaseData +{ +private: + + typedef ShapeBaseData Parent; + friend class VActor; + +public: + + // Animation Data. + + enum eAnimationList + { + k_NextAnimation = 0, + }; + + struct sAnimationSequence + { + U32 Index; + const char *Name; + F32 Priority; + + VActorAnimationState *State; + S32 Sequence; + }; + + struct sAnimationTransition + { + U32 FromIndex; + U32 ToIndex; + + F32 Duration; + + bool Ordered; + U32 Sequence; + }; + + typedef Vector tAnimationSequenceVector; + typedef Vector tAnimationTransitionVector; + + // Physics Data. + + enum ePhysicsStateList + { + k_NextPhysicsState = 0, + }; + + struct sPhysicsState + { + U32 Index; + F32 Priority; + + VActorPhysicsState *State; + }; + typedef Vector tPhysicsStateVector; + +protected: + + tAnimationSequenceVector mAnimationSequenceList; + tAnimationTransitionVector mAnimationTransitionList; + tPhysicsStateVector mPhysicsList; + + F32 mMaxStepHeight; + F32 mRunSpeed; + + F32 mSubmergeCoverage; + +public: + + VActorData( void ); + ~VActorData( void ); + + static void initPersistFields( void ); + + virtual bool initAnimationSequenceList( const S32 &pSize, const sAnimationSequence *pTable ); + virtual bool initAnimationTransitionList( const S32 &pSize, const sAnimationTransition *pTable ); + virtual bool initPhysicsStateList( const S32 &pSize, const sPhysicsState *pTable ); + + virtual void packData( BitStream *pStream ); + virtual void unpackData( BitStream *pStream ); + + DECLARE_CONOBJECT( VActorData ); + +public: + + tAnimationSequenceVector *getAnimationList( void ) { return &mAnimationSequenceList; }; + S32 getAnimationSequence( const U32 &pIndex ); + + tPhysicsStateVector *getPhysicsStateList( void ) { return &mPhysicsList; }; + + inline const F32 &getMaxStepHeight( void ) const { return mMaxStepHeight; }; + inline const F32 &getRunSpeed( void ) const { return mRunSpeed; }; + inline const F32 &getSumbergeCoverage( void ) const { return mSubmergeCoverage; }; +}; + +#endif // _VT_VACTORDATA_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorPhysicsController.cpp b/Engine/source/Verve/VActor/VActorPhysicsController.cpp new file mode 100644 index 000000000..5e3332d59 --- /dev/null +++ b/Engine/source/Verve/VActor/VActorPhysicsController.cpp @@ -0,0 +1,1277 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorPhysicsController.h" + +#include "VActor.h" +#include "VActorData.h" +#include "VActorPhysicsStates.h" + +#include "Verve/VPath/VPath.h" + +#include "collision/clippedPolyList.h" +#include "collision/earlyOutPolyList.h" +#include "collision/extrudedPolyList.h" +#include "core/stream/bitStream.h" +#include "environment/waterObject.h" + +//----------------------------------------------------------------------------- + +static const U32 sGroundCollisionMask = ( StaticObjectType | StaticShapeObjectType | TerrainObjectType ); +static const U32 sMoveCollisionMask = ( PlayerObjectType | VehicleObjectType ); +static const U32 sCollisionMask = ( sGroundCollisionMask | sMoveCollisionMask ); + +//----------------------------------------------------------------------------- + +VActorPhysicsController::VActorPhysicsController( void ) : + mObject( NULL ), + mMountedPath( NULL ), + mPhysicsState( 0 ), + mControlState( k_NullControlState ), + mMoveState( k_NullMove ), + mVelocity( VectorF::Zero ), + mGravity( 0.f, 0.f, -9.8f ) +{ + // Void. +} + +VActorPhysicsController::~VActorPhysicsController( void ) +{ + // Clear Object. + clearObject(); +} + + + + +//----------------------------------------------------------------------------- +// +// Initialisation Methods. +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::initPhysicsController(); +// +// Initialise the physics table and setup the interface between the Controller +// and the reference object. +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::initPhysicsController( VActor *pObject ) +{ + // Valid Object? + if ( !pObject ) + { + // Assert & Quit. + AssertFatal( false, "VActorPhysicsController::initPhysicsController() - Invalid Object Specified." ); + return false; + } + + // Set Object. + mObject = pObject; + // Register for Actor Events. + mObject->getEventSignal().notify( this, &VActorPhysicsController::onActorEvent ); + + // Set Table's Reference. + mPhysicsStateTable.setObject( pObject ); + + // Init the Convex Box. + mConvex.init( pObject ); + + // Reset Interp. + mInterpController.resetDelta( pObject->getTransform() ); + + // Validate. + return initPhysicsTable(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::initPhysicsTable(); +// +// Register the available physics states which this controller may utilize. +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::initPhysicsTable( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No, Quit Now. + return false; + } + + // Clear the Table. + mPhysicsStateTable.clear(); + + // Fetch Sequence List. + VActorData::tPhysicsStateVector *stateList = getObjectDataBlock()->getPhysicsStateList(); + + // Initialise the Physics States. + for ( VActorData::tPhysicsStateVector::iterator itr = stateList->begin(); + itr != stateList->end(); + itr++ ) + { + // Fetch Sequence Definition. + const VActorData::sPhysicsState &physState = ( *itr ); + + // Valid State? + if ( physState.State ) + { + // Register State. + mPhysicsStateTable.registerState( physState.State, physState.Priority ); + } + } + + // Sort the Table. + mPhysicsStateTable.sort(); + + // Valid. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// Accessor Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isValidObject(); +// +// Do we have a valid reference object? +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::isValidObject( void ) +{ + return ( mObject && mObject->getDataBlock() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getObject(); +// +// Return the reference object. +// +//----------------------------------------------------------------------------- +VActor *VActorPhysicsController::getObject( void ) +{ + return mObject; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getObjectDataBlock(); +// +// Get the Actor Data for the reference object. +// +//----------------------------------------------------------------------------- +VActorData *VActorPhysicsController::getObjectDataBlock( void ) +{ + // Valid Object? + if ( !mObject ) + { + // No. + return NULL; + } + + // Return DataBlock. + return mObject->getDataBlock(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearObject(); +// +// Clear the reference object. Note that this should *never* be called outside +// of the controller's destructor! +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearObject( void ) +{ + // Valid Object? + if ( !mObject ) + { + // No. + return; + } + + // Clear Notify. + mObject->getEventSignal().remove( this, &VActorPhysicsController::onActorEvent ); + + // Clear Object. + mObject = NULL; + + // Clear Table. + mPhysicsStateTable.setObject( NULL ); + mPhysicsStateTable.clear(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getControlState(); +// +// Get the current Control State. +// +//----------------------------------------------------------------------------- +const U32 VActorPhysicsController::getControlState( void ) +{ + return mControlState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearControlState( pControlState ); +// +// Clear the Control State of a particular mask. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearControlState( const U32 &pControlState ) +{ + mControlState &= ( ~pControlState ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setControlState( pControlState ); +// +// Set the Control State. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setControlState( const U32 &pControlState ) +{ + mControlState = pControlState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isMoving(); +// +// Is the Actor currently Moving? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isMoving( void ) +{ + return ( !mIsZero( getVelocity().lenSquared() ) ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isMoving( pMoveState ); +// +// Is the Actor currently moving with the desired state? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isMoving( const U32 &pMoveState ) +{ + // Moving? + return ( ( getMoveState() & pMoveState ) && isMoving() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getMoveState(); +// +// Get the current Move State. +// +//----------------------------------------------------------------------------- +const U32 VActorPhysicsController::getMoveState( void ) +{ + // Return Move State. + return mMoveState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearMoveState( pMoveState ); +// +// Clear the Move State of a particular mask. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearMoveState( const U32 &pMoveState ) +{ + // Set Move State. + mMoveState &= ( ~pMoveState ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setMoveState( pMoveState ); +// +// Set the Move State. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setMoveState( const U32 &pMoveState ) +{ + // Set Move State. + mMoveState = pMoveState; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isPathing(); +// +// Is the Actor Pathing? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isPathing( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return false; + } + + return ( mMountedPath != NULL ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getPathObject(); +// +// Get the Path Object the Actor is mounted to. +// +//----------------------------------------------------------------------------- +VPath *VActorPhysicsController::getPathObject( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return NULL; + } + + return mMountedPath; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isOnGround(); +// +// Is the Actor On the Ground? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isOnGround( void ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No. + return false; + } + + // On Ground? + return ( mOnGround && mGroundObject && !isInWater() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isInAir(); +// +// Is the Actor in the Air? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isInAir( void ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No. + return false; + } + + // In Air? + return ( !isOnGround() && !isInWater() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::isInWater(); +// +// Is the Actor in the Water? +// +//----------------------------------------------------------------------------- +const bool VActorPhysicsController::isInWater( void ) +{ + // Valid Objects? + if ( !isValidObject() || !getWaterObject() ) + { + // No. + return false; + } + + // Submerged? + return ( ( mObject->getWaterCoverage() + POINT_EPSILON ) >= mObject->getDataBlock()->getSumbergeCoverage() ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getWaterObject(); +// +// Get the current Water Object the Actor is in. +// +//----------------------------------------------------------------------------- +WaterObject *VActorPhysicsController::getWaterObject( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return NULL; + } + + return mObject->getCurrentWaterObject(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getTransform(); +// +// Get the Actor's Transform. +// +//----------------------------------------------------------------------------- +MatrixF VActorPhysicsController::getTransform( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return MatrixF::Identity; + } + + // Return Transform. + return mObject->getTransform(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setTransform( pTransform ); +// +// Set the Actor's Transform. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setTransform( const MatrixF &pTransform ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return; + } + + // Apply Transform. + mObject->setTransform( pTransform ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getPosition(); +// +// Get the Actor's Position. +// +//----------------------------------------------------------------------------- +Point3F VActorPhysicsController::getPosition( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return Point3F::Zero; + } + + // Return Position. + return mObject->getPosition(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setPosition( pPosition ); +// +// Set the Actor's Position. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setPosition( const Point3F &pPosition ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return; + } + + // Apply Position. + mObject->setPosition( pPosition ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::applyGravity( pElapsedTime ); +// +// Apply gravity for the elapsed period. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::applyGravity( const F32 &pElapsedTime ) +{ + // Get Velocity. + VectorF velocity = getVelocity(); + // Add Tick Gravity. + velocity += getGravity() * pElapsedTime; + // Apply. + setVelocity( velocity ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::getVelocity(); +// +// Get the Actor's Velocity. +// +//----------------------------------------------------------------------------- +VectorF VActorPhysicsController::getVelocity( void ) +{ + // Valid Object? + if ( !isValidObject() ) + { + // No. + return VectorF::Zero; + } + + // Return Velocity. + return mVelocity; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::setVelocity( pVelocity ); +// +// Set the Actor's Velocity. +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::setVelocity( const VectorF &pVelocity ) +{ + // Set Velocity. + mVelocity = pVelocity; +} + + + + +//----------------------------------------------------------------------------- +// +// Physics Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::update( pDelta, pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::update( const F32 &pDelta, const Move *pMove ) +{ + // Valid Objects? + if ( !isValidObject() ) + { + // No, Quit Now. + return; + } + + // Pre-tick Update. + preTickUpdate( pDelta ); + + // Integrate Tick Update. + integrateTickUpdate( pDelta, pMove ); + + // Post-tick Update. + postTickUpdate( pDelta ); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::preTickUpdate( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::preTickUpdate( const F32 &pDelta ) +{ + // Pop Delta. + mInterpController.popDelta(); + + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::preTickUpdate() - Invalid Path State." ); + + // Fetch Mount Velocity. + const VectorF &mountVelocity = mMountedPath->getMountVelocity( mObject->getMountNode() ); + + // Use X & Y Velocity. + VectorF velocity = getVelocity(); + velocity.x = mountVelocity.x; + velocity.y = mountVelocity.y; + + // Apply Updates. + setVelocity( velocity ); + + } break; + } + + // Update Move State. + updateMoveState(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::integrateTickUpdate( pDelta, pMove ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::integrateTickUpdate( const F32 &pDelta, const Move *pMove ) +{ + // Update Collision Set. + updateWorkingCollisionSet(); + // Ground Ground Status. + updateGroundStatus(); + + // Execute Physics Table. + VActorPhysicsState *physState = dynamic_cast( mPhysicsStateTable.execute() ); + // Assert. + AssertFatal( physState, "VActorPhysicsController::update() - Invalid Physics State in the Table." ); + + // Process the State. + physState->processTick( mObject, pDelta, pMove ); + + // Process Collisions. + processCollisions(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::postTickUpdate( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::postTickUpdate( const F32 &pDelta ) +{ + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::postTickUpdate() - Invalid Path State." ); + + // Fetch Mount Transform. + MatrixF transform; + mMountedPath->getMountTransform( mObject->getMountNode(), getTransform(), &transform ); + // Fetch Mount Position. + const Point3F &mountPosition = transform.getPosition(); + + // Update X & Y Position. + Point3F position = getPosition(); + position.x = mountPosition.x; + position.y = mountPosition.y; + + // In Water? + bool underWater = false; + if ( isInWater() ) + { + // Fetch Body of Water. + WaterObject *waterBody = getWaterObject(); + + // Fetch Surface Position. + const F32 &waterSurfacePosition = waterBody->getSurfaceHeight( Point2F( position.x, position.y ) ); + // Fetch Submersion Position. + const F32 sumbersionPosition = waterSurfacePosition - ( mObject->getWorldBox().len_z() * mObject->getDataBlock()->getSumbergeCoverage() ); + + // Choose a Z Value. + // Note: This is done so that the Actor will either path under the + // water, or it will swim along the water's surface. + position.z = getMin( mountPosition.z, sumbersionPosition ); + + // Under Water? + underWater = ( position.z < sumbersionPosition ); + } + + // Under Water? + if ( !underWater ) + { + // Fetch Y Column. + VectorF forwardVector; + transform.getColumn( 1, &forwardVector ); + + // Determine Angle. + const F32 &angle = -mAtan2( -forwardVector.x, forwardVector.y ); + + // Reset Transform. + transform.set( EulerF( 0.f, 0.f, angle ) ); + + // In the air? + if ( !isOnGround() ) + { + // Apply z-axis force. + position.z += ( getVelocity().z * pDelta ); + } + } + + // Update Transform. + transform.setPosition( position ); + + // Apply Update. + setTransform( transform ); + + } break; + + default : + { + // Fetch Transform. + MatrixF transform = getTransform(); + + // Determine the Post-Tick Position. + Point3F postTickPosition = getPosition() + ( getVelocity() * pDelta ); + // Set the Post Tick Position. + transform.setPosition( postTickPosition ); + + // Apply the Transform. + setTransform( transform ); + + } break; + } + + // Push Delta. + mInterpController.pushDelta( getTransform() ); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::interpolateTick( pDelta ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::interpolateTick( const F32 &pDelta ) +{ + // Fetch Interpolated Transform. + const MatrixF transform = mInterpController.getTransform( pDelta ); + // Apply Render Transform. + mObject->setRenderTransform( transform ); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateWorkingCollisionSet(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateWorkingCollisionSet() +{ + // Contstruct Bounding Box. + const Box3F boundingBox = mConvex.getBoundingBox( getTransform(), mObject->getScale() ); + + // Determine Sweep Vector. + const VectorF sweepVector = ( getVelocity() * TickSec ); + + // Construct Swept Box. + Box3F sweptBox = boundingBox; + sweptBox.minExtents.setMin( boundingBox.minExtents + sweepVector ); + sweptBox.maxExtents.setMax( boundingBox.maxExtents + sweepVector ); + + // Update Collision List. + mObject->disableCollision(); + mConvex.updateWorkingList( sweptBox, sCollisionMask ); + mObject->enableCollision(); +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateMoveState(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateMoveState( void ) +{ + switch( mControlState ) + { + case k_PathControlState : + { + AssertFatal( isPathing(), "VActorPhysicsController::updateMoveState() - Invalid Path State." ); + + // Update Move State. + VPathObject *pathObject = mMountedPath->getPathObject( mObject ); + if ( !pathObject->isActive() ) + { + // Idle. + setMoveState( k_NullMove ); + } + else + { + // Set Movement Direction. + setMoveState( ( pathObject->isForward() ) ? k_ForwardMove : k_BackwardMove ); + } + + } break; + + default : + { + // Set Idle. + setMoveState( k_NullMove ); + + } break; + } +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::clearGroundStatus(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::clearGroundStatus( void ) +{ + // Clear Grounding. + mOnGround = false; + mGroundObject = NULL; + mGroundNormal.zero(); +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::updateGroundStatus(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::updateGroundStatus( void ) +{ + // Submerged? + if ( isInWater() ) + { + // Clear Ground Status. + clearGroundStatus(); + return; + } + + // Check for Grounding. + SceneObject *groundObject; + Point3F groundPoint; + VectorF groundNormal; + if ( !findGroundContact( groundObject, groundPoint, groundNormal ) ) + { + // Clear Ground Status. + clearGroundStatus(); + return; + } + + // Tidy up the Contact Position. + // Note: This basically "clamps" the Actor to the surface of the ground + // object. + const Point3F objPosition = getPosition(); + setPosition( objPosition - Point3F( 0.f, 0.f, ( objPosition.z - groundPoint.z ) ) ); + + // Clear Z-Axis Velocity. + mVelocity.z = 0.f; + + // Store Details. + mOnGround = true; + mGroundObject = groundObject; + mGroundNormal = groundNormal; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::findGroundContact( pContactObject, pContactPoint, pContactNormal ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal ) +{ + // Setup Collision List. + static CollisionList sCollisionList; + sCollisionList.clear(); + + static Polyhedron sBoxPolyhedron; + static ExtrudedPolyList sExtrudedPolyList; + + // Fetch Max Step Height. + const F32 stepHeight = mObject->getDataBlock()->getMaxStepHeight(); + + // Determine Positions. + const Point3F preTickPosition = getPosition() + Point3F( 0.f, 0.f, stepHeight ); + const VectorF preTickVelocity = getVelocity() + mGravity - VectorF( 0.f, 0.f, stepHeight / TickSec ); + const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); + const VectorF postTickVector = postTickPosition - preTickPosition; + + // Construct Scaled Box. + Box3F scaledBox = mObject->getObjBox(); + scaledBox.minExtents.convolve( mObject->getScale() ); + scaledBox.maxExtents.convolve( mObject->getScale() ); + + // Setup Polyherdron. + MatrixF collisionMatrix( true ); + collisionMatrix.setPosition( preTickPosition ); + sBoxPolyhedron.buildBox( collisionMatrix, scaledBox ); + + // Setup Extruded Poly List. + sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); + sExtrudedPolyList.setVelocity( preTickVelocity ); + sExtrudedPolyList.setCollisionList( &sCollisionList ); + + // Construct World Convex Box & Adjust for Sweep. + Box3F convexBox = scaledBox; + getTransform().mul( convexBox ); + convexBox.minExtents += postTickVector; + convexBox.maxExtents += postTickVector; + + // Build List of Contacts. + CollisionWorkingList &rList = mConvex.getWorkingList(); + for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) + { + Convex *convexShape = pList->mConvex; + + // Ground Object? + if ( !( convexShape->getObject()->getTypeMask() & sGroundCollisionMask ) ) + { + // No, Continue. + continue; + } + + // Overlap? + const Box3F &collisionConvexBox = convexShape->getBoundingBox(); + if ( convexBox.isOverlapped( collisionConvexBox ) ) + { + // Build Contact Information. + convexShape->getPolyList( &sExtrudedPolyList ); + } + } + + // Valid Collision? + if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() < 0.f || sCollisionList.getTime() > 1.f ) + { + // No, Quit Now. + return false; + } + + // Use First Collision. + Collision *collision = &sCollisionList[0]; + + // More Collisions? + if ( sCollisionList.getCount() > 1 ) + { + // Check for Better Contacts. + for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) + { + if ( cp->faceDot > collision->faceDot ) + { + // Use this One. + collision = cp; + } + } + } + + // Set Properties. + pContactObject = collision->object; + //pContactPoint = collision->point; + pContactPoint = ( preTickPosition + ( preTickVelocity * TickSec * sCollisionList.getTime() ) ); + pContactNormal = collision->normal; + + // Valid Contact. + return true; +} + + + + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::processCollisions(); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::processCollisions( void ) +{ + // Find & Resolve Collisions. + Collision *collision; + if ( findCollision( collision ) ) + { + // Solve the Collision. + solveCollision( collision ); + } +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::findCollision( pCollision ); +// +// ... +// +//----------------------------------------------------------------------------- +bool VActorPhysicsController::findCollision( Collision *&pCollision ) +{ + // Setup Collision List. + static CollisionList sCollisionList; + sCollisionList.clear(); + + static Polyhedron sBoxPolyhedron; + static ExtrudedPolyList sExtrudedPolyList; + + // Determine Positions. + const Point3F preTickPosition = getPosition(); + const VectorF preTickVelocity = getVelocity(); + const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); + const VectorF postTickVector = postTickPosition - preTickPosition; + + // Construct Scaled Box. + Box3F scaledBox = mObject->getObjBox(); + scaledBox.minExtents.convolve( mObject->getScale() ); + scaledBox.maxExtents.convolve( mObject->getScale() ); + + // Setup Polyherdron. + MatrixF collisionMatrix( true ); + collisionMatrix.setPosition( preTickPosition ); + sBoxPolyhedron.buildBox( collisionMatrix, scaledBox ); + + // Setup Extruded Poly List. + sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); + sExtrudedPolyList.setVelocity( preTickVelocity ); + sExtrudedPolyList.setCollisionList( &sCollisionList ); + + // Construct World Convex Box & Adjust for Sweep. + Box3F convexBox = scaledBox; + getTransform().mul( convexBox ); + convexBox.minExtents += postTickVector; + convexBox.maxExtents += postTickVector; + + // Determine the Collision Mask. + const U32 collisionMask = ( isInWater() ) ? ( sGroundCollisionMask | sMoveCollisionMask ) : sMoveCollisionMask; + + // Build List of Contacts. + CollisionWorkingList &rList = mConvex.getWorkingList(); + for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) + { + Convex *convexShape = pList->mConvex; + + // Valid Collision Target? + if ( !( convexShape->getObject()->getTypeMask() & collisionMask ) ) + { + // No, Continue. + continue; + } + + // Overlap? + const Box3F &collisionConvexBox = convexShape->getBoundingBox(); + if ( convexBox.isOverlapped( collisionConvexBox ) ) + { + // Build Contact Information. + convexShape->getPolyList( &sExtrudedPolyList ); + } + } + + // Valid Collision? + if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() > 1.f ) + { + // No, Quit Now. + return false; + } + + // Use First Collision. + Collision *collision = &sCollisionList[0]; + + // More Collisions? + if ( sCollisionList.getCount() > 1 ) + { + // Check for Better Contacts. + for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) + { + if ( cp->faceDot > collision->faceDot ) + { + // Use this One. + collision = cp; + } + } + } + + // Store Reference. + pCollision = collision; + + // Valid Collision. + return true; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::solveCollision( pCollision ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::solveCollision( Collision *pCollision ) +{ + // Fetch Velocity. + VectorF velocity = getVelocity(); + // Resolve Collision. + velocity -= ( pCollision->normal * mDot( getVelocity(), pCollision->normal ) ); + + // Pathing? + if ( isPathing() ) + { + // Clear X & Y Velocity Adjustments. + // Note: This means that any collisions made during pathing will not + // be solved, unless they only affect Z position. It is up to the + // user to construct Paths which avoid obsticles! + velocity.x = velocity.y = 0.f; + } + + // Set Velocity. + setVelocity( velocity ); +} + + + + +//----------------------------------------------------------------------------- +// +// Update Methods +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::onActorEvent( pEvent ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::onActorEvent( const VActor::eEventType &pEvent ) +{ + switch( pEvent ) + { + case VActor::k_MountEvent : + { + // Set Control State. + setControlState( k_PathControlState ); + + // Store Path. + mMountedPath = dynamic_cast( mObject->getObjectMount() ); + + } break; + + case VActor::k_UnmountEvent : + { + // Clear Control State. + clearControlState( k_PathControlState ); + + // Clear Path. + mMountedPath = NULL; + // Clear X & Y Velocity. + setVelocity( VectorF( 0.f, 0.f, mVelocity.z ) ); + + } break; + } +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::packUpdate( pConnection, pMask, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +U32 VActorPhysicsController::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + // Return Mask. + U32 retMask = 0; + + // Valid Object? + if ( !pStream->writeFlag( isValidObject() ) ) + { + return retMask; + } + + // Write Move? + const bool writeMove = ( pMask & VActor::MoveMask ) && !isPathing(); + if ( pStream->writeFlag( writeMove ) ) + { + // Write Position. + const Point3F &position = getPosition(); + pStream->write( position.x ); + pStream->write( position.y ); + pStream->write( position.z ); + } + + return retMask; +} + +//----------------------------------------------------------------------------- +// +// VActorPhysicsController::unpackUpdate( pConnection, pStream ); +// +// ... +// +//----------------------------------------------------------------------------- +void VActorPhysicsController::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Valid Object? + if ( !pStream->readFlag() ) + { + return; + } + + // Read Move? + if ( pStream->readFlag() ) + { + // Read Position. + Point3F position; + pStream->read( &position.x ); + pStream->read( &position.y ); + pStream->read( &position.z ); + + // Apply. + setPosition( position ); + } +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorPhysicsController.h b/Engine/source/Verve/VActor/VActorPhysicsController.h new file mode 100644 index 000000000..3e4a2912e --- /dev/null +++ b/Engine/source/Verve/VActor/VActorPhysicsController.h @@ -0,0 +1,160 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORPHYSICSCONTROLLER_H_ +#define _VT_VACTORPHYSICSCONTROLLER_H_ + +#ifndef _VT_TYPES_H_ +#include "Types/VTypes.h" +#endif + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _VT_VACTOR_H_ +#include "VActor.h" +#endif + +#ifndef _VT_VINTERPCONTROLLER_H_ +#include "VInterpController.h" +#endif + +#ifndef _BOXCONVEX_H_ +#include "collision/boxConvex.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; + +//----------------------------------------------------------------------------- + +class VActorPhysicsController +{ +protected: + + SimObjectPtr mObject; + SimObjectPtr mMountedPath; + + VActorStateTable mPhysicsStateTable; + + VInterpController mInterpController; + + U32 mPhysicsState; + U32 mControlState; + U32 mMoveState; + + OrthoBoxConvex mConvex; + + VectorF mGravity; + VectorF mVelocity; + + bool mOnGround; + SimObjectPtr mGroundObject; + VectorF mGroundNormal; + +public: + + VActorPhysicsController( void ); + virtual ~VActorPhysicsController( void ); + + // Initialisation Methods. + + bool initPhysicsController( VActor *pObject ); + bool initPhysicsTable( void ); + + // Accessor Methods. + + bool isValidObject( void ); + VActor *getObject( void ); + VActorData *getObjectDataBlock( void ); + void clearObject( void ); + + virtual const U32 getControlState( void ); + virtual void clearControlState( const U32 &pControlState ); + virtual void setControlState( const U32 &pControlState ); + + virtual const bool isMoving( void ); + virtual const bool isMoving( const U32 &pMoveState ); + virtual const U32 getMoveState( void ); + virtual void clearMoveState( const U32 &pMoveState ); + virtual void setMoveState( const U32 &pMoveState ); + + virtual const bool isPathing( void ); + virtual VPath *getPathObject( void ); + + virtual const bool isInWater( void ); + virtual WaterObject *getWaterObject( void ); + + virtual const bool isOnGround( void ); + virtual const bool isInAir( void ); + inline SceneObject *getGroundObject( void ) { return mGroundObject; }; + inline const VectorF &getGroundNormal( void ) { return mGroundNormal; }; + + inline const U32 &getPhysicsState( void ) { return mPhysicsState; }; + inline void setPhysicsState( const U32 &pState ) { mPhysicsState = pState; }; + + virtual MatrixF getTransform( void ); + virtual void setTransform( const MatrixF &pTransform ); + + virtual Point3F getPosition( void ); + virtual void setPosition( const Point3F &pPosition ); + + inline VectorF getGravity( void ) { return mGravity; }; + inline void setGravity( VectorF &pGravity ) { mGravity = pGravity; }; + virtual void applyGravity( const F32 &pElapsedTime ); + + virtual VectorF getVelocity( void ); + virtual void setVelocity( const VectorF &pVelocity ); + + // Physics Methods. + + void update( const F32 &pDelta, const Move *pMove ); + + virtual void preTickUpdate( const F32 &pDelta ); + virtual void integrateTickUpdate( const F32 &pDelta, const Move *pMove ); + virtual void postTickUpdate( const F32 &pDelta ); + + void interpolateTick( const F32 &pDelta ); + + void updateWorkingCollisionSet( void ); + + void updateMoveState( void ); + + void clearGroundStatus( void ); + void updateGroundStatus( void ); + bool findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal ); + + void processCollisions( void ); + bool findCollision( Collision *&pCollision ); + void solveCollision( Collision *pCollision ); + + // Updates Methods. + + void onActorEvent( const VActor::eEventType &pEvent ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); +}; + +#endif // _VT_VACTORANIMATIONCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorPhysicsStates.h b/Engine/source/Verve/VActor/VActorPhysicsStates.h new file mode 100644 index 000000000..24585b07a --- /dev/null +++ b/Engine/source/Verve/VActor/VActorPhysicsStates.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORPHYSICSSTATES_H_ +#define _VT_VACTORPHYSICSSTATES_H_ + +#ifndef _VT_VACTORSTATETABLE_H_ +#include "VActorStateTable.h" +#endif + +#ifndef _TSINGLETON_H_ +#include "core/util/tSingleton.h" +#endif + +//----------------------------------------------------------------------------- +struct Move; +//----------------------------------------------------------------------------- + +class VActorPhysicsState : public VActorState +{ +public: + + virtual void exit( VActor *pObject ) {}; + + virtual void processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ) = 0; +}; + +//----------------------------------------------------------------------------- + +#define DeclareActorPhysicsState( name ) \ + class VActor##name##PhysicsState : public VActorPhysicsState \ + { \ + public: \ + void enter( VActor *pObject ); \ + bool execute( VActor *pObject ); \ + void processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ); \ + } + +#define ActorPhysicsStateInstance( name ) \ + Singleton::instance() + +#define ImplementActorPhysicsState( name, state ) \ + void VActor##name##PhysicsState::enter( VActor *pObject ) { pObject->getPhysicsController()->setPhysicsState( state ); } + +#define ExecuteActorPhysicsState( name ) \ + bool VActor##name##PhysicsState::execute( VActor *pObject ) + +#define ProcessActorPhysicsState( name ) \ + void VActor##name##PhysicsState::processTick( VActor *pObject, const F32 &pElapsedTime, const Move *pMove ) + +//----------------------------------------------------------------------------- + +#endif // _VT_VACTORPHYSICSSTATES_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorStateTable.cpp b/Engine/source/Verve/VActor/VActorStateTable.cpp new file mode 100644 index 000000000..a2c065ce7 --- /dev/null +++ b/Engine/source/Verve/VActor/VActorStateTable.cpp @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VActorStateTable.h" +#include "VActor.h" + +//----------------------------------------------------------------------------- + +bool VActorStateTable::isRegisteredState( VActorState *pState ) +{ + for ( tStateConstIterator itr = mStateVector.begin(); itr != mStateVector.end(); itr++ ) + { + // Target State? + if ( ( *itr ).State == pState ) + { + // Yes. + return true; + } + } + + // No. + return false; +} + +void VActorStateTable::clear( void ) +{ + // Clear the States. + mLastState = NULL; + mCurrentState = NULL; + + // Clear the State Vector. + mStateVector.clear(); +}; + +void VActorStateTable::sort( void ) +{ + mStateVector.sort( &_onSortCallback ); +} + +void VActorStateTable::registerState( VActorState *pState, const F32 &pPriority ) +{ + // Already a State? + if ( isRegisteredState( pState ) ) + { + // Exit Now. + return; + } + + // Create the Reference. + sStateRef entry; + entry.State = pState; + entry.Priority = pPriority; + + // Push to Back. + mStateVector.push_back( entry ); + + // Set Current? + if ( mStateVector.size() == 1 ) + { + // Set State. + setState( pState ); + } +}; + +void VActorStateTable::setState( VActorState *pState ) +{ + if ( !mObject || !pState || pState == mCurrentState ) + { + // Invalid. + return; + } + + if ( mCurrentState ) + { + // Exit. + exit(); + + // Exit the Old State. + mCurrentState->exit( mObject ); + } + + // Update States. + mLastState = mCurrentState; + mCurrentState = pState; + + // Enter. + enter(); + + // Enter the New State. + pState->enter( mObject ); +}; + +VActorState *VActorStateTable::execute( void ) +{ + if ( !mObject || !mCurrentState ) + { + // Invalid. + return NULL; + } + + for ( tStateConstIterator itr = mStateVector.begin(); itr != mStateVector.end(); itr++ ) + { + // Fetch State Reference. + const sStateRef &stateRef = ( *itr ); + + // Enter State? + if ( stateRef.State->execute( mObject ) ) + { + // Set the State. + setState( stateRef.State ); + + // Return. + return stateRef.State; + } + } + + // No Valid Entries, Ouch! + Con::warnf( "VActorStateTable::execute() - No Valid Entries." ); + + // Return Current State. + return mCurrentState; +} + +S32 QSORT_CALLBACK VActorStateTable::_onSortCallback( const VActorStateTable::sStateRef *pA, const VActorStateTable::sStateRef *pB ) +{ + if ( pB->Priority > pA->Priority ) + { + return 1; + } + else if ( pB->Priority < pA->Priority ) + { + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VActorStateTable.h b/Engine/source/Verve/VActor/VActorStateTable.h new file mode 100644 index 000000000..6a514a2fc --- /dev/null +++ b/Engine/source/Verve/VActor/VActorStateTable.h @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VACTORSTATETABLE_H_ +#define _VT_VACTORSTATETABLE_H_ + +#ifndef _TVECTOR_H +#include "core/util/tVector.h" +#endif + +//----------------------------------------------------------------------------- +class VActor; +class VActorStateTable; +//----------------------------------------------------------------------------- + +class VActorState +{ +public: + + VActorState( void ) { }; + virtual ~VActorState( void ) { }; + + virtual void enter( VActor *pObject ) = 0; + virtual bool execute( VActor *pObject ) = 0; + virtual void exit( VActor *pObject ) = 0; +}; + +//----------------------------------------------------------------------------- + +class VActorStateTable +{ +public: + + struct sStateRef + { + VActorState *State; + F32 Priority; + }; + + typedef Vector tStateVector; + typedef tStateVector::iterator tStateIterator; + typedef tStateVector::const_iterator tStateConstIterator; + +protected: + + tStateVector mStateVector; + + VActor *mObject; + + VActorState *mLastState; + VActorState *mCurrentState; + +public: + + VActorStateTable( void ) : + mObject( NULL ), + mLastState( NULL ), + mCurrentState( NULL ) + { + VECTOR_SET_ASSOCIATION( mStateVector ); + }; + + virtual ~VActorStateTable( void ) + { + // Clear Table. + clear(); + }; + + void registerState( VActorState *pState, const F32 &pPriority = 0.5f ); + + virtual void enter( void ) { }; + virtual VActorState *execute( void ); + virtual void exit( void ) { }; + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline VActor *getObject( void ) { return mObject; }; + + bool isRegisteredState( VActorState *pState ); + + inline VActorState *getCurrentState( void ) { return mCurrentState; }; + inline VActorState *getLastState( void ) { return mLastState; }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + void clear( void ); + void sort( void ); + + inline void setObject( VActor *pObject ) { mObject = pObject; }; + void setState( VActorState *pState ); + + //------------------------------------------------------------------------- + // + // Accessors + // + //------------------------------------------------------------------------- + + tStateConstIterator begin( void ) const { return mStateVector.begin(); }; + tStateConstIterator end( void ) const { return mStateVector.end(); }; + S32 size( void ) const { return mStateVector.size(); }; + +protected: + + static S32 QSORT_CALLBACK _onSortCallback( const VActorStateTable::sStateRef *pA, const VActorStateTable::sStateRef *pB ); +}; + +#endif // _VT_VACTORSTATETABLE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VActor/VInterpController.h b/Engine/source/Verve/VActor/VInterpController.h new file mode 100644 index 000000000..3b9f34a1c --- /dev/null +++ b/Engine/source/Verve/VActor/VInterpController.h @@ -0,0 +1,207 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VINTERPCONTROLLER_H_ +#define _VT_VINTERPCONTROLLER_H_ + +#ifndef _MATH_H_ +#include "math/mMath.h" +#endif + +//----------------------------------------------------------------------------- + +class VInterpController +{ +protected: + + Point3F mPosition[2]; + QuatF mRotation[2]; + +public: + + //------------------------------------------------------------------------- + // Interpolation Methods. + //------------------------------------------------------------------------- + + /// Get Position. + Point3F getPosition( const F32 &pDelta ) + { + // Interpolate Position. + Point3F interpPosition; + interpPosition.interpolate( mPosition[1], mPosition[0], pDelta ); + // Return Interpolated Point. + return interpPosition; + }; + + /// Get Rotation. + QuatF getRotation( const F32 &pDelta ) + { + // Interpolate Rotation. + QuatF interpRotation; + interpRotation.interpolate( mRotation[1], mRotation[0], pDelta ); + // Return Interpolated Quat. + return interpRotation; + }; + + /// Get Transform. + MatrixF getTransform( const F32 &pDelta ) + { + // Get Position. + const Point3F interpPosition = getPosition( pDelta ); + // Get Rotation. + const QuatF interpRotation = getRotation( pDelta ); + + // Setup Matrix. + MatrixF transform; + interpRotation.setMatrix( &transform ); + // Set Position. + transform.setPosition( interpPosition ); + + // Return Matrix. + return transform; + }; + + //------------------------------------------------------------------------- + // Delta Methods. + //------------------------------------------------------------------------- + + /// Reset Delta. + void resetDelta( const Point3F &pPosition, const QuatF &pRotation ) + { + mPosition[0] = mPosition[1] = pPosition; + mRotation[0] = mRotation[1] = pRotation; + }; + + /// Reset Delta. + void resetDelta( const MatrixF &pMatrix ) + { + // Setup Quat. + QuatF rotationQuat( pMatrix ); + // Reset Delta. + resetDelta( pMatrix.getPosition(), rotationQuat ); + }; + + /// Reset Delta (Vector) + void resetDelta( const Point3F &pPosition, const VectorF &pForwardVector ) + { + // Assert. + AssertFatal( pForwardVector.isUnitLength(), "VInterpController::resetDelta() - Forward Vector hasn't been Normalized." ); + + // Static Up Vector. + static const VectorF sUpVector( 0.f, 0.f, 1.f ); + + // X-Axis. + VectorF xVec = mCross( pForwardVector, sUpVector ); + xVec.normalize(); + // Z-Axis. + VectorF zVec = mCross( xVec, pForwardVector ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF transform; + transform.setColumn( 0, xVec ); + transform.setColumn( 1, pForwardVector ); + transform.setColumn( 2, zVec ); + transform.setColumn( 3, pPosition ); + + // Reset Delta. + resetDelta( transform ); + }; + + /// Reset Delta (AngAxis) + void resetDelta( const Point3F &pPosition, const AngAxisF &pAngAxis ) + { + // Setup Matrix. + MatrixF transform; + pAngAxis.setMatrix( &transform ); + // Set Position. + transform.setPosition( pPosition ); + + // Reset Delta. + resetDelta( transform ); + }; + + /// Push Delta. + void pushDelta( const Point3F &pPosition, const QuatF &pRotation ) + { + mPosition[1] = pPosition; + mRotation[1] = pRotation; + }; + + /// Push Delta (Matrix) + void pushDelta( const MatrixF &pMatrix ) + { + // Setup Quat. + QuatF rotationQuat( pMatrix ); + // Push Delta. + pushDelta( pMatrix.getPosition(), rotationQuat ); + }; + + /// Push Delta (Vector) + void pushDelta( const Point3F &pPosition, const VectorF &pForwardVector ) + { + // Assert. + AssertFatal( pForwardVector.isUnitLength(), "VInterpController::pushDelta() - Forward Vector hasn't been Normalized." ); + + // Static Up Vector. + static const VectorF sUpVector( 0.f, 0.f, 1.f ); + + // X-Axis. + VectorF xVec = mCross( pForwardVector, sUpVector ); + xVec.normalize(); + // Z-Axis. + VectorF zVec = mCross( xVec, pForwardVector ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF transform; + transform.setColumn( 0, xVec ); + transform.setColumn( 1, pForwardVector ); + transform.setColumn( 2, zVec ); + transform.setColumn( 3, pPosition ); + + // Push Delta. + pushDelta( transform ); + }; + + /// Push Delta (AngAxis) + void pushDelta( const Point3F &pPosition, const AngAxisF &pAngAxis ) + { + // Setup Matrix. + MatrixF transform; + pAngAxis.setMatrix( &transform ); + // Set Position. + transform.setPosition( pPosition ); + + // Push Delta. + pushDelta( transform ); + }; + + /// Pop Delta. + void popDelta( void ) + { + mPosition[0] = mPosition[1]; + mRotation[0] = mRotation[1]; + }; +}; + +#endif // _VT_VINTERPCONTROLLER_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VNetState.cpp b/Engine/source/Verve/VPath/VNetState.cpp new file mode 100644 index 000000000..d08c2ea0d --- /dev/null +++ b/Engine/source/Verve/VPath/VNetState.cpp @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VNetState.h" + +//----------------------------------------------------------------------------- + +U32 VNetState::gInvalidMask = 0; + +//----------------------------------------------------------------------------- + +VNetState::VNetState() : + mMask( 0 ) +{ +} + +VNetState::~VNetState( void ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Delete State. + delete state; + } + + // Clear. + clear(); +} + +//----------------------------------------------------------------------------- +// +// Connection Methods. +// +//----------------------------------------------------------------------------- + +bool VNetState::isConnection( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + // Valid. + return true; + } + } + + // Invalid. + return false; +} + +void VNetState::addConnection( NetConnection *pConnection ) +{ + // Init State. + VNetStateInfo *state = new VNetStateInfo( pConnection, mMask ); + // Add. + push_back( state ); +} + +void VNetState::clearConnection( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + // Delete. + delete state; + // Erase. + erase( itr ); + // Quit. + return; + } + } +} + +//----------------------------------------------------------------------------- +// +// Mask Methods. +// +//----------------------------------------------------------------------------- + +VNetStateInfo *VNetState::getState( NetConnection *pConnection ) +{ + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + VNetStateInfo *state = ( *itr ); + if ( state->Connection == pConnection ) + { + return state; + } + } + + return NULL; +} + +void VNetState::setMaskBits( const U32 &pMask ) +{ + // Apply Mask. + mMask |= pMask; + + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Apply Mask. + state->Mask |= pMask; + } +} + +void VNetState::clearMaskBits( const U32 &pMask ) +{ + // Clear Mask. + mMask &= ~pMask; + + for ( VNetState::iterator itr = begin(); itr != end(); itr++ ) + { + // Fetch info. + VNetStateInfo *state = ( *itr ); + // Clear Mask. + state->Mask &= ~pMask; + } +} \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VNetState.h b/Engine/source/Verve/VPath/VNetState.h new file mode 100644 index 000000000..9cecef0a7 --- /dev/null +++ b/Engine/source/Verve/VPath/VNetState.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VNETSTATE_H_ +#define _VT_VNETSTATE_H_ + +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif + +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif + +//----------------------------------------------------------------------------- + +struct VNetStateInfo +{ + SimObjectPtr Connection; + U32 Mask; + + VNetStateInfo( void ) : + Connection( NULL ), + Mask( 0 ) + { + // Void. + }; + + VNetStateInfo( NetConnection *pConnection, U32 pMask ) + { + Connection = pConnection; + Mask = pMask; + }; +}; + +//----------------------------------------------------------------------------- + +class VNetState : public Vector +{ +protected: + + static U32 gInvalidMask; + + U32 mMask; + +public: + + VNetState( void ); + virtual ~VNetState( void ); + + // Connection Methods. + + bool isConnection( NetConnection *pConnection ); + void addConnection( NetConnection *pConnection ); + void clearConnection( NetConnection *pConnection ); + + // Property Methods. + + VNetStateInfo *getState( NetConnection *pConnection ); + + void setMaskBits( const U32 &pMask ); + void clearMaskBits( const U32 &pMask ); +}; + +#endif // _VT_VNETSTATE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPath.cpp b/Engine/source/Verve/VPath/VPath.cpp new file mode 100644 index 000000000..21a874869 --- /dev/null +++ b/Engine/source/Verve/VPath/VPath.cpp @@ -0,0 +1,3375 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPath.h" + +#include "console/consoleTypes.h" +#include "core/iTickable.h" +#include "core/stream/bitStream.h" +#include "math/mMathFn.h" +#include "math/mathIO.h" +#include "math/mTransform.h" + +//----------------------------------------------------------------------------- + +// Uncomment this definition to debug the network information. +//#define VPATH_DEBUG_NET + +// Uncomment this definition to debug the time step information +//#define VPATH_DEBUG_STEP + +//----------------------------------------------------------------------------- + +SimObjectPtr VPath::gServerSet = NULL; + +U32 VPath::gMaxNodeTransmit = 16; +U32 VPath::gMaxNodeBits = 8; +U32 VPath::gMaxNodeCount = 1 << gMaxNodeBits; // 256 + +U32 VPath::gMaxObjectTransmit = 4; +U32 VPath::gMaxObjectBits = 4; +U32 VPath::gMaxObjectCount = 1 << gMaxObjectBits; // 16 + +Point3F VPath::gBezierAxis( 0.f, 1.f, 0.f ); +Point3F VPath::gBezierUp( 0.f, 0.f, 1.f ); + +//----------------------------------------------------------------------------- + +static U32 gPathTypeBits = getBinLog2( getNextPow2( VPath::k_PathTypeSize ) ); +static F32 gBezierInterpStep = 0.0001f; + +//----------------------------------------------------------------------------- +// Path Type Table. +//----------------------------------------------------------------------------- + +// Implement the Path Type enum list. +ImplementEnumType( VPathType, "" ) + { VPath::k_PathBezier, "BEZIER" }, + { VPath::k_PathLinear, "LINEAR" }, +EndImplementEnumType; + +static VPath::ePathType getPathTypeEnum( const char *pLabel ) +{ + VPath::ePathType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPath::k_PathInvalid; + } + + // Return. + return out; +} + +//----------------------------------------------------------------------------- +IMPLEMENT_CO_NETOBJECT_V1( VPath ); +//----------------------------------------------------------------------------- + +VPath::VPath( void ) : + mPathType( k_PathBezier ) +{ + // Marker Type. + mTypeMask = MarkerObjectType; + + // Ghost & Scope. + mNetFlags.set( Ghostable | ScopeAlways ); + + // Process Ticks. + setProcessTick( true ); + + VECTOR_SET_ASSOCIATION( mNodeList ); + VECTOR_SET_ASSOCIATION( mObjectList ); +} + +VPath::~VPath( void ) +{ + // Void. +} + +bool VPath::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + // Add to Scene. + addToScene(); + + if ( isServerObject() ) + { + // Read Fields. + readFields(); + + // Add to Set. + getServerSet()->addObject( this ); + } + + return true; +} + +void VPath::onDeleteNotify( SimObject *pObject ) +{ + // Parent Notify. + Parent::onDeleteNotify( pObject ); + + if ( SceneObject *sceneObject = dynamic_cast( pObject ) ) + { + // Detach Object. + detachObject( sceneObject ); + + // Exit. + return; + } + + if ( NetConnection *connection = dynamic_cast( pObject ) ) + { + // Clear Connection References. + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Erase Connection. + ( *itr )->clearConnection( connection ); + } + + // Exit. + return; + } +} + +void VPath::onRemove( void ) +{ + // Remove From Scene. + removeFromScene(); + + // Clear Everything. + clear(); + + Parent::onRemove(); +} + +void VPath::initPersistFields( void ) +{ + Parent::initPersistFields(); + + addProtectedField( "PathType", TYPEID(), Offset( mPathType, VPath ), &setPathType, &defaultProtectedGetFn, "The type of path this is." ); +} + +SimSet *VPath::getServerSet( void ) +{ + if ( !gServerSet ) + { + gServerSet = new SimSet(); + gServerSet->registerObject( "ServerPathSet" ); + Sim::getRootGroup()->addObject( gServerSet ); + } + + return gServerSet; +} + +DefineEngineFunction( getServerPathSet, S32, (),, "( void )" ) +{ + return VPath::getServerSet()->getId(); +} + +//----------------------------------------------------------------------------- +// +// Editor Methods. +// +//----------------------------------------------------------------------------- + +bool VPath::collideBox( const Point3F &pStart, const Point3F &pEnd, RayInfo* pInfo ) +{ + if ( mObjBox.isContained( pStart ) ) + { + pInfo->t = 0.f; + pInfo->object = this; + pInfo->normal = VectorF( 0.f, 0.f, 1.f ); + pInfo->material = NULL; + + return true; + } + + return Parent::collideBox( pStart, pEnd, pInfo ); +} + +//----------------------------------------------------------------------------- +// +// Update Methods. +// +//----------------------------------------------------------------------------- + +F32 VPath::getUpdatePriority( CameraScopeQuery *pFocusObject, U32 pUpdateMask, S32 pUpdateSkips ) +{ + if ( mObjectList.size() > 0 ) + { + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Fetch Object. + VPathObject *pathObject = ( *itr ); + if ( pathObject->isActive() ) + { + // High Priority. + return 100.f; + } + } + } + + // Normal Priority. + return 0.f; +} + +void VPath::updateContainer( void ) +{ + if ( mNodeList.size() == 0 ) + { + // Sanity!. + return; + } + + // Init Min / Max. + mObjBox.minExtents = ( mNodeList[0]->getLocalPosition() ); + mObjBox.maxExtents = mObjBox.minExtents; + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Node Position. + const Point3F &nodeLocalPosition = node->getLocalPosition(); + + // Update Object Box. + mObjBox.minExtents.setMin( nodeLocalPosition ); + mObjBox.maxExtents.setMax( nodeLocalPosition ); + } + + // Adjust. + mObjBox.minExtents -= Point3F( 1.f, 1.f, 1.f ); + mObjBox.maxExtents += Point3F( 1.f, 1.f, 1.f ); + + // Reset Box. + resetWorldBox(); + resetRenderWorldBox(); +} + +void VPath::updateNodeTransforms( void ) +{ + // Fetch Transform Details. + const MatrixF &pathTransform = getTransform(); + const QuatF &pathRotation( pathTransform ); + const VectorF &pathScale = getScale(); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Fetch Node Spatials. + const Point3F &nodePosition = node->getLocalPosition(); + const QuatF &nodeRotation = node->getLocalRotation(); + + // Calculate the new Position. + Point3F newPosition = nodePosition; + newPosition.convolve( pathScale ); + pathTransform.mulP( newPosition ); + + // Calculate the new Rotation. + QuatF newRotation; + newRotation.mul( nodeRotation, pathRotation ); + + // Apply. + node->setWorldPosition( newPosition ); + node->setWorldRotation( newRotation ); + } +} + +void VPath::setTransform( const MatrixF &pMatrix ) +{ + // Parent Call. + Parent::setTransform( pMatrix ); + + // Update Nodes. + updateNodeTransforms(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +void VPath::setScale( const VectorF &pScale ) +{ + // Parent Call. + Parent::setScale( pScale ); + + // Update Nodes. + updateNodeTransforms(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +DefineEngineMethod( VPath, setPathType, void, (String pathType), ("LINEAR"), "( string pPathType ) - The path type dictates how attached objects move between nodes. There are currently two supported path types, \"BEZIER\" and \"LINEAR\".\n" + "@return No return value." ) +{ + // Fetch Enum. + const VPath::ePathType &type = getPathTypeEnum(pathType); + + // Update. + object->setPathType( type ); +} + +void VPath::setPathType( const ePathType &pType ) +{ + // Apply Value. + mPathType = pType; + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Update Path. + setMaskBits( PathUpdateMask ); + } +} + +bool VPath::setPathType( void *pObject, const char *pArray, const char *pData ) +{ + // Apply Type. + static_cast( pObject )->setPathType( getPathTypeEnum( pData ) ); + return false; +} + +//----------------------------------------------------------------------------- +// +// Mounting Methods. +// +//----------------------------------------------------------------------------- + +bool VPath::isMountIndex( const U32 &pIndex ) +{ + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + // Yes. + return true; + } + } + + // No. + return false; +} + +U32 VPath::getAvailableMountIndex( void ) +{ + U32 i = 0; + while( isMountIndex( i ) ) + { + // Increment. + i++; + } + + // Return Index. + return i; +} + +void VPath::mountObject( SceneObject *pObject, S32 pIndex, const MatrixF &pTransform ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::mountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), isObjectAttached( pObject ) ); +#endif + + // Attached? + if ( !isObjectAttached( pObject ) ) + { + if ( isServerObject() ) + { + // Shouldn't Use this Method. + Con::warnf( "VPath::mountObject() - Use 'attachObject' instead." ); + } + + // Not Attached. + return; + } + + // Parent Call. + Parent::mountObject( pObject, pIndex, pTransform ); + + // Clear the mounted mask. + // Note: This is so that we send the mounting information via the VPath + // packets instead of letting T3D handle it. + pObject->clearMaskBits( SceneObject::MountedMask ); +} + +void VPath::unmountObject( SceneObject *pObject ) +{ + // Fetch Path Object. + VPathObject *pathObject = getPathObject( pObject ); + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::unmountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), pathObject != NULL ); +#endif + + // Valid? + if ( !pathObject || pObject->getObjectMount() != this ) + { + // Warn. + Con::warnf( "VPath::unmountObject() - Object is not attached to this Path. %d", pObject->getId() ); + // Not Mounted Here! + return; + } + + // Parent Call. + Parent::unmountObject( pObject ); + + // Clear the mounted mask. + // Note: This is so that we send the mounting information via the VPath + // packets instead of letting T3D handle it. + pObject->clearMaskBits( SceneObject::MountedMask ); +} + +void VPath::getMountTransform( S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Reset Transform. + *pTransform = pInTransform; + // Sanity! + return; + } + + // Advance the Object. + advanceObject( pathObject, TickSec ); + + // Apply Transform. + *pTransform = pathObject->getTransform(); +} + +void VPath::getRenderMountTransform( F32 pDelta, S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Reset Transform. + *pTransform = pInTransform; + // Sanity! + return; + } + + // Apply Transform. + *pTransform = pathObject->getRenderTransform( pDelta ); +} + +VectorF VPath::getMountVelocity( const U32 &pIndex ) +{ + // Fetch the Scene Object. + VPathObject *pathObject = NULL; + for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) + { + if ( itr->getMountNode() == pIndex ) + { + pathObject = getPathObject( itr ); + break; + } + } + + if ( !pathObject ) + { + // Sanity! + return VectorF::Zero; + } + + // Determine Velocity. + return ( pathObject->getOrientation() * pathObject->getSpeed() ); +} + +//----------------------------------------------------------------------------- +// +// Persistence Methods. +// +//----------------------------------------------------------------------------- + +void VPath::readFields( void ) +{ + const char *nodeData = ""; + for ( S32 nodeIndex = 0; dStrcmp( nodeData = getDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL ), "" ) != 0; nodeIndex++ ) + { + // Create Node. + VPathNode *node = createNode(); + // Deserialize the Node. + node->fromString( nodeData ); + // Add the Node. + addNode( node ); + + // Clear Field. + setDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL, "" ); + } + + // Update Transforms. + updateNodeTransforms(); + + // Update Size. + updateContainer(); + + // Calculate Path. + calculatePath(); +} + +void VPath::writeFields( Stream &pStream, U32 pTabStop ) +{ + // Field Name. + StringTableEntry fieldName = StringTable->insert( "node" ); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Set Field. + setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), ( *itr )->toString().c_str() ); + } + + // Write Fields. + Parent::writeFields( pStream, pTabStop ); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + // Clear Field. + setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), "" ); + } +} + +U32 VPath::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) +{ + U32 retMask = Parent::packUpdate( pConnection, pMask, pStream ); + + if ( pMask & InitialUpdateMask ) + { + // Delete Notify. + deleteNotify( pConnection ); + } + + if ( pStream->writeFlag( pMask & PathUpdateMask ) ) + { + // Write Path Type. + pStream->writeInt( mPathType, gPathTypeBits ); + + // Write Transform. + mathWrite( *pStream, mObjToWorld ); + // Write Scale. + mathWrite( *pStream, mObjScale ); + } + + if ( pStream->writeFlag( pMask & NodeUpdateMask ) ) + { + // Path needs recalculating? + bool needsCalculating = false; + + // Delete Vector. + Vector deleteVector; + // Update Vector. + Vector updateVector; + + for ( U32 i = 0; i < mNodeList.size(); i++ ) + { + // Fetch Node. + VPathNode *node = mNodeList[i]; + + // Already In Map? + if ( !node->isConnection( pConnection ) ) + { + // Insert. + node->addConnection( pConnection ); + } + + // Fetch State. + VNetStateInfo *state = node->getState( pConnection ); + + // Delete new node? + if ( state->Mask & VPathNode::k_StateDelete + && state->Mask & VPathNode::k_StateCreate ) + { + // Remove Node. + removeNode( i-- ); + // Flag true. + needsCalculating = true; + } + + // Delete? + else if ( state->Mask & VPathNode::k_StateDelete ) + { + // Add To List. + deleteVector.push_front( i ); + } + + // Update? + else if ( state->Mask & VPathNode::k_StateUpdate ) + { + if ( updateVector.size() < gMaxNodeTransmit ) + { + // Add To List. + updateVector.push_back( i ); + } + } + } + + // More Updates? + if ( updateVector.size() == gMaxNodeTransmit ) + { + // More Updates. + retMask |= NodeUpdateMask; + } + + // Write Count. + pStream->writeInt( updateVector.size(), gMaxNodeBits + 1 ); + + for ( Vector::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxNodeBits ); + // Pack Update. + retMask |= mNodeList[index]->packNode( pConnection, pStream ); + } + + // Write Count. + pStream->writeInt( deleteVector.size(), gMaxNodeBits + 1 ); + + if ( deleteVector.size() > 0 ) + { + for ( Vector::iterator itr = deleteVector.begin(); itr != deleteVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxNodeBits ); + // Remove Node. + removeNode( index ); + } + + // Flag true. + needsCalculating = true; + // Clear Vector. + deleteVector.clear(); + } + + // Recalculate path? + if ( needsCalculating ) + { + // Update Size. + updateContainer(); + // Calculate Path. + calculatePath(); + } + } + + if ( pStream->writeFlag( pMask & ObjectUpdateMask ) ) + { + // Detach Vector. + Vector detachVector; + // Update Vector. + Vector updateVector; + + for ( U32 i = 0; i < mObjectList.size(); i++ ) + { + // Fetch Node. + VPathObject *pathObject = mObjectList[i]; + + // Already In Map? + if ( !pathObject->isConnection( pConnection ) ) + { + // Insert. + pathObject->addConnection( pConnection ); + } + + // Fetch State. + VNetStateInfo *state = pathObject->getState( pConnection ); + + // Detach newly attached object? + if ( state->Mask & VPathObject::k_StateAttach + && state->Mask & VPathObject::k_StateDetach ) + { + // Process Detach. + onDetachObject( pathObject ); + // Decrease index. + i -= 1; + + // Skip. + continue; + } + + // Update? + if ( state->Mask & VPathObject::k_StateUpdate ) + { + if ( updateVector.size() < gMaxObjectTransmit ) + { + // Add To List. + updateVector.push_back( i ); + } + } + + // Detach? + if ( state->Mask & VPathObject::k_StateDetach ) + { + // Add To List. + detachVector.push_front( i ); + } + } + + // More Updates? + if ( updateVector.size() == gMaxObjectTransmit ) + { + // More Updates. + retMask |= ObjectUpdateMask; + } + + // Write Count. + pStream->writeInt( updateVector.size(), gMaxObjectBits + 1 ); + + for ( Vector::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + + // Write Index. + pStream->writeInt( index, gMaxObjectBits ); + + // Fetch the object. + VPathObject *pathObject = mObjectList[index]; + // Fetch State. + VNetStateInfo *state = pathObject->getState( pConnection ); + + // Was the Object Attached? + if ( pStream->writeFlag( state->Mask & VPathObject::k_StateAttach ) ) + { +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::packUpdate() - Attached - %d | %d", isServerObject(), index ); +#endif + + // Clear Update. + state->Mask &= ~VPathObject::k_StateAttach; + } + + // Pack Object. + retMask |= mObjectList[index]->packUpdate( pConnection, pStream ); + } + + // Write Count. + pStream->writeInt( detachVector.size(), gMaxObjectBits + 1 ); + + if ( detachVector.size() > 0 ) + { + for ( Vector::iterator itr = detachVector.begin(); itr != detachVector.end(); itr++ ) + { + // Fetch Index. + const U32 index = ( *itr ); + // Write Index. + pStream->writeInt( index, gMaxObjectBits ); + // Process Detach. + onDetachObject( mObjectList[index] ); + } + + // Clear Vector. + detachVector.clear(); + } + } + + // Return. + return retMask; +} + +void VPath::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + Parent::unpackUpdate( pConnection, pStream ); + + // Update Path? + if ( pStream->readFlag() ) + { + // Read Path Type. + mPathType = pStream->readInt( gPathTypeBits ); + + // Read Transform. + mathRead( *pStream, &mObjToWorld ); + // Read Scale. + mathRead( *pStream, &mObjScale ); + + // Update Nodes. + updateNodeTransforms(); + // Calculate Path. + calculatePath(); + } + + // Update Nodes? + if ( pStream->readFlag() ) + { + // Number To Update. + const U32 updateCount = pStream->readInt( gMaxNodeBits + 1 ); + + for ( U32 i = 0; i < updateCount; i++ ) + { + // Read Index. + const U32 nodeIndex = pStream->readInt( gMaxNodeBits ); + + // Was the Node Created? + if ( pStream->readFlag() ) + { + // Create Node. + VPathNode *node = createNode(); + // Add the Node. + addNode( node, nodeIndex ); + } + + // Reference Node. + VPathNode *node = mNodeList[nodeIndex]; + // Apply Update. + node->unpackNode( pConnection, pStream ); + } + + // Number To Delete. + const U32 deleteCount = pStream->readInt( gMaxNodeBits + 1 ); + + for ( U32 i = 0; i < deleteCount; i++ ) + { + // Remove Node. + removeNode( pStream->readInt( gMaxNodeBits ) ); + } + + // Update Size. + updateContainer(); + // Calculate Path. + calculatePath(); + } + + // Update Objects? + if ( pStream->readFlag() ) + { + // Number To Update. + const U32 updateCount = pStream->readInt( gMaxObjectBits + 1 ); + + for ( U32 i = 0; i < updateCount; i++ ) + { + // Read Index. + const U32 objectIndex = pStream->readInt( gMaxObjectBits ); + + // Read Attached. + // Note: The editor handles the both the server and client side attachment calls. + // This is dangerous because there could be a mix up in indices, but it is + // needed to ensure the editor runs smoothly :( + const bool wasAttached = pStream->readFlag(); + if ( wasAttached && objectIndex >= mObjectList.size() ) + { +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::unpackUpdate() - WasAttached - %d | %d", isServerObject(), objectIndex ); +#endif + + // Create & Add to the List. + attachObject( new VPathObject() ); + } + + // Reference Node. + VPathObject *pathObject = mObjectList[objectIndex]; + + // Unpack Update. + pathObject->unpackUpdate( pConnection, pStream ); + + // Object Attached this Unpack? + if ( wasAttached ) + { + // Reset. + setPathObjectInterp( pathObject, pathObject->getTimeInterp() ); + } + } + + // Number To Detach. + const U32 detachCount = pStream->readInt( gMaxObjectBits + 1 ); + + for ( U32 i = 0; i < detachCount; i++ ) + { + // Fetch the path object. + VPathObject *pathObject = mObjectList[pStream->readInt( gMaxObjectBits )]; + // Detach callback. + onDetachObject( pathObject ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Node Methods. +// +//----------------------------------------------------------------------------- + +VPathNode *VPath::createNode( void ) +{ + return new VPathNode(); +} + +void VPath::deleteNode( VPathNode *pNode ) +{ + delete pNode; +} + +void VPath::clear( void ) +{ + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + VPathObject *pathObject = ( *itr ); + + // Fetch the attached object. + SceneObject *refObject = pathObject->getObject(); + // Unmount Object. + unmountObject( refObject ); + + // Delete the Path Object. + delete pathObject; + } + + // Clear Object List. + mObjectList.clear(); + + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + deleteNode( ( *itr ) ); + } + + // Clear Node List. + mNodeList.clear(); + + if ( isServerObject() ) + { + // Update. + setMaskBits( NodeUpdateMask ); + } +} + +VPathNode *VPath::getNode( const S32 &pNodeIndex ) +{ + // Sanity! + AssertFatal( pNodeIndex >= 0 && pNodeIndex < mNodeList.size(), "VPath::getNode() - Invalid Index" ); + + // Return Node. + return mNodeList[pNodeIndex]; +} + +DefineEngineMethod( VPath, addNode, void, (TransformF transform, F32 weight, S32 location), (MatrixF::Identity, 1.0, -1), + "( transform pTransform, float pWeight, [int pLocation] ) - Add a node with the given properties. Nodes represent physical points that attached objects move towards or between, but the PathType determines \"how\" they move between them.\n" + "@param pTransform The position and rotation of the new node.\n" + "@param pWeight The weight of the new node.\n" + "@param pLocation The index of the new node.\n" + "@return No return value.") +{ + // Fetch Invers Path Transform. + MatrixF pathTransformInv = object->getTransform(); + pathTransformInv.setPosition( Point3F::Zero ); + pathTransformInv.inverse(); + + Point3F pos; + QuatF rot; + AngAxisF aa; + + pos = transform.mPosition; + aa = transform.mOrientation; + + // Set Rotation. + rot.set( aa ); + + // World to Local Position. + Point3F nodePosition = ( pos - object->getPosition() ); + pathTransformInv.mulP( nodePosition ); + + // World to Local Rotation. + MatrixF nodeRotationMat; + rot.setMatrix( &nodeRotationMat ); + pathTransformInv.mul( nodeRotationMat ); + + // Set Quat. + QuatF nodeRotation; + nodeRotation.set( nodeRotationMat ); + + // Add Node. + VPathNode *node = object->addNode( nodePosition, nodeRotation, weight, location ); + + // Valid Node? + if ( node ) + { + // Update Size. + object->updateContainer(); + + // Calculate Path. + object->calculatePath(); + } +} + +VPathNode *VPath::addNode( const Point3F &pPosition, const QuatF &pRotation, const F32 &pWeight, const S32 &pLocation ) +{ + // Reference Object. + VPathNode *pathNode = createNode(); + + // Store Properties. + pathNode->setLocalPosition( pPosition ); + pathNode->setLocalRotation( pRotation ); + pathNode->setWeight( pWeight ); + + // Add Node. + return addNode( pathNode, pLocation ); +} + +VPathNode *VPath::addNode( VPathNode *pNode, const S32 &pLocation ) +{ + if ( pNode->getPath() ) + { + // Error. + Con::errorf( "VPath::addNode() - Node already belongs to a Path, '%d'", pNode->getPath()->getId() ); + + return NULL; + } + else if ( mNodeList.size() == gMaxNodeCount ) + { + // Error. + Con::errorf( "VPath::addNode() - Reached Max Nodes (%d)", gMaxNodeCount ); + + // Delete Node. + deleteNode( pNode ); + + return NULL; + } + + // Set Path. + pNode->setPath( this ); + + // Update World Data. + pNode->updateWorldData(); + + if ( pLocation < 0 ) + { + // Push Back. + mNodeList.push_back( pNode ); + } + else + { + // Fetch Size. + const S32 nodeCount = mNodeList.size(); + + if ( pLocation >= nodeCount ) + { + // Push Back. + mNodeList.push_back( pNode ); + } + else + { + // Insert. + mNodeList.insert( ( mNodeList.address() + pLocation ), pNode ); + } + } + + if ( isServerObject() ) + { + // Update. + setMaskBits( NodeUpdateMask ); + } + + // Return Node. + return pNode; +} + +DefineEngineMethod( VPath, deleteNode, void, (S32 nodeIndex), (0), "( int pNodeIndex ) - Delete the node with the given index. If you delete a node that an attached object is moving to, or from then the object's movement will adjust so that it has a valid path.\n" + "@param pNodeIndex The index of the node to be deleted.\n" + "@return No return value." ) +{ + // Apply Update. + object->deleteNode( nodeIndex ); +} + +void VPath::deleteNode( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::deleteNode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Remove Node References. + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Fetch Object. + VPathObject *pathObject = ( *itr ); + + if ( ( pathObject->getSourceNode() >= pNodeIndex ) || ( pathObject->getDestinationNode() >= pNodeIndex ) ) + { + S32 srcNode = pathObject->getSourceNode(); + S32 dstNode = pathObject->getDestinationNode(); + + if ( pathObject->isForward() ) + { + if ( srcNode >= pNodeIndex ) + { + srcNode -= 1; + } + + if ( dstNode > pNodeIndex ) + { + dstNode -= 1; + } + } + else + { + if ( srcNode > pNodeIndex ) + { + srcNode -= 1; + } + + if ( dstNode >= pNodeIndex ) + { + dstNode -= 1; + } + } + + // Normalize indices. + normalizeNodeIndex( srcNode, ( mNodeList.size() - 1 ) ); + normalizeNodeIndex( dstNode, ( mNodeList.size() - 1 ) ); + + // Apply Update. + pathObject->setNode( srcNode, dstNode ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + } + } + } + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + + // Flag for Deletion. + node->setMaskBits( VPathNode::k_StateDelete ); + } +} + +void VPath::removeNode( const S32 &pNodeIndex ) +{ + // Fetch the node. + VPathNode *node = getNode( pNodeIndex ); + if ( !node ) + { + // Quit. + return; + } + + // Delete Node. + deleteNode( node ); + // Erase Node. + mNodeList.erase( pNodeIndex ); +} + +S32 VPath::normalizeNodeIndex( S32 &pNodeIndex ) +{ + const S32 nodeCount = mNodeList.size(); + if ( nodeCount == 0 ) + { + // No Nodex. + pNodeIndex = 0; + } + else + { + while ( pNodeIndex < 0 ) + { + // Wrap Backwards. + pNodeIndex += nodeCount; + } + + // Wrap Forwards. + pNodeIndex %= nodeCount; + } + + // Return Index. + return pNodeIndex; +} + +S32 VPath::normalizeNodeIndex( const S32 &pNodeIndex ) +{ + // Temp. + S32 nodeIndex = pNodeIndex; + + // Return Index. + return normalizeNodeIndex( nodeIndex ); +} + +S32 VPath::normalizeNodeIndex( S32 &pNodeIndex, const S32 &pNodeCount ) +{ + if ( pNodeCount == 0 ) + { + // No Nodex. + pNodeIndex = 0; + } + else + { + while ( pNodeIndex < 0 ) + { + // Wrap Backwards. + pNodeIndex += pNodeCount; + } + + // Wrap Forwards. + pNodeIndex %= pNodeCount; + } + + // Return Index. + return pNodeIndex; +} + +//----------------------------------------------------------------------------- +// +// Object Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VPath, isObjectAttached, bool, (SceneObject* sceneObject), (nullAsType()), "( SimObject pObject ) - Is the object attached to this path?\n" + "@param pObject The SimObjectID of the object you wish to check.\n" + "@return Returns true if the object is attached to this path." ) +{ + if (sceneObject== nullptr) + { + Con::errorf( "VPath::isObjectAttached() - Invalid Target Object." ); + return false; + } + + // Attached? + return object->isObjectAttached( sceneObject ); +} + +bool VPath::isObjectAttached( SceneObject *pObject ) +{ + // Valid Object? + return ( getPathObject( pObject ) != NULL ); +} + +VPathObject *VPath::getPathObject( SceneObject *pObject ) +{ + for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) + { + // Correct Object? + if ( ( *itr )->getObject() == pObject ) + { + // Yes. + return ( *itr ); + } + } + + return NULL; +} + +DefineEngineStringlyVariadicMethod( VPath, attachObject, void, 7, 8, "( SimObject pObject, bool pForward, float pSpeed, bool pRelative, int pStartNode, [int pEndNode] ) - Attach an object to this path with the given properties. If the object is already attached to a path, then a warning will be displayed and the object will *not* be attached to this path.\n" + "@param pObject The SimObjectID of the object to be attached.\n" + "@param pForward Should the object be moving forward?\n" + "@param pSpeed The speed that the object will travel around the path.\n" + "@param pRelative Offset the object based on the difference between the start node and its current position.\n" + "@param pStartNode The index of the node this object starts pathing from.\n" + "@param pEndNode The index of the node this object will stop pathing at." + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::attachObject() - Invalid Target Object." ); + return; + } + + // Fetch Direction. + const bool forward = dAtob( argv[3] ); + // Fetch Speed. + const F32 speed = dAtof( argv[4] ); + // Fetch Relativity. + const bool relative = dAtob( argv[5] ); + // Fetch Start Node. + const S32 startNode = dAtoi( argv[6] ); + // Fetch End Node. + const S32 endNode = ( argc >= 8 ) ? dAtoi( argv[7] ) : -1; + + // Attach Object. + object->attachObject( sceneObject, forward, speed, relative, startNode, endNode ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode ) +{ + attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, VPathObject::k_OrientationToPath, NULL ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode ) +{ + attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, pOrientationMode, NULL ); +} + +void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode, void *pOrientationData ) +{ + // Already Pathing? + if ( isObjectAttached( pObject ) ) + { + Con::warnf( "VPath::attachObject() - Object Already Attached to a Path." ); + return; + } + + // Determine Target Nodes. + const S32 srcNode = normalizeNodeIndex( pStartNode ); + const S32 dstNode = normalizeNodeIndex( ( pForward ) ? pStartNode + 1 : pStartNode - 1 ); + const S32 endNode = ( pEndNode == -1 ) ? pEndNode : normalizeNodeIndex( pEndNode ); + + // Valid Source Node? + if ( getNodeCount() == 0 || !getNode( srcNode ) ) + { + Con::warnf( "VPath::attachObject() - Invalid Start Node." ); + return; + } + + VPathObject *pathObject = new VPathObject(); + + // Init Properties. + pathObject->setActive( true ); + pathObject->setObject( pObject ); + + pathObject->setForward( pForward ); + + pathObject->setTimeInterp( 0.f ); + pathObject->setPathInterp( 0.f ); + pathObject->setOffset( Point3F::Zero ); + pathObject->setSpeed( pSpeed ); + + switch( pOrientationMode ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + pathObject->setOrientationMode( pOrientationMode ); + + } break; + + case VPathObject::k_OrientationToObject : + { + pathObject->setOrientationMode( pOrientationMode, (SceneObject*)pOrientationData ); + + } break; + + case VPathObject::k_OrientationToPoint : + { + pathObject->setOrientationMode( pOrientationMode, ( *(Point3F*)pOrientationData ) ); + + } break; + } + + pathObject->setNode( srcNode, dstNode ); + pathObject->setStartNode( srcNode ); + pathObject->setEndNode( endNode ); + + // Fetch Init Node. + VPathNode *node = mNodeList[srcNode]; + + // Relative Position? + if ( pRelative ) + { + // Set Position Offset. + pathObject->setOffset( pObject->getPosition() - node->getWorldPosition() ); + } + + // Set info. + setPathObjectInterp( pathObject, 0.f ); + + // Attach. + attachObject( pathObject ); +} + +void VPath::attachObject( VPathObject *pPathObject ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::attachObject() - %d", isServerObject() ); +#endif + + if ( mObjectList.size() == gMaxObjectCount ) + { + Con::errorf( "VPath::attachObject() - Reached Max Objects (%d)", gMaxObjectCount ); + return; + } + + // Add to List. + mObjectList.push_back( pPathObject ); + + // Callback. + onAttachObject( pPathObject ); + + if ( isServerObject() ) + { + // Update. + setMaskBits( ObjectUpdateMask ); + } +} + +void VPath::onAttachObject( VPathObject *pPathObject ) +{ + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject ) + { + return; + } + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::onAttachObject() - %d | %d", isServerObject(), refObject->getId() ); +#endif + + // Delete Notify. + deleteNotify( refObject ); + + if ( isServerObject() ) + { + // Fetch the Available Mount Index. + U32 mountIndex = getAvailableMountIndex(); + // Mount the Object to this Path. + mountObject( refObject, mountIndex ); + + // Return Buffer. + char buffer[1][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + + // Callback. + // VPath::onAttachObject( %object ); + Con::executef( this, "onAttachObject", buffer[0] ); + } +} + +DefineEngineMethod( VPath, detachObject, void, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Detach the object from this path in place.\n" + "@param pObject The SimObjectID of the object to be detached.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::detachObject() - Invalid Target Object." ); + return; + } + + // Detach Object. + object->detachObject( sceneObject ); +} + +void VPath::detachObject( SceneObject *pObject ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::detachObject() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Detach. + detachObject( pathObject ); +} + +void VPath::detachObject( VPathObject *pPathObject ) +{ +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::detachObject() - %d", isServerObject() ); +#endif + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Detach. + pPathObject->setMaskBits( VPathObject::k_StateDetach ); + } + + /* + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( refObject ) + { + // Unmount Object. + unmountObject( refObject ); + } + */ +} + +void VPath::onDetachObject( VPathObject *pPathObject ) +{ + // Valid Object? + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject ) + { + return; + } + +#ifdef VPATH_DEBUG_NET + Con::printf( "VPath::onDetachObject() - %d | %d", isServerObject(), refObject->getId() ); +#endif + + // Reset. + setPathObjectInterp( pPathObject, pPathObject->getTimeInterp() ); + // Unmount Object. + unmountObject( refObject ); + + // Delete the Path Object. + delete pPathObject; + // Remove from the Set. + mObjectList.erase( mObjectList.find_next( pPathObject ) ); + + // Clear Delete Notify. + clearNotify( refObject ); + + if ( isServerObject() ) + { + // Return Buffer. + char buffer[1][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + + // Callback. + // VPath::onDetachObject( %object ); + Con::executef( this, "onDetachObject", buffer[0] ); + } +} + +void VPath::processTick( const Move *pMove ) +{ +} + +void VPath::advanceObject( VPathObject *pPathObject, const F32 &pDelta ) +{ + SceneObject *refObject = pPathObject->getObject(); + if ( !refObject || mIsZero( pDelta ) ) + { + // Ignore. + return; + } + + // Spatial Delta. + pPathObject->popDelta(); + + // Active and Moving? + if ( !pPathObject->isActive() || mIsZero( pPathObject->getSpeed() ) ) + { + // Update Delta. + pPathObject->pushDelta( refObject->getPosition(), refObject->getTransform().getForwardVector() ); + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + VPathNode *lenNode = ( pPathObject->isForward() ) ? srcNode : dstNode; + + // Calculate Interp Delta. + const F32 stepDistance = ( pPathObject->getSpeed() * pDelta ); + const F32 speedMod = ( pPathObject->getSpeed() / lenNode->getLength() ); + F32 timeInterp = pPathObject->getTimeInterp(); + F32 timeInterpDelta = ( speedMod * pDelta ); + F32 pathInterp = pPathObject->getPathInterp(); + F32 pathInterpDelta = 0.f; + + // Fetch the old position. + const Point3F oldPosition = pPathObject->getPosition(); + // Calculate the new position and path delta. + Point3F newPosition = getAdvancedPathPosition( pPathObject, stepDistance, pathInterpDelta ); + + // Finished? + if ( ( timeInterp + timeInterpDelta ) >= 1.f ) + { + // Finished? + if ( pPathObject->getDestinationNode() == pPathObject->getEndNode() ) + { + // Stop Updates. + pPathObject->setActive( false ); + } + else + { + // Update Nodes. + const S32 srcNodeIndex = pPathObject->getDestinationNode(); + const S32 dstNodeIndex = normalizeNodeIndex( ( pPathObject->isForward() ) ? srcNodeIndex + 1 : srcNodeIndex - 1 ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::errorf( "Change Node:\n Source, %d\n Destination, %d", srcNodeIndex, dstNodeIndex ); +#endif + + // Apply Changes. + pPathObject->setNode( srcNodeIndex, dstNodeIndex ); + pPathObject->setTimeInterp( 0.f ); + pPathObject->setPathInterp( 0.f ); + pPathObject->setPosition( newPosition ); + + // Reset local interp information. + timeInterp = 0.f; + timeInterpDelta = 0.f; + pathInterp = 0.f; + pathInterpDelta = 0.f; + + // Fetch the distance we've travelled. + const F32 &advanceDistance = ( newPosition - oldPosition ).len(); + // Any remaining distance? + if ( ( stepDistance - advanceDistance ) > 0.0001f ) + { + // Determine how much more we need to move. + Point3F newPosition0 = newPosition; + newPosition = getAdvancedPathPosition( pPathObject, ( stepDistance - advanceDistance ), pathInterpDelta ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::errorf( "Transition Step: %f\nTransition Distance: %f + %f = %f", pathInterpDelta, advanceDistance, ( newPosition - newPosition0 ).len(), advanceDistance + ( newPosition - newPosition0 ).len() ); +#endif + } + } + + if ( isServerObject() ) + { + // Return Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pPathObject->isActive() ? pPathObject->getSourceNode() : pPathObject->getDestinationNode() ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", !pPathObject->isActive() ); + + // Callback. + // VPath::onReachNode( %object, %node, %finished ); + Con::executef( this, "onReachNode", buffer[0], buffer[1], buffer[2] ); + } + } + + // Update Object Interp. + timeInterp = mClampF( timeInterp + timeInterpDelta, 0.f, 1.f ); + pathInterp = mClampF( pathInterp + pathInterpDelta, 0.f, 1.f ); + + // Apply Changes. + pPathObject->setTimeInterp( timeInterp ); + pPathObject->setPathInterp( pathInterp ); + pPathObject->setPosition( newPosition ); + +#ifdef VPATH_DEBUG_STEP + if ( isServerObject() ) + Con::printf( "Time / Distance: %f %f / %f %f", timeInterp, pathInterp, stepDistance, ( newPosition - oldPosition ).len() ); +#endif + + switch ( pPathObject->getOrientationMode().Type ) + { + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToObject : + case VPathObject::k_OrientationToPoint : + { + // Update Orientation. + updateOrientation( pPathObject ); + + } break; + + case VPathObject::k_OrientationToPath : + { + // Determine the path orientation. + VectorF pathOrientation = ( newPosition - oldPosition ); + pathOrientation.normalize(); + + // Update Orientation. + updateOrientation( pPathObject, pathOrientation ); + + } break; + } + + // Update Delta. + pPathObject->pushDelta( pPathObject->getPosition(), pPathObject->getOrientation() ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Update This Object. + pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); + } +} + +void VPath::updatePosition( VPathObject *pPathObject ) +{ + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Fetch Position. + F32 pathInterp = 0.f; + const Point3F newPosition = getPathPosition( srcNode, dstNode, pPathObject->getTimeInterp(), pPathObject->isForward(), pathInterp ); + + // Apply Position. + pPathObject->setPosition( newPosition ); + pPathObject->setPathInterp( pathInterp ); +} + +void VPath::updateOrientation( VPathObject *pPathObject ) +{ + // Update Orientation? + if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) + { + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Determine Path Orientation. + VectorF pathOrientation; + switch ( pPathObject->getOrientationMode().Type ) + { + case VPathObject::k_OrientationInterpolate : + { + // Interpolate Between Transforms. + QuatF rot; + rot.interpolate( srcNode->getWorldRotation(), dstNode->getWorldRotation(), pPathObject->getPathInterp() ); + + // Set Matrix. + MatrixF mat; + rot.setMatrix( &mat ); + + // Fetch Orientation. + pathOrientation = mat.getColumn3F( 1 ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Orientation. + pathOrientation = ( pPathObject->getOrientationMode().Object->getPosition() - pPathObject->getWorldPosition() ); + pathOrientation.normalizeSafe(); + + } break; + + case VPathObject::k_OrientationToPoint : + { + // Fetch Orientation. + pathOrientation = ( pPathObject->getOrientationMode().Point - pPathObject->getWorldPosition() ); + pathOrientation.normalizeSafe(); + + } break; + + case VPathObject::k_OrientationToPath : + { + // Fetch Orientation. + pathOrientation = getPathOrientation( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward() ); + + } break; + } + + // Update. + updateOrientation( pPathObject, pathOrientation ); +} + +void VPath::updateOrientation( VPathObject *pPathObject, const Point3F &pPathOrientation ) +{ + // Update Orientation? + if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) + { + // Skip. + return; + } + + // Fetch Nodes. + VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); + VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); + + // Determine Source Orientation. + VectorF srcOrientation; + switch ( srcNode->getOrientationMode().Type ) + { + case VPathNode::k_OrientationToPoint : + { + // Fetch Orientation. + srcOrientation = ( srcNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); + srcOrientation.normalize(); + + } break; + + default : + { + // Use Path Orientation. + srcOrientation = pPathOrientation; + + } break; + } + + // Determine Destination Orientation. + VectorF dstOrientation; + switch ( dstNode->getOrientationMode().Type ) + { + case VPathNode::k_OrientationToPoint : + { + // Fetch Orientation. + dstOrientation = ( dstNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); + dstOrientation.normalize(); + + } break; + + default : + { + // Use Path Orientation. + dstOrientation = pPathOrientation; + + } break; + } + + // Determine Actual Orientation. + VectorF orientation; + orientation.interpolate( srcOrientation, dstOrientation, pPathObject->getTimeInterp() ); + + // Apply. + pPathObject->setOrientation( orientation ); +} + +//----------------------------------------------------------------------------- +// +// Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculatePath( void ) +{ + if ( mNodeList.size() < 2 ) + { + // No Path. + return; + } + + switch ( mPathType ) + { + case k_PathLinear : + { + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + if ( itr == ( mNodeList.end() - 1 ) ) + { + // Head, Front. + calculateLinearPath( ( *itr ), ( *( mNodeList.begin() ) ) ); + } + else + { + // Head, Next. + calculateLinearPath( ( *itr ), ( *( itr + 1 ) ) ); + } + } + + } break; + + case k_PathBezier : + { + for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) + { + if ( itr == ( mNodeList.end() - 1 ) ) + { + // Head, Prev, Front. + calculateBezierPath( ( *itr ), ( *( mNodeList.begin() ) ) ); + } + else + { + // Head, Prev, Next. + calculateBezierPath( ( *itr ), ( *( itr + 1 ) ) ); + } + } + + } break; + } +} + +Point3F VPath::getAdvancedPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + switch( mPathType ) + { + case k_PathLinear : + { + return getAdvancedLinearPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); + + } break; + + case k_PathBezier : + { + return getAdvancedBezierPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); + + } break; + } + + // Sanity! + AssertFatal( false, "Invalid path type!" ); + return Point3F::Zero; +} + +DefineEngineMethod( VPath, getPathTransform, const char *, (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp), (0,0,1.0), "( int pSrcNodeIndex, int pDstNodeIndex, float pTimeInterp ) - Get the transform of the path at the interp point between two nodes.\n" + "@param pSrcNodeIndex The first node.\n" + "@param pDstNodeIndex The second node.\n" + "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" + "@return Returns the transform of the interp time between the two given nodes." ) +{ + // Fetch Nodes. + VPathNode *srcNode = object->getNode(srcNodeIndex); + VPathNode *dstNode = object->getNode(dstNodeIndex); + + // Interp Time. + const F32 &interp = timeInterp; + + // Fetch Position & Orientation. + const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); + const VectorF orientation = object->getPathOrientation( srcNode, dstNode, interp, true ); + + // Y-Axis. + VectorF yVec = orientation; + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + MatrixF mat( true ); + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + + // AngAxis. + AngAxisF aa( mat ); + + // Return Buffer; + char *buffer = Con::getReturnBuffer( 256 ); + dSprintf( buffer, 256, "%g %g %g %g %g %g %g", position.x, position.y, position.z, + aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + // Return. + return buffer; +} + +DefineEngineMethod( VPath, getPathPosition, const char *, (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp), (0, 0, 1.0), "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the world position of the path at the interp point between two nodes.\n" + "@param pSrcNodeIndex The first node.\n" + "@param pDstNodeIndex The second node.\n" + "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" + "@return Returns the world position of the interp time between the two given nodes." ) +{ + // Fetch Nodes. + VPathNode *srcNode = object->getNode(srcNodeIndex); + VPathNode *dstNode = object->getNode(dstNodeIndex); + + // Interp Time. + const F32 &interp = timeInterp; + + // Find Position. + const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); + + // Return Buffer; + char *buffer = Con::getReturnBuffer( 128 ); + dSprintf( buffer, 128, "%g %g %g", position.x, position.y, position.z ); + + // Return. + return buffer; +} + +Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + F32 pathInterp = 0.f; + return getPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pathInterp ); +} + +Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + switch( mPathType ) + { + case k_PathBezier : + { + return getBezierPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); + + } break; + + case k_PathLinear : + { + return getLinearPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); + + } break; + } + + // NULL. + return Point3F::Zero; +} + +VectorF VPath::getPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + switch( mPathType ) + { + case k_PathBezier : + { + return getBezierPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); + + } break; + + case k_PathLinear : + { + return getLinearPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); + + } break; + } + + // NULL. + return VectorF::Zero; +} + +//----------------------------------------------------------------------------- +// +// Linear Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculateLinearPath( VPathNode *pNode, VPathNode *pNextNode ) +{ + // Calculate Segment Length. + pNode->setLength( ( pNextNode->getWorldPosition() - pNode->getWorldPosition() ).len() ); +} + +Point3F VPath::getAdvancedLinearPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + + // Fetch the length of the segment. + const F32 length = ( pPathObject->isForward() ) ? srcNode->getLength() : dstNode->getLength(); + + // Set the interp delta. + pPathInterpDelta = ( pTargetDistance / length ); + + // Return the position. + F32 pathInterp = 0.f; + return getLinearPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward(), pathInterp ); +} + +Point3F VPath::getLinearPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + // Set path interp to the time interp. + pPathInterp = pTimeInterp; + + if ( pTimeInterp <= 0.f ) + { + // Source Node. + return pSourceNode->getWorldPosition(); + } + else if ( pTimeInterp >= 1.f ) + { + // Destination Node. + return pDestinationNode->getWorldPosition(); + } + + // Calculate Position. + Point3F position; + position.interpolate( pSourceNode->getWorldPosition(), pDestinationNode->getWorldPosition(), pTimeInterp ); + + // Return. + return position; +} + +VectorF VPath::getLinearPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + // Calculate Orientation. + VectorF newOrientation = ( pDestinationNode->getWorldPosition() - pSourceNode->getWorldPosition() ); + newOrientation.normalizeSafe(); + + // Return. + return newOrientation; +} + +//----------------------------------------------------------------------------- +// +// Bezier Path Methods. +// +//----------------------------------------------------------------------------- + +void VPath::calculateBezierPath( VPathNode *pNode, VPathNode *pNextNode ) +{ + // Reset Length. + F32 segmentLength = 0.f; + + // Positions. + const Point3F &pt0 = pNode->getWorldPosition(); + const Point3F &pt3 = pNextNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pNode->getWorldRotation().setMatrix( &mat0 ); + pNextNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pNode->getWeight() ); + Point3F pt2( -gBezierAxis * pNextNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Initial Position. + Point3F ptA = pt0; + const F32 i = gBezierInterpStep; + for ( F32 t = 0.f, it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F ptB = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + + // Add Segment. + segmentLength += ( ptB - ptA ).len(); + + // Store Position. + ptA = ptB; + } + + // Apply Update. + pNode->setLength( segmentLength ); +} + +Point3F VPath::getAdvancedBezierPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) +{ + // Fetch Nodes. + VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; + VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; + + // Fetch the delta position. + return getBezierPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->getPosition(), pTargetDistance, pPathObject->isForward(), true, pPathInterpDelta ); +} + +Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) +{ + // Fetch the length of the segment. + const F32 length = ( pForward ) ? pSourceNode->getLength() : pDestinationNode->getLength(); + + // Determine the real interp time for the distance fraction. + return getBezierPathPosition( pSourceNode, pDestinationNode, 0.f, pSourceNode->getWorldPosition(), ( length * pTimeInterp ), pForward, false, pPathInterp ); +} + +Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const Point3F &pReferencePosition, const F32 &pTargetDistance, const bool &pForward, const bool &pRelativeToReference, F32 &pPathInterpDelta ) +{ + // Positions. + const Point3F &pt0 = pSourceNode->getWorldPosition(); + const Point3F &pt3 = pDestinationNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pSourceNode->getWorldRotation().setMatrix( &mat0 ); + pDestinationNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); + Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); + + if ( !pForward ) + { + pt1 *= -1.f; + pt2 *= -1.f; + } + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Move Position. + Point3F movePosition = pReferencePosition; + // Movement Distance. + F32 moveDistance = 0.f; + + // Determine the Real Delta. + const F32 i = gBezierInterpStep; + for ( F32 t = ( pTimeInterp + i ), it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) + { + // Calculate Step. + const Point3F stepPosition = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + // Step Length. + const F32 &stepDistance = ( stepPosition - movePosition ).len(); + + if ( pRelativeToReference ) + { + // Calculate Distance. + moveDistance = ( pReferencePosition - stepPosition ).len(); + + // Moved Target Distance? + if ( moveDistance >= pTargetDistance ) + { + // Interpolate Step. + const F32 stepInterp = ( moveDistance - pTargetDistance ) / moveDistance; + // Store Interp Delta. + pPathInterpDelta = ( t - pTimeInterp ) * ( 1.f - stepInterp ); + + // Interpolate the step. + Point3F outPosition; + outPosition.interpolate( pReferencePosition, stepPosition, ( 1.f - stepInterp ) ); + // Return the position. + return outPosition; + } + } + else + { + // Calculate Distance. + moveDistance += stepDistance; + + // Moved Target Distance? + if ( moveDistance >= pTargetDistance ) + { + // Interpolate Step. + const F32 stepInterp = ( moveDistance - pTargetDistance ) / stepDistance; + // Store Interp Delta. + pPathInterpDelta = ( t - pTimeInterp ) - ( stepInterp * i ); + + // Interpolate the step. + Point3F outPosition; + outPosition.interpolate( movePosition, stepPosition, ( 1.f - stepInterp ) ); + // Return the position. + return outPosition; + } + } + + // Apply New Position. + movePosition = stepPosition; + } + + // Update. + pPathInterpDelta = ( 1.f - pTimeInterp ); + // At the destination node? + return pt3; +} + +VectorF VPath::getBezierPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) +{ + // Positions. + const Point3F &pt0 = pSourceNode->getWorldPosition(); + const Point3F &pt3 = pDestinationNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + pSourceNode->getWorldRotation().setMatrix( &mat0 ); + pDestinationNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); + Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); + + if ( !pForward ) + { + pt1 *= -1.f; + pt2 *= -1.f; + } + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + const F32 halfStep = ( gBezierInterpStep / 2.f ); + if ( ( pTimeInterp - halfStep ) <= 0.f ) + { + // Orientation From Node Tangent. + pt1.normalize(); + + // Return. + return pt1; + } + else if ( ( pTimeInterp + halfStep ) >= 1.f ) + { + // Orientation From Node Tangent. + pt2.normalize(); + + // Return. + return -pt2; + } + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + // Interp Times. + const F32 t0 = ( pTimeInterp - halfStep ); + const F32 it0 = ( 1.f - t0 ); + + const F32 t1 = ( pTimeInterp + halfStep ); + const F32 it1 = ( 1.f - t1 ); + + // Calculate Position. + Point3F d0 = ( pt0 * it0 * it0 * it0 ) + ( 3 * pt1 * it0 * it0 * t0 ) + ( 3 * pt2 * it0 * t0 * t0 ) + ( pt3 * t0 * t0 * t0 ); + Point3F d1 = ( pt0 * it1 * it1 * it1 ) + ( 3 * pt1 * it1 * it1 * t1 ) + ( 3 * pt2 * it1 * t1 * t1 ) + ( pt3 * t1 * t1 * t1 ); + + // Set Orientation. + Point3F orientation = ( d1 - d0 ); + orientation.normalizeSafe(); + + // Return. + return orientation; +} + +//----------------------------------------------------------------------------- +// +// Path Node Property Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VPath, getNodeCount, S32, (),, "() - Get the number of nodes in this path.\n" + "@return Returns the number of nodes." ) +{ + // Return Count. + return object->getNodeCount(); +} + +S32 VPath::getNodeCount( void ) +{ + // Return the Size of the Node List. + return mNodeList.size(); +} + +DefineEngineMethod( VPath, getNodeLocalTransform, const char *, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the local transform (local position and rotation) of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the transform of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeLocalPosition(nodeIndex); + + // Fetch Rotation. + const QuatF &rotation = object->getNodeLocalRotation(nodeIndex); + + // Angle & Axis. + AngAxisF aa( rotation ); + + // Return Buffer. + char *buffer = Con::getReturnBuffer( 256 ); + dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g %.3g %.3g %.3g", position.x, position.y, position.z, aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); + + return buffer; +} + +DefineEngineMethod( VPath, getNodeLocalPosition, Point3F, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + " @return Returns the Local Position of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeLocalPosition(nodeIndex); + + return position; +} + +Point3F VPath::getNodeLocalPosition( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLocalPosition() - Invalid Index Specified (%d).", pNodeIndex ); + return Point3F::Zero; + } + + return mNodeList[pNodeIndex]->getLocalPosition(); +} + +DefineEngineMethod( VPath, getNodeLocalRotation, AngAxisF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the Local Rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the Local Rotation of the given node." ) +{ + // Fetch Rotation. + const QuatF &rotation = object->getNodeLocalRotation(nodeIndex); + + // Angle & Axis. + AngAxisF aa( rotation ); + + return aa; +} + +QuatF VPath::getNodeLocalRotation( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLocalRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return QuatF( Point3F::Zero, 0.f ); + } + + return mNodeList[pNodeIndex]->getLocalRotation(); +} + +DefineEngineMethod( VPath, getNodeWorldTransform, TransformF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the World Transform (position and rotation) of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the transform of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeWorldPosition(nodeIndex); + + // Fetch Rotation. + const QuatF &rotation = object->getNodeWorldRotation(nodeIndex); + + // Angle & Axis. + AngAxisF aa( rotation ); + + TransformF trans; + trans.mPosition = position; + trans.mOrientation = aa; + + return trans; +} + +DefineEngineMethod( VPath, getNodeWorldPosition, Point3F, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the World Position of the given node." ) +{ + // Fetch Position. + const Point3F &position = object->getNodeWorldPosition(nodeIndex); + + return position; +} + +Point3F VPath::getNodeWorldPosition( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWorldPosition() - Invalid Index Specified (%d).", pNodeIndex ); + return Point3F::Zero; + } + + return mNodeList[pNodeIndex]->getWorldPosition(); +} + +DefineEngineMethod( VPath, getNodeWorldRotation, AngAxisF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the World Rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the World Rotation of the given node." ) +{ + // Fetch Rotation. + const QuatF &rotation = object->getNodeWorldRotation(nodeIndex); + + // Angle & Axis. + AngAxisF aa( rotation ); + + return aa; +} + +QuatF VPath::getNodeWorldRotation( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWorldRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return QuatF( Point3F::Zero, 0.f ); + } + + return mNodeList[pNodeIndex]->getWorldRotation(); +} + +DefineEngineMethod( VPath, getNodeWeight, F32, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the weight of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the weight of the given node." ) +{ + // Fetch Weight. + return object->getNodeWeight(nodeIndex); +} + +F32 VPath::getNodeWeight( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); + return 0.f; + } + + return mNodeList[pNodeIndex]->getWeight(); +} + +DefineEngineMethod( VPath, getNodeLength, F32, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the length of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns the length of the given node." ) +{ + // Fetch Length. + return object->getNodeLength( nodeIndex ); +} + +F32 VPath::getNodeLength( const S32 &pNodeIndex ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::getNodeLength() - Invalid Index Specified (%d).", pNodeIndex ); + return 0.f; + } + + return mNodeList[pNodeIndex]->getLength(); +} + +DefineEngineMethod( VPath, setNodeTransform, void, (S32 nodeIndex, TransformF transform), (0, MatrixF::Identity), "( int pNodeIndex, matrix pTransform ) - Set the transform of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pTransform The new transform to be applied to the node.\n" + "@return No return value." ) +{ + // Fetch Position & Rotation. + Point3F position = transform.mPosition; + AngAxisF aa = transform.mOrientation; + QuatF rotation; + + // Set Rotation. + rotation.set( aa ); + + // Apply Update. + object->setNodePosition( nodeIndex, position ); + object->setNodeRotation( nodeIndex, rotation ); +} + +DefineEngineMethod( VPath, setNodePosition, void, (S32 nodeIndex, Point3F position), (0, Point3F::Zero), "( int pNodeIndex, vector pPosition ) - Set the position of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pPosition The new position to be applied to the node.\n" + "@return No return value." ) +{ + // Apply Update. + object->setNodePosition( nodeIndex, position ); +} + +void VPath::setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodePosition() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setLocalPosition( pPosition ); + + // Update Size. + updateContainer(); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +DefineEngineMethod( VPath, setNodeRotation, void, (S32 nodeIndex, AngAxisF aa), (0, AngAxisF()), "( int pNodeIndex, angAxis pRotation ) - Set the rotation of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pRotation The new rotation to be applied to the node.\n" + "@return No return value." ) +{ + QuatF rotation; + + // Set Rotation. + rotation.set( aa ); + + // Apply Update. + object->setNodeRotation( nodeIndex, rotation ); +} + +void VPath::setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeRotation() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setLocalRotation( pRotation ); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +DefineEngineMethod( VPath, setNodeWeight, void, (S32 nodeIndex, F32 nodeWeight), (0, 1.0), "( int pNodeIndex, float pWeight ) - Set the weight of the given node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pWeight The new weight to be applied to the node.\n" + "@return No return value." ) +{ + // Apply Update. + object->setNodeWeight( nodeIndex, nodeWeight ); +} + +void VPath::setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply Update. + node->setWeight( pWeight ); + + // Calculate Path. + calculatePath(); + + if ( isServerObject() ) + { + // Network Flags. + setMaskBits( NodeUpdateMask ); + } +} + +DefineEngineMethod( VPath, getNodeOrientationMode, const char *, (S32 nodeIndex), (0), "( int pNodeIndex ) - Gets the current orientation mode of the node.\n" + "@param pNodeIndex The index of the node.\n" + "@return Returns a string indicating the orientation mode and its properties." ) +{ + if ( nodeIndex < 0 || nodeIndex >= object->getNodeCount() ) + { + // Woops! + Con::warnf( "VPath::getNodeOrientationMode() - Invalid Index Specified (%d).", nodeIndex ); + return ""; + } + + // Fetch Object + VPathNode *node = object->getNode( nodeIndex ); + + // Fetch Orientation Mode. + const VPathNode::sOrientation &orientation = node->getOrientationMode(); + + // Determine the Type. + StringTableEntry type = VPathNode::getOrientationTypeLabel( orientation.Type ); + + // Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + + switch( orientation.Type ) + { + case VPathNode::k_OrientationFree : + { + // Buffer String. + dSprintf( buffer, 128, "%s", type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = orientation.Point; + // Buffer String. + dSprintf( buffer, 128, "%s\t%.2f %.2f %.2f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return Buffer. + return buffer; +} + +DefineEngineStringlyVariadicMethod( VPath, setNodeOrientationMode, void, 4, 5, "( int pNodeIndex, string pOrientationType, [vector pPoint] ) - Set the orientation mode of the node.\n" + "@param pNodeIndex The index of the node.\n" + "@param pOrientationType The new orientation type of the object.\n" + "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" + "@return No return value." ) +{ + // Fetch Index. + const S32 nodeIndex = dAtoi( argv[2] ); + + // Orient? + const VPathNode::eOrientationType type = VPathNode::getOrientationTypeEnum( argv[3] ); + + switch ( type ) + { + case VPathNode::k_OrientationFree : + { + // Apply Mode. + object->setNodeOrientationMode( nodeIndex, type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + object->setNodeOrientationMode( nodeIndex, type, lookAtPoint ); + + } break; + + default : + { + AssertFatal( false, "VPath::setNodeOrientationMode() - Invalid Orientation Mode Specified." ); + + } break; + } +} + +void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply. + node->setOrientationMode( pType ); + + // Network Flags. + setMaskBits( NodeUpdateMask ); +} + +void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F pPoint ) +{ + if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) + { + // Woops! + Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); + return; + } + + // Fetch Node. + VPathNode *node = mNodeList[pNodeIndex]; + + // Apply. + node->setOrientationMode( pType, pPoint ); + + // Network Flags. + setMaskBits( NodeUpdateMask ); +} + +//----------------------------------------------------------------------------- +// +// Path Object Property Methods. +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VPath, isPathObjectActive, bool, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Is the object actively traveling around this path?\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns true of the object is active." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::isPathObjectActive() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->isActive(); +} + +DefineEngineMethod( VPath, setPathObjectActive, void, (SceneObject *sceneObject, bool isActive), (nullAsType(), true), "( SimObject pObject, bool pActive ) - Enable or disable the object from traveling around this path. Inactive objects are still attached to the path, but are not updated.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pActive The new status of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectActive() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectActive( sceneObject, isActive); +} + +void VPath::setPathObjectActive( SceneObject *pObject, const bool &pActive ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectActive() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setActive( pActive ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, getPathObjectInterp, F32, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Get the current interp position of the path object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the current interp position." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectInterp() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getTimeInterp(); +} + +DefineEngineMethod( VPath, setPathObjectInterp, void, (SceneObject *sceneObject, F32 timeInterp), (nullAsType(), 1.0), "( SimObject pObject, float pTimeInterp ) - Set the interp position of the object between its current nodes.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pTimeInterp The new interp position of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectInterp() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectInterp( sceneObject, timeInterp); +} + +void VPath::setPathObjectInterp( SceneObject *pObject, const F32 &pTimeInterp ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectInterp() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Update. + setPathObjectInterp( pathObject, pTimeInterp ); +} + +void VPath::setPathObjectInterp( VPathObject *pPathObject, const F32 &pTimeInterp ) +{ + // Set Interp Time. + pPathObject->setTimeInterp( pTimeInterp ); + + // Update Position. + updatePosition( pPathObject ); + // Update Orientation. + updateOrientation( pPathObject ); + // Reset the delta. + pPathObject->resetDelta(); + + // Set the object transform. + pPathObject->getObject()->setTransform( pPathObject->getTransform() ); + + if ( isServerObject() ) + { + // Update Objects. + setMaskBits( ObjectUpdateMask ); + + // Update This Object. + pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); + } +} + +DefineEngineMethod( VPath, getPathObjectOffset, const char *, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Get the position offset assigned to this object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the position offset." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectOffset() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Fetch Offset. + const Point3F &offset = pathObject->getOffset(); + + // Buffer. + char *buffer = Con::getReturnBuffer( 64 ); + dSprintf( buffer, 64, "%f %f %f", offset.x, offset.y, offset.z ); + return buffer; +} + +DefineEngineMethod( VPath, setPathObjectOffset, void, (SceneObject *sceneObject, Point3F offset), (nullAsType(), Point3F::Zero), "( SimObject pObject, vector pOffset ) - Set the position offset of the object. As the object is moving along the path, its position is offset by this value. Setting the \"Relative\" parameter while attaching an object will automatically apply an offset value.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pOffset The new position offset of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectOffset() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectOffset( sceneObject, offset ); +} + +void VPath::setPathObjectOffset( SceneObject *pObject, const Point3F &pOffset ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOffset() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOffset( pOffset ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, getPathObjectSpeed, F32, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Get the speed this object is traveling along the path at.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the speed of the object." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectSpeed() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getSpeed(); +} + +DefineEngineMethod( VPath, setPathObjectSpeed, void, (SceneObject *sceneObject, F32 speed), (nullAsType(), 1.0), "( SimObject pObject, float pSpeed ) - Set the speed of the object.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pSpeed The new speed of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectSpeed() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectSpeed( sceneObject, speed ); +} + +void VPath::setPathObjectSpeed( SceneObject *pObject, const F32 &pSpeed ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectSpeed() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setSpeed( mFabs( pSpeed ) ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, getPathObjectOrientationMode, const char *, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Gets the current orientation mode of the object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns a string indicating the orientation mode and its properties." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectOrientationMode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Fetch Orientation Mode. + const VPathObject::sOrientation &orientation = pathObject->getOrientationMode(); + + // Determine the Type. + StringTableEntry type = VPathObject::getOrientationTypeLabel( orientation.Type ); + + // Buffer. + char *buffer = Con::getReturnBuffer( 128 ); + + switch( orientation.Type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Buffer String. + dSprintf( buffer, 128, "%s", type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch the Object ID. + const S32 objId = ( ( orientation.Object ) ? orientation.Object->getId() : 0 ); + // Buffer String. + dSprintf( buffer, 128, "%s %d", type, objId ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = orientation.Point; + // Buffer String. + dSprintf( buffer, 128, "%s %f %f %f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return Buffer. + return buffer; +} + +DefineEngineStringlyVariadicMethod( VPath, setPathObjectOrientationMode, void, 4, 5, "( SimObject pObject, string pOrientationType, [SimObject pObject / vector pPoint] ) - Set the orientation mode of the object. This property affects the rotation of the object. If you wish to ignore the object's rotation altogether, set the mode to \"FREE\".\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pOrientationType The new orientation type of the object.\n" + "@param pObject If the orientation type is set to OBJECT, this parameter must be the SimObjectID of a scene object.\n" + "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" + "@return No return value." ) +{ + // Fetch Object. + SceneObject *sceneObject; + if ( !Sim::findObject( argv[2], sceneObject ) ) + { + Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid Target Object." ); + return; + } + + // Orient? + const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( argv[3] ); + + switch ( type ) + { + case VPathObject::k_OrientationFree : + case VPathObject::k_OrientationInterpolate : + case VPathObject::k_OrientationToPath : + { + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type ); + + } break; + + case VPathObject::k_OrientationToObject : + { + // Fetch Object. + SceneObject *lookAtObject = dynamic_cast( Sim::findObject( argv[4] ) ); + if ( !lookAtObject ) + { + Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid LookAt Object." ); + return; + } + + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type, lookAtObject ); + + } break; + + case VPathObject::k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint( 0.f, 0.f, 0.f ); + dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + object->setPathObjectOrientationMode( sceneObject, type, lookAtPoint ); + + } break; + + default : + { + AssertFatal( false, "VPath::setPathObjectOrientationMode() - Invalid Orientation Mode Specified." ); + + } break; + } +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, SceneObject *pLookAtObject ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType, pLookAtObject ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, const Point3F pPoint ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setOrientationMode( pType, pPoint ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, isPathObjectForward, bool, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Get if this object is traveling forwards along the path.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns true if the object is traveling forwards." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::isPathObjectForward() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->isForward(); +} + +DefineEngineMethod( VPath, setPathObjectForward, void, (SceneObject *sceneObject, bool forward), (nullAsType(), true), "( SimObject pObject, bool pForward ) - Set the travel direction of the object.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pForward The direction of the object.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectForward() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectForward( sceneObject, forward); +} + +void VPath::setPathObjectForward( SceneObject *pObject, const bool &pForward ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectForward() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Apply. + pathObject->setForward( pForward ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, getPathObjectNode, S32, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Gets the last node of the object.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the node index." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectNode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getSourceNode(); +} + +DefineEngineMethod( VPath, setPathObjectNode, void, (SceneObject *sceneObject, S32 nodeIndex), (nullAsType(), 0), "( SimObject pObject, bool pNodeIndex ) - Move the object to the node's position. You may also want to observe the \"setPathObjectInterp\" method.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pNodeIndex The index of the node that the object will reposition to.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectNode() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectNode( sceneObject, nodeIndex); +} + +void VPath::setPathObjectNode( SceneObject *pObject, const S32 &pNodeIndex ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectNode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Source & Destination Nodes. + const S32 srcNode = pNodeIndex; + const S32 dstNode = ( pathObject->isForward() ) ? ( pNodeIndex + 1 ) : ( pNodeIndex - 1 ); + + // Set Current Node. + pathObject->setNode( normalizeNodeIndex( srcNode ), normalizeNodeIndex( dstNode ) ); + + // Reset Interp. + pathObject->setTimeInterp( 0.f ); + pathObject->setPathInterp( 0.f ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} + +DefineEngineMethod( VPath, getPathObjectEndNode, S32, (SceneObject *sceneObject), (nullAsType()), "( SimObject pObject ) - Get the index of the node this object is meant to stop upon reaching.\n" + "@param pObject The SimObjectID of the object being observed.\n" + "@return Returns the node index." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::getPathObjectEndNode() - Invalid Target Object." ); + return false; + } + + // Fetch Object + VPathObject *pathObject = object->getPathObject( sceneObject ); + + // Return. + return pathObject->getEndNode(); +} + +DefineEngineMethod( VPath, setPathObjectEndNode, void, (SceneObject *sceneObject, S32 nodeIndex), (nullAsType(), 0), "( SimObject pObject, bool pNodeIndex ) - Set end node of the path object. If a value of \"-1\" is applied, the object will path indefinitely.\n" + "@param pObject The SimObjectID of the object being altered.\n" + "@param pNodeIndex The index of the node that the object will cease pathing upon reaching.\n" + "@return No return value." ) +{ + // Fetch Object. + if (sceneObject == nullptr) + { + Con::errorf( "VPath::setPathObjectEndNode() - Invalid Target Object." ); + return; + } + + // Apply. + object->setPathObjectEndNode( sceneObject, nodeIndex); +} + +void VPath::setPathObjectEndNode( SceneObject *pObject, const S32 &pNodeIndex ) +{ + VPathObject *pathObject = getPathObject( pObject ); + if ( !pathObject ) + { + Con::warnf( "VPath::setPathObjectEndNode() - Object (%d) Not Attached to Path.", pObject->getId() ); + return; + } + + // Set index. + S32 index = pNodeIndex; + + if ( index != -1 ) + { + // Normalize index. + normalizeNodeIndex( index ); + } + + // Apply. + pathObject->setEndNode( index ); + + // Network Flags. + setMaskBits( ObjectUpdateMask ); +} diff --git a/Engine/source/Verve/VPath/VPath.h b/Engine/source/Verve/VPath/VPath.h new file mode 100644 index 000000000..925d88d78 --- /dev/null +++ b/Engine/source/Verve/VPath/VPath.h @@ -0,0 +1,271 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATH_H_ +#define _VT_VPATH_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif + +#ifndef _VT_PATHNODE_H_ +#include "VPathNode.h" +#endif + +#ifndef _VT_PATHOBJECT_H_ +#include "VPathObject.h" +#endif + +//----------------------------------------------------------------------------- + +typedef Vector VPathNodeVector; +typedef VPathNodeVector::iterator VPathNodeIterator; + +typedef Vector VPathObjectVector; +typedef VPathObjectVector::iterator VPathObjectIterator; + +//----------------------------------------------------------------------------- + +class VPath : public SceneObject +{ + typedef SceneObject Parent; + + friend class VPathEditor; + +public: + + // Static Members. + + static SimObjectPtr gServerSet; + + static U32 gMaxNodeTransmit; + static U32 gMaxNodeBits; + static U32 gMaxNodeCount; + + static U32 gMaxObjectTransmit; + static U32 gMaxObjectBits; + static U32 gMaxObjectCount; + + static Point3F gBezierAxis; + static Point3F gBezierUp; + + enum eMaskBits + { + InitialUpdateMask = Parent::NextFreeMask << 0, + PathUpdateMask = Parent::NextFreeMask << 1, + NodeUpdateMask = Parent::NextFreeMask << 2, + ObjectUpdateMask = Parent::NextFreeMask << 3, + NextFreeMask = Parent::NextFreeMask << 4, + }; + + enum ePathType + { + k_PathLinear, + k_PathBezier, + + k_PathInvalid, + + k_PathTypeSize, + }; + +private: + + U32 mPathType; + + VPathNodeVector mNodeList; + + VPathObjectVector mObjectList; + +public: + + VPath( void ); + ~VPath( void ); + + bool onAdd( void ); + void onDeleteNotify( SimObject *pObject ); + void onRemove( void ); + + static void initPersistFields( void ); + + static SimSet *getServerSet( void ); + + // Editor Methods. + + bool collideBox( const Point3F &pStart, const Point3F &pEnd, RayInfo* pInfo ); + + // Update Methods. + + F32 getUpdatePriority( CameraScopeQuery *pFocusObject, U32 pUpdateMask, S32 pUpdateSkips ); + + void updateContainer( void ); + void updateNodeTransforms( void ); + + void setTransform( const MatrixF &pMatrix ); + void setScale( const VectorF &pScale ); + + void setPathType( const ePathType &pType ); + static bool setPathType( void *pObject, const char *pArray, const char *pData ); + + // Mounting Methods. + + U32 getAvailableMountIndex( void ); + bool isMountIndex( const U32 &pIndex ); + + void mountObject( SceneObject *pObject, S32 pIndex, const MatrixF &pTransform = MatrixF::Identity ); + void unmountObject( SceneObject *pObject ); + + void getMountTransform( S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ); + void getRenderMountTransform( F32 pDelta, S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ); + + VectorF getMountVelocity( const U32 &pIndex ); + + // Persistence Methods. + + void readFields( void ); + void writeFields( Stream &pStream, U32 pTabStop ); + + U32 packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + DECLARE_CONOBJECT( VPath ); + +public: + + // Node Methods. + + static VPathNode *createNode( void ); + static void deleteNode( VPathNode *pNode ); + + void clear( void ); + + VPathNode *getNode( const S32 &pNodeIndex ); + + VPathNode *addNode( const Point3F &pPosition, const QuatF &pRotation, const F32 &pWeight, const S32 &pLocation = -1 ); + VPathNode *addNode( VPathNode *pNode, const S32 &pLocation = -1 ); + + void deleteNode( const S32 &pNodeIndex ); + void removeNode( const S32 &pNodeIndex ); + + S32 normalizeNodeIndex( S32 &pNodeIndex ); + S32 normalizeNodeIndex( const S32 &pNodeIndex ); + S32 normalizeNodeIndex( S32 &pNodeIndex, const S32 &pNodeCount ); + + // Object Methods. + + bool isObjectAttached( SceneObject *pObject ); + VPathObject *getPathObject( SceneObject *pObject ); + + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode ); + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode ); + void attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode, void *pOrientationData ); + void attachObject( VPathObject *pPathObject ); + void onAttachObject( VPathObject *pPathObject ); + + void detachObject( SceneObject *pObject ); + void detachObject( VPathObject *pPathObject ); + void onDetachObject( VPathObject *pPathObject ); + + void processTick( const Move *pMove ); + void advanceObject( VPathObject *pPathObject, const F32 &pDelta ); + + void updatePosition( VPathObject *pPathObject ); + void updateOrientation( VPathObject *pPathObject ); + void updateOrientation( VPathObject *pPathObject, const Point3F &pPathOrientation ); + + // Path Methods. + + void calculatePath( void ); + + Point3F getAdvancedPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ); + Point3F getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ); + VectorF getPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ); + + // + // Linear Path Methods. + + void calculateLinearPath( VPathNode *pNode, VPathNode *pNextNode ); + + Point3F getAdvancedLinearPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getLinearPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward, F32 &pPathInterp ); + VectorF getLinearPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward ); + + // + // Bezier Path Methods. + + void calculateBezierPath( VPathNode *pNode, VPathNode *pNextNode ); + + Point3F getAdvancedBezierPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pInterpDelta ); + + Point3F getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward, F32 &pPathInterp ); + Point3F getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const Point3F &pReferencePosition, const F32 &pTargetDistance, const bool &pForward, const bool &pRelativeToReference, F32 &pPathInterpDelta ); + VectorF getBezierPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pInterp, const bool &pForward ); + +public: + + // Node Property Methods. + + S32 getNodeCount( void ); + + Point3F getNodeLocalPosition( const S32 &pNodeIndex ); + Point3F getNodeWorldPosition( const S32 &pNodeIndex ); + QuatF getNodeLocalRotation( const S32 &pNodeIndex ); + QuatF getNodeWorldRotation( const S32 &pNodeIndex ); + F32 getNodeWeight( const S32 &pNodeIndex ); + F32 getNodeLength( const S32 &pNodeIndex ); + + void setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ); + void setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ); + void setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ); + + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F pPoint ); + + // Path Object Property Methods. + + void setPathObjectActive( SceneObject *pObject, const bool &pActive ); + void setPathObjectInterp( SceneObject *pObject, const F32 &pTimeInterp ); + void setPathObjectOffset( SceneObject *pObject, const Point3F &pOffset ); + void setPathObjectSpeed( SceneObject *pObject, const F32 &pSpeed ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, SceneObject *pLookAtObject ); + void setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, const Point3F pPoint ); + void setPathObjectForward( SceneObject *pObject, const bool &pForward ); + void setPathObjectNode( SceneObject *pObject, const S32 &pNodeIndex ); + void setPathObjectEndNode( SceneObject *pObject, const S32 &pNodeIndex ); + + void setPathObjectInterp( VPathObject *pPathObject, const F32 &pTimeInterp ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPath::ePathType VPathType; + +// Declare Enum Types. +DefineEnumType( VPathType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATH_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPathEditor.cpp b/Engine/source/Verve/VPath/VPathEditor.cpp new file mode 100644 index 000000000..6315e6560 --- /dev/null +++ b/Engine/source/Verve/VPath/VPathEditor.cpp @@ -0,0 +1,2190 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathEditor.h" + +#include "console/consoleTypes.h" +#include "gfx/gfxDrawUtil.h" +#include "gfx/primBuilder.h" +#include "gui/worldEditor/worldEditor.h" +#include "math/mathUtils.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static F32 gProjectDistance = 2000.f; +static F32 gSelectionDistance = 2.f; + +static ColorI gPathColor( 255, 255, 255 ); +static ColorI gPathColorSel( 0, 255, 255 ); +static ColorI gNodeLookAtPointColor( 255, 127, 39 ); + +//----------------------------------------------------------------------------- + +// Implement the Edit Mode enum list. +ImplementEnumType( VPathEditorMode, "" ) + { VPathEditor::k_Gizmo, "GIZMO" }, + { VPathEditor::k_AddNode, "ADDNODE" }, + { VPathEditor::k_DeleteNode, "DELETENODE" }, +EndImplementEnumType; + +//----------------------------------------------------------------------------- +IMPLEMENT_CONOBJECT( VPathEditor ); +//----------------------------------------------------------------------------- + +VPathEditor::VPathEditor( void ) : + mIsDirty( false ), + mEditMode( k_Gizmo ), + mEditWeight( false ), + mEditWeightHandle( -1 ) +{ + // Void. +} + +bool VPathEditor::onAdd( void ) +{ + if ( !Parent::onAdd() ) + { + return false; + } + + // Assign Gizmo Name. + mGizmo->assignName( "VPathEditorGizmo" ); + + return true; +} + +bool VPathEditor::onWake( void ) +{ + // Clear Selection. + updateSelection( NULL, -1 ); + + // Return Parent Value. + return Parent::onWake(); +} + +void VPathEditor::initPersistFields( void ) +{ + addField( "IsDirty", TypeBool, Offset( mIsDirty, VPathEditor ) ); + addField( "EditMode", TYPEID(), Offset( mEditMode, VPathEditor ) ); + + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- +// +// Gui Events +// +//----------------------------------------------------------------------------- + +void VPathEditor::on3DMouseDown( const Gui3DMouseEvent &pEvent ) +{ + // Using the Gizmo? + if ( mEditMode != k_Gizmo ) + { + // No, Quit Now. + return; + } + + // Gizmo Event. + mGizmo->on3DMouseDown( pEvent ); + + if ( isValidSelection() ) + { + // Store Node Information. + pushNodeEdit(); + + switch( mGizmoProfile->mode ) + { + case MoveMode: + case RotateMode: + { + if ( mGizmo->getSelection() != Gizmo::None ) + { + // Using Gizmo. + return; + } + + } break; + + case ScaleMode: + { + if ( isEditingWeight( pEvent ) ) + { + // Editing Weights. + return; + } + + } break; + } + } + else if ( mSelection.Path ) + { + // Store Path Information. + pushPathEdit(); + + if ( mGizmo->getSelection() != Gizmo::None ) + { + // Using Gizmo. + return; + } + } + + // Update Selection. + if ( !updateSelection( pEvent ) ) + { + // Clear Selection. + updateSelection( NULL, -1 ); + } +} + +void VPathEditor::on3DMouseUp( const Gui3DMouseEvent &pEvent ) +{ + switch ( mEditMode ) + { + case k_Gizmo : + { + // Gizmo Event. + mGizmo->on3DMouseUp( pEvent ); + + // Handle History Actions. + popPathEdit(); + popNodeEdit(); + + // Clear Editing. + mEditWeight = false; + + } break; + + case k_AddNode : + { + if ( mSelection.Path != NULL ) + { + // Add New! + addNode( pEvent ); + + // Dirty. + mIsDirty = true; + } + + } break; + + case k_DeleteNode : + { + // Update Selection. + if ( updateSelection( pEvent ) ) + { + if ( isValidSelection() ) + { + // Delete Node. + deleteNode( mSelection.Node ); + + // Dirty. + mIsDirty = true; + } + + // Clear Node Selection. + updateSelection( mSelection.Path, -1 ); + } + + } break; + } +} + +void VPathEditor::on3DMouseMove( const Gui3DMouseEvent &pEvent ) +{ + // Update? + if ( mEditMode != k_Gizmo || !mSelection.Path ) + { + return; + } + + // Update Gizmo? + if ( mSelection.Node == -1 || mGizmoProfile->mode != ScaleMode ) + { + // Gizmo Event. + mGizmo->on3DMouseMove( pEvent ); + } +} + +void VPathEditor::on3DMouseDragged( const Gui3DMouseEvent &pEvent ) +{ + // Update? + if ( mEditMode != k_Gizmo || !mSelection.Path ) + { + return; + } + + // Update Gizmo? + if ( mSelection.Node == -1 || mGizmoProfile->mode != ScaleMode ) + { + // Gizmo Event. + mGizmo->on3DMouseDragged( pEvent ); + + // Handle Gizmo? + if ( mGizmo->getSelection() == Gizmo::None ) + { + // Return. + return; + } + } + + // Editing the Path? + if ( mSelection.Node == -1 ) + { + switch ( mGizmoProfile->mode ) + { + case MoveMode : + { + // Fetch Node Position. + const Point3F oldPosition = mSelection.Path->getPosition(); + // Determine New Position. + const Point3F newPosition = ( oldPosition + mGizmo->getOffset() ); + + // Apply New Position. + setPathPosition( newPosition ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + /* + case RotateMode : + { + + // Rotation Delta. + MatrixF deltaRotation( EulerF( mGizmo->getDeltaRot() ) ); + + // Fetch Current Transform. + MatrixF mat = mSelection.Path->getTransform(); + mat.mul( deltaRotation ); + + // Apply New Transform. + setPathTransform( mat ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + + case ScaleMode : + { + + // Apply New Scale. + setPathScale( mGizmo->getScale() ); + + // Dirty. + mIsDirty = true; + mPathEdit.Dirty = true; + + } break; + */ + } + } + + // No, Editing a Node + else + { + switch ( mGizmoProfile->mode ) + { + case MoveMode : + { + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Fetch Node Position. + const Point3F oldPosition = node->getLocalPosition(); + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + Point3F deltaPosition = mGizmo->getOffset(); + pathTransform.mulP( deltaPosition ); + + // Apply New Position. + setNodePosition( mSelection.Node, ( oldPosition + deltaPosition ) ); + + } break; + + case RotateMode : + { + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + // Rotation Delta. + MatrixF deltaRotation( EulerF( mGizmo->getDeltaRot() ) ); + pathTransform.mul( deltaRotation ); + + // Fetch Current Transform. + MatrixF mat = node->getWorldTransform(); + mat.mul( deltaRotation ); + + // Construct Quat. + QuatF newRotation; + newRotation.set( mat ); + + // Apply New Rotation. + setNodeRotation( mSelection.Node, newRotation ); + + } break; + + case ScaleMode : + { + + if ( isEditingWeight() ) + { + // Edit Weight. + updateWeight( pEvent ); + } + + } break; + } + } +} + +//----------------------------------------------------------------------------- +// +// Reference Methods. +// +//----------------------------------------------------------------------------- + +VPath *VPathEditor::getClientPath( VPath *pPath ) +{ + if ( !pPath ) + { + return NULL; + } + + NetConnection *toServer = NetConnection::getConnectionToServer(); + NetConnection *toClient = NetConnection::getLocalClientConnection(); + if ( !toServer || !toClient ) + { + return NULL; + } + + const S32 ghostIndex = toClient->getGhostIndex( pPath ); + if ( ghostIndex == -1 ) + { + return NULL; + } + + return dynamic_cast( toServer->resolveGhost( ghostIndex ) ); +} + +//----------------------------------------------------------------------------- +// +// Selection Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::updateSelection( const Gui3DMouseEvent &pEvent ) +{ + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + RayInfo ri; + if ( !gServerContainer.collideBox( pt0, pt1, MarkerObjectType, &ri ) ) + { + // No Object. + return false; + } + + VPath *path = dynamic_cast( ri.object ); + if ( !path ) + { + // No Path Object. + return false; + } + + // No Node. + S32 nodeIndex = -1; + + for ( VPathNodeIterator itr = path->mNodeList.begin(); itr != path->mNodeList.end(); itr++ ) + { + VPathNode *node = ( *itr ); + + Point3F projPosition; + project( node->getWorldPosition(), &projPosition ); + + if ( projPosition.z <= 0.0f ) + { + continue; + } + + const Point2I rectHalfSize( 8, 8 ); + const Point2I screenPosition( ( S32 )projPosition.x, ( S32 )projPosition.y ); + const RectI screenRect( screenPosition - rectHalfSize, 2 * rectHalfSize ); + + // Mouse Close Enough? + if ( screenRect.pointInRect( pEvent.mousePoint ) ) + { + // Select Node. + nodeIndex = ( itr - path->mNodeList.begin() ); + } + } + + // Set Selection. + updateSelection( path, nodeIndex ); + + // Valid Selection. + return true; +} + +void VPathEditor::updateSelection( VPath *pPathObject, const S32 &pNodeIndex ) +{ + // Store Selection. + mSelection.Path = pPathObject; + mSelection.Node = pNodeIndex; + + // Quick Update. + updateSelection(); + + // Return Buffer. + char buffer[2][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", ( pPathObject ) ? pPathObject->getId() : 0 ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + + // Callback. + Con::executef( this, "onUpdateSelection", buffer[0], buffer[1] ); +} + +void VPathEditor::updateSelection( void ) +{ + if ( !isValidSelection() ) + { + // No Further Updates. + return; + } + + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Fetch Node Rotation Matrix. + MatrixF mat; + node->getWorldRotation().setMatrix( &mat ); + + // Determine Tangent Axis. + Point3F pt0( VPath::gBezierAxis * node->getWeight() ); + Point3F pt1( -VPath::gBezierAxis * node->getWeight() ); + + // Rotate Axis. + mat.mulP( pt0 ); + mat.mulP( pt1 ); + + // Offset Points. + pt0 += node->getWorldPosition(); + pt1 += node->getWorldPosition(); + + // Store Points. + mSelection.TangentHandle[0] = pt0; + mSelection.TangentHandle[1] = pt1; +} + +DefineEngineMethod( VPathEditor, clearSelection, void, (),, "( void )" ) +{ + // Clear Selection. + object->updateSelection( NULL, -1 ); +} + +DefineEngineMethod(VPathEditor, setSelection, void, (SceneObject* sceneObject, S32 nodeIndex), (nullAsType(), -1), "( pObject, [pNodeIndex] )") +{ + if (sceneObject == nullptr) + { + Con::errorf("VPathEditor::setSelection() - Unable to select target Object."); + return; + } + // Fetch Path. + VPath *path = dynamic_cast(sceneObject); + if ( !path ) + { + Con::errorf( "VPathEditor::setSelection() - Unable to select target Object." ); + return; + } + + object->updateSelection( path, nodeIndex); +} + +DefineEngineMethod( VPathEditor, isValidSelection, bool, (),, "( void )" ) +{ + return object->isValidSelection(); +} + +DefineEngineMethod( VPathEditor, getSelectedPath, S32, (),, "( void )" ) +{ + // Fetch Path. + VPath *path = object->mSelection.Path; + + // Return ID. + return ( path ) ? path->getId() : 0; +} + +DefineEngineMethod( VPathEditor, getSelectedNode, S32, (),, "( void )" ) +{ + // Return Node Index. + return ( object->mSelection.Path ) ? object->mSelection.Node : -1; +} + +DefineEngineMethod( VPathEditor, deleteSelection, void, (),, "( void )" ) +{ + // Valid Selection? + if ( object->isValidSelection() ) + { + object->deleteNode( object->mSelection.Node ); + } +} + +//----------------------------------------------------------------------------- +// +// Weight Editing Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::isEditingWeight( const Gui3DMouseEvent &pEvent ) +{ + if ( !isValidSelection() || mSelection.Path->mPathType != VPath::k_PathBezier ) + { + // False. + mEditWeight = false; + + // Invalid Selection. + return false; + } + + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + // Min Index. + S32 minNode = -1; + F32 minDistance = F32_MAX; + + for ( S32 i = 0; i < 2; i++ ) + { + Point3F pt; + if ( !Utility::FindNearestPointOnLine( mSelection.TangentHandle[i], pt0, pt1, &pt ) ) + { + // Skip. + continue; + } + + // Distance. + const F32 ptDistance = ( pt - mSelection.TangentHandle[i] ).len(); + if ( ptDistance < minDistance ) + { + // Store Index. + minNode = i; + + // Store Distance. + minDistance = ptDistance; + } + } + + if ( minDistance > gSelectionDistance ) + { + // False. + mEditWeight = false; + + // Too Far Away. + return false; + } + + // True. + mEditWeight = true; + mEditWeightHandle = minNode; + + return true; +} + +void VPathEditor::updateWeight( const Gui3DMouseEvent &pEvent ) +{ + if ( !isEditingWeight() ) + { + // Woops! + return; + } + + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + Point3F nodePos = node->getWorldPosition(); + + // Fetch Node Transform. + MatrixF mat = node->getWorldTransform(); + + // Fetch the Normal. + const VectorF planeNormal = mat.getColumn3F( 0 ); + + // Construct Plane. + const PlaneF plane( nodePos, planeNormal ); + + Point3F iPt; + if ( plane.intersect( pEvent.pos, pEvent.vec, &iPt ) ) + { +/* + // Fetch Edit Vector. + VectorF tangentVect( mSelection.TangentHandle[mEditWeightHandle] - nodePos ); + tangentVect.normalize(); + + // Fetch Mouse Vector. + VectorF mouseVec( iPt - nodePos ); + F32 mouseDist = mouseVec.len(); + mouseVec.normalize(); + + // Find the Angles. + F32 tangentAngle = mAtan2( -tangentVect.z, tangentVect.x ); + F32 mouseAngle = mAtan2( -mouseVec.z, mouseVec.x ); + + // Determine Sign. + const S32 sign = ( planeNormal.y > 0.f ) ? -1.f : 1.f; + + // Delta Rotation.. + const QuatF deltaRotation( AngAxisF( planeNormal, sign * ( mouseAngle - tangentAngle ) ) ); + + // Calculate New Rotation. + QuatF newRotation; + newRotation.mul( nodePos, deltaRotation ); + + // Apply Rotation. + setNodeRotation( mSelection.Node, newRotation ); +*/ +/* + // Fetch Edit Vector. + VectorF handleVec( mSelection.TangentHandle[mEditWeightHandle] - nodePos ); + handleVec.normalize(); + + // Fetch Mouse Vector. + VectorF mouseVec( iPt - nodePos ); + mouseVec.normalize(); + + // Find the Angles. + F32 handleAngle = Utility::GetPitch( handleVec ); //mAtan2( -handleVec.z, handleVec.x ); + F32 mouseAngle = Utility::GetPitch( mouseVec ); //mAtan2( -mouseVec.z, mouseVec.x ); + + // Determine Sign. + const S32 sign = ( planeNormal.y > 0.f ) ? -1.f : 1.f; + + // Delta Rotation. + MatrixF rotMat; + AngAxisF::RotateY( sign * ( mouseAngle - handleAngle ), &rotMat ); + + // Rotate. + mat.mul( rotMat ); + + QuatF newRotation; + newRotation.set( mat ); + + // Apply Rotation. + setNodeRotation( mSelection.Node, newRotation ); +*/ + // Apply Weight. + setNodeWeight( mSelection.Node, ( iPt - nodePos ).len() ); + } +} + +//----------------------------------------------------------------------------- +// +// Path Editing Methods. +// +//----------------------------------------------------------------------------- + +void VPathEditor::setPathPosition( const Point3F &pPosition ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Update Position. + serverPath->setPosition( pPosition ); + clientPath->setPosition( pPosition ); + + // Update Selection. + updateSelection(); +} + +void VPathEditor::setPathRotation( const QuatF &pRotation ) +{ + // Determine the Matrix. + MatrixF mat; + pRotation.setMatrix( &mat ); + mat.setPosition( mSelection.Path->getPosition() ); + + // Update Transform. + setPathTransform( mat ); +} + +void VPathEditor::setPathTransform( const MatrixF &pTransform ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Update Transform. + serverPath->setTransform( pTransform ); + clientPath->setTransform( pTransform ); + + // Update Selection. + updateSelection(); +} + +void VPathEditor::setPathScale( const VectorF &pScale ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Fetch Current Scale. + VectorF scale = serverPath->getScale(); + scale.convolve( pScale ); + + // Update Scale. + serverPath->setScale( scale ); + clientPath->setScale( scale ); + + // Update Selection. + updateSelection(); +} + +//----------------------------------------------------------------------------- +// +// Node Editing Methods. +// +//----------------------------------------------------------------------------- + +bool VPathEditor::getPointOnPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + if ( pPath->getNodeCount() < 2 ) + { + // Start / End Points. + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + // Create Intersection Plane. + const PlaneF plane( pPath->getPosition(), VPath::gBezierUp ); + + // Intersection Point. + Point3F intersectionPoint; + if ( !plane.intersect( pEvent.pos, pEvent.vec, &intersectionPoint ) ) + { + // No Intersection. + return false; + } + + // I'th Node. + pNode = pPath->getNodeCount(); + // Set Identity. + pTransform.identity(); + // Set Position. + pTransform.setPosition( intersectionPoint ); + + // Return. + return true; + } + + switch ( pPath->mPathType ) + { + case VPath::k_PathLinear : + { + + return getPointOnLinearPath( pPath, pEvent, pNode, pTransform ); + + } break; + + case VPath::k_PathBezier : + { + + return getPointOnBezierPath( pPath, pEvent, pNode, pTransform ); + + } break; + } + + return false; +} + +bool VPathEditor::getPointOnLinearPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + // Start / End Points. + const Point3F pt0 = pEvent.pos; + const Point3F pt1 = pEvent.pos + pEvent.vec * gProjectDistance; + + S32 minNode = -1; + F32 minDistance = F32_MAX; + Point3F minPoint( 0.f, 0.f, 0.f ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Project to Screen. + Point3F srcNodeScreenPosition, dstNodeScreenPosition; + project( srcNode->getWorldPosition(), &srcNodeScreenPosition ); + project( dstNode->getWorldPosition(), &dstNodeScreenPosition ); + + // Skip? + if ( srcNodeScreenPosition.z > 1.f && dstNodeScreenPosition.z > 1.f ) + { + continue; + } + + Point3F ptOut0, ptOut1; + F32 ptOutDistance; + if ( !Utility::FindNearestDistanceBetweenLines( pt0, pt1, + srcNode->getWorldPosition(), dstNode->getWorldPosition(), + &ptOut0, &ptOut1, &ptOutDistance ) ) + { + continue; + } + + if ( ptOutDistance < minDistance ) + { + minDistance = ptOutDistance; + minPoint = ptOut1; + minNode = ( itr - pPath->mNodeList.begin() ); + } + } + + // Distance too Large? + if ( minDistance > 0.25f ) + { + // Invalid. + return false; + } + + // Setup. + pTransform.identity(); + pTransform.setPosition( minPoint ); + + // Store Node. + pNode = minNode; + + return true; +} + +bool VPathEditor::getPointOnBezierPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ) +{ + S32 minNode = -1; + F32 minInterp = 0.f; + F32 minDistance = F32_MAX; + Point3F minPoint( 0.f, 0.f, 0.f ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Project to Screen. + Point3F srcNodeScreenPosition, dstNodeScreenPosition; + project( srcNode->getWorldPosition(), &srcNodeScreenPosition ); + project( dstNode->getWorldPosition(), &dstNodeScreenPosition ); + + // Skip? + if ( srcNodeScreenPosition.z > 1.f && dstNodeScreenPosition.z > 1.f ) + { + continue; + } + + // Positions. + const Point3F &pt0 = srcNode->getWorldPosition(); + const Point3F &pt3 = dstNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + srcNode->getWorldRotation().setMatrix( &mat0 ); + dstNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( VPath::gBezierAxis * srcNode->getWeight() ); + Point3F pt2( -VPath::gBezierAxis * dstNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + for ( F32 t = 0.f, it = 1.f; t <= 1.f; t += 0.1f, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F pos = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + + // Determine the Screen Position. + Point3F screenPos; + project( pos, &screenPos ); + // Behind? + if ( screenPos.z > 1.f ) + { + // Skip Point. + continue; + } + + // Determine the Distance. + F32 screenDistance = Point2F( screenPos.x - pEvent.mousePoint.x, screenPos.y - pEvent.mousePoint.y ).lenSquared(); + // Min Distance? + if ( screenDistance < minDistance ) + { + // Store. + minDistance = screenDistance; + minInterp = t; + minPoint = pos; + minNode = ( itr - pPath->mNodeList.begin() ); + } + } + } + + // Distance too Large? + if ( minDistance > 1000.f ) + { + // Invalid. + return false; + } + + // Fetch Orientation. + const VectorF &orientation = pPath->getPathOrientation( pPath->getNode( minNode ), + pPath->getNode( ( minNode + 1 ) % pPath->getNodeCount() ), + minInterp, true ); + + // Z-Axis. + VectorF zVec = -orientation; + zVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( VPath::gBezierUp, zVec ); + xVec.normalize(); + + // Y-Axis. + VectorF yVec = mCross( zVec, xVec ); + yVec.normalize(); + + // Setup Object Transform. + pTransform.identity(); + pTransform.setColumn( 0, xVec ); + pTransform.setColumn( 1, -zVec ); + pTransform.setColumn( 2, yVec ); + // Set the Position. + pTransform.setPosition( minPoint ); + + // Store Node. + pNode = minNode; + + return true; +} + +void VPathEditor::addNode( const Gui3DMouseEvent &pEvent ) +{ + VPath *path = mSelection.Path; + if ( !path ) + { + // Woops! + return; + } + + // Min Index. + S32 nodeIndex = -1; + MatrixF nodeTransform( true ); + if ( !getPointOnPath( path, pEvent, nodeIndex, nodeTransform ) ) + { + // Can't Add. + return; + } + + // Invert Transform. + MatrixF pathTransform = mSelection.Path->getTransform(); + pathTransform.setPosition( Point3F::Zero ); + pathTransform.inverse(); + + Point3F nodePosition = ( nodeTransform.getPosition() - mSelection.Path->getPosition() ); + pathTransform.mulP( nodePosition ); + + // Node Rotation. + nodeTransform.mul( pathTransform ); + QuatF nodeRotation( nodeTransform ); + + // Node Weights. + F32 nodeWeight = 10.f; + + // Add New Node. + VPathNode *node = path->addNode( nodePosition, nodeRotation, nodeWeight, ++nodeIndex ); + + // Valid Node? + if ( !node ) + { + return; + } + + // Update Size. + path->updateContainer(); + + // Calculate Path. + path->calculatePath(); + + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor::addNode() - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorAddNodeAction *editAction = new VPathEditorAddNodeAction(); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = path; + editAction->mNodeIndex = nodeIndex; + + editAction->mNodePosition = nodePosition; + editAction->mNodeRotation = nodeRotation; + editAction->mNodeWeight = nodeWeight; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Set World Editor Dirty. + setWorldEditorDirty(); +} + +void VPathEditor::deleteNode( const S32 &pNodeIndex ) +{ + VPath *path = mSelection.Path; + if ( !path ) + { + // Woops! + return; + } + + // Fetch Node Properites. + VPathNode *node = path->getNode( pNodeIndex ); + const Point3F position = node->getLocalPosition(); + const QuatF rotation = node->getLocalRotation(); + const F32 weight = node->getWeight(); + + // Delete Node. + path->deleteNode( pNodeIndex ); + + // Update Path. + path->updateContainer(); + + // Calculate Path. + path->calculatePath(); + + // Selected Node? + const S32 _nodeIndex = pNodeIndex; + if ( pNodeIndex == mSelection.Node ) + { + // Update Selection. + updateSelection( mSelection.Path, -1 ); + } + + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor::deleteNode() - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorDeleteNodeAction *editAction = new VPathEditorDeleteNodeAction(); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = path; + editAction->mNodeIndex = _nodeIndex; + + editAction->mNodePosition = position; + editAction->mNodeRotation = rotation; + editAction->mNodeWeight = weight; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Set World Editor Dirty. + setWorldEditorDirty(); +} + +void VPathEditor::setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeLocalPosition( pNodeIndex ) == pPosition ) + { + return; + } + + // Set Position. + serverPath->setNodePosition( pNodeIndex, pPosition ); + clientPath->setNodePosition( pNodeIndex, pPosition ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodePosition", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeLocalRotation( pNodeIndex ) == pRotation ) + { + return; + } + + // Set Position. + serverPath->setNodeRotation( pNodeIndex, pRotation ); + clientPath->setNodeRotation( pNodeIndex, pRotation ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeRotation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Change? + if ( serverPath->getNodeWeight( pNodeIndex ) == pWeight ) + { + return; + } + + // Set Weight. + serverPath->setNodeWeight( pNodeIndex, pWeight ); + clientPath->setNodeWeight( pNodeIndex, pWeight ); + + // Update Selection. + updateSelection(); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeWeight", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Set Orientation Mode. + serverPath->setNodeOrientationMode( pNodeIndex, pType ); + clientPath->setNodeOrientationMode( pNodeIndex, pType ); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeOrientation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F &pPoint ) +{ + // Fetch Paths. + VPath *serverPath = mSelection.Path; + VPath *clientPath = getClientPath( serverPath ); + + // Sanity! + if ( !serverPath || !clientPath ) + { + return; + } + + // Set Orientation Mode. + serverPath->setNodeOrientationMode( pNodeIndex, pType, pPoint ); + clientPath->setNodeOrientationMode( pNodeIndex, pType, pPoint ); + + // Dirty. + mIsDirty = true; + mNodeEdit.Dirty = true; + + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mSelection.Path->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mSelection.Node == pNodeIndex ) ); + + // Callback. + Con::executef( this, "onUpdateNodeOrientation", buffer[0], buffer[1], buffer[2] ); +} + +void VPathEditor::pushPathEdit( void ) +{ + // Clear Current Edit Dirty. + mPathEdit.Dirty = false; + + if ( mSelection.Path != NULL ) + { + // Store Node Details. + mPathEdit.Transform = mSelection.Path->getTransform(); + } +} + +void VPathEditor::popPathEdit( void ) +{ + // Did Edit? + if ( mPathEdit.Dirty && mSelection.Path != NULL ) + { + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorEditPathAction *editAction = new VPathEditorEditPathAction( "Edit Path" ); + + // Store Editor. + editAction->mEditor = this; + + // Store Path Details. + editAction->mPath = mSelection.Path; + editAction->mTransform = mPathEdit.Transform; + + // Add To Manager. + historyManager->addAction( editAction ); + + // Clear Dirty. + mPathEdit.Dirty = false; + + // Set World Editor Dirty. + setWorldEditorDirty(); + } +} + +void VPathEditor::pushNodeEdit( void ) +{ + // Clear Current Edit Dirty. + mNodeEdit.Dirty = false; + + if ( isValidSelection() ) + { + // Fetch Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Store Node Details. + mNodeEdit.Position = node->getLocalPosition(); + mNodeEdit.Rotation = node->getLocalRotation(); + mNodeEdit.Weight = node->getWeight(); + } +} + +void VPathEditor::popNodeEdit( void ) +{ + // Did Edit? + if ( mNodeEdit.Dirty && isValidSelection() ) + { + UndoManager *historyManager = NULL; + if ( !Sim::findObject( "EUndoManager", historyManager ) ) + { + Con::errorf( "VPathEditor - EUndoManager not found!" ); + return; + } + + // Create Undo Action. + VPathEditorEditNodeAction *editAction = new VPathEditorEditNodeAction( "Edit Node" ); + + // Store Editor. + editAction->mEditor = this; + + // Store Node Details. + editAction->mPath = mSelection.Path; + editAction->mNodeIndex = mSelection.Node; + + editAction->mNodePosition = mNodeEdit.Position; + editAction->mNodeRotation = mNodeEdit.Rotation; + editAction->mNodeWeight = mNodeEdit.Weight; + + editAction->mNodeOrientation = mSelection.Path->getNode( mSelection.Node )->getOrientationMode(); + + // Add To Manager. + historyManager->addAction( editAction ); + + // Clear Dirty. + mNodeEdit.Dirty = false; + + // Set World Editor Dirty. + setWorldEditorDirty(); + } +} + +void VPathEditor::setWorldEditorDirty( void ) +{ + WorldEditor *worldEditor; + if ( Sim::findObject( "EWorldEditor", worldEditor ) ) + { + worldEditor->setDirty(); + } +} + +//----------------------------------------------------------------------------- +// +// Render Methods. +// +//----------------------------------------------------------------------------- + +void VPathEditor::setStateBlock( void ) +{ + // Valid State Block? + if ( !mStateBlock ) + { + // Setup Definition. + GFXStateBlockDesc def; + def.blendDefined = true; + def.blendEnable = true; + def.blendSrc = GFXBlendSrcAlpha; + def.blendDest = GFXBlendInvSrcAlpha; + def.zDefined = true; + def.cullDefined = false; + + // Create State Block. + mStateBlock = GFX->createStateBlock( def ); + } + + // Set State Block. + GFX->setStateBlock( mStateBlock ); +} + +void VPathEditor::renderScene( const RectI &pUpdateRect ) +{ + // Setup State Block. + setStateBlock(); + + if ( isValidSelection() ) + { + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // Render Gizmo? + if ( mEditMode == k_Gizmo && mGizmoProfile->mode != ScaleMode ) + { + // Fetch Node Transform. + MatrixF mat= node->getWorldTransform(); + + // Move Gizmo. + mGizmo->set( mat, node->getWorldPosition(), Point3F( 1.0f, 1.0f, 1.0f ) ); + + // Render Gizmo. + mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix ); + } + + // Render Handles? + if ( mSelection.Path->mPathType == VPath::k_PathBezier ) + { + // Fetch Tangent Handles. + const Point3F &pt0 = mSelection.TangentHandle[0]; + const Point3F &pt1 = mSelection.TangentHandle[1]; + + // State Block. + GFXStateBlockDesc desc; + desc.setZReadWrite( true, true ); + desc.fillMode = GFXFillSolid; + + // Set Color. + PrimBuild::color( gPathColorSel ); + + // Render Line. + PrimBuild::begin( GFXLineList, 2 ); + PrimBuild::vertex3fv( pt0 ); + PrimBuild::vertex3fv( pt1 ); + PrimBuild::end(); + + // Render Handles. + GFX->getDrawUtil()->drawSphere( desc, 0.1f, pt0, gPathColorSel ); + GFX->getDrawUtil()->drawSphere( desc, 0.1f, pt1, gPathColorSel ); + } + + // ToPoint Node? + if ( node->getOrientationMode().Type == VPathNode::k_OrientationToPoint ) + { + PrimBuild::color( gNodeLookAtPointColor ); + PrimBuild::begin( GFXLineStrip, 2 ); + + PrimBuild::vertex3fv( node->getWorldPosition() ); + PrimBuild::vertex3fv( node->getOrientationMode().Point ); + + PrimBuild::end(); + } + } + else if ( mSelection.Path && mEditMode == k_Gizmo ) + { + switch ( mGizmoProfile->mode ) + { + case MoveMode: + { + // Fetch Path Transform. + const MatrixF &mat = mSelection.Path->getTransform(); + + // Fetch the Path's Box Center. + const Point3F &pos = mSelection.Path->getWorldBox().getCenter(); + + // Move Gizmo. + mGizmo->set( mat, pos, Point3F( 1.0f, 1.0f, 1.0f ) ); + + // Render Gizmo. + mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix ); + + } break; + } + } + + // Render Path Segments. + renderPaths( k_RenderSegments ); + + // Set Clip Rect. + GFX->setClipRect( pUpdateRect ); + + // Render Path Nodes. + renderPaths( k_RenderNodes ); + + if ( isValidSelection() ) + { + // Fetch Current Node. + VPathNode *node = mSelection.Path->getNode( mSelection.Node ); + + // ToPoint Node? + if ( node->getOrientationMode().Type == VPathNode::k_OrientationToPoint ) + { + // Project to Screen. + Point3F screenPosition; + project( node->getOrientationMode().Point, &screenPosition ); + if ( screenPosition.z <= 1.0f ) + { + // Determine the center & size of the node rectangle. + Point2I nodeCenter = Point2I( screenPosition.x, screenPosition.y ); + Point2I nodeHalfSize = Point2I( 8, 8 ); + // Determine Render Rectangle. + RectI nodeRect; + nodeRect.point = nodeCenter - nodeHalfSize; + nodeRect.extent = ( 2 * nodeHalfSize ); + + // Draw? + if ( getBounds().overlaps( nodeRect ) ) + { + // Render the Point. + GFX->getDrawUtil()->drawRectFill( nodeRect, gNodeLookAtPointColor ); + } + } + } + } +} + +void VPathEditor::renderPaths( const RenderType &pRenderType ) +{ + SimSet *objectSet = VPath::getServerSet(); + for ( SimSetIterator itr( objectSet ); *itr; ++itr ) + { + VPath *path = dynamic_cast( *itr ); + if ( path ) + { + // Render Path. + renderPath( pRenderType, path, ( path == mSelection.Path ) ? gPathColorSel : gPathColor ); + } + } +} + +void VPathEditor::renderPath( const RenderType &pRenderType, VPath *pPath, const ColorI &pColor ) +{ + if ( !pPath ) + { + // Sanity! + return; + } + + switch ( pRenderType ) + { + case k_RenderSegments : + { + switch ( pPath->mPathType ) + { + case VPath::k_PathLinear : + { + renderLinearPath( pPath, pColor ); + + } break; + + case VPath::k_PathBezier : + { + renderBezierPath( pPath, pColor ); + + } break; + } + + } break; + + case k_RenderNodes : + { + // Fetch Draw Util. + GFXDrawUtil *drawUtil = GFX->getDrawUtil(); + + // Fetch Bounds. + RectI bounds = getBounds(); + + const Point2I nodeMinHalfSize( 8, 8 ); + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Node. + VPathNode *node = ( *itr ); + + // Project to Screen. + Point3F screenPosition; + project( node->getWorldPosition(), &screenPosition ); + if ( screenPosition.z > 1.0f ) + { + continue; + } + + // Determine the node text information. + const char *nodeText = avar( "%d", ( itr - pPath->mNodeList.begin() ) ); + const Point2I nodeTextHalfSize = Point2I( 0.5f * (F32)getControlProfile()->mFont->getStrWidth( nodeText ), + 0.5f * (F32)getControlProfile()->mFont->getHeight() ); + + // Determine the center & size of the node rectangle. + Point2I nodeCenter = Point2I( screenPosition.x, screenPosition.y ); + Point2I nodeHalfSize = Point2I( nodeTextHalfSize.x + 3, nodeTextHalfSize.y + 3 ); + nodeHalfSize.setMax( nodeMinHalfSize ); + // Determine Render Rectangle. + RectI nodeRect; + nodeRect.point = nodeCenter - nodeHalfSize; + nodeRect.extent = ( 2 * nodeHalfSize ); + + // Draw? + if ( !bounds.overlaps( nodeRect ) ) + { + continue; + } + + // Render the Point. + drawUtil->drawRectFill( nodeRect, pColor ); + + // Draw the node index text. + drawUtil->setBitmapModulation( getControlProfile()->mFontColor ); + drawUtil->drawText( getControlProfile()->mFont, nodeCenter - nodeTextHalfSize, nodeText ); + } + + } break; + } +} + +void VPathEditor::renderLinearPath( VPath *pPath, const ColorI &pColor ) +{ + if ( pPath->mNodeList.size() < 2 ) + { + // No Lines. + return; + } + + PrimBuild::color( pColor ); + PrimBuild::begin( GFXLineStrip, ( pPath->mNodeList.size() + 1 ) ); + + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Apply Vertex. + PrimBuild::vertex3fv( ( *itr )->getWorldPosition() ); + } + + // Loop Back. + PrimBuild::vertex3fv( pPath->mNodeList.front()->getWorldPosition() ); + + PrimBuild::end(); +} + +void VPathEditor::renderBezierPath( VPath *pPath, const ColorI &pColor ) +{ + if ( pPath->mNodeList.size() < 2 ) + { + // No Lines. + return; + } + + PrimBuild::color( pColor ); + PrimBuild::begin( GFXLineStrip, U32( ( ( 1.01f / 0.01f ) + 1 ) * pPath->mNodeList.size() ) ); + + for ( VPathNodeIterator itr = pPath->mNodeList.begin(); itr != pPath->mNodeList.end(); itr++ ) + { + // Fetch Nodes. + VPathNode *srcNode = ( *itr ); + VPathNode *dstNode = ( itr == ( pPath->mNodeList.end() - 1 ) ) ? ( *( pPath->mNodeList.begin() ) ) : ( *( itr + 1 ) ); + + // Positions. + const Point3F &pt0 = srcNode->getWorldPosition(); + const Point3F &pt3 = dstNode->getWorldPosition(); + + // Fetch Node Rotation Matrices. + MatrixF mat0, mat1; + srcNode->getWorldRotation().setMatrix( &mat0 ); + dstNode->getWorldRotation().setMatrix( &mat1 ); + + // Determine Tangent Axis. + Point3F pt1( VPath::gBezierAxis * srcNode->getWeight() ); + Point3F pt2( -VPath::gBezierAxis * dstNode->getWeight() ); + + // Rotate Axis. + mat0.mulP( pt1 ); + mat1.mulP( pt2 ); + + // Offset Points. + pt1 += pt0; + pt2 += pt3; + + for ( F32 t = 0.f, it = 1.f; t <= 1.f; t += 0.01f, it = ( 1.f - t ) ) + { + // Calculate Position. + Point3F pos = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); + // Apply Vertex. + PrimBuild::vertex3fv( pos ); + } + } + + PrimBuild::end(); +} + +//----------------------------------------------------------------------------- +// +// History Events +// +//----------------------------------------------------------------------------- + +void VPathEditor::VPathEditorEditPathAction::undo( void ) +{ + const MatrixF oldTransform = mTransform; + const MatrixF newTransform = mPath->getTransform(); + + // Apply Old Values. + mEditor->setPathTransform( oldTransform ); + + // The ol' Switcheroo. + mTransform = newTransform; + + // Update Selection. + mEditor->updateSelection(); + + if ( mPath == mEditor->mSelection.Path ) + { + // Arg Buffer. + char buffer[32]; + dSprintf( buffer, sizeof( buffer ), "%d", mPath->getId() ); + + // Callback. + Con::executef( mEditor, "onUpdatePath", buffer ); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorEditPathAction::redo( void ) +{ + // Undo. + undo(); +} + +void VPathEditor::VPathEditorEditNodeAction::undo( void ) +{ + // Fetch Properties. + const Point3F oldPosition = mNodePosition; + const QuatF oldRotation = mNodeRotation; + const F32 oldWeight = mNodeWeight; + const VPathNode::sOrientation oldOrientation = mNodeOrientation; + + VPathNode *node = mPath->getNode( mNodeIndex ); + const Point3F newPosition = node->getLocalPosition(); + const QuatF newRotation = node->getLocalRotation(); + const F32 newWeight = node->getWeight(); + const VPathNode::sOrientation newOrientation = node->getOrientationMode(); + + // Apply Old Values. + mPath->setNodePosition( mNodeIndex, oldPosition ); + mPath->setNodeRotation( mNodeIndex, oldRotation ); + mPath->setNodeWeight( mNodeIndex, oldWeight ); + + switch( oldOrientation.Type ) + { + case VPathNode::k_OrientationFree : + { + + // Orient Free. + mPath->setNodeOrientationMode( mNodeIndex, oldOrientation.Type ); + + } break; + + case VPathNode::k_OrientationToPoint : + { + + // Orient To Point. + mPath->setNodeOrientationMode( mNodeIndex, oldOrientation.Type, oldOrientation.Point ); + + } break; + } + + // The ol' Switcheroo. + mNodePosition = newPosition; + mNodeRotation = newRotation; + mNodeWeight = newWeight; + mNodeOrientation = newOrientation; + + // Update Selection. + mEditor->updateSelection(); + + if ( mPath == mEditor->mSelection.Path ) + { + // Arg Buffer. + char buffer[3][32]; + dSprintf( buffer[0], sizeof( buffer[0] ), "%d", mPath->getId() ); + dSprintf( buffer[1], sizeof( buffer[1] ), "%d", mNodeIndex ); + dSprintf( buffer[2], sizeof( buffer[2] ), "%d", ( mEditor->mSelection.Node == mNodeIndex ) ); + + // Callback. + Con::executef( mEditor, "onUpdateNode", buffer[0], buffer[1], buffer[2] ); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorEditNodeAction::redo( void ) +{ + // Undo. + undo(); +} + +void VPathEditor::VPathEditorAddNodeAction::undo( void ) +{ + // Selected Node? + if ( mNodeIndex == mEditor->mSelection.Node ) + { + // Update Selection. + mEditor->updateSelection( mEditor->mSelection.Path, -1 ); + } + + // Delete Node. + mPath->deleteNode( mNodeIndex ); + + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorAddNodeAction::redo( void ) +{ + // Add Node. + VPathNode *node = mPath->addNode( mNodePosition, mNodeRotation, mNodeWeight, mNodeIndex ); + + // Valid Node? + if ( node ) + { + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorDeleteNodeAction::undo( void ) +{ + // Add Node. + VPathNode *node = mPath->addNode( mNodePosition, mNodeRotation, mNodeWeight, mNodeIndex ); + + // Valid Node? + if ( node ) + { + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + } + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +void VPathEditor::VPathEditorDeleteNodeAction::redo( void ) +{ + // Delete Node. + mPath->deleteNode( mNodeIndex ); + + // Update Size. + mPath->updateContainer(); + + // Calculate Path. + mPath->calculatePath(); + + // Set World Editor Dirty. + mEditor->setWorldEditorDirty(); +} + +//----------------------------------------------------------------------------- +// +// Script Edit Methods +// +//----------------------------------------------------------------------------- + +DefineEngineMethod( VPathEditor, setNodePosition, void, (Point3F position), (Point3F::Zero), "( pPosition )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodePosition() - Invalid Node Selection." ); + return; + } + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodePosition( object->mSelection.Node, position ); + + // Create Undo Action. + object->popNodeEdit(); +} + +DefineEngineMethod( VPathEditor, setNodeRotation, void, (AngAxisF aa), (AngAxisF::AngAxisF()), "( pRotation )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeRotation() - Invalid Node Selection." ); + return; + } + + // Fetch Rotation. + QuatF rotation; + + // Set Rotation. + rotation.set( aa ); + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodeRotation( object->mSelection.Node, rotation ); + + // Create Undo Action. + object->popNodeEdit(); +} + +DefineEngineMethod( VPathEditor, setNodeWeight, void, (F32 weight), (1), "( pWeight )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeWeight() - Invalid Node Selection." ); + return; + } + + // Store. + object->pushNodeEdit(); + + // Apply Update. + object->setNodeWeight( object->mSelection.Node, weight); + + // Create Undo Action. + object->popNodeEdit(); +} + +DefineEngineMethod( VPathEditor, setNodeOrientationMode, void, (String orientationType, Point3F lookAtPoint), ("", Point3F::One), "( string pOrientationType, [vector pPoint] )" ) +{ + // Valid Selection? + if ( !object->isValidSelection() ) + { + Con::warnf( "VPathEditor::setNodeOrientationMode() - Invalid Node Selection." ); + return; + } + + // Store. + object->pushNodeEdit(); + + // Orient? + const VPathNode::eOrientationType type = VPathNode::getOrientationTypeEnum(orientationType); + + switch ( type ) + { + case VPathNode::k_OrientationFree : + { + + // Apply Mode. + object->setNodeOrientationMode( object->mSelection.Node, type ); + + } break; + + case VPathNode::k_OrientationToPoint: + { + // Apply Mode. + object->setNodeOrientationMode( object->mSelection.Node, type, lookAtPoint ); + } break; + } + + // Create Undo Action. + object->popNodeEdit(); +} + +//----------------------------------------------------------------------------- +// +// Utility +// +//----------------------------------------------------------------------------- + +bool Utility::FindNearestDistanceBetweenLines( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, Point3F *pOutA, Point3F *pOutB, F32 *pDist ) +{ + const Point3F pA1A0 = ( pA1 - pA0 ); + if ( pA1A0.isZero() ) + { + return false; + } + + const Point3F pB1B0 = ( pB1 - pB0 ); + if ( pB1B0.isZero() ) + { + return false; + } + + const Point3F pA0B0 = ( pA0 - pB0 ); + + const F32 &d1343 = pA0B0.x * pB1B0.x + pA0B0.y * pB1B0.y + pA0B0.z * pB1B0.z; + const F32 &d4321 = pB1B0.x * pA1A0.x + pB1B0.y * pA1A0.y + pB1B0.z * pA1A0.z; + const F32 &d1321 = pA0B0.x * pA1A0.x + pA0B0.y * pA1A0.y + pA0B0.z * pA1A0.z; + const F32 &d4343 = pB1B0.x * pB1B0.x + pB1B0.y * pB1B0.y + pB1B0.z * pB1B0.z; + const F32 &d2121 = pA1A0.x * pA1A0.x + pA1A0.y * pA1A0.y + pA1A0.z * pA1A0.z; + + const F32 &denom = d2121 * d4343 - d4321 * d4321; + if ( mIsZero( denom ) ) + { + return false; + } + + const F32 &mua = ( d1343 * d4321 - d1321 * d4343 ) / denom; + const F32 &mub = ( d1343 + d4321 * mua ) / d4343; + + *pOutA = pA0 + mua *pA1A0; + *pOutB = pB0 + mub *pB1B0; + + // Store Distance. + *pDist = ( ( *pOutA ) - ( *pOutB ) ).len(); + + return true; +} + +bool Utility::IntersectLineSegment( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, const bool pSnap, Point3F *pX ) +{ + // + // Finding the intersection with the following method: + // We have line a going from P1 to P2: + // Pa = P1 + ua( P2 - P1 ) + // and line b going from P3 to P4: + // Pb = P3 + ub( P4 - P3 ) + // + // Solving for Pa = Pb: + // x1 + ua( x2 - x1 ) = x3 + ub( x4 - x3 ) + // y1 + ua( y2 - y1 ) = y3 + ub( y4 - y3 ) + // + // Solving for ua and ub: + // ua = ( ( x4 - x3 )( y1 - y3 ) - ( y4 - y3 )( x1 - x3 ) ) / d + // ub = ( ( x2 - x1 )( y1 - y3 ) - ( y2 - y1 )( x1 - x3 ) ) / d + // denom = ( y4 - y3 )( x2 - x1 ) - ( x4 - x3 )( y2 - y1 ) + // + // x = x1 + ua( x2 - x1 ) + // y = y1 + ua( y2 - y1 ) + // + + const F32 d = ( ( pB1.y - pB0.y ) * ( pA1.x - pA0.x ) ) - ( ( pB1.x - pB0.x ) * ( pA1.y - pA0.y ) ); + + if ( d == 0.0f ) + { + // Lines are parallel + return false; + } + + // Find the point of intersection + const F32 uA = ( ( ( pB1.x - pB0.x ) * ( pA0.y - pB0.y ) ) - ( ( pB1.y - pB0.y ) * ( pA0.x - pB0.x ) ) ) / d; + const F32 uB = ( ( ( pA1.x - pA0.x ) * ( pA0.y - pB0.y ) ) - ( ( pA1.y - pA0.y ) * ( pA0.x - pB0.x ) ) ) / d; + + if ( !pSnap + && ( ( uA < 0.0f ) || ( uA > 1.0f ) + || ( uB < 0.0f ) || ( uB > 1.0f ) ) ) + { + return false; + } + + if ( pX ) + { + if ( uA < 0.0f ) + { + *pX = pA0; + } + else if ( uA > 1.f ) + { + *pX = pA1; + } + else + { + // The path intersects the segment + *pX = pA0 + uA * ( pA1 - pA0 ); + } + } + + return true; +} + +bool Utility::FindNearestPointOnLine( const Point3F &pSrcPosition, const Point3F &pA0, const Point3F &pA1, Point3F *pDstPosition ) +{ + const Point3F up( 0.0f, 0.0f, 1.0f ); + + Point3F dir = ( pA1 - pA0 ); + dir.normalize(); + + Point3F normal = mCross( dir, up ); + normal.normalize(); + + // Find the nearest intersection point between the point and the line + + const Point3F b0 = pSrcPosition + ( normal * 100000.0f ); + const Point3F b1 = pSrcPosition - ( normal * 100000.0f ); + + return IntersectLineSegment( pA0, pA1, b0, b1, true, pDstPosition ); +} + +F32 Utility::GetPitch( const VectorF &pVec ) +{ + F32 pitch; + if ( mFabs( pVec.x ) > mFabs( pVec.y ) ) + { + pitch = mAtan2( mFabs( pVec.z ), mFabs( pVec.x ) ); + } + else + { + pitch = mAtan2( mFabs( pVec.z ), mFabs( pVec.y ) ); + } + + if ( pVec.z < 0.f ) + { + pitch = -pitch; + } + + return pitch; +} + +F32 Utility::GetYaw( const VectorF &pVec ) +{ + F32 yaw = mAtan2( pVec.x, pVec.y ); + if ( yaw < 0.f ) + { + yaw += M_2PI_F; + } + + return yaw; +} diff --git a/Engine/source/Verve/VPath/VPathEditor.h b/Engine/source/Verve/VPath/VPathEditor.h new file mode 100644 index 000000000..c337edd0c --- /dev/null +++ b/Engine/source/Verve/VPath/VPathEditor.h @@ -0,0 +1,293 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHEDITOR_H_ +#define _VT_VPATHEDITOR_H_ + +#ifndef _EDITTSCTRL_H_ +#include "gui/worldEditor/editTSCtrl.h" +#endif + +#ifndef _VT_VPATH_H_ +#include "VPath.h" +#endif + +#ifndef _UNDO_H_ +#include "util/undo.h" +#endif + +//----------------------------------------------------------------------------- + +class VPathEditor : public EditTSCtrl +{ + typedef EditTSCtrl Parent; + +public: + + enum RenderType + { + k_RenderSegments, + k_RenderNodes, + }; + + enum EditMode + { + k_Gizmo, + k_AddNode, + k_DeleteNode + }; + + struct Selection + { + Selection( void ) : + Path( NULL ), + Node( -1 ) + { + TangentHandle[0].zero(); + TangentHandle[1].zero(); + }; + + VPath *Path; + S32 Node; + Point3F TangentHandle[2]; + }; + + struct PathEditAction + { + PathEditAction( void ) : + Dirty( false ), + Transform( true ) + { + // Void. + }; + + bool Dirty; + MatrixF Transform; + }; + + struct NodeEditAction + { + NodeEditAction( void ) : + Dirty( false ), + Position( 0.f, 0.f, 0.f ), + Rotation( 0.f, 0.f, 0.f, 0.f ), + Weight( 0.f ) + { + // Void. + }; + + bool Dirty; + Point3F Position; + QuatF Rotation; + F32 Weight; + }; + + bool mIsDirty; + EditMode mEditMode; + + Selection mSelection; + PathEditAction mPathEdit; + NodeEditAction mNodeEdit; + + bool mEditWeight; + S32 mEditWeightHandle; + + GFXStateBlockRef mStateBlock; + +public: + + VPathEditor( void ); + + virtual bool onAdd( void ); + virtual bool onWake( void ); + + static void initPersistFields( void ); + + // Gui Events. + + virtual void on3DMouseDown( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseUp( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseMove( const Gui3DMouseEvent &pEvent ); + virtual void on3DMouseDragged( const Gui3DMouseEvent &pEvent ); + + // Render Methods. + + virtual void setStateBlock( void ); + virtual void renderScene( const RectI &pUpdateRect ); + void renderPaths( const RenderType &pRenderType ); + + void renderPath( const RenderType &pRenderType, VPath *pPath, const ColorI &pColor ); + void renderLinearPath( VPath *pPath, const ColorI &pColor ); + void renderBezierPath( VPath *pPath, const ColorI &pColor ); + + DECLARE_CONOBJECT( VPathEditor ); + +public: + + // Reference Methods. + + VPath *getClientPath( VPath *pPath ); + + // Selection Methods. + + inline bool isValidSelection( void ) { return ( mSelection.Path != NULL && mSelection.Node != -1 ); }; + + bool updateSelection( const Gui3DMouseEvent &pEvent ); + void updateSelection( VPath *pPathObject, const S32 &pNodeIndex ); + void updateSelection( void ); + + // Weight Editing. + + bool isEditingWeight( const Gui3DMouseEvent &pEvent ); + inline bool isEditingWeight( void ) { return mEditWeight; }; + + void updateWeight( const Gui3DMouseEvent &pEvent ); + + // Path Editor. + + bool getPointOnPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + bool getPointOnLinearPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + bool getPointOnBezierPath( VPath *pPath, const Gui3DMouseEvent &pEvent, S32 &pNode, MatrixF &pTransform ); + + void setPathPosition( const Point3F &pPosition ); + void setPathRotation( const QuatF &pRotation ); + void setPathTransform( const MatrixF &pTransform ); + void setPathScale( const VectorF &pScale ); + + // Node Editing. + + void addNode( const Gui3DMouseEvent &pEvent ); + void deleteNode( const S32 &pNodeIndex ); + + void setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ); + void setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ); + void setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ); + void setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F &pPoint ); + + void pushPathEdit( void ); + void popPathEdit( void ); + + void pushNodeEdit( void ); + void popNodeEdit( void ); + + void setWorldEditorDirty( void ); + +private: + + class VPathEditorEditPathAction : public UndoAction + { + public: + + VPathEditorEditPathAction( const UTF8 *pName = "" ) : + UndoAction( pName ) + { + // Void. + }; + + VPathEditor *mEditor; + + VPath *mPath; + MatrixF mTransform; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorEditNodeAction : public UndoAction + { + public: + + VPathEditorEditNodeAction( const UTF8 *pName = "" ) : + UndoAction( pName ) + { + // Void. + }; + + VPathEditor *mEditor; + + VPath *mPath; + S32 mNodeIndex; + + Point3F mNodePosition; + QuatF mNodeRotation; + F32 mNodeWeight; + + VPathNode::sOrientation mNodeOrientation; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorAddNodeAction : public VPathEditorEditNodeAction + { + public: + + VPathEditorAddNodeAction( const UTF8 *pName = "" ) : + VPathEditorEditNodeAction( "Add Node" ) + { + // Void. + }; + + virtual void undo( void ); + virtual void redo( void ); + }; + + class VPathEditorDeleteNodeAction : public VPathEditorEditNodeAction + { + public: + + VPathEditorDeleteNodeAction( const UTF8 *pName = "" ) : + VPathEditorEditNodeAction( "Delete Node" ) + { + // Void. + }; + + virtual void undo( void ); + virtual void redo( void ); + }; +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathEditor::EditMode VPathEditorMode; + +// Declare Enum Types. +DefineEnumType( VPathEditorMode ); + +//----------------------------------------------------------------------------- + +namespace Utility +{ + bool FindNearestDistanceBetweenLines( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, Point3F *pOutA, Point3F *pOutB, F32 *pDist ); + + bool IntersectLineSegment( const Point3F &pA0, const Point3F &pA1, const Point3F &pB0, const Point3F &pB1, const bool pSnap, Point3F *pX ); + bool FindNearestPointOnLine( const Point3F &pSrcPosition, const Point3F &pA0, const Point3F &pA1, Point3F *pDstPosition ); + + F32 GetPitch( const VectorF &pVec ); + F32 GetYaw( const VectorF &pVec ); +}; + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHEDITOR_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPathNode.cpp b/Engine/source/Verve/VPath/VPathNode.cpp new file mode 100644 index 000000000..d18794c4e --- /dev/null +++ b/Engine/source/Verve/VPath/VPathNode.cpp @@ -0,0 +1,470 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathNode.h" +#include "VPath.h" + +#include "core/stream/bitStream.h" +#include "core/strings/stringUnit.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathNode::k_OrientationTypeSize ) ); + +//----------------------------------------------------------------------------- + +VPathNode::VPathNode( void ) : + mPath( NULL ), + mLocalPosition( Point3F( 0.f, 0.f, 0.f ) ), + mLocalRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), + mWorldPosition( Point3F( 0.f, 0.f, 0.f ) ), + mWorldRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), + mWeight( 10.f ), + mLength( 0.f ) +{ + // Init. + mOrientationMode.Type = k_OrientationFree; + mOrientationMode.Point = Point3F::Zero; + + // Set the initial mask. + mNetState.setMaskBits( k_StateInit ); + + VECTOR_SET_ASSOCIATION( mNetState ); +} + +VPathNode::~VPathNode( void ) +{ + mNetState.clear(); +} + +//----------------------------------------------------------------------------- +// +// Network Methods. +// +//----------------------------------------------------------------------------- + +U32 VPathNode::packNode( NetConnection *pConnection, BitStream *pStream ) +{ + // Init Return Mask. + U32 retMask = 0; + + // Fetch State. + VNetStateInfo *state = getState( pConnection ); + + // Note: This is out of sync with VPathNode::unpackUpdate(). + // If you're ever going to use these methods outside of VPath, you + // will need to read a flag *before* calling unpack! + + // Was the Node Created? + if ( pStream->writeFlag( state->Mask & k_StateCreate ) ) + { + // Clear Update. + state->Mask &= ~k_StateCreate; + } + + // Send mLocalPosition? + if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) + { + // Write mLocalPosition. + pStream->write( mLocalPosition.x ); + pStream->write( mLocalPosition.y ); + pStream->write( mLocalPosition.z ); + + // Clear Update. + state->Mask &= ~k_StateUpdatePosition; + } + + // Send mLocalRotation? + if ( pStream->writeFlag( state->Mask & k_StateUpdateRotation ) ) + { + // Write mLocalRotation. + pStream->write( mLocalRotation.x ); + pStream->write( mLocalRotation.y ); + pStream->write( mLocalRotation.z ); + pStream->write( mLocalRotation.w ); + + // Clear Update. + state->Mask &= ~k_StateUpdateRotation; + } + + // Send mWeight? + if ( pStream->writeFlag( state->Mask & k_StateUpdateWeight ) ) + { + // Write mWeight. + pStream->write( mWeight ); + + // Clear Update. + state->Mask &= ~k_StateUpdateWeight; + } + + // Send Orientation Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateOrientation ) ) + { + // Clear Update? + bool clearUpdate = true; + + // Write State. + pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToPoint : + { + // Write Point. + pStream->write( mOrientationMode.Point.x ); + pStream->write( mOrientationMode.Point.y ); + pStream->write( mOrientationMode.Point.z ); + + } break; + } + + if ( clearUpdate ) + { + // Clear Update. + state->Mask &= ~k_StateUpdateOrientation; + } + } + + // Return Mask. + return retMask; +} + +void VPathNode::unpackNode( NetConnection *pConnection, BitStream *pStream ) +{ + // Note: This is out of sync with VPathNode::packUpdate(). + // If you're ever going to use these methods outside of VPath, you + // will need to read a flag *before* calling unpack! + + // Update World Data. + bool updateWorld = false; + + // Update Local Position? + if ( pStream->readFlag() ) + { + // Read Local Position. + pStream->read( &mLocalPosition.x ); + pStream->read( &mLocalPosition.y ); + pStream->read( &mLocalPosition.z ); + + updateWorld = true; + } + + // Update Local Rotation? + if ( pStream->readFlag() ) + { + // Read Local Rotation. + pStream->read( &mLocalRotation.x ); + pStream->read( &mLocalRotation.y ); + pStream->read( &mLocalRotation.z ); + pStream->read( &mLocalRotation.w ); + + updateWorld = true; + } + + // Update Weight? + if ( pStream->readFlag() ) + { + // Read Weight. + pStream->read( &mWeight ); + } + + // Update Orientation? + if ( pStream->readFlag() ) + { + // Read Orientation Mode. + mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToPoint : + { + // Read Point. + pStream->read( &mOrientationMode.Point.x ); + pStream->read( &mOrientationMode.Point.y ); + pStream->read( &mOrientationMode.Point.z ); + + } break; + } + } + + if ( updateWorld ) + { + // Update World Position. + updateWorldData(); + } +} + +String VPathNode::toString( void ) +{ + String retBuffer; + + // Buffer Node Properties. + // {Position} {Rotation} {Weight} + const AngAxisF aa( mLocalRotation ); + retBuffer = String::ToString( "%f %f %f %f %f %f %f %f", mLocalPosition.x, mLocalPosition.y, mLocalPosition.z, + aa.axis.x, aa.axis.y, aa.axis.z, aa.angle, + mWeight ); + + // Add Tab. + retBuffer += "\t"; + + // Determine the Type. + StringTableEntry typeString = getOrientationTypeLabel( mOrientationMode.Type ); + switch( mOrientationMode.Type ) + { + case k_OrientationFree : + { + // Buffer String. + retBuffer += typeString; + + } break; + + case k_OrientationToPoint: + { + // Fetch Point. + const Point3F &lookAtPoint = mOrientationMode.Point; + + // Buffer String. + retBuffer += String::ToString( "%s %f %f %f", typeString, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); + + } break; + } + + // Return String. + return retBuffer; +} + +bool VPathNode::fromString( const String &pString ) +{ + // Split Data. + // {Position} {Rotation} {Weight} + const char *baseData = StringUnit::getUnit( pString.c_str(), 0, "\t" ); + + Point3F pos; + AngAxisF aa; + F32 weight; + + // Scan Base. + dSscanf( baseData, "%g %g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z, + &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle, + &weight ); + + // Apply Changes. + setLocalPosition( pos ); + setLocalRotation( QuatF( aa ) ); + setWeight( weight ); + + // Fetch Orientation Data. + String orientationData = StringUnit::getUnit( pString.c_str(), 1, "\t" ); + + // Fetch Orientation Type. + String orientationTypeString = orientationData; + if ( orientationData.find( " " ) ) + { + // Use First Word. + orientationTypeString = orientationData.substr( 0, orientationData.find( " " ) ); + } + + // Set Orientation Type. + const eOrientationType &orientationType = getOrientationTypeEnum( orientationTypeString.c_str() ); + switch( orientationType ) + { + case k_OrientationFree : + { + // Apply Mode. + setOrientationMode( orientationType ); + + } break; + + case k_OrientationToPoint: + { + // Fetch Point. + Point3F lookAtPoint; + // Buffer String. + dSscanf( orientationData.c_str(), "%*s %f %f %f", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); + + // Apply Mode. + setOrientationMode( orientationType, lookAtPoint ); + + } break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +Point3F VPathNode::getWorldPosition( void ) const +{ + return mWorldPosition; +} + +QuatF VPathNode::getWorldRotation( void ) const +{ + return mWorldRotation; +} + +MatrixF VPathNode::getWorldTransform( void ) const +{ + MatrixF mat; + getWorldRotation().setMatrix( &mat ); + mat.setPosition( getWorldPosition() ); + + return mat; +} + +void VPathNode::setLocalPosition( const Point3F &pPosition ) +{ + // Update? + if ( mLocalPosition != pPosition ) + { + // Apply. + mLocalPosition = pPosition; + + // Update World Position. + updateWorldData(); + + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathNode::setLocalRotation( const QuatF &pRotation ) +{ + // Update? + if ( mLocalRotation != pRotation ) + { + // Apply. + mLocalRotation = pRotation; + + // Update World Rotation. + updateWorldData(); + + // Flag Update. + setMaskBits( k_StateUpdateRotation ); + } +} + +void VPathNode::setWeight( const F32 &pWeight ) +{ + // Update? + if ( mWeight != pWeight ) + { + // Apply. + mWeight = pWeight; + + // Flag Update. + setMaskBits( k_StateUpdateWeight ); + } +} + +void VPathNode::setOrientationMode( const eOrientationType &pType ) +{ + // Update? + if ( mOrientationMode.Type != pType ) + { + // Update. + mOrientationMode.Type = pType; + + // Flag Update. + setMaskBits( k_StateUpdateOrientation ); + } +} + +void VPathNode::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) +{ + AssertFatal( pType == k_OrientationToPoint, "VPathNode::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Point = pPoint; + + // Flag Update. + setMaskBits( k_StateUpdateOrientation ); + } +} + +void VPathNode::updateWorldData( void ) +{ + if ( !mPath ) + { + setWorldPosition( getLocalPosition() ); + setWorldRotation( getLocalRotation() ); + return; + } + + // Fetch Path Details. + const MatrixF &pathTransform = mPath->getTransform(); + const QuatF &pathRotation( pathTransform ); + + // Calculate the World Position. + Point3F newPosition = getLocalPosition(); + newPosition.convolve( mPath->getScale() ); + pathTransform.mulP( newPosition ); + + // Calculate the new Rotation. + QuatF newRotation; + newRotation.mul( getLocalRotation(), pathRotation ); + + // Apply. + setWorldPosition( newPosition ); + setWorldRotation( newRotation ); +} + +//----------------------------------------------------------------------------- +// +// Enumeration Methods. +// +//----------------------------------------------------------------------------- + +// Implement the Orientation Type enum list. +ImplementEnumType( VPathNodeOrientationType,"" ) + { VPathNode::k_OrientationFree, "FREE" }, + { VPathNode::k_OrientationToPoint, "TOPOINT" }, +EndImplementEnumType; + +VPathNode::eOrientationType VPathNode::getOrientationTypeEnum( const char *pLabel ) +{ + VPathNode::eOrientationType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPathNode::k_OrientationFree; + } + + // Return. + return out; +} + +StringTableEntry VPathNode::getOrientationTypeLabel( const eOrientationType &pType ) +{ + // Return. + return castConsoleTypeToString( pType ); +} \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPathNode.h b/Engine/source/Verve/VPath/VPathNode.h new file mode 100644 index 000000000..dd829c5b5 --- /dev/null +++ b/Engine/source/Verve/VPath/VPathNode.h @@ -0,0 +1,172 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHNODE_H_ +#define _VT_VPATHNODE_H_ + +#ifndef _GAMEBASE_H_ +#include "T3D/gameBase/gameBase.h" +#endif + +#ifndef _VNETSTATE_H_ +#include "VNetState.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; +class VPathNode +{ +public: + + enum eState + { + k_StateUpdatePosition = BIT( 0 ), + k_StateUpdateRotation = BIT( 1 ), + k_StateUpdateWeight = BIT( 2 ), + + k_StateUpdateOrientation = BIT( 3 ), + + k_StateCreate = BIT( 4 ), + k_StateDelete = BIT( 5 ), + + k_StateUpdate = ( k_StateUpdatePosition | k_StateUpdateRotation | k_StateUpdateWeight | k_StateUpdateOrientation ), + + k_StateInit = ( k_StateCreate | k_StateUpdate ), + }; + + enum eOrientationType + { + k_OrientationFree, + k_OrientationToPoint, + + k_OrientationTypeSize, + }; + + struct sOrientation + { + eOrientationType Type; + + // k_OrientationToPoint + Point3F Point; + }; + +protected: + + VPath *mPath; + + VNetState mNetState; + + sOrientation mOrientationMode; + + Point3F mLocalPosition; + QuatF mLocalRotation; + + Point3F mWorldPosition; + QuatF mWorldRotation; + + F32 mWeight; + F32 mLength; + +public: + + VPathNode( void ); + virtual ~VPathNode( void ); + + // Serialisation Methods. + + virtual U32 packNode( NetConnection *pConnection, BitStream *pStream ); + virtual void unpackNode( NetConnection *pConnection, BitStream *pStream ); + + virtual String toString( void ); + virtual bool fromString( const String &pString ); + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline VPath *getPath( void ) const { return mPath; }; + + inline const Point3F &getLocalPosition( void ) const { return mLocalPosition; }; + inline const QuatF &getLocalRotation( void ) const { return mLocalRotation; }; + + virtual Point3F getWorldPosition( void ) const; + virtual QuatF getWorldRotation( void ) const; + virtual MatrixF getWorldTransform( void ) const; + + inline const F32 &getWeight( void ) const { return mWeight; }; + inline const F32 &getLength( void ) const { return mLength; }; + + inline const sOrientation &getOrientationMode( void ) const { return mOrientationMode; }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + inline void setPath( VPath *pPath ) { mPath = pPath; }; + + void setLocalPosition( const Point3F &pPosition ); + void setLocalRotation( const QuatF &pRotation ); + + inline void setWorldPosition( const Point3F &pPosition ) { mWorldPosition = pPosition; }; + inline void setWorldRotation( const QuatF &pRotation ) { mWorldRotation = pRotation; }; + + void setWeight( const F32 &pWeight ); + inline void setLength( const F32 &pLength ) { mLength = pLength; }; + + void setOrientationMode( const eOrientationType &pType ); + void setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ); + + void updateWorldData( void ); + + // Net State Methods. + + inline VNetStateInfo *getState( NetConnection *pConnection ) { return mNetState.getState( pConnection ); }; + + inline void setMaskBits( const U32 &pMask ) { mNetState.setMaskBits( pMask ); }; + inline void clearMaskBits( const U32 &pMask ) { mNetState.clearMaskBits( pMask ); }; + + inline bool isConnection( NetConnection *pConnection ) { return mNetState.isConnection( pConnection ); }; + inline void addConnection( NetConnection *pConnection ) { mNetState.addConnection( pConnection ); }; + inline void clearConnection( NetConnection *pConnection ) { mNetState.clearConnection( pConnection ); }; + + // Enum Methods. + + static eOrientationType getOrientationTypeEnum( const char *pLabel ); + static StringTableEntry getOrientationTypeLabel( const eOrientationType &pType ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathNode::eOrientationType VPathNodeOrientationType; + +// Declare Enum Types. +DefineEnumType( VPathNodeOrientationType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHNODE_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPathObject.cpp b/Engine/source/Verve/VPath/VPathObject.cpp new file mode 100644 index 000000000..5d1116b78 --- /dev/null +++ b/Engine/source/Verve/VPath/VPathObject.cpp @@ -0,0 +1,731 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "VPathObject.h" +#include "VPath.h" + +#include "core/stream/bitStream.h" +#include "sim/netConnection.h" + +//----------------------------------------------------------------------------- + +static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathObject::k_OrientationTypeSize ) ); + +//----------------------------------------------------------------------------- + +VPathObject::VPathObject( void ) : + mActive( false ), + mLastTime( 0 ), + mLastDelta( 0.f ), + mObject( NULL ), + mTimeInterp( 0.f ), + mPathInterp( 0.f ), + mPosition( 0.f, 0.f, 0.f ), + mOffset( 0.f, 0.f, 0.f ), + mOrientation( 0.f, 1.f, 0.f ), + mForward( true ), + mSpeed( 10.f ), + mSourceNode( 0 ), + mDestinationNode( 0 ), + mStartNode( 0 ), + mEndNode( 0 ) +{ + // Init. + mOrientationMode.Type = k_OrientationToPath; + mOrientationMode.Object = NULL; + mOrientationMode.Point = Point3F::Zero; + + // Set the initial mask. + mNetState.setMaskBits( k_StateInit ); + + // Reset Time. + resetTime(); + + // Reset Delta. + resetDelta(); + + VECTOR_SET_ASSOCIATION( mNetState ); +} + +VPathObject::~VPathObject( void ) +{ + // Void. +} + +//----------------------------------------------------------------------------- +// +// Network Methods. +// +//----------------------------------------------------------------------------- + +U32 VPathObject::packUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Init Return Mask. + U32 retMask = 0; + + // Fetch State. + VNetStateInfo *state = getState( pConnection ); + + // Write Active. + pStream->writeFlag( mActive ); + + // Send Object Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateObject ) ) + { + // Successful Send? + bool success = false; + + // Valid Object? + if ( !mObject ) + { + // No Object. + pStream->writeFlag( false ); + } + else + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mObject ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + // Write Ghost Id. + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + + // Success! + success = true; + // Clear Update. + state->Mask &= ~k_StateUpdateObject; + } + } + + if ( !success ) + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Send Mount Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateMount ) ) + { + // Successful Send? + bool success = false; + + // Valid Objects? + if ( !mObject || !mObject->getObjectMount() || ( state->Mask & k_StateUpdateObject ) ) + { + // No Object. + pStream->writeFlag( false ); + } + else + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mObject->getObjectMount() ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + // Write Ghost Id. + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + // Write Mount Node. + pStream->writeInt( mObject->getMountNode(), SceneObject::NumMountPointBits ); + + // Success! + success = true; + // Clear Update. + state->Mask &= ~k_StateUpdateMount; + } + } + + if ( !success ) + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Send Position Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) + { + // Write Position. + pStream->write( mTimeInterp ); + pStream->write( mPathInterp ); + + pStream->write( mPosition.x ); + pStream->write( mPosition.y ); + pStream->write( mPosition.z ); + + pStream->write( mOrientation.x ); + pStream->write( mOrientation.y ); + pStream->write( mOrientation.z ); + + pStream->writeInt( mSourceNode, VPath::gMaxNodeBits ); + pStream->writeInt( mDestinationNode, VPath::gMaxNodeBits ); + + // Clear Update. + state->Mask &= ~k_StateUpdatePosition; + } + + // Send State Update? + if ( pStream->writeFlag( state->Mask & k_StateUpdateState ) ) + { + // Successful Send? + bool success = true; + + // Write State. + pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case k_OrientationToObject : + { + // Write Ghost Index. + const S32 ghostIndex = pConnection->getGhostIndex( mOrientationMode.Object ); + if ( pStream->writeFlag( ghostIndex != -1 ) ) + { + pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); + } + else + { + // Failed. + success = false; + } + + } break; + + case k_OrientationToPoint : + { + // Write Point. + pStream->write( mOrientationMode.Point.x ); + pStream->write( mOrientationMode.Point.y ); + pStream->write( mOrientationMode.Point.z ); + + } break; + } + + pStream->writeFlag( mForward ); + pStream->write( mSpeed ); + + // Write Offset. + pStream->write( mOffset.x ); + pStream->write( mOffset.y ); + pStream->write( mOffset.z ); + + pStream->writeInt( mStartNode, VPath::gMaxNodeBits ); + pStream->writeInt( mEndNode, VPath::gMaxNodeBits ); + + if ( success ) + { + // Clear Update. + state->Mask &= ~k_StateUpdateState; + } + else + { + // Try Again Later. + retMask |= VPath::ObjectUpdateMask; + } + } + + // Return Mask. + return retMask; +} + +void VPathObject::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) +{ + // Read Active. + setActive( pStream->readFlag() ); + + // Update Object? + if ( pStream->readFlag() ) + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + + // Resolve Object. + setObject( static_cast( pConnection->resolveGhost( ghostIndex ) ) ); + + // Reset Delta. + resetDelta(); + } + else + { + // Clear Object. + mObject = NULL; + } + } + + // Update Mount? + if ( pStream->readFlag() ) + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + // Read Mount Node. + const S32 nodeIndex = pStream->readInt( SceneObject::NumMountPointBits ); + + // Resolve Object. + SceneObject *mountObject = static_cast( pConnection->resolveGhost( ghostIndex ) ); + // Mount Object. + mountObject->mountObject( mObject, nodeIndex ); + } + else + { + // ... unmount? + } + } + + // Update Position? + if ( pStream->readFlag() ) + { + // Read Updates. + pStream->read( &mTimeInterp ); + pStream->read( &mPathInterp ); + + pStream->read( &mPosition.x ); + pStream->read( &mPosition.y ); + pStream->read( &mPosition.z ); + + pStream->read( &mOrientation.x ); + pStream->read( &mOrientation.y ); + pStream->read( &mOrientation.z ); + + mSourceNode = pStream->readInt( VPath::gMaxNodeBits ); + mDestinationNode = pStream->readInt( VPath::gMaxNodeBits ); + } + + // Update Heading? + if ( pStream->readFlag() ) + { + // Read Orientation Mode. + mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); + + switch ( mOrientationMode.Type ) + { + case VPathObject::k_OrientationToObject : + { + if ( pStream->readFlag() ) + { + // Read Ghost Index. + const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); + // Resolve Object. + mOrientationMode.Object = static_cast( pConnection->resolveGhost( ghostIndex ) ); + } + + } break; + + case VPathObject::k_OrientationToPoint : + { + // Read Point. + pStream->read( &mOrientationMode.Point.x ); + pStream->read( &mOrientationMode.Point.y ); + pStream->read( &mOrientationMode.Point.z ); + + } break; + } + + // Read Updates. + mForward = pStream->readFlag(); + + pStream->read( &mSpeed ); + + pStream->read( &mOffset.x ); + pStream->read( &mOffset.y ); + pStream->read( &mOffset.z ); + + mStartNode = pStream->readInt( VPath::gMaxNodeBits ); + mEndNode = pStream->readInt( VPath::gMaxNodeBits ); + } +} + +//----------------------------------------------------------------------------- +// +// Property Methods. +// +//----------------------------------------------------------------------------- + +Point3F VPathObject::getWorldPosition( void ) +{ + return ( mPosition + mOffset ); +} + +Point3F VPathObject::getRenderWorldPosition( const F32 &pDelta ) +{ + return ( getPositionDelta( pDelta ) + mOffset ); +} + +MatrixF VPathObject::getTransform( void ) +{ + MatrixF mat( true ); + switch ( mOrientationMode.Type ) + { + case k_OrientationInterpolate : + case k_OrientationToObject : + case k_OrientationToPoint : + case k_OrientationToPath : + { + // Y-Axis. + VectorF yVec = mOrientation; + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + mat.setColumn( 3, getWorldPosition() ); + + } break; + + case k_OrientationFree : + { + // Fetch Current Transform. + mat = mObject->getTransform(); + mat.setPosition( getWorldPosition() ); + + } break; + } + + // Return. + return mat; +} + +MatrixF VPathObject::getRenderTransform( const F32 &pDelta ) +{ + MatrixF mat( true ); + switch ( mOrientationMode.Type ) + { + case k_OrientationInterpolate : + case k_OrientationToObject : + case k_OrientationToPoint : + case k_OrientationToPath : + { + // Y-Axis. + VectorF yVec = getOrientationDelta( pDelta ); + yVec.normalize(); + + // X-Axis. + VectorF xVec = mCross( yVec, VPath::gBezierUp ); + xVec.normalize(); + + // Z-Axis. + VectorF zVec = mCross( xVec, yVec ); + zVec.normalize(); + + // Setup Object Transform. + mat.setColumn( 0, xVec ); + mat.setColumn( 1, yVec ); + mat.setColumn( 2, zVec ); + mat.setColumn( 3, getRenderWorldPosition( pDelta ) ); + + } break; + + case k_OrientationFree : + { + // Fetch Current Transform. + mat = mObject->getRenderTransform(); + mat.setPosition( getRenderWorldPosition( pDelta ) ); + + } break; + } + + // Return. + return mat; +} + +void VPathObject::setActive( const bool &pActive ) +{ + // Update? + if ( pActive != mActive ) + { + // Apply. + mActive = pActive; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setObject( SceneObject *pObject ) +{ + // Update? + if ( pObject != mObject ) + { + // Apply. + mObject = pObject; + // Flag Update. + setMaskBits( k_StateUpdateObject ); + } +} + +void VPathObject::setTimeInterp( const F32 &pInterp ) +{ + // Update? + if ( mTimeInterp != pInterp ) + { + // Apply. + mTimeInterp = pInterp; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setPathInterp( const F32 &pInterp ) +{ + // Update? + if ( mPathInterp != pInterp ) + { + // Apply. + mPathInterp = pInterp; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setPosition( const Point3F &pPosition ) +{ + // Update? + if ( mPosition != pPosition ) + { + // Update. + mPosition = pPosition; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setOffset( const Point3F &pOffset ) +{ + // Update? + if ( mOffset != pOffset ) + { + // Update. + mOffset = pOffset; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientation( const VectorF &pOrientation ) +{ + // Update? + if ( mOrientation != pOrientation ) + { + // Update. + mOrientation = pOrientation; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType ) +{ + // Update? + if ( mOrientationMode.Type != pType ) + { + // Update. + mOrientationMode.Type = pType; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType, SceneObject *pObject ) +{ + AssertFatal( ( pType == k_OrientationToObject ) && ( pObject != NULL ), "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Object != pObject ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Object = pObject; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) +{ + AssertFatal( pType == k_OrientationToPoint, "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); + + // Update? + if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) + { + // Update. + mOrientationMode.Type = pType; + mOrientationMode.Point = pPoint; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setForward( const bool &pForward ) +{ + // Update? + if ( mForward != pForward ) + { + // Update. + mForward = pForward; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setSpeed( const F32 &pSpeed ) +{ + // Update? + if ( mSpeed != pSpeed ) + { + // Update. + mSpeed = pSpeed; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setNode( const S32 &pSourceNodeIndex, const S32 &pDestinationNodeIndex ) +{ + // Update? + if ( ( mSourceNode != pSourceNodeIndex ) || ( mDestinationNode != pDestinationNodeIndex ) ) + { + // Update. + mSourceNode = pSourceNodeIndex; + mDestinationNode = pDestinationNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdatePosition ); + } +} + +void VPathObject::setStartNode( const S32 &pNodeIndex ) +{ + // Update? + if ( mStartNode != pNodeIndex ) + { + // Update. + mStartNode = pNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +void VPathObject::setEndNode( const S32 &pNodeIndex ) +{ + // Update? + if ( mEndNode != pNodeIndex ) + { + // Update. + mEndNode = pNodeIndex; + // Flag Update. + setMaskBits( k_StateUpdateState ); + } +} + +//----------------------------------------------------------------------------- +// +// Delta Methods. +// +//----------------------------------------------------------------------------- + +void VPathObject::resetDelta( void ) +{ + mDelta.Position[0] = mPosition; + mDelta.Position[1] = mPosition; + mDelta.Orientation[0] = mOrientation; + mDelta.Orientation[1] = mOrientation; +} + +void VPathObject::resetDelta( const Point3F &pPosition, const VectorF &pOrientation ) +{ + mDelta.Position[0] = pPosition; + mDelta.Position[1] = pPosition; + mDelta.Orientation[0] = pOrientation; + mDelta.Orientation[1] = pOrientation; +} + +void VPathObject::popDelta( void ) +{ + mDelta.Position[0] = mDelta.Position[1]; + mDelta.Orientation[0] = mDelta.Orientation[1]; +} + +void VPathObject::pushDelta( const Point3F &pPosition, const VectorF &pOrientation ) +{ + mDelta.Position[1] = pPosition; + mDelta.Orientation[1] = pOrientation; +} + +Point3F VPathObject::getPositionDelta( const F32 &pInterp ) +{ + Point3F interpPosition; + interpPosition.interpolate( mDelta.Position[1], mDelta.Position[0], pInterp ); + + return interpPosition; +} + +VectorF VPathObject::getOrientationDelta( const F32 &pInterp ) +{ + VectorF interpOrientation; + interpOrientation.interpolate( mDelta.Orientation[1], mDelta.Orientation[0], pInterp ); + interpOrientation.normalize(); + + return interpOrientation; +} + +//----------------------------------------------------------------------------- +// +// Enumeration Methods. +// +//----------------------------------------------------------------------------- + +// Implement the Orientation Type enum list. +ImplementEnumType( VPathObjectOrientationType, "" ) + { VPathObject::k_OrientationFree, "FREE" }, + { VPathObject::k_OrientationInterpolate, "INTERPOLATE" }, + { VPathObject::k_OrientationToPath, "TOPATH" }, + { VPathObject::k_OrientationToObject, "TOOBJECT" }, + { VPathObject::k_OrientationToPoint, "TOPOINT" }, +EndImplementEnumType; + +VPathObject::eOrientationType VPathObject::getOrientationTypeEnum( const char *pLabel ) +{ + VPathObject::eOrientationType out; + if ( !castConsoleTypeFromString( out, pLabel ) ) + { + // Bah! + return VPathObject::k_OrientationFree; + } + + // Return. + return out; +} + +StringTableEntry VPathObject::getOrientationTypeLabel( const eOrientationType &pType ) +{ + // Return. + return castConsoleTypeToString( pType ); +} \ No newline at end of file diff --git a/Engine/source/Verve/VPath/VPathObject.h b/Engine/source/Verve/VPath/VPathObject.h new file mode 100644 index 000000000..72153021d --- /dev/null +++ b/Engine/source/Verve/VPath/VPathObject.h @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VPATHOBJECT_H_ +#define _VT_VPATHOBJECT_H_ + +#ifndef _GAMEBASE_H_ +#include "T3D/gameBase/gameBase.h" +#endif + +#ifndef _VNETSTATE_H_ +#include "VNetState.h" +#endif + +#ifndef _MOVEMANAGER_H_ +#include "T3D/gameBase/moveManager.h" +#endif + +//----------------------------------------------------------------------------- + +class VPath; +class NetConnection; + +struct VPathObject +{ +public: + + enum eState + { + k_StateUpdateObject = BIT( 0 ), + k_StateUpdateMount = BIT( 1 ), + k_StateUpdatePosition = BIT( 2 ), + k_StateUpdateState = BIT( 3 ), + + k_StateAttach = BIT( 4 ), + k_StateDetach = BIT( 5 ), + + k_StateUpdate = ( k_StateUpdateObject | k_StateUpdateMount | k_StateUpdatePosition | k_StateUpdateState ), + + k_StateInit = ( k_StateAttach | k_StateUpdate ), + }; + + enum eOrientationType + { + k_OrientationFree, + k_OrientationInterpolate, + + k_OrientationToPath, + k_OrientationToObject, + k_OrientationToPoint, + + k_OrientationTypeSize, + }; + + struct sOrientation + { + eOrientationType Type; + + // k_OrientationToObject + SceneObject *Object; + // k_OrientationToPoint + Point3F Point; + }; + + struct sDelta + { + Point3F Position[2]; + VectorF Orientation[2]; + }; + +protected: + + bool mActive; + + U32 mLastTime; + F32 mLastDelta; + + SceneObject *mObject; + + VNetState mNetState; + sDelta mDelta; + + F32 mTimeInterp; + F32 mPathInterp; + Point3F mPosition; + Point3F mOffset; + sOrientation mOrientationMode; + VectorF mOrientation; + bool mForward; + F32 mSpeed; + + S32 mSourceNode; + S32 mDestinationNode; + + S32 mStartNode; + S32 mEndNode; + +public: + + VPathObject( void ); + ~VPathObject( void ); + + // Network Methods. + + U32 packUpdate( NetConnection *pConnection, BitStream *pStream ); + void unpackUpdate( NetConnection *pConnection, BitStream *pStream ); + + //------------------------------------------------------------------------- + // + // Gets + // + //------------------------------------------------------------------------- + + inline const bool &isActive( void ) { return mActive; }; + + inline SceneObject *getObject( void ) { return mObject; }; + + inline const F32 &getTimeInterp( void ) { return mTimeInterp; }; + inline const F32 &getPathInterp( void ) { return mPathInterp; }; + inline const Point3F &getPosition( void ) { return mPosition; }; + inline const Point3F &getOffset( void ) { return mOffset; }; + inline const VectorF &getOrientation( void ) { return mOrientation; }; + inline const sOrientation &getOrientationMode( void ) { return mOrientationMode; }; + + inline const bool &isForward( void ) { return mForward; }; + inline const F32 &getSpeed( void ) { return mSpeed; }; + + inline const S32 &getSourceNode( void ) { return mSourceNode; }; + inline const S32 &getDestinationNode( void ) { return mDestinationNode; }; + inline const S32 &getStartNode( void ) { return mStartNode; }; + inline const S32 &getEndNode( void ) { return mEndNode; }; + + Point3F getWorldPosition( void ); + Point3F getRenderWorldPosition( const F32 &pDelta ); + + MatrixF getTransform( void ); + MatrixF getRenderTransform( const F32 &pDelta ); + + inline F32 getTimeDelta( const bool &pUpdate = true ) + { + if ( !pUpdate ) + { + return mLastDelta; + } + + // Calculate Delta. + const S32 time = Sim::getCurrentTime(); + const F32 delta = ( time - mLastTime ) / 1000.f; + + // Store Time. + mLastTime = time; + mLastDelta = delta; + + // Return Delta. + return delta; + }; + + inline void resetTime( void ) + { + mLastTime = Sim::getCurrentTime(); + }; + + //------------------------------------------------------------------------- + // + // Sets + // + //------------------------------------------------------------------------- + + void setActive( const bool &pActive ); + + void setObject( SceneObject *pObject ); + + void setTimeInterp( const F32 &pInterp ); + void setPathInterp( const F32 &pInterp ); + void setPosition( const Point3F &pPosition ); + void setOffset( const Point3F &pOffset ); + void setOrientation( const VectorF &pOrientation ); + void setOrientationMode( const eOrientationType &pType ); + void setOrientationMode( const eOrientationType &pType, SceneObject *pObject ); + void setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ); + + void setForward( const bool &pForward ); + void setSpeed( const F32 &pSpeed ); + + void setNode( const S32 &pSourceNodeIndex, const S32 &pDestinationNodeIndex ); + void setStartNode( const S32 &pNodeIndex ); + void setEndNode( const S32 &pNodeIndex ); + + // Delta Methods. + + void resetDelta( void ); + void resetDelta( const Point3F &pPosition, const VectorF &pOrientation ); + + void popDelta( void ); + void pushDelta( const Point3F &pPosition, const VectorF &pOrientation ); + + Point3F getPositionDelta( const F32 &pInterp ); + VectorF getOrientationDelta( const F32 &pInterp ); + + // Net State Methods. + + inline VNetStateInfo *getState( NetConnection *pConnection ) { return mNetState.getState( pConnection ); }; + + inline void setMaskBits( const U32 &pMask ) { mNetState.setMaskBits( pMask ); }; + inline void clearMaskBits( const U32 &pMask ) { mNetState.clearMaskBits( pMask ); }; + + inline bool isConnection( NetConnection *pConnection ) { return mNetState.isConnection( pConnection ); }; + inline void addConnection( NetConnection *pConnection ) { mNetState.addConnection( pConnection ); }; + inline void clearConnection( NetConnection *pConnection ) { mNetState.clearConnection( pConnection ); }; + + // Enum Methods. + + static eOrientationType getOrientationTypeEnum( const char *pLabel ); + static StringTableEntry getOrientationTypeLabel( const eOrientationType &pType ); +}; + +//----------------------------------------------------------------------------- + +// Define Types. +typedef VPathObject::eOrientationType VPathObjectOrientationType; + +// Declare Enum Types. +DefineEnumType( VPathObjectOrientationType ); + +//----------------------------------------------------------------------------- + +#endif // _VT_VPATHOBJECT_H_ \ No newline at end of file diff --git a/Engine/source/Verve/VerveConfig.h b/Engine/source/Verve/VerveConfig.h new file mode 100644 index 000000000..deaf8f831 --- /dev/null +++ b/Engine/source/Verve/VerveConfig.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _VT_VERVECONFIG_H_ +#define _VT_VERVECONFIG_H_ + +//----------------------------------------------------------------------------- + +//#define VT_EDITOR + +//----------------------------------------------------------------------------- + +#endif // _VT_VERVECONFIG_H_ \ No newline at end of file diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 447d96ce4..285c6c89a 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -2841,6 +2841,10 @@ DefineEngineMethod( SimObject, getFieldValue, const char*, ( const char* fieldNa const char* arrayIndex = NULL; const U32 nameLen = dStrlen( fieldName ); + + if (nameLen == 0) + return ""; + if( fieldName[ nameLen - 1 ] == ']' ) { const char* leftBracket = dStrchr( fieldName, '[' ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index 2be8d2a15..56e869032 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -825,10 +825,10 @@ void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp) // Now re aquire all the resources we trashed earlier reacquireDefaultPoolResources(); //set last bound shaders - mD3DDeviceContext->PSSetShader(mLastPixShader, NULL, 0); - mD3DDeviceContext->VSSetShader(mLastVertShader, NULL, 0); + //mD3DDeviceContext->PSSetShader(mLastPixShader, NULL, 0); + //mD3DDeviceContext->VSSetShader(mLastVertShader, NULL, 0); // Mark everything dirty and flush to card, for sanity. - updateStates(true); + //updateStates(true); } void GFXD3D11Device::setupGenericShaders(GenericShaderType type) @@ -1865,4 +1865,4 @@ void GFXD3D11Device::setDebugMarker(ColorI color, const char *name) MultiByteToWideChar(CP_ACP, 0, name, -1, eventName, 260); mUserAnnotation->SetMarker(eventName); } -} \ No newline at end of file +} diff --git a/Templates/BaseGame/game/data/Verve/Verve.cs b/Templates/BaseGame/game/data/Verve/Verve.cs new file mode 100644 index 000000000..61b8b4ab6 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/Verve.cs @@ -0,0 +1,19 @@ +function Verve::create( %this ) +{ + exec("data/Verve/gui/verveCinematic.gui"); + + exec("data/Verve/scripts/server/verveCinematicController.cs"); + exec("data/Verve/scripts/server/verveCinematicTrigger.cs"); + exec("data/Verve/scripts/server/vervePathTutorialData.cs"); + + if(isObject(DatablockFilesList)) + { + DatablockFilesList.add( "data/Verve/scripts/datablocks/verve/VerveActorData.cs" ); + DatablockFilesList.add( "data/Verve/scripts/datablocks/verve/VervePathTutorialData.cs" ); + } +} + +function Verve::destroy( %this ) +{ + +} \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/Verve.module b/Templates/BaseGame/game/data/Verve/Verve.module new file mode 100644 index 000000000..00e86707c --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/Verve.module @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/BLACK.png b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/BLACK.png new file mode 100644 index 0000000000000000000000000000000000000000..7ed2ea55ad9a774b72eb2363dfc8a15dfecc4dde GIT binary patch literal 2824 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 + + + + + Torque 3D 2009 Interior Exporter + + + 8/09/2009 2:52:45 PM + 8/09/2009 2:52:45 PM + + + <subject /> + <keywords /> + <unit meter="1.000000" /> + <up_axis>Z_UP</up_axis> + </asset> + <library_images> + <image id="BLACK-Diffuse" name="BLACK-Diffuse"> + <init_from>file://BLACK.png</init_from> + </image> + <image id="FULL128X128G-Diffuse" name="FULL128X128G-Diffuse"> + <init_from>file://FULL128X128G.png</init_from> + </image> + <image id="PILLAR128X128G-Diffuse" name="PILLAR128X128G-Diffuse"> + <init_from>file://PILLAR128X128G.png</init_from> + </image> + <image id="FULL64X64G-Diffuse" name="FULL64X64G-Diffuse"> + <init_from>file://FULL64X64G.png</init_from> + </image> + </library_images> + <library_materials> + <material id="BLACK" name="BLACK"> + <instance_effect url="#BLACK-fx" /> + </material> + <material id="FULL128X128G" name="FULL128X128G"> + <instance_effect url="#FULL128X128G-fx" /> + </material> + <material id="PILLAR128X128G" name="PILLAR128X128G"> + <instance_effect url="#PILLAR128X128G-fx" /> + </material> + <material id="FULL64X64G" name="FULL64X64G"> + <instance_effect url="#FULL64X64G-fx" /> + </material> + </library_materials> + <library_effects> + <effect id="BLACK-fx" name="BLACK-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="BLACK-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="FULL128X128G-fx" name="FULL128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="FULL128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="PILLAR128X128G-fx" name="PILLAR128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="PILLAR128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="FULL64X64G-fx" name="FULL64X64G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="FULL64X64G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + </library_effects> + <library_geometries> + <geometry id="DemoRoomLrg_5c1b8cbb-lib" name="DemoRoomLrg_5c1b8cbbMesh"> + <mesh> + <source id="DemoRoomLrg_5c1b8cbb-Position"> + <float_array id="DemoRoomLrg_5c1b8cbb-Position-array" count="1014"> + -10.5000 10.5000 -0.5000 + -10.5000 10.5000 4.5000 + -10.5000 -10.5000 -0.5000 + -10.5000 -10.5000 4.5000 + -10.0000 10.5000 -0.5000 + -10.0000 10.5000 4.5000 + -10.0000 -10.5000 4.5000 + -10.0000 -10.5000 -0.5000 + -10.0000 10.0000 4.0000 + -10.0000 10.0000 -0.0000 + -10.0000 -10.0000 4.0000 + -10.0000 -10.0000 0.0000 + 10.0000 -10.5000 4.5000 + 10.0000 -10.5000 -0.5000 + 10.0000 -10.0000 4.5000 + -10.0000 -10.0000 4.5000 + -10.0000 -10.0000 -0.5000 + 10.0000 -10.0000 -0.5000 + 10.0000 -10.0000 0.0000 + 10.0000 -10.0000 4.0000 + 10.0000 10.0000 4.5000 + -10.0000 10.0000 4.5000 + 4.5000 -10.0000 4.0000 + 4.5000 10.0000 4.0000 + 10.0000 10.0000 4.0000 + 3.5000 4.5000 4.0000 + -3.5000 4.5000 4.0000 + 3.5000 3.5000 4.0000 + -3.5000 3.5000 4.0000 + 3.5000 -3.5000 4.0000 + -3.5000 -3.5000 4.0000 + 3.5000 -4.5000 4.0000 + -3.5000 -4.5000 4.0000 + -4.5000 10.0000 4.0000 + -4.5000 -10.0000 4.0000 + 4.5000 4.5000 4.0000 + -4.5000 4.5000 4.0000 + 4.5000 -3.5000 4.0000 + 4.5000 3.5000 4.0000 + -4.5000 -3.5000 4.0000 + -4.5000 3.5000 4.0000 + 4.5000 -4.5000 4.0000 + -4.5000 -4.5000 4.0000 + 10.0000 10.0000 -0.5000 + -10.0000 10.0000 -0.5000 + 4.5000 10.0000 0.0000 + 10.0000 10.0000 0.0000 + 4.5000 -10.0000 0.0000 + 3.5000 3.5000 0.0000 + -3.5000 3.5000 0.0000 + 3.5000 4.5000 0.0000 + -3.5000 4.5000 0.0000 + 3.5000 -4.5000 0.0000 + -3.5000 -4.5000 0.0000 + 3.5000 -3.5000 0.0000 + -3.5000 -3.5000 0.0000 + -4.5000 10.0000 0.0000 + -4.5000 -10.0000 0.0000 + 4.5000 4.5000 0.0000 + -4.5000 4.5000 0.0000 + 4.5000 3.5000 0.0000 + 4.5000 -3.5000 0.0000 + -4.5000 3.5000 0.0000 + -4.5000 -3.5000 0.0000 + 4.5000 -4.5000 0.0000 + -4.5000 -4.5000 0.0000 + 10.5000 10.5000 4.5000 + 10.5000 10.5000 -0.5000 + 10.5000 -10.0000 4.5000 + 10.5000 -10.5000 -0.5000 + 10.5000 -10.5000 4.5000 + 10.0000 10.5000 4.5000 + 10.5000 10.0000 4.5000 + 10.0000 10.5000 -0.5000 + -6.0000 10.5000 -0.5000 + -6.0000 10.5000 4.5000 + -6.0000 10.0000 4.5000 + -6.0000 10.0000 -0.5000 + -6.0000 10.0000 -0.0000 + -6.0000 10.0000 4.0000 + 6.0000 10.5000 -0.5000 + 6.0000 10.5000 4.5000 + 6.0000 10.0000 4.5000 + 6.0000 10.0000 -0.5000 + 6.0000 10.0000 0.0000 + 6.0000 10.0000 4.0000 + -2.0000 18.0000 0.0000 + 2.0000 18.0000 0.0000 + -2.0000 10.0000 0.0000 + 2.0000 10.0000 0.0000 + 2.0000 18.0000 -0.5000 + -2.0000 18.0000 -0.5000 + 2.0000 10.0000 -0.5000 + -2.0000 10.0000 -0.5000 + -4.5000 20.5000 -0.5000 + -4.5000 20.5000 4.5000 + -4.5000 10.5000 -0.5000 + -4.5000 10.5000 4.5000 + -4.0000 20.5000 -0.5000 + -4.0000 20.5000 4.5000 + -4.0000 10.0000 4.0000 + -4.0000 10.0000 -0.0000 + -4.5000 10.0000 4.5000 + -4.0000 10.0000 4.5000 + -4.0000 10.0000 -0.5000 + -4.5000 10.0000 -0.5000 + -4.0000 20.0000 4.0000 + -4.0000 20.0000 0.0000 + 4.0000 20.0000 -0.0000 + 4.0000 20.0000 4.0000 + 4.0000 10.0000 0.0000 + 4.0000 10.0000 4.0000 + 4.0000 20.5000 -0.5000 + 4.5000 20.5000 -0.5000 + 4.0000 20.5000 4.5000 + 4.5000 20.5000 4.5000 + 4.0000 10.0000 4.5000 + 4.5000 10.0000 4.5000 + 4.5000 10.0000 -0.5000 + 4.0000 10.0000 -0.5000 + 4.5000 10.5000 4.5000 + 4.5000 10.5000 -0.5000 + -2.0000 20.0000 0.0000 + -2.0000 20.0000 4.0000 + -2.0000 20.5000 -0.0000 + -2.0000 20.5000 4.0000 + -2.0000 20.0000 12.0000 + -2.0000 20.0000 15.9999 + -2.0000 20.5000 12.0000 + -2.0000 20.5000 15.9999 + -2.0000 20.5000 18.0000 + -2.0000 24.0000 18.0000 + -2.0000 20.5000 -2.0000 + -2.0000 24.0000 -2.0000 + -2.5000 20.5000 4.5000 + -2.5000 20.5000 11.5000 + -2.5000 20.0000 4.5000 + -2.5000 20.0000 11.5000 + -2.5000 20.0000 -2.5000 + -2.5000 20.5000 -2.5000 + -2.5000 20.0000 -0.5000 + -2.5000 20.5000 -0.5000 + -2.5000 20.5000 18.5000 + -2.5000 20.0000 18.5000 + -2.5000 20.5000 16.5000 + -2.5000 20.0000 16.5000 + -2.5000 24.5000 -2.5000 + -2.5000 24.5000 18.5000 + -2.0000 24.5000 18.5000 + -2.0000 24.5000 -2.5000 + -2.5000 20.0000 0.0000 + -2.5000 20.0000 4.0000 + -2.0000 20.0000 4.5000 + -2.0000 20.0000 11.5000 + -2.0000 20.0000 -2.5000 + -2.0000 20.0000 -0.5000 + -2.5000 20.0000 12.0000 + -2.5000 20.0000 15.9999 + -2.0000 20.0000 16.5000 + -2.0000 20.0000 18.5000 + 2.5000 20.0000 4.5000 + 2.5000 20.0000 11.5000 + 2.5000 20.5000 4.5000 + 2.5000 20.5000 11.5000 + 2.5000 20.0000 -2.5000 + 2.5000 20.0000 -0.5000 + 2.5000 20.5000 -2.5000 + 2.5000 20.5000 -0.5000 + 2.5000 20.0000 16.5000 + 2.5000 20.0000 18.5000 + 2.5000 20.5000 16.5000 + 2.5000 20.5000 18.5000 + 2.5000 24.5000 18.5000 + 2.5000 24.5000 -2.5000 + 2.0000 20.0000 4.0000 + 2.0000 20.0000 -0.0000 + 2.0000 20.5000 4.0000 + 2.0000 20.5000 -0.0000 + 2.0000 20.5000 15.9999 + 2.0000 20.0000 15.9999 + 2.0000 20.5000 12.0000 + 2.0000 20.0000 12.0000 + 2.0000 24.0000 18.0000 + 2.0000 20.5000 18.0000 + 2.0000 24.0000 -2.0000 + 2.0000 20.5000 -2.0000 + 2.0000 24.5000 18.5000 + 2.0000 24.5000 -2.5000 + 2.5000 20.0000 -0.0000 + 2.5000 20.0000 4.0000 + 2.0000 20.0000 4.5000 + 2.0000 20.0000 11.5000 + 2.0000 20.0000 -2.5000 + 2.0000 20.0000 -0.5000 + 2.5000 20.0000 12.0000 + 2.5000 20.0000 15.9999 + 2.0000 20.0000 16.5000 + 2.0000 20.0000 18.5000 + -4.0000 20.0000 4.5000 + -4.0000 20.0000 -0.5000 + 4.0000 20.0000 4.5000 + 4.0000 20.0000 -0.5000 + -2.0000 24.0000 18.5000 + 2.0000 24.0000 18.5000 + -2.0000 24.0000 -2.5000 + 2.0000 24.0000 -2.5000 + -2.0000 20.5000 -2.5000 + 2.0000 20.5000 -2.5000 + -2.0000 20.5000 18.5000 + 2.0000 20.5000 18.5000 + -4.0000 20.5000 11.5000 + -4.0000 20.5000 16.5000 + -4.0000 20.0000 12.0000 + -4.0000 20.0000 15.9999 + -4.0000 20.0000 16.5000 + -4.0000 20.0000 11.5000 + 4.0000 20.5000 11.5000 + 4.0000 20.5000 16.5000 + 4.0000 20.0000 12.0000 + 4.0000 20.0000 15.9999 + 4.0000 20.0000 16.5000 + 4.0000 20.0000 11.5000 + -2.0000 20.0000 18.4999 + 2.0000 20.0000 18.4999 + -2.0000 20.5000 18.4999 + 2.0000 20.5000 18.4999 + -4.0000 18.0000 0.0000 + -4.0000 18.0000 -0.5000 + 4.0000 18.0000 0.0000 + 4.0000 18.0000 -0.5000 + -2.0000 18.0000 4.5000 + 2.0000 18.0000 4.5000 + -2.0000 10.0000 4.5000 + 2.0000 10.0000 4.5000 + 2.0000 18.0000 4.0000 + -2.0000 18.0000 4.0000 + 2.0000 10.0000 4.0000 + -2.0000 10.0000 4.0000 + -4.0000 18.0000 4.5000 + -4.0000 18.0000 4.0000 + 4.0000 18.0000 4.5000 + 4.0000 18.0000 4.0000 + -2.0000 18.0000 12.0000 + 2.0000 18.0000 12.0000 + -2.0000 10.0000 12.0000 + 2.0000 10.0000 12.0000 + 2.0000 18.0000 11.5000 + -2.0000 18.0000 11.5000 + 2.0000 10.0000 11.5000 + -2.0000 10.0000 11.5000 + -4.5000 20.5000 11.5000 + -4.5000 20.5000 16.5000 + -4.5000 10.5000 11.5000 + -4.5000 10.5000 16.5000 + -4.0000 10.0000 15.9999 + -4.0000 10.0000 12.0000 + -4.5000 10.0000 15.9999 + -4.5000 10.0000 12.0000 + -4.5000 10.0000 16.5000 + -4.0000 10.0000 16.5000 + -4.0000 10.0000 11.5000 + -4.5000 10.0000 11.5000 + 4.0000 10.0000 12.0000 + 4.0000 10.0000 15.9999 + 4.5000 20.5000 11.5000 + 4.5000 20.5000 16.5000 + 4.5000 10.0000 15.9999 + 4.5000 10.0000 12.0000 + 4.0000 10.0000 16.5000 + 4.5000 10.0000 16.5000 + 4.5000 10.0000 11.5000 + 4.0000 10.0000 11.5000 + 4.5000 10.5000 16.5000 + 4.5000 10.5000 11.5000 + -4.0000 18.0000 12.0000 + -4.0000 18.0000 11.5000 + 4.0000 18.0000 12.0000 + 4.0000 18.0000 11.5000 + -2.0000 18.0000 16.5000 + 2.0000 18.0000 16.5000 + -2.0000 10.0000 16.5000 + 2.0000 10.0000 16.5000 + 2.0000 18.0000 16.0000 + -2.0000 18.0000 16.0000 + 2.0000 10.0000 16.0000 + -2.0000 10.0000 16.0000 + -4.0000 18.0000 16.5000 + -4.0000 18.0000 16.0000 + 4.0000 18.0000 16.5000 + 4.0000 18.0000 16.0000 + -10.5000 10.5000 11.5000 + -10.5000 10.5000 16.5000 + -10.5000 -10.5000 11.5000 + -10.5000 10.0000 16.5000 + -10.5000 -10.5000 16.5000 + -10.0000 10.5000 11.5000 + -10.0000 10.5000 16.5000 + -10.0000 -10.5000 11.5000 + -10.0000 -10.5000 16.5000 + -10.0000 10.0000 16.5000 + -10.5000 10.0000 11.5000 + -10.0000 10.0000 15.9999 + -10.0000 10.0000 12.0000 + -10.0000 -10.0000 15.9999 + -10.0000 -10.0000 12.0000 + 10.0000 -10.5000 16.5000 + 10.0000 -10.5000 11.5000 + 10.0000 -10.0000 16.5000 + -10.0000 -10.0000 16.5000 + 10.0000 -10.0000 11.5000 + -10.0000 -10.0000 11.5000 + 10.0000 -10.0000 12.0000 + 10.0000 -10.0000 15.9999 + 10.0000 10.0000 16.5000 + 10.0000 10.0000 16.0000 + 10.0000 10.0000 11.5000 + -10.0000 10.0000 11.5000 + 10.0000 10.0000 12.0000 + 10.5000 10.5000 16.5000 + 10.5000 10.5000 11.5000 + 10.5000 -10.5000 16.5000 + 10.5000 10.0000 11.5000 + 10.5000 -10.5000 11.5000 + 10.0000 10.5000 16.5000 + 10.5000 10.0000 16.5000 + 10.0000 10.5000 11.5000 + -6.0000 10.5000 11.5000 + -6.0000 10.5000 16.5000 + -6.0000 10.0000 16.5000 + -6.0000 10.0000 11.5000 + -6.0000 10.0000 12.0000 + -6.0000 10.0000 15.9999 + 6.0000 10.5000 11.5000 + 6.0000 10.5000 16.5000 + 6.0000 10.0000 16.5000 + 6.0000 10.0000 11.5000 + 6.0000 10.0000 12.0000 + 6.0000 10.0000 15.9999 + </float_array> + <technique_common> + <accessor source="#DemoRoomLrg_5c1b8cbb-Position-array" count="338" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="DemoRoomLrg_5c1b8cbb-Normal"> + <float_array id="DemoRoomLrg_5c1b8cbb-Normal-array" count="18"> + -1.0000 -0.0000 -0.0000 + -0.0000 1.0000 -0.0000 + -0.0000 -1.0000 -0.0000 + 0.0000 -0.0000 1.0000 + -0.0000 -0.0000 -1.0000 + 1.0000 -0.0000 0.0000 + </float_array> + <technique_common> + <accessor source="#DemoRoomLrg_5c1b8cbb-Normal-array" count="6" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="DemoRoomLrg_5c1b8cbb-UV0"> + <float_array id="DemoRoomLrg_5c1b8cbb-UV0-array" count="498"> + 0.0000 -0.0000 + 0.0000 9.0000 + 42.0000 -0.0000 + 42.0000 9.0000 + 41.0000 -0.0000 + 41.0000 9.0000 + 1.0000 9.0000 + 1.0000 -0.0000 + 0.0000 42.0000 + 1.0000 42.0000 + 41.0000 42.0000 + 42.0000 42.0000 + 3.0000 1.0000 + 3.0000 -0.0000 + -2.0000 1.0000 + -2.0000 0.0000 + 42.0000 1.0000 + 1.0000 1.0000 + 41.0000 1.0000 + 0.0000 1.0000 + 42.0000 41.0000 + 1.0000 41.0000 + -0.6250 -3.0000 + -2.0000 -3.0000 + -0.6250 2.0000 + -2.0000 2.0000 + -0.3750 0.6250 + 1.3750 0.6250 + -0.3750 0.3750 + 1.3750 0.3750 + -0.3750 -1.3750 + 1.3750 -1.3750 + -0.3750 -1.6250 + 1.3750 -1.6250 + 1.6250 2.0000 + 3.0000 2.0000 + 1.6250 -3.0000 + 3.0000 -3.0000 + -0.6250 0.6250 + 1.6250 0.6250 + -0.6250 -1.3750 + -0.6250 0.3750 + 1.6250 -1.3750 + 1.6250 0.3750 + -0.6250 -1.6250 + 1.6250 -1.6250 + 0.0000 41.0000 + 41.0000 41.0000 + 41.0000 8.0000 + 1.9524 8.0000 + 1.0000 8.0000 + 43.0500 42.0000 + 43.0500 41.0000 + 43.0500 0.0000 + -1.0500 0.0000 + -1.0500 9.0000 + 43.0500 9.0000 + -1.0500 42.0000 + -2.0030 -0.0000 + -2.0030 1.0000 + 2.8780 -0.0000 + 2.8780 1.0000 + 0.0000 -1.0000 + 0.2500 -1.0000 + 0.2500 0.0000 + -1.0000 -0.0000 + -1.0000 1.0000 + -1.0000 5.0000 + 0.0000 5.0000 + -1.0000 3.0000 + 0.0000 3.0000 + 0.0000 40.0000 + 24.0000 40.0000 + 24.0000 0.0000 + 40.0000 -0.0000 + 40.0000 9.0000 + -2.2500 2.0000 + -2.2500 0.0000 + 5.5000 1.0000 + 5.5000 0.0000 + -4.5000 -0.0000 + -4.5000 1.0000 + 2.2500 2.0000 + 2.2500 0.0000 + 2.0000 2.0000 + 2.0000 0.0000 + 32.0000 9.0000 + 32.0000 -1.0000 + 25.3333 9.0000 + 25.3333 -1.0000 + 5.0000 0.0000 + 5.0000 1.0000 + 5.1250 -0.0000 + 5.1250 1.0000 + 5.0000 3.0000 + 5.0000 4.0000 + 5.1250 3.0000 + 5.1250 4.0000 + 5.1250 4.5000 + 6.0000 4.5000 + 5.1250 -0.5000 + 6.0000 -0.5000 + 7.1111 0.3333 + 7.1111 0.6667 + 8.0000 0.3333 + 8.0000 0.6667 + 8.0000 -0.0000 + 7.1111 -0.0000 + 8.0000 0.0952 + 7.1111 0.0952 + 7.1111 1.0000 + 8.0000 1.0000 + 7.1111 0.9048 + 8.0000 0.9048 + -1.2500 0.0000 + -1.2500 2.0000 + -1.0000 2.0000 + -1.2500 2.2500 + -1.2500 5.7500 + -1.0000 2.2500 + -1.0000 5.7500 + -1.2500 -1.2500 + -1.2500 -0.2500 + -1.0000 -1.2500 + -1.0000 -0.2500 + -1.2500 6.0000 + -1.2500 8.0000 + -1.0000 6.0000 + -1.0000 8.0000 + -1.2500 8.2500 + -1.2500 9.2500 + -1.0000 8.2500 + -1.0000 9.2500 + 0.0000 8.0000 + 0.0000 0.3333 + 0.0000 0.6667 + 0.8889 0.3333 + 0.8889 0.6667 + 0.0000 0.0952 + 0.8889 -0.0000 + 0.8889 0.0952 + 0.0000 0.9048 + 0.8889 0.9048 + 0.8889 1.0000 + -5.0000 1.0000 + -5.0000 -0.0000 + -5.1250 1.0000 + -5.1250 -0.0000 + -5.1250 4.0000 + -5.0000 4.0000 + -5.1250 3.0000 + -5.0000 3.0000 + -6.0000 4.5000 + -5.1250 4.5000 + -6.0000 -0.5000 + -5.1250 -0.5000 + 1.0000 2.0000 + 1.2500 -0.0000 + 1.2500 2.0000 + 1.0000 2.2500 + 1.0000 5.7500 + 1.2500 2.2500 + 1.2500 5.7500 + 1.0000 -1.2500 + 1.0000 -0.2500 + 1.2500 -1.2500 + 1.2500 -0.2500 + 1.0000 6.0000 + 1.2500 6.0000 + 1.2500 8.0000 + 1.0000 8.2500 + 1.0000 9.2500 + 1.2500 8.2500 + 1.2500 9.2500 + 5.0000 10.0000 + -0.0000 10.0000 + 0.0000 4.5000 + 1.0000 4.5000 + 0.0000 -0.5000 + 1.0000 -0.5000 + 0.0000 5.1250 + 0.0000 6.0000 + 1.0000 5.1250 + -1.0000 -1.0000 + 1.0000 -1.0000 + 5.0000 8.0000 + -1.0000 9.7500 + -1.0000 10.0000 + 1.0000 9.7500 + 1.0000 10.0000 + 1.0000 2.3750 + 0.0000 2.3750 + 0.0000 0.6250 + 0.0000 9.3750 + 5.0000 0.6250 + 5.0000 9.3750 + -2.0000 6.0000 + -2.0000 8.0000 + 2.0000 6.0000 + 2.0000 8.0000 + -1.0000 9.0000 + 0.0000 2.0003 + 5.0000 2.0003 + -0.0011 9.0000 + 40.9989 9.0000 + -0.0011 -0.0000 + 40.9989 -0.0000 + 1.0002 42.0000 + 42.0001 42.0000 + 1.0002 41.0000 + 42.0001 41.0000 + -0.0011 41.0000 + -0.0011 42.0000 + 40.9989 41.0000 + 40.9989 42.0000 + -3.0000 2.0000 + -3.0000 -0.0000 + 40.9991 -0.0000 + -0.0008 -0.0000 + 40.9991 9.0000 + -0.0008 9.0000 + 0.9999 42.0000 + 41.9998 42.0000 + 0.9999 41.0000 + 41.9998 41.0000 + -0.0008 41.0000 + -0.0008 42.0000 + 40.9991 41.0000 + 40.9991 42.0000 + -2.0000 9.0000 + -2.0000 5.0000 + 0.0001 40.0000 + 0.0001 0.0000 + 2.0000 9.0000 + 1.0000 5.0000 + 2.0000 5.0000 + -2.0000 10.0000 + 2.0000 10.0000 + -4.0000 36.0000 + 4.0000 36.0000 + -4.0000 20.0000 + 4.0000 20.0000 + -8.0000 36.0000 + -8.0000 20.0000 + 8.0000 36.0000 + 8.0000 20.0000 + -8.0000 40.0000 + 8.0000 40.0000 + 40.0476 1.0000 + </float_array> + <technique_common> + <accessor source="#DemoRoomLrg_5c1b8cbb-UV0-array" count="249" stride="2"> + <param name="S" type="float" /> + <param name="T" type="float" /> + </accessor> + </technique_common> + </source> + <vertices id="DemoRoomLrg_5c1b8cbb-Vertex"> + <input semantic="POSITION" source="#DemoRoomLrg_5c1b8cbb-Position" /> + </vertices> + <triangles material="BLACK" count="253"> + <input semantic="VERTEX" offset="0" source="#DemoRoomLrg_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#DemoRoomLrg_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#DemoRoomLrg_5c1b8cbb-UV0" /> + <p> + 3 0 3 1 0 1 0 0 0 + 2 0 2 3 0 3 0 0 0 + 5 1 5 4 1 4 0 1 2 + 1 1 3 5 1 5 0 1 2 + 7 2 7 6 2 6 3 2 1 + 2 2 0 7 2 7 3 2 1 + 6 3 7 5 3 9 1 3 8 + 3 3 0 6 3 7 1 3 8 + 2 4 2 0 4 11 4 4 10 + 7 4 4 2 4 2 4 4 10 + 7 2 7 13 2 2 12 2 3 + 6 2 6 7 2 7 12 2 3 + 6 3 7 12 3 2 14 3 16 + 15 3 17 6 3 7 14 3 16 + 17 4 19 13 4 0 7 4 4 + 16 4 18 17 4 19 7 4 4 + 15 3 17 14 3 16 20 3 20 + 21 3 21 15 3 17 20 3 20 + 44 4 47 43 4 46 17 4 19 + 16 4 18 44 4 47 17 4 19 + 69 5 17 67 5 18 66 5 48 + 70 5 50 69 5 17 66 5 48 + 68 5 49 70 5 50 66 5 48 + 72 3 52 66 3 51 71 3 11 + 70 3 53 72 3 52 71 3 11 + 12 3 2 70 3 53 71 3 11 + 14 3 16 12 3 2 71 3 11 + 71 1 1 66 1 55 67 1 54 + 73 1 0 71 1 1 67 1 54 + 69 2 53 70 2 56 12 2 3 + 13 2 2 69 2 53 12 2 3 + 13 4 0 73 4 8 67 4 57 + 69 4 54 13 4 0 67 4 57 + 75 1 1 74 1 0 4 1 4 + 5 1 5 75 1 1 4 1 4 + 76 3 20 75 3 11 5 3 9 + 21 3 21 76 3 20 5 3 9 + 4 4 10 74 4 8 77 4 46 + 44 4 47 4 4 10 77 4 46 + 71 1 1 73 1 0 80 1 4 + 81 1 5 71 1 1 80 1 4 + 20 3 20 71 3 11 81 3 9 + 82 3 21 20 3 20 81 3 9 + 80 4 10 73 4 8 43 4 46 + 83 4 47 80 4 10 43 4 46 + 93 4 73 91 4 72 90 4 71 + 92 4 0 93 4 73 90 4 71 + 97 0 75 95 0 1 94 0 0 + 96 0 74 97 0 75 94 0 0 + 99 1 5 98 1 4 94 1 2 + 95 1 3 99 1 5 94 1 2 + 103 3 7 99 3 9 95 3 8 + 102 3 0 103 3 7 95 3 8 + 105 4 2 94 4 11 98 4 10 + 104 4 4 105 4 2 98 4 10 + 115 1 5 113 1 4 112 1 2 + 114 1 3 115 1 5 112 1 2 + 117 3 7 115 3 9 114 3 8 + 116 3 0 117 3 7 114 3 8 + 119 4 2 112 4 11 113 4 10 + 118 4 4 119 4 2 113 4 10 + 121 5 89 113 5 87 115 5 86 + 120 5 88 121 5 89 115 5 86 + 137 0 105 135 0 103 134 0 102 + 136 0 104 137 0 105 134 0 102 + 141 0 109 139 0 107 138 0 106 + 140 0 108 141 0 109 138 0 106 + 145 0 113 143 0 111 142 0 110 + 144 0 112 145 0 113 142 0 110 + 147 0 19 146 0 0 139 0 107 + 142 0 110 147 0 19 139 0 107 + 146 1 7 147 1 17 148 1 19 + 149 1 0 146 1 7 148 1 19 + 148 3 50 147 3 133 143 3 0 + 159 3 7 148 3 50 143 3 0 + 149 4 133 154 4 0 138 4 7 + 146 4 50 149 4 133 138 4 7 + 163 5 137 161 5 135 160 5 134 + 162 5 136 163 5 137 160 5 134 + 167 5 140 165 5 138 164 5 0 + 166 5 139 167 5 140 164 5 0 + 171 5 143 169 5 19 168 5 141 + 170 5 142 171 5 143 168 5 141 + 173 5 106 172 5 111 171 5 143 + 166 5 139 173 5 106 171 5 143 + 187 1 7 186 1 17 172 1 19 + 173 1 0 187 1 7 172 1 19 + 172 3 50 186 3 133 197 3 0 + 169 3 7 172 3 50 197 3 0 + 173 4 133 164 4 0 192 4 7 + 187 4 50 173 4 133 192 4 7 + 134 1 175 141 1 0 98 1 90 + 99 1 174 134 1 175 98 1 90 + 134 3 91 99 3 19 198 3 0 + 136 3 90 134 3 91 198 3 0 + 141 4 19 140 4 0 199 4 90 + 98 4 91 141 4 19 199 4 90 + 114 1 175 112 1 0 167 1 90 + 162 1 174 114 1 175 167 1 90 + 114 3 91 162 3 19 160 3 0 + 200 3 90 114 3 91 160 3 0 + 112 4 19 201 4 0 165 4 90 + 167 4 91 112 4 19 165 4 90 + 149 1 90 148 1 174 186 1 175 + 187 1 0 149 1 90 186 1 175 + 186 3 91 148 3 19 202 3 0 + 203 3 90 186 3 91 202 3 0 + 187 4 19 205 4 0 204 4 90 + 149 4 91 187 4 19 204 4 90 + 205 4 133 207 4 0 206 4 7 + 204 4 50 205 4 133 206 4 7 + 193 2 185 155 2 133 154 2 0 + 192 2 90 193 2 185 154 2 0 + 207 4 19 192 4 0 154 4 90 + 206 4 91 207 4 19 154 4 90 + 191 2 195 153 2 193 152 2 192 + 190 2 194 191 2 195 152 2 192 + 203 3 50 202 3 133 208 3 0 + 209 3 7 203 3 50 208 3 0 + 144 1 175 135 1 0 210 1 90 + 211 1 174 144 1 175 210 1 90 + 144 3 91 211 3 19 214 3 0 + 145 3 90 144 3 91 214 3 0 + 135 4 19 137 4 0 215 4 90 + 210 4 91 135 4 19 215 4 90 + 217 1 175 216 1 0 163 1 90 + 170 1 174 217 1 175 163 1 90 + 217 3 91 170 3 19 168 3 0 + 220 3 90 217 3 91 168 3 0 + 216 4 19 221 4 0 161 4 90 + 163 4 91 216 4 19 161 4 90 + 223 2 174 222 2 175 158 2 201 + 196 2 202 223 2 174 158 2 201 + 225 3 91 224 3 19 222 3 0 + 223 3 90 225 3 91 222 3 0 + 74 1 206 75 1 204 97 1 203 + 96 1 205 74 1 206 97 1 203 + 102 3 210 97 3 208 75 3 207 + 76 3 209 102 3 210 75 3 207 + 74 4 214 96 4 212 105 4 211 + 77 4 213 74 4 214 105 4 211 + 81 1 220 80 1 218 121 1 217 + 120 1 219 81 1 220 121 1 217 + 82 3 224 81 3 222 120 3 221 + 117 3 223 82 3 224 120 3 221 + 121 4 228 80 4 226 83 4 225 + 118 4 227 121 4 228 83 4 225 + 104 4 73 227 4 72 91 4 231 + 93 4 232 104 4 73 91 4 231 + 92 4 73 90 4 72 229 4 71 + 119 4 0 92 4 73 229 4 71 + 201 4 71 229 4 0 227 4 73 + 199 4 72 201 4 71 227 4 73 + 233 3 241 231 3 239 230 3 238 + 232 3 240 233 3 241 230 3 238 + 232 3 240 230 3 238 238 3 242 + 103 3 243 232 3 240 238 3 242 + 116 3 245 240 3 244 231 3 239 + 233 3 241 116 3 245 231 3 239 + 200 3 247 198 3 246 238 3 242 + 240 3 244 200 3 247 238 3 242 + 249 4 73 247 4 72 246 4 71 + 248 4 0 249 4 73 246 4 71 + 253 0 75 251 0 1 250 0 0 + 252 0 74 253 0 75 250 0 0 + 211 1 5 210 1 4 250 1 2 + 251 1 3 211 1 5 250 1 2 + 259 3 7 211 3 9 251 3 8 + 258 3 0 259 3 7 251 3 8 + 261 4 2 250 4 11 210 4 10 + 260 4 4 261 4 2 210 4 10 + 265 1 5 264 1 4 216 1 2 + 217 1 3 265 1 5 216 1 2 + 269 3 7 265 3 9 217 3 8 + 268 3 0 269 3 7 217 3 8 + 271 4 2 216 4 11 264 4 10 + 270 4 4 271 4 2 264 4 10 + 273 5 89 264 5 87 265 5 86 + 272 5 88 273 5 89 265 5 86 + 260 4 73 275 4 72 247 4 231 + 249 4 232 260 4 73 247 4 231 + 248 4 73 246 4 72 277 4 71 + 271 4 0 248 4 73 277 4 71 + 281 3 241 279 3 239 278 3 238 + 280 3 240 281 3 241 278 3 238 + 280 3 240 278 3 238 286 3 242 + 259 3 243 280 3 240 286 3 242 + 268 3 245 288 3 244 279 3 239 + 281 3 241 268 3 245 279 3 239 + 220 3 247 214 3 246 286 3 242 + 288 3 244 220 3 247 286 3 242 + 221 4 71 277 4 0 275 4 73 + 215 4 72 221 4 71 275 4 73 + 293 0 6 291 0 1 290 0 0 + 294 0 3 293 0 6 290 0 0 + 292 0 2 294 0 3 290 0 0 + 296 1 5 295 1 4 290 1 2 + 291 1 3 296 1 5 290 1 2 + 298 2 6 294 2 1 292 2 0 + 297 2 7 298 2 6 292 2 0 + 299 3 21 296 3 9 291 3 8 + 298 3 7 299 3 21 291 3 8 + 294 3 0 298 3 7 291 3 8 + 300 4 20 290 4 11 295 4 10 + 292 4 2 300 4 20 295 4 10 + 297 4 4 292 4 2 295 4 10 + 306 2 2 305 2 3 298 2 6 + 297 2 7 306 2 2 298 2 6 + 298 3 7 305 3 2 307 3 16 + 308 3 17 298 3 7 307 3 16 + 310 4 18 309 4 19 306 4 0 + 297 4 4 310 4 18 306 4 0 + 308 3 17 307 3 16 313 3 20 + 299 3 21 308 3 17 313 3 20 + 316 4 47 315 4 46 309 4 19 + 310 4 18 316 4 47 309 4 19 + 321 5 248 319 5 18 318 5 48 + 322 5 17 321 5 248 318 5 48 + 320 5 50 322 5 17 318 5 48 + 324 3 52 318 3 51 323 3 11 + 320 3 53 324 3 52 323 3 11 + 305 3 2 320 3 53 323 3 11 + 323 1 1 318 1 55 319 1 54 + 325 1 0 323 1 1 319 1 54 + 322 2 53 320 2 56 305 2 3 + 306 2 2 322 2 53 305 2 3 + 315 4 46 325 4 8 319 4 57 + 306 4 0 315 4 46 319 4 57 + 322 4 54 306 4 0 319 4 57 + 327 1 1 326 1 0 295 1 4 + 296 1 5 327 1 1 295 1 4 + 328 3 20 327 3 11 296 3 9 + 299 3 21 328 3 20 296 3 9 + 295 4 10 326 4 8 329 4 46 + 316 4 47 295 4 10 329 4 46 + 323 1 1 325 1 0 332 1 4 + 333 1 5 323 1 1 332 1 4 + 313 3 20 323 3 11 333 3 9 + 334 3 21 313 3 20 333 3 9 + 332 4 10 325 4 8 315 4 46 + 335 4 47 332 4 10 315 4 46 + 326 1 206 327 1 204 253 1 203 + 252 1 205 326 1 206 253 1 203 + 258 3 210 253 3 208 327 3 207 + 328 3 209 258 3 210 327 3 207 + 326 4 214 252 4 212 261 4 211 + 329 4 213 326 4 214 261 4 211 + 333 1 220 332 1 218 273 1 217 + 272 1 219 333 1 220 273 1 217 + 334 3 224 333 3 222 272 3 221 + 269 3 223 334 3 224 272 3 221 + 273 4 228 332 4 226 335 4 225 + 270 4 227 273 4 228 335 4 225 + </p> + </triangles> + <triangles material="FULL128X128G" count="88"> + <input semantic="VERTEX" offset="0" source="#DemoRoomLrg_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#DemoRoomLrg_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#DemoRoomLrg_5c1b8cbb-UV0" /> + <p> + 11 5 15 9 5 13 8 5 12 + 10 5 14 11 5 15 8 5 12 + 10 1 12 19 1 14 18 1 15 + 11 1 13 10 1 12 18 1 15 + 24 4 25 19 4 23 22 4 22 + 23 4 24 24 4 25 22 4 22 + 28 4 29 26 4 27 25 4 26 + 27 4 28 28 4 29 25 4 26 + 32 4 33 30 4 31 29 4 30 + 31 4 32 32 4 33 29 4 30 + 10 4 37 8 4 35 33 4 34 + 34 4 36 10 4 37 33 4 34 + 33 4 34 23 4 24 35 4 38 + 36 4 39 33 4 34 35 4 38 + 40 4 43 38 4 41 37 4 40 + 39 4 42 40 4 43 37 4 40 + 42 4 45 41 4 44 22 4 22 + 34 4 36 42 4 45 22 4 22 + 18 3 37 46 3 35 45 3 34 + 47 3 36 18 3 37 45 3 34 + 51 3 26 49 3 28 48 3 29 + 50 3 27 51 3 26 48 3 29 + 55 3 30 53 3 32 52 3 33 + 54 3 31 55 3 30 52 3 33 + 57 3 22 56 3 24 9 3 25 + 11 3 23 57 3 22 9 3 25 + 59 3 38 58 3 39 45 3 34 + 56 3 24 59 3 38 45 3 34 + 63 3 40 61 3 42 60 3 43 + 62 3 41 63 3 40 60 3 43 + 57 3 22 47 3 36 64 3 45 + 65 3 44 57 3 22 64 3 45 + 19 0 61 24 0 59 46 0 58 + 18 0 60 19 0 61 46 0 58 + 79 2 66 8 2 14 9 2 15 + 78 2 65 79 2 66 9 2 15 + 24 2 66 85 2 14 84 2 15 + 46 2 65 24 2 66 84 2 15 + 89 3 70 87 3 68 86 3 67 + 88 3 69 89 3 70 86 3 67 + 101 5 13 107 5 79 106 5 78 + 100 5 12 101 5 13 106 5 78 + 111 0 14 109 0 81 108 0 80 + 110 0 15 111 0 14 108 0 80 + 125 5 93 123 5 91 122 5 90 + 124 5 92 125 5 93 122 5 90 + 129 5 97 127 5 95 126 5 94 + 128 5 96 129 5 97 126 5 94 + 133 5 101 131 5 99 130 5 98 + 132 5 100 133 5 101 130 5 98 + 177 0 147 175 0 145 174 0 144 + 176 0 146 177 0 147 174 0 144 + 181 0 151 179 0 149 178 0 148 + 180 0 150 181 0 151 178 0 148 + 185 0 155 183 0 153 182 0 152 + 184 0 154 185 0 155 182 0 152 + 184 2 179 182 2 177 131 2 176 + 133 2 178 184 2 179 131 2 176 + 184 3 167 133 3 181 132 3 180 + 185 3 182 184 3 167 132 3 180 + 180 1 191 176 1 19 125 1 17 + 128 1 190 180 1 191 125 1 17 + 182 4 181 183 4 180 130 4 182 + 131 4 167 182 4 181 130 4 182 + 237 4 70 235 4 68 234 4 67 + 236 4 69 237 4 70 234 4 67 + 245 3 70 243 3 68 242 3 67 + 244 3 69 245 3 70 242 3 67 + 255 5 13 212 5 79 213 5 78 + 254 5 12 255 5 13 213 5 78 + 263 0 14 219 0 81 218 0 80 + 262 0 15 263 0 14 218 0 80 + 285 4 70 283 4 68 282 4 67 + 284 4 69 285 4 70 282 4 67 + 304 5 15 302 5 13 301 5 12 + 303 5 14 304 5 15 301 5 12 + 303 1 12 312 1 14 311 1 15 + 304 1 13 303 1 12 311 1 15 + 314 4 25 312 4 23 303 4 37 + 301 4 35 314 4 25 303 4 37 + 317 3 35 302 3 25 304 3 23 + 311 3 37 317 3 35 304 3 23 + 312 0 61 314 0 59 317 0 58 + 311 0 60 312 0 61 317 0 58 + 331 2 66 301 2 14 302 2 15 + 330 2 65 331 2 66 302 2 15 + 314 2 66 337 2 14 336 2 15 + 317 2 65 314 2 66 336 2 15 + </p> + </triangles> + <triangles material="PILLAR128X128G" count="32"> + <input semantic="VERTEX" offset="0" source="#DemoRoomLrg_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#DemoRoomLrg_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#DemoRoomLrg_5c1b8cbb-UV0" /> + <p> + 30 5 64 32 5 0 53 5 62 + 55 5 63 30 5 64 53 5 62 + 39 0 0 63 0 62 65 0 63 + 42 0 64 39 0 0 65 0 63 + 30 1 0 55 1 62 63 1 63 + 39 1 64 30 1 0 63 1 63 + 32 2 64 42 2 0 65 2 62 + 53 2 63 32 2 64 65 2 62 + 26 5 64 28 5 0 49 5 62 + 51 5 63 26 5 64 49 5 62 + 36 0 0 59 0 62 62 0 63 + 40 0 64 36 0 0 62 0 63 + 26 1 0 51 1 62 59 1 63 + 36 1 64 26 1 0 59 1 63 + 28 2 64 40 2 0 62 2 62 + 49 2 63 28 2 64 62 2 62 + 35 5 64 38 5 0 60 5 62 + 58 5 63 35 5 64 60 5 62 + 25 0 0 50 0 62 48 0 63 + 27 0 64 25 0 0 48 0 63 + 35 1 0 58 1 62 50 1 63 + 25 1 64 35 1 0 50 1 63 + 38 2 64 27 2 0 48 2 62 + 60 2 63 38 2 64 48 2 62 + 37 5 64 41 5 0 64 5 62 + 61 5 63 37 5 64 64 5 62 + 29 0 0 54 0 62 52 0 63 + 31 0 64 29 0 0 52 0 63 + 37 1 0 61 1 62 54 1 63 + 29 1 64 37 1 0 54 1 63 + 41 2 64 31 2 0 52 2 62 + 64 2 63 41 2 64 52 2 62 + </p> + </triangles> + <triangles material="FULL64X64G" count="80"> + <input semantic="VERTEX" offset="0" source="#DemoRoomLrg_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#DemoRoomLrg_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#DemoRoomLrg_5c1b8cbb-UV0" /> + <p> + 56 2 77 101 2 15 100 2 25 + 33 2 76 56 2 77 100 2 25 + 110 2 85 45 2 83 23 2 82 + 111 2 84 110 2 85 23 2 82 + 123 2 116 151 2 115 150 2 114 + 122 2 65 123 2 116 150 2 114 + 153 2 120 137 2 118 136 2 117 + 152 2 119 153 2 120 136 2 117 + 155 2 124 140 2 122 138 2 121 + 154 2 123 155 2 124 138 2 121 + 127 2 128 157 2 126 156 2 125 + 126 2 127 127 2 128 156 2 125 + 159 2 132 143 2 130 145 2 129 + 158 2 131 159 2 132 145 2 129 + 189 2 158 174 2 156 175 2 7 + 188 2 157 189 2 158 175 2 7 + 161 2 162 191 2 160 190 2 159 + 160 2 161 161 2 162 190 2 159 + 165 2 166 193 2 164 192 2 163 + 164 2 165 165 2 166 192 2 163 + 195 2 169 179 2 50 181 2 167 + 194 2 168 195 2 169 181 2 167 + 169 2 173 197 2 171 196 2 170 + 168 2 172 169 2 173 196 2 170 + 151 2 115 106 2 25 107 2 15 + 150 2 114 151 2 115 107 2 15 + 109 2 84 189 2 158 188 2 157 + 108 2 85 109 2 84 188 2 157 + 124 1 7 177 1 65 185 1 183 + 132 1 184 124 1 7 185 1 183 + 177 3 189 124 3 187 122 3 186 + 175 3 188 177 3 189 122 3 186 + 180 3 189 128 3 187 126 3 186 + 181 3 188 180 3 189 126 3 186 + 176 4 187 174 4 186 123 4 188 + 125 4 189 176 4 187 123 4 188 + 157 2 126 213 2 197 212 2 196 + 156 2 125 157 2 126 212 2 196 + 219 2 199 195 2 169 194 2 168 + 218 2 198 219 2 199 194 2 168 + 183 1 200 178 1 128 129 1 50 + 130 1 6 183 1 200 129 1 50 + 178 4 187 179 4 186 127 4 188 + 129 4 189 178 4 187 127 4 188 + 78 2 216 56 2 77 33 2 76 + 79 2 215 78 2 216 33 2 76 + 85 2 35 23 2 82 45 2 83 + 84 2 13 85 2 35 45 2 83 + 88 3 67 86 3 200 226 3 229 + 101 3 230 88 3 67 226 3 229 + 110 3 235 228 3 233 87 3 6 + 89 3 234 110 3 235 87 3 6 + 108 3 237 107 3 236 226 3 229 + 228 3 233 108 3 237 226 3 229 + 100 4 235 239 4 233 235 4 6 + 237 4 234 100 4 235 235 4 6 + 236 4 67 234 4 200 241 4 229 + 111 4 230 236 4 67 241 4 229 + 109 4 236 241 4 229 239 4 233 + 106 4 237 109 4 236 239 4 233 + 257 2 77 255 2 15 254 2 25 + 256 2 76 257 2 77 254 2 25 + 262 2 85 267 2 83 266 2 82 + 263 2 84 262 2 85 266 2 82 + 244 3 67 242 3 200 274 3 229 + 255 3 230 244 3 67 274 3 229 + 262 3 235 276 3 233 243 3 6 + 245 3 234 262 3 235 243 3 6 + 254 4 235 287 4 233 283 4 6 + 285 4 234 254 4 235 283 4 6 + 284 4 67 282 4 200 289 4 229 + 263 4 230 284 4 67 289 4 229 + 219 4 236 289 4 229 287 4 233 + 213 4 237 219 4 236 287 4 233 + 218 3 237 212 3 236 274 3 229 + 276 3 233 218 3 237 274 3 229 + 330 2 216 257 2 77 256 2 76 + 331 2 215 330 2 216 256 2 76 + 337 2 35 266 2 82 267 2 83 + 336 2 13 337 2 35 267 2 83 + </p> + </triangles> + </mesh> + </geometry> + </library_geometries> + <library_visual_scenes> + <visual_scene id="RootNode" name="RootNode"> + <node id="DemoRoomLrg_5c1b8cbb" name="DemoRoomLrg_5c1b8cbb"> + <instance_geometry url="#DemoRoomLrg_5c1b8cbb-lib"> + <bind_material> + <technique_common> + <instance_material symbol="BLACK" target="#BLACK" /> + <instance_material symbol="FULL128X128G" target="#FULL128X128G" /> + <instance_material symbol="PILLAR128X128G" target="#PILLAR128X128G" /> + <instance_material symbol="FULL64X64G" target="#FULL64X64G" /> + </technique_common> + </bind_material> + </instance_geometry> + </node> + </visual_scene> + </library_visual_scenes> + <scene> + <instance_visual_scene url="#RootNode" /> + </scene> +</COLLADA> diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/Door.dae b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/Door.dae new file mode 100644 index 000000000..b930cea65 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/Door.dae @@ -0,0 +1,219 @@ +<?xml version="1.0" encoding="utf-8" ?> +<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.0"> + <asset> + <contributor> + <author /> + <authoring_tool>Torque 3D 2009 Interior Exporter</authoring_tool> + <comments /> + </contributor> + <created>8/09/2009 2:52:45 PM</created> + <modified>8/09/2009 2:52:45 PM</modified> + <revision /> + <title /> + <subject /> + <keywords /> + <unit meter="1.000000" /> + <up_axis>Z_UP</up_axis> + </asset> + <library_images> + <image id="PILLAR128X128G-Diffuse" name="PILLAR128X128G-Diffuse"> + <init_from>file://PILLAR128X128G.png</init_from> + </image> + <image id="FULL128X128G-Diffuse" name="FULL128X128G-Diffuse"> + <init_from>file://FULL128X128G.png</init_from> + </image> + <image id="BLACK-Diffuse" name="BLACK-Diffuse"> + <init_from>file://BLACK.png</init_from> + </image> + </library_images> + <library_materials> + <material id="PILLAR128X128G" name="PILLAR128X128G"> + <instance_effect url="#PILLAR128X128G-fx" /> + </material> + <material id="FULL128X128G" name="FULL128X128G"> + <instance_effect url="#FULL128X128G-fx" /> + </material> + <material id="BLACK" name="BLACK"> + <instance_effect url="#BLACK-fx" /> + </material> + </library_materials> + <library_effects> + <effect id="PILLAR128X128G-fx" name="PILLAR128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="PILLAR128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="FULL128X128G-fx" name="FULL128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="FULL128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="BLACK-fx" name="BLACK-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="BLACK-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + </library_effects> + <library_geometries> + <geometry id="Door-lib" name="DoorMesh"> + <mesh> + <source id="Door-Position"> + <float_array id="Door-Position-array" count="24"> + 2.0000 -0.2500 -2.0000 + 2.0000 -0.2500 2.0000 + 2.0000 0.2500 -2.0000 + 2.0000 0.2500 2.0000 + -2.0000 -0.2500 -2.0000 + -2.0000 0.2500 -2.0000 + -2.0000 -0.2500 2.0000 + -2.0000 0.2500 2.0000 + </float_array> + <technique_common> + <accessor source="#Door-Position-array" count="8" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="Door-Normal"> + <float_array id="Door-Normal-array" count="18"> + 1.0000 -0.0000 -0.0000 + -1.0000 -0.0000 -0.0000 + -0.0000 1.0000 -0.0000 + -0.0000 -1.0000 -0.0000 + -0.0000 -0.0000 1.0000 + -0.0000 -0.0000 -1.0000 + </float_array> + <technique_common> + <accessor source="#Door-Normal-array" count="6" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="Door-UV0"> + <float_array id="Door-UV0-array" count="28"> + 5.7500 0.0000 + 5.7500 1.0000 + 6.0000 0.0000 + 6.0000 1.0000 + -5.7500 0.0000 + -6.0000 0.0000 + -5.7500 1.0000 + -6.0000 1.0000 + 1.0000 0.0000 + 0.0000 0.0000 + 1.0000 1.0000 + 0.0000 1.0000 + 8.0000 0.0000 + 8.0000 1.0000 + </float_array> + <technique_common> + <accessor source="#Door-UV0-array" count="14" stride="2"> + <param name="S" type="float" /> + <param name="T" type="float" /> + </accessor> + </technique_common> + </source> + <vertices id="Door-Vertex"> + <input semantic="POSITION" source="#Door-Position" /> + </vertices> + <triangles material="PILLAR128X128G" count="4"> + <input semantic="VERTEX" offset="0" source="#Door-Vertex" /> + <input semantic="NORMAL" offset="1" source="#Door-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#Door-UV0" /> + <p> + 3 0 3 1 0 1 0 0 0 + 2 0 2 3 0 3 0 0 0 + 7 1 7 5 1 5 4 1 4 + 6 1 6 7 1 7 4 1 4 + </p> + </triangles> + <triangles material="FULL128X128G" count="4"> + <input semantic="VERTEX" offset="0" source="#Door-Vertex" /> + <input semantic="NORMAL" offset="1" source="#Door-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#Door-UV0" /> + <p> + 3 2 11 2 2 9 5 2 8 + 7 2 10 3 2 11 5 2 8 + 1 3 10 6 3 11 4 3 9 + 0 3 8 1 3 10 4 3 9 + </p> + </triangles> + <triangles material="BLACK" count="4"> + <input semantic="VERTEX" offset="0" source="#Door-Vertex" /> + <input semantic="NORMAL" offset="1" source="#Door-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#Door-UV0" /> + <p> + 3 4 13 7 4 11 6 4 9 + 1 4 12 3 4 13 6 4 9 + 2 5 11 0 5 9 4 5 12 + 5 5 13 2 5 11 4 5 12 + </p> + </triangles> + </mesh> + </geometry> + </library_geometries> + <library_visual_scenes> + <visual_scene id="RootNode" name="RootNode"> + <node id="Door" name="Door"> + <instance_geometry url="#Door-lib"> + <bind_material> + <technique_common> + <instance_material symbol="PILLAR128X128G" target="#PILLAR128X128G" /> + <instance_material symbol="FULL128X128G" target="#FULL128X128G" /> + <instance_material symbol="BLACK" target="#BLACK" /> + </technique_common> + </bind_material> + </instance_geometry> + </node> + </visual_scene> + </library_visual_scenes> + <scene> + <instance_visual_scene url="#RootNode" /> + </scene> +</COLLADA> diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/ElevatorPlatform.dae b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/ElevatorPlatform.dae new file mode 100644 index 000000000..2aaf2649f --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/ElevatorPlatform.dae @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8" ?> +<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.0"> + <asset> + <contributor> + <author /> + <authoring_tool>Torque 3D 2009 Interior Exporter</authoring_tool> + <comments /> + </contributor> + <created>12/09/2009 9:50:04 AM</created> + <modified>12/09/2009 9:50:04 AM</modified> + <revision /> + <title /> + <subject /> + <keywords /> + <unit meter="1.000000" /> + <up_axis>Z_UP</up_axis> + </asset> + <library_images> + <image id="DemoRoomLrg_PILLAR128X128G-Diffuse" name="DemoRoomLrg_PILLAR128X128G-Diffuse"> + <init_from>file://PILLAR128X128G.png</init_from> + </image> + <image id="DemoRoomLrg_FULL128X128G-Diffuse" name="DemoRoomLrg_FULL128X128G-Diffuse"> + <init_from>file://FULL128X128G.png</init_from> + </image> + </library_images> + <library_materials> + <material id="DemoRoomLrg_PILLAR128X128G" name="DemoRoomLrg_PILLAR128X128G"> + <instance_effect url="#DemoRoomLrg_PILLAR128X128G-fx" /> + </material> + <material id="DemoRoomLrg_FULL128X128G" name="DemoRoomLrg_FULL128X128G"> + <instance_effect url="#DemoRoomLrg_FULL128X128G-fx" /> + </material> + </library_materials> + <library_effects> + <effect id="DemoRoomLrg_PILLAR128X128G-fx" name="DemoRoomLrg_PILLAR128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="DemoRoomLrg_PILLAR128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + <effect id="DemoRoomLrg_FULL128X128G-fx" name="DemoRoomLrg_FULL128X128G-fx"> + <profile_COMMON> + <technique sid="standard"> + <phong> + <diffuse> + <texture texture="DemoRoomLrg_FULL128X128G-Diffuse" texcoord="CHANNEL0"> + <extra> + <technique profile="MAYA"> + <wrapU sid="wrapU0">TRUE</wrapU> + <wrapV sid="wrapV0">TRUE</wrapV> + <blend_mode>ADD</blend_mode> + </technique> + </extra> + </texture> + </diffuse> + </phong> + </technique> + </profile_COMMON> + </effect> + </library_effects> + <library_geometries> + <geometry id="ElevatorPlatform_5c1b8cbb-lib" name="ElevatorPlatform_5c1b8cbbMesh"> + <mesh> + <source id="ElevatorPlatform_5c1b8cbb-Position"> + <float_array id="ElevatorPlatform_5c1b8cbb-Position-array" count="24"> + 2.0000 -1.7500 -0.2500 + 2.0000 -1.7500 0.2500 + 2.0000 1.7500 -0.2500 + 2.0000 1.7500 0.2500 + -2.0000 -1.7500 -0.2500 + -2.0000 1.7500 -0.2500 + -2.0000 -1.7500 0.2500 + -2.0000 1.7500 0.2500 + </float_array> + <technique_common> + <accessor source="#ElevatorPlatform_5c1b8cbb-Position-array" count="8" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="ElevatorPlatform_5c1b8cbb-Normal"> + <float_array id="ElevatorPlatform_5c1b8cbb-Normal-array" count="18"> + 1.0000 -0.0000 -0.0000 + -1.0000 -0.0000 -0.0000 + -0.0000 1.0000 -0.0000 + -0.0000 -1.0000 -0.0000 + -0.0000 -0.0000 1.0000 + -0.0000 -0.0000 -1.0000 + </float_array> + <technique_common> + <accessor source="#ElevatorPlatform_5c1b8cbb-Normal-array" count="6" stride="3"> + <param name="X" type="float" /> + <param name="Y" type="float" /> + <param name="Z" type="float" /> + </accessor> + </technique_common> + </source> + <source id="ElevatorPlatform_5c1b8cbb-UV0"> + <float_array id="ElevatorPlatform_5c1b8cbb-UV0-array" count="16"> + 3.2500 -1.0000 + 3.0000 -1.0000 + 3.2500 0.0000 + 3.0000 0.0000 + 0.0000 -1.0000 + 0.0000 0.0000 + 1.0000 -1.0000 + 1.0000 0.0000 + </float_array> + <technique_common> + <accessor source="#ElevatorPlatform_5c1b8cbb-UV0-array" count="8" stride="2"> + <param name="S" type="float" /> + <param name="T" type="float" /> + </accessor> + </technique_common> + </source> + <vertices id="ElevatorPlatform_5c1b8cbb-Vertex"> + <input semantic="POSITION" source="#ElevatorPlatform_5c1b8cbb-Position" /> + </vertices> + <triangles material="DemoRoomLrg_PILLAR128X128G" count="8"> + <input semantic="VERTEX" offset="0" source="#ElevatorPlatform_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#ElevatorPlatform_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#ElevatorPlatform_5c1b8cbb-UV0" /> + <p> + 3 0 3 1 0 1 0 0 0 + 2 0 2 3 0 3 0 0 0 + 7 1 1 5 1 0 4 1 2 + 6 1 3 7 1 1 4 1 2 + 3 2 1 2 2 0 5 2 2 + 7 2 3 3 2 1 5 2 2 + 1 3 3 6 3 1 4 3 0 + 0 3 2 1 3 3 4 3 0 + </p> + </triangles> + <triangles material="DemoRoomLrg_FULL128X128G" count="4"> + <input semantic="VERTEX" offset="0" source="#ElevatorPlatform_5c1b8cbb-Vertex" /> + <input semantic="NORMAL" offset="1" source="#ElevatorPlatform_5c1b8cbb-Normal" /> + <input semantic="TEXCOORD" offset="2" set="0" source="#ElevatorPlatform_5c1b8cbb-UV0" /> + <p> + 3 4 7 7 4 5 6 4 4 + 1 4 6 3 4 7 6 4 4 + 2 5 5 0 5 4 4 5 6 + 5 5 7 2 5 5 4 5 6 + </p> + </triangles> + </mesh> + </geometry> + </library_geometries> + <library_visual_scenes> + <visual_scene id="RootNode" name="RootNode"> + <node id="ElevatorPlatform_5c1b8cbb" name="ElevatorPlatform_5c1b8cbb"> + <instance_geometry url="#ElevatorPlatform_5c1b8cbb-lib"> + <bind_material> + <technique_common> + <instance_material symbol="DemoRoomLrg_PILLAR128X128G" target="#DemoRoomLrg_PILLAR128X128G" /> + <instance_material symbol="DemoRoomLrg_FULL128X128G" target="#DemoRoomLrg_FULL128X128G" /> + </technique_common> + </bind_material> + </instance_geometry> + </node> + </visual_scene> + </library_visual_scenes> + <scene> + <instance_visual_scene url="#RootNode" /> + </scene> +</COLLADA> diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL128X128G.png b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL128X128G.png new file mode 100644 index 0000000000000000000000000000000000000000..58008eae0478132e711c6b31506cc6c2c40591fd GIT binary patch literal 3266 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 Gbo*Zw?EyRh literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL64X64G.png b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/FULL64X64G.png new file mode 100644 index 0000000000000000000000000000000000000000..ac26d2b72f436c91341e925f35dd13193a164847 GIT binary patch literal 2952 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/PILLAR128X128G.png b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/PILLAR128X128G.png new file mode 100644 index 0000000000000000000000000000000000000000..9e570122d3a2724eec87db085b3830ecd8cbfae0 GIT binary patch literal 4917 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/materials.cs b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/materials.cs new file mode 100644 index 000000000..c316237c6 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/art/shapes/VervePathTutorial/materials.cs @@ -0,0 +1,179 @@ +//--- Door.dae MATERIALS BEGIN --- +singleton Material(Door_PILLAR128X128G) +{ + mapTo = "PILLAR128X128G"; + + diffuseMap[0] = "PILLAR128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(Door_FULL128X128G) +{ + mapTo = "FULL128X128G"; + + diffuseMap[0] = "FULL128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(Door_BLACK) +{ + mapTo = "BLACK"; + + diffuseMap[0] = "BLACK"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +//--- Door.dae MATERIALS END --- + +//--- DemoRoomLrg.dae MATERIALS BEGIN --- +singleton Material(DemoRoomLrg_BLACK) +{ + mapTo = "BLACK"; + + diffuseMap[0] = "BLACK"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(DemoRoomLrg_FULL128X128G) +{ + mapTo = "FULL128X128G"; + + diffuseMap[0] = "FULL128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(DemoRoomLrg_PILLAR128X128G) +{ + mapTo = "PILLAR128X128G"; + + diffuseMap[0] = "PILLAR128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(DemoRoomLrg_FULL64X64G) +{ + mapTo = "FULL64X64G"; + + diffuseMap[0] = "FULL64X64G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +//--- DemoRoomLrg.dae MATERIALS END --- +//--- ElevatorPlatform.dae MATERIALS BEGIN --- +singleton Material(ElevatorPlatform_DemoRoomLrg_PILLAR128X128G) +{ + mapTo = "DemoRoomLrg_PILLAR128X128G"; + + diffuseMap[0] = "PILLAR128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +singleton Material(ElevatorPlatform_DemoRoomLrg_FULL128X128G) +{ + mapTo = "DemoRoomLrg_FULL128X128G"; + + diffuseMap[0] = "FULL128X128G"; + normalMap[0] = ""; + specularMap[0] = ""; + + diffuseColor[0] = "1 1 1 1"; + specular[0] = "1 1 1 1"; + specularPower[0] = 8; + pixelSpecular[0] = false; + emissive[0] = false; + + doubleSided = false; + translucent = false; + translucentBlendOp = "None"; +}; + +//--- ElevatorPlatform.dae MATERIALS END --- + diff --git a/Templates/BaseGame/game/data/Verve/art/shapes/actors/Soldier/soldier_rigged.dts b/Templates/BaseGame/game/data/Verve/art/shapes/actors/Soldier/soldier_rigged.dts new file mode 100644 index 0000000000000000000000000000000000000000..8ca481f9041a18dd06fc552de64479f07961b869 GIT binary patch literal 2237151 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%0AV~qU`oeMU=lZs)%w$J9Sak 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Π_Gk8tSB>vyyudjBNiBQc%%tpQ2ItNjLCt8K)ueEXF2 zmL_4>B_=%adO+&vJT%ic;6Ht%zcqer1K!zHpYPy!ivBOnMto3Rk3YFNiOdU2#C1b; z`S}qW$(wE)a8*H9e&Z#3GHy^JZuPSZKYD9VV)aciW^?AI=<~VJdu4qtCE}Csy7Gq( z=g5NhZ@|^AhWtc}tcooWn{ZnjBVOf{L1n-Ejkv(bjBh6KlJ)Pg8Ta{a&Kp;G$;O)~ z;=jqM2M^_?<bzcb4t{LLzl}RVde$pm$4||y`TJW8$>7Lj{BnU6PwxnkudzwEGRcY$ z_!L95OOx>6{?>ea;0AJ|BpEAR@6I<HdVn0@HsFQby7Q0VB)M+20dFWU;B{UnkjB-C zIJ8oqH^|#eo;^vx^jSc@qj5hn#v>80AEVD#t4T=AwgiQk&3SmwkjFV6WG&}XtRx0} z=BR_RX73Vka*PS@(_xKl$h8f4u#pMRFJDmk<>CfB<DmurwW37!BWM$Tbj6Z)96Lxh zxf^|dJ98b`>&4D9JLl}RW9NarcI?cs*NB}l_Ij~%$gZ>3j^zTI&+>xh4$B30=2<SV zykm9#zr2;ze^%RB-(+=_^;TAs|0{>}WmYFy?`Cz6^>^0ySv_R6qFS#fAGF+%1o>~q z9ejK8hVjWHaf70Uuo}f`2+MI+(^@Yz;H&b_l3VLGC~*IXo*qA9{${EVi3;5BP}!AV z7-CPHe<vt#pXE54lX*g)54n^nGg^>{S?*Vt8}Z-QO+Fkoexm~4FI=+VwK-$iu@^}S zd}sI0a+&2UiwVnFc8@G)**&tH{jdJnbvB>nFS{?6zwEwP{(3ck21hSyLCKCxoHpb= z#A>t$&7Ik}q=y~vcH=Tx(?1FuHnZhNB_1Oy!z1yHi`IPkgyZD;wJ3a8sTUthfAeV3 z=4dRDTJe40I4MHw@XUyweCr9<Nwv;;{Nh6oKDa{`X`dU7ZD*VDFDGS?>V@lZY;SY^ zLJ&{(w}`>`eRtj=Z3`)_j>RS|jCr*DFd+_cIK0}HKheye+<X#=tNPmTKIeCm3#L(c z%1>K<>B>w}uzM}uch;USsqrU$nytmdzxU+7J1rtBcSU2j7v_A3##&N&WIguNG3J-} zM-a!$vH0;hJ3i0vv+SL2Bo57X;5GUCvX}7@SSQbv@9f!|Ydjr-UBgWIW2d~i@+qOX zVVW`TVLyU<`78vF@-X2oi)^^XGeQ*B+59dICj5y56FGnVFdS@Y%r8!w!KoUBVbv?n z{Mjz_{%O1QxU0Dv-@?C$Javo4ry3pj5T&c6&>|XFoa@c6yK|Y$h+l_)mpbwT_v|AF zf5hOLa9h5n<24f5GX|fJ>&>UW+eem<kH;C2^jhd#A=UI<f@>pt@ekeilEp=dc$jk! zzT2QGaxN(WYumZ;mwL}3ZLhDxyI)E9np1Pgl?ze$fSL>c=*m)(rxJ@-=sNN{*RLiz z^W*WIT01_yB8+@GMg7snjZgolLAES-9sPbr$`2;*Wf{d$_(K~P{@3f@GLuO$xWL_! zKipoOtj&(YmtWiQozq$q-?oW3V1^6tV4*IH{}_!&_HpA4=iaF7u`~)#o8-jr8m1?+ z9=9HETVv1PUaKv;F)kM0dv3#DzN9AGdo&)~ezxG(&*~wy-5HC63at6=(;rEeHIK!) zCoTBUBPp&=FUDiX<#zn~1CJ!F(%0kDbyoa9=Ll)mjdi$1y$$d6evmZlP&D?;=*=sA zH<xs}5s9Z#oD=+#T^ll^==-wl`C)|{B}4v+#>Hl~{P0a%C8r&tF!8eFUxnvYYB!6- zS)Qi+tVQ9KMhTJF<cJBsXUKAy&&eokde?$KH}{zAa7`qhS8vQ8UK%AmGbjSbee2Gz z9!R8X-bdg-M`Qlm>N}F0*-<#i*pi>sm?xbwDgqDwV#de5ijbzXj=+cAtohkin<dvL zM`D$DOTJ~VXHuVs5m=_vlV7}hp|rGR6ppO2<X?U)md@T6g}3Qh@P`w%xti#;|CwK# zV8qXCrojzLUyHMCO!-1E<i6Cb#Xfar{N}rtq!+npY=}+xqr20j&wfTJ^vU-B$jOpF zqjH)424^f*on^|`9X~^U7{}w#7zcjQ^p29uo{_i}IPsHbmAG}@5{Vn%I`Y#j@3@t0 zTZ;#ua^YRFr@Jk*T8m#^?Zd}}?yEe~bqRLg;K9GTd%N<@o5eT=Jb0I@6J)zjFUFUg z`|`JZLS&V7i*dlQe!TM=BU09C5zg4qmtPiRNwjY*#B)OW@~=JV^gUjPKfmwC-&Y<> zmVQ}CzyI{$Uvx?&M>j6PFdy^#9&IL{beCe?Ak6b~Gs*hz^t^TM{2iqnLUt{|{k1qg zVc#v{aB(^2hjV=RtTW_!!*X1EL&A>@uOi>(uE0<BN%%$UuaaTYR^VGV?D=^Omx){T zT5RQQ&-blAPK138o$bn-zAq=Ut0HkqgA*UeUnQ%LM&b~V^0!8Xl0hva@i-$1U)VQ` zn68Y(zb|wA)pnZncPQ85Ut2i-=91AQ^v+s*{H=sPG@z`q?7&*=@kYw;GB1(!d!UFR zi>?1h2mbh5hsqQ0BJi6SXTI&!v6Z*$!?E<OGw+*~E8ChJj(g2^;kzLf@@suKKC;M# zzZN-!`0WX&TyW;|l$R5w#&A3`&ym-ewS#<I6@e2EIrFD1is}2D*WxRIF8s$`c_h@H z>Z+E6&)q(sG}7N5>gg-tZ7nAe<>3+d*$4?ASoJ~X+Ajis`R&HnnO~4i>l1-@gFB!1 zc!g|Ed>Fng<M=%j_Q{gmLvg@(ci!N$LuF!M7(S{g;oZ9(sMt9u1a~ds_~R(st?o=H zKK{v#x2TVoSzHOm+1P`h>Fz~>)WdMuEW|$vo=z5S3Bg@Xc<?pbTM?ayq4+~DDZi+L z4(VeOjBl4BzV6j$S?$aah2Em0q`b;lUov=nFuodq`Ldlm$+}-*xOqn@-|l1qIqw~Y zv!7w!u>E>s{vb?Yzq-ra_(GK^vh+Nyd7k4{Pb??Sox|w0bLHo)+DW_&Lb3WyXTIF= z0oh_5j;C8W@%aZY5asMJ?BpTg6E58$<aane)m_SO(K$w191q8(108tV<O8ITUOU?? zC;r8~!{qR$Fnng4EB|xcVfx)mxWcti_4VM#IZlz~D~DkF7MS1gd$+7b_!=DU>cKCJ zHLmRWCKyj|&+%UUoh$IBRXEEK^O_#2lH(C;@VPda@83T{=3TS`_o2sjo7biirLDjN zJ97NA<VczK>{Yn_s|UaGu_w83U=42B)17~OV>(%SXchJt(}zELQJXluT7#b)MSMvs zUDEGJAf8(9&QFiiCj-VV!|qS}@GCyIB5rG!<K<J_`Nad2NX^Gpc<nuRewOnXGGN0p zY}+35%NLCyJFW-f!nW@G<#U;2#Pwi&@*&6DZ73ikp0CCa?z{6BX2lWiV=x|cLCX8u z$B;pJt8i)};+It<k_*RI;#1-7ywc=Ia&2`Wc2>sxKcm9Pk#TEqo9`Sy^Kv$szGNld z;UndBN9-m)!dBs{8E!o3dXH>hxC+}GbK~_I&XVWxtMGAmSKdW>f-F21jALH7@Tqrh zl1(>)vCSkYA9C>lNnH_!yMK1&+s=4KhP(^GYraVNCBY{M84-p@Y?1Oi9`NLt$7<Zs zP{L<zl9BxvL+~~;55DZ{cG;Y_EAd^QzWm8qQ)HuR0`c1weR+dfezE|=6}W{{AO6?> zF?Q8aRW{GxMny>l6a@)U0Ywo5xH|)gU5H{}f(3$w0TvCSAcBF2h234m-F<Aqzyibq z`_<R(*53o(>pS;*j_3UNYtEk8+1dH*&g|#mKF|8EQtmrH9qVupX>iw++@yCi<h!~& zB=NpU?xjOv=*``vtV82nGM0v-i>sT|ZB1&fUC=b_7vnA+k87V}zHK_L&y-_3Fj854 z{4_L6^OWkY?8`Uynu+#ZI!ou3-u%?YX*hdFCn=+394{Rhg8$lhNJpQI<$CcmaHVr+ zDLcW6FOHsuH(q&4k=GjYq4Q?qL~jo%ZC4ZC&UPy5Wp$En)~e4N)(gSu!#pJEUVpwT zU@C4bbC)s(Y~~NOXW>jE56KfY@w(|V(Q}BKWbL+#Z=Ey)2d_jqSM285_F<TH-b1>b zwwQm<orx_E%k#aJ#2rm%Vc=bmTw+uCZsQr4cf?IP_c4wSI6MQtT?Q#=|0aI$;&g0a z>MBiWb)Db;Hx#`(x=IPX@_FSS@)~FkQvT91o}W4wk8A>|;q*Iv>Y7>TwoD;)e|wLQ z^$WunRtl+f(If8NU=AKF2C3)$Gkom6S=h1wq^gI`@URVY(eI~1dT{JGzqTw4f3@?J zR)-H(-u@n<QG>iscaj{OZ|64GorYiAb&+a@^y9~COx376{77dBo;BxpUQNNrF&@(7 zY3uopQPVVPO-6}_)W$r8*BLYo<F0~K#kGXje>+p723fuXsZv5dZ{Ii+=`)1=pX{Y6 z6ZY}2h!iZ_-AtPD_6)a{xj%ijpnKC&8f<)o3%*F>S%H4DCX!Tr6rY!xr14CEJ~zmC z)<g=hTF&neUW7X*H<1#p<U1yVlaM|Wxb)dZ`hKdu^3$|rtmkeona&SWCQZ<M4nUt3 z&}SOh%Ry2`HRR2LQqaoTL9%g)=kuPYXguq<Hq=7O@_D1UJ|PN^j*!pTA1)|7mPX=; zLCvM7GwZTVK2g|VM>FZxo+k>Ugh-6CXeJrCS~9&M(Hc67(NenXP@jc|L?gAC|I$*5 zI9rPqw2i<uXd&6VHexM(BeBbcrqbvy7Znk5{;#*!Mv|h8S>^5#7*)HeG}};{jg{{% z)U|0QwJB`HR{BR`ps|hgs5`R2_E8$`Egx7&^_#S3OXc<w`5dVI0$FHu6fViMmTV4N zv&uYLW88P=EhX(I&Dp_>aO{52Lb_Dw#%{Naz~jjl(*4!GtX6|ajdnJtrSy4U6aGv7 zjTt>h(K8Y~|IqUct>d(I(|S#7G_A$7=F-|q>n5#<w0_Y#Me7l*FSK6JIzsCL&GR(h z(mYIaFU_$um(u)6^C8WXH1E+oM)Mo3K{R*Kd}8{=L2@f=oBL{TEH=%zlKyerlABqU zh<7JgOaIhKa$WRhfyVxFnqetb@|maf?Ys!T$vP>ETom7b&X>7%bLo1=bjA0O1Wdhe zA?4Vo@ttW&_;Zw{<TQE*f43_MO%_{7(z;mgT{{Wuw6u~wuMOb4@)lx`!IsjL?Oyzm z|3X|e#ZuaJ&s6ENApuVxvyf`9Uaagmej#doY9U#TY07Qy#o@98Hj>LSZ=Sq&KAyLi z_g(fF9ydHeBPTq&+eCW4^PzIa{zPnNYbA|{dzEwMt0uRi9BSxEM@i?=?A+%vH>Z5z z(qU_<UPL3_xbb`qJJip>N><X7ol2!a{CuS2Hj1#2jy*TyXIC%4sCgFB@E66(GYuAK z%!@v=8g}iRc%-N)LT_i{&!acR>CNWCe(Xl1&pP}apNPx8W}-uae2*1*?s5C;YvG+z zOSl(r*ZAMfqo&71hsy>6E^NT311^j9LAJvA;AZ5v?uajqTZrpo8*VXuEFL7(7oNtu zu&Hj2m^s>1?DN@zx$RDhWz+4%l&9Np*N00Yw34m(lDQLOt!{|5BO8hBM!T_c$YHUi ztD*2t-->MqXNmVARwDHJPPAJu_nl`U^iB8Rn)XHFP_~}%kKd#5e>(dAKKg%2`W%w} zkCOf`jE<%8zccbbHR=QPliH!a(Xk#Gb%$N|8p7DkQJBA@HMBiY1(;qGT4p-HfZ<i4 z)#E6fZ`%dh-);bR1EX=3R)1JtWDPFM;?TN%A87T^0<2%h;mQUBAY-8o9K5&`p=w_^ zw9gWP_b<imr~AXgoTe~ATJcw%(?xy3vcLj92>Jfgwd3IaO@j)3+L!7K-|i1r|IvZ- zvi`4>(NL{{4vdk<8ai=2IJY!}jj|8a4%I(uHUaiH8H4T475Le5Fs$m>0t$Alz!ffo zVUl+X=;OXj!%vqE6Tr5&F@W4o?NfO`&RAG!X#gg2OsGGPPWr=b`MnZ*IX)TLL*Z(x zniX-*i|GU#*Ojr}a-3tce8I!BdPQvYT6=<X;vM!%j``IuGhoY?FU))NG8|qb1b(!A zC;uKh9+#hRfn%Rr!)sagYX%VcuM?E(JjyhO(~>?EG?brFyfTG<?&`zl*79?SXB|Li zq8+SgFW*x<D;NeOzF_6@qB3tt-F29i>zEz$h729fisimkrZ%ZQwLj;MHzYUT&kS{! zVfX&iAi?bw`?z8ivK{>)dG=m*ZtE&MuABu8ld6Hyv1O=O77EoYD#Mnn)z~+yGo0Gq z5jx84zjil(V`chKZpZGr2~^o_0OfsS@;gFG7e^?!IiQyZJc@2#(YI-S5X|5&Sz(>^ zm}@v5EUw*U(Jt$-YivgdR@y>&`|hdzVEc}}tXE<t2EA_z{n{A8g)8e(=cNgZn63xq z?Np~}he2?ES3Z06KRTC^+CW@w8z{H$)BgqQ-=bdyjtd`NW-UwGRO}a{*#&HxxnsqC z*_!r*9kA_NfoXQ}XO>@UM8(>;@#GClNf=VG9;&VS!ajc)S+QU0Uw_N0rutUw7Yq4& z%uOstg1@|9{-#r>@&^{G<y)~|@*35L+ARiD>=)XX>ioK506O}8;e@<jHoiB6#vA)o z?3WeC>%;To11k0lwL|simKi~p<RQ>N-Y-|}elfk0(V#EO=7WE+G1_A)_6zk>|B(^o z$=}^6-!IfYmA@^h2QORpuZRit$0XbkhGg`vh|kJg9oX2fOGTV-pRELbFKnQEztk<# zf$54)6|wzxx-#(AHc-A_a?uX%Id-nt3wkG;!?jE|DBmwXubf~94vnhVFUCX9usJKo zR_K`fY+-I?&K3LR`@nVV%<hgA`{l%p<IFL}w_?BKEwhFWRTLF+gOx_G<D5x_PK;fB z*x=X*%J&PEsZFX+?bngNeY1PFQN=p9+G7g`04vsZwtSy;c1xp*HUF=HJ=n@|Fq8L1 zjV^YOwXu7}nolmg!g`$#s@N}w%~!EzWgRN)=zdRU@!lOP`uaHu_PnECh0T$lF0d0R z0Tq4MXIsGnZ$-tvFuG^~T1}lQ)-%^T$>QqyR<z$4U<B7^)vwqWX+QU{C0*Pq_RE>v z4Cd6eeMLLfxng1rXZBb@`F^1~m;AHY^7j2J?925<98}d8xsC{?sv~lJ5x%PWBG(<^ zqN+P`eUX13@~6ItcB=Zaq`?5O{=fPnNPQ8hs`?_=2+=}SN8}pxM~C*6>w<WysxNX~ z5b8QY`^t6ak4-tB%il2nU0<j^wIkO8;ijrPa!nEHnj+U4p{_M4E`!B%RehoU(7tl5 z5p7hpMy@GBT~nwI^+&ER;(@BZEX^J&NPQ9N`Xbj9p{^-%tr6;4bN<T=aY$8PhBgB+ zUsXpIpKuXpRP{x!JEFGJ@48c(X)eyI>dUfc9fZ23$hAPcRMi@}z6ihn>Wf(UUwsi9 z|En*5WNK5cFMsr@O}V~^wEyahSpHvq5oxOWBG(jATUAr!S|cn}wWfQP{GD4>eUa;k zP}dQ;z6f=Fk?W37*PTASJj8QVeK}+}UO1>~id<_%jH=ei^+inkufB-=|J4_vt}k*O z5&x>{h+JR(=*V?PsOyegQ-r#v&~~}La9>q@$w+&`)pbO!FI-(;=03d4om6#4t}mR_ z7oPTCec`0OaCLn#T=|8o>&wqdAGo@X$TjGXj-1c`^gZ6FzEIbfFINnNx{lDk)aL5< zhQeA^U#LE{lXASic&n;Ar|o`mbxo0LjZoJbgTcQzsV{&0p?$R<8HoZ_t$Dwoo>12m zszd$J4>uI*`m!WfN09m=)b&NKDMDRSY82^+IjUMC*B9|bRbO<6p5f{`^6|<EuC6a~ z-4W`#)4*p7SJxLl<2YB>l#c_~adoYc>x+Q@>WkR_UwsjzzWkA?O}W1O(Wf@$`XWeu z5!tHxa$t&yP}i4Vo$Z9Aswr}<5p7hpMy@YhU0;Sc39haqHNU6xMXLI;&wLeE*B$Rq z7r45<=w7rC>Y9>~Z6#7vwdRQ4NlxmEP}i4~pL=+^s=ml|L|jzW5xKtn(K(iz!Ch5# zC(l2dt7{5vZ&B4AeqMXQ4lM61KdUKYraf!IFLw_dI_ejD7^VvyJ-l#wzqVlT{VO{+ zVF2dUn*d!#k5_~$x?{kH0T9wEoef>r6`RcVg-gDxn9H=mxMayB=%ch!<a8f`$%7-< z)(%hDd3P7w^7AgsE&GR!_~D56`bM$WMb}u=k2W~pZU`7RS;W65^uXw|edV*qTweW5 z8yxp&IE0Q_tSHQI#5k)bieEN6S*1zs@X+)pihTFA?9yfj9QeA}b>ow@istv*VBOu_ zVO4Q7Tjt&t_nBJ3rJEO7568B6EUqnlaCpidd>M;_ehmS|{uQiulZhCa69{F(OHs4Z z6zq3xC>S4b<a-uOz|YP@Ab!z&KC;yyyu|9lj-Oi4_wi6{<50}>>V07oEjnRp;ahgc zs48^*)K?=`G=`%JqFKVV0_NlCsu73#w^J3Niz5{Y)7#?Ud0K31=Vh!kxV^?4>AZU7 zwuFnZm)VfG@#uU&J{Lb)%yOzt(wGaKV{rILsAK7^*miab#=PhUEn3;}CIf>s=1Av$ z`eaQgo$--%-8f8RzR?A!n0BEbkBD)^t9>k7?|kjU_1m@4z=&eU4)lSES}D9}YY((- z-33k#oyX70xKJOoCiQ_O5exV~uLo+xna02Fpe3wU&m`6%tsypSWz3ci=*)H|)x%?Z zKPb9Ah-0&>TA@*!`D~!=0e0ePQ#|D11XfErF-2~DtlkizrD6=ze`<|y@AU`$E9(>q ztE_R-WDltE;GhB<>fl(T`-=4es}v)3bg*B@JVo-Pp4`V(AD>r$?>fZQhkIpMVdLU% zikZHP6&7)p7?>%4M<jk7^ZMQhl{Fu*C!Zu15^sZ_Bg`T3>rPgS*<hs_jiKGZL^i#w zp+>A)Zs-N=2K({1*Q_uqy(`p+>B+f^KDMrOPqBFaq};H1)v$;62E{6iHhibC7S1~9 z0TBZo`6hoYyf?`M+y{Toa$j5xj|^PRZ1)(m6)q<DcIhw{*RNF3puV9-d}!Q;H);)! zn73k(JYR=?O`-d-Q;M5L^)zBdW8yHmK+!9yzx)MveH`kZs<>b3!>ff_X~cxaYQn_& zP<KZI_D`4zI@ms72ih<eW8F|ARx~EzTV2?{XKfYp<e1a=uRY_;EMl4~XUcJ)F`@0l zAIRTcDL}qfjt`9$)&H9gjb~(UXNYQ`;G6Wdusl8q@rAi#<=E0V|E-;3M=`A%>JFFp zP2>v_tuWmH;9U<Nu5(i#=~&bU%c}OGPT}u-J5j!ir->@B_8#?%KU3w~L&;@aormRo zD^gYYR?e$pi7Kzk`BvOg<y$!qi@B;iJZ*3UKdj2PMSY{VI>)B}yvx<Ocahx?VW`Tt za*h>iR5@18z2c%O_xf5rQC4gAJKr9BRh+BNu?wa@Q5L9jubgAWZB>qybFbK>%Dr-q z6<t+1R?bVJO6%XbSI#-2iS#?)$~jg<t8%Qo_eC95?#*X)#XeQOwRR}xW~zKkV?tvU zQ}~uYP~~Btf@r>6m2YVrl($or^Hlkk&V|mg^E@rSTa|~q<hB&*d`tbO^OEzhc&f_7 za=sP4RQZ<9k<Lrbfx=pqhv^)}$(rJsD);s(K;<k|zP;DmBKQ7(`SuSka$Xg=s=O-a zTM?kjw-i%47WIL~TxU`rk*vzYl?N^1I;woD-DW-?rpl`sdp{_9tMaW@D`UP&m4|nG zIEnVEd>b&?L)feGs+?~{dsV)b^RVzx<zY9Y`^sIae0#R2n{tjSuZC5BpF2X8Z}mgw zDN|K>SkAY6hbrI7IYhXr^6HxibCIUXw|i<n;ICDAn8r%po5J?Ld@FuN|IW91mF_90 zsPb)V?+wbes(dT&eWBg)caD|!shF(Fy?X|(=IvDZmd1z1p={|ezFd`u<-8$m;CH^I zF`==N^RNh1<>7jh3zU6T`IgR|#>Cw{Rr!x956k&hG*;zX8WS2TIS=y_sys|%K5459 zuax&Y_tH3|oN?xrRk@eSRENf@?}N&GohlDgnd;CO(%6>A$3&HH<=iNy{+EaUv{QXK z-~Pc)&a2{yDzD1<R^+MjEybFSOYPHh%jFTH6lo1N^6-Ie&~xHSMS6B7Pnh9|^qf=r z5MkxPYrN`a&2tVt&peV`q2H?l`9IT+7<|A8)*Dt4f$Q7gy?^RK$oU`K+QAWhTp5eo z{F>LuZG+=)ons9;RTF2nwL$Za7uoWXN@Bf-BRW^@#mtvH<J;x)6+L^@9kW@n*=!4s z(X~eEGo6d;Y8QyPc7d<HVTIIZ>QBcKL)g;oCoj5dh41d1XC9%I#iZ|68val}|B3Ws zOY`6JOY*q%4DiLVK(Q-gBiGHdLh2j!*>$rXL|6U57s+QQle6u>>D*avxYP=%pVS{( zH)%aBdU1jEY4nwUKBVb0^=*^ca8`ZN3;yJ+71F&=^QXhamCCg$d^1LjQf8=dmt!T= z_{um6HI6i|(mE)|Q>gL1`A<Ee#<#C4<4aWdwyoNWt8tX^<*QZrj=pt{o2ziA`<nVp zefvCmvvQXTcR6lCjjtRxaZrUL^@q;o&7JdHjqklkFTP%dBlVN|LvsuDjr#D=u|T;; zg}aQeP~%Jep?=D^i?%A<|F%zMe7PFmb!PG%&1xKp&vY*Axi{1?ZNVExwZRu3{9pq5 z@K?Hi7<nWFrrJcYPN$}0d;eh&^CX_t%xHseEEmC@#4zU2yEPj0PKSe96Io#BG|Yd# z7#74%;6^7$;`{Ll&~_AXPp8&@?Mrp24|FW*109R{K<!W;=v=7%j(dZk&SN*;u+M1x zJa#smF7{(@`c2oEFYQamjm%vNIYYcz^2li#v7+Nzk4l1u^4+&$s6SGfj!W&+cB=o+ zhbS18TUqhNvoF$dsn1l0_NDq%hxVo8QXOiC&Z}#UV6n6E8^!4t_W03egxI;F4=<Oe z;Udv`VJM&L*$Pb^mWh-`>lEekzw-A4^n31CL`|B7wvkIkzSBCznFiA^IweWygopBS z*<(zscpWl{m+REnv`p-Y4rOn6Yg{rcO&I%!vX+hdW3llh@#J+1v+L}Oja~<f)h;RW zH&7ik#x=Z}EWAQPd02QqR32Y0dU~u=l*`ngrmNz`H``0R+`ezAmpHONhnL$itl=%j zf6M0O_ILMB5ItNkaR+%^I$!o7NchBjP&f`8iqGqh5XA#~@p75Qf%;GVq;sJ<TK<bf z`lN8?x@!hLe!fhYu8LrnpG?-6ufdLyVz1{?=5%Tr7Mvd@EUx@gH2*MD!+$z2Iu|;} z>JQ_^&2fdi-2R+e5n|=l^L&x~ySqa+%Y|3oY(B_q9L_RWECMbS@tpXvNcAaR-E;#) z$^6%fChbD;lY{(?qryJCT%Py5kNDT2D=+tr`g!hFAMtKhE^k$BI(AF%Br>-i<>hms zc3g5ti{^FTD^As!i_6B36OC3ZW?e1jV$zEVVnoPdR^FG|Y_(>v7-3V1CES~Xv@f+u z^=S;hH5n=%zDZ&2-_Jp6hw9LAsXw$YojaXl4XbWq%l9n4ZBRHKcs@`#zaGZDT<2-b zz0?SVS;0Pj(J~yVKD9&R+4g8J5u4DP53fECX<r&os!x5RK2SToKdumAb7!+frekoF z(Q4t9nXV{b1No0LL`ct6#ipm;*!a^@aUvv~m&?H~76_v~7kRn<aMLxS>bbeBe4VU| zS|x_8oW+LCAE2=}>6)Z_ipG}Oq3fUS3%YmczNUUsA7~z+{!<@v!WM}$<FE5_pXr*X z?Gy{zPW`7jjqWLm1)Uegi>^27Kizi`_lFAOMgJ<&Jmla1zvwIswT~-qPD{jp7P*QK zBcj-Do`{X)?=nTtPGZw*%I{S@^%CDsyi<5}h{YbAUB$Q|rxnL1Cu;PiHmy3f7FXVc zRoJ2W)XpH$Tbvl4$o#&^?_!W~X<w>C{rNbkfoL4Em_J{bh-rmRVzzw7D3{w;?;+AR z_vDsS<FLb2N744e7JdWbF<^BI5$c}7zqW|SI-~W)ubcBK^r;=Hf8dUrxG>v^HytW} ztFX*oxEa)}(5HQ=P3i;Hr*^1s4eb}fX@j+jZgE~%zgHSmvQ1PpIUIvu?UupYg|l-r zO(QX$B|&ueS2@0sUT7A(0G7OI#phKWfrj1ZL)MjA{8+jd+8Zx`Sgjp7^EP<lyeWyW zZ1o_eeU=|OYNvqtnXb8Q!e(peP@8ltw^_*myel(L^1`(A6`*VYEFmifnPLIxcCC`T zbYLW|o|^z8N}lD6wV#WpXD5T7ONZPB9&_;3kZ7>httQUB3&Ryp=0l_E)kQ&87*_7P z5S|@)$7|Mz#)isR_>}*K->{07^KdkbZvBBDxiJ&{`@}**iYH$&T7GvXVj)E5c*-v+ zO~%n{6X1u-M}DJqD7G7z1PvZCUUqCUx&|jgiN^rt{Ifxr+HMi#^d6!#kuN%YojM<O zoIa{NU^W+rMJ$55xfhg=o#trxN&Tm>qIRf#w_%BJ*epX~_&P=dBO0H)ZAox(Q)j00 zPE&{W-7eoRI4$-zAMzs#t6ocjnT^VL?bs;He4h;3$4ix)yk_HBzc?6OP{OssqA@yn zA@tq!fv;a5su71)wh7=C`<Z|F9EvS6qTzAcM?TvrOe3BHzQ@8GkGs6>sVMYIUI>lt z?{k|iQAmBDV^M$TxbiQ4AnZanWsTKANM+NlG0?V+hw?#ff26W+ZWMf9(So-eGD2gm z(l}Ecn@SOIA+(zOyK66v^-R|}U6U&o#6UmyzAUXuKcq3ISkN_3Wr{D2IbBzOi^Iy5 zlc2k`Qjs*JA3n<shKRy9E}237uq1shJU(fj-AR5&W?^t7+;H8lIB6S;4<1Z|qfEY^ zZ^sC<RE9#E3--#LBmMDm&1tYHW|zy)?)}hi(quU8`cvub)(`K5MMC8k53~20&(W|+ z$D)0Qx19?0&kSVaLi?e1b`<Qf?9J?3$?y7giH0B5Jaha`&%u4(;owmEihp#E#;a+w zz@br9F|_q8^ezhnOYOJ(-a+|HwP7w?^;K}sUz5={VHUJ$-Ifmtn1WNg%mKf7t(41O z2BS?_IJ7zDsLbpUtYLp<_bAx+HdpDIHAiEPRG-?Re$rS`IUd8o!n=f5#c14rDjcd0 z$yZu_o{iyAvtjCq8~ptBD13Qn28`|Tnwxf)-$@~JajG{PX6%2@*G~yUYA3QV9R3+p z%In^b`l}s^5yg(m6tBO<pW;Ym8V5Qr8uP!+k?vo*uW2r&GR?Pt>q}!o*9n!WO*$^^ zOJh#g7?r8bzxAbgjMfn<Q=4>L+Lz`=T7#%eZT_t<jT?<8m8nfS?%drIVcg0c%9$}E z@oxW6*!{U0E7J|Yn;)jbjon(T#g`ELcwsWk{JKGD_c#PS8wNlt%Xnqw{v(n0r8+;> zj)e}Vqm|z-YwFW>-$z04akwGVx*vjuQ>Q`)Cu26DY`lg{b*MkoPvfS;VNcVoN-KG< z<t-iyowjMQUdd6Y^T{1nnSWEb>m*?fCj}@golrVwB;tbg{b7V-qEh~zH`2aTr=&$I zSXFJe(rZg1?n!n8^WJY1MNN`$vDOgyaG?$xwKz({4%MgQQh#V)YO^dX4&K-Oq^!Ep z4?PaVLU^yYO5f69`1xBL>^o(qOqb(qye}TEjBcsakw$CCJw2je*-SHK$d}P*s2vG| zR=iRM-SI<e(>^&860Ykie=Zt{j}yY-MbW=XVKQ7ppW2~1)StRvV!_AQp8tEw52KAD zp!Trl-20aw_GfY6W@pV8-tb4NLw%sW)m#?=Une)=uMJ0Q^rbebPS@^nupqE2SNM&^ zPe&raZBHk@an)GNN{j=`g&jGQe_ug$o;Qw!n*~mMW7}~WI<zm<Nq!UuRwiD&c4{C> zp^;EDtQVhrJ`fuj#KZcfz|-agBGu`&DG~;jxbUxsHFaoTs^gL$4+DZa@`-~dV$jei zsJhRIUt2N}Ctiq$I?Cq!p9#T8b=HrF0#T_c@3A>pLx=XII``7%!@lHte00%dG-?qI z<FD!QbGlQ|;KY1LYgDRyIb{-3oh}2Sq1u*W<-nbjG<0ZRsuR#E8j>t+_*U!j_!DB` z)}m&7lFoQsJ0%t>FKEWS+XZ0FQPHryu?<h?8Gua&#lot0jrpBQ<8gsp-#rr=aRcM= z7&$i@yapI^{i*?Iv?vy~N+$g7b4?vO7PU$H#$S&GoNvz88BM@f@?8M;P0e_b{RCWn zD;9cuugl--1|rp=e$sKPo{xqXDRsE5O`t|!YLn`mnHLA2Y^rcD3`YBjF|azf5})28 z7?thfVBX#L$_Y;bk?L4Aje(L{Z<QN=25RWgzEsE1G#>V7Z&Kde8jN#m$3nGs>y>&U z81JUV!Mc*e$}2V#km_`izlHvx@<F8*o1mdX`%;~<>GAM7_<Qc`*dXjYCKikh-sJAg z2*OJz<TJcMfbxreAW|LY12OPwjK8vZ^FR$9+L!8_%!mgAg;nmlnn7s0Fc$pc>*QWG z3&PB-IA}G~Rr$y)0I5#xZ87jDubt9VUO!Za_N6*>Ezvbb*Cbs(f75x><P+cZpgG*A zE%5QV*W7lI2{eC|i)r(3aohEc;f#?I0~-`@$N4s3vO<X)8(iQ8w_C&J-W+LP+U~Aj z%q{LXLuxI7CkH&`+zcTqU0~<om4vP{f_0(5e}2{$wVJv>_%4Az4(kgonV~q@3w(6g zKm<Ltfvq#RhOD1cSC~9)47u4#9Ar{W%-w1N7i^XIB<&n8_A`ZH^7mICPI$#_(hT5; zem36he~^crw}r({IXK|XUVd@E0!~lK#g|Qv^XlDuf%_4qM*GC@`+Ub}AGorcV`6l5 z;g;$H4eJYB`rKHoINb}TU*>3(Y$ZO(_hGreRpQ9*O-05GJJ3Foi;K245`Lwouy{(2 zMti|$ZNX0(z^|}uEGx<5w<JsG9)CpsUg$esw88|cbvT02-*@xUL?^fve-s~m-_DIX zbcdhsve5B4=O;T1h3i2%s6Xu?{~*7gvwJ}<j#yVqtb8>V-c?fK`uk>L>Di&McYiJx zc-f1TZ{4BM{v2HE)k^g9Y6n$4v+?_2Yq7Jh6<Az2s?nZMUti3+U;;h&9Kl+ri}}Oj zZ6J31A^e&Cjko&P9PU^i!WU5zkF;}#qn!`q9Bn1PrQaW3L>)n+z8862`TeE9vqv@B z<9EH}2TlgT7m<bOE479Dn;`J8$;Qm8W+J`mXjpwO3tMb%A%5ichk&YC7&OXGY$$RE z$FoN;Q&@^XaD*dKhc()7>KcesR`NY%3lE`R=4&48?+LRL58{P4Rm8YH2!*2$Vl&4F zd}6oWa7z0S4syK5tF9dcLrxsRO197Vu(hLrg&)>vpFZ&?e_J*d?CT!EO;2kJ&#z<Q zQnw?BiSm1Ok4J%{#St9t(Ma^DG#Kt?9>$&?jm4fFy`lfVhcL8@i5RfM6UMbVq|tt4 zla73+AwuZ7gSbv;i4z-rz`W%l4LLx@#Y4{uUOp38qggXCGt?AD&yg_9%|`TEZU*fR zNGN>m#S)#S@V<kDh1QM5<H`*nq~0;K$!;vl<~D*%r(@Xpvw`S3xDnVSACtesP+z<l zU=9OUAH!iowZ+-x)^PmnF|3=aBZ7TxV8+E`*kW)^Q8~^5KJ7n-uYPHZGdmsNZq6|b z;k8B8jxLbseGKDj>xiB5drHd!k740seR1isI~bjm@RW5u@z4Xo`;~--Pff+hE}l@s zRzj;?jl_td?obvi;i~#J;?pZP7`jj3tU*mhzZd|Q>Jr8tXer_jbcB5~1-2`+6X)m2 z?|R64fB)guqUXt$5S=8@cWf&WXWt68J{CB-s-0LLZViuQoyJeC#n9?z;LumX^L~xQ z%jc$$aYe#OM-0WcQ)Yn9$8e`}T`}!kQy4el7%tmZTbwm@fGdNJq3yvsBHOtm#ML;4 zf%12!z8nDPlqBKt0j6Tyc{jK$f1c8~lC|)D$G~cXz?*Yz#myJ(q1sd-e|M;*h+o|j zR>ladU+Dp#{-`O$W*o<+qO$nd*%CT!KaRokzH{4N`cP%eF|@0Eo3DRX4_tkY;f2-@ z`N$7eFsmBZXzyWNS?qpo3VpN%Qu)fjD&oe#CQ!qWYxF(p@Qk;4<peq1HGQCCQJIcQ z`(kl*vCFFs^c^hl*v4w|`w{k#?j>o=i_Y<HeW{<+e`=G;bX?kZdH-5sxKlky?;~OD zYjs5HR!!mlQh7}dw-L4Mn}V*q7pNRrYAKjwJvh@&Ani-zPjR6(sr>)xOXEQ2LS<@` zj!R>bx5Z32lp4d2bsWLQQq(MI4qYD!4Vl`ceW{;x?$jog|JK*53RL`N-d*RA{B09= zk=W4-68j&<lr)7f>(>vO_0^Oujh#j3L2huT)*+;QsSgwvYLm+UpT0CEfAfdhq~p@Q zG!E2%DpUJ^>r3ZI{iiauNynw@fnrL>qB5Ne?Mrc_`<kwED${jB`vz$Dhsb0GJG$+} zl$#2Ox@rd(tM9-TtD3^Mf+|oDoQ;()xWd<k_2AIn9NcZ}3R_0#LgNeD5KF8;apVFs zYnz4l&h>$*xo_Bj{@ZX`Vh0E~w2qC)If`!sgQ4L2zpT^!Z5V6o1KA(aS?}&yIJS2b zjCIk1CQWzX=%GQ7Gf~NGld|!;%$3~acOov2*oj@tCc=215A5dY9Gtad3N&+YffV`O zbAurH4lFx;$bej={!>5cT&T{DoRKgkz5#^R-=Q%V>Ob|F`bmAG{?Ku0+_ERQ!phgr z*vawP8nL>;++pC2bL_y)ER9&v_*_WzfhwlO3{$f;;zMJyE2}Sn<0sbDEJq_I4%_<5 zd-pi27shd4VRwiQyw65e7s%t=!KG%`*{wbt+xfaeiT)8b|F{yVKeT=SerK3@`w@Ge zn1fWN^P+vJ&(sHMlgfYVOXs!eS8r%;_J&1y<RZ06WjZeHOZ}w&Q=3%&Ti;$aognb} z8y4cNL>$-+bXxsjA8T@4aKRmNuQmjanMw_Lad=C3+NM4nk#dptrSYe@P@7br>d^U8 zpQ%jk(7tr;{XAR4^N;%Q_-PLISmFs;D~w@UX0C=zZPLEfH#$dZlgfYV+dIGorhV@O zQ(gC=+mSxdd5z3p-t5Ekv%FwWh9`77t0`ZxQ^2h+0FvH5q<yIm6bovT%Kx9fG$w!Z zhuWm$(!Mkf)PE{d`+w_8=ScmhGPOy^rR#xWO2?uyoeS+taisf~u4gLKbwc}AdZ>Ul zxt36=zY>pRb^x>H4WO_#NAoyW2uwABd^3)&mEFJ~rwKHVmiL-@M<@xa3(XdA{Q24y zqF3v{%!OReS0F#1tOBiearqtrckqm_4qn?h9vR#Xe6>Hbm<b%)p6U*-=KNxVr*Pbo z(;rgqd|*<M65T`l!<x(=EcJ~N9}gT3m$v_6IrWveYwJ+>_`M1|@2y0Z;SZGqYQf{- zxtM1)3euZuLr<A6XPWv$Z{zxqSeAoNkB)?84eP^}&be6Q$57~e++4o%ItM>T`a(%- zGq}(!7hB)&2eagNw>$jI!95TAfyoyuI5jdCdq;MGLF=2rw<Wo_rA;?D{@5B4OLNhE zDM0h3=JLDwO0+h1f%y}RVe(NWR*i9i)ERZ5o)yP`vJr-ktOhULICdnts7ozxIOqM1 zIV@D-erI2(S6msEJeE2B;SsRyXDxWsJs0nF9|3FL8G>hN4!$-R0#9l+h6%@VaMw&P zXm!;R{6FX5=969EvSbA<LUZxi&Czfv^a{(~d>-3&8Uu%WpJuy{pGSj`ArR1bJA1r0 z50~{A46(iknUPl>*7Fa95mk?}tcwM>`<VPcj^N$wb5H>u?Gyw$^^#aX%`4dNK_HAO zjbjD@m+@?P5crfLi}-dGy)pyAOv{N~n0Hk}hxWC9+aIpI^Ja@)UBiv~-q56BSGIWS zHI2U1=J&Q<5ZFD1%?`Pup-=5tHtG-iN|&=MRj%UU%fXQUtvAb`c1?cHJP^zVjAAWE z6k?WDFm$}NNWK^5ipE@M-)-A{;OFNwrnUSkzOC*J%5le-kGO<Xhx&6vuP>yR9A$%M zUcz?^dqKm;H<{Lo3%Ew<2KOE-*?7-<JarslU;05dEju5lE$spRS(jM73m4>fHeKND z;HB)mbQPIdB;+@m#NhcQJl$;`>@dk>UOpEwu46}tHB+)17MJm=ZZI5ryoTL-b{4nX z4ujH4Cs^~k=kZ6|Nf4kjjU8&7kJVatfB_qCvyn$G;-#b(Fn`2ymjCEHKD4(7^UFtB zZ1gz|ncAfK)Mkt1=J4Z{J8SJwfX_yDg!Lxx6~21KIKiX^TnRYq+S2AK-n2z1GkB!9 zG3q*AT7~d-)e5#U`kMUvkVq&CpUsBfy^JeQM#APBvlXiwT*Kz8LSVp!+R6iV@_egJ z0sdKwz3F})P47m+C$kWR%br5KwXp+?4t(#@a6>V=w^Km3x(jo)JWB9+7x`|-X$zI% z+l#Qft{oU(KcqB@FT^u<r$VD`di>X(YZ%zi2`-0nWm3yx4IP8MQ^EeQAz!@x3ci^? z8wzH*DEmCWhO|BY(_^0GU@5Zo<oa)3z`I46i>RY^u&c=x?(U-_4%&G^xlY`9U9q}X zKkzO*$!Gc5h;E&<z-stfzBaRoxM=&9Rm$JZ*ZycIUJbJX_eleIfLnFZxN<d!sy&Vu z+^H&b7Fs|P=S7@<)EBpPn}BO@C_i4azBu>lB`df8WQMJ{R9F*?|2@nv>u8JcO})WM zKaigv@tS`&Ko~i71%I9{zt^y}8;mUY&bz66Ykle0AD>6mtuEBQ)il%-YJa}w8H;j1 zkI8<1z12pjeVfy$g;4wO!?%f0`}XhjmO|}wRFyhH?GGHZ7ixb>!BnXIxz;R%H9e#U z*_(^7#qa<&psOC(Y%4<7X~AqnD+AbBy%>8K-(!mg&1B}WxACjVHdcC58y@d1#_4{W zSo&gJn2~%P?L2O=As6G>*n4;I!je_&<Uj-XXFv&ln0%21#Vux6P0FxTnanoaG=#p- zN-(5nHapm58M{*LE<U;*&itMm!VJ8D3q01diQ&uGlZ3n2;_V1_e}MsX?|K8rxF)dT zrYWq&^1JA^-km+VqYL?!Z{U_0{><v+eAcM>U7Rz?mc4PQ1EWGqu%-^Mqyu5>d7m=* z4z)(Ci+)WwnROkVH#K7&Q%A64R;6eXWx|5*RfUJQi}B|(3kKaineyCi4VmiHd~MFM z?JGgApG7z@ttB(5(UMJ?cnc>jYQq|y|H^K5D8j8S-PyP0rmRx?n~2UmS<uN(Y|i>Z z6fsj-fT01a-Qx!SxEaXG)_r2Vd&}+TQrP#6`t1Gb5*&XwmX(hA$|5@#;-f3unT=0F zb|AY1uOuvG*Ok9mrNlxEzj}<tH?(6%ZEm2W<vKPpsw()`FT&0>uCZP(-Px;OH*iLm zEv)uVEvQjgB!5S=lqKs9V}^FOG_cE#&SV~r+K_Ru7-s~mVI6zuz}Sh`H86G4Nn_7f z>4AY^i3X<42PLwDW%{rxr9=Z$(?;`H^h<rXU0kAp>F_!JZ0Q+2@Vir@f$8unJ=n@b z9q`{+qJin&P3>7ov^HFKDAB-lbe1hEu2~bZQm$)YnzXwa(_L5%n%yYYz*PUfj8RBs z7-n9K6uYTu3YO>glkJ^Vq=DVyYTitd{f*gtFVw)UC@qMsS@n%QI$WrMU7l$SoAm4l z8@0Dk1G_$h7qg?SE5oR#g&Np3&|1k#ovXpW!-_Pp>+xePn{!YL^uHHrU`H`3sh!Sj zYSxGCAB*r}pXIE@31b+ap^4p>YsqZf#Rd>$e;p}y6aC|u__rZwuey#DyI|Mp?82vp z@TKHBQtWb14r4#xHULq29VvD;j$K*aH)B|_Q*I~NmCE10yxFHd<aNG|6uXOS?N|XA zKtgsgQtXDjZqA%-b>W0@F;eWPOm%_+S}``I4t$$dgcQ@S!(G|0F}0!6{X(ReHgNC5 zwsx%rgQpcD#We2R7`D`<7KF4bM2e}a$6V%zwPCkIAyQ0lKTTk3+t-0Y|3ajgCWWN3 zqzCeMqw)%oV!G;J8cThr4-W<uA;pwpx9r_w<~^VuWPU9|>#{|x^>`y_8CtA?>B=_= z%;bYHI6f{$is`o#QLIUU2@H0*jucZ9{}85IVgi!_uOr2@;et`@fW8TwllL{n^pu4c z`?<sjUUa#R6w^YRPRvMt?iBH*7%8R?n!B?6b_P(KEc;0?y=vyn>Xz!ldBb9)c&+Tp zSo`yJ0ag?t#V*^jE9=VYfOGRAq}ct6@L@PcTmHX;98ZE>@y2m%kgqoU*i?uVyDM|$ z-#a&{11mENkz&^{B$oNDs|z#E79zzi?bSl&wM`eE*DFGbUEIrLmiApAmPZsJ#g1b1 zz1|WwcbFcWT~(}sSAuQ=I}m3G%jaE3iWkLbjORplf2AS#+_{bvBZ^D?r#;#F#qu}e z<QhtGp;+wP=E~|{(}t0Ui;-eM<Nt4CPquQE7MNxgA&ozc`G)>}tlRzS@Uu=4(wNgY zM_!6%n`UT1<7!1n<4j}gSS5u$P1lC>^+iZyOXEr7_RqE$W;aa-j)oWG-WlQSPKhqW z-!DcQ!?|@Qvy1n1;ZB|FNaJ?2&nR|sfsXwAq!?+e(#(gj6I1Iz^@YVq<CAlH7+bci zHq>uej5H?g&IGb~S873UK@rk8%(ya(or$Rp^Uf6^oqK2bUSjRRb--LcKhycrxilC% zo4sgg2s!flfAoDiV;>A*lb7ZkOO^+*{a+0sbV4!GIU1z-Gtt}-EPaZR&T&WE5p4B6 zeON8~Pv>}K&L}ob=z(`}5z;x*GaH>FJ=f7Wp6oJ<y}F_g&X?sg1DPW|zYS<}o+S_Q zWVhy*V!bApnCA{B=DYfi#yK#?@gggEW66{UZ)=<}bT^%5^ZV<ws{h{7IFmFRk<EI( zs>~J+x}|Z3IdW?|d*k*(p{;XE<IJ<}TRL+~xTol4bW7um^z%#t3pcy37(Q8UCugdj zV`j3HH!l@)b#7~%!QLJl%}%>iWi#*I);P0Gc`%fj{%gQKoxh`T-lOM0s<T&&WOFxI zv$cmxHO`RJZcSpB+}g7~;bj_U&W#6SSk=v)nWT4D<BY1?ekptU&Wm;Ry{mDiZECcM zIbR;gs(atnI0K*Waflhj4P@^>muZ}tx0D@c$);YcXh@mH8Jl8PQon#*OFg8}bGwW4 zg08RupI0gdg~{h(g6X@wORRcvsG{D%Qlyyf8I{jk)>A0-YL+6!H1e}xm&>#iWr=r? zVtVGver8eoq-#v?J4i8I6TOk;bz9{cKj02hO!H1HXEnR5an;F`<4-VM>$Z?xKb`0L z)20+Drph7F%*3;fqQ;F<q?j7k3}+2O-4!CU3@KhzraEi4M6%S>d5S9I?jpssOlLlm zwy##y(7%Ti)9RtA?Cr@TiVlnJA;t9cnzd}`n|#H>^Y@Tq`uzDWw*B5U#o|-<kYbv% zBZqbJzoyWdbq^_~FIt^pqoVT^#&6|yLNKNIf#wjJXXsw0d4uL9nm5ij3*l<6*LGSk zSMxiI;Q?ID`(&=im#es*oD=wP6{nlxw~4E{-ba&dT+IPxe#a-P_+8$TRb0*cru59_ zM^*gprZSnUdEb1G^?a&|-`&0*&egon&ozOUsQ8`5+YwyN`!>$-=hiBI*Kxf&SMxrZ z-|@vNem8BBEm!kCncs1y;&*jy8gVu6llL`uQ}H{!C=*V2-=B7w({WQ3r>pYXT)xNP zH`k;3GQZ=M(|+^2z(sAin)k`Mh)+`SyAIAh`5)eQE`?Xw^qb#(z8T2XyiewL+)l;s zM&FI)YThUFJD#lKcNY_uay9Rh`5pIB@w--*>$sZt$^4F|tN7iNE?c;o_fd=}c2fh^ za5dLE6rIV{9FStC&`INJ-bb;s9+b${ypLjM*k~SC^FE55&m4cQ=6w`9pDI1Ln)gxc zwr*<A)x3{lH$2Oht9c*AB6fE(uI7CdFYWs+xtjM;i~`dXT+RC^MhmNX^X@9%M=`pT z7R1%Ok79JnG=|Sn@ji-CkHL$%n)gwR>T9j!YTidN>hfbPSMxrK1;r@8&vLHjdWE&q zxtaq~j6PgT=4#$YF$(mL<7(bVF&g7KovV2t#pvM4VO-7oC`M+EUAda~QH+Y4wC8Hx zM=?6P){d)rAH}HO>*id|`)E7GYji*>uI74FpJMlRxGPulK8l^bdmpameH6QS=f?1r zD&9x2YwIzW2dH=-#jfOO0$1}sid{lTDp&J9irtEXX*^xU`zS^fyC!9exSH#wyj#rG z9FStS{7nK^^FE5*rxQ_J&HE^Jdj26?&HE^J1`9^<Y!&aL*eNZ%xSID-><Vl;$#=T` z=6w{qTg_d$n)gvG&Y3xLHSeQ%rFLap&HE@u`z^c5Z#@3yeH5cl5k6ea`zS^Q8^>`q z@1q#y&kf^h-bXPq3W?=v-bXQ7@@gSh^FE4E)XQY9=6w_kiqYqKOL&Zm_fcG8brX2D ziuX}mC>Fy!C-NsM-bb;Z@vr-|Cs*@68h;w|joVzgn)lI|(>UL6?8()<kH(qCHlx2E zSMxp^TN=-~m!i3v_tALL7`CdC!e6U+AB`c66^+l<8R1;b^&V`C;c5;@<1@YPWUl6Y zG$wodjN)qEN8^xeK7^}zAD#Pw+rzk;_tE*bJQK*(ypPUt;+0waqKfy?dAW;duI7Ez zXF8WV-=}jm*V7+6o2xk>oy+CrL0rxI=v->2`ExbzqjTBNb_7@RK022@b4GDB@1t{} zXEr()dd8!3$?Y<Wt9c(i*U|Hy%nNv571xt_1W!|OKzhcIIRd|{;(hc?B69@3SjGG3 z8Aj#^e1MAg(KC<C5qM?y-@H$L2L9)aBy$AbQ_cIxnM&pee1VGh(KDFL5%?+<@1y58 znIrH#74M^GKbaTs#{coYKW9IBZj^Zek5F+vs;_b8yfukmRq;N0MwK}Nuc_jF^h_&r z1pY?F`{)^1<_H{AypNulWsblbs(2qgW6K<YuTb$miV?+5=6ZaLitEW7kUvmyK#HBr z`*>3o@1xl59hJ}fsCXa6F6y)3uT{K{VwZPiKlfAdK8oGC=#BidiuY0M&YfD$JE(Xc z#crM3LSFOCZ{A0-6GNhTYZdRKSQym|=dJ$ZeSa{e*kx{s<Xco+kLt_(?hke{@8joG zypLih^FIDv#rr6BGVkN#RJ@O3C-XjjNX7dob~5kdy;Z!AVkh%HK1Id*XilJcgXS5! ze`&6u`G@9;A?{oh8klgM&spd`{;*g%D@@tzto-f+91(f3Z*o87DKV?@LGd}G)OlH) zgtyym6?!w)D@KeF==EWd81Z1f;+w@84Bog*oVeP}#o*4_3i)BcPhKvU>*xjOigKO1 za$nC315w_$+~$qLKX|##s+b`>oR9M*iu?-sbLdNDxjbC<?drvS6~6h){(KfMc)362 ze%8*r!^{1gk$YGKZq?$MrYF!OH%yGxYa#3$j^o9bNuoz(I}urwi~UEXi+=r@h-!m4 z*6bE9B8?k~g3^;{mpM^P{OKSXFbUUwjTVv4PNJh;4pwR!DC)LvCnkMTV#546!pWz- z*tskRy<|HV)3lh{PQ8&Y6y<ix$J#N_k(G~C?n8~GwyfNT4B6)V4ue>^O>229lb&5z z`B+i1&3;=(vT~c{W9?`$l$DQlC4IGUzdo0Dx|d%uuZ2~!E9RB`ElYsho;66GW598t zkmcm_SvXt%twH~%4iF~aaXiH+ja}~23QP-=aGz&7+tIugL?kTLkT<_w#;TXuL+=~% zT^@)0bC&mLE59?TDQ}n@oPFoA6Eu|jHm$YO<>Cz|sPaEHX<w>C{h>bmO^3GI=2Ui> zP`f>7w}``+7cyCb$x7~XBMN7fEkE$nY9+Uq-+_I5A(O|d+NrFU*jV&ExPiw(G(OpH zE*dn<<nfgjYRLT$nu{Z48~IPqRD4s~NNkEd%s0GVu3?k*r8-n@&?|#a>b{@9te%FW z+HF4Y*>^wRsHG_z_R3%(Djm5m>{5+I?a;ndht7-YQynVzI%p0`)x7TSH<y2V^Ly_9 zW9N?#RENfy>Qfy#wlGi?TdGfW(mVDBEBDph<Yf|$uhttT1gz!dYcKImPuTo0gLjtK z8<lOG2g9$7_POQju>ZXwz^|XpDc7fVs6N%9^7(A}_r_ye<d%<X^~Dz)8Ykrre3PJI zhw4+EeINQj^4XRAfAy)3YvaMtJy*Dv+kf3<FjUf6?ON`q_3D9;{`r(^`MjvyZCiIZ z&~rU2pI7|(9`OF!CRVOb?NEKHL*+M>dqTtA8(8_c+mH8xj;@)k+)rwU>QkMYgNK0g ztdFk$t50?0xQXa7zvCvyN6ahw9e)`YQMU3oE>xDW5bIPp%J>R@6~5FC)u%dCmhlx0 zRqN#Fhdv@+6@O}n>QfyV7qPC<Z+xjf)sf>SELCxn<0HPS;xFSOa#XlbS;j&%`0^V^ z8DEj2!k5~i`c#L?GA`nVYMsdO7x}9AQ#(|j>d3eVHx<5ApX$&%t>`^g^sXp+9~RZ8 zI#i~2PSN|Vs2!^RHyzqe@64ihXuEuu%AdQy=-or~z9D+2552dD>Qfym(|dpDJw((F z)&H9gZKrn|Q9HDq-l;_IaG`g*(0f(roibFP>QGt6;?KP;@*4Pa*9^5o_5Y?r+v#04 z)DCT@_u$aGHs~E3^!^Ka_XpLdI#iai_;bGoy%U7mq56N*q3!g}5o(9F)B8&N`vgF> zi<V;L4GGhe#(`^CJ@LNu6z1qmfS4V1gx<_k7@ao(HneOgo~BDU0VcwW_)6lzrgNCk zCj^G-ec*?G<m1*Z)1d!^)BHuwMO?#XL6XNYKI6#+tdbK7ZN*qVq`@WZS}+gvPLAh+ z&IS0~W;RUO5uq&C*IyF>%`2}~#>@J*TFnC39iS+;Z{#!&K7ab+nkd^}d2<GA%C5`G zeOvJ(6jGj-C{Bf*!u7pp!LtSKtla<GY&N_;(^&pLtc1y{BH{VTt}JK1!0%C!VCiDT z7ETj*yKOv-`R>V92XpMPD-I@aZo=xw@1*4FCc?XXSB8_7=mHC&u7L^bnxe#3HB;be zlmlBIos09@E`}-BwAr#vxj2a}himJbvXSXIXgYcsG^tdDeaOwh1qU-=_DvJ^_;EJQ zn!FOm)P14Y(;^3**6e_=ETK4Ol#MTrYy%J5XhrqJY;;Lgf+D7|OL_a7JK3=B(~{h* z3)$$q^b|N~y;PRBH+XU!?%UVpf%(~}=y3+JN*nR%{zuWV?@4%g-+^~-m4#~y&Oo0! zOZfQ@N6;tlB=mif!b=K|;_%NW;7k4D3VqL+$KaLcIeykI3&Y)y!w0uVyxjg-6A8w2 zF5v_6vN8AD5x8uvBg)&CW*vfq&NbzGyt1+V#EtOJQ}c@U`L-LNSAnqzl>JXyw*)@) zX)em=D|K7~Q+k+-iRL+IpO*v{S<OYgH2IwWAqi@wn~R)HIT+M=J`AkcT;xXPVqx5T znEJ1oI3vFgZsZaTUw<|evnMKXepobE-7^z)LX}wO!ff!F-At6@Rc-4W(DE}AM*=wZ zIXxL(9&aiP76=^IaVjWJG!kZ$1?DDg1B28k-gw{{bU$v0p0j#NMek88@2rm{)!n6< z<F|{|?R#V5I}@oWVz**L`xfY;?IsylO;Z{^^b>h;Go;z)+QE&a<zmN`>C%Cl9Tnlb ztsGu|i;zZzwpYHoZoB{D)>%@~Vt>$iqlbsSdP}8l^OUv;JK$%V{!-ZKr()qQqXRt+ z`btLeM$*2qPL5xC_Lqhx=t(h#lb~T>XUR9$SW4?N5v2y}M5)anc;_?~%iKc6u!|ER zYV!!Rjyo+juU!MP?{&lMo%N)=@57<^<#w^5ad+wMuIgAx{xjL{BklZD2NRbYIwU7f zl?JTd4%LHFgzkf}lKDToVEVR1X3c!0(M#$`?A-y@D|ndX?p{f{(%=Pq{&1*dGU}Ju z|16a`yzr6SgSDmc1=IIyISr7`JL*c^C#-KhvByy9hEX-CFm(->tnrhYXB-u?Uhja` zZ^lWd-zAFqnObn|!(7RG?mF&mzXMJ|uvEpbt7tb|V$1TvrI^uo73F>oD2<Ssbg#<F z<uW;j#~*i4JUFvt|Ck=(l4sZF{O$Y6824t6czP+3SIL@;eFyCmCyEzvH?0tiG}<D* zfBdG5yEYZ?b=WHQq*mr{XU@RNyOKoXjZ4^kj~Q6sa<S+i62;cZ-~PLsYAc#-KF(t6 z%)!E$Eydl_dCZ{IdwAg1OUgW_gaaqip_a{X$^POch*};44YWh0akmGs`Ietxy4fg6 z{xFZiVPF}2?Pe~mpJ0P0X6=QM$u^Q=ZcF(d-ZB{5zml|WC}P!hhhd+04QY#M7j(Nl z5v?P0#RVrXUTwuBJUlW>wAtQ*ckPl5x|{qY)2XY3Z&o^sz8x-ozZS$S_JrXs{b}NK z{_5P5C9_b=e59}#xzKfTw+M9K70bsqZonqGMc`q@OrF%-o!vhcft`1B%&j%FEz8*+ zf$ff(D-$~RVQ16AapK~oeDlv$to`b6j9fdPZy&RX6<&`(iw%|ec*hyasW&6=tH)O5 z7`r>lsCp6DYyVuuy~R5?uN;Bh?j|erw(jEzS~tbe0lKL7p&hz%<Mtg&YN37BAawcG zx!s=9s^}a%6mRD134?Wpxa4PV>{cxdGx}9x*Z0p6*T;{=#A^M7_St+<bJhs_6~9H4 z-4o(ihfth(Y&J`87bTnykH^@fCqaKbi0Zd}aA)<}7;b!v3zJ98{o-gTIqW_>%%2M( zZ>^=1J)QA#*+S^QLQA^Dd*hR%g<$ctuN0JfMI2v!4c>cpmDap`BT_mWVpMKx>E!CW z!tTZ+7~8nF)FA1c7~oq4S&)ZR&HIvgJn#by-O@|aOUxGazB*z0zG~9Q(I3T(=SQK@ zyY@=UN0Tt|=Qdba*%B-ilQ8N15%9G#hy0U4_~FedSX%Z#VdfZ&(S7W2M=C?pOX2Lr zBfux;TVUH`QM}gPs#v3IcU;_iFGTuUV(~WxT8#_>qYY)?)1@OWZd@COM=0U4X?yhR z)BvY`+X2}*mGR`vp7_vu18ml<gkAdf!KkJY7`8W_@4V2NeGG^|yM3WN)aJXQzWlxM zMZ3FTOJ5!Q=jJ{*_;Dy+Z+9I2(eDjidV1lrquPiE65#NG(HQcAgP(B`L_8gf!<Xp8 z9YcS}^aw-ymxb)8cU^oo-3PmE4tLfK_lAHf@;5l+qS*WXd*QTiU&;66JCW8+8-uFY zOOrNLk`k<k;<GC|M19+HA}ezi7B4enYZs3csq*)9(w1I;2T~EgaHuc7pQ4AoqZ&c- z_hx*<HV6Fh!daTNrjuyB+!1s0T1%<7SBhR!o8j8SZKTic!^DUaz8IqWR;0Scigh6a z@yMu;;=$8zta_&*Xt}SdbY;69e4o<~J8aOA$~@jf+bhLvf!|1}V9b7~|82E!dG9YB z8G9KH{EQNrYez}#7QThzCdb)~=A)#!p_gH8^gF1#wyTuxmIry^)iKP<L)temNs+Go zf0UhhJXhcM@68mF2%&*WN=e3ezt3Kxj8W#4R7i--^VBS<NTpE&mF6_a^gerq=6OJ+ z=+i9Cr9tD}`t<$%-rdLj-N(KD@qDbuI{UrO-s`o`IeYK3PZ3>Hm4JgM3@tx?bS)Kr zPQXWP+ea@U>*&`93HVMsS7;Nno@y;jK+i<3rp#k29gz@^!qeAlNBfpi`>k<!^-`Vi zo6T{0F*h3BH(7GmZAFy37=;_-SJ7{V1K^#55LQa*<J2JvpxwJSh-*q*JCEYhIFBMV zTvap~{=)@~pD?=@vllY{wJMuy@m9pf5x)ONzQOGCY%Iqd-#-(b=6xix)z$RszS(%X z?*bxz{Sv=UK|&8yyX}WjY>!>>>smv-JRUT5NB>nhe_cEJ6%N4BJq<BF^WI<Aoq0_~ zeAhTtu<i7KogybXf8SuXCkFw|nilF-;fRCfJBY8W3<|P_V(MEJC@Z^1!F~j;8mJ4# zdKaidfg|qt@`Y&Wj;61cjlt_9%s|3q&5?)iM&aF?0$8rr)AaLeW8~Ux;MZ0I>gj8S zrT51`%e56IDz#FWs2zZ}FIaLjUFA_q-XGsM7;p(ivMAJ_ioF_ll@D%~#LGJZP&~KA z`v)(Sg|#VwswLN{(O@kIDISZpE+_u#PsIBf@jhgqiYFYu-WyNMDC3PJeW2*HGFDxX z<o6Bpfi0_*QFqcO(d@|{u)IkX+ne|C=~-UTx>XUMJnK!iruo9`K0UB~Q44othbbJ( z?1`6x-xB5CHn1l`6?2cACRcXoz=A;==#@+%e3nvy=O4o9%>EOhBx4;JF~Eup$%z45 zlQm>(n-@u(6Aj!O4f1338hUp^9Mr167Ir<_N%bHO)*a0koz*r(P1$jf7T;A{7Cr>+ zt;WMpc_GZtQp8ExS4sU)BM^KxL(_;9a{N}>Vf|SWuseM^h_|o*wguex@x5?|g*SE< z=WwgGDPcSDK}+-F=FyH>@J#g;_j7wW_xN@eT-4X&f^G$pkI|{{{&+YyWu278sgc=m zY2r?<4io9Jsu}P->Na(`F9C0V1i)J>EnX=;0|GaN3FdYTr#@3$;eNzN8l;7EFWWcD z`b#4XX<W>I8=eg<r+(FTZQ98xwM>H_H@=Z^H~Y{fw}au~^yegmjuiGEuL%1u`9hIV ztw7d&4!5s!8q!fxXgO<V`HGqVR6HPw=VetZn-k*jk=IVTcCj}X|2Cctyl<p&Y|Pj} z)gMiAByi%)0P;OQ2H$Hgqu1VDXP-=VM49RD>2|#yFky%%RyMoP(F-P%${lHt+;pXO zfqSyxeP=e@6RZ&pR}X^ANAA&+yEt+*As#YL_v5Sdi^-I}v!Hcv2T|!GOYRR+g0;rJ zupzfpnDLpjayy=dCKoRAy@s9^dKzZq^_;Ezj-RuLe0eHf8+2;yfHN9kyL=*QSAXG- zPa`C6W;&!_P~m6HQsv_9ve}-gx%`a7n>kHIceFUDft%SoM_-q^pq7yi(uhq*LoYev zc;!L(LB__cqn9k$9iNJE!{yB5PpN^Pk_S$Hc%Ccq$O7GGQQUgf+uVMuERZ_n%Pm;v zMb?L<!Gf@AVVRo}TpZ*Ja}HJ5%wYEfYJ(1tHvd~RbpB#edE5yKVtd1{p?A3BZ!@9i zKK3r+1SdG!_mJRV{6Oe)*$HkA)fBm&82}&lj)w<Y`?+-)`tb9IE!a;`BRvKTfrKf9 z7$o~ZI*V`dw7$o)`lZ0cc^ULl`E}Fw_Dt|8lA?1q*%G7KDNu7&hq@TL5i99f7~Z&? zZhBxs)HGNQX;+E5^i52UzR8C6niHZPCl?X*>B*3zVk(Lsmjn_&mXjYRB={$blR(=n zmpohEDJ*@Q1O-h?$-zRAkX%ZEN4IAXzjenrlcA|F`t%gCJhqY(KSzZ{r^)bM@kB)! z0tXkTlhgHyBz7L#pVlUp_=PA!g1S328yzyG!&8Z`dkTy@G|UuT<iXe5A0$J19B=gN zVtY8wz<USxaR#m9;PZ{4D1O}(Z=+YO24GhqgdK^NbV$h<u)b;q!yRVwQzn|g%ha*3 zblXn;qJ;sNJ8^I#*OLDHr3NEE+ryF_1*EB31J*CI0~M8(<jbf6V&8Wn_*E#t-I5jL zaO*^<OH=^6_7c;cU%VhUPX%%pmW@g6@PdMEDu10zqF=MwLJeo&qXztSE)PGV;8(jJ zZp`fght5sp`mUUfD@`AekJF-v{o-kOc+?BhKI;s3e0ws?P>!KTPH7OSH?eRhb{+lk zW+*9{6%UdDIdr%BLE&n{6c}5WMwf5@OtkpvFzBHKeLl($!hCwdGo1lk-4;2piuZvf zb|dLeKPytG84usjETYlgVaLl4CBVv+MRZ8v`4jbdK4@;D42@%MotS)NHeT=ZkUThq zWG}koX{YDJCipeCVp;^gw?0kOc6}z}a;L(fn-i$UmYGnxxswDNS#W8M>2OM7lJG&X z6}hLM0q=@^Ie2ME28K_CZ)<PSzI%#Ehs9j@d~G#7^FEJ+uatx{x83n_#wIe<VE|k_ zWrl0(kCU?V#TFX}2Xn(VXXE`>xt3lZ_LFsbu{dqx5NuO>KwMW1!dGLR@Nl2UqSAnY zcrc(B$+U|CvmHmNMOi^bURM}=v}~k4l2#|a)Q$wXcS6)SDdO{$g2A=^8TFg}()8+z zY}|}--28#tg@Yoq@oe5Au6lK*#n8ci7<jTLij>v3S#tx?s_8rR4Blk!{f{1fe>MZP zSAV9jtj|!xE+;(7d(gfK{cxIw11{W|X!&?;2d!NZjN<W&$C;v|OipEHVnS23Fz94Y zl4u!=0Zm)zyRr?$Mv#C`{l5xbbuJS1DeOL^eIi}gGyv*@oG?z&fe*ZG3;I6{Q2FkD z&UV~4^5*???6LF+XX6_JmI=?O-gga=-bNp&8?1;nowb}UF@{EOOB6PYCWae?kgPij zo$q=H6hu*=XIx2BYR<8B-ZS9qig&b9@DIPHUn)dy^`P#lcla}n@!(V3!FA;nkQY)h zaC$~DEx%+yz67l!iw1_{+AHgbL9_y7-*mz$(@V(8ax3^YYba*BFCmf%bHV%9dhV+K zX|m?i9zx6_VYl-{I&P#rjK4Sp#)ai@HfO8JD7h%uQge$-v322cin5_={$tVN0DpKQ z@qxT8h$1VjzHr|TrNKXu21I|-O*$wl3=E#H<F0A%qwhX?;k=2@sJ*j3O`SgnXS}~a z5Bf@ibfzy_q8D*1V&Av_5r^&j7t&I@L3~1PHun2s!&h<sWP^S<p3JBquzVEWzGMwm zC*Sa8FH%ud=Rx*F6!5A1LUKMO8CRSr5VpxKCtq?CQBta$3l;7pWZGQ(E)1t6rIddx zlZCaX>p68mUiMlBZY`0d8@zN-`L+{UypkeqT@tuxgeUec%%w*U#p1T+Z8SCP4tH&8 z0@^HJO>fMu;?oMU@xt?&{Gbclg|=5%jB)csCnVJQ&v9vZ(7~Pvvv=_cTM0_98UY92 z8}i3nr=VrNJmltEaB}@J&^)RSd2;0fZ}376d*u7W$mZpOm;;8mb5K07tF?rwO;WTZ zAQQiYE#_9JYvI`#Hw<wK=J(Wx;#-+k`t-d5Z<Uvc?<M7E<}HiA_<xFxn>HC`t54H6 zc5T%3+(G(g;Yjq6G(^>wd;HByv+(fk4*Gg+Ai3Rci!L_@;MqtaNc8K0M<p7mRh=X} zJLv^ROH!!B`Ve@u?+IDCUzc0(QW=cPJ;8GR4}SUhyJYB=>EM8isc1$DR!tp7+6Gz? z5lZ5vU;gmMt_QtpIzo8uSu#kIY}&ZyBCY?SMom7=!ORg^P#V(Cl}zl%J!npXE&Jwk zYwj;1$COT!`<Ft1?LSC|dao18=A^<J#Sog<?~yROECnhb#L~NiGC}>B77fb_7rbam z1O8ASI&@es@-53i_(3HTp89Chx3>$(jN&-xGSj4oR%M`W{aK+&_E1_gas~=2J`y=R z&oA7QiUT#@a!wky^z*V5?2vlIo9^?csl|8cyC83v|Mdi2y|<VKy3GOE^&6;v(_%VM zGYLYKDSs*^hjhe-;k4<yNlRV@dG0+A&03Cdy3;1Z(v9jUV}DinEo%ZCo7Ni#KQ1D> zc7~w6;v@Q4dlTnd`kw0UoQWaJi@1k5FX^uLlTgd~1UWur2FjVAq@}()NO<c-(V_fA zj2Kox+9&cNrwQ4(yVn|S)L=h2b5$A*yhf2-)l<QcJ$o!nS;+5cctdJ6gHZp$9g$z< zbK=}Q12wlB5=AF#VaMleTwG-;9RBT=Fv21e4Fc84$cS2c-Dn=FY&$4AQF@aeSrdlw z^6A{0yvZ0Gt%5kaA2o|{M^_I`6g({w?bPbY_M>;lO>9s7$hrXV+|xv3ZWWS^FEu!_ zIt!)GUf}MmM7sQHB)&hql#4KN!!=6%@aKT>BBj9@5aThL&LUTZ1Ee$2VVDk$Gg%<2 zNln6h6KCrFgZryp{%S8Vp8*?VV30%+m49PK#oJE2P0wspz{UN>fzj;-`torb9kpR9 z6!k2m2TcxAnd>o7BhxHeQTkBe{v#Wt8c-l(Uq|LHngb!9T<HhB&t&JQsZh4qo!V@< zPtyB)LB4Dionc>2j2=eA<$KY5;(}eo+$atv%3c!<RUZk_(rbxZmNClhP$5gAGU3dD zLXp+i1KhIZ84!jl1Uw5!0sEfDosm;%;RPX4K9>qsKJWP{UmTz#Uk8-Uhf!q-JFt~L zNgWR>;E~mdkkqq)Jek=n>hU852FlDMcYC|kNEo_;=`9g`eC9I^A3g(uLVRiVjfd2J z!fg0BD~`Ifo}}kB(_!r0@#L(l6sNaq5?r0tKwrIkNJAcELBjMh?n#(6U!I--UZ>WR zNvE}h|5G_*J_SKr?_xUF@d({NG7HYeNANQZn|X1&l>Km!k7C;wKR?Smc;Da(9%n$y z-q&2G)_BpyBN<RpFqn$_h}Wn3<U-+&x@^e$q0e_@uja0lW<n40l5bW$EIPJ23uNnV z@&%`F3uX_=1hsiuRH8zgpZ_icBs;Z;WThQwD!-zM($A@|P7&&NyI|j(74+$#nUFv2 zGYvA)6^h&C6v_kxbdyn7yM$cNyGt*hn}IVD!^u|XLb@v>9;>C_@-~-G)v_10P~k-f zADvM`2F;1Zclnq32K9EbQ!5akFZCcjE;-X(wWb(rYJw93Z`Y1g>4l#^dgHd?p72kf zJ}6&vShU&yA>oJ%mSo%^CTe|g`dmqz|4kp1pC2MuOJ2|)XFOob(RM))Yv)sOQ{c!6 zUtyAS5I*pHL(V)rL=(;BF-X=Ce)MgopS&mIv|U%o*O|$%%`cLUQ+m#uwccXSO0&@` zO^&ud(1C#0<FWr}2kO`EN=fr9yph#HHT!Jk3*W`zw}o41kkJH)f2M<FYIbzlkt`TH zY!~ksk;0d`CW6zeMI^8FCs(uXFdcSfF1GC!(i`SH4XBxkyMJz`&m@OK$qGwU+7wG2 zSzE6eMKCR@nHRT<`-_)zhs0pW%X~U)p&L=$6OTFXmQkf!{fM}KsBQ?T`DxO3)pyC5 z3`3Z8wSv}k4u_hBKgd`YZ|vT$y>>th+rM}^uQBZ~Icrl$OU}pP9&Ke}QhAD=ydk93 zMRPzaN|W67e9HIEONTVS3{beHP09>5aN@^`w}p5-sk`kkMf8#;uXz4f`ENS)(Yqms zM21>J;Xxe~^hdI8n%Q4$JY@v;#_lUAQJ(?-Q~BaP_DQMaYd={sKq(1Sj`qO7QQ_P? zPd_*sJYLv-d<S>HI2-JAJn8v2`CPB|RLH$w#L3=`0AIm5ve~nigzk-C&-_D(UT7CF zw6}vszgE)g(pzqvjVE-x?*-oJm7MqCIEW0|LJGoNgd4w2g(~)K?!!6bxCZt-+wYtr z)Xgs!O2x73m;Q31!G-Ye$0tC*vLZ4ev0k{d?_^N<r4Di*_wrMpy2F%lec=E~QI*3k zFz=NXG^k2LX{7}eANWkt`;H;&**LInt0t6L%_LjY?SYfjg>|he@YvP}e)jDm^%s7T zi(b>&{c9j6&NA<Vi7<uT55!B7a03}A5KIFVyYa%Wj+JC@uTY4*xPbJ@&!$d3Nw9To z8#iwJPda;0AS7(86gD@R;$k&(h_#iYCHDEef8T6?EIV$_?X&cILkP4!4I-t_dg7Jm zKJZ<1nCmj_&AViz!S;!hiM8=}(H9yE7S(0M`&<bB?pY$djc4<pb<b$$!T=y_Z=UGv z7V=Xr09N-dAOTB9!J^dySelc{)!tWzIz=BKlU4{@4BirWHVb;aRO6;DzE0-W27_+% zB&s&|6zOf*4_uYZ@l>M+5lGsD>6HGM6In&#H%EcPC*-G{{X|-G0-;If0bf3D6<NG1 z9KOYDq{os~L1Z!!9_dXYRd0j9p#DAyysYz=U8-Uuxy<HZq7Me4_-~2FdBQXUB73S3 z>-0-}!cj{&aQ7XV7a@b<e63eDJXX%(iyUWim(GZYt@$K=!Img?f0PZ{n~Zofkx)4I zS0)rce#M)b33&e|J5ank5NF;uqe=&j!Oqhf_wK#MyU!R+`hV?@ql(Al2UB@GwrL{x zKQ5%=ZS=M>9TiSkkQq;gaZ;(Xu+Sody7jwC>(^zY#J-Kfb2<V1^A#aDvF9rKldbE# z)FTV!Mm^@M8mIEEk^!iqEus_EPf&3l_SFHmpS(q%jeSFtyq)mKq(<6!_7xQ`XBWGV z?y0LnKP3GUNjb;ht*ZT0ZQ?He9lPJtnrKRH?olMf$q~zs48q<wPgG|c`eEOmJ#f6y z0WM;^1P(gyjT;)0X!dtgtPGaNS>B(hxIJ>rR+8=-j-}ptw0QmyEU~me99Bf9rrsqq zTo)T>jsX1|bD&`J3F=4Y67?)wyqtK0R=kr&@p=%iw+7h}c=6BzBCl$WhxaU`BVChW zQNsv6K6@`6VipUZqrLgp)tUJ7pd4BJYrE)BSPGhTC6Qiz7YPpsWaCQNDZIf);B*r* zu(V}3bsQFFGriCh9~zsYle;kuI$?$jSDIn2^bh`Rb{0O*EaRik6>w!`<~TIK9D|;1 z<Y)CB#N(Z0G#Z&nJ)}%TuUgV^y@?f-P&mt<Ela{)vDwr+EgfCMHA(uT4qjZF8Siv3 z?G6XA_w&gnr3+MZ!W<|&Yea*#&!xrv6XCqEDHZq0Iwp+^F0y+qnSAbOcn+7OnhAOB zJ?RPs2|Cq30|W=3^8K8n_}q?6IA-0>-gR5aAK0A%z1YU?Wik$Y*pNv0Zg`3qdCuj7 z<Fg@Xn*_HodLT7<ng9iTGpK@9FM8-i3|!aQMuRGL)2-X0V9unmWJRJR&KoWOr>qY0 z=&U_D_8tK8c|s~7HG#kXK?*{)PlI_QqNxYZ!HWTU;Owi8rWQkBPNf8VwpPTUeFj2P zaBq+sp@h*2CQxk9N%pm7qS1Y6a%%5N!MY_`=yk1u>&SKF3|mjL_0mnGYQ87v`KrL8 zt6PYj#sv7DoPa*(0(keZbwoT*#Pdfy9&x*qMj&|SpQGpAZ29Y0@$&CRslvHjAEI`} z6~tpW<6TXweG5tG&|rv~(?wQ#uMl?S%m8ygbJ*W1hwW@W$&{<3drwZngR>qJ<rFrL z9ztouAprkf1{g5j4kl*o5Y8WCN#jhNVcG^wR9?NC`q%41WYSm+R&Az=f-o4MY0tH< z9DzTV%E6aJdA$2k1y>*Sgu5$Cd2zdVnd0TRU0XqS8d9=EHW*dP*HeXqjx=IgG|p3& z<`=(p1+}HxSTHb)zcxw}<G#7U_HqqWt~$Y09CiZ@H4k*Y@`85B93`J$t7Dv=B04?S z2AiC6YPBUAGg?;j;yz^)x6my?({Z@oCDNWBO{nL7u18n$UuDWG$-%&#^>m-H{a^PR z3AL-pOZH8gLldK*rQQWbPhC!J2P=WNU7Tx#-^m1{=_r4ri4*tF?Ak<bYI|dc$vYzM zBOY_AM>#PrttRb9rh}L1WSqWs5&gDH7A8%o7fsO~h)a{4Ks2L(z8W7+Qi|rmz;sy< z8rpHMb*93jN!y9zd=Kh6Hwr}O1E`?!8eg_0<u8BnGR4ag_YZta$mL$C_<pDo@h=W1 zQ`(d8hqnUNxg>`X13d9^V-OMd`Sofz1}_n!@Qy4M_m_~CK%w$<9Hp7VMYKvm##Ajl z!#*_O)@6c$PY=<?U-~dHb^==`B!m4I@+4onkZjwYfEO2R;MZO-C7aGhV0(Hc5kE(9 z|2Mrual(%wwDR^fBCa*@zFNEwZ#$7lW%{u_Umhldcx?BcpQFOJA&6W64W6!urMxFr zOAV!SwE7bN^D&sHUQFvpZzBI}n}}uuWpTjgLc;C!#_QIdf7!+TCA}|j*5lG}<}yNs zvRZ=L<0<HIIPR}Lc6ZD%QL6)6Px7vv*Q~4%9oi6wyR}PczpOCP)xcx46r-_vpBlsk z@-!sD2FuNh={}(!*0?>UubtF!%&r67&(!GLIEX4%CSZ|r7G0|oB;2ZyhK@edsEOeO z-f?;ozI(rn9&BGinlcP<@LEe0XN{wc+|l|3w02)Xb7pIEB`cCJAa&VaEbh}&J4$#y zKM7~$<x-hlZ-ob+q~QxwXL@YvQ2wH2CQ3Z${TKg?kmr2*B;)wci|Iepytr5Tsd#$H zY`T@o@oGY5uU|y_PZsj7q3LKGEuiApCh=z+@#iw}=b-+bzew=Jp-|VL20gV;5c`;q zWPFGlh(EiD-)lW+Ttf|O$D_!&51Jj;#;hqONEI*Bol5hFg}@aZZmZyJ?=bF}hBGdy z?~h}vrQpXy4j*l6`|DaMeyn(o4L=)>J=vVSwZTeJTFoiipcDy8og6Q2FFhq-IWY*G z1$KXxFCM?R76Qf^V2LdOVf;`ky;u{6Bs#J0FWHk>T*C3wHQ69*BjoJDe2#m@B!j=( zBC5Er@pwc+G=O>q35)tdo!$MQ_ooEnkt~TG9iA}a`$E!nYyR=vCqAIGM+siLd*Fq{ zUJ&l7NsLB^;;5io#JbmK-njK0oupt0Q;Rgv;k2OQ%K%4cdOQeU>sVCus89#nS(8!y z_&_{6st?TDqJUl0rlQZAa9Hu-Ds_}p$Fe6TpgOFL>a|bCAek4$<JK|iy;KU9PIQA` zA=}8dVi`Q5=mLkE_mI`E-y9FvIfH!<s*9Ko(LKH?cLwyy?IO<&V^OeZ51F=Z314wI z26u$*CS4lW`6;Fmm|#PRo{~Q4^?VNQzJ8AQ<qjrQ@q3SN+Z+cD^Gc~|j!K2upcH78 z$)Ju$6mgKUHSAQrLu)q-Lcfv2AW(RRYN&-{j!^+I9<-TmHJXFgy?2nuSJ%;lalI<0 zS!Y9o?>2tDdsv0LZ5CYVdd(-jkj5Ps{b738O+GZl4eza2hxV1d==zJv7?D%X4O<aQ zjTf=;#)xK4I@*QaKbnfOVq{6CfhBE#Omt@Zm9(vqr@z|Maq@u4oLr4D<@d+ou|_vK z=tBlIxs!qoR?;*x(3x(~%0L<Q8a|MH-)8iI1l-#aO5+!eql49K>5*$LcyE_F{EP$o z^{y)}uvddC60<C%r*Np`Iua(Y4Yf$}6X4BcW9W0cl~%m+W^?gJ$a8~-^iaMRp1E+8 zysF(zPqg@<lH6U=T(pt4sQ6-J-xp-yP<O8H-Y|ONOA7R>Tf+5{wWG7Hq(KE%3$=6$ zshx8oNYP4ROy5Gf%_R}G)@|hk1NZVyQ?r29Rd8dCSMZv_S>UQxKxPLG6s_Eu2)2@C zWI@cuT92QxFm0>>l(KxbWce(=SQCb_eAZ(5?4B$M6Ip(GviuB;`a-(%)`;cp8+Q-* zPks&?9SRfv<fnG)J2K@@e)c{-5Kgl^jAeOfE2$1gS?)>yn|lz+a?g?F9$6{{+gR=) z%e@7~GH{jU-h7sOFAQVBoaLA|%Q3m<bKnNcrO7Opd`u%?9m_F!mSfe2V_?mn+&i^l z5V*1YiDdcXa6}PwSYC-(UTLX?!{YzWB{2PyOMa|B>STFxhUJNR`Y#f{AplO4iui`k zWSBBUk91g0pmbFnnAxo&yLI$w)X5}>T{@Cvj`N~n=Bc3UsX(spBs6t&8sx0*<n~N3 zqjfo%u<xw{SMgYeo{dU}C|O(5cWjDqlwK+b9aq)nZJbMoBxOO<=piB%+xz@pHCwWQ z<;(|`GcoZ%9<rQS&vItO>VJrzsy7}8K1$MyHj<Al2OL=rn6>RDORo5#gzjBZW&4Em z%=bjoHOI)079oG$J)DZZr$B=9QIXWMLh3Uz5x%`XD*E!gke)V51p9ZP{3>%dIwm9y z(uc3-69f|UwPPlX&#L5?%KhM-B{HE*Z7Usm^bMc4GZs?YYw5*a?|2*=361P~wN_jy zS=T=T4mRE7%FWJ@e^x|5PJXFyX+tFmeKZdy3|_*2`Nor%gQLJwMT4patS60oW7!<I zKX-{TU0oeR{8w+`w?@uD@4KIfS5P4tbz&as4h$m6iN(U0?J4MM8c$U3xzX8ul5n*5 zII=-=EzS5Gfv?Bp5%D<=@wp7~`HRmB)I~GBvvJ#pLf&3)9HdC<qffdiT^ZpB<G&6> zw-j$aMqy!X<*RJGT}wr~CZ*xaUFZ3<r5qJL1niqIgw1abrVl+Fai`oMOus*i&*QT2 zqTWq@taLCx;S?Jy9r%$S-Y1AJ9hL$1ZMS$IB_(n-#}Q8C48RRr>bZA)obcC%{@DKY z3RfB}D-hnw!kUu$-|JDk*Q82F%*TKK|KEAigH$*xe960)2<i8Vbhg%DTeaL?8yZ}Y z4XVQ(Y}{VY<7csXu}P5*Ht*le<Bx66#&Zf@Hlr^F@H4B@@$ylrnvsb%^nFD-R&U)_ zeU%++7Ly4x%Ik!diM>dRbUNg@=y8ow6G(ZnF=$w=Bd3oTf%j8ixO%jl6uoLDA2a>X zQvNX6_@ar7jmbpKiaO!CgkI#!@(dhhSHo}5P$VM?(s8(EB7bI&8HszUGj@W-=c?{= zw7hOJc3y>A_3!hYxua5gYEor4uT3bels8TJ&53Uf;C|;cvU`vX$P0}?BW475Pl7=3 zLwnJXHD%n2f!XkO+Cov0=0Z|ZkPNk_(qVniwY>AM;Z!F-4UT7+(4x(ccnLO6?t1Jo zfA*mfcWPrcJnf^+UyvTo3%(3NGv5@UMwLC7FO0|d>&5(~t_`GrbTT@5M%PMsEh0Wk z^zq%0Q1XN0;MQOlh?3MnwYrO3Mn;}szG^0FBx{rZm-hPq^)U-uV?I-^mT;5i0jqzE zV)cKF)xUV1f2rRl(77l8<FBJYydA~cUA(;t9Wx+)aTp)-ZZHvVYw_5+l3mexv=%yl z>G~@t=jCN!a=S9k+i{eKiD}sP<|%%>D$tl^*;upQf!{n^jo&EBV$VM3`B_$O!lv2D z;NG-FC?bnU;rBT94((#z<U}#iyFJM8W#1^X?zXP<_Ap#>Y3pycZ$4*wab1aNxBb9V zIkU`7%EsM%WP3J@Eb+9lVR<{FDjj^>q-ru*-m?6}BNO$wT`WIGNmy6@82tTrUcDGx zT48K4=yzU;=j6n*&ahXcgWPJ$B}eoZM!n3!%WG>m$sv<5=CvAXIj-hrS7qYs`bVP2 zQ)Ef;RW=4SMFrMQUiBBB9-%B$$W4a$?1iLP?+G9=Qw?5?TKN~>oS6al_q)~TmKu?B zPvwrip78IvuyZ{6pK}zib8!~eueh$S_EHeEjGsu$*_`U9jX8Ae(eM2D#ssKxF{T^% z;WTM~3f$SY+2%X*Im>)>l^QAEazf<)E(`+mPtg}kgZQ+Mb0L7V(T)BCtL3+cf+e)k zeDjZ0H@AhtLz^~QbY(?#E3-!m+UVo&E2>3|&kws#dyXE+mzadYxQ)-~I){Az?&e^a z6>CQOR?G79o~DDtrEzq{96kP=Q93vsK0rGAW${l_V?g>;8&TiYi{IfD3RCr4$@O6) zd4-*!fUozG;LVA=vIJW@^|_Vw{JgAs<Pmm{@Trx^-dkEdn{jzpEBWC!usXjy6jpt0 zB_EwWR!wC*Z1fE>()Ffjl3zIFeLYDI8)Wm`x=7eLo_(j)T83`xOn{Ar#^ja4NUENn z0^;>1UOzv7Wn<Xv5|$?t5<eI_mg?6y4z#rB<_;H=8l$OQR^2|Lm$lWOyOgSoL$dI~ zuqXWd5~09In1wdJulYS2Lq*dTq+!ehPc|?8QLuDuI%c?zr@^Y(qMyAppf%2v&I%kW zid&lnS%J6si?jO*zT{_tibOLnH#JvuZbSwQQ!$}^cy|%|UEn6_*ZheGa+Hi~KJ>ob z-4DVspMT@*=7sxrRxftRtO`3n-@H_ECMezcOqV%DnwK$_Vm!Na)^EG)AA8Av`Mfmi z_W9TT-<-$R*^P01$9Mm(ICuY6x2^kcwVNa8?jQ8~y420uf4F1l8-d+VHeSsBG!6cn z#qFl$PU!Gv05%@gGW!qz@BYj8Wns~UYkZ`^DYI^-j4v%XXs%(<`*?L*80H;lq?y)L z$0_3k##xU`eseNoqmqxux_wqL?ryuLwH7t@Z8Fwh7^`Tc)yQf;s{W8U%A9WtgEZz7 zq$Tm2v;H^MH5mI}KH@BXY<C;2$+M{0_dvRul@GR#X*Kf;A6tvZ@E`7u`N^JjwVRKJ z!Hii=v~f#TO>2)ZuynjlFYV2)xyd+?@%YKhYAf!ALD|tpdiG9}p!04Rd^yrc*O7CA z9_-k0?AY$#4NJDE`Kj4d)yepf;?kPAnW{E9C6BGv1c%{~Q_a*WHLUW->@akwX{Ksv z|IM0tJ=v{E7!Ez#Onb_GJSO{xSMEA};y=fJV|BGQ(5B|gAxG;^jNeaNT4OQoOLc$a z7dEtgF4o>SLt9?l5fn^{!e+^n)a&Ux!40J-taYlR)97=XCg$VJeAc(5V2WZST{gyy zKOT{YriwZA{_z&R&+1sA-=n!O=G+<T<<?Q#GC35?vhLH-mtWP+^9Y5_>G!Fb#%iIt zLKK9V*3s+}MOE7#MZ!g$dRo3=bZunoT;S!|JkqFCh~F1XBlgbb*^3L%c`ApRZb9Lb z%fmzi6r<3S#j|~gxyaTn3LpMLTKi)J&Ut@?$fp>><Yp-|D5@iGenvv)ot;99ca{(< zVFo{*>!Qc=9#H#P4Za0>;>B@no^0ejPE}tQ%bJ{EZOIevMX(O01iQkRDI0~B(Oy_- z)*C_s8-#H^JRxAW3RI8$hl_JffUS~+WK~fmSIyRTKJUsU9@c6ik0>vwvFHu98%_)N zFVTg<WGDDx{+!dueLymhz-Chk7`oI64952WAEh0n!!`lGn-`MH%c{6SzepT+b3I9P zOCwGroiJ8M5iW*pAq%3j(82yN=YMe(x2Pc-$;aN@<jAw4&T9#<xBpIV_WOJyn{Eud zrB-uE@ix#_-()$yX|HAX_0;g?4a=40|8max!m5pidSkoocP%$n2?k91&0Bwr0Bu%p zHmu&x-_(ZS2u0{!rw*y|<HyE3urYthzNEk80Wx{-Jm??QgH)>BBpD@P;FG_EmrV+& zX(`Nx*A9_<TjF3YSJxNbcPfHsQzvz$_HbZqD-q5;W3$-h9(Qz67EF*Z##!n6Iky!y zaDH$$=r3K&?J9TUm+fTF9;@$gU)uL`6YeJ9joYU<XZ4lj#L^@*f0;{a*Q$!fEsO+} zsv`0*A&p4Q?65d<rOu-JT%Hy@v2f~r?l<3lHf!vrN;j)+d;PA!u};NVzj?#?W;$-q z9BBMp$Ort|PhHFALF>UDq-EdX<GsJc!{q*($q(UnQjr-Bqj%(x<zYHdHNzDS$8Qog z3AfV*W>;qRrwNJh4i^)<g|B!=-7L^ZQs8{9z2>i8&H|stL{9$6CVpBZ%hk_|i1v{E z{6jVeVWHs79h!5J-?l3YJMC6+J??JeckWKaVBun7t@(t%5toEz4;GVzms@z)+l%=2 z5t0YmsW5%;6moGOTN9^~0@=fzh<~FhSr(eYmf-aw`Fa9UG9neyFV82pf8=lvjg#Sn z;sSDg^)fDbXflYxbIB>66@qV@l3-q34hg>%D{Q!v1V<|(tA_e`{;re!S<zJot|tHH zTzQLQsxfN6@2OU8(XH~GLMyxLu>WqOBT@Q|zu7cGcdSg_zxJdR24h`JG=AH2zCN@} z*IMzr9IJq=v9b>a{LZU~Ct}B5|Hu9}A8gw-_QSkl0o&9X9#-70eegs^5c@M5s`_y? zuF+Q3tWN^}YGDnI8~dBHI}B=KRvowQ?hEg%?pGr_`O0sWZaiCU{`LEB_S<u@I^R#i zrrXDY#^ZONEj0g0itwK;skpx;h)%X!C=3y#;-|UcRPRo-aGrWRP7B&jH*a1dw0o9@ zL9?A{{~K*WTbhPf*G#1IzO@R?wjSm0Z(k_t_>l$Uf*#atw6CeT&B}i+TTrtp{$5QR z<E)G2eC3_hqE`~xQ1avi7kaWt^y_sNczRWGU-=wS+nX$iIgkeLJlyEgx4(pK_Uw5- zKa3W5ZxHU?m<r#w22tN<B|_2NG)Q7&Nb8r%b1z23Lzc>Ry0z3@p!6ahq9Zobj9(iB zej{@Q+2vtyExw6*A08m`$qxbP)lcc?jq)OG;cVFX@DV-uVVS_4`IIFz(H(_s-FmbF z?XBN~e>FJ+jGKqkmV>g~6Z>_Q#^YnL(PTfJ5wP7#X<RJE+3lyM*Z<`d#;uaqDz7jf zmr?uar+<!AHZs;{++rJ5X~y^{JGMGH6K}5QO-HSYx7j!*0|y@+PUY5G^J!t{ZT1Rg zgTd=Z^w6_AR{Y`+C_DF*s;jOMbh2^v<kC1gE^3r0NHrbVS9hsNn1%@J)9}?}H>#n& zR`7!P)H0vPOOtVM&unu0X%Ig}kb*O&%q3b!_wh2BhJx^bD7bwNsY}EY!H3#dc$2w@ z4!rqDaDnm1tUc6p(*dg>_TBsZIj3kr$70c7w@8?9_7u&<KvAAo6cjcgy*?%xzHFaQ z%AIrh_dzL8Q5{ca95ClEgkH7zd@c<;x4Y4AN?c`zK{{5>aG+&jZ35kGF}NEK(coFR zqNh@csBN&8e%Ux%^vjXWgM8jV3l9Aw_^>qwJx(5?w=a5PtELLP?|F_7+&c+<E7d{k zU@k96NJQOPtBH)Mf=J=(V=7%33{K$}c%M+`8f&*Kn7!}?@3HSbIS>&7uRcEK#~${E z#tJ2f5FF#zPw{~LH&nsu^&UPZew-lEo6RF!-#~XPU04}CJP|!Y*U+)w@1Gdy@vjD7 z<r!4<asF4E-5L&Z5mxA30ZU`ncg<%pj51OXiI1iCJ}V6`4psAhFcsS~N`-p!rD*cK z%)iFi#mD6DZU019pT5NpsSNyUY<#Ao8yF}k^SZMAa5=i-v*X5m_GazB#_+}0If$=Y z5Fc+BpJx=G-xQy76kpdNK3^%m9z%SchWI>Y^QUv>{*JNuVZeTJS*e(8Xq=7K%{$0u z^9b@iYzB^LyGQPN_*g_chG0|8Gjb=SoGeI)z)A}*@+LtNiX!~5?Uo&B&VEc(XHCV; zDa(oeVmqk#FaTeBPays(=5Who6yls2q;tJ4#G@_F+mu2S;tU}|)dr_;cP1~2?wK2& zWb3E@nMvII8_4+#Hnx)AK+0#2fCGn&u?shmVkKpe?y$!-v-gql<`Gmn{NLDkrDD2; z#caxAei~9vvsr9MSZp2HkEs%iXBCU*ZGt3r$N7ZC*?+MeQWl%E&jj)_)(~S@3`<xH zEH+GJvCU+$*{Yc18y0g5i`mw{fnH_t3}^8inmq!`Sv)UUJY`DCD8b^%VDao6?v49K zzou-omP$sL;L6=rNQ$p>vW#;XPh?!md=4@nW#;3Md7YNM08BNM1#iZsj1w8pZ(GRY zVP*6#VrzUE*E05Fyk+1*@}R_;^5*fs`OF`d41GafH7q01SEoRqKOD)}=;==~@U;;r zrz(LdV>QM)jJrZB$(@Wyn6|zrdBeDcaTw!0<F<28>JmV9YXM!!_#tBr# UsLWD3 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%0DTWcO8uL zH9KI$d1D?-`8ehKmyCH&I(Hwr^#@nASi>ABmv8&QN1Lr->e-rjd1NiW;@b~)Q(iQx zmLK!!2P^fxcv9_N{(8wI$m!w5oo?*qJ17f>=QD$U@_D#02@V{Y&#KnYH6)Z9@0!A# z_3QZO1WTBC&lFhRI=+kY<En8md~+GUdVdugdVCzzZYtx4?yh2OevF65{cE__q`v%8 z^LW^1UBhi+`tsRM=J0IRdp<ru9oJHxM0qCVjxU!p!&dDua)meke6gIJR%nMMlxvUK zaf=>Z@$Nux{8DAdXH(9m?9;C^&fY}VcqVng&6b@pfpTVY2OPZL#IbgCCQfgDCOj=f zp+9|YvGjRf{O9Q5pKH@`Z&YtK^GCI$-HcQWnK+cK$z3E&UXY9nForFD*eLuOl7uJn zW0=pJUTnNc5;nCP$_$q?R@WsN`#d#b2ep9hyiIc-|9C1q{bs~+exzY@Q?@Yp(FdVT zLk7;@XeZb%$rf^YWZ@xmd*RdC%Mv@EEQEc_glA!zSi8^>O>_>hOv*hLIiers+Sk2t z*YI-gVoC)}*)yn|@1dNLFNepTUlHzAkAgtTyI%j!gQ}glj$$)wemoMgPdM?{O3iF0 z<xYzuS=A~BC~9K@8z~o4-cMP1OgESu;so0?O4;YIZs0)qYR6KxY11g!@jwA)D+GuK zDW_2W)-FJtW)(wosJCX;I>>z}KUZtbGAOTj;07mDHgW$xYS^0cxb~a)I?CPapR(v3 zHu%%CJu=D?%BF+b<JS+iLTBeGc<B0m?$~52SW?!dJf{B+ez4V495+jp7WCV}ThshA zD`;2bYjPJlF5Jk|8%*I1<qwooDW9O6HN25`rW{P!mGUCWK8anRbXX(r`PLL{DcjKU z3Y5ntbpg4NjeH_4GnevF%55pnpV0-LjcVjZln+xLPT7pICB5cEdd))0qbT1DYUDd8 z_e$vkT9g^(?tii?<tenxra#M!qg+h+AU*z$-s@d(Bln~Hm~u7c@sxci2T;~}Z3+V^ zn^EpVxs395df)G~%nr(1DF2{*ld=xwHnhxF%Jua6vd5FxoZ|@{JkfRKSLRB21?A3^ zojbnZHnq38*(XnM(0IYUZ{FrlK6=9Kx=lQ5_Xg?Ol4;QX!6rWS`3C7c%5|mZq(|28 zVAZeVVZgz2((t?;OyNyDw0^gnEqLD!DqLKliL(5McF>3N+~Zd8Yn3Y8KKzPFDTm~$ z(i}gpSm=^iIJNiyJAD6@P(itH(E;Xs{gvQ<E)CWlTJEfN$bkn_ZoPN8^U#A1eC@sw z@T2SkU9Yr<U!tr)c`D`ATU9}w=2#K}cJTtra+ISfM;kda4@kz9^+x;-<x!MJJTv0m zn@zd?!xX$%-ht_VGv&i57wqW3ws|YS{JU-Om4^jvq|Z&AKIaGYxy=#fpuy=IA2G`g zHZE%op>rSeP$OsPLDyYxE4#=yd~yN>MNQ!HC-~-{wqPYSfP~WHd{M4B#7c}IZT|(H z{?!o7&zL|~|3^HC>%fYyy+FDCD`(v_LI0923=D6J!QPtiEVCmd*tSQxfx4i0Rtfq? zw#Vr0y<kNbd%Rya@PPB1{-Cba9itbVKXAW?H>l0-hMV6`VZPm5!ToDLG<h+eHHelF z*<gfgjcQokxZZHMYeyW}_X68(XAfHbO33IM(bj6l&}phResfcT?(MW;F?{12O9$>< zJ$wv!EgQ?F)1K{pTABiO5h?u5^gx!fWExmaQ^3Rz)~rKOFmzq8fETZKhv2WB;CQ(T z9~<ZiLvHE90E@Z&+ca;;Q&$5Q^>w_@^}b+R(iifpzl#&r4uXO8I&j#sSzMRt1E)2$ zV6u-H4-fYPzP}?(nwtf$*M|twn6J|J$FiWWk($u-tya1`ISXcXxF>mfH%_!&m<3+j z%_Y7E5=8bP6V7@b7S3m@9XSz@1-C6%3Cnb2q;v0N!QKzSlGa+^r872Ufm-83Nx~r) z;po}kynJmm_!}K%<HL0EWw-?HZduKiRakJFr&B?yw4B|q?}HN$H8CGKb$E6u0{xA) zvp(;)vA{5AY;)X;oont*b3l#5r!`uv-H>Zc*=qv+8ZwR*_pW407i=(dd>Ioy=|kKJ zH!N4v5?-VmVs)J>ek$%P99+>0a~0fi=~=1G>10DpdGC%z>3eLx2K7YW1KwD0Nl#i3 zsEg`bym7Qsp|o<8E|$;s#FIaINiIhkV2=@=XzHIO@n2zpqgM{V?rp|NOEQcxFUy&> z%cms|EiLd{7cVUS^1}I0j2_x`^TXi}XG^SlX=5+tDR3^Kge{BH=EF8*fO^ah!RqU6 z0e_~$GNp&Y>Cjuk`L{7}bnI64=Fw2@u<jOHMEA7WT1KLC;VTxMJAkj&2*aI{SM2%2 z(0vmkBGGr=L$=n|et&10^V(u%75ms!!Ht_o;>)L7S>E<ve2S(Yew%rT$xl(hLG1@( z2gwsA9d(R9IUay3+ZD0n-<;6HP6s1Rj<e@St#F{LE^eMx#-{Ew!ukc4=zVPs<5$el z+o&&=jA(@?`^iDS<o<9$&zV~mX+qTFLC{D0lgM}wY@VwOhu8}qlJ5-j$H;?zKo!?I zr(&aZYcfny9f;UlvhUW{-mqqW71!t-#e&a`gXFjhKJ)BZ7U?hoxZEDjsh19_4TLlG z&3y3OLGZxs7z^I;nGf&j4waU*?7G)Y-lL-@)J}fGmeagUzmEAp-h{_&&~}mC-_`}k zpK`!Py|rw!Qdi9U=7QZiu4TmmMyS)t23t-3M(4*$_z%MXObYwRMw_Vc$KGN1&ypw1 z(LopAE;UB4zMt6QyFd7+8ICx|r46)|R{~#sGwci<p&eI&cW1j}^8|9m3zb0EGzhuc z0H!Evz@9t4_{muX?PlB()?*M_L~IkEpL@;jRz%=JYj580vYh#;#9-b9Ed=8>!T?7< z{QfHoKJLG|$II5y>ByEWxc+sJu;ktbsmbOn5J$P~8T4_aIJ7zoM!&x6JiV)#*z;`` z+*fm#4x@A2xz6)>#Z`Yu)KP@s&oO+yP|XypqF_n068dc_VR0)x!6PXP9#;nlD(eh| zyt7$we%6gWy911bLr>{_r|Rw5tWYognHq&jYvlI{jnCLG@jdg~cfJ4c@eycd{fTR_ zK2SrQu=B7A9vEi|&Lyp3%cV>>esaIiakq|e;B_X*&Dta!t9BIh6EmS!W0k};;hx|> zvw-<qTj9~3#;BxD-(~y07<$wc=S|3G?b^^hTl>tBH_`dN!e7FO<s&4<)R{Ny>HG?} z1l`|V%3Y{Sqo_agjcWKk>Q7luHoGaI4)x@p{zO@S%6iqX?*%SWuUb+!PWWKWHK-d+ zsWY!m59ArtnM#e>JV?<M>mGCgf%?$wdSA4oJ{+P&{b}HhLA9!|x{oO@yyA&(0=vQG zIwSt2)*p8$YJl>MHvIB{0K7@tgl@ykc;F>ZJZshMKRr1kKSVrFJ!wyUsJYWzD(gd8 zPcBuzC%sKQDeKRzMrz_u>Q7luR(l>67gA5Q%g+MleMh?Mq`NSidUEQAV5zJpW&L@> za+P?C`qRzRk_WUOkNvM)VB@J9ZJ$m>q;8aTW<$6HuTW>odUDF4CO+u@dXo2|o*Y3v z`LfE3*HBNYP#>m^FXIyG!*<k@H-?PkTd5~y{du-Vi_7{mo_f+(O-q#Z<SFXO+~Urn ztS4oCSaeBGBI`q0@9FzzN&TqzWPMoqqnA|HhibojQX=cgKYb{X^`WfyCOn)imGz#i z5BGd|Q7P-geCo-RQKzM{p5#eWV88qp{>f6CpQGNpGj=P#O}#gGbO!Wje?@ePKPP;A zo&opvZWpa|s|8sfrtP+4_J8_tZ0-Oi>q8sry?0F&OxAm{e%m$b7<)$jCO7L6lbfOd z9@Km9s1G-6|HURzAGT{>#I}BOf<e@KTdCjXU!i>j>bIrTdo%YLK^^s8KJ{V4Q7bT~ zJ}jl)JJwGQWxZEI{Wd1w8D~?!ozwax4&XspM7{UocOT+d>cflFZ$_P?xDWN)8tS*n zXV3D8KmB$*R}~LXzajOT|J*_NlKQQHdaU`F59U&j)lt70bo4}7zfGpz^Y7`7)zo{8 z`mI%27x1NiJE^gj(KrSJ>NHu`l`3_GH0rvx)Nhr%g#GO|FB28^l=^KG^&4~0g;&&X ze$;O>@BX0q;~i0hI!&3Y;3w*|OzOH{a!NRix^6RdTC-FG4^yW-q^?USRKgzAb?>R) zhRnDn=2O3IpdRaG+(vYv9-B`6_TgnYm-QP^?>#>En#+1m)@jjAgTxioX|f)B@%C=z zf<HYbs<}%dsmHqLFW{$K0`R$0TbTd5$9OC1v6a+gl1(K%hI-76dMxl{fY_RPtUvXV zChLQ;UOGs<w11o_jpg6HbnN7Q@k_amaFBXw@T^VZHtMAtNttk>ajtZ;(>>u)Rsrj4 zZ3RE5mo9eL$`0E1g^koptEiVwwl)Kc{pKj8Ua~LzB|cg<LZUO&8FwzyfS|cYIsOdA z_n+$6;7>F8w{8<~z>mvJda*Un@C`(stOTY7W_*o_2andA3~$1>Gu=l`Vs+n0c$@#2 zEt%VihYXwoHnU1t?R^`vkf*_kvIQ(Cr-;9P-pVHL)ij7av7Gl0U(ZHqMZ>zI?a{fW zly%ze2H)c}F@HdajqOB#c={xOH+pu1lR56t>6aSs)!+-K?7Dzq=xly$LNM%9`p9Ox z-sbK@3_zk|3|H&#@~^$eL*kFMqH5bc{5YL|nA4?72y2zk^NvmhsQn@2(>+J$={=9^ zF_Es&Pr+;ZxJ^0zj?NDbL;tmVZKA4aKF)sz<FC{cEF$GTGm{^Wp>Jx~G)sZ?Ths@G zDl8!S%Q~jO<guRSc8I>M$aJ?WW1G>zuw!zh*nao`oEuO3-O5_5p3Y6Sb^T&<_}WlD zW?dFu%dWMt>@`k2wojcGZcl)LgO{+(&HcHVTq5l37t4~*cyaMZA_SXzGM__1px?W4 zzx$i^(DUeU*jPDBRGgp!E(3z$T5_gnRjLd#uLMGF>i+#VJ=DPOrZ<Eq9v44AH*l2q zg94S~qCMRQd3&2DXcg`hhj2Yu)_M?_(g~bGT|Ic!-~nqY7m3U54B&?6Ajr>LD}MCT zBg@$hGW2zw{AU`%rzx)Ru*tXb@(3f)p<}1rQeuSDnHN~f^%$sL;3Cj9i!A<4EI2rg zV?AuwuvR@2VCPv0t5`UTIc{xaKk*^+R&~RVi|g3iVGT@Uw>ut7Fa<@WTIS)Yj|(@M z!I_R1*%m<`Q@*I8!dNc!*gFhMofYs}hjwCnr%>E6`X^ssZz<u%Vfbx+d%R<<!z`x^ z#poS$pO@w=>A+!=(XS2X*$Rg%;b1I!t}5iOH*6KA2Tj8%Hk*0Q#&d$3&s0?1p1>!c z)ZuSeCE{WG1$_G40`ZkT%{QUDk~z>hhL3qidGXXkY>9dp96Gw2>l`m+KDCk1MkwQ5 zUoBz-)<?nVyb8V`Y%41<ozLF8O~l*{YRu9-h6SvdftiXunTNYEJM5i;>!6aAPaMLc z>AJ(E_NS$%!vd{i8?vy=l_k#Mx4rjH_?3k!;jLiq3ol^4JGr^(eb)Ee2$(e`p9dDt z=8gq)kA1->p;jw`X-;~;vUTa4^(R|)tL7CuwJ8ksX`F6bq=B+=I-AC0WwH|Xr1AKZ z#;N^}%lsgX(`p*Ok3Q9L+4x=ldz@lDjnj9($0Hu5@woE$I7JH@ryn0SiB)|gQLf-I z%ct>ZRa444(s-Oe<J2;IJ(rEs`@hE{o}%%XL*ve6hye;T?t0UB6ek4Zej1M#f2whv z24B2R<Ftat<ImpXu_KMgXc~8Sw4$-gRukz68jtIbPQ^qTk3ZV%;itaG;anQ0eQB)u zys6=`vG$C{;QQ1QTs8)6Y1|F2u)uLN?o?@fWyKq!Y<wBhxN8ojd!u3_MMWBqPeMY_ zpT^^b-{T8q<7?jU@rAPSb@Bf(cINR^ec%6=R3r^VghEQlJSF$6B@HMMQW`YMluRiy zS4tW+OOuL3b0~4o-j(KgPDO*FQFAIyzop^(@qYh4eSbfHJs<0_?mqjTyViL*=j^=} z<yYyq>D-L+%Zc(RGB!zQ%%g6UUy)_AgqD<Fc9c8oTbB#=lsj&eQ{$$W3ynFof^w&; zdWn!lxpR+l>e<F!f;;8ZMarGqiJ5||dl!5_Id!8nUC5@KdQZ9Yw%*O*D&<aNPL1xW zRq8=G)tEaqX^x^Y<&HMxl;g}P;t|TJ#@sn_M#6Se?o6kg!akFk66KT)<&omy2h5f7 zXc6Vh3FV6{oATx8uRNmt^<DWh$}hQLFIXGOuf{wwoXEt+JZj9BZ&sSjnDV7DkG4HA zlQ!m2V}4y|rzj{<etA;v<jEd#5GZ#VbIPsLEJ<TdMN#hLWS<kAD0dojN^#S6u`#C_ zb7xBG2H^$ePGe4ap3sE1lvB%o<q>bpBMZtGhjsq^2IY$q<<Za^lejG9(LBnpW$nlE zy_8?6lt;S^=dpK`M=O5i3v0}m2+E@&0}NPW9?hftk_?!_hEjg1QI423`10kHBeIk` z=}%p`2j$LU$`|Vm(|Pgw55gkK7vqroY$4@~66MSLv(MR4$`|<+6ZwkGQkY(_3>ubC z<f>bw(35!4zzIAht^)e(^kbum4-v=j_G6nx9e(mn1!(9Ra1UZz;x)wM+PShp_e9Ve z7sS6Qx-!cux(y^|T5BOWZ3*n#9?T83*Mi3UC6GpJE49b%E@tpys}bK+W{+P7n}L6h z5zmv0#h{2yLiU{qRzd6-x=Ap<6~TIx%s{!%T+&i?K6nw^)^W)NmH9Br%ocTXN+eGY zTVb@RExK<ikz74uh0g<*Lei8hA>ljqy$xCl8X;Li0I}S(G0gvtF{nAyJCvv~%%sW~ z+7L&(>T}mSiy)()9Ugbl=Xu2H{q1nhO$P|li^CC0RYC@F0C5!YvKtOChFGdnC0x4Z z07=9X+E)orPdPwzw>Vt%wo-^7jwBxTp;E}W>;MVmlc!lF$X{`Q5aRf*RYKB52Utp+ zt6e436E7q_qE#jICjTtr%^j-*S@K^=yoZj}m5v)ltlX|jF!{|#+Exjzt~x+I*)3aF z3Gc{%JMj==ZQ}LB?K@NnM#LM5pU^y?T>9nT$hV1iki9wiG|qD^@i;oxd*U_3dzERP z*BxL1@dg_6Bk?@qR|-|a3+?_~4ps2Z-Q{qMScN$1-f}ql+=<sU(?Mon&W;dwm({^S zeRKBpLM#5kMh9DuQ|3o5w&D(SJ!m~vncGZj&EzhtV2qAC?-tXV-6!7L)tz5c-3qqu zU%|}HgP&IW#a{<|@av0gP($Vnl&@6fn-<&Pu<xhonTRT{$qGX&yNxjGP+!)4T^POJ z+X#0K^kv_Ir{dz0R5+%(0B#c_u|lT>@ZQZ5JqM+N<9K5{Jj4=rxu!z;IAip%%7VHM z8{mvyAU?6qf@8`XU?Opltrp9OJOvBfgYcw{7Hc-`6gUxADk<{Cha13uwJ8oIPU8(= zwZ;@ZZk7n0^AoU7sytNC`Cm@wt?@jYRvi+0v`NC7w+jTD!F9sJ4oUdBxSLRsrw7%v zmgwQrFv+E!K5)n{4%-|JkUa8AfpeQ<P))syaIbU`>~frr?ONptZ(<igUez=#TH6vL zgk*Sda~hskw}N2~-tfSj-eIZ^ff+?Q;ISwMJ7f-lr4i2r4VO49O|gbkCN22&j#s1( z^GD%3VgrRMQa$2^E4p02@+Q0w>p^?fboqMX7U4ax+Y$wSV37+dzuW}?Lr(DlV8 zcwIi1DbYIkw<U|k>%?DTXP{~MV)3GGgOD^i7;oG>#cu022vNl6h#l9;qRv%)wE5P7 zzsi)wo5Xv*cHrspZkRAX6h7It<=co`%nJn-TCa0QCm1Kr@MF!Ph;1M?j`3siSj1c^ zhvJ;CDm<<zSXy>xD0+QU;mv0SOCwBM<BlhN`Ovmf7(;xDxFc~-O&z##-I{kRHAg2c z9mpc~B0k$=Dzlk;pDh_O7U$|sWh(RTvkk<<Xn*e&vsy6jXn>uGj}iwE?;y@KsfA2p zGve*0wNOkvT2l+Z+txy$ssRomo<v+gJidz-hV-fhiJAds5}z}!1%bE&aT^+Q9r;)h z7Z5uWOKHrB7Pa80Vt`wSR}v2(K1n_r=C!bfj>U-Ilm8ClDDqiKtWVrHHyh%1#NIku zIN7KcG-*sAentF+?6UOPbn;0dd$qO}n$wt*h?kOm67g>G2_se|en#v;J{9zRMVfOG zaXxW2@z>_tS*tgDgrQd=&_{MVE2`Tg<P!H!tYkAvzrh;X=g^io?a()<CuZ_{*}x)i zx_^5JMa1ES-Z=C0L%3~RDta7C#2XRiLT}Sj(VDn0rd&vNoC{%RB5{n{5H`N=T+k<; z?=gh+TBnW1Uo7!ew^Fu@IHkc7O}m$}wJsA-epn9JU?F=%oZyuM#>A`U#bc-ZV$px4 z0oy=qSx_trD-76Rx5?<z=_a#tQU!lv3*sP0Rq$A>kNr2Q@=i;?!3<)5;>k<Cfr}f} z>B&*xC250j#*kGIuvLM7CvKfGTa?*Cd)1tyQ9f?A_<%T^xMo>v{JQuqEOzRRgXny^ z(mD5}^Bi}u6>cB>0cI*&;c}|C=Ki=jPMvOq$-O$@vN(CHD%C;Xx1F)4Nh`dWq>g?! z^igA^3~GN+!7i4)Fe>LcjPU7*Ticl7#2eRuYL{cnExmBR|4}H`)x$4qx+A@1fFE~^ zQT4JWs@^Vx7wXoiP}c!h&pHj4w$OXT_+-8>|AE7|!Lx*2#G}~*hZP>Pg!qO2T#(xe zTWq(oLBzT(w!&HBQLgRyz0ywT*uNu>c4^1u$~xgE;_Bf=BG2rLA3t~Jx7~`w;l%42 zy7RHQXQ12Tet7d^GcG0WL%f_guWLVi+^P#YFLh>4#KH1iP?5Ovp<vwIw+K?ZdxHz{ zIL9Km-NPHCr`<92Wp}}Ui5j|}ai@Mq-Gw!a)$p~_J5Zez&T4v(#G*FT@6A7)8Q71+ zb}OA79)_P~_#y;z-#a_p4m-<YiSPHUXNC%wSo*Vp=t`_Fe~Eo1uDS2aN4cc3P5bL0 zmsrI$m1!2%LDU>zJIq{B<&zrjO8vzRAJuSKGSve$b;S-1YIq_ASP5~)XR6IgODwur zxT55P8opQx?4!9Wjv;=q7}#ACs##AyhlsO?o6~29F9-IH*qrR2GiWa}jU!KdD-GB% zI<6@l_Z;z5;&#OJ?+D8zo=S6gxDZ$}@n+&%vw(f2&vv2DMiZ-%{RjD1lfM$NA@K}4 z?f~LT<nK;)O`6-8dNtfg_M>F)LG}iEwC~r;73*kj?TCjGt9((zNp!3Z<l{)=*ro#; zM65$xxo$eY*LM)y)^UfU#LbAecXNmMmt*)b`;VZ~PMzfvhY-(HQfG$O+VaXe2b^JY zf_1*$maiw?VSIwc*2}O~t`o6(MJ@aGQHE&~k0CxabqnmA?2pGb=CGIHTVMq7eByLH z0}L*rHD)v0iMrhk@L^$JoEP6tJeo2HpC>lQu$~35oLD`nIbI}Ymn^Wuy<m8_)s*^P zSzw#H!EhkQ6gP*RgssENq$7%_pj-G!xD-+*H6tGU$wXXt-<&;o7LT*vn}{ma=IknQ z^|nuJ#4vl-|J5kmpZAHCc-k{l;;Z1r6I=8VyJdF3w!|jw`iNF*JD|;irL5sPt*sC5 zh(&Y`b?Cfxr}L(6vVgriF__jBx5k7CQOx$Z7p`t6hjA`WtoHSAY#1zyRUg{3T~tq? z;6V#KV0BYe2=GS5J4$#xqC||{;)Xp{)$vNrc`<rlf82Rl7gs)(X9o)ftdH)A4&QpS zMf2@Zy|)p)yAENB?)DhFxd%qwNn?g80w!+nf;VfnLd)_L_U39ZhBvfF#m5>vdsusn z`Oyc@eLTv(>2<){sRQupY}$*{LkFiGGC`R^--MIC_W$^7Q+xA<cTk+M5HdddVBMba z;N5E#IQxa6R>@K6`5smf+7OTSA&#tExsO<89FOagL)d7oO{`bXP&D&WWSdU5;afj= z{e!LhqzQ_(mVBy@Ej@3^1uU}TN8V^-U_vksEkDcjXPgm68t9|bXD9yPJQsLH9IkB9 zO)&6wfs?De@mR=RIOcv3v?IU515Hyr{jfDQwOhz77F-l;u|U@f<1Gu={wg_~lSzH# z!aDQK8ePGrp9@x;G3IJ(GFU>Q8D^!)@smSM_}XVJ@J_yjS=oj1rDJwMQ@i|u>2O3p zn%f?+hmRqCC>+?#q7I#8vIE-UP8|n6;n*3LD~Y7K?h*(xTFQ2Y^v6ztdU)p3VNvJR zad5E-!7YI=h4sx&iK<T1s9)$B&>GN|&(d+g;$vsvbBG^*TD%!{96AXHB=ol3OTui7 zmO@@gf36s)$B%zKEV#Tn&TMQ#`1jzKVpIFP=BES`r)m7u%r(p*jQWacbY)KcT=*!< z0{B=Z$H!*6^2{^Fcy>(&tV}fHd1-QZcPP~=e%68)=1X9RT`0C0vx_yghaRAHYx>bR z<%m5SYoO1aKU2-bvt0B`2<B_b&%*xbGvbAcIC{_8O&sdw!nUsR=C)JrvTFB(EG+UX zyRK=<_dIOPo7!hLUo4JMu;puXt$1OOBeYZRBb+gg=Z6j*l|1QT#ilgG^Wu~cxTLiS z<f)&WjJG1pI@tzyeemLfkS0#3wZt|)w*RpAj>u)fMYR6<jW)M!XwO$arghQ7+Vjyr z`ta4Cj>3Jt4*Wvu0Dd|3g+MXS6%U#4&V#>++9U0GV8c76zic6!_}S+l_O!j@nQ^aG zY=B=Fzgn}EIh9lY!>hsn;NXw1SxEX=u7093TWoY+y7PMyj|$r<RQ0;dEZd)8t+#sP zqIhjS?M5COzr+rE7FR%}?r2^>z0Kx(4raA<&6^`P71gOnz)|(j%-5_EbcP#>YVYWp z`Xm9@-ttGCrz0iP{Ays~%L2({%N>Gyn`At&&lQs+Widc)A6!&;CY7<@40Tme*rMSz ze4IZPoey`0;oGg5L;H`gG<!7e`*u&F@goWAU3QAwyBuRl+gszdB}l#IE7%_0(YXKX z8fJH`6TkcD9sR%714r+1;zjD8p_yeRd*9xX$CR#viOy<xrNW;pJsK%pHNJ)|`$~0_ z&Mgxzck77hdtAAHq%2>rvyc54){jqb=*F^!>R|LvYk1V|Ba6%)&E>irgJ(NhbKgbO z^66?P^nLt}l^OTotJ*uFSLr(T#F^gXe(|6htII^!?j5;@S3f*n*9~?L)8WJ7v{CtD z9%wGJ<I9aM!veJv&~=M950ngsP5C)+y7^R|8e}MJeWwl@PZIdj-38La);mP+Hp$#N z^O<Cy)n-<3H;RW<4B=DK)X?)#p-`=qNWF^NGrNxC#aiO}p!V#Z%6Ku7d?u2Q75T`t zQs?!nT=^|kL)OS2i0=`5^j3!zUt)P=XFGPCc<FBrt{8$5X=;4vp+Yf&IG9*MOvgg^ z;P%kE<9LCNg^I*GRmKa-t<>@9Dpx$KY6u;PYk%`aJ9U=%B^GIXu<otSR{rLu^KUv& zE$14E+%N$?$H(*j18O9Fy#<g<i04@@H4=^AtTm)Ya)G#kd@gy^NO}-ACm*jtHIj>7 z0>~2|C;v&rO2h>;&Z0l;R3oYU?c+YSM!MKjV9E*c*uk$x`psKlAL8RNc2td2-$!6i z8hJ#GbSd#8;!Nin=_ul7#Lb4*NY4)wSRJvdM~#%`!)QL}H>gHBhPWAxnd4F;&7$!; z5r;@>q^mpxW=UL697Xod#MVwV(&FDf%0sH9=Q9NsJTo5ET&tzWvIOQ$+|9jO>PYr* zVjZt)sq1Qir4c`Fsm^6ryK+Izko}D{=(j#bzjYgRL)OSAn(!Zc<8K{Fzc147`{#FW z<iIBO0OD!nL-8j5;l|i#^!Z~SK)?HW`rRLQG=!!+kn9(J+nW(n?BPL*lfUtl-?4p$ z;`VRc7(W3N+uEgt!rypiuOc>Z>k{gX7KVT0YU3jInS6SY&%Gx6$8Jh?<@p+X>hU%3 zV<7yM-=%5r2=Y;N27KFuo7%s&{Po@C)ePZptV8FglFm;9ou9vP?L8eRIbA4xx*X5{ z%?Ezl^B(BH!!vYkAfHBl)Px)D_sQOY;(>CO@1^Si<u8B!U-%2f*gLY@QH=eKQ!Q&G zal-|8K>7HG@BND}nAS+zju7BB+5g6`quu!P;YxVJa60w7|L=UC>|e>}Bl$Gt>Lzx1 zI)^Xm9M;k~{2TWrAIb%!?+%WC;YYpQa9Uv-t}C0w{u^tO{UQ0pkk9|djd@p1=kN-h z=fClvYcl=r>^q(F#_RLHxfRW`F?W{Iod3r3S)}VcGV*E4G(LX%ZEr{Oc|qgTIIJ-S z{u@`&98~GrQb0ccX0_k;p(EpX!E`t1=anE@Y>MRdfnMxfd@7{XigeHV1Z?|JA36CG zOmbcy7t0%BH-nx$gPxNm&5^~om!sIj@vGpP-Bi?`HIS)_eR<`Du9$ajx74?I5LDfZ z!>1E+pms!GzRg7$7uSq~W>W{#v;Szk{T;DIHzht>rwsCaZb04W)sX&UH1;1EhgQ?v zm`QSiaBpNw{4(Sj)Qfg#xhWFMLcO43Cap1amPOm7?x>vF0gViL;uO2KSd=Qu<JAts z?*1P1O!6_v&mIWojB1yk@5<G!x<TcDK&lUZ7V0PFFq7eZF?*0QZ)2D%zElgu(*YF_ z_#JtMt`bUnl(DSsOIh_1ceFY#NB@Jiq+XuS*i|X@E_0RT=1JYT{+tfnM)fc&=;y)X zwI8z(%WiD)fIz<P(pk1eBUd=08pu;ZE7-_wOCkP<JD+kwj>jpU0NZo=e4)G{Pk1JR z^W!IM1bzO^l_*H{Uq%1lQ+?h`yCvH<4`O%j$8m?+aqMKoV0L(UG+#922DA5H%{s}9 z;RoB~K;wSQzO)~62JIPt^?9<iV94b@`fn2O@n~fhEfXrdzT<^OUt914N#o$7at=r~ zq_EzXgK<^+9B?JhAzrVN1NOvSh`+1mKu_ZRmx9ra?j5Gmy+Z=sJN%7x$tQ|@9+A%< ze%yo`?FZ;yLzeC}{2C66jVwnzwh1@dFOdCSfF8Y<`#Tr+Z_7vPI^e;hXW(zFP4_HU z>7FH}{0ubmb>ca{`Hy`Y-LufW4?o&)SZKUY`NNHN)!+6r#BT%ixaa4?!XNhd7wfmp zk{(L=%(f?u!+*2%w_UMKmNYr(GaHmV4*wgwkX@lu0n<LA%ftIx{bbGm!hO{X*p!pH zydJIaZ#<X2uQGjKqvL1bZ!D#Acz}Gq&^_JX*rC|~HgaMi=;w#<KisVeH`@D>kLsjC z__6)(+>2r(m0}~AV&LCA?{{43k<SKVd-C}=Z~ARFe7u!)IGO@C=pN^9yz&t}E2R4% zt!u&jZ(QnX!%v1A@ik=;@HfsSpBnP9C!arT*@PSI<#e9EcXhzibPoT<U+FyWrSnYp z-S9X5KEN8+oiM@{uVYywZ)n1Q?5zh{<07&vlTRZrX~KW(edrt}(zyzvbJ)nq#8dvo zf6L#0**Sd{B{XNUa~c!rcY(o8IGR|4><$!TjokUaaN{$F`!t8l@-si5KU5R1`^}B^ zMxISRvBZb|7jAz}0gtvafyraNd76hDem|WlUho>lEnqDadK8Gqe5Ub;P6wgO$Y?mK z7s%f_4#yLHIh?(44iuAf;g*6Q-gP?x;?9-u&X@Ls-yV+3oI-KiOa<X|z%ekmeio*G z@WHcLN7#n2R45(mkE}#w9XjPg(tB^reesMHSY(3PeOhPJX$k9YF%a9y%%EP!s$A)s z2OfsO;+|I>`HatjSb8}Vu7|B<cMZcaGr9n5TQz4&K2-Z{!i6%W{wu`27h`aB;y&q| z`ee4LEE0Q1<-sHq4Y8iq!R~3J>+oK-R?=82K=FPII=)I~Z3dPDUh_xA5s|FVpq)^; zeJmb2SHj-4K5r498IGDhMJ)VN5%i7=qyB)qg$JwEEo;BfScB{&ZuhA7RC~nEuRCzL zhcBS}DKq@MxE(+7XuZ{=U=QkJN6%4vmcdN_{<!^hOT2XBHLNJ{qMFcKsCUyVIF~*K z3r4!K_hC<<`0M~YV*8M_nEVbVts9GbUdl7aAF=S|qZfvLl0}R5tswMA2W(j4fqJ26 z9W>q*Pqgd8U02Pu-Y_B()yoV1ac<{U6+lLvKR(-^$*6q_98L;Ehk75@^tWhw&h3iI z;ff8dZF+fHY<k=xsvB2J`*jbD9r}+s>^*j5|KX(l;>MQAe0%Q{s{v{8VB9nIAM;si zscP->VlocZd+?7rG@V=1<4%g(Xhjc<@I>dq*!G+PKlM8%DfXE0@7S}3wQTe6m`wMO z<9B|?>Kn)5{5-|vNs38|J^m;5j_h2?>VL;%v*cX%Csye^uo=H&a+^ga`xASuJLR%j z6qB1NCRc=|vj2(IYaYB(_!Wox76Z8j#phg#Pl`$YCnk4ajNt*lV~=8z|A|S8RsJVd zDGvFcIHdUG5{l396rWaucCz~vd&LxcEeDn}$KNp-^r?vTq1cO{*lYIi1=Yy=6=MVL z?P0@z$KLgxWi0-8j8R;%^S|Tj#EsW%&F^@t3wy#EV@#wN`{MtO`BRK-{}p5GPmF1| zZ^a@g#y(MuHT~|9RRwI-?^rsU&DhcZ#L|B~hgL=9tTC2O|B9vmI{w;${a9mMl~7zY z9kc1NnvT<FaWkH=qZLM3netUNn%v{E7A%%H^WyC@`E1K-;e*hhT?m-L8!E;_2la03 z*<Cs63F3n)HqPu2i{|aZSHgs=*5al84!kw(S)Q31%69jO<2O6{!sv`@hi+%h_}cZY z;mb{1{F~3QOXhr-#}whkg5Ids#R^l47D|F|*<#brHuZUW)*P=co+;i=pn9(dlTky- zQTTkgg~PaQ!*F0=Gt_Ar&YF(X)IZ!x9doGu)cB!Fcx2IM_SVJ(gWZ(StnGWY{f!%T zczuX9o#*=-o$*Sj4VKm)Vok?y${!y0KuhL;5A6o9rt>MAm5BRx%fo&>J@I>j8m>5S z59SUs<z2?<VC?CELY9Fu@8Fbxrx#2XHkawM4G-e*x$i{LxvU?XP%#!QuUrNXdVZSs z#1R*0cgMP3vMgeSK9`|)g%=_}i~Vj6;dK=)ajW5C=9R0)x4!$z$|}0?^5ihS|8ybi zzmSUqf3)Ib-?YWzF5UPwWi8aKp*7L1_4y-{(b!^rGj8H@Roqeb36@Ga@ye(AyeT&w zv#Ed6@zVz+<27NW=saPkG~q!K1}Sb9sDFkK6HM#&k4K1es}+Rd4_aZ!K3ja(_8AM9 zpobna1zfVzALb0bz#cXX!U3(HvG8Tdym(rW5T@)Z^&67R6RTGXmX@gw^L%G=yIYeW z{k(~=q>BvK)*FsDcllGz6fF!&pm+VZdZ2Y&5;}@*VywXlVf;p_oOZ1x4nJam?mOJ@ zqx~8-zP1JK8s3}-HP03Oj#KZnf|2}&ml8{nm;HxN_NY5x6w`;@TQ>0@J|Tk=`QgxF zq1Tw_LUrgN;pzt+zUjaKEQv3I>dG!W&eIB$wpPPxyUV2+izj3B$|u6mwM%VV_$Hyo z_nVTuTX8&n*&ujic}rNnV<wj_7zj6C2aE6h#`BHm-m`~!o^0jdN&MD(+KY4Vt@x!) zAyauWmAkjEWC_tF%<r8y|FQmwsNwk>%#$YYqWPDZw$EGWyWg4H=#7!KPD#X@YHeBm z^l_ri%p^Q9=7{*@d%m!Gj16`VwZab<H-p!C3yhiG9h>?z{cM-ZvbeidPadGw7I$cN zM1?^uMWd}l@pG0Jywr~4%?D2wzIEuwG^)n%D;Hj|CjqkjwNEKqm+j00+G+Eet|y`W z8#AuaJdfEujl`6f7o=T$7QsQVz^`|Wu&MpFyN7Y_iK}d7WKz&7y{1sQSf3|o_Q&bh z&59;aZQ__q7SJKPbJ49rKmP5<57y8xy3j^@4=Y|8!J{)aSuH#D2)tWN=Hzcp{^)nf zf;HvVS<S3>T(QS}s^;htZH~_iZ_)E`H4H7j3y)iAfus2(44$ruF7F2M!ui7mC(R{b zw%v<Y-1){vvtI1e<nQeIi;;Z(J!L*U*al`DaO01cs&e1wLvXWMm1q#Dz&2Aom;o*( z*wjAwD_~rZKU=*?2lf2opu;U!=+tH!j;6XQrH{X`MYdywr{9cGo3*8V+Mijkj8X6? z<0`w7J&^~lddrS{Ru@JH6DW7Rd7`TVzH&EaBTZj0g9A#KHOm5<+TDxIQKO>)n?Kze zX`{7}c~e!GA)%Ty=c4ffTgW`CZVGcVJ+NCP^?vBvf)BLLh5_38Y|Hj=E;>JEe20}# ztL@KC-o@|(;|D@PWmm=wt+?`YTc}i|JsVBzDa;5DteGVwDFNDbnkF2XCkH<MRO`Yp z0qv$Mh&zXvKyAesjM=Hqvcf*HsggYCdVMlmtw1$~)nvGmVS9GEa1@`tEs47xn=MFv za>TDe2K<>)XGo#GZB6Y)Z)oifKLC}25tg4a7L0{D>cKP-_iazWqQeJ;sF(6^u*Mf} zJ|D;2Z+~PT($>Pl!B<!b^^)-lde4&eF0&TK&eRtqiKiNdi`oaaiVBNq@7bnZ@UEpH zHnmT9qK_w+=%JqXZRoVMrx0%Kjb1M8aY92Jt~=EWDz;n_Hbsr6^<N@0*4x0|$LGV- z99w=xqYLktuE5Q<b?1&rt@(!IR9no&K-5z<mGq{45p7RtVb4B~psBt4dR;syi@0Tr zFPy$*DAcu|jt;Yy!+<xm7LwKuYt<_YA2h~bZSe=z^Q<NFSIGj&`9MCc_gZGvMUGFr z>d77VB(c%bWG+44TWnvx+hLr0Hy%Xm0m4RvK~p>B71vo%zVBo8IqOC~TXeQica`{) zBNJHR`mO9IH~zn_S#_RRMke)05bfK${<EIj|Heap`lMj1G1-N=1BMkh=J2m^hWz9Y zw(E=8z09AS-ZroJ>G1W9%ni%)t!2$`{?BnYJf8cLYiB3etZ-GdY4mY<y51&3vn8>N z%%Ne4d~&=B{F|*#_vJsF4SpWehWOi0{xye2-#_#De=t9^I?MWpdxTZvaa-&iZC&%= z9I=c{Zss-S^f2h>_>J8EC;xT)pEd7(AFBz=$OOgBWCL7de~$AX{`)wSv|Vl9)GsY+ zoX^Z)f16#MGl*qm&UQ}V6W&|={9XRT|9u?UlC4D_$3*gqoC4O!^~Bej@E`jhACt{@ z3XN*0FE+j3{KN50_>a8@`83)a=T>0&y=X-a6gG0l*~^Moy59cDA+fWIyOx&!WSQni zi-ykYP`GQ`9V^49o8fY06#xHW8WZc6ye_^NGv{age2(2wY@2QTlkNRViWLhaKlyId zx8k{97Z!gCJtSWFt;M9dVwmOfpPKt+OEvQnE|=~jEslyWVlPRfQ%R$vzu%PR{?=k8 zt6O3QY4K6g;{C6Kg+E%{V!J0aYVo;WS}gq0;;!v0VJK<wv|m~*{Lx~k`Iq6@u(uFK zTKqt7jO33NUyU9oG-~m8(&9Vc^Tj_}{5KzdaWe}djh;#xeND3?-z#Y;s*(PFx+KfL zkuIB%E}zNrVsA-{ZCob{qm=u>r^+$B|HW6VZ=ftX4J&2kq{UI~w6R3zB%FI~#+94r zL2uIHlBXA>O?i>`A~qW>Fp+e*uIMf+kk<lV(!}Y}=Ddcqav^DD)O1bmMEbaC-f-cF z<`U*W`Z$&J(Vg{zY|_Wqq>m@=DdP#!M^Dnn9vQ0Go%Hby>0?t~5TyYAq?J*mmG{QP zu@j_;Dx`^|m3$UyWfp1W#0c77NBZb!H&*!Z&6w+xKI)M^wpcof*^oZA*-Z82R=tI* zG8%#%>Eq$kbe$%BR2XW^n(}3{7vM%(`6I;wds;0NjjB|I7}CUuVspMi#ehYURvMg( z=J}+L11fI{Q!_nyGt$Qgq>rtwve`>beO5#Ic-i?eWbd&Osz@KZzKg*#q>sm{y0WJH z)zAtfNGsQpRywLp6JtmdeMu8%Fxpo_S~;JzQpYfXW0Zop&)ozbRgB?dNFVb^AMZ=@ z*pw@i*$&djC^Z=zLHc-<^f7f?5>}Vb7Iu<8Hsvot26&3JGL^J4`IxadkTkIkX=0x@ z2AtFzu9H?C*`C0Mv4etEojiop_;Q!JaZKsXN49VNTGptKS)`A11K)#Ix67>aFMUKy zqi`{+c&kX7_&-cqiAtoEA4w}!a(ar5n&?iNIO2&uzeQTvmb8-ek#8Y=Oe1|<9yOlZ zl0JHqJ}!;VXOL^l7mz+y%~!yiq>p>3{|)INh7U3jFSj+7H03_DCan!=r7>xx^F2fH zIccH}X=2ayx}4fbVgP9+zKP>brq0m*qq1;LV+;>H@PVx$ecYgu#mq<_mytd?b&*3K z(#ILU^bzw(9~<~?2hzm<;py((a3pD^C23{jb!KCp@_wfR4bqxl*V40-JO5;#s<uU} zq3usza#FqMl363m$jl{u{H1;Ww^lZ_|JFyo6fRqZrVJ=<yiVqQxn=X<Q|ixayWWkn zHZ9w)`N@srYF7Qy%^;tBh36}eSvSr{vBjdI^m}$c=kRJ~PSK$49zVI!|Cet5Qy&|3 z@Q)@o)yMy6Xi5`p`u}45k0z$zp`}Sy_IVPTn~Y3;6Mg&-r*N%GO&gWcsK)v8;uAVH z&t9+k`CS@6^XspvX8ltiCy-Y5`>B;FJfeT5&5$$0e~y#3bFGba>(xKUF?2R4?%Hul zQRDfU_eCfUuU}03SAG1i-}m48_(uo-ZEw`gMy+hr#6Q~ihySgKO?9(zZcQ{1L;s_X z|FHk@`EQzd@qf|E#&f&xfNAlzSfihD)#hc#;`Lz~Ke_vorNujW^iK|mT3`I((d^=b z4{m`VE)|VG2H-i<docWj57=st#}mFQ;aTDWIM-?lPJ5^iQ_nVM(^BHF`-A7uFJBgA z9@^uWDTg3oQ!Cu-(;w{)?Sd~<8(^!m7JkeQgQyf+T<v9ukA3@sg{(7%tkXao(Hw5~ z0<^a3iG7@NgyhWvns6h`*Q*!SbsvPj@|{uZ`A4gwSAZAi8R3@X3aeTzUEJ_yAU;)z z6q`2-MtF4@Ui^i}4~-Dzp9i62*cF)Agd6QGf7>&!NATpuBcM`aJ`8aQ=P8q-gtDkY zsO%TcW0yq;l9h#!e;}Mcvk8P@tJ2}r0e>!IZUsYbUIlf%DctSYLim)h9PVBT<a>nx z&@n9mo8}|<+PiK{(Xbh=oaD`OnLqPeBZuqEyYup$RkX%Sm!8?5WJR88{M>#UJaWI3 z&7P;uWA*K@ewQxqzWO11vq=wE{irQmnrp&?J4?{ZLau1Y;a*&+PJ-JGM?lE4=PXcd zG+sHZgI{PprCWDvJh!?IoQ(6B=Xoz27Uhdwqmw00Ir4b?xfObi+(?UxY|ycGFa|~x zLvcj|#ATS_IiKrbc~l+S&+CSd=ThAQ|10oAUI{DvT3~4UONhMl2=<x#qJNt;kTc;R zTvzhJ!8<FU-xdZ(A5F&dU&A5V7of2}R6O;Enm*!&)oe9a6sLB<sYa#3BdTw0aC0y& zTy{iISZIlDD{XMvr`^Ks@1~fZVUIgajtOcq%E)dFrTs70VWWQlyE$e8TJ~!T{hyEE zskh~jXBHKw=tlCZ@2DQl-V~wt9&4Px)f(TlR<QQZ74XgnW7K@q#(GDoJ<6Jy<0tPl zA!()swkom1$mR8dC|Lw=2SlT+sV^*}#o)$+!*O-m4>&bvg($D=ho0#G(+yhSZGRsO zDVqT|KE8t286&aflQYFzD7PffHbcRa<B+~?9B;m24V0@cgtsH7@*Q1M!6|!I@sHXW zyxutt%!j`(p4L8^ubh(wN}9QlIhcA)NA(BG7kePEbtv{<Z42h#o`U6%F(?fj4Yuzt zzyy;?xbVY7s%amHkL?dYtl?CsvYLX;pRR`2N%P?Oz9@WPH;$Q%nhGu2#-giZy@<X1 zAUs_cS4H)~h70qd?vXJz)1ZE~GRvW2gL$#7brQBWek+u{=wQ95T@vEDFT$6H%AlSd zk138X1g#P^xV%0dPk1~O_N^B1l%USl&9cGV%^90VDDrtbHo?i<e$wfFTVdYXC@dVh zx2*N|d>B7768FolvrJ3g2H#bqF#L4h-U7cI=rt`0d$-V#ZZCNUVO=NS1DjH*verw; zS~3wot5(=sT$M+SvA)=$^F&GPAqCpYI|4&o%B3rZH^9k0<IqH!E&aIoE9}`k7GI^d z7H8kBgy&}hu<&^Y(f-bDsCNv+hS0P_<tr4iPu6gpn77!$+(!|+A03XCCFNFEpT2~Q zDHAdLFp3lF&%pAM5DYwFAzr(191<$0p!uTvHkVKNVx^%xf3eWQc2@HdIQ~s*uBqM* zj?5j2s|;j$U-Q<`qWx&pIrf8{vI@mi69(=|*96niL0IH-8P+d2Dr`#&$E$%mK!436 zp&%gw$EM~&i|tQ^a@PlkhAn#o@&_ki^5B(LzIIe2Cu<_M&B?O9eKQ#YMzs^pSkGf) z-^{@FxsN5xG?m@@F#}&eb`@q=ZL)T~k&K(Pm4zK&Tk<&(nQUa~V4R#jn?20QW<lLU zaA{6DyE9=Ii@hFzVfz$$sBS*{W-tKx1M0&}HHu}!9}CmV!}-$A%fz&@Jy1L{ig#=_ zSG=CF8D?uw<2oZ&Lcdq<gbOnLc<|6*rrlo?UH1>-DpoUD&nfM&!EtP1zhxWQjo@jx zHE>y>&GtNYx;hf0=Gk!CyM{wQJT0@FV#zng+TnM-^OE={BXF<q5mq=xg7=0%Y<c_^ zgdLYkVlVc>zV$Zf6F&&v1exO|)s7gOa1VBm*aqY8Qs0uxT`{9!9$eTIh)%czX05ii zva$=uYr_w~rr9Res}lsgq}K~4oTvl~BU7w8&<WGqmcT-z3D|x0CYZe`0%fOd6yDeu zz$~ginw3)_G<dHTUMSQ4(%MC!uslQBLp2obR%QYpp8(;by>ZUvEi7xxOK@?Vf(Ned zVBb0q1FBhypC7(whZnZRq?q3L@_0A??dg2ztsPzTU|#@td|w4I_yRzeYTWyj!ZQ8i zu;#HAZ@1MPw=BI{IBsAM9=6R1tsc?)#=bjY@XHPuH&`D7=afNeVlO<qvNJwUD-&{x z2VsjX64az#!HOEa@J6gHCYqbEJY7><+0GGPwC=?Eeb>i|NJ-&(&os8PW(I!$vL9YN zna8de1>oX4rEs&?Y@z?@sc3!chec4{RAKG1WSp|$6nr%~2<^Z7V&Xb0s~vkvq0jg* z93rQJvK}hjL0J{Ax%>bduXOfV&KoCAOF+5Bx-g;4OU%159dD)22kqr~;`F>|%#K*i zzUZ%!_82}C&zE=PhJG^~<Xtj~98M?moL~cC`N3vbm@|eK=xzP$?><vc9s|bhfZ`s` z*z|W_Y!Qm_J&wb}gN4#_4-_R=q7%`rv>kic(@kO>6on;8IV|2VPdJ+si5<>wWxCaa zB|0Y)Ffdw|jhGv|+tQxu(FCcnWj_k{_DzgJGrb(vyqmg}&s1m3pQD3vqjp<ng?r)5 zQyuW*l9m{6VT4_(TVY>lfFZ|>u-lt<_<1?t$kjTiA%wtS(;)mFvJ+|+&w}%lW@581 zL!s*UadF5pe+<304XR8xv9t~Pc;hW#-Bk-_wcCgG86Sm~8RuBj*p{^KjXj^3<Id-6 z1f6FKA<8}yJ9Qoic}urjzUUi=-aAKt(>4aj&IRL0TElkXWi(oLO=Y7eD=?p(BXQaj z8Q$Tl7JJqwrpO_2Cik5=nQ6cJ237_m`2+)C3op>S=vYU#e8For?r}W!s%Z<U530q` zIjf7-Y@EUS4NGTj_J0L2WH^^T4`+j4^}tD=l3<~y9Zyalg1)*zaHqQx@2i~y;Yy)U zZZ(Cc2fh-dd@CdrMsQoVZTr?e+6wt;QQV|H+v3HC9iT({8uogd;5@xS7|}bC&&*sd zHC;OkUT%!xsrC6%JB`WU96gi!)Mp9H<(k15@_C>BMRMh9GuU+@k-yE~AsM)|8C<PS z<nniA_u0wG!kRkjyS2Q~{NRxv!pHB4{LnamR$b|f=ib+|$kv`r&C>_{<~QeecBhDa zy1C(jts0mx{<*a7sTJCMvcc`LPbBw?a-m*}>a_G*;9yd)6`o~8;SqTq@HyBO=I@?~ zg&*bNX7gUqw^baXYa}|h$_CjFZ^RC&G1yUeE|g4oDc$E5fDPxD2ze!y>|(G#rW`SZ ziEVGP;R-RhBryRt*c}vQF8gBNmNGcEx;Gn};)U-Q<$~noE7oE6O)xa^5mufJ#PwDC z;mwcLLV!*<npR(hxoVpP2df~QGCR`p(TjEvF+CB#+-kYsFhCKWZAiqji`9@7JxiGL z+8>nz7r<#|$n6U)`F-eHR4z55`*7f2J2(~9w=v<jwn?Z4$Ql@Rocgt^n)4A-Lp-X{ ziobZ)iYuRJfHyakxSV${p1+Uw#zt&r9(neB_Ho3}q!yAl%MJMx588vYUlHy-ap0xn ztZ{$p5iwHHnqU3of%!!vz|m5XTc$u+^7&-!?xQ2rx9C&$;aW0keO3_~?}=>gB;&n4 z3PRTXbhxQJ1tE7ObCN?L+%^C&@3_lyn%N5z&rZe_vG>{9_Y2{g>J-e}u$&D%lE2q` zO%NJCy3WFSZ8G0n8HjBaZvA}r*#2B1o>XiJE1VWWu6s1zF#jfuN=gI+iy8Pp^5*Ap zf$Exhy+0--T0Vl?n<ruX6?(T=_W-2F{m~#kPn<ib8os4YKwBFVmhV#ytvx2-4o?f# zZAuI5_s#?RwV4M)4`^cAAzkd=rXH#d4A6AB4gcJFJ{;@!9?Z8*6bcuN$4}{oRPPme z)~tDwrv5v<TH}K(A56Y*S7<tB`a)gw`_Y#ls->PxQe7O9PwRGMXED{aS%SNAy-*pH z$a^+;3&GF72p5YJdDYTMg)<Ix0FB9syvOV;HujS~^jH$Xb2ELJ!BZW0@NNb_VeM(T zZd3=DOrO;V`NnoE-Uc)KyYr+`Us;RSIk4oJJ8yMmChi+-D_(s)iX|7s<BJ+)Rv7hE z)b)?YzLVNA-8xxzw{j**W}AwM8Kc;QhjhJ6R%ct1Y=zes6Ht4*I@@<?h|pY!M~93e zu}8KkJd2OR3(C3T##|>zGK<AY*`Laa-p9cWqgY%eX(7E}9}hPV&cI&Q3ni0A%!dW3 zGf;V0zU0BSbofGh;??_K6FLRh!<kNTIN;hXVeobVB#H_6L*9yNC3Ta$+8&P)5e_it zjHzVh(l|`zMqoAWy*TK29A4UH2o-@(#Tug|y!b{GO0=^?(`iYl_f#rOT@o$E(Emr> ztYn4SQ8T0gSE!C<7bT&hMTj(^FbcFx+SBu(LA*zr1T-VNqE)^V*GO~#%`07TSFjUb z(GU)wI<>=$je~jdt2O&}?NGrj+Mc}RM@!2W{Z-Mm!GpV5%qcuwb)RW`o6H~GuM-Zm zdBZFpj^oY=bwb-GRAbg^JWt9=Exc`4$sDx;`INF?@apxLUB5hr-#a@AHXg2Jnx1|< zWWgNx(fv4k{(K^THZKJp$(~@tj3)8pvtPsUEt6R7fl)lWKmlVMkBbYZ4Cjvu<?y5H zBXN?_NWQ}S5nPd*#h%xW=0m3zgYv6w><Ycd-L|0syu0VKFYPCCvwa<LdE#JkvCL5Z zMMVpL=(ZE5l?>u}<8tA1kS_cBD2$IkeFPG2DX>}LA>64i{T^p+*s-lK++&C_lq_>% zX8AGP*2dFPWl0|<IT+7FrET{IbhBq4Pf|}U=i5aMcGI}w(M=F=aSr$=`*X(yB80~7 zhs06AJT+h(*u}Iej%!Byy_{X)L92ckQ>V;Z9$yQ}Kx<k3y72O8=HSvV5?8Ou2HmN3 zLQ#?(Ug=|j<MtE?vT?q+Vy-;yH009L1=Fc6+I+aaZl9pGCJGDmaz$%lBlNPTcVw1w z%-hBox+HeOhfDgRoBmQZVWcJArT5M=%pZ%s9~CjY`EcBE2?gW3wkTiT6>W64uo8bO zRIW9`Tjx{Qqk9ukOS=ZV$9xdVT*hIukOp{c@S;q%TRJE@4WOD29l7t*NLX^M7sfrY z<j2n%!(>N)Odo!e8Qso;gjti&D||1rSgDNjwkhG-d!6}Cqo?3wH35e^v|*}`{qU*# zcbMyIEjW+phHX6oCyy8c{?v=y^wvP^+Wk4L+30{HPPpNv15Rv9uTGe0^cgZQ=<`Kk zeK5*`YI9M&h|edMKx>~<Fn7*)zIT8HoO}6!>UNCb7IVfy;XYNI)ZB&p?Oz1bPIbgR zYW?|Q`Gb(I(gWvzHReb6n`8GqozeK(S+*(U28>!a5Xa=aVg24t!u@VXK_fqfxp`1c zgE~XhGOA+Tv-QwzuOo)4Sun+#P~0(cJ>2^|nN?{Bxcc=wsMdYY(vHXA$D>Jbm8*#r zF?YbZU?_UdKgs52d<Mm3ws`-u443tP0S$^1Fd+M_klRHbt{zOp$4Tua6S7-bO*Ni^ z%iPXDSJ|DG%1G-}POE~=lyTApXX<I~<aoZs+dvo_t&95p1NoNwMQ}{R2b-<F&2HAq z3sbC)K<e{Qo_??`)THf%e&fRUDbp`-_tgcc%O1dOJ}IEfEe)Kc(TN9Q3sm*-L`@zK z4clG`B@lqKb8o_qv;(lrE`aKZ%mUwbwEkwj3-+vD4!vwUVqP@WTD@h>U0%we@5BTc zli<mB)%3tvHVEn`IPgAQEl@M>4qPwj$nPvm!0`C4EJ@p0TzfSR%MJ~O4I%l`4V@D( zd%O-@8<Hh<k(-Wz)uF7Q$da84o`9a!cfq;6BXd3LkJ+vAp)_?J3(+5fHHY4U^7&F0 z+LiVn1&6^FbtT@ezQEFn-dBXuVyesWa%d9J7v)ONGwE|Vn7bnZr#c-Kb&sBhNDJCG z>Y*=GggQ}go*q1A{(7l=D;HD=(d5dy9of6+XOL_=i3jxe5WfX`79Bg1%->A66x(;q zFN!^v%$)=Dgn{c%Lq7GabX?ezl|Pok*pz12dA&2Y*t!ucI~<2s8Dsgad#w+QT|NkF z=V|dy@3gJkSdYP%OJ(`4pbAiFuYs3FnR5BL)2)3?RdHtPp?ul+bnENK%~9Xj{^v8% zn+wi^NlXYYzY~Y)r+Y*Bsa@jov9Y-3mIZ89GJ*V8@px#=Dq+K}?y&c25+1SilU}=b zMA)O6jG-qB#A%DhN-phAM9V>kMg62>;%?J8oHjUL{6@VQvii-yZ(K$C_~b(7(>fBj zcxMR7IosJihpDI<Wdrql^4V2-pPIg80X*xonPpxM#Hves!EICmdp9hA){347M`v@U zoD+m8PFLWfMW(1QJ_P+s&cnRs8zk{`f7vW=57=xf7b+E|p;_QUh)&jlgZm>fJJA&U z!ZM)a;~6+R?z!aX%z5B=YAhC3OT{7OAK}K)c&uEzPzZl(3|GI;K=Y|qFkp`hn4I^a zo}w!7xsv)Hex8Uci`TKRp#1=AlCYrpY3Y+qmjus9`i}CK#V@;i!?!JQSXArG4jWGu z+C7<ovyaxWCyDK0<ozU6o6E#~FAXFnw?<>jEE%eCdO?h5323<OtGI3ac`-tdp7}@u zS%r8~)N+`Hb46#i-Et<2HuJ{mOP{creRi^&!Lj%*<Egl%$0)Y`hYM~o*v!79%kwR} zqj0UpSTSN9Eficp{fe#~6Qd$Z*eMJ|`;pCrdkS~h+TMVLxwOB1q9Gr?a|#}uED;VY zI>D?LTH*SxsxWGcB|k*{bu+q}!+Wi3ES#QkJl<skN3Y#uxt;xRUg!q6AAgR;oHfRM z;pL!JtjFW^#$m5EYoYIx6D*J$VERX8v>gA1iNnWW^OOtVs<MgAemn|yUc3s`ve_(j zz$h#^TMu8BxU+{-dg7{4mMA-QIWzA%2FvEXhKI#&%=Bz8JRcyzJ{i8E_xG{bX5A++ zp1VfO96g5qw`qp$jxQ1Gc8tSx{0R2*!-aPbt+Cw_GyGU!2|W%^LWBKJ0N2_G7vBRO zeB2f#vZc^XJp?_1%0an70p@j|jM+t3z^cFu7Jd%FJlhR$nWaFNjf3#=QxSAaK7rZJ z2-H8l42&-z7|Axr*CDIes7iPII<y7$x}?b$paxnz`T%2HmJ5r{jl(Bp>%r4-jNs%& zHPuFJhhbZGF{7Lbxa)WU430J7=4T8r?THKyYUar=9LRtJgPy?FK9l&`%q^mJ|Baxs zIDjvlu^w9Jg@EJ!7#`fRQXI7T1k8Cel=ta#hdK2wf;|T`c|%uQu3D%C8w<zr{exey zvc+8?!rF{Gj<Dr@jElg}VkP_hU=r`+M>Vk5@1fdpkzCtmH0+vK%8ZqQxY(vQsLNyv znhNn;byz0&Ex!%V){o*=hnK?vZjIMYbmzIIy3lXkUFiI6B7gi=9lng{gK?h5yd--S zXpEeMIlGEk%;9Wk+hQ6j`=v@19%;kOepB$$sYC36rv<p_B;eT7wPn`QeXx7m1bq2! zE66CHgt<>FFu$TRmfdv&bPK_59Sh;&<#1@zr#Hq7H^56<?!t|4*T87H8=i_-0J`-z z;rk*#e0=z!)dr>gFtbI(&ui4)t5=}QpkTg#A@DY-W8u<vUEZeeb(U1I2##L$<14ls z2tAhEXJJ<-W3SfR%}dYTXQ|Bs@b<f!!q4nJ%a#kkel2W-O+)Up*0(03)|(4v>0Ut? z)b=LCmgw(0-aH6rO{jowtIGwe@IX}ax(=Rh`viHab9(jMd_gWh9CdRGVf^!b(x?a2 z|ES_1^mbe$eKa_Z`ac>%?Um-N-QAgZU)=_bk2hn<hFaWUy)`c>E@2%#Jo%J<@;u}8 zc-A6pGOe4dU>o<hX4@`m@|-c&+~amBbC10%`X?NO*l|<&{r8I{qwO!j3EKCO7P(mb z-tH6}`Vzvk!xu_#zNfm~4?_9ve&0a1|2}r1gB$K#M*kP>zrjX-_ru9Mspfm`X|}f0 zIQ*>J5`FD<Guubb*a4lu-YFjEwzwnp7Xx8en~8XA{uK~l8_1jaVXKzMp{n8vtYJa; zp)OI3db@{BJLbvX);wd+RkpGE;a=R~%PY3Nd$D*cw;W;<rf^;oC9WKF9#UI{aF>G@ zh1$;dn94hU+<c%~uxoplxxVm6=e?JObID2g!l$k1(9jE3Or4BM3Rl2bD}n8Z8O}GQ ze`be2sWZ7+AAWUID}FTNlBjKU0Qz5^%5N>GDYSPU%}urB`0@wEMQL(geCb4G{-UoF zEN)dn`y41%*PRykd6ht7%2e)i+ywgvEM;~lO{m|8F)GU^vWeza$imv-q*7N5)Lsg{ z*E^xH(GaZsu|de)`$CvAbv(ZA{E9uTJ`8-*NGuJKGQIq+SXb+e(ca3!@%FYjXP5~+ zm+cGR@~MVb$4oH2Vu@V>yW_E=Hy}}<8mxwG5kFlQ(rmr)?x!|5`Oa>^f7vi(a>bC{ zOb28-hoVni33x9w0`~_Y=-y8PwQWa&E%h0T(s6>Qo_?^xYC4wtmI~{JN5RZ3G1&U@ z5g}4B8j2%gaLbH~7M(W6K>NU0ESr|SFTgbx#*K-^4;$*OvK52yELN~rU{>g8AB-Md zt}^FgmfYlgSL$n2%yh~v`CHE}XtcP5b#_w~diV9ij^Q%=_7Y8@jE}{ZYre4CD~}0z z8IR!E;YobJn=?Y8<|`QcW;~bVtrF`LFTowdVE*|18Zm#<IhbA(%%$b?#b#!QL8l;; zM-C4VP2G=zS#T(?ySG&8bLIh59h}VLtQ4gx4UgfFwLjMznkZQj_7ODI#`C&C7r|}N zHn@Ii6#aj=6+B;c!Sqpf+{pSk*mbQ2-v|%BZt_m(sT7F|$4%-JtDOh?8X|Gmjx(i$ zs{&zsb_{x2KNGxOj)kr#V=#-$Ku)wAymX`c;k0&et(`3BV>~LDs=&kBHG(1COOKU9 z*tYJG&|}+7>IBgbw5h+k)|BaBs3XstvSt%|)0{o;o5`kr^WisoykLL$HgOks0b_#p zLW)vHuHD-Ktt|J!@M&s1g?nNf$8Ava;tkce^Tsm6TqrAk!RBo)1pC5poT3vbz3f#8 zi_622Jsl)%`rQMe7nb{-fi~(oTrcA-jBS<&PlG-Gao#RX-^em0!}!3cm&~bP8^c51 zJS+DZYdO`AJ-_e6ulY3NZ-$Ow3!eD!S9Q(!VlS$DR5zOC_v?tW-jBqzvLE8@DYEz@ zd?K1u*Fkogv0%BxAJZ<^z^u`l!n#AT{N<1+Hg4L9vM-^r{Kbpu?1uR{>B6)=Xgqj5 z8}LC3dnu~or45H!QfhC!)ovJOFPp|@-)M#p`^6);z83xuVRs!CMfd-YUleQwy9E^+ zk<OiS6ja1OL=+3eB2=WL%TDa>4(tL1cFs%1?$+CGLF{gS&ym^hz4!b2c>Vskuj_dq z&(1Eh^Lh>JKF-YJr**~fl}Y^Oi${`ASWQuN!B=MMJCj{7_NDb(ab2FXGuS%vrusu} zF;}}eEce6!%F9{JDiqCPp(!DBt6Fu*KYx^H^ceRw$!}_XGk2QsoD)mmrx{xLc9|uw z8=OX8zx9<z&aEULO-`c>w<PP`Ygf6t;M)Jard#bj<hEUeR>L*UZiccorKXERDY#Cw zLwV+Y$3%LWn!@w_GMI<;XsVXph-I#AwfEbDWV+^U%DNwDxyQLj3b|FSE*@W8#iCwC z(Cf+N#Lp^o<gMmL@(UL{FQ2X5GN^>O{U(J(pb>wZ9w#2n?#ZjK3Sf2YPfB~2$HSjH z@@}QAD8~Dh+)#Gl0d=h@yW~A7v4gwlI{Bx3y=wyPU*Af+-`i4*z7kJGUz>{)6$<5T zxW3E2({`d==0@4n4Cm`QC3sO{4%^zplgHfszyeObVa@Kr{O}6gV#jutyRQTPda*1w z>6^-oE_&hjuwJ}Il}fZC^s|(l;lSCuwq)X0fk{uyc{OJ@O4xQ>w(RB3*A6lxZ);pP z<WehEuy%#?b5j!0l2*)S;0nofYZ4{=v}9$rtd$~0B~iS6TQ<FDt>hb;MC+%z@HVK= z3Oj4_rEV_#3f6JmD_@6CE^y_Y3bwQL*J|?dO*Q=ZukEbn#G2gXpI9E4H(A_!@>|mZ z-;cGAnj{*E#!^A@Xr8kg_s#z7DxWwM#tnAnis*!C^4z9c`FTY@VbC^#Mx4l#KSbDz z)SHRq8#sZL`BjQ{?%b2Ja%pVQ!79Ar+|K-Cjc~sB?OJhXN-J^kd=!rhS|+-GIVJ_A z*O5!(bCMxblc@W<Y1;2vD^bBTnVgQcl6>u7vimEC@M<sfB+nmjSxjIc-(Mw(CwiC) zvv+UhW_bTfer+HxXb>sJuACzkxgHkQ7Nh8j_tZU~j$9GV{s|!`yZchm@ZI9uuF<sA zXarw0_O$SFUoWRn5MTEBrf9HnhUB(#E#rL{&3;jn$1H8hd)=x{qvk(jV|Gs28+-|$ z1L6C#c?K)3qpZhJ+}@>PVZ>_Y*erx9jGimTEOh5Tvg(s3c?&;7e{O7bSKPfmfi+w0 z#$T_lOIu%$VI}X@=CyJe{lc266ZP8hMKM*$H9kX}9~r{~hfEhwA7)DX8piOU4bnx+ z)wz;Y*U`L})gIAm<QsX<y3u_5&|TupmDh5-Q4Duz>?B?-4H4n^{O9ta6mjb5aQ35b zBA<HDSNJwRpv|lq%gdJBs7=pI7s)S&b90Yt;&iF<Vw+)x-EI8tWQO0Jl+T$f8HRAr zz#DA(yl<JuFrJ8U?-5h779jT?a)X6zeV4TnxeW3luaen~F#qGA8!T<kSG(&Nx5oUv z-bD^~k!vCw`_Io#K+eZ}_j1XU+A&|sTU}FBU++(wF0>cBtzR-r<S*yji!kKAm~+N0 zUy@eU6rRSrM7GgE@nyk4{up@#auM=q<6SHj`6qHUlU-~D@^$1=>;3s8Z1X*~V~V^6 zc?z;;xny4Co-d{2c?ThTA&*;GQ;ZmA&PRUS&F)ujOWlztBY!|P>U+oDb?zf}#b-Fx zNjPqAr{>Ay%xN&@9K)O_<Z$F$$bTEZ*}j`Y1?-<**q?vPosAqF%3)4_%=uehJ7k)p z6Xs0Ee*Rk?HnP3rdhF*a*w6o)*Q(>n`#TKVxf)RXUJudB`s2Dh-1K7B6Fl}iUYn91 z>1Eycn&-E(O|hM?cy0fim19F0*QPmV>Gp$?m7iDHC;H=cANTw-?uYTe<z@Dl9sa>< zXochIZ#k)dE4xLQ(*^tC|H@t%*E+ngx58`KtGqTfXX<5T{4w`%c!}*?!|VB5&Y9HG zz7)2TggLq#uVw>v{L_ycSvKl({VhlT>}{Wi=gPp(^}kuGjxPzf%07s^6mxWW;s4}d ztebJ{zDSB})=2zsc2dXtVooqF?sK_CBheo@L@(>c%i%holV~IRskJ8kTwZUy*(`JZ zDSsn-nQKjd%gXV#!~X``W*GA4Z@~Y}8GjkqpRdgMnQl&Zk8EV8@~r=w@fv8p*vQ)8 zH8<DG`s3IqbkJjww6A$15sG{WITu-fybs3f_E;pH!+3Ax+W$vhfi+CC0{RLcqXMSn zg~)x>tQ%j4@viE)E-UkOS()Fx{w~p`?`dIe)Sv$?|1jMp=6jzOPNn;EU3U4OjK{Kn z{7wsZY^SGQR>rTX<Kf6v)#v(K#?Qi=;5CO8|1AG!uCd>r#|-T&f=U*!>VL_XPTa81 z#<7Y8kAKc7KTG18(8ExVtrN2HF+LUJOZNvjR7G7lp<WUu{j#frTn$+{W|Y2k13jw2 zh4*%EFrP4P8Zp*U={aAJZMQdZ>Wn#lsMBFMU%bcp;=_uX0{x$!oNF(-+q`7uku^A{ zG(_%&IU1aID&w3IgY(FQQU}F|g#&py@+#y&WIvo!wjhThV-B05&iS>@pT}c69@vf{ z&MEJ(eI+aB5%&)Hk|WL|-H~S_-^KRz$9-{5vHrB1<>MSNWITR<Lq1ap=Ni5FqVk!n z^Ekikz`3To!?~>6$lH;hk2R-epLeqYJoY2bHJLcqcp`&uWrt%wyha~Wa-?3?jk{jF z;%JZkvljd3Z@F||_iRHvHV^O1-?Cp(?d)EdGjiw+rpqB}_EpD~_v<O%Uuk&pd-qH) zE8{Nexc;2~&B~lb@llR1Fu#djHdXU0j4OF&{ThzSvGfmK^WXBi#{09E;<dHI{!#K` zWa)phe8SwRA@)xx980=fS}!Z(yPLks8iU7P$77Wo`+ww(BNt?s!1!srp1<XBKW1gS z;JGH_y->17FYCtJPY=&tgY7iNbNwyPeW!K2fH^%-JAcb%DqeO_wm$*S^|zeF);V^- zc6Q=@RI;01){RH6@Z9f-@%fme%X9RyGCm6Dj+5x0?a?QdeER>$5g4D_d69Go=cB*n zXX)m=#nFxI40^kMF2s0ijGx2!#u?_k*};vhk+7!qf62;msJst&KmMF+{{M0rtWQnD z`9hMd$w*nNs%HK1Ei=sNK3>BKoKy7kR(1R&#__Y$`G0@*|Ktl8_rU(a&rT-loY8t& zf4m3I7Xd+i#b(0-_P2Z;b9(vr6^AkB+W+Kk>iA5YFFeun$*@2FTh76pSA9;4Q<$UV zw|ZGOKG$>?(_;J%=IG}I>i9j3=Ob6ca~;&n%Jb^RmD~;IlxUn&W|b~rUV6EUUOtBW z4Cj>CQU&a9Ika${vJQ<GEJ)7E2%ca+`fXp{sIUz0SulkKBG(NmV!pveYy@(A;S^?w ze@jK45w$d{lRBPMI7QUM{4p4R7hELV{l?k{AUhV8p|J&1g!0%27;lIF{E?qwer^0) zG;%*bvn=J`JdwSz{dSlij{FhZe#7rGqmQ3hjJ+GbGO>@tY2^Ox0(oove-q?W?e4Q! z{C^Pgw8fLM95HT;oYn5WFvY(qj}5VRqaoE-WvP#)rTo6w`Qa1Gz<4wK*B*2BV*ZGB zfixSrOyrJC<uQGbkKp-v`}^V-=GVlwKX>}fs!W{7o;2;l&v%*Z(0bBDcCb?%e}n&D zJz*lN;PIKg!T$^7#y>`7-NpD+<bfWa#ZUa3+xUs>LDN3uaQR)<K5XY=r#QOS>9hES z@w(0W&`bQABj)$U{386@ZRBUsW3$#`yb_+PAGYxj|5gK!#Tak@@E=i;X3M3qW?|QJ zb5V4*lrX{Cg#5k>#3HO&xQ;aoX_ogy9js;Oj<pQ!N9G7+okAwoDg3;TeU9}DWw3t1 zaP4R@8tW7mW1WIs&JLklzp$-ODRBzx6uM)b0`+Y#tgwC|e0d$-*kgk{0c#doW6i?2 z#-HRBShLUvYZe}PM@YK$1^=6M>k(>Ki<It^2<30Ee&KI<+tmo}iM0u1ur}d9Rye<n zH3;wEeP6kU^M7VVNRQ|5V?#QJ<DQFAQZUvmh^%4Upsg+2g0%?`F5x>0tVigK^$6yT zaoz1BGgv0pDQq6vi*Ltz1cvnp9pIq%W1YgQ76yEsRa0)V<Bph)wF$3wG~(;92H`x` zAndsh|BAH<;aHoH-yYXNR@W?CqX-d)H3*SdgYazOOHmE$4whrx!Qz8v)WmkHh{t+_ z%|*5}59<yFV%>ptRA0Iom!?U?dW4owyV4x2L3oTc2!rRerI%QP&=G48zL%{;53ufF z2-Y1`nB0WEVLigVp_kaATaSgZ2B8+#Ae<PSEpB5Cf-%-0VBLXG)*U2Z-9i6#LgZjQ z!Vj!RnB6K@{(^M}wXyD?gyj*r0oE7fV0}TkZ#(6Rzb(1%9B1Br!6CUD)+5j@d+vAX zswf;9Bz|GtL2LKQq6XF-T)?`6Q@h8?ZdhxOjI{;_drgtYV@*M6tSP|S0dWLt2g+mZ zfQxxwam;TXn}#(74HG`eIZ`^a>okVn#&yVNU`@ehtSNYWFjkmgO~GNTDcDqSRII}~ zg6MgR*{K>cMCtxvR2S<AO4ZvamSVlYJggV6cz;d|$GU)tSQmix0>bY1K)wa*1+b1l zgkT*3!#aXrM}w(}OBTC^^#Y|U$5TZ6Px9H;{>pj*YV9;g-0l~~PQiUTU>!lzw8?Dn zv_`Z6>jj=-y};+kt?5_owmc5&1)>ks6c?}-AlK`W)ar3nQ5S0j?(r8A)&fwIhzitj z+iI4#NTLf8uEA=#hCSQpt{I7S0n@QAU{=rFt|hQ8U<lR)SeLG&*{J&eV|9jT6IJKW zE8WP^`Trpfxta=C7qA@b0ycKe*C_t~1pI$~Q58w&{69}DFQuveKS8@j^IlySV6$Y3 zv(Eo--7qsx=l}N}vzBhb`KQA9%LlnM3jTi<{C^#*^5Up5u2*vOx5%z#Eat-bzl8JO zZ##+#VEZ3dydrH%j-U`2{@a@irL|MS=@o4M_eGDT$^$~EW1owx49x%R;0MlqRok!c z`SsoY3CoG>Iz0b-c>XJPlbJt0$25cU&-j6RE2^G<#2&aN)$PyNFpWKg=Z}Nuhx2F8 zROf&2!5D6V`o1~(nKY?EG&hFZZvnRt&(GVao*&MiuU4IZ$Gu&6a~S@XF#Kmqxbqa) zepA@~=*jl{0Nnl*xP7~kHhcx#e&r@-HL(SLlnb}N3~v8Lh!t(X=Zi`3`H|->s1w}& zK)C&$D}%`do<9Jdf1BSXF&J+D2HgJiZ<B@2?Z;F;AZEejw}i=u)yFl_E%_~2efWH8 zt@?cP8l$K^9R2|~eE57ygwL-IpAWZBhvD`=!R<#3=tX1U^H&!8eA=h_e3*RFnS5A% zdJn6A2v&cI`BAY54!<%S{y6>uH|gs^b>Q=@9&>7{I(&G0YNdMnvkU6dSJmOe=hH~| z{PFPl^NickJ=psWu=g<e6t0^5xwmq~GkE)s@b(5j_KHH);fJg|A%3gg{(9%%!qR7& z_zYLy)36%-@+$WBaP@Q_uHF=`J}^3&>cHC%gSU^{Jcd@l*nccG_M{m5rZDykvkhnu zT>UP%dj0oBfB(lcE=v)Eie0__`;~4zipDi7cJ(jrRnRJ~-Y3^sEWOiJtN8iR@be>E zZkErguKq@gZd#qUcVyp$4{Ur>*!T~#N>i$8=DS#iP`Q!YSs`rvhk1+wVCI{{%%2&W zKsDgx3yPgQg{w}!?atm5tlD^(dAg~ZdHrL_$;63T!^!W3ldto9h8UwddCN^g99M1p zg;!&!#lJS5bT+>E>z~3(_3$w8WD5fy3Ijjw+(23n8@~`XzUJN^A{Pce9|qp@bu)@o z4SaI&Yxy9odkU;O47`X{4Sedf?pQlhY~w@UY?5`>z1OE@vd*;Ue9F)$*4-1<J!i>0 zjn2T|oAzC+v+mb3wrRVm);+#_Po_BbfpF|+2MxouefskA@a>BNi!?9b*q!0nAMYG1 z>3sXW_S5rpjy(kTf!6tUn0BFO+J(-vYdj+<0H)murX6;j7Qn6tz^=ozQ~h(Zqzy3b z#x>%oF|7L#Sogl=;z%*=J7C&>Ug%41s%h^()`z~qw7VV0cl3AmijpN3|8eZ_?ZQ*_ z?J(_Pj%wOr*F}bE*G+?`i*vB+Hv4R7as9=@A4c60MqS^o>znq0+Lm+(cD)dG9bTPC z_3BNIeG{+Y*nj(2(4!u$=r_FjqXJhNca)Q9nvv!`96Rhf&4yi%hF!n<r3amYU3Z3E z&z#I$6}$e~_m5q7)!Frt_os=6@aj$A)#E<Q5clBH!{E|e8#v2D;nk<Xt7nwrvf|jU zz_G)h3!Oio<~BoYflEIDmmdD|fj9+o9uIRa**q4{)(+*TVbM4Bekc@kehlV3smnv5 zSo99C=w0D%(qYb9z??T6X+#}Vi~gv2b84gd^Mmdmggg9sCj9x2X)S3w{P}A5^S?cI zvrl<?s9N-yGaAuA)t@_S8<EbR8!ufZ4^aJi?Qgwgoj>2cq%TvP`8_!EHshBuoj)Jf z{|D3A@&+S*GMzbxGbf!hhbJeUCx<g9oim3&C!IfsEhn8VhdC#mIfpGLoh^qsCyi>( zFSUv%;cBG44O^blHl9pZf62>(IiEH$mS)11KZY%bIj6%g=Rq*%XKE$VAlPyr*m9V2 zvVl2o0CWCoOA^h1Eq@GK?ouI{%*xraF)-(yk0#O`*z%{a<#T2y(p;GH?l9-D<<t<i zJRY_j=A16ToF9cbhb<?aEr&VB@2JJ*eDJ;~(V&e9zXfL=|1Df7o_sDmdBqf0p>yVS zrf5V1)t~oHekqrS8y^lg4o@!cQ$2ZPUZ~Ky@o$sIiU;uF-tgh^(<g}UaO2P5#^K3@ z&XXS=|3+lPjTdC~SA4iQZCLEX3-=k)dARXGaN`+U%aIQ}`E+=4xN%V#Zv0BI8yAWj z{|Pq^D^6En#baQ_+w7@MqhQEq!;t%*JS1XZ#mB>n!;lM|A%`0m`Tx3cu}5{|`aWFW zfrrQM6-n^nbK%27&rcA6aN|AU#w)Q7R7N%7FL96eAXsq|Sn)RQk@OTkymiD&>B!a? zS_%g)t=J>|PUuSu;lp_g(k@SRq$hCWi}!4mDld+ruVx$NMeyNP&WSV%KHMBWylP4< zx(XkD+kCcw2`9ybkG#aCpnf)VYap&s1}hF9PGwaep3`{{m4yS3YVjiP;k_Z$7(P4@ zK0I@nE!BV<zYI72vhg%g2|nBiKD^G&Wg=}{u>;?Fy0uVz_#F6fT!&0dhZ`RUH@>M= zq3ENU@U{!8(p1%ocl2vQRa6sR^_f4tffZj3D?WJhZDFnY@DtfpNb%t(;lo#3)S?Xd z@P+W<vq!s7Bz*W@`0y9UX5o6NC)i~8@TncGh2q1HH5f>(Ckzt%;lqc+hxgx`F7$l3 z(D`tfaG^8d2lrZ0bJdEwy&Fnd@ZqNL;V|K(GvTn}q_g6spNygd@ZkpEhKtEZ<EVCi zDjRUHrVJ}iiWR>LD}E~OmgoW>?gbw{Zq8Ss^Wl3NmKBN#?>xao^L^+G@e@{@!HSO^ zIY=`_b>O3WHJAP2z?;H>ue!fqC=UGB!kc3Ar?PUe>cAIeR~9-4e#Y{<cmfCh0uH?8 zmvZC|2OeGQz^N`A_<NDW%4~iu?}7v000+KkN|sopI&eSZN~Ab&3pnsr4%NvW4!jW@ zcuP}jdb8;k`vUL1{Yf)Qg#-T#2k!C8kcPvD`@@IdoSRIF1OL^~L-F3^1Mj^X-Wv{_ zcEW)_f&*W1Ig#Sw!+VEkXgi-CMmu1?_rZRj4joMGV8U}@!ePHDUbWw$=H2N+&O0W- zgc~Ot(!JrhXBO=D+9E@t*zW|`@8*Zkig4KPNwDAF#yl4(Fy65+-WAJqCS%y|+OXfZ zM!As(O!!ZjaDDHs@4)$rlVTU__rvKeg!Y+M41xWw5BuF}{VL%E`&|V4Z4r7yWE$7u zKVZBM-AbgD@Y{#sw_&zPtD5ck0r8}>-0<79)!JWswb*Zy75w(?8GrmXz4bgOn-=?R za{bqD(~*DuHf@C89uL2L%QcJ?zx@?{`{JVzS_!{>AAWoO#bEjZzir(=S-kcQqAKv) z9`M^H8$xJ0{Pvk*zfGgzx6i<D$2x{nZTRha@Y^@bMN=pE?Lhc#m~Bc?%{DAIDVDn* zEI0f%MZ<4<!*5%h?M>a_w7<b=!*7$$Z^Ly{tz|Q$5V&r)#i?|<#7V8k>I+iD*CCV) z%RLyDyTtlLN`=|J1hefOnMe$l+jy4~t5PtSlHj*r7yE7cHBrce-Za<1Y?IDx!*Y|( za+|qElN-$TF2!s&j;D&S+*e?^;kPLYetQD^_O;M>x&gnP1-}imO%5>Ii7?x1e|M(2 zu-so^xnZ`+K{ea3+_+xl5jhr?dzllXCGgu(#eSP~emncjFxmjK{RL(lmYcS!mK$c9 z7Qk%Zf!T)Tru(Yp4m;hN^5D0dz;8!19z-ti+oAB=FxzATv&~_)hf{N!sakHBZBop3 z$=P0t<)&O%?pr0-h<hVj&{FvAU!(r`ZPNK|pI-q~6=vHGX1mR43sNk%2P`+tHYsM? z9cCMr8^22!@S3pPZy(uF71eK>!yUGU-}ZywZd7{&^@7>14YLi)O*+dx<?9GK0JD7x zW*e59cEEBsgXONistY}V-);-P-E?~d^?=_VQ|!0t`M-XfTEcIq7yE4yruuD|ZQ%v8 zZ2_|l%MG(TQ0f574Zkfq|LeC&&u<Gozb*9qw$St2Lh;)Y{B}2|{bKvSep~4IZ4nN? z-5!415%+WHr}}Nlf0NkouiqA1;kPZ|x3eoci5jZkuI#%+1j26@z;CxWI8WrNetU^! zBcb!#XWrEoI={Vh%|cO6_1lpL*9a5%ZAbX+kB=G%#cyAS-#&xieY?YNKY-tEqunER z!*9QRzn=Z9a$HP?-`)nly&0b)wu9ep2ETpyVz^NJb^`qNv2}OFZTM|V`0Yax(}m)< zzrk-;Yk!p`!e$@5?5~(@{(C|II|s9UXiIb10#17boOY6ty{vfbvhdjDy6ut6!&={f zwf?y<U)CAyk{RLD9PYX!+;ye93G@NJx*>cu+%-LcyM76G9rj=}`arSAPHkDAw^H5p zy7Tq;7WnF}@YM#R;f~?1x5Hf<_vpzZ;IUW2W5Zob!K%A{6Fx(86TZ4PeD$=*nUaA? zvAgCUW@;6WeH<S9vHMR^3-0<X-1YZHrKz{-t4D2LD5k6KI&1DUp?K_m@Ytoen^4?! z8r=2C8<)g#`0CH_)h*d3Q4#LCeCeaiQw|n7k3Ia|E*7u4>&MkLF~waw!d<^P5GBn~ zt#wAzOi3}=i7?o(*0N%)Jz%YSXP=jK2D{4ci?ZUb3*oNYe6tWbcWqKXnJMmi1>E(< zFSVJ@T|b|5K~mhc8{GBp<tHVbsm^HcCg#9eC%{^pOm9s_FxA6hs(T%6LlUgD6Rfq@ z)mmf^Q+)`g8rGV0)*8NAR($nK`07g!4~ir3)ra7#>t&eI8~ExUK7V{Q>G^8X`D!?7 z3Q`?4d^PEOHQY7n+_lfk143u2VXehxSZf1V>rrNILT9Qy+%-aHt$$ol)=ZCKSuoXk zeRJh?s<k%H$Ng_%q}#wq!%p*7u+!17)5%?H$T}~*U{*a@=cSJ<I3jO_mo7x#f{T{6 zt1cQ|TGDyxMsH8aG90x(9QCF?K~fVKX=@nibNN%HZ<fV&I?k?wrjlx;L+;Pkc)?EJ zgPmU6BSow8(r>z)7v8FuZew>;bbyiegOL`N>qQLg^hnt0*x}nnTX^Zh^r0?3uL6Y5 zMZ-%AotGZgV6)f{N4;?6socHBB}FqB>5?$g)5aKzH>#a>UH({Z1tWbCMmqlH6S)=a zv;;d17tJfHURudD{*SC*Q!vs@@zRQs)@8*`!%I^tymTtOG+Z<tg^NA_7oAEysix|s z;i$<Oj=C2db(gjKM8|#Mykxy#?OdOIVi`Ugz4xe#R)0U}?;m(+F<kZ1qnQOAhod%t zqrM)qiY<ee*1${WdHb;$aMADJqA!fX=jrg$H{hi^Z{5V&!%@$HqmKK~k9NUG7s5!x zPE$$MPJam>LLK0xFBf}h(s}8nIq;%hQKDb5m*(H#rMtjOPn+UGjo_s_6?<tq2`@bs zUiu~sbgJs5AGjyc7<lO-c<G@llc?3pM^e9HFD)EYFTHkaN!*ij23rd+U3Cc71=-DE z+F~y)bYA*Hwd%6YOT$G=qg59T^DMk!o?pN`!$ONiu+aIi&=>tOguCjW-(6fK!r`0? z;hazM*&3Z~{#9j;l&hNO%Buo|jcS`I(1`A;=DCsVKz(7Gx573%CpuCmnCB3fXE<l3 zbI$P0thef!;hfo3)j982--^9}e-4L#u2QE2y;7YsJTtX|XEuaq#@+kKR&~yicRvWl zKR1Veb`0!ARpFeo;GAuGxzieWW`B5QIA_v1XZUB*`RDnUT8WRUa~@&eRxD6G^QfPe z!dP|A2bQ!F8r46qnCe0joU;j>b3#)MU4>_^56?UfpJ(~OId6h<p6BL558<C5!au_~ zlg>HAGn39U!#R`AIm17b&OgI8OFG*;zo}MwtD0xnW}&mqFweqBHP4sMM^PATa|hUF zm}i==n&;5;I+Eg?hZQ?#jm|m4Hp@EO4D&4O%rl%b>6~-Z<?(d$O9MF{&UwMgIr0-Y zXInVuK)d^LC~WiBV%tnhRok3QL9|k}&527}QV)3M5P0SuE7uBFIOn-=&YL1u3tQDN z$1QZH&#GZ=zS@ln;FkBmEe|mCrw?uKig)nLhIerfFBoP+n?Ht`X2US|C^pQbXP8OP zFq58PCY@o9HHsm{Fn@$$j>Kma$Nn|Uq%+LBYR1wigN@qEV#7>2!@SP5t&L&>vJWO_ zdEk5bP<$_64j$n3%*4z{<hrl`?)dIrF$1IV-Tjw>GBgQUu>lSkSLQ_GyZ$P8Yy$FQ zj9oIDoH+#97T^CTzzmE+zKL;XeBZB_fk&8M1KU+BK~`(CtUDO*g4_+;moQ)1W)a2; z@jbrs{eB$2mtT_5IqMLzf3Xc9oehY`cltvyuG#=nY(P%C`=U1fQyv?N@A(~qHaHwX z9)P(k@O}RVeAmAX<BBnG#kgV#Mq|6<kbULtnRpEEjC=xf-P_-1Z!y0X#@^t2e8mP7 z;CuO&W5#Cb*#OeB0i<UGNM{4S;X8fB20X&|{9?~n2R$3W^lSjvvjJSs25>zaz;rg? zu1}_>$CWs0xFJo9E1S8yaY`&5aGx&xY@Y1%cgC6|pQB>hwoJ_elSs;Ww@p0o>AF8Q z4{IH4T!ho>3YyHUWIF2IMATheVt>Hrdi0@0SK2kbL0*;o`ZRxN7kZUqz$;$;EsmA4 zqicS)JZ`r&^;+Ljj9cx=*V$C1mcK>`lhLWXR8yAQHU6Qz=uH}5-`3A{{F+_b2Av+U z_O%Am{l4Qw=Y^5{L-+NfW`+II{_$^F^swI4&tX1$doPXuFn^&5%Iu_h+c}6g>Xpy- z-tQ+id`#n(7P-#y=DAwq&5ilX=Vx85cXp(KjeavHcLTm6%#O-hA9XRlZt9x%JB{?` zEKALIHTI~)SyFErxo^sjfE$etDA$QB`|O!*&rKEicC58qJ%!uNnHI{w<y;h1e+6jr z7mVaz+no^l+wZ@dv^IugsCNHlEW^0D^|ld1=}PS)wqjbY+;XllJ>KfWPn;XHuY`S7 zYH#kt$Bpc5>oq%#xjc>ICaaF*?kPJK*T{|IA6kUucx3)!zp4iC=mY0%mqmSJ9-RmA z_l7R}$|Up_wF48mrRJq}(#DnYuSU53)zk|t)ykipZ9SA%C@RlS`aaQ?EbPP0tY0w4 zL%+qdELT3nF`5T#Eh}tC&0%K-#&P4`hSHp?<NuSh&U^9UeI~Qlb<6NBkJ5PJTPsb7 z_JKx!Tz{Xx2&+avMpYx@^y)Ou$cCPcTblRalOu(Vw&o*5cJ7pEPSojcRjg62M)sfo zJIC4di;(in=-KmnG%-Jop5&I6&2WEIDriKNkJ-?@CELV5)zWDHlI>E&ruw)q(pY|D zm}Snr+wYt%%x}VP&G%v}$}sLay8(|Hctx;zt@#|RWy%jPmDkCzi)+~hP3X`(FP4Tm z1Hu~6gDzJ^U~p@$ysx#-)pZ(hGu-JHj)TUUaXEI@0nT6VTTq8F*V#1Vdi>#C3qC*O zIxDJCkDFr7_I*5WcS5>r6aSXHa+E!#$%*U=o~v=QvAH)NmT~p)H|MUq+miHkr#ROq zjVGU;C#@Pg+tqMN3u<-2o^D5{u^vCts6?pjl>4&HpPyxYR8IC~+Yi}ua9!VtKCR?# zhhFEE`Ph^9jQT0YJew!<_u=_oncD8C*><SenC+Qbr8du^Hm|>_pw-pm^2rTcbv5`d z#emAGHF(|6md2<xIAOIXtwar471tm=t@i(Fkp8jtbDe@3bnEm;IH)z)V__uygBtu) ze!p~X{96%<8th$MgEXOOaSgue97LA?)*!h=6xX21=Emgn;;d_1)L@@RzlF0}gC(qw z=2lm0P=AglB|lGBgWrDyXpf@4KB2z!9~-}mG?u8Z#;C9OX}OX)YN`-571A-pxr16S z-&P-S(bZ8M%}b3^BR^0hgQs2)@u-mtsF6xV<?%Pv|Em#UhZ=caTqD#4HR6aGIWaJf zqEI7?Q6u_!&v`Ezg&O&Y8qv?F7drXgN|TCu(cdSJ!m9DosFO;l5%0TIsjXTIcz-EL zt&s^vHoQ=+9sP{D;5$$k_d7q-E;IeYEKo0(Q7@SVjd)$u$nD}9;d@XcGm2}35*;mb zMjm|Ugj%2mVWsl+8Fg{xvm4MzwMI}o^iZvx{$UOH9n{5O)CKB=>*__Rwb^rOIE7Xj z<y7H;1<qU7St9BJ^};XujLQk<0nXR%THtya*V(J$8sUCfJnwUSx-05}TB~(o<=>JF zQ7^+#FQ^L|i@Mm1y6E9=PBv=2e4X5a+oDDu7S{;Zs}b7xWoLHtbuW|}q3x)VE~pXx z{Z{E?Px3&$1fyPzI-eC&zB^IdmL~kbIYyOxHm2+^J}d*dByy#1KJ25%S+Nguezh>+ zMbie+p&2(t``Z!X5c2!<o5K5Mgovurj+Q#%yXQ!A8i(A<)lAeyF4%ZcRA_Te`Uvk@ zY12h9yX`dzKAut<gh?yb%wzqpjG?+s!=xo^as3tKWoJrrSKFP;KFWiJBby-)LVo!v zfM?ww%b4*Ek^DJ;AG$Y|O{jE36z)yq&K(`3t;beso*}RDbdX*hSgFZ(4&<9XgT*`V zn`}GsBjk=fZ!(YXWqH{iU&YZ}EAD`t>Gf5-N0tvwmpa+DreV`1eipeua!=&$NslGF z#UWJ1?40=0Y>!mOI)FSwzlo;@rZb1$Bj`=?5>YY0k@=Skqf;HXifR|rSr4y1G@<4@ z;d?oqP3hi;KG%9DY>?+8-$#CaA)WQaoW+<k@lrawit%9>pN@PHIT(2W=6^#Tj5(E% zA0yvIu6re&72&a~s=gD?FkZVyAF7R93)u#9yz0CY7RbGjPuG4Y5|G`IuOchk2|&(8 z{&6jx#dhmM>o9-O^>h}F9Dsc6d^&rMIT@H!8n07%Z8wl(@K|F!ZyCG>cjW5G<&kUP zHQ&OVX?V>okzXTgkY8dyC_lUM8fs%a9=Q;C?D3_d)B=C1Xm^%1+t`4%UF=M5j}}Su zjtVhw)<`PY^+~??v6Ohc1b;t7lwk&IU1^0&ZF*yuAr{qpDXx|5L@smgh%#py(&Zg{ z1gmC85wi{o@3J-M!gME^dt{|J_58N{`%5HkFfT6}#GV#s{X?kz#*fnIW)V_PTw`r? zdS`ZZ@iZ}QbR<4Yu88&2cch%gzBIjJ8UDS=C^5^sC*=>swVPaSYb=9H;P3g4d|=B( z;>b!9>e@Gn&$!-9)Sq}<PF*pOJF*92Q2%ja`NRNR_w160t2&eI?9+)?U)G2`##E8! zFM~JoX-0lwhTMNiSw7*ZH-)bm%0ep{vcwPGw6v88KfkL7^Sd5NJw8leFXA6cpH_R5 z?fNS8VY59uILVzhK5U59nbUAhI2URh)QAjE9AE}}9qB|`ZJOEd7V~VPq0S3RQyt3! zwsTr1a=dq6^uKY7U8w6z2Mi8~C+l+9VY|U}VB$)#>0CN%hGXV)^>-rrD&A|n?{DzF zJjHQU1Mksl<ocM?3v)JOP753ZqmUa`!|`)Ao%O-{ejIZ;Vt!5JxEk-oVjK_3@w30) zJ7FMM^BT*n=)sP@?25*kyDzn(<GFp=6XY4lK3RR4DduEg&b1AFS;HsU;wfrpqx4$Z zQjjf5BAa%7Elo!*hrFrFYw7OeZ1Gjen%9!?&`n}$ms=v?rXQUN*d)CB;PdYre&i9j zNwo91B`W>nM-_uMiB4{}#P3^vRAPiJ-|SH+kL+MaS;*_G3*{EbyO4X@6v`IJZ$oXl zhi9Q2fsB60rm6k#i^o}}^t~VGd+3K;*AKIiP1HWAoi>P9o_SNaqX#}lzK!1Kg5HQ8 z$eq+4h~CI`y%9Z->3Se~Bh&T9ljdRa0<{PBZxAN0R(oUMnbKs99_WuAh~7v&kgbu? z1L?Th1JN5v>5Xpajp%`->w)Nvr0b37fu!q!N0E1;9~PlEw)<X|2tDu#dY~6_P4vb* z<jaSq%LC8@d!PqqAuGKx5V?QSV_E5k)zJ^l0vyEvyf0VK_g);BE|h-w68*4b^F6Yz zPu9GcE_D6y)rEAS>wD;jLe~$`Cxxz0q6Z442aZ4wL2ne7)r{UHbUhHgQRsRjdZ5tt zK=ekT>y7AvLe~QuBDcYI`l7#uBReA-AYVo{MK(oVb3I**!ZAD?`S-PSF$P)bjp%_w z*8|ZTg|0Vt$77X#SPwmL8gfNsr8kD+HJ3y_i98Vb6}I01KZ_Nz(gSa!b_|gxBP(@; ze#mtF5Pgq5Qu`kIA=C9k^hv%$?UU$%>?V4k9eN;oBVUEy_!PY{de%Yaiyn9yJ+R!F zhWr|OqYHW?dLYyFK=ekY>y7AvLe~S)8)aQ@Os`mm%9@W7)6oN~FRw^SZ_Gw-l%hIP zKlH$Z=z-{sbWiP#=z*l`f#{8->y7*RbfQY=fkn|(q*W6Gs4;ru2=vC_C1oiEJ#YYe z;L>H4X+C<RFM1<-py-1h=z|`J-Y9gvv3kNoS?Py1=!f4o+Y5nyxW2d_in{2BjnEIP zoWT7x(GRugho}1860Ycn9nlY)TNa3|=!aJ5ha+#?635XG&!8XvSeGNT=!e?kekgSP z5PeVR`X2hB(Dg&~NuleL)@O^4VHxk82FJ!o^u~JVjp&EM2=DuD^h3h&5d3dHBwas5 z-y>b$Lq8;4KSZA-U7xJ-B%8fNO$|XmMBih&zL)VVo4H}UpT}$IAhLv<ft)vF6FY%^ z7>|CqdH5!lhrag_ea|3p6YGh7SQGtlPQWJC9euJt`Xu@x>G~o19_jiX`XTB1A^Ifg z`lOlL$=u1^wz=HJ@28XR9nWokaJI`M<kR`3bJq!t>jC7#NjGx#o4Ne?eBfo!Xz}h- zJe{0t>Kdkv5f&5UsYS#}SMy{hAIM6hkl__HAsQRmkkV+IM_rBCxwE#{@i(61OEb+9 zX|J6NGCgmr855adUv1&#+~@e+`My^Nmlbce<i0{aSFw+a)1ozh@~oJxndSD}%Pqus z|5n#?D|-Cnq|9&cx-0jA*A3^_$a5x@)VA30z~%DKG-|Q_d)~zz?_EA3kF&FsEeATd zMjlBc|D%?2wX_DVX2?fZk9GdO|GvvJ{9MMr|8cHz=Dy1l<kTM~^yZrnO*7BWd)>^K z`rG5P_0PUqCp*);snug#`{TKq=hn!3Wjx;12RYV!FqMpYFW9!-TBGxW=~%h9B7V;T zZPt^mxpCX(E8FKgPfyOZKAYnF1^GonI(|=%<$c;WzMy7&|w%b#{J$mtM%TkbR= z72gxt<)qHKCkMu-@&TW`b4=s=${`!lcuW(oocGOr<+5AS_|iAFIlhxdYMgOD`zI%w z=a_jVXhOfF@q@n%asuWJ6OChyWzFCO?vfuWvc2u)iQnV-q02sEYwgPN#sP`kIeds1 zw&a!8d}adg{MD0fs9aU^>|-L|TdfoG6B(|3S|;)EQ;aQ`(Z#ji#3VkhTnE;?$BP43 z-II9t#ueF+^A~gbE>58xAB<Vnfr_~;VsPE&0To%?%ug;p3sY#rjS8&JglyMWOHycX z#mXXX?MV4d?G*YM*Z@60O#U<}8D^)3c(mF?Zd)UT`rot=Lz<M8FIy&4;|Ip{S?<OA ziJH0p95E)#i@2Y!+w%iE9`IcI)Csxo@gB`M*e>_;#PHk?$V*QS%gq`;H0LY!ZOYc( zx#f<Z{FB!o4J2))kF1}4zdY;sK)T)Z6T_c}c{3KY$}!C7ockS*eSW`M&ctggbCl0H zDm`1Cd(Cr8UM*}#y4gSXx!1}(C*&IM(&+oK0oqL#W3_g#)2K-5p?z|GsdnhB61i`$ zShya+W7GOn$({Mjp|~!Vw9Xk5zbUT;9y{6oqvNOfd-KX74{v?Y<*UO6mxq|IU2?<a zWX^JzJIGHn?>R4Q*XGZ5)||NHJoK^ipY8muUdo!dOQUhVFZ$I;V^Y#liqWP~mlq{9 zZEYgiz0>h@bbBLLzdNC<jcWo?<JGSE^`&1&F>m5?+fLa1r>5?Tk-3|PF8@<&Ejwhm z%uXong#FBKB<^>aH2(6R`g%S3n`^&{_gsFXroMJ8p{Zo`-Q^x~nPqLH+T+@}UO`R$ z$ZaF}W;b`efUI9r`n49*unKp%>qF;e^wv)5YRq3Z@}*X959b}7XzAKUljhn9&)Xxw z!gb=28Ln-RdnXR&RXV*Bff)<5>Gg;3l*_M0#p%1X6YfrR=~ip%pPH(5b(>4Tt)+iz zZQy)ob_v&E460i)CldK0ve!|AoJtjp_~NYoywpOo-03Zh_|^^mdBqR!4=ixq?b6g> zU5?U2Oq<5I9NwIn^QTVxws*>!HQ8DDn|^=Gj!qNpiu2AEZ4T6GH|x(aV-{<DpoYcV zKly9(9xl@!y5{1s)M3&Hmxa;8{~W8IUJT}|4!^;*ttjup+QGccy|?Um&jEQ3Pb)e* z1fBi!*x1Fv&YwGb{5dA;r%ZAwKWaf<S3Ga6*hClGlUwrYA~(Y4z+X2eYoD(lt36(n z#$BIH)TWp%)3#}9=u-QWtLp(g?|9c*E-nW4t}^oN^Cg`vqPONX#AB=WUgP-v;MzP} z<hAxYh1JP$-v4KY)Vb)D?9wikw{78`$44>w$>KD=Z%9cwa8PM^+3qnsbk0IiF!-3X zAJ@nlR4GCPIyK`f+cB<*ZYm6to7?-~d+$EoCx{1IEbWixrg1M9jZ}7GEp8gqnR}dc zXJThF`_W^<xpVbQw&GN4`^8Us^KY9g@;-3}yxVgh-sZ=6HaP4H>+I!+b?IZ+Td$t{ zXiQ}u>r;zawGHA;hFoVBl|RdtciuA3vMu<qMK#HIzbQZ2rYa9#Q5N?#cDMhqzdH9G z>`h;ePO&d+=)s>oHluC^)%ltyR=i&GyW*y1s(qE$p?uN%^TNEqoBJ6Sv7XoWi5`>j zU2M1R{Q0oeEVN2R`(^l@-gw$q7BpnE{lE=_c(s;a*}9d6e1C;5eDSp{>{*LQ7{)EE z^TJ7T)xu!D=;8^MHmwO8Y%_xQb`h*z#l~#^t_Z#}WD{#!>!QpjSlO>$9>qJ2UN2~g z8SiS*oTq615#D<$@T!%Zxwg_jqDsYBdt0-3e$p^m)U6iEBU;a4_GZh)+Sb9mw#iyn zbbg`G%nz{d=bXmR_E{|t9)|13F0RgR&a5ori%Rh|r~7gLkjwHtld1MzcpuMweI;8? zNZ@ToT$9R&cM*$E$ML39c1y15k>cLo1U@>#h@~`h5WfqO_{Rp`Qlnf;k&kag8<kC! zuFo$ctp17TcO6TK@BmMdvn`4rztUaUy-ya)YA5p+)pKRdi&~=1_A&g%%^(py0oTW= z){d>cfbTRmR_7kxb22ykxzegQtnIllKC@Y0i5_*a;BBHgyML=It#Pl$e_g-Ba$ow= z>^*zf`9(|FZDaf%UZaRT%ERw7_`RlVX<To&*+aH(b}u@6YA@Ss<|V(}5+bx;;&~a7 zt&ONLPps||!|#e5+%IOHXzv-rw~0yedqX!7bS{y1pjEPmX@=aRe=6TVnX-pvx?F!~ zDnC+fjyM}=s!iSy!=D*!7Ivdf=h^*=<bF=gXfuxIwm6=DO{hgJaok$qxa}17MR?<w z?1*F1BhG+&;aF{tWA(XLPdcq0pDo)4k*j)qmb>#-_^QWe>HVg34##ISj!(&;I<6^f z#jE2uG%fI^5cSw|m|T)J<Jil@v6r&akgnhui^4JXxJ4xO!7*lyV{GrP2-4zMYK&uP zkj)6{rygUK3xjD5j=cpq_S)^KK=svQDRYS#^};bW7ROl4YPim$dMvGK9ZWXru~a_k zw}@LZkY8M{mA!^_ryuIEB+rVXc5buSj(Uy7p$~DCVBUy5cjzcW4#v{{$rdc7eJ>H; zHjz%x{UELFXe)->B~V+Rvh2wQCi26QXsb~>mf#YvIW#4OYQF6xWj;0(Z5k!e{EoBo zHZC10%wtn&xP`g4W4n8Dnd<Gt6dW@pH&y4k(OjIyv5|>m!*uR_(XWax?H;<9?QHi% zRGRHW4p^`1cz2VSbk2`{*1N?fEm|r*;Fxj8F;nWgMq1_-Dh~gM=k;F(Nnv)~g~PB! zKH}A0&6mP?;#lh#PM&);CGpv3FN+x5|8TLC<XS?!@krqVQ?sQ7rGLtvB~o}%wN>oL zp4akNtbNiJ<gxXY-^%-)M)9_>SSMH4h?!N4#rJiW<)604*yZ#Qd_ajbF+*C<W;PhX zPx-ZyOS^w#E2<CTRfcxZPRU#=ZMDSjVYAk2KjvpMuScVKra?!k=zU2(V9fw7SFXvz z2QFr(Ga~th#*?J}KV){ZNf>Wl&xdt>GaJ{JPvBv;{p2$ui9F9+vpX>>wc%^xX@*TS z>px_ku*e!sO-zTds5vX7ZKDQ}#jQ{5)2;3-80+O)__k-GYAs-CpK*<7>lv)w{L}3B z&uXIkr(ilXD4tsnXwF_VbYwTL;rq;tvC^e`6WFqrzWhwvSE3SMEf%Y}0dlDkR($3r zN9wlnqGW_T1DPQQq+Dccia5pL{Mj9Oy_yHy9WNc-Rf)V8`SLq=#!H8heUVp~ju*Gq zISbh?nr}jWpyskcMdEG#R5tp2U;b-&k@$=pj@<g`FH!qdYhEj%;-B0Ixe{_gP`0?6 zJc@fQF3(;g-$wRDHfg^`es*XKH(E7E*dP}mzg;;;_+?IIhLhd+4Q(y*M*cm?jXywc zaI6NumU4^@8{j}@$or9lk^6>r;p?>Va?MZm{^TlZo|x#&GX_0l&s>afy=UBeOwIF= z<NlAl0^^Ao{|EDx9D#fvc^tAMazj@mK3UB*kar?4#CR6wD0w;ZKIECmOOPKSEAv+) z7a&I=pF)0z9E~iic{Orp<d+y<i`*Xh1+uc8ae8?!vhuSibFLuoKvrJo4P@ncXCX%; zE89`B^7@tMnunZ%{6x*lHkJG?Hk@y}zg9G<(pbDlo{!uQ+4+DMA5*m=1#cb99FY@{ z`y;1Tt;Dx(tVUu;U7m)#6FCQYcyt6?-Ql#TVm_32K%RwM7x{8juzc*~aJi^0?(G>J zEJvOw&dm-aiVJfy*@%+Cd?4}@<YCA&oM(&dwa)xejYfP0@;2mG$b;kSiNpC=E9*6u z>E{^DHR)xaWPYVX8POg2wVLA+ud}(mytqlzt73+lOCV40iTev+J#yn!rAf)k+GI22 z@To!EX>x$H^1*E}64@Jh8}c0NH)UTb`+Vewj{Hufmd&v=#B~llc}n+_Y_jKj7I2aA zj%RXNo2!+1bwdZf^z0E<PvAcC1#NiX@#`$}R2{xxYYT3$;T1d6vKBYk+nj6H8sL7J z#@xSsYd+4nEH5xJ;*rB_c%O%5ac|fUY@4+!&wfyf?|Jc<_2}--SDyU9W?a6@EN67) zpI+Qy-D^B%8(QMJnQHADjIg3vsPS^BaV0CYUlVx?<}AXTTIdPBDHp{`)O#9ge=zcL z<WywqyW{0N)O$bFySZNWF&)n)px#fT_FEyJMLvuCZFmv;uGaoNWTg+pqxRjO{$lk} z@1;@i9Jvy5L*!Dy+3X+G`vBCtl5ZlnLoVHZjr11veiZe7qum<m1@dEL&&;VpsrP%R z_g=`~ksl&AKURZ`Qjak&)O!o$52$@_<dD!V6p<G%mq6_YBmd5gmyM8jCpwc4-n;X7 z?+zos2`H}RL&%@iyd8OvItMjHhRCH+*QiG_KrWAr8YElfO30|GKe+-jYMFXtyeV=R z@<8NP$f!qB>hxl9t&vjuw~+T>yuCV}i`)$P62^NYI|LTjdp~3wWVK(B(nFM59*1!y zE491{`8D!VH5Vc;M^=6oUH?&@OL^Yy7*}48Qv1ql(B<pM_hQ4T<b$<h4C+1ffEQVz z#(Sa01CU*jlaOy>P6Nyd!knp9E74}P-j%!t`5<b4R&<1jR_lEM@>t}WsC~caV98dk z{pC@?lHsZ0av}P_rUQxWlv?j`$Xk#{qxR#RXR{5c_ur`Zp~yRszan3bug8?yuZ-G1 zfP57BTlcZdMsrP8>U|$--&`+`OS~?W+AocIk3e34TpoE^PX~Hm?-jE^y^lx!hHQ&G zc4`m>O%0H`qu!OAG%Y~tgdFvuBkfn~eF^rVa=v(g{dQ)8Ck3GPBT@Sy7a7$=?YBkk zH!^gf(Q54{6|^Bswf0wUZ9%`*zhVbb`=$0ar;Dilb*TM*?OW44)c!xH{lH;16oT5H zfZAVc?MjDG`+2DSe%;+^GHQPuYG0bsnJ%LCIcnc=#XXVKpckKKbU>I@x1f+x3z%=J zC5;@nQP{VR;@6EXX#2YF7HuAe^Le+!<#%h0#iXzlUUSDhZJ$#bQT0Ru@7VjD%zfsF z^yF|}zfFJ9`rCGS>hxqjgp662FP-Se?0UR}U2{>fgd5r7+GX8$m8Fs`x{~E}t$2Lw zvncm7p4u3WX00l9$=xwGhQ^kk!zK^DrVVU4h+>EJ5sNN86dgMbr&oicM9(`1h3Uo~ zbYgJ6c=Pt5I9V%+oNjesX<bW7!ycs4V*kz3mk?)Jf4=^9b|#IXen%Fwb4O}xtUe8) z$0jR9jK?0a%_5cdM~{$`T3nO$$G^C>B;zo~*A^a^Th-~HIk_j9Yv(i(Ccc;CIggV$ zWxSH~=jiWGsmDC+`a@}a`_IPm&a}Dmx%DaBoV}3!s_xS4o14n39l9)A9=?$`+&qPs z9$j0QWY(3&zD?#Y-`8gDhboYab)}W3qzi*=H>zIgrHCq3C<@F1X~uxhqM>ztjsBcf z<u~UwtRF|3yh&{SsUxm#Ua54f@VUIea~{h`j;2+m-pJ=>++t@>45FZzP<EkufmmBR zfF4fn$&!=TiH5<EG=KJ4dGTpaCh}}(u#FYf54_<z!niV>`{+xnTKdqVs#WP>&Ms|6 zzlXwwb)j|1|FC+6JH@4SMdI7Bp1f(b8a!yE0Zsbem<MO~(Z+fXp$9&%+0uOldBJ$k z^KoC<V-I(-RJ$_dZ{)#0)wssK_~Ltkjpx{pz&Kj%H%i!6ER=6Qs7J$Jbs+P$orLY3 z>!Qr=;S`uyT1>3EN}BsNioTCuA-WWFWiHnS)5Fx8V(Ok$D&KsgTx&$UJfL+)N`40S zQO!+k?uvDJFDJ0bJHMpe3wJS#b0g{0CXE>2-jc?)VRR$xn*7wDC9O+$AlGG);+&n# z2IdCR`d`b%-^TT~qd(txOEjPIcB(jhtqyy{A~=6BTf80DomHLiQ)s&Q(zHDjnRRjt z3OJuB#D|uAVEtjV)UTE(nR|<EX&6Dr>-fuY19q{~F7w#plTmcIUL|%e>j*Qyq7iwE zf_dSnTH?IdQ@PQMB(6U{*)N&OUZ~5KHCrO-?|=Q*vjg{=9IbsJ?#w9s&-UYX)Z+~r z5Zgb%mcRedn77WK!Xkq3`>fu${&w`YumAT>oxSDw*EXTjP#-_u^WGx4%&if;pX&*> z*e6en%oxEZoH1t&g1(B@?ryN*ci6(yZ{&6^KK%8&%DjD2w(PqriiZwa!ET3k(JuXt z`+3YZ<a5XF)|QNl<w1?7vk8;i%ZJSR@cJhzaL+M^wHs=9bK~FDd9XB0de>nLuAi`o z9i)=1{H`vz?^JEhKW0e%o_e7#*5IN_DO#It&o^)X%sSSv77IN*d6PS}_`*BJ^spT) zPtC7vzGI+RQr(?*FsRRWp872=^z!GPmH|@X+o3`ekL%?}8!-LxCmz{icjX`+aC#gI zYGz3DT?cT3b{#ae;S)Rej^(Qs+?9^G&zAbtNaI~n-K1MrZTQ4$c6>y;(xQEbUo6-x zfInH9ty%G`JU?I9o1fP1l7ep>XTS1?aqZI~tg@|%)GaxY&+F#R8e0C){1lPAdd_C{ z?a(v!e*8e*(RdVVdUBZb{#gva5j}%>rQH<e%M9evCUcnA<Tf;St}EX)IYG+0SBZ{P z=*=H_rE3m1dm}nO8_dIss!8q>FN(;#p}g$19^%7@Bci@T9p1H~9kDAtMSBBx?%cNl z1&ul&5|)SYpid+_AO9qtO$p%sh7aTw?PrN;8$<cqh^1n4TopQO)s4St)PrTe8A29^ z@3E+}_5L$%l(|%#T%F0HcMPE{n`9bS-k6O}IwR}9PW{&~Y_9_yzx9^Ik1!<teEFDG znA!D^(^iDhh019pSDGSwdjv|Oey7mN$1mkDTUWXM;WVncthH>Dr_mVhuq00(XUfR9 zAh*5hMlQEZDe0cAa2eEAH2c<onyu_W?`+EOeapJ>fsf~jAMv=iihZ*1t#e+y$xh<m zGVR%jC(Zx!-W^_uzdbURYL3<$C_hgh#(R{XCBEckiqqv%d7n0q<+E4%%Uuly@(Oje zqDS>Cp`Z2V$M|;UdwN_EH;%s)jlXr`8xCF<ubf_s^#fD5MSWxOEB3ecXXgn1`oK0( zx7$Yf{gwo7*v*Dr-co@jxA5b2%a@}Tt+z|gojrK=9y8jxBrC_SLkZscB>HrItcdwx z!w(KELnD1Z3H|X{>s2D5Ybb5?ogtQtHRszL>?x=DBGCl*AD^&1OY~$T*_eb|Vn=9w zx)s=p>+h3_sqJ`C%q5Zgw$y+2n=op{_v{?Us#LL~u(S-;%r=sbi13vUZW)hzWykU9 zM_S3dL*n`8FR{$O`UK6ZoD^=fvov%5y+&JaOfo-uv!yU<8RfETU>bj9)K|9p$fW`E zZ1_`48*=lq6vMJ?`M8<3)T`7_dEaI`UJq;TDm+^%zrp&m>ZzOMWhdrHFHOv(L;u84 zIg1qWq>Pp3_01#-v2qmdWsgh8H^)-t$TZ=bn8Z7T)?&RLJ(u-sF!60Yp8Su*huxda zmQ_5(YIO|e^N+U{`r{sJMzWO+V)#2t8xgy&6rX&$Kc8wiTS^O^BF9!q;WG-#i(#H& z(v0URe4lfHoLaU7>)$V#o9%ci_c=UM+OjE`H?CVlyff@11(}cHKUy4NUOpqGq0wo4 z=IRoX2sdSRPsi|HHIl`U%uQ_7>M%aIhZC#eSefn4ir`1;trl}*40vcuSKc}GIeT&3 zopY0h{QY!|(Em*7hcoVLUDcFd7;3^j`&8#`?ald!Y#bM@!dXvQ;%^!@;$>P@<Ri*j z@tw^+u$^~Oc){ILtjfljt_vsO7`~7%HJR=q)#_tReb298y=!*lPIrznzeiVDChlwc zJ8ld=bYh_F60-0=$I0K0pN=&H$b0q)@#ysmb}Ot3<xTC)8lUUR^|!D8*t5PlY!&XY z9@2E^f1bCUpB*i`Q<@6Kzh^6gzlwbW(ltd>2JynUiad6h5a)MtK16eftv=X;rVM$^ zd^R@YgFCo!%apYm=ee6$@5A+ZaI6zWSv#;K8&B@Dq!tBLxyH)5hVX4Q-KBdoTk%p; zO7q__W$4mJW4>gs51%u0y{td3zfC{*sI4so8*em}^taz&_hR;ayN3uG5KjFnm68^` z!8PP2*QHJkQ>B77wP^77?!0BSp4{zRk=SRrm#x`dlQ%q&C1vjF&cD5?&LbODppJ!g zxin=rvs)2PCb#Cwo4c)GtA_ZKX`?et|FKtQhl}Sv+oW<|<GB8I=2s|9Pc|GD$1UBt zL4Fr%+kd*K(4-<?oi|H7nKhPe?iTi+-zD_N^|StCWz7%a(b}J^E?$-NbIR9c;u?I# zeXF-j|1~G{+%1l-&tWI__;WuSZyvv3f_S^ph;JM;hb46gWfK?S{tO)sYXa+<Qd%rN zXHPPs&&}MVr}g^(XO7vafvnG!3-bCE@w}t=8nHjMr|=mW_MdI)&(Yuh%r{J2sGLC2 zO)IkXD?>%Ef>>(UyR6V3|8=@F4{hi}&#n&n&zw@PTJoWjG}PrEBT=GM39hN+Pt9vh zk&?e!;j_q{V#n{s{K;)x53YZ0G7t^<yHhq|+wl=JHYuAeDm726S~G^qj9(&miR?%& za}CLCyv+1}M*Z=(Cb&Q0Pjj*9#s#KdU;6!7zi;2oieblV&ytorjN|&R?Ofpr*6z(P zIwlPi``a!PPgZxMwx&j8UAu-Dcrt=UR$nPX{VVX*vJb5)*%a3loG08fd@0}ggQ(?u zN_K3Yh`(K#(4Viroh1gf^YZq`Q_o#d|LLo1vobZ?mPAo@-Sy&1_&&{@PN}r&ZGpUh zYc-l4Ad8`6T*x^!L~}Y|pIA%bwAyYZ+o<uQ|BtTsfa~%5|Nkqa(jZYudmv3|_qxs# z?UKk!R!Kuzv^OCkD_d5D>>{*Y*Lm72A{8<UnaSQ+|C2Z0-{p4uf81_vx5w@Dyw2-f z<9Y7qI@dYRXPx&WTI${hCha;v<9~2y)}TY=%HwdKLIz!`F+;pfCIyF&pG=Dfx^Ny- z6Y$l$9J>42A~yFs05#Xzpipn0q0SfQCZJbx4*h<(fiF81hxVg#sj%EdGg4f$G6Bae zTk?;M;$%bayba4ieZLp&w)>6vz~dBbw)CLF@?KNM@-OvR%%erY^jo+zKfZS&+J0V0 zchl}%Ur{0sJ+*+g`G`2LkW@5_cBDcc3Ex?S?^eS17o88kXwXPQ;7==qy83Y%AM=q| zu<v`q_b=i2>RQ7ZGN{^_?bBsz<XP;N1%4J-E_a27Dn!x#j$Sz7R!`hGE{uPr;(?i` z*Z{v$3co(&@ZR?3fA}aoR``q=pPvO^6Rwf>hRekZtIn{bXc3_Cf#Zec*UvZ-r*1kp z%yGm&^$XiC^o9S`w)1I4;y&}FXyV;;lsn%As}EK3Q@|gE=UBVr6FG49CT~<e?VsP8 zDCdnu(h9smw|@UzhXv>bF~`jKoP2c@j`xIPNMT<sJQpD&gnhVhY%J{ag=1IYSXao1 zka>MX0pl|9)%!d?OfJi@@?|D=5mRw)xEnfmXyb*XalE_kaEy}F!^BieTI`boZ+Bhf zL$W#ceJKN;=+^VUq=NV-W87dzcO49B3FK`b0`!kFU~4Dz>6OK9Sg}|O<F}mRb`4BJ zo93H*Z+Us*awZ+WX?^51m1pqJdb@+nCQUT{R?FRr=~gYenSo~uPyNoL-5H;{bFa_6 z!Z^#yqtlOc>f?(%hvr64-`lDG`}==3qaGyVYf(F&UMQkLt1>YcTpb)<Me*;CrJ~-& z?Ujf2I?%vXY;JCptHYbuQT)4Oso>MPz49$952#3m!WyZnq45s%@QzHNUwj>;Yo_o+ zW74tx@JW$Tydv>`G663fDJ7XNZ;;}xW~gGjj$Aox47a<aVxgBVS1IK}-ltE5zS1S6 z{6!-fv?>+GsK)cJ_6#MT*qqa-5mo%fG&y1ylMZcVCq;E}iX{C)|B6-JKmXpR7U*AO z+mMq`-g#bKT?=gA9f<p_?T<QCJlLjO*;$_QW&pnYFqstSIDqSvEK#Ov7TLWj5f-&N ziS*YLbGh1?AR#iwl`(_4hY|$n8J4@K$6Ef~Pa}F}6I+9$tj_y%G2$iIoKoMiNBrW4 z#+=s56r7W0L8J0pdG3n=a1)Y5$`wv9Zjl~bGYBCPgahs9M0h$ey1L8Q1;jEd7GmnQ z@>joZBzN^aF-)>Q{y0&?Nn|doo~M+KGKuQH^AY@aZ|0$jQo)|RM>clGq5kK7X?x2Z zarZ6k+=Ge_K8`+;u;Kl0UE<?jmNo17(9Ux4$Lum=CrztP-F)_WnSS?b;^q?t-%f0= zR;+OZQHLoAulfG1W?;we%V~CBg!fl?--Y*4cz;*BrD5+yVf?JO`v0{5L!uXqGFQXg zFJHMwVLC&Ht=sqeT%wkxLE<w7T3T>~-z3g}h_x5_VYc3)h@4Dl+u+LQ2P^Z#My7yP z{TZH90-E=IE(TRE<V}umB~8JJ7}U5$w2LetY7=`L36XjE`+Pe-SC>p*y5o2K#kH3$ z+qg}?pLxT4#l4FzYyG|s(<@T3i;Ps&4EC&+?O?fc2ao;ztg`12Tu171C)jh?`q9?5 z$JcMapR0y-o2}(_b$&lT!e_5MTvHs;o`LOatGH3;J#eSEKQ3EMxu5!@A^w#za&D`+ z;EHrua=KM4KdBqpdesdM`1OQsqgRmpK?-8&C5e!bne|V(R4*5l4p4^PX3I%^KpNh? z;9aFrWK4wRw~uWsi&=l+_xY9<E-q6J-SJ!74qIRLe1Q4ybG*OkQkkPl#Bcq-e0i6W zO!Y_Sk@V2*6zIAmze?3*Bt6IUWluA5fH$J?`&s_jO)Sp&k?*{7LmZ4=d4|X>p24Sn zoDIF@8(5ya<KoG0!=MK=lgQMM70ug2z?3wTOY^iVd+!JV6USz9_GfP86{dGPG!w<9 z+{zbBkKgo^Ty|Z_-^dSwrhzTQ(p;M_um}OTJe;f!)#Wc4r$XSIp+v8;8z1!~70OH4 zI6^&xuS<>r{nvYGO@2Jz@hb+(_3zPxgG~6NMIjJywwWH=rO1yO8v<QF-=o=AvMVhQ zhd?vaa#wRIf0l;8x{iCayx+$PKc-8+-lN??yK*(tjvXx5lVK)5dR+t@GP_Q5z3Ro` z6K6qno*DfhV?ukcWcd@F7f~bot~CEc+&|Y!cnv$(kX=1cSgAN*#j#FpXCkiL9i~|E zgXzy97FE55f3fY<M@sanau1HPHWFok+k{vA&J7`AvzaW0&A`We-2stfwp}VL@N%Xb zdS!|y%};@a4}2-N>7(P%UTJu9t|e`mU?;vjI1RrjTF|5Aqr_iUW}vOa4gUCqCE~ej zGjP+io4n-mzK-m-P`1sq>P<j>d8cmC(yNkM&0BZ&1sMrDD|<Pm{C>Vyy)IzSwuFSG z_J*=z$pH9v>od)9Z!g=&^k=3obs06Jh-vwz&vf)uv!R7d_hj1h>$Ra<nbu&sV7H=G zr`Bh>v;McX%a5(@h_uPI%|I2ex4e1RQmala%XH^&<$1fI+J2qi{n=`P9y9QD^@yKr zk0|@+{6DnN#<<iSM!weiZEwo7*B_m;F9T{WUE@p7pS4=bG-Z0Tiqg@NmaS#So5OJ9 zfd*>Oxaa@$@wH85M_KuHR&HGQ@&7bi=LZ!=DOG{l4=X$G-N&=mRc~dw*(-0;wc?w@ zAdcB<46w7JOs6m%WTk9%g6T-6`$hEmtz($3Hrn&szSG8h*U|setbWY-l3caY^O1e$ zJ<9R5t{Pj>rSkNyDM!m#dy1I-<AV6#dN0%7``0<<9}R=afsOQxZ;s=!yJ1j#q=A}L zWjZv<hJl~kE$VVG!=Z&~6Q(aYUZ|F3_HNAn+KtBQ4|l?VjiYJjn%YBh*;UuR^m6F@ z-LOQ5swPoW#bD{@<#|D2h-Yq4BPw4Z$+YG98&r-2*?tWU!?9I2=y$#Ur>AJ0u<5iv z$L!7b<&;S<ZO`mKv1`>4oLzM<@=GOKgA2-$4pqjLZuSliFRH}PX5-oG=ji8)&#M}l z9?Nv*v$xd^@{w5Xev)2(*;Jk96Ny(PPtelvc<_{4OgoO=<~Q6<f<<x>^q0j@zG%f9 z@x<2IV0YmhRqDH1Y$X#3VU{Q9^{X!(gU5uxk<=FIG`h{Pesl<o%4ngd)|)%dx;Go@ zq|ejwvFq*fTO;6Z|5McMbOM&2Sxm2QM9~k^WQ^DsMET-i{?+AyA}zT{^kwa#`c|S5 z-jUe+3u*O_!4UNBFp*9g1izkZz^Lc4Y{REAOu4mFZ1UCyQY3}~H?m`>-TIT{?av61 znC=VbhWCVbCU-fj=&?{Wv=@X-KP_qt>JLdlUQpn-Nu;8u0fmk3u(t3q7bWY9LA!gx zev|v0OXOIrvF-&UH=Pw#E=<7IuS<x&y|Q?&R~&AW%p+^omvh?}Y2fBWcX(s<oa>+M zjuy_cFj>BU$S-+7vyi}QO9^Nj76%g6dE{(P1?O(!4pIH(pf+p^$(tAf&h;Beymty& z!1maBeeA_qMxGbXkIn!urxMP!W(D^v#SAY=t>%(q9pJ;YIQ*!&lbiN#CAlkg<9Jc+ zA)8KLZ*|#h*Gu2Wu2YMf^X!Vp>i*W3zFj}=a_T>ubM@*N8ZO7ai}iv0AA?!`)WgJ) zT|<R&P8D-p)8V9KU!s#X#o=~dCJ?s>exGtZO)m^%%vr=cN*<u@dsz;`NLdop_<=Z4 zCn&MIN1n#%^Yb(&z>g1d@H+Th)oRbX+!406-bum?;!^i>-nkBNQ9lzMvKMlVrQUqb z&UAEM-NZe5wx4sp69<=Wo#DLuEGI{^6Tq~63E8?<Njy9&0((}hC(q+jNL|RwWAe>= ze)pHBc1^1|zBR+P^BlF_2UfgS@cyl*=RP}jL$l<!&AeaxiBoYD3_K)D4qm)LSa5!L z{yC2y#O<IZ>9fGPU@;ll&Ct5nmsl9BnNO0#`s3N@UeFS|StQNvAjg=EF0*+Y7mpus zAqmfV$xn_*z&D>4kRAs6`72j4u(~0hbA7y-ch<<jAqg^^ecdbmA)DWGk{QQUg`VIG zc4fea5i7Wtw>R_G**BKr2MbAD`xd@vcRWlHEhIZtAM>yGDAIRIBGRVL_70dTQcYb) zvVU+gWE;8D$Oa{n9g+l7_5EnOwiLPBpUv;e&1Y+Ga=1jpL`Y@vQlI`<%sn(q1l_rd z>3|z^M0G4zXVk1EbmF*N$8Pxvuq;2?Zu$De-`D5#lL)({?PGpxjVD$^m12~CGiQaF z(U3^JhVstqxnhfk-2^}STU&-}RCHbTpLXeZcsx}t_xG_0xdSRZEmVHn_{-0&7`ff~ z_cONpNJd577VY2q$+26GXP<O+ob!|IA-=t<!Z&)WBe1^5wo>GfGThF-vmaX6k8|iA zZTnllSl!Q|+vwWPeiv4?4RDBAarC#oQe0#2Fj1njUj)DU^Y+1CzyB`xps|oVehYo| zC`pvvCl;;;?x4f+7l~#&Cd0<rvuH$9wCM4cWEfjDgT{}@5{;lKP`qX&P5yRI<n%NJ zh6Q`D`S@lLx9tdbX-Ag$$&U;+-(1QSHmw%7OJu@0nN<#(WA9cqv)|no^1$JWQ&rV1 zriYI$=O@#};^x;GkoWjFfBnRI@vm1I5OW{}m3_TwT>CFkIg8=hYq|$LxImh_v?&=k zZJ9wIKQ9z@ab|NHxnXpI-$s$ei&$JSE1#<W+~}xi9E-(@JLu`{qa3A;mQ*K|hQW*2 zM!MilPPH4;C*vCF;e2V4nkX2GAGXr=QZ3Q=l{2Bs>L>KgXf_UMG@@DuyK#ki>G(5B zhHlc6<%{O5v$b%ZgC{KZQw5c4wslO4O!rfXS%u|F!{^}C5&LPgY+-q?Kf2eqK-;0r z<~Xy@e!Abbp6Nl%e#?+Fw*JY8KFPD^E2Gn)KDQUm+YsxpAnan*UdLcCdeutLS=}zD z3ui*{g(ozr&zkBNZ2sy^(Oep>y0-cW(?fU8rKX`OBJrsdw0P`Ir$?BIrn4AEKGco+ zIVORx-)!>h@IL-gb|M({$Rx5)X7IP;2USN;iG->PNY_d4Ee{QkfH|ROXzJD0>Z{dr z;C99ydL`s>^%tgV)A!IFC#H$kjg5q$Mx@<eEEJh~M?mlMXXv{bNmyJNOD^xX;;#)! z#4kJMk@+4=_^ha_Ri7@TASv*sU-#SFCJ#u(57S*)oX_TJ?d>tR0uRyRlKa)4x5XfL z;t&nk7%ckf7KbgLH`2s_C8AcTc(fd_mO@-SC<d-3Swm#R!FzpRWO*OxIIx7jU*ikc zS)6J~xeL60$0PE6br6Kky2NKkdpOv8XTZd)7rfWL7RJ<>aR1|Texu(Q+;?3GbYAV@ z?MudC!!dan?O4Wprwp%-7#D|mbsK5LxOCfSqj(%2vWC_z8(=5x@t+UMe{Zod8S|fS zG9L!R*!jo$y;)>q#`>-l*0$-!GU8J94LD@$E244O997nMlY($Hh#BOD8jpaK?N5N~ z$xhV#;9BA~dk(C$89;+7r$WlD$3#;jknYc`AT!2ALFt4De$$n~VD-Qfrs^!DvdL>m zl3_f!yy6|TEJu*InI^FHMdy0D|9_jUF^{>aZ_U7`#10Y~HTZ|uEwSHA8xS5Vw0XCw zo!`-9hD8N-a2a2SogZc5$X?5;*NmwpTGIp2?o~Dw)+4l^rz;BsSzL)@;}k$+jSajo zzehBE6+m_LXfX1-MtWs6P+>d2=IO)MONNL!4OCdaP%B+90p)F0c*$uh6}IPB>;g_! zHxnP68Ov*SIYqdx+PHs<IUXK!ziM8c4knnnAt$O6Z%a%=$9V(kxlhtG>sb;S{BWiX z?{|~(0l|1|Pd+;rB~W|kjrUzl=+SyFI2hXpE}XESK^xRSBbb2r&1R}r-AYgBX~Vu= zhPdLwV!DLw4VXAuioWqvg#o2sh;f4fPN=UVXA%vt?^#29Hc<(!7mvm<Ti^35zG&mB z#%8MXk{v71!aD!47t|lQOM`~pNy9q_B>B}{hE;Vxn2A!dqqw(v3e<mAI(GMz<)pq3 zgvXEjuzj(gsO2|vxc=M%&m5RZ7D@X+#Oj0Ospcoz>SawrZ>K{3fG6VZGA^XHUn;a8 ze=qvByokMr&V^bZXD+f}I`oOSM?4PAB%j_~CM(+va7fbtxOS%t9kVA5>js|VOvWj} z!#=+VJvR`Fe;%i6d%9w`m)$_IK#i}^?h0>vcIK6d<n2uTVA~j(e{8JyDRhKWJvCoF z;~$${zP4oG-el<ir7Ky(rdt=W7?MWC<~Zt2Yc;*91D{RZaCmwz8hMDt3Y_Oe2kEKu zhEZwI$9Mphb1;Uq)7Fr*ERa4}EYHmi&xAJ?QG83_Wuh}I5N>{7K%-i$_zs#0ueS1z zT`!vO_b*w(iYGSkzig5tKJq4;&0q)fmr)^ZgzI90xy)aL#|mwXLSJ!DYt1mb&<;kl zZ6=3)#bVT^#Ol6@#t?I52v(<OQ(-+q`{^v#xm}OjbnA2lI8`DIw8Q`uqZL4Rj2=iE z41`Rh1}bdlLcKAtxaSr6GpT_J>lbR%_0wQ^Kr8i5pGt-8Iof=NT>dm0->drY?mv41 z*T0>nl$fJLp)bjQu8OfXZaA-H6Ny|JgFE&Pq<uJd(#t#n`@e9ehEeM9<g^G2cjVLU zMc(k*sW+S3F`*5?J)v8;5163^l?^T=&s0NT){D*byQB^pI6ojGl?>7OPA@E8HX05w zf9biqhM0{S$l@s)V4WAseeU#@7F{qz-!nNh>uMaz6usyBB|oC>Uo_Ex`HN5s>lE4x z>;L(}p7^m?koh|$`OBeu$nIHlP*-LYr#{Mq<g@X?U=LZ&tK0{o9rw{Mx}RwC`~X;d ztBJNVe=$2Z05U)Y0tbGgC4sv1!I3mLbN8|MLWUBp^+<=bgYQL?>MX=}OEbaR*O{BO z$_x(pSi(i-FWm;If>il?I+FRzJr)3eMqo0wGk+l#l%!4`1Y+hdp|X2;52HzVxV;+~ z&GDsvhVMxW^OyO!k183tfg|%5q0NovCH&c2FX$}hFG3r&91ZGrIR#=rcO@0?6w#gW zMVs+u=)tv=V;q@oJAg_)0(zM7ML)%fO0DsxyBT+)8F!{tvi!M>FFhGwj^tI)PQLgt zzKp&y7^4_pHvPvJ+R2xWcHU9eas*BI!<YRrkNE(`k&(<V7=!-LMtJPJdJXP1<BJ0G zmx4|0+#be}t&Ai894n|(`rHfA2*wwQ-pi_m_QHCi#?(?n#vQ`AqrS!lUooa=Gp6j) zmBns<Sc5*J(V6kZXF&rMwnuoZ6tmsTSX07SqkX{yyD_HRWK0p-2;1{Cb^+hXm+_1* z>RnFJzkJ!}ecxd|<4Zi_%aKpgB%3islQHF-L!D?lV~sLn&9(QtX(wNh@nzZuHPmGs zImI|~xZaDc!|VgQ8DCNxm9Q`4P7~vfMs+Lc<jWq$mydp`Xv&zP$C$G2!ea85HU9N= z^z<LTJea5ic8o7hj4#W+Xv5||d=YA4okDwIoxZy?NGD&K7+<=|4Rh$m_@co0a!*fz zbn-=+@x}I=IbLB*xy5{hu?8P7)*NB1$&zO45g1?YF}}QAUPNmdM|LxgER%7eoqQ29 zzTEY)rhmB;Rxlk68DB)qU#jnPA)QRAVLtNX&1JfRv1Taq9rJNY*vXel<}aIn9w+Pn z@TF#l8dt^m@|yX}0DcN_XB;tQej&86I~&PaGwu{IKic4HON|&)`Y@&l%lD5!8qWCQ z$oS%^ugd8#j!b178O37Ock)Gr@dY2XIv!`-`Ng;+?_i86j4!hpUuqZ2^PPNA84|^( z&$vvxFuv?!d?{$L;yU>vznyn9zi7gpV0<~i_+mTzBd5wZQpx;9Xd^uKe25!e&iG=- z{AFVFD?W&E<Tm4o@K|A;0d1S<KE{`s`H9s+dtp6C6O8dR<IZQsovIRPJi?e_z?kwa z*%locYqSCsz>~##F=2dJF{ptG+ao;IOK%MBWvr=6ZlDh9r{NgJlrY8=p^dOT?k#8N ze#Vy;H6MP`&z=~;_%em@<yfIFUBdX1$oS&Pxl={P6bZ(Z<d#h|hOs7*vBoG$9UuSU zOPAn6+R2d+#*u5mJyH4(Ul@0=lRGwyJ3l3LK=Th@WOmn3i$6?pxzh^@|FDMf1?T<Y z%cwIsWC7z#N8x*3CHWEY{=*lc7S<`W7uG4)ZcjV;vXSxSdgvb7$rpXbmqDXEXeVD( z8DCoF2jILvOku3SPS$*5tYLh?zkIQ{ZXxRAh%MttYlaf(<jZ2lm(zi|<o+M-Fuvel zzPwc$Lj(RWMS74b{yhF4YiunjoyYjn=`U8YdpH4Kh%e*IedaHho0o8%9EoK9BD7hE z`$(@p+_BHmATEq4k&G$Aa-H~v{QODDSmrQ|7N`#t#i^NNiP!;CYwplo+Ds3!90I+K zdeAEC7`*$dkSdrwpkJ=Y(T7|R_Pv;lJ3l?;D_;ZMx%eU7((D0T$!#*uUK(eljD|~t z6Uc*c52#d45S)JfiF4@pgmMX^;kmMyj1l$3*}J+z&SpahD|kwEAAci9XA@|-s)<fh z%ekvg?l4PH3Uj3Ha*xjY!_JfaFsgM0?SB<un5zQzH{C$*?Qw%MbGotIb9%VCLkWDB zbYZb-^w7<mt;?u5ONU&Zf-e(_Nv?bi?fGpo>Ibkq_j)CC)|hCV)9*AF+_Z_dxzEK3 zHt#r1Wd&4NHXfUED#VFy)~GkA3kIM4Li>#UM9c4gqZ3Zqqal{@I|fByWBdu)eYp~9 zy>kZ_l{9+Pa|T_zV<K!R|3=%Vb;ornSILiUfPKmaVQA0$WO}{^x~?6AJAd{9OOsQ) zWY-BeVD3Sp*zF!|kW0Y4!8yco=ti!oM;tCUk|4e(a;f6nc$C$(p+`T=pvt{dFmcQ; z{!U*@0?kt}<>qxd$Z|bBJl2oxQ<22E+2$m)?kRb`e-l~pdIA<jD1)Zre6iuMF{tS4 zNT1g=@sd_4=zKVqMnzR|A9EA`u@UV$M<za!L0QvbIC=dty6!>|9qJkO&$0Fr8l?EF z5tMFpWcg{2(WYg2r1?P*e(44<T5=;9xl9d%t0k~s>SiK0#RrAYN!#QJU_auy=+r4W zocFFLY?pjXrz@DDuskH7gBD~e!`kA3*f^~#6x0la%P-_na-=7E1Uhl=LN(y)ED;vp zen565c7Z20!|*Q6X8GUxgTWk@lhJbuu8yc6N0roZzJ)qk4DSv}ZCb=XJPpl1Ci7zI zk7tIJknepi&`j|hR4RGG?VPxc3ZLPK>LuKoiAj)rCyEZN_(*qo_(B7}l{Qbdz$<Kx zdG~RIhS#+47p5oSl+dZ<`x|*&;qL^Cy$_P~Lo4W@QSmV7(E?8Apck7TI4RQpq7L3) z2cdaW0eu>022-R5;p%HDxPH`IGC9-}AL%^gcblj~`OlR!?m`51d6PxtoeSv=76;C2 z(+*CGc#x|nBalTvql0vwa?+l&Fze(cI^abI@$1=z4Lz(d=}a5>IkP+4qhgC$7nNb1 zb3cCUH5Nl4QXR6QQ~9f_z5Xf34_C;n$!AEH>*G+hO&P{-*+68Djrhkt#&i^Yp*Rc5 zdskBZ<!kx4J1owMh|p6eXUWr3=J2US6J^KlAZoo#p!|$6_6=9T%Dz6(5mhXTc92B% z&tqU!(-LxZl>^E&%0tHKYvk^FBUJg?4endZg47fPjNPgTD!01BwWd0%=`sN#SiHBc z)4lNBlW&f($^Bu#=@Gc$bTN4}t0%NYh|r_Qa&mm67JQvQ1P8y7z@oM;@X+Qa4NVKe zh-Z!@Y{Fn}VfO@F#&Rv5VtM~Qw=3eb1S6IY&JgtWJaZi4<%B5`ny|9}KB73+_MdXe z*zd$A#S*IQyJ637<GHC>ERKZqNxt{_bh=}&C!F}Ch+czq@%#oS7_hq+HGb}m@6@`1 zn)4dctH=e5WJZ#<EOq#J(23=UEF;ztJ)rf320q~iL2&m6L^8U9yUubs^T|nc>#lkl z#A55ro*hbpMsJ}}M}r_u{Se7HVM3M+N`qH6efhXHH<VrRT-=Li;~14exJFMJzqH9h z@XdZuSAk^WIV=2f$r?;|-4Soq_*bv!t_ZKD_eGrsRV-DP0*Qk*Ftzm)J^IQHAM943 zKVwW`o8BbunCCijJ~Iv^pHoM-hCE_Q;z80;0yjn}klR)Mu;;WiN$Ft>p^=W@5zWRx zH*I0odP8`-XF8eb=LO2zN-$uKDt{v{7Sdw2kS9}D6Ypblz*WbXMDG|zUR5Q*=x@EL zp1nFGY4?RkrE;jg2VmUPLGVd-Ki?ZNL2A0H$htM3k4%<;*rB0x_=)j&^`Radlshk8 z73_k0Z^po{mAAN)Pj*t@lisL1CzqxTX7P$^)$!bDE%Hms9Rf>kk|8@5QMt*}Fnzi{ zRKJT8%PG3xvM?FYBu0?QSajo=JNeKz1wLmS<k$TeD1Iv!2i%g)q@g2_UfKl^BCiAc zvhI>Qxi^UGj*+nYeFYgb?g%M}o(k*s^@DAZkBH}MBhYn`1rNT4d|E}|$J2Upq}B?8 zWRzi8Kb8Z#P6b*cUXa?aF>t!qaFXY@l30&V273oK?tEuW)C)?<k0FKptjK6M8uFI> z*lfX%Ne_gtJ!gT0ZLO#=x}KO12!z0OE313%eNTkfM_A{=+FMlm@N~9DE{<4w9;7*H zVTixxk%a?wap2HTRDo!~?4fpOT5y*3x}*$B{cSL$|4M46VhHoPJ)v2*C!>x|8qt*K zhmY>Kb3^Wpgi9Nr(f9}jy!G4?_8VTIT?P)oGs_L3!bcwE4>j>RLF2$b)*g4P=|g0* zP1t=UI7HKp+?Laa;b8==1N_MHiF#nP>JWAHu>o^+P1vM+l?KkXhTa{@An*N|em}s$ z<mazQjJSi&Y;gwP@z;r^>`%%fAVAkO*NOb-{OXH#$#9{2IN8JARb20-!mCItqSWsa zub!C!sU6mw#mp7_;A81f82_C2xVwkD)GH03Sd;FISwhZkj{)Q76KTg)e=?7K_nb6w z2Nl*Mtbg&YA;jF@AC&rhr%fuh<oSCR=RH*$h4l-6x95hF<YB7`$oJDj;qPXjo>#3C z8HHcNtElPFO3_N^SfsMs>6Wl>qN3VxyfCeX?rhM6g#Mq&QqV><jbCgG_K9GI9WLE} zj>sz=B1^p|<A(SW(s6Aa`I0jezq#Hdn_Sis5A7+K>7@d4x9n-)Cl3raF@wVUUetD_ z6&4rC!OUqoXtzueH5EUSg-x0`q?-;N?{$ILD6yDXyJn)v{uZ)zayYFkn}&PW?j%Y- zv~bl=8%#X9j0~vOM9%>n&M4VNJ~19GmIaL7)IhX{c+%SOL8$j_Ar&tTM`M>Q>|IWt zY-MYYdq{@TlZzIL&tJ{N${0o7PO*Ua{ThlM!}VG0+$YpJdn`_UdXOI3SxoKT`Jj*P zXKH_pLv=Jp8t_om)!hfrM=7Cig$nUm)fLz89EKSauaPft1Z^ra$mla#ut%>4HuM+< ztB#x|76ryQqW^qyy2ujx*%;%u`qjkoiaE%)vAnu>w5eK>3A7!w!>5sBs8fIu3=3rW z;@JP)M=p{fsVuIl-Uz%ic`XTTaYT!WI&_JR5iHc$%ss4O`;ul6I(%(A$(gJT2af8Z zu$=$-ofPJ~kegDI(7o;vITNy!t{&x&inYkM<ws&A+gCKEV=fJjk3*v)Hq^Fp2U%Ea zi+iNBagxUw0@X%nm~Vgy<CVcIu7H*q4aZ!u8r1F2rWI-<aO4tom~yy{+wj!`d;Qb^ zOG87l`Mt|OT4-}tMh0T`_JPVrnz(O~9Q5>2g%^%$=pd2JW!ojesF`zU{+pSisb^Cm zsMd~-)p|#316*Kk;B8Wv^^Q7G7tr5!izLd5@Z_~gH2;$Urq*)UBfy7#IjfIuZoN@q z7RzxV^1yp+9qOlLV`=k9S5zG6gs;ujxonnGsK~_$$#z*z*4GekejbiFnlgOk?EzR4 z<b*C(E_}at2B?<vof@yX#$Pd-ikb2~P|N2We|XRY+&@Vc<C}qBT{aQ<n?3Lf*z#}A zPQbp!>>WWekMBOg4}-sTMT;X#`Hr6c|7f92_KvQY6P{9i{F6V9Y3YW=28%^WgZ)vr zRu${7=W+`Jz44&6I>xRk;%<!g!kjl2c=FOkPQ~38H|`mNZ!fiQQsy?eY}5_fyloin zu$026qlWaQ#v^)+<uhDfp-lI4x9AU*U>u!sl-3`1KqqY#T-aL7$Ew&<w`VEX#cwzN zUNnfl+{@k%Z=~{HtLnHbgEP=|@hU$2N+Xy5F&(AnE#x0QtRvT-hv71QEziqdATlq) zaiRY)x^I*-6iLgX^wO=A7<14tx8FbI!$!K}@i1+$nxP`D))|3?+u2;Bbzfd+uRJ^! z{Tf0@)5s~rcuXw5of}HrbNq=Wdtc~1wI6*tGLg*HjmMv0Om8Q~kRH?r!`Jo2BFS%# zRfk;hk&G_tUa;oh`EH<(hep$K7PDm@%Y*E-cOIRnG9AR9!nux>Wt_)`47gg?z#X0$ zOEN@>Fz;0ic`{oMwxo$5!pEN|h4zQ>9Zq0*gC`p-T!9<c1x}eCCrU={ut>fOd})(} zZPMPbq^gkoFPrkrH$-BoFBtgjB&~67Fy^ENe29}JA!~ghe@9PP^N{B@ic`SioEcd$ z>@F`kCk^x)`;gQpJNYkaY)w}0t#p?c(xm4TS?;wGy2_NTP0|mhr!@nKD*JYQvBRI% z$z+k3lsWKn_!4@*tp}AgiGzemi>ab-e=2o777l$n!W;Yd#I<d{;GE&kPx_&Odi5UA zzOaF;Fqndq`)nlAsrjVH$Oo681o%}sz-Vm~G#MmG)|rijd?$5u4sRAcoe>Yx-&fMX zvqZdYeG<f&htgdmviS<BG+3gfKrY>A;h(9d!FFYNGJ3+@f3(nMaNA_KSRn=7E-P~# z-2>r$>wD6;ZLjFi>(?azsVD5MK2Mgqc7v{)-Jx#nLDJVRO|();AHI6Kz*TKG@y4YZ zFms6~oLuUM;dx6*(6|>Q%G3{g%B>^Lwok}5>ma<usZk5J7P2y82Kx4!N_$?YCkA^D zaj#yRqc!VO*TyLmQOE#%(iQM<6D4Es?4;8!O~cGb7l=>A3VJCx02LSBBITJ&x&9ME z@$jrVaw)!+TWA`F2?KW#wjdL3qxV1MLVMrY2g$IVpNVw-DD<B&h;AG+8HSDSpmLd$ z=m3Z5@Z$OdDt}rZTM|dW*{*N6=YB?bzf=T8n-$2LO%up6iMjahQ6?P~5Kgysk3-La zo}~5BI`U#_IPUXWPG4sagpIj3DACo$)4VbK$hkvLK2pbO?<{i0BLWN0uA!r<v|t*0 zkFb$oea7>x<oSXK-19D!^63UJZ16>~W>07K-NYPJ)x1O+_6|tKs>60EHQW>_gLh~o z@ITc=q1Sl2daEaVTGbnG=}o3{9}fZDgQcP}NjuD+V+UO<{kYsNL$JpUU6`;WSG0eW zEB2_=hWw{bL~~xbVb;h2aGBQ=zuqze*FQIchWeglx3UPs6y3qj>jLL~QWJ+4=|Ycz zwPHHU6*b4}f>J_vZpnIAl-2x3FPtAnF4s@OS5+$5_FNLo6m`)nCy48PMgo+tOu?94 zUi^8-dXXMm(=99)+SjgcqhYsaz%$(ye51(|E^J~3ME6@NIwL&-o7I2N^!6sQ&tnuG zT=$cX-LsRZeBVu*pU*-|(<E~2;9mM+egv{>MIMM8(NA3g-)_1>Qkyo@?lRHX+sv6{ ztD2&FiZXT?{DQ1x<Fi*?=b-J*Y!bO)5C*)~z$u9>#B-}0%^IA5S3k#+S1MC*hUs~J z-4qEh5JzBJ4<o9!riASKJRLu7yvHA`cuOw5ACJL9+xdcMS@5lxfHM|!qhlsYL-<M` zYzguw8M$(>AwCFawz(3!n+@dSnz2~;DT8>7kc5UqUO08ZGV*C&50KyGiU}Tt#9%91 zTSa^0gt>!Z(UK3u>YWB|%{PIUSFe-ibTe#U-v_>HJtFEU1MvAJC5SpE0j=wQP{ocR zQ0Cta+;<J&j6Vf{aq@e@7Vgse2$tsv?~^q@61fG2Y`?Qu5=I2K(dX{t;Jv|4GT*9z z*2INFjd3QC)4fH1UJ8NsQ>Xa7zg&6CbFpx4;%54yrjibx7XkOzf8`n@dSd#WvG8O| zFRpU#I{J3?OmNyzLRTaluKa4$LN!A}FgZ&Oq*CP3%S#U()g0l0%6ckuSrcDh%O;ZR z%cx(k5X{^Bm0ZlW$1LBk^rS@s<jLgHyhU3??hWZ6FaF9G{jlXTUfW{*kx*JSZ4ge{ zU_~crncxXIJDflC2GzT}oIH!3iftvq7<aOU^!edLI|dn}Uw><m+7V7O9(ToI>|H+E zdI)h_u7MA}IYHhY_HO(??C;F+1ksWg#DE1S58bc9zOw|ukit7e%BPwOSv&<cp8Z8^ zmbgHATRZs}*FuEt6t;in#O>s{=^RWf`o;I$_K3Wf3&yk;gGG`3pKz<$o`hZfBj}ch z$&|9VI$O?<B#Y`UaS3bZz~Ws6w0`z!KDs^wl%iUy4V24h+))h(Tw#q%<4Q=y`5F?^ zGzlf1mXf`#XQ+z)WIWzZX@RIWb~krKwR6REd$T&!p0~#jXV;NI`zlG&!WlU8dMy#@ z?V$#1{BcCc61w+DKa{^S4D-g{tk%-i1i5~mc=n<#T=-E+79LW^;05|n6Gy3QqzOv* z+se=RppJbTJaJCRR!74h?`Yz<KvZ&h$~!Mohh%wA%$}$YFSh+8!;WdAyPP!~3k{+< zjmEfW`*kwjd<L3(2Gi*CEC;DUHeLBsAA5fdz_?d!^tut-w>;tqed{<CcYdoRFZI({ zoM}yZ_~;G}ZuwvZ>4RS`Zs0yP#iH-rg=C|r0Wk}YMyg&$_pb=xma_4m=0-!fedsDV zQj~!wR;6)LEqgfOH56XkO{QOo^LRPPe`$u5pOxUFqZY*E^gzW867c=zSi1HV%g1o# zDx0I8Lz;WdKwZ9#NDetnujP)x6SrH*u#j<Neb?#O#q|bZD^}=gV}I01QNw<78p*|T z<`|`rOkY_}N9&>{+E{OZV|4G438lJt@KhmvQ|!-jkzA*<TEEi;4a1<v%x3y#2Ah98 zB!{_u^|55PKjz(dNP|<Ck<gpnD8C~OGaXO!T4pv_wpRnH_m`5AQX|M&G#K*xmQZDp zHy^8)2^0JlaUbtlfWr$p-0Q{SsPFc`h4&Ot=gJcDy-N;n?#5!u4(!RP&K-psJLO@c zQ~((<oj_*)dt~@tDGV7tMnrC;!)1%E|FmsvnFX}G(7+XU&(Q5l9MNo1KfKerlWhAY z7R9w?qDHW-=tI?1G=5)0{8w)#!t)(_NC&2ZKA06eqVnlZ^h$jS_>7L@4?l5%9nW6U zmumND*X74a#giyJre({oiW~=XX0M{D%RW)#QWc!-W{cw-PLP@1reclaL()elh4dJE zoA^l$A?rMYux-60?EN$ZQuj#V-2-FkzN93`Klq&&-V22Qf7JNMa&*j`MpUGv>Gi`b zM)F1!U%&2xv+Y&j%Hc#}Vs8d+SM)&7r;0A=OZjm$1IpLPbFN?q6LVGY&}%WZR<VVy zvPvMztD}?NTf*o^y|IqPhp6-O#$&cJ*mQC!iF<dBPgs_Lr<PiBRVM5{U;99YPMk!H zlbpe^=`|@=xlaq)he1IP8JN@O9F3n{%$rA~L(#5wK4Hihv3E%ZSRTB>H&1f`=iy!O z$Ly2zz!(Cip33-R{UI8sY>H7oEpf176q&suo4XE~ELWcnw_!^dHh7hjYuZ!D&Ikh- zAFB<=%N|jQakjAdNnglKKShW5IPl+C{L<L_clblbD)iNtR9IAhksshY0TOo9)2wOb zbd{<HsP+Fsjg`*Q#Ec1WV_X}}_T5OwzV`r3lZLHtw$t11G+^Z|O{jYKoxW7{h0>R0 z^yI-O)OCv{&PuXEJNKg`_1F&5RyG&iCXeNl+<ozhwj><z%pu2T7gnyDk^zIqJ>}O; z4deG4Wx#<gH~I9FYP3`<9UpsJi7Q5jpxfqJT2e5WENz*C`v<O|o8>Ku&O#?TmhB<U zwGZSC-8^w88&9s%H0HW_k3>oHesKQeYVMQeA%2QVI&@L~$<LZ>1G*bt6P;(>aB|3H zzUXr@9DL(MS9$0|u{+CmqVa+%n~%gDax%C|J&z1|?T0T`y{5O)S^T=sijFGf>3BCy zhW<(^5<Ow@sTH1WbNH4v6(uUZ6YJi`xEZ?xSl-)5M7q?P=t>yDbpvU@i!vyk@PJpD znFMPOPNB7}_AqVrN7~)-I}Mu3q1|=%J{sdrMyq(?(&PPcTkQ?e+pSIF?i<<nXfU95 zp+mVll*LUyCoO)X9F2;%j*-DRgLt*6A=pw>OPWHA$c=VCXi<DeTs9_B-@&Iv_KhhJ z!Fkc1>0_WV`y;h*ETpEv{@_t^o+`u~rkaPnK(0m}&V8Ow{Yo5>ULT0(J?u$dp*yNe zXyel<rjA?Vl*ksCi~TFs(hIj6xzFFyuuT6k|AC)~hc3v%N?9Y3>OB^N{oDi6cwi8D zUUpt&!M+umE9=ql;yKtDGMBzyG@A+;WHf-~ZD8*u;YX)YgR!$w=Jg?3;p0w)+<BGd zkKWVUiR7?En!3{&J>uTd{gmaS5wOOWb4JCS_r(3lT}n$w-~+o?^u^<+RLCHGrP0_& z>IvEZlBZ*3`=jAlGaP>HI%yiEfhYS6#zBYgl6LP1uD&!C+ZGKW6LUB7MeS*LQN0Iw z-rXKf4YR;YC*paP$);dp>4<iH_wb<!;V@{}bAFk|S?cgG8Jy-_<X!~2QtN_Xh}yE3 zn%-GQD?27YS<6KlqlGkUNCG6*edjU@Q)p>WI2?a?g?RSYcH9s&nzS3tfW(2f$ewpM z>9|%~DBY<5Ge7U6Y<V**`q>XYH<uFKnNz`iWfi&b#+dETUQDRj5V+aoh!y;H!e^+n zn2oNe_ezJ>7ivJdi9OC*Wk{#qHiqE=aS)!mn%c8<%H72cL?mI4cf(k$z^4%?QrJaw z<wnv<WqaIRR772C+4nw`o;cle6g(T|PJ}jNX1Ie-{X6pBr<Mro)M<G{<}H59);x^B z-VKTHQ>B&fY8pbTRQuE66Ncc8EGukLHo<3Wm-FVwMfm*82fnM*6<V_>41cgVRZ)W* z$oIyn)Gu5XukITTU0jd|%RLzjEO*`~vUzQ!+@PH+>g@tUkLkeqEkM@0g}`LZOGNm) zjnis~nwuI8YYautx2_=m($3jV(?X|dt`M<a7amB<@xt<N9_6I<W&zE75rD#RlyHnB z9RCQ%GeV9F*)8O?kkLXG3z;iqtB{*QCJOl_<dl#{LcR!jA>@dV3&MV0*xw5KVPW4Z z>|=#}sj&YP_J_iLQrPba`!QkvCS;JX?-KSW+-Wfvv`vTjRHfq5TgDK+Z!nZM?;<bR zJ5AkfLpUC^oe2F){L%&F^V#=I4_ER=)(NiuRDrHNmypEwkGPL~7{rD#Km0Tc^8A+4 zD}D3n+V&VY_vHZ1pFCMS=bjIw@7zrLR{x@F>#U&9-o13Gz7FpA<q4;EHPch+w<)ih z0tYgjNDu8Z{LL{ja51Qq^f)3ZPW6l;rdet@zs4B{udN`L!)$PYnmXo{zb8eJ-Lcyy zD-`w#p5IbI$;gVt-wP5=X5S4Kbbl?nI;ruWcPrsLR7mMF7E6?pR#P7ozAqTf)Q7%> z4YcTuAqwjewsY;;V0gEyh_AcSOohMeF>f}c{ai#ZrLCg|^J9PuY~t?M?54u=ddP*6 z3a?$%#cMX+zqyK}yWF5xUr)i>=ePLHK7ROWXm@N3lc2+RZ?t&P2Zwx-z#6|PD0^fb zUo}(>*S2`!cEeUa>6|mF=(N+c_YcW=mjFy}+(8pZRg<PUY>m9(H(GIfFwP%7l)D}~ z2R|0?p&y6rqnV*GsPN(lcc5Gz*Q(0mW<3KohoK8~hNjp)=M;6EoJzi0Bx2dS5`L!E zSN`FnNL;@52>FV;sg}k-yrO0f`mcN;!ul;e;8;Kp7Vjm`)aGE3@hmQMca3=1?OB-m z@+y(jx<IFU$YEno0<xnhIeV*~`(he_3)#21Pg?rb#sz+ORBbr2WFfq~>p<w?Fa^(N zjv~&dUK5KzRaA<$rf)+$AjsGW);{XP4`*}H@vGmFH|+pBR<)Dr^bTU&g@YcYFNyT3 zheSQx0knT~gMF$GN!4jb$oK3Di-$<S0xMg9QD4c#nO&e#!UCGIx<Kdmk&2P#Y&}|E zD6@D%7X35=$+v27Kv9#wxSRvS3v69jb0tmH=?Y<+T=Cv@6Wn5K3&*?LQQ1SP*tgsh zV6`eeAyOiD+>%)?E*rYFfz9nMoCsF-{dkE+MH<&T5iT^%pkh4@+;-0sGH16sz8KO> zBlF~;@|F$!FPr7L-)PaV4)SiK9ZVS@4>w&}=&qY=t-at_p-sAe2N}HWJGFGMgQ6x+ zSYV{V;%VkOo`0MGEMO_s9X^u^>k-;(*^UR9xeGYcYI(S@YB9ISYdo7flLvn%E%In@ z1T39<gbLgF`FI2v?9?DNIY+3lexc5roD8pq_aYeq)>POY+4_l)9W09r#w+l#vpDF} zs>h#eGsf@Vy1)b1Dr(EF^N=l`AX}k|1I+r-DUWO*K+_a!l<nwJ-DpVKmrk#2T|mF) zWx%d1Q_-7KH~217`-`08GQjv@3-56@oo*0CLsm@|-R<du*J^h=l<Ml^m!r|>sB(aO zUU8Mb{n4DiCFcssH+6A(pbJc$q`-f=pobMKKK<IaG1%LL=VN#4i`Qp5qk<A!ry$V6 zI)(Pa`X^1Wh5GH5c)#BQvFtS;Xz$h+j~^hMzk@vtTWEojv%7NdH%$ZGE@MdF;ZJCP zg+x%kphebA^CNT0eaYp8(;&|L34LD4)|K0{_oCO{VznG|oHx_~5=z=c3l#gJ=XD=w za<=Ar6zh=VUlV|v?ngq#JHy!q6F&c?KKNQVz(Er;3_M)H4gZkC%WFG9O``#LO=u)9 zrHA8-?~<Uc_LP2)%^{1s_`{_bM<lrqiPws*|JbPB8&7h#+@_h1f&bXtGqS+z2DXs; z`7;*~u!&w@X$obxj4`~m8wS-KB{$c(qD%P<>_6cSsV=dldGE%f+caq?Jg7>i=S-#} z?!`l?g$*6?%o}6sRAJXdRlZ}(J9^sOA8M}6puP0{F@dcWc`x<Qam%@W7@}N3#?{)u z|FT(Sp@&DhuO|0Kvvtes218(@KkfFw28727ZAM?!g`T===s`z2xL^<uGV|Bae9U#! z*dGf?*%L|d_?c8#kI;VOsNoRbahx1EDi5oo=Tb>2Zzy1ETo!EPXgoI?7EC-sh3#zN zd_b3d@87FhMuqhY^*#3~V6x={(Xg_n!uCAakOH$NjG}H+6nMuXD;Vk(N+j91)qcGO z%$u)6%d%YY%=lOsFk>0rYSWLJFAam1IVWlTDqHFxmjLT3YPm}0FSFi8z>5)8q~Y`p z-aD_9-rW-g>snj*Es?#j-!FH#!ThB%-44sIE~BrQza$lA;FZH$#FBYe`Rxk|C_mU5 zmNS1b-0TR-9}>w^<}WAa>4V2gC){ev^I?4#6NhDX_`H_^3bn9Kp}nyFtf%3iFtvt? z`YaHC;8?u9ZCNZH8sVZ|%m%(M+dm!MmAf3pfwO`HgbsT`l~1so@G>1_414AumAvNj zkIaB3<}dZTL$TM5CL;IITYSnp1YJ~H$fWW%(aGWC@rbbkD7jd39x)ztVZV4VXUCrO zb%X=`qscYqFNWV|v+oQispioNuIT<g+H<%C++qH*A#f0sM=9bJ<}ceubj85_$G8v7 zU$&%7#Exwm<Qel9q0O_Z!=!}lrVE(A2yF^$gK=>CEt1snncJqQ$({ehmmY^yp_3yn zj3f82o4|%Ye9368B*}lcb3~*>JNe@MA77x8FSd*?3XO`SlP{<K;|mD*LjLlFF@pT% z2xHLy*$9uFF+d*AF}@Ttz8ui+pel?b#*8DvV;Oh;uTIvV<9x=K7{(W&y|A9Mk6B&@ z#+^ZoJEf}@^Gg_0)-$Fs)}SV1jX7hDx04oq%=nVc_#$kN@Ys*XBhZqurk1g0)#PLx zJfas_#+V|s5w@pq{Y0G0_)^LEGIth-8vl<k*vS`1#uvsE{L2)pEuPr@4{I1-a4O@= zHRdm)&!&^V9C4b`U;LLZ9eEkpyzoEnFc!f0^Sd2Nn7<f)GUxs>g|Psv{;-De1ttIR zr9NyoUCsC+%lHygtS{Qg_#)5vBGke<h4#Wa11H$x<v)CpzvhEa8DB0kzRYxBvC|n} z`Z2yRrr=+uFxFrvYkD)*Fuu@Bj4w&dUlu9$1vkc#TE-Fe9CJuxe3{Jn(q1_PD*kY% zOR*09%a=(O4!D~!#g8#1c)T;NWUSf3d}rK;9PTe)!Y4G+XN)h8|KkgJ$M}-N{N?-I z@pKX6$U^29LYvwcM{xMVod-r1P{){(!<Zs0pA@i(bn@jW<ICE2<6#8j$X><~#uxa@ zm&n#`5X!i7gK;N6XEFiCm%WTH6P|g)SjHD`#+QCu-;qkjmpaB5U44I;$oTSr@n!e9 ze&ECSGMe!v&q5F48AqNojtFgp$1*P9U%oIdU?)coFpdb171qi6bL`~HCdL<`y|5m} z0{qJz#uW0GDeFfK$4=H9WvpR*A%FQIY>)6*#u}De@;}zxai4;JnIg0iwukWr1$;pV z#+P5OjZw5-1A`e~jxxSjEe*q(KTKh)K@G;54U9F6FL>(@U$#f~0yV~wdd88-d8MT3 z4_|`cM&L)ro%4)473p?x@(*7aQ;3)`WhG+@V*w-`*&^=ASfjt$5eG89JY#%0IZq!u z`LdnyWp3Za)b0;ogj!gq&|X;Q;-}&GeM$`-$@ub(OT=l6FD?J^1*;fezB9gbJK=|q z8B?4X7cNF|==O&-KTBS7TmSIo^ziXe!Z>2YIC9QA1PJ3xCgaP^-J#Iq4|k@<c#s8u z_%iVOY&`jgDU3B(#aMHd`AhNreMI38Up55}!sGvsFEITNUtU!mrhhpiv|&tvzuaL= z0RzUAMT{xJ@?2Y4Ncc4d26&F7b(s#tKWHvos98*#-1d=q9no;lrJnC*)El(=`-0V! z{o)N=29T~ZxnsAk^Fv$x!P!XyZv2p;XX68)LirQn_9u%+{>+4^2`?PgBXz5uE!a%Y zXoj&lg7q|e+y_zqfH|OHw4dHjKThQpW<d8zTWHDLWDswkL~W$k^IN~L?{D2B=*m8n z&sv!ZvWs7FXQ(n&-)e)o158*9bx)e4=7LAGG~hwTFxtL532kOfAp=sb@^Rn2A?T?h zY!dlU<s7zVGK|I0)?ZGKzc+*kn-MG~(;`le%@a<2`hZl<V{0&WWrA_f4I=KlJGb+A zB4pmppqcu{T>ZraHqXD9<xGDsDh}F9{9|Ka&yOlDVUq{C7Ct0?d3VV22h*`?Pa|=Z zOegPuPQ&u-267@in{06(gYV*Rkjkl-NREjXl06)`x!nm8%lqMjfPv&ukUMB-chF_u zyv5a%ro*vGYDh!bUZyN>aGI`wC(m=7iQ0IOVrwAhe~A`*>IA^p9}DRL;~wzg=SWal z*n?<~cut0qz~A$li<Y(!8NHd{w-4#F-7@g9{|IRESVO9ZFXcC^jspYVNkrY^G94W> z6T+uWCp-IIrnPc2q1Tx_GB@BD-)<ELvg2*BOrw?<eo}(w6VCW~!FlrRktFQ%|4cWW z*;HMr9{?AYex@<^H&;ih1OREQ5M6tff#JW7@+pI4$k5~II3j9@c=%EoQdpLblXZ2( ziKTNz=Rap)SIcAk%jETZgkK!GbX!XbytZ-G8L6nNX+{PQS<HREpMqmY3?ts<NBLcb zak$QA4Oy{n0o{)?VSTEY%1&Z=pe6f4=A~#l>5>gjEEou>)#<d=dkqVOI};iWN~y;Q z4hnA=!d87N+OLMd>4#bXamlo9c06oY?MqU|deBXBsi1PvkW5Q|z#luEh`t&Aq<ygr zm0yvH(bsj!P_6TPenL7v`>~VHU-^QsnU#o8Gl7&*#tz>zq6MoW;M>U4G|uyjNZvdW z&d8pihNl{cq}C*8aN9#W#@{B}FHDB@7gtkBmo!W)>BIVpV|?EkDd4VcMz>{t;*E}G z!2ieBna9=8{&Byo$x_y|NR|{?Dp@;oT}0OGAt^!$h04-imhAhIeTl45S(4P5>&uN> zc9LDF>>;}>@qFgK&v~Bn^SXQb>;3w^t}}DZd}lsq-lubB%($;KwBG^w>E1}nKirh{ zN=}oPg+)?YhgPg~`7Zfq<yambSXX+ua))e<^XLh?;k@H!bk>HJ>sfr@aduQ5OC2Yj zXKSxi=Lc>(Q&)bSRXg~OU3cw8XEQ@t)fPKg(=W)dwRz(4;Ew#kBSU(2+lU<7lrqoL z&B?b@j(Gj$7qeR2jm8c?Cg!-}ecZPmRc_KvoGb{Z6T5H9HHXYnzxxzRNkbc`Ki#S< zufG{fO*;CjPp%#!zSIsUzsWb`Ir$l)sa-m&asa=hc$uMkc6v8k*ffM5+3i%VS+<v5 zxf@K;BSM5la5{7K^CxeU6lT*w;yHKg(6g^uEI!nM&pm5NZ49=t5f|LK&B@oop!;4n z7r&u+JFHkNpLjqno;_9U_!dg);qkIddZ;*YIFznuZIMGtri<DaL#ai?A^F|b$zrYn z?$he9ShVRJLeZz&i@&W`iS-|Y$ka?FE_7_f-Wm)SGb)ABci)aIr*&VkIB_O<{Jbc| z&zvsC_70^rZI4KI(;`I8cA@lY+g>rb{9xX``a99@O}rSmbuiyO^P3p=*^||q7D^LR zjKu=WrR;9Y8D#n3n4HmQG3$Zv(m9<=mkS(yn9t%+I(f39IGnqXJ$fEO?X6o1Kd(5p za>g|Ju(_3(-JuFaAa7eDZ-3g>B5UO8V&v-Co=GAOd0T|MO^@v?v^k8trBF@Y_QO5E zYJ2>ftEXo8&|k<~Z{)3Gp(pi54nIH+BX8Mh<n1HmZDDjetBQ;@M8?vPPiiH5n<0CV zx3mL!>x8_WwIY(5YBCntOG@^xNA_B7ZO@lz^7hT1Fy2^`vElVyd8#IR%P)K{%1s=` zt&p)(fA*sZ$le5GFEW<KAY(5eV-J0_#_z~oxB;>kc}uI1x9yO(x6aR`w#e8#WbE$r zP#TWx^+fhA9k*YMM&8E%o40%j^0q(n7P-p5Ay*F~SBrm*;%AY!>B!rq`J?$c<ggQR zcz#PuZh^eLgS?%7+>{gY_SwIA%c}kSH*bHtePv%YxrzsS@+jnOYvk?W5%u{j<ggk! zJgzj3ZAIReB5%hh5xa|A{eWEcy8cs+LEctF-d2e-6sE{w7vwPVR-Dr0Epk<OYH~Gg z)M&94d3ynQ8##D{FhLIYLk<_7?9Lw}V_zd<YYgqcHz0fMkiEM+zp}??H)draZ_h6N z%F^>UWlcriuDg+;R`PZ<^7j3~5Vex4-yDv~$XlW0EkoWShlP^EjgiAE!`4Ytk+;2& zx2KM!N&AqiTac@g!va~!TQ}tGuD;u3C5O$C!`tKMvc1ULO~~6f{njwGCRe>LwC6*S zw{wuUh9i3NaOCiO<Z!Q(6753X9!B2ASB)fB<m!Cn>Xm>Ql!3fmfV{19k<s7CVK?OP z@zbH4Y4R4i%I!3{ioE4jfBl=c)t5)|k;vf=$l<s_XVgmGmLPADt3sQrmVf1nikiI5 z=v|^#a`+^27<tR*A#Y3n&0Fe>ygi7#wMmO1%PziB0P^<P-bj3>peY-Oyj>9%$u}Zz ztE||iWGwCIe#4oNu|F!ulIP^QQteec<W()#i;bGR6`7%;t|nJI^Xo#%+Z^Pr!=&?K z4RSaYIb1zHkKIS!<{@tbhabb|^PRajay7V94$If%ZP9HbZmr4TJB_=szmT^D$lJKp zL)cg3>MZ2y?OT;4C2yZ1Z%u~GQYksScvu59@|Kw)Z>u72<3@zAy2#a@$kpw3JJm~( zx7U!jGhb$?A8B&<!PhLIWb6WDteZ)SP_p-ylD*ybip83Yt!%JOj79b~LH3TEctFzT z?bq-_l9H<nkgMymwn*W~+d9bG*~8<d-pJuB<gmHJV&;gvor}C(X1$8-K;Aa|H*dvr zP2O&8dqh@pwKj5f^v{d3lDEFdTja2~q{-ouZF|`y<ZWl<t;d^q)(?4m0D1fVlc%si z-bNvBgB*Q?A96Jpxw@;-V$l<M>xjG!w_Ganki!j-!=7GoLdn=lTUv><+=W8P-ag3Q zy@BOu`V|x0qt1ihv8YQdW}CP^p$nG{jmR)%pNP8U!sF|G6DL?@5o6-bSM@v0HqV$T zS~Z-&pXPU!R@MKg-n|j`5IML}TGPr<zS$_2o4RMP`v%MLokd^%?p8BqnEzYMJU4>Z z_p8Fva>~<B;lX{*CyT9beu->1H-6UGQ=WU(h*pgl!pm1RlKV8RMfP|PaKSzH)-9+- zEU^dIz4qv3K7xw2R-_BfvgB)LM^eZOeQJ7oy{vm((d(lN@0Hzz&d<x0FE#JRUkz_U zgF^D;2cy=r>6fRGal}SBfAR*_D0dp&+Z`w088AnV@Q9@qZ7RxZQd8vzc!rQ$hY@l& ztMd4c=}2mK{I~jgLb1rOA4|^17O9`*EtDs(N|g^q;`{3FI*adJzRE@y!)cFeD`6M- zOiteyL1*`S%0@oP^2c;!)6I4gl@1Vv{t?u1iUnJ}!cbh_5<#BTE!n4?MY3i4NTL?A zr1x=Mg)=fJ=kNDY-?3ffN3Wx4VeJ>vt&x&Eymk!DsX0$QIX_$!bPA)@6E>))hlGg+ z{ljRmszk2Q%~e$B6;5(ouH2@`T|6rdquqh!cqIC(Mt@h;`^E@;j71;G(1;tOzv1Zb z1B<%IpKan2`i}mJK=juh{jK4iAs(WSmC?r=2RF(KHT^xF-&LNk>3h}N&BU|Ezr`%{ z_ls{8u@C*NNFKPBOlIEbZxQ<2^vnV_5Pb|qAD<c;NxjftNAx$r*i+K>T{r7=^9udt z)6w6S=x-165xf|Em(llrA6=*m`g;rg{XBVtutXnUqK}_OtrtP)uQ~dAy?Hl!ioTCV z-?InIk(B-(L4VOlru6YE`q<T~Jg<uW=A*yisi~6E_d)1;Ufx1!f~LRdqhx?SenuZ- zTwAdQ=<jj#*YaIwb_RW~jlQG5@=EmgDf)Z3#Vq+6`Y54~Q>t5vXXvjP`s+5uLTpFh zFQe~U{(djpqrZ>QU)S0%<aG3R1p2$6<~&tL^tTZGT^pAxRYD(Mp^p}-66vFhtEh<n zhD_L?V(5Eg^!;zU7^-nBMH=!bNjd{A2lmjg0oYx`wZQ}bWj^p&iro28l8o`ZE7(E9 zJ;Ck4f1y4U%)pno?U$dtYppUdkEN#D_sctrTdV4VLr{14&{|~*wg6B2*ji-<uJSrn z@~Vz!h3EJ?J8SsRHGgLZuqW!3uKPQe)6}cn@OLgzAD74ByN_qw2FRzue&GG!>l#i4 zSCIc5a{)XeqF8M3DipsGyK!^V?{YQ$-NG3E-=<H^MA+9O!rUQ{S6TO7tUp*F3>~`h zvEyS|$KKf@EPE{P72(h7E=m_;Yfa!6PkdH?d*eyPGb@zI-?Kie*I~@c&<b4PP2klU z*48__evsO)>dS}m`dncr4fh0h)Ud;QUpb-MG@9{b3oDCT)efW0%}=TC?vG@4;B^|- zt-rMj<!4U$iownBtXuE}4eQo_ji|^+e=kpS>{|01&CBtacNOT+?KV8&_g#6+)B<Vw zSKJ?3f1aG3P(_?-6isgS3+1Jk^+Y$nXxjDZmaNzHs&uGZG`TOlgy&ZLEzKD<k(+KF zMt3tRsYfoa%6G)|qw(@Av2VN~5BzpiSUP$N@6i)^FB3a4etZ<~bjLF*=gSk>W^4?P zzh|!Y>Ci|Vxe~>tfYeTgOYKC|m?*B-XkgZef-ovNF-0_5d|16LK8!Z4oF?24W~%$% zj-l(xYI*4reAn?v4E=0*UOs;7n0kPT9mDde<vma5noI2%mV@tl4Rp@#+K9PciK6U@ z*H5TN`>-h|!ztP}P_^Jl4Bt5PinKbhRc6)FXr61EE3HUbAqSrb<9)OInYYt&+0Z1M zf9oH}md#$2x%^J4Y!)}3)$$L;{eJ%Cnqb4*xV~6;Nj;+cWpyy_yVK&=YW3>Pnd)5M zx1#C7aJJ^s2p(PNPTrSpN=dt_@>CYfb5^yN4Bo}c1u@Y)v_he(Z<T7IVuL8Y*Kn`& z@uh{x3TrR3(s1#yG?bFT9W*@2YzBYnzLM4M8Y3I9>D+hhMz%hA{fQ%+IFY+7KEJKT zi~AoJ4QE{zhp!LkK|^O!N{GKWJJ6g>sXdLh;IqWadmFOo5I@>lYlB$4eIE<l96-52 zL1KQh1U9qihqSm{MRxgNBzJz&oY{|ED7SkY$(NL-O5bl!QLV2O%l`t;zcWP@4_+SD zf^7_lq72)wS;t?h*qu$0lxyLTb-8sUMa<|eJ34SyZ)-R`tzjr1+V8_`D4e<$^q1u# zPc{yp6?8AUp?34C&IX>woN}TlqGYZ5heKsHXMHri8ChFyT-Asz@QkL0zbeS*J~n4X zSeIBEq}JV6y8F<mVgz^a=_NUK8z!3k4(E1BUsPUwJw>C>4MbRB6o0sHi>gvubHS%X z@r@&9s`5;h%N4DWMN93a6GeSwHSR?-bGEZof7evHGh@Fnz4cK_3=N|C*Efmc2i7bj z%AfS+X9_PfU$*03Ak{8+RNT`yVY=JC!2BHhksCn2k9AaadVQR=DVRcgCrwuA?yIz{ z>HMDgLKfTOmprWbWd7#R5f-)ASQL3r;DbGJB{gz{uzwWHZRf9NYn~d3EdPOGS$-%# zFdo0fT4E-?Z3yQ*jBHrdk-NnEr@{DrFy6ZcW{8uqQ~07beI>oOCi0W(v3ySPv8+jj zk#s*dLvC=a0XwiQhFs2Glnwlf)eDA)liG8<@HTm<w!r<^8(zh8uM)SZo2v0Vh{@IE zoTd%&xl}AAe9@B)M%R=FzKZ36M{`sijr2Ni*))x8^tOuk`wy$nnN26}vm3=Zt262) zJNHP1RvTFA(rMf+p^bFza4dH_Kx$LARyt}M%e`;bk)K9>kw;j?@V)(;s64KI65r1h zNg>Zh(Vq1sLR?Ey%~g-4k~v?+w!CF3ry4%Q+kF%zvtCIBBS%w_?=!J!S}PG6>O&Tr zUx>E3EyS{lK9qXythgfPibki#(mL}C;`f}n!tCZ4N*<KLI`j#mM3=EL6`y9u`~t~m z*lX2fQ&;xJc8Qof7Wd!$dj{1UzFY)t)RT3OjpU+WvhTk^{!lZKedy`Nx*d%mzpd3| z-QK024Wd)08>)UkPG-9O(mmeleC#2~sj)mi!c0B?<2}~H-;X*E{U{&qF^ytQ-H=9m ztz+FAPM~HzJXlI$CcB>QPZK{hW92KIXEi5>kmK<#(wVHCj4wJb<s6KrCI_<QK%bsc z^_S6P<^5hxI_xQh<U~`D<wrSSO|Eq2Z#=`pZ@0YX{CIBU(nXw0I4A0C7|)OPnkfpK zpAbQXA^bw=Te;exb;4&;2=Cl_f_&vcf=F<7W5X^-@R8&9s?HdUU{9?h@Ez9$s+_IC zl0&Olp59@UG~`8VDSaZIL1sE!8kCLiT+FCS5vgxj?gTrM^sR`^xXc!q_ohmp-;36B zE-{;@U8wwl=VEI6Pb^NaE;qd1pV}>w<(a+O@qW8o)AezkanCbHUZ=YwJ-pEtzn3uP zm+uayO`|a=8~2}n{hnD}yDZ}WYQgJ{Z^%7EuZz!P9C^jCs@yB@tr+Rvm6v;m=N+&4 z0RM8N${U?{N!1GMJ)Q|Tt(-lNaIL~_HLOZQ#t!4tTqa8woh#CmL7v>{q`ideB0lM8 zioE>szt=gd(^BM@xSlzOdd%SzIWj*<c^(Jfu`NaJiTd!j(R}omOu0#Dnw;A%noqiN zUydAqMP8m5&EFJc%NJ&lycDmUcqK(HxSJ$z%ukg=tH)B8YyMfDd8zVT@T3y|tWg>s z3l3U0M&5HKgp$i8uvK`i)!7tzD%N`*oQt`YK1`BlH61IL{1rk6t0b^5MX55bk*Ld7 z|EycDQsq(LRX+Y%p;c$ecMgQo)hdx}<<{Bqmpyo{Ym-RUrPeH&rQkVtg%Rv=?OF0E z@VR>tEMwDSd40)AQG0p-ZL0fN-h$u4{4NQg(2f(>BLCCk**HHct+j})r_;!uv1DeS z%W_U-iA$Y_lGlB2cGd1Q?vFd3YLtJ#wp*MKHaSD6w8A;5`D}Y;|1N@m3NqnNhF7FZ z=iPX)O?f`*<S_Y5&`6##bDwm-#WHo{`pA-1yX8sEV`*-ooaw7RA=i8#L+`xzI)B@? zRX(YTrP0NEo%`+IFSReSQ(KtF@*6dhqzY0Sb&)AvJ8ZvX*P(^l&?1&!Punl`4z^LZ z!k8b8)~QEM>PKzU>T{cBo78K;Pmk2+cRlOzm`SVHrV1{+%T)YE_F@kf7-Y;H7WL&f ze6~yZKTY{d&&Sf5lf*L80(ivN2W*0CmN;2|2(3ICCv|k4PKK-FMWZ2AS^n+_DtF6F ztU8k|_ZSvQHTN|WtM>gR$9#^WR|CJw4rV*lDKY)&X=fAup>QJG>@k>{r&i=q@ea(S zp9}ThZ^b*dyQnUH;7+e=)!?DMWcK>!C^Fozo6YO7o%yw%M)J>hs-7d!BQ=S6#{wuO zB1QgSjO*y#3C@*^Q{@5Z`}OUCS*70frQHt;M2MRo-+ZOM<T0Z_*p0{cxYH~o^}Yge zXP6%^^{6Aw{#hUn_4LCt&a>s^V<V~OVrwyFQ?~3qE|SiMT8rVwv*l-~kBYDsTy<U+ zK9RIwzO``uo+?@6nmq5^Oy}#LQl)m_sPvi6fnQT4JFrz;nDg~zholu%V|nj7q0UZv z?fIn_%jBB2ZFxG5VMld}Y?_xO?*ecCD@Aqz?*Sh|y?$YmyartRREpgEX_CAhT#%6> zr@u&&cYrg%@!%}QUrwY*eh-tRQ1HQPDbh!HiVQx4diT5}3Fj<*NlTHAW6b-v_`L;X zO3lO5B;|QJ(>A6^wVx(Q8+S$1`i<FAyGbNPc8Dggp!-s%-dCifpHt<o*q@s>`)9GN zv9j6e5L#U^f!+I_Dm$Uxb)SFMQ?Mhr9{3B^m9Z;Da>aV#M^ql(v<CCp`#Mz~fiZJ@ z{j-+gyz7E<?Poy*JNY_F-k%yuPxT_%-4XA_4d+DBc=lkL_%cs~dhHQ4?T1rrKQr<! zw?aJe;B;?S19G)oBIdbE<XH2rD8=tT=eT*0Lvp4lP03P8{ipB_2kweXVO`jq{bTvA zfD`h~54eYWr)HVyP~TUNW2oqUuCvkLMEPjzSi0P0k@NNPNmB0K7V1uBvE0XLzqD>$ zYjt~^JN@*xsZIU*QSTG=d5z8&MRvNH)o~ck=iafUEy)Ae*4~})oJ1QcoSMiso@&E) z;Qw)R&6bJFaVk9DV2OBlE0ApQ90h}b-6Cpf5OqBCOn#W|Dqc#Rsp=A29vHt=T<q18 zqGuWN9eOWBVWArx`jyQ_?sz3UT*gw&zLSzubqlG`xKJ#R{CM%|I+D%m0MA1^9B zCmZ=jQoD85!Z9XWj>fUtDcV{bFHV)vFTSU6rnB#uR4KbgERS%Ea30#U9<@8&QgW<0 zfZsr0t|q5Q_Z}xnufg-sFR%P0sQ_F(B}M9VKS}xo{(;|M54xKqJqHIKPLZnI`j;1j zn}Qn;yC=1uwS%qk4dz;2rQuGRdP?yf>GhW#OdcA{%VIzGyVBW`9jt<TFfWUzp1UWV zkKVz?jtk~m_W6Tt+Q!f(gM*R@=4K1t{2yGoHTu6KRdQ;+Uorr{1-H}iYYiXla8Dkv zXorX#7fk=f;i$VFx-a`a-yz2I|8E|P`jX(g^3ZoXM1`Scb5w;pvS0iTF&g*vD~qe) zeYR3!vK)5*fNTgZufr8Je6UdrZ?xsGJZi@QIR)Gp?DGdNjg01N>l+E)>6WwAuW(-U z#9fTB887MiM)3w!-^pfcK1n6|(R|;mn{v#RLTSeh3!1?DkfZl$)!W65Y1BSf8e{Q5 z_2VgtZ}={Sf1;;cn3O3dKb}lmw}r}sE=AJc^XyntzeRFfNF-gpUm(>}nTyQKaB_ZW z%p9k;6t;OYDQo>ScCYqZx!2ZOyz0q8-1hk`mF3-dwy48&9`k*k)c@HoW_CT8=kJ*< zJ?m+~4G#C=BX=jM7R;N<o3*JR3Z3?`BPPK-W=x6PcWnae5j}~oE+~<6vQIO=-II93 zexK#P2A*bl0SCltt0{EX+D!cTm?~UuPo~SwtBFfvdWy!rVYI=zwy=CJiN+tp==W@6 zVPxe`pI4lfIxe{-&W8k1PNOtwUEY4N9?uR<JA7EmPsMNX+K#7cArB-Qi@PE*V4=Kn z7_R+pJy0z$dn$D-i00?AX5l;KB)!A$-3)8bkt}l(WL1+`enNdprCd{$;<}}c=9+3P zuBrNhmCuWggL`Z0r@_8pvp$Z}l9SouuquEjyE;nF;Im*p&{6sYUJXulca#R5$`&zT z!g+c%Jw;lKyj8db7|WDSf~O;g_o0q;(F)W*;JqMoL9v_>Ka`HXszTl77t4ph*<g>1 zBH1Nw6peKHB2I(*fZKvIFwbwtQ{-EioAUmZ0S?9W*eSQClB4-uR;%WC?E9yZ3D^X@ z-s6*G|DhvKAJLkR1=j)J1Yg7)_)&bGhB;gU-#n5c8GsuF+?G9$PN(ZLmx^nXZp&l9 z`@wjR<2CVqw-eWy3U|YLm1|L#oE*uZH=c=MFpb%OD}j51GqKFI*v1veH0Awq3)lm^ z`}cZzP3vfCQ@1>ur{Tt6<$ChfkrX)t%T)L|I2`QpV1=|ODUvVf-Aa7Y@M!Q&Ec0P% zij<5wD_j5`1UCNkQk~R$1odfNnVW$(gMGo+US0>E2e!uhyR!UNU_Y?vMb71uobjFV z)|A(poOAa(^R-~5Utz~nq&irp(#JF4zTl31K4%$JW3*?s9S<J#IqO$dMn}QQadksE zmT*0+T%V_bFN5!O{i$}Z|C3!v9!0|j|5QIT`N^JvF`g`OJe<Qa6?Vh5feDU{!k5W% z?V7Rlq@bc|(u-udKG@?{MV0^Hb+X>`D4O=XDjPdwo&4ij6g>rZ+BHnd-W0@LuN)K& z;)hAg!Pl=I6!Y+ZR%bl-*?87H(YLXkR1=&9R(dfI+j0c!!m)&VFQrIraeOM<=#L)t zM_svAS&8}F#oRtEuO>Ify~W(UN?6?$)#O^>WnhfwHE<raz%>%CG58d4T^xrB|3vR{ zz}LWMQc~nVu-C3*&b3v}9L=Xhvt!O`XJ>A?wlyio-W9x;t;c#Xo+^QVV!cm|^rVNb z-$h;f(LByrPudS|3Rd>B5%%p|92?4hX5a_d&qg1+%8AP|*w)A?H0D!RIR_jMR<>&g z_Oq?#9J~#FgmoEAKQ5(Nt&$oJK^{y!E>&&3O0oef%gn*HD4!cE>zaw>ZvkJfcTToC zXD^<<j-Zp(&dKR#?M0n8U@SiZ%Z$@3zYq3d6)b;w(tRmBB#E8Noyu45xi95`&ww$W z4@m#_^J;}<Fh1Xwvphe_FSl9KoSZIH2yPCxz0rk~^E4OB*L#p8DeR2C+`x5RP}Y6v z=Cvet>hx5u%SvCW;5-e(K2i8G&eO%<?GN9}Jv;Uzs#uTIuindF!1F8A`)B#eakvo6 zSB}HU*#A}qNs_h230bn(EiY*hLoX|wkpKR^OSZ9$q3y;e<ix7G<vXa~w>cr3x7sbM zz)BXa!+IwmmlRLDk89?yPm<(z%z#<+`Yt?<d+`qS2eZsaUesgFYnCwZIm<fE$gKAd z)?|@6PkU5_+^5y$Z^Ih#Fujd}@cU`q*Xq^}JTA{|#$?EDPWY{@S3G;1R8Cr%Ii2rc zut)VPxSI6xVl3Zv!e2DQJp~^Hg>mbxr-enxS}}Vkp5+#ORm|K_nLeLn|HCDH*NUOl zB#O*8=W{nMkOR7T(OXY_J~*)<H!<!-)4%Of?aK3Jt~uc}A^ed#ed-u)Eb{TqAqU2t z19;O@on)tj*{uHf&U{|0jqKUu23)sZzG?<bFwx_0clGA&^V8%!Q+@9Hd?fF<qEuYN zJ=Zp#8Nh3<?Lq_WeyAzRmLD43hdy__C%)O?e)@}XPvZfu^sAK@)2$EN7bwPD3!~4$ zPEu}U6K)#WkZ!p>7ZzO|S$r=K>NZ=SnrxiHBhO70*S0JZo6m)F|1G1K<<Up#xdtvg zahL^feqj>pxc(sSO);E*8+e!fc5xI@y*zmL+4}rqWD{x{*^u9Gd(O&loI-ETO=aV@ zE@NxYg;V5~QKH=0N2*l@E|f6Lg7%-EBy{VM>ko?ljfYdjz`NqZ@=}(WvP~4889)p3 z(xf$}`n2WwNc?uM3-{~zL$xi+mKKlh!*_MM#~#|{i>ZrE`RoC%d{j#>p<AD~FOYd$ z3*%R2ILSBiyhWFsaDFQCk*ZN*L+WbWi#IOVrM^FP484%^nT^^(jB^g4H`GZ=IFKzm zjK_DCTWu7Xj~kF~eO}cJamhrF(suQxM``|SPt^lb!{9KQyl#(ren2%D#}Y|fPqTs3 z*D{NpK9mx5l^xqqnLj#-M+m#EWj@s;?w@b|KlSZf7f7bvytv;;eKM*)SS)+w#ec1N zEj|o*F7z@OFYfh2JYQ%|^Bz^<^0c~CFT4@?>uqE^+&fUr<MMQHT!!T1<oQ4KT+eu6 zw6~mmA#*y7k_?1>ukUQ+aj*a3t|0>`p>k#V``{eG@%+M(38TsW)j)a7np$+_<2*6= zWe@&jb|-2(^Rm2mQET3J;xqNh{!tX2--502&Jcg4B#3D*eE6_e4_Us?P)f2*Vb2!S z7C*0siM-V__z;&~{MYhV;*r%Iw(Q$VmHy}@@_FxAK4vVghw_?8x4UGs<)(Y3^EGT4 z{s+X%g$&@i6)W?T$L6q~F+Wu2hG(-6(*yXx+^@_6&mBqYJ_!G7Dv>*fR_77*hVbpK z&s3@Xqxj>(7GlNwB+>D<89!F16OSu;DDuV(<-;1Mi0Hqo(XFEfyyC>B+`CIJdb9i$ zYioN)G;PtIymF2+_bq08iBAA^ec42I#sAD6FX=(mZtJre11$MvtDowXKH1_$NB~`m zEs<ivtCMTpAvEc267#=hMh)t9qReyEc-S!m+BCi?UAAe@Ph2}LR%|z;UJH6~vpjt< z+uf2T&hErBXIz%-7Plt9wYB)f3iDa^(;if7WCr_%`!5`L?nCBtYO_Ii!&vm{8MGsP zrP{}PiFC_5mU{o(BQL9AE1D-oQsu)2>}BWgVo$mk_c&z0&VY}D+oS#wyaSvEuJ8O^ ztOR%M?#Slgyf(vm{U^t1>VsSy83SiwjFvP1;C0A>>BxaxdZgZ@!@6~ak7LZ<tVe2` z*Z;|tx;YB0m$yS!Xt{%iG0%VMHMyfO?Crr1&eF$sbN`!_+&GIo*&-gP)|A1R4=u!) z7V;xiS-d-9saX5PfEF)z<7M&2u%-Cki2;?aaN}k1siPKDe^sd%e7ylLi&e)g=<VuK z+<UwMFN@D(|BS_c@WMV(*jI<O^?@o!aRv4M7*iH+8hAt1Jgfq5|HYHa;s%3ns9Z3{ z24l)%;*P9lZx32EOP|W(op|rqgyY8%$Be=o!1fx})?2$72!{MQlkP<dchzBS{iL0N z7>c@Hh8M1p48&mYFXUCG4$lY)rV9_&ipo!#vS~UT3_gdt9_l{eV|i=E;DV-XEck?m zb?b3`9mTVr9y}WRP~jK<!HaS15%zOKjQKBagnH}jApW9w9lMdyQndVopK9toQLhj7 zInh#-#kH6t`-c7Y5c~O0E<ybP>XAJiS#xjz_N|sD{=xcP9YtlFI}32`C|vPBcxw+w zu>;#XYK}hFvd<r!icC0*bzQ`I6+ZVLT++>v9Yg&p#weVw!%F=!>LyR{zdZX%+&w;= zElnOvs=IIS-NU|Wg}Z_Kg1;2*5}z?<0>-p~_s=RHC;TqX6E@(3;BfGi77s+Ct2>$9 zO&31k{Ti<GWEaEoX-s^$c#ZoUeF1xdmnDzo?eD%3Ch2`u3bz5zI@VX!)@lkLSw4<o z`OFFI0Uir>ZSjDmxVrO3cheb`&#*3T2iBdx?mRt$oLEtd?fAX=RB9dU#4<Ge0rltL zLew9EYujyS4>V(Lp#BtWhVg%E#y`OrHTX5^`@lvR{}>#AF*e|we_2#&v0aomoyv2k zISEhj?fO&sZtwx{CGcW!9{3#CDa1*vu-h(9fPV!$iDYm(cvO&+_zD(a|0zylE5;jP znUBHm!9P%U1zUryQSUz0NqlL(U08t!gB?+?3qIM$Nqif<UEHlXmB)eigI|Ml!8Lrg zi(GKczD{Bk_$=5Oee^>gPot0jKOTiK7c^u3i(8`C@6ca6^jG1xI;^d~z%igOVT{7c zvGFG_L*ILqi(@~|&tpq9{1vQQ$2|E792<c+Hp=22IJOIL+#bMjTNW?Cv2EipiEmsJ z&i-U;O}+f+c#$*ph!k*V8m|Pt@gMvb>NSFoNPRJ;EFL%gnCSYXkcH15%(Wb;!++L| zu#G3Nja4qqW4c^Jr(Pet0As#kKj^Y4>WfkTiF)0({w!rk6V@L0&DV0rKe(xbKO5%W zgt?(!77xI2G8M<bk_+=hS*&CN<}5~P^5MTY59iKVo9%3r=~OC<hht2N<{Z@WbDV3s z9QpE)h$->pJGY%>3P*vrYgnl(+!ggXVEI3IuBJW+`|2EyH*4&xviM`eDg1DSIQ9f% z%HlQ=hneN;5p*o=yeNweF~%BWGBD;(ZlbA=!aj^I7bo<v552*w|AXC7e}{TojOkMb z*TZ)0!!b~VIqR}=oFKRVsrLeR2S2?qkCny9Wa@&RF2lNX*+Hk?8r&aaR$)vV@F4Ko zKRB>eYl?Dr=7YkUN}~>rr}HNJ+2NNfnA?q=@&uRr>}Ak+exMSmsx5B7BaZauS4WMZ z$?;9ZmHkhcx77-H@NPFY#xa6tBsZiM<IHJYlb>wel)h4NUUl`pgRy+$1vin`*_Zm% zzs7Diie`%vjKv-Q8GNYza`yQ3RI*v*!8~K$vB%Sz35O=5cy6oKoVh!bfqPRqXNWCd zv45d_#1i)qOc~F^>g*Sf3swk9a^XYQe39nhnFF%-7;d(z2|J(i1mA7$!tK`_VV+xz z_>Y4PdHh&&{<zss(SA)MK4y0fp5NGzf6I1b3p@MrR%X{k^-2#JZM5gDCe-1g{BmLT zdMfu_=^>6fday$^+VdAlcKo2bEv-DbP%3KBg}NMcp|y*?$X~ph&^(7O^kmf$@pG#Y zHDBF`ToP+gzh;KiyV65(YP~&8n}laZcJ>fGs<o$E2kq$TQK1f8jOXhd=}iU|6Q%hs z_r<WF@g&t;A#F@`6W<*oXzGl<vgxDhs>Fk_6xKLeSnM=rr~GHogV=W>G^iQ-(0CNp zx!jzuGwguh)QuInd#2-=2#KoY{_Dix0|DH=<`VV9v*$$4JQH4dkue|Mtu__(AH=sG z*XORkmau+zBl+KVGu4&s+KaUdr|{-iPOz#=ZB!?6!?+QBk?(KnFD$P+a{uwo>2MUr ze`~?Z*|evL>qax(F}klczGX_*UYEqlUJl%3xD~B)d?xA`G{Li1{@-hLmzkLCLvuDQ zWSt&fWV+*Zm(wcSh%$;=@GJJ;+2JJ4U8cE+&+8lWg7^hu!=!ntzBgv_@!6dFW>|Cc z^F~Z}KDw{9NQf0DcaPu?-QTc&OO^?*Bb|8qm_}T8jP86MH5*Fp>mOxj?%rp0r7VH_ z67#2cl1R^w#<V5FjhifT6Z0Y`(wPD2td{#gHemB8`qlhAo6&M3J7sD~H%GVN-WzVQ z{_m&o0eg?I-*yM(R*U@j(wP_7)e3HGt<w!L|BNkP_|A$)wOhyTUBR7*>P;iPBu9Q? zr~|*$sk11lYR`M`+$=J(ZK+OkwfNO-5}#DmoSE9-``jhxRF8w-$$gKvqv{C>EGz`~ z9M)moW$KRCU1mx5DHQQ#3>)DV&o%{n(e^#l*s7|}SUtBux@6goohnLUG4sNOZ85Pu zKYe*0PbNm4_2t`|US~~~wc!`zI&jmMdhErC2=4T{iuh?{CT{28|CH@|3zJpzg>AJU zJ|(-c_}+G#xLiDl*Z$F%t<I>%^M6ew-moG|KYoTSU5o!!?KTklXQuF|fhxZA7rtMS zRg(vq4y7su*<z7bHk+{WIXnAu1g&;k$ZpPhEbP~{qanSk|Ie6LZ9DK9sSeasN|4`d z#WmBqm10Bl;X=1QqfWk)XU|}IW_f^}sJ4}D&GjS4TRT{~(<G)paWvI__<)(7@^=dB z=}VcJ&)H31+!uEGBwEpK2zxkPpYND7oYHT*u)kuTFq1K!v?^>dYZT|gPkgkb&+e|Q zpOF*Kw{Jz{KbpN+Z^6T;3;ApcV_$-8d3epv<eSi&6|H;VWQ*^bsvr9>_YtSrg{a}w ze8p+D*RKWsHPo6)X%pL6tvavxsvE8IOJbv)CW%Uzn+fK&v)WdXh&i{$oG<zw67w;) zg_xU&eIm>;p9PrD<LUaO%rh19tQqG*7cjRMnA_W6TRb14GkIeUuhv^oH0Cx0bL(W} zM4vF{x0rMD5vN5i=F<%GIpo)ZQZS!l%qO8*b*hZ{#9}_e#768j^W@%{zr=4-8!-^v zD(jc%Uf)LeYIwuFX?)noHO%$K1$iwv2CScRL7uaFG&lKJh~LrmW_Q6eKNPZPv)=5~ znKnGFl`+rrFJcYBZ@?WU7O}}CH<;C4E8Iidme2WmgVh83gIA;<lYaU);;#O#e1SM7 z*-dD~%Y!?9jTMVV)Z#mE-|j1)Vg-Q@fPW+#QSFVdm}Q7Pp8`Gw9tmEf?oSQpZDt+; z`rJV7PhI0Svxk$wD`${?sXjCBGn=&od;ZX8&3n&gBf?^7*0h20_lk|=k>HIX1Lb!W z{+D&f4C@v^1Kfs+F}?@HO0aX^p(1eH0bxDXnU2)hEBZGyrI}-#sh`na@eSO=sYp2J zXNzAQ+-SZ-k$4W?)X|N84Xq-s&pj`mU7tWP!>WkO;6kv&oIy+)e?UwR51<y2gV;mx z3Gi6s3fytSSn=z@5Q;LYz&mUlD<boT&}z$W{L$lu^0r$|X%y~7bm755`Pj{-<oaPE zPwA8|l{Cy2(cn_&eCaao88)}BjaZMKenPK3>)D7oU{mzECF+^rrKmSRJq+9n^&oQ_ z5pC+p&&$6=0eA!06Z{Cr%qxruKk-ZS1y?lp<ZZy`YuSh)s1H*A5(%~cJ$^o7IqnuV z;wI`9FecQ@MqC7kfb}q554;A;w5Vw#?qm550%Pjf2qV-#U^#A>k0JO3_!f@OI^YW6 zWGqLiE1Uox1HOm($70M<@C>jG=1>81E5f?+u&xr+%}}?;vCY7lnA=)#XYg_GA#6(( zjIWRJv%%)zf{b6n4s%fE+#0W~0zL^I4&IE{?gaM(cfj}s;OF4$*p^0MJ8V}t)@uyz z23~;i<G{-KWraB_=hqXA@2%lH@G{Il6m<e8q~Le1qxZ3EW~K5r@G)@D2BmVx-6Q$5 zJ|!%8aw}#Jo&|mY&THP1b5k>ZDC7bA0d5Bl0(-u_%uJ`Y;2}?}c=4OdtRnaT_;{;C z$)>d(x9%$O`b`t1pjLLg7#!Dfu1I4R{AD5MtL^5Birj+dfUPzgQ_F&1Y<{>cZ?MUj zhCcblR)hVT44{3XhnRixN0tG;KJySuKKPL>NSr~z<6E)61IDv8;M(9W;F&XH>CDBa zSwC*hm1l!3W1nUnxc0xSJLXMb0BtR2Bc6Up7mX$dP_dqk=m4Jn!I>saSRtAXv!vc& z0qzdI8}mkdu5(Bn(H}%Vz?JGA61%`(j~I)>HHXE7QIl!NF=G)7_6OTK_hfGAYeW~l zAga)zC%b)YjaULM&e7wZ_D<r*IuGi4LytRxuYmiF<lNz2rh4S3=JXT%1J_*}J~pTL z`+nTEr3DKKz99~S1HrF@ZV0;uHlitd%Fy?(==E^0at_*}*QapIt8i?z!0|H;b>-No zhT}FA$KGfhdv|awZ3J6@E1~`tW7^@hY2X5I5AZG=lcO|areis)!2^%~5+f{aL@%%n z_!ZXM5?l+*QI7KvytV<>Rf==X1N;))1Itm)iyAnmX5m=109$|!asI}FJ7Qfm!SUc? zoFg+ZJ_O4w#PXFn^aGE;^6M$*0=CN==ki_DAA{Rq8(U#rFY#IvEJxXv0T}-d<GUb# z!ok0=9EAhHEl}T$%;^NqMm-Sod4$(4z<O6=nZ;P9A(r_S%h?T{j&-GCU*&*1f|V?~ z3N`~P`^p5b{f2E(=3oZC5B4#(5jI$UK9;GBIfHr%<`%j=k_NuC6Q=o_q|_ArRyTXL z*t57q4xBTV+$=N2v##-CNk~1K@cx^a+sc}*;hso?-@FhFvPy-?*vq0(u>s|KGs@Z) zB0YHbQ>cwb(XAu(MPghPIz8W={%W#>)!Fg}_Y)sZM*CXvb)y#{Q`%6g{^faG{7G?m zu`3-&8N@TTszhGBsw5sq@UusfB>%ddgcbf*o#NM3u5|UVcw8%r^Un^9ETdG*4-Mx1 zzFuHc+^#X26v$fzu4f~xBiN&t_S`k5fSqx##iK8+V0WcT{LZ<4{K}EfY-IVLEU~B) zU;lHH)UU9Vt(fV}z0J=HtIgM#nb8pL+?tED_-D)@ZZr?LT?@a}*v3A$bm4ElkD<ez zFH02+i`bVV-Kb>?7uH^Gz?XfPM%z-psFy@;!tZo(zG8pcVShSdpDWp`?B^ypHZFmG zgN@P0*<dFedrICac{o_Z-N0wSmC<+Qe3=Z^*W{-w_y%6P0rd<le?MNUyzk6Iy$;T) z^5D_vuMLj*>R{z~-hsL&SUKiPz{+~(<F(N^#`=Sm^Km}v${c=y>tbCi!3V%f{vXne zUurd+Pq|ZtKM0GJ<H1A0YiGsE9+iGF6Jr;?w#I#S0&D>G0QcDaTuuq?#^0Z6%+DTt zE=PjP{neN^b9Erq`098*;~Vx2?BiFRcLFz97*3lKd|B6khgk}%!BzbqW@Q!+A=9nP z<;jsXsPy#^{PuLYY!zFB3>)vl{Sdke)%wX4Wxh*XD(51K!K(e+nCeENtiLFPvJ<y4 z{oF*k5WMnmcitn?ogLLPr+%s3d2+ZrOD}Iu_eKxp`fbJurzQIQB-kE20{p;mJTIx4 zCQc8W&z^ukgBOEuJoM%(Tm2Sw-XBtFxohzuRrxy-H-6KUthaLU^0vgAf_H;OP8B|T zi7QnapDf;hr+_c}C5vLam2AWuZ>sH?E2g$w$p(XOjmQ-&-Pk$n%|yCVa#a{rH+DV* z{sv}zp;*v=BCR=}AohSG!1KW`e13@i$4Aorul4bq<{u&tJfWn%(6hIuGnZUwO0^}@ z(Kgmp<FX4itg=LUajzXsU(tvLF51p6fm6UA7yd8nj`=&K6^$%kB3#g?3*dv``rxU1 zt5fE%WZ|9b!k2+}4o?<!!Pz~I3agGDqRIA&e5LDA@vNPPm<8_HmgFvJ@8l(>(R`T$ z$<+_PledER#4uJobea6)1@6}y%kVwZW%66_+JqOZ-+<Nfr-9>mOK=si(V%hs=;Kzr zhrw@oREtjB9;|QpTfPQ9(I9{aWRGFX?e?)0@FuVf{ys7m|F4`SiP{yVui$c9XGvsI zQ8J!7gSU2hEoaxjXHDSrF0bY1)#r)GMg95QQ}Mzeuspp6HwMoLC{N+uM%?1Z6LDmr zBPDtn@#WyoiyY~OSq$#!ZbY(uANtD#8w36gUVS7}o}O%pd!YBEZ^@bRGH`Wp^xT_b z)awRx{BaA~GUuk44ZaT^cEFyx22`gCql?8zaA&Xq_#?hIFlEp~<nTbzHqnR94}2)h z77Y|0`P1p+nq^`}Z5iK<n@(TBM*qRuG5((>kwx%%dE4hREE+s}+IhJ;xF()UR5W0R z)C!+FJ+9H6whh`LjRAkpuRt9eOl3Qw2J_hk6-c?a;RJAVM|WiLVOF#0B)+4qyGZ)$ zFslWQ=~kI_czc!gjP&Q7Tr0B;U@P#+uvbhSaD~;*?Zba+xE%P9wKKmlF`3yWn(%tf zoH>D$cbahJ`j#Ve1|Y8jkW0!n>I(28WRX(;4p!c~)4>VID8=2TfX{+Y;yqN!v}YKj zLVYs$J?d~hrgc5|9UG6ja=n4qvcVdL-_a!aT@|?At=*$(?uSCQ9!@t4Z27T}$#6Yo z%tDMYfdj(tNbx%-_}vL`2KYI=FY@aRVFJJNgWq|T+z^exCgASknA}|Bck|Pa$)y_a zd-*ArWx?<E!|&jIOzV9?$woX=<9F~rZUnZ1>%s51v&Qe>eY`%r&kNoMzvErtcTM1T z@IL<Or#`cU_l*pT<+b2?c5pp79sdP(t@MxU{oneEZUMZv#_0xwC&Kk6!1Z*;&luy( zhiLo`-pAA7eSP41u?|J-4g78k{0`p7I)Y2#eegS`^*eYU(|Vsn<RGE-J9wYytnohh z9XV+HZoF{?YO3)*_#Gv|?~cRo;C++^@7oOTgWr+0Dqp$|zv~9R4e$F6?}O{1Z~wlp z4XJ0t!obS)XHV1>e+j|y00(4R2aK|?!9CXSo``FzQga*T5B?0s`!cJHYox|_zs7qa zdydyC-Uq*9%6p~acevKVW4!+LKKLEe`W?KFX}u4A$FzP2?_*l;gWoZ&-@*Hs*86b$ z|5I1|4&KMK-Uq*9OR%mm%pcyz6z@~K34X_vYYa;;ypNT`oRw=-_#IQu9mVh9eN5|p z%64h}4%fp>>wUN;`Dgzqeuww{f3`)rhJoKP#qShf+ll2U-Zv1u59?LtKM?z>GT02< z9_)g-d4o%oF&OU!R`x&qj)j61zk~Pvvk#T|!|&)b{O&Yduleqgv<go53QpG+toWVc zddirS7}F3A__29Q>TGJp=fUqDfV+bg?}Oh7t>3}>gx34uce2*+;C-^z``~v>>v!-z zru9Df9Ulz8TLZs?_i?TF!SA@%@8Er0>wWM$uJt>3AJ=*x{Ej!6^E4|Peg~)HI^Oqx z>lTv(xV65G=nAJR3Jl<f;d%vN-SIs?IP**JyDsoMcpsk*ZUp`s^M+N|_#M0t&mlh~ z4#D-@ju|tp-@*Hs;(dzi!S96PcZ=b7@IKL7<9+ZuQvB``{0`nnTJMA3(R=vaI{2L% zSn)nDcpv<ZLg07B@Vhl&#rwkHeRmt!FjMr`4ZU{7F%tnc0{f!xXK_v`p9yTo`PB<` z1JvPnOzU^>KBo0P_y|+{t{aXGxDwNPAN-Cfe&_bDb1|*=!S9&X@8Eq*>wS2SV9NEg z;&;k%uJu0n9n<<9yzig$Lb*<c-!ZM<!TXrj``~v>>v!-zru9Df9aH?y5!(gtV_NT1 z=B)VLYj_--i)p<Ne#f+ar?A%h;CD>%yTv$X;eAZ&eeejT^*eYU(|VthIa<Gi_c5*a zDeF?s!TZ=2WgnV=zkv(EGFb5icpuYxA6$=XT@QZ8wSEWh<67^7-*K(q!TY$@``~&^ z>w54zruDlM+d||!8t;Sa31f}xHSb@Zw0;NgBdzzr^+@Y_@H^7_9lVdU-Urtst?R+> zNb7g-KGJ$0T#vM_2fq`F-|d9o!TW^P`!@aDBoETK9{i4J{SMy8wB85T<L@=D2fyQ5 zzk~O2t@pw8xQ^>Ft?S|Qv44&k#p&RBOzV1Zz<=^taX=+|wSK3t*8AXhO!<6F@jH0m zKgX@&eek<~-d_~IgZDA5_rdR&*6-kbOzVB{JErwJcpvk`G8ONG-~F?E#qZ#KOzVA0 z&TIWnd5_b2A6$>Lt_P<RTBn2S39akF0cnWF0pWL&*6-kblGgj+cU<dt@IJ2fKKLD1 z{H`MWPGPP0!SA@%@8Er0>wWM$ru92`AJcjt{7z{74&EoU-shIuowR-j?<1}E!S(2I z>v5tJ{0>e>Z{c+7;dBqdAHaWu&tQxZ9MBzO;CHkPuGa&8r?BFErtrR^+Y&W_-))26 zRk$OO5x61vT}~C648OYozay~XedXbOQ7u;r#qX}d?@H}fis9gD@V+=><1DS;RgsOe z6z{tT*GuFJnbz-c2V<u7zB)cXSU&u2Cj2fRoD432_Z?|t&1=E$%;9&X;B0tbAiOX8 zUORpmepd{?dj_5fR=iKQ4!`5+8mBu29tG|OztbJRcyD#SPvduiU>V*wTJb*DqwFL6 zE(U&gw#QLsqw&7g4kVdt{LZ;8Nm}oN--#rR-@*Gtp2qvyB)ky!`>&R(!|&FE8*9AJ z>2WJO|NLLSI}R=n@ALZC^+@Y_a5`!Rr@H{BD*<P~^^)pTl;D7*bwKzXO@rUPh2PZ# zU+el>PJ{Qs@2C#^E)0Gb0iFr24)5FTWkhirzk~NtUGOn@-z}3Eq4=GiLmzr>79+Z8 zyzfqOrlj>d|09`_*8Ae;++=a^yW8-)nR9Ql(cpBj#{qk;xSl@zZYa11`1`10;gIOV zZ^Q3u!|&eW_Xcy|eMjMa!}F(e{k6+PYxvzza4B4G4Oq7x`DqeQg3}qo>EL=i5U#ft ztUDfl$9HP{&eW(o-w5w(3fF_*{d4bnfB4;x{0dz0z69{Tw(d;vJH_?v9o?DM`y5>> zi_IFp3+`4~v<3Hq>wOD*B^1|F{7wcF7|)$l{EigAONHOT`{))}@xC<VnBsKGXJ2qV z)(Na}y?^Q&*JFz7?Lu}bzNR>x#`XTmF^%i}Q&(K?ZtzsTwBKGa<EEk5JlmWvwQ7U= zo?c<Ls8^bwD)Jf~mEAjc=e?Kx7C}W<gd@An{1OJ!*88W$dEeWtscJAS8+BF;$*;rJ zS(a4(S|#!TAIq}j6~S9i-)5#6gSk}jmzcTsCbP{O%+-6(h!I$(YT0k5EHjksxmEZ< z7E;)RW`LW89~27T!yJP9?Pbc`T7o~!OJ!z_kIKqCmsqvoS254XwL`gVwna2*T_hII zUB=!P1ah7qCu-oHqDJ16`H^>X#0c*Mmej$Yw{%@6zMR^}2AlhF^RF9)%cxLx)F7DW zgawH@m*UuNlPP>y*LlM6@@V$zcnH5WDNt;?oXD)l`S6~$86xn>b~gC7KlwaaExzJe zytyfU^z+Lm@vgyAR?mAfrC?oSF^8`Ofn<j{=wX@rO{S0!mRTF?I&Kh5m$0rGSZ2F% zc!o2UxgP6!a6E)u0s=*Sm(DzR!;!R{?QJL)+jYon3u~Zk*F;|)Q14Az7pLdqTxmFe zIIGdI=;dCbvPCTJceq<#9=%KTCqG7gA?nF%ljXq=VyMD7TUpDMz$vH?L0w_H7U49x z!$k3<-7B@i{{O+@pEt^-onq;9s|0mK8GQEEPI*y_SPHu4rT&wbXzJa5CCR;vW2u*M zyjquCb?W*dU7buTOykFXCWx|lT+`Wd{lHkhuY#;Di{Cz-%HM7~!nQo_tSXDE|HY){ z_zl&k=J}Gsb~>!Br+w<**(YZS%j-Uq%HkPs`e%;Qj46xFk1uTdu<u@W`a>{j`K%5r z^`u$@o!s?f`8c06N#ViZu^Jwz;rCCc(mia~d~8=)Jjr^Ny4ScEe$Tm3Qn<GcYwP=? z`Z}fTh~?^oBc-x9y6J35yPwNqkNJVL^}=Z}yJ2VbFdf#d-x(f7<vQ80{j#mB%eQsv zhSj3zdaxra*MFh9EWX#-ie_x;Nv-&5Raso`M<lI~+p?dx)~o;Ib((th9#K@-+J?E- zbdin9;HjS(RgGvtXU#jS%i;jNC@SyTM(AbQ%DOyNQ!kJDquo(7pm$SIzVAYHz7Ffw z<JTn#fA?VO@3vaCx(x1mIEu!9Yb-k5S+CaRE;{w|ZzJhT`!=FREf@KMhHL)8Mnk*c zUOKjXv_ofgb#SqUb?fL0f8G%ub<$QYi`8GFxMK$kcCODtwJvAs)Ex^`Sj!bbyodQ} zmBKClgZ;`y^R6$<SX}mcwU%RaSgGsvh~io3*LrIgS<7p6SgDU3Fqv2UM63_%tS*Zu z=tc3;?rnrIwyP|@mlDaZM0OTkv0V>zSgD`W)H}Rw#NTx4!7UrCR+YtWTO+yN-_GLa z-|N+7an{>N{to@B)zn4Sa@{}p;9!5@G%B3--Lg}c#Xd2Os2`rM()MexT9?P_)F;(w zN7vGw=+edpvcgw19H^;ZMSYV?2U?l#NPRX;RO|8<)K_cj6&5(qx8RPnVd?6Oa({4% zrv9j9JKB)zM6H9o)PM3uP2KRTA*;JBnvMxOby+-fVS>11gy&v-30D8f7c_N~?CZjQ z&_q&W{t7$(2ipy~EnJ-^Pz!9AF5BwVr!B}9K1&0r&%l)#K{~8kPb|7Fo`+7PfGJ*T zg<t#!hlk@isu6x-uR%+7S^P_{Ctvi-isULGYK518vo)-(qeuJ>dQ@}eKmGbojy7t` zj~BHk`<)ZjW$};fjy$NP0}UK8FQY8J-?AOwioUE2^-`C``p4aQ*u)wXU9P3NEG~CI zkH_@#rq-21)Mas<?CY!pdejr!Ra3*=!MgS8k(XHC1C!|M_K9l4GPsTFefE5)KUqzl zmr)jPExOKLp+}X%ywnOS{rZ!Q7f+-G-zD~{BvX7^GKpI1WixY=<MO=yJ;|}yl(+cX zL1d0}r8RB7utWE6iprG-(>d$Pe8_DdaVNMl-5q4b=S*EL4nF5JrR8~6cZ30@erkp1 zH9umWwM=Lx>q>@$0;EzG8_Er^CxaWFQqu2^w7&WvsujIZw5?H|-u`x`(PsMu)vix} zXH1}|Qzt~m*+C*gZy@!J!|w}wt`+Gs!pZIEaB+FfcKOjsZ@Ss+y)e#hA?6>QLZ<bW zs!OkAi0W;Ilfl6>@hB)qEF9CG3`(a;O)Ivgf;M*4`gMX>GOH!6nr%tp^Ub8ti@oUb zWpjFP3eOLz(~<6ZTF~z?dsO`r`_M7lM%2+QP5kcXK()N<lD=6Nm0#fivLbVuZzsgE zrEMu?WI57%a8#Yx#fyIX8ql(XLhM=SLaX*37b#(t1zQ$K&u?89iGSS`C$|oO(##U$ zW+#ci_f8<&4SPheUqu@GyEjcsE)<{UToWTZ;W^b^%F&IFKk!T{C%RByqGzvMrEJTV z6ksr%hAwbc-Oo3qI;Fiy|D!hxX;GV|mm5xT16s3@@5)ooI!;SBZIWgkvZYL$A#{e4 zr1rK(^ecQQrFVEMCtDg)k9MP|d#}ZEjr<=%{^~+`J$p%SCR>w%;RuRfzfgLRT!})R zj)|1gkIc4We|q#gN31whi>HogM}zdbiHLUx*^ZI`iXIp&Ha|1s{vZ3$zH!^dqZ>8Y zuU$dZyZlD+v*a~<xN9hR$lpZQHWAY0x1*@f>D$7#Q64+n#EmZ1uSLhYPn7zm4<e_X zdQ{J@kQINGs9!$|TDH+&8r``MITsj`f%PNS`%VX1+sTT2e|3;5y7#1gepSfV=03Y< z-I-2jb)@e_lcX-&>?z@`IZZOV&EB<bNe?e~Ax{SnDdeFIb=1?-dzPDhxZbB)@>Sdi zea+8x{O;O=PGDXOwRv4SF+IImyj%Riv}Y?%J3P0k>V%i*{LSL`TJ}!+tJsPyxgN!z zHO{3bU2nBp21ZR>v|7pZ^=8qt#H;P@R(_SXx3G6RofiXV@%Xev)wGKxa&UD#d%;Mb zJ3T*<6;U70jI8xd9(L)hbpL%UZ(>|Q6?A)xs>}O_(x0!N)N}}SSu#%bF5US55Oycf zHrI>)|4R}wX3AU<Wk^Dj;e<+qA(^KpO{9qkWo|$jqG&LLQldfT;hbYCQK%3Z3MECE z5~b+(c;D~)v%dRx>-Yb+?qfY)`>eayKKHZF+3(}7?33B4YTL9u9lF(Bn5Tbc`;OnF z@96SZ-M7xjmzl5n$@FEdnx`Fka8~Aj-+yq9-1TN}&6zf&Ld(q24Thwx@jm7wzHF9x zw0z#o_P?K~H-2}Y%u2&M)mxo)#?m_VO8w*hb(&SLm+RIu)5iGwoX_7hIIVf<Dj9V; zw#;0Ae)h~P`}fuRt3vP0TR!hmZ}vlvrEhrjynoz(+Pm2^_fK9{_ejY$nTt06R_{Q8 zCTZ_yeJ10}&vInmG-`C(v%`jG{Jpnl=HMTO)U9*vh>ZXK{P(`lvfjm=Dx{tHT+Pg< zvb0Z|S0-CV+oClxbFQzNxw~K4w9_8{R*yf&<A44ykH0JLiHvQn$1NRI>5k04<8q~a zR_Knjv1MzePwIO-WAK>KX^VFKx%7|O{!CV;c-_X^Hm3jg;}>a`HM82vE$O-Xx65o% z<*#}h8?;Hg{*6<0i|omk+3Wb&v_mhIt@p$DCo{LTT~lXWpXGJ_`~FiG?9RBd(y8=v z<2z^WFHj`y<!PPMJ}C4`-NuFYWi*^IBCU9*lXXYk(l0aLw25_V@A=>#kKefbf{c{| zO4KdA<DtwwlPjd1Tz7Zc;yfcVuDEJm#+)^S(uTTzXa3MLbBOC#_g}8x{yG&hGWSee z`c~&BGf$6bnbs?_d)k70BQq*qRw|?L*pC0Xe-`(D>i=>76FL3Pi53f&Ze7?l^VjoB zrd=|lYuee3tELy}{%OXNjl<HGxPGTxzw2GUCjWB%=GUH_G4sQ%OZU|1kvVrrrL=o1 z_ei^PZ~62WU!Rn*zs2DHT>o(Y|JU`;SLM@;W@pYxPy5N=JLp<6t#Z5j(uUlVt6tq% z8!~3}8=iL1_5a@W-|6}<|Cj53`_IENZr?RLeg4lqGsictl~%4`kF@M9i_|MLb3{h> zGy4DM`P&<xzfb<<{&PF7$>_cGSo(_FyJQY}yhPfbMqScc*PUKBbMg9&UltBaE9v=r z!Sk2j^LN$1JbzV}mCjgJcvX7FtS2(N`P$igpl{l^;XCUN%UdC%kN0*f8lV4g|9^Y_ z!`D;Q^xD<DmSh%fTD;!6(|MK-J~be%#gf|9K7RJ~x?%fRovBN{sIn}_-haG)99~sF zv-Yljb$2~iF7uie+0riDv^stHlKz<sI=tf7UgpX8uG__#E6<)>_v;P~(ynSc^&j8A zT@Dw@Ty<%VrH7wrmN{y}Icbe|H%%+?%Z&7XHx$Y|a_6|T-?|S-U+lfi>#w}4?nQTA z_>b@3yZ6?}d|=<bOD`!_J+sf5UDAHsFs{xfzlY+zYD=$fHLgqgv;x&L%RJd|X|IDd z(lTbe{g20Qe0*!h<8@}$IAiyH-p64@=9Z09t_as6_rBFN&YUqUJ%^7Ud!u5FX2-YI zD_D5{KOVn%_bGK=&N4B*;}rwEZ)NYaYpQKoa=Oldv@4oSOiwF5zV1%1zh%AtKI-+i z!N0uzre5zxLtjgG-RHc0N8LH$wY~Mu>z5?g-^Z%`+x4H&sbS_1-;GbN(57tWZCP(j z+cIxs?cz`O&pc=F_PR&zYMrs$^<VM-asB@u`PbY(&RtutWvvI&vael|S@W9RHEy+! zpSw0=jn~D~e|rz7-1BR!+&5-khxNbz<NPUn(c&7r-g%-@_<SqQ>z#QzU*-8>hp($H zIfhOM*D`$UKmWZ=bLWMR|L;Eo(_Wb~ZRwzRe)V*I4c)k?_CL<AY+0A)+cIHkha=zo z<Mpds*%oP|$9ArB$obX5`E^gbZt06t&aZczUoEShtn2*BbbkHk^GbdEtvPaM%yfPY zbbgI;e%(;6QoU#5`PIq!HP-pHW_YKJiCJgVxu#yJf877MX4Ny!j_22N&abaZSE*OS z`L)6Mb(Zt%sPp5;&wFIN`p{!_onQaB|KxYG`}fP1)&0f!HP`v|U4bT<2c2IV<N3A8 z>+f%Sd!~8)Om}|yc_Q_nfoaXgw9F{sc{;=SHOTo@zHGL7EmF>};~xKKkN=v--}o<& zzbEgBdJnh!pYyAa^XrpBepgeu|2e+~I=>e0{m=Q8)~HPJ^qaPA{Kxly@n%`m#;n+q zo->|b+ZwdVtTXLY-SeGak2}9wd;R=n{F7-r+OAoe*=PCE)XzSAoy=UYyWWQtPo-bt z{5s(LdUaao%&`Uk_x$?0!^yfY-qJ5E&$Nl@b@qJlkH^2c{DOKj2L8|awcGi1c-`HZ zS@Mp^xZ3%(*!i{5^*iSJJ>&Y-{+H|bQ=JO+e%U>7>6^~4lg_VhncXwb%s(=ts`IOu z^J}yFpK$+Y-QW55kL&OJs<*cJ!lj#>Ux)wa{K{<Jv}$@W=hsT-SBC5N=WOrU>iRjq z{_*)Qsy(@0so7hX?s9(3`JeME^W}Zz(_eCa9dLgA|J}bxl~3z!IAczF-FSXgZ+Bnj ziMw;vOLKm`<NRvn`X6xp{rs?W<-c72dww2PFNgDMuJdc0^Q&^f9+?le_}}v@+&?^j z;r{9Wa{r8uYw8_cax8t7^XqBn*WN~5GON~^UUx-2zmn(A&mZZ|pMU)CPg_>H-U#Pc zy7TKn=hsgM`ewEowzKYV=T~3n*LKhUxcL14+x^4W)BkmT9m`WEIln$i&aY#6mTsT* z#rxZG>`njgufId9>Zg_3^S|fUZJSruUF!Ur@BAv@{MzC5b9A=J>CUgrnoXzv<NLSk z;X-LYmdUa7kn?MV^XtalO*2a#oRQw&`E}I!)vM=#^o7L-q%~Z5S9+N{FZ{>XkMk?7 z){pltE${rwDAy-#?S^qnH#@&tr!BoY>!7ab)16=6_ib3G=fN78B|mxVACLdiqf?en zN;!YJmEKZ2Ie+RU=a1LV{9Zph{mbj;x|Hh`&!1|~|M&Uh`h}1E+x45&sbSjTJ>%2M zJAc|ce@;%>xFq%b`PTIt6R)51{~w=!t@qEV-s$|W)0d6xpZ4?g7c)0j*j!_U?PGPf z6fKq!{`^y?;+HjE*gCQLl^eIu{qN_mTG2k$`!;Ii?-)IicC_Q<%$6;-)Ck+h>eZb1 zjPrV6W~FlLYCQ6Nz8bS8)&Ix&GofnE>a9!cOg}Wxd%b--J99;~%{9XIvARwE&i9}D zH!kvJjo((jUcJt^_5XPM<+cCkGdfeUL}zJM&L$h@kewXl<Xm!*JIbR$Uh<Kj^C&<; z3Q?FMoKI1TQJfN#q!gvOfD5^ZGL+?F%2A$6xReT1#KHX^l{L7GDk(0vgQ_X~fOJOS zhsHC)A85l51y@p&@Mq#$Turz%;SVg~n?8KuhbR9U>eGOR(X|>}$MrPg25#ggZl*C! zqNW-&i*C{8+)4{t(u&r!p)KvA_8N4cBb~U7+qomUQ}2p8>)qTF-K+O;KV9g`19am- z9^zph;ZeHNgU9GeFCM2iedx;*JV`(LGk}2%VlYE^il=#oXBo<{Xt)N?@q9EwgOSlF z4Ms;VXfTGcyvR$8V>~bO3a|1S6PU=PXtKV}lxV6>;|<<qI&bkdGkAxY%;H_%<9$A0 zHXkyFxy)le3s{(9k-a#@5<6HLrE8E8Wooc2TCOWt$tphLV^;GCYf`MW6QA0jv5xg@ zNb$Ly_`?1&#YQ`^$==LYDYn>&t@hU`w%OZL?68BK(Ki}=8|~6yceF=?@1pND*c<(z z!M^B6{fYe?;Aei}Acr{25svaJ$M}uooZxr<;3R+YS9D5G^EYRl=|5!QEV6Po**J&n z<RB;Kk}JxsdB_{()BK!A0SZ!x!W7|ric*Z?l!!`dP%1@fJGdaaP=kx2G8&YPF4mx2 zR9=HiqDwWXkfNfUsAMN9+lkBUL=`)6xt*wLC$6v))$Bxdy9QULsA(szvJ<uJtE1W) z)S)i^kH<68qHDB%iUxMjkZZXv#r1Zh=mrgLjBe84=BTj-O=wCpZlO81(t?<G@%# zcA|})Xlp0h+3izwuoE5aPSI_8J9ltrbe9I5qq{Y@C%RYf<Nm0NcI5%O@gNWJFpuyk z-RZ$&^rRP$)0;l@<q4jQ`f1QV8lVFi#9)T-6i@RE&oVR`ronKYi=NkDL^M)IF*<rd zgE7%qeUX=<aT<*0WnSS`UW+DZFfp2>lX;yfOl2Bx@FvrFi?^d08oU$D)LGHH`d;+D zeh|&p51GSU<}sfIEMyUjS;A7%$sm(uEN2BPS;a?u%xXSi4Qu(7&sfKLHt;!L@Fg4B z#Ad!?3tRb`ZER-;JNbrh*~M=5@EzZ?mmk>2kNm`b4)8O-aF9bB<_Jgmm1F$IaZd0% ze{hmN`HNGW=5N9etY?yiv&hQXWaAvNlY^X`OD=MghrHw?Kj%?^f)t`KML3_L6r(sL zC`l<wa{(7}5oIXL#gwBwmvAW+s7NI$a~V~*oT^+wHL6pCE2+s<)Z%JtQ-`|LBaLgQ zPXii8*J^NGbiFp>25#i0=w=NX(}bop;})88Yt%x6mb9WZZD>n7+S7rKbmBH{=ML`V zE;@5J_i!)waX($?$^&%cK_22^9^p~C(}Tz8NiQC!H+|^K6Ff;j`ZIum3}P@tc#5Za zhG!YdFoyFS&ohFNjAAq|Fov<b$V-f4JTLPKuksobn8+k1^Ey+Q$~4~KO{Vh}Z!?2; zn8_^O<vrf#17`DKG)IHE(L9~c0v56;TCBkmmXaQ2XeP^8&I(qtijVl1)qKJl*77Nz zv5xg@;B&s<OE$8J&3wfcw(>RG*v<}i@(tgzi{0$uJHBTxKd_G<`HB4;;Aei}Acr{2 z5svaJ$M}uooZxr<;3R+Y7pFMQ-<)xl*9@|77Fju)Y@9=Oa*&gA$whARke7Vq=R68f zkU|uu2<KCjViczYB`HN|F5p5gq6}rZm~xco5-z0z6{$pJE~5&UQ<W>IMs;d%B{jK< zT3k(S>QI+@q;U=PX+T4+<vOmX5jSunH*qtKX+l$)aSP44l@_$56|HGQTiVf{4s@gw zw{bgna3^=snY+1%d%2JM=|Wc?pc@bJ5D)VRkJ6nUJVsA?@i@KdLtmcYN&3;B0Ssgi zgBik8Jk2va%TR_foacC+5sYLMqj`ZbjO9gMVjSannOAs~*O<UWCPkC=b*3<tX}l4= zsndBYdRu4k4l|j>yS&Hye86lzWDawqc{-m3EMyUjS;EpNU4slVSr#qVU`4c2gH_Q- z8hjkB*2E`vuqIlo!Kcw@8mx=fYp@~uT)*H;HnNG$e8m>F@-^Go9_`RzC*MTh>MnM( zhwu2Fz0nUE?2CTX;HPN61_z>_HTZ>t(IGv|5spT`YH%$2O^<Ve-}!@+{K;RO;xvCp zXJqx-L>A5>D`%69bI4APD5nPJl8fBrA#apVgZ$BX8We~MYEURDtU(dZrzpiJP6<j< ziqc%bg<M1#%5rg3PJ{B%B^q2BRnVYfR7opy8CAHPs$4-es#Ak2smWE;;%aJBhq}}w zjcce+gQ%fi%XM5&BW~bEZsO*su{NP8&A5f;+)4{tMy)hx9ktP*ZPZSK_H>9kYNzNn z4Q}TS?&Pkhv)&!uqrtt=eHz>!b<v<}^neE4q6am2h=-#`G<Y=Xu0fCJG3`k&9;Y{b z=*ts4Nk95CfPoBRFhh8Xr+FrNR)<EzG#JivJkJP5GK$f>z!=8zA}=v68n402yb`^t z!D~!lB9oZR>r7!P(|Ch7na*3h%?#dQCbM{#_jsQVn9YaGVJ`ES&jJ>*h{Y^nDd}X8 z$ugF+f|ab|BR*y|pRk6te9C96V?7)AoG<v2jcj5wU$KR)e9bntvxA*{!?)~WH+!P* z^n3P3Kj=Pw<R|uXfS>t=gB;>8M>xu_9OE~RbAsRbgOmKpU!3AJe{;s!Uen0JS!CsG zvT+XC$w5xeB^SBLLtgTcpYtd{!KjcHrU>U#lwuT*N@!3rDy2c`=mHHc<RZ#YmWwGz zc`o5nDo~M1ROT|Oa5+`Ef@)N!23Jy(tEk1*)TRz~sYe>uP@e`g<XW!ddKz&9H*ym< z)0ieSr5U%-oLgx@OIp#IHngQ3?dd>AI&mAfa|d^F7oEAAd$^bTxSuX`<pH|!AP?~{ zkMJnn>A_?4q!*9Vn?CgA37(`M{TaYO1~Hf+JjK&I!?O%!7{hsv=NZ9BMlqTf7{gdz z<R!*2o|k!rS9y&IOk@(1d7UXtWg2hrCewL~x0%5^%w!ht@*eN=0kip#Im~4q^I5<` z7O|KmEG3-`GFirQR<M#)e8k7B<`dSimQVSNb*yItpYsJ@vXM<}<}0?am9N>xc6P9n zZ}^s7>}C(&@jZL_fqf}{w0~lMiUan~DSojJrZ{9L4%<gKn&MacSc>25<0($qzw<|m zlXl`y`>zzI?BH~YzwN{s*}N8UW{NC!;w(Fn)lQsk2ic-?G{_$1&>&}Yt_HcH+?vQ^ zC-T~fe0CzgojA`<6tEKo?L;9vQP@rtv4iuYq8b#7ifd3JDyc!KsI&$bL>FpsQB+2Q zveCs_E-J6VCDEl?fr?a$D(huY6-``jC#u?sE9^uyJ5k+E)UXp*+KHNW;wn2)%T8Qv zCu-Y?I(DM2U5~Wr8m&(Q8gebyaXpQ=fg8Dro1?}WG>MvOGj5?dx6*=^w4ya_XiGcV zr|4jJq*HX8-p(D|nc^-x=p5ax_eA&VecVr%sH;9ex9C9)9^zph;ZeHNgU9HZqL=+R zz3D^W=m~w2eo=oN5DnBp4336q;wd}vw4Hdyel{Aa!7zqL&*}4wNHNk*jItA>?ZgXq zFeb%VJ9sgANrQ3Gcnw}o@rs>z)lR%-2NR-+8ca$t*-pG}2UAi^wS#HA!JE-^4c_8y zW<>Ak%xIPd??&(G`_Ts)%;rPpL~}Km$NXr41`AmfE!JR3ilugto+85zGNWahSZ=RK zvC>|}N72W+I>je;VvU_xYbQRn6Q9|Mb#`LCo!DR}KDQHJ*oiOgR2$t+Y_fyR(N`L5 zNwL*V^|jlHZFaCd#SS~wPPc<^{>!&+r`qLqusg*bJMo>J>U*~nd+o#zcCat{QG=gS z?6(sK?8MJ@s$bkrb<pj^Av@J!w-ZO~#8Er(s~sFm@tYkSk4|XfcRTna#YsEyrycwi zozmcRiofmPjC1~PXS$upVy8OG?NnLaPMmEA*`jkak=;(@uoF4$#JP4NmmTCzk;hKt zwNvGDJCWZ`oM#6GqJkO}iVAB`BsyP%qERsoibo|hQPK`dMWr>kAi7Y4i=r|bl#MRd zpj=d5gG-`IHK>rHq8(I<Dr<0AR7De)+li`na79#2gX$@2*uj<5jIPq47FS2LHK;>f z>XF7ZQGE>>(2#4R>omBYM$ru#+!)=YH`ACVQBzGcvu~k!id*d#DO%dCqShL;iP~z= zE^4nqhp3|loub<`xIMZ<gFB<UH0T`Nt-(Ffy&BvX-LFBHsH+AK(2WOqh=-#`G<cNm z^hoiTo#<&NdfBNScRT3)U;4P6s;}Fro^U(WlWwQ#=XR?8ZYKuViGg-vkR1&EFGJi; z^_1JGo_0I&jGcJa4u(d<G#H-ZIXieh8ll0+Xp|;K+ld$KU<_kZyl5w0vJ>O%@zKi~ zyb`^t!E4b3oyepVlkHTmyFDeEs?$=uVFzzU(=~XDx1$;Q4l`5CvJ>yx!Fws*w?9ZR z+fMbN+jE%9ycF~8!~%O^ibZx}v7K0A2TP-L4Km1#mT9n@6|9U_=||DWx;pwqgEi4w z{WSVagLSND1E2E+U$T)+Z04(Iiw0YxuQk{fZP#E&v{Qp`qHi_W#cuXQ-|6@4<p=ih zBR{d91N_V{9OMv(Il@tX<ru$loD=-cADrY*{^As;`J3=BL7zz$&LS&klZ|u8P7ZQ% zF1g4}9`cfp{G3Mt3Q~x|6ybb|QjFr1pd_Uz%>`V@MU<f|7gLV%T*9SPpdyv1%w<&J za;kC#)u>JluB0YcQH!goO&#h|k2J2KJ`HHdwOq&bG~xzs<R)&WF->SnGj5?dx6*=^ zw4ya_XiGcV(}9k3;x=yQ4({YGI&(Moa4+|9KV9g`19am-9^zph;ZeHNgU9GeFCM2i zedx;*JV`(LGk}2%VlYE^il=#oXBo;chVvZHGlG$fVl*!>hOxZJON?VYFY^ko@){GE z$RsB7I#Za+G~S5b)Wmc<@s^!<+YV+#?`UGCotR}O-nA3&*@^e<517q|%waC`n9l+h zvWUejVJYckkjXNZvx1eZ;v+t0HJ`ACwS3BFtYbYJ_?$2Jl8tO)GheZVt$fWkwzGqs ze8acVF5S%@zT<oL@&o($k)PPl0e<Ee4swXY9N{RxM#nVxjpLk%e%IiS=%faJ@)xH# z&EJH-XmKW4IE$>DO*YOUJ2}Y7xlu07O&;=+kNliR0SZQiG$<Su(eo)vF^W@yl9Y-{ zYj6P<auH=H%f*z7%IhW3rCNcCRH8DMQH9H+s(J<0s7?*8q$XEUi>s+k9qLk#G_IjO z4QR-<T*vh^;s$QyCT^xNO=wCpZi$*}aBI{;gO*V%4O&NSG-yjZ+S7rKbmBH{=ML`V zE;@5J_i!)waX($?$^&%cK_22^9^p~CM?ExnjGj?1eLU)|eWJelMD(Nv{i6OF42TBm zAO<spr+AuYQao!9Wf;SGF2(b9VuU@CQ7J~-i5KiKDaP7~7wwlAmtwsAa*9{%;MM3g z4JJerHJB7l*5LJMiUw1e#v8oJ^yn>pn;E>rOlI*e@9{n#M6>ln<}jCe%x3`$S;S(N zu#|K%qD&2zv78mGWECIrF{}9`#Tq-Y)=qqC2cM-_XD8O%!G`E_O?+VoUq%}>*c5Hn z;Hwl{?8H_(@wJ`UW+%4Wi5+%gr=9r5PJC-8cG<h5JsNz+_v}sagB|RPe$=1XA05!2 z`GtegAq@^kNAzg)s|LrS-!wQLozUR-=np-~pZvusPV+ba`3rM7|EFhaB8#0k%T8pq z6KC7mQk-KavfDupa&j)Y$Q|X;Aa9gUgZ$BX8We~MY9R_!g!3s%F^W@yl9Zw}7jPjL zQHHWyOgYL&m*}NY1q~`viOO6?6)vYLS5Pggu0aj1q-J!L2DPHAwKjF4x*F7r()1eY z(;#Z7*K!@#(<r(@gB!Vtn`ulFn$nD0XwI#)pk>rbgVs?S4cbQSG-w}n(4b?~NrT(C zojbUbyXef_+{3-x$NhAnD-Y0(2YHBxd4xylP7fZVC%t%_-t>w3YVbt#qz3(>{u&I3 z25K-U8mz&P=qU}Jj-Jur*=VQ+!=m9DJQqE$!H8(22BV_U8oUsV(O_)!q6RNT<1`o_ zy{y42(W@G~7ERD#Vl+vE$<gZ?Oo^syFfDpRgEyn;8oU*~t-*}w9Svqivov@&dQXG* zqYpHg9et?5oM^5F^P>40EQl6ruqaxr!IEgH2I*vw87<T0(FzS#MyoXVh>uyF;uCuf zYx$JVSjT!c@Ht;ZU+P9SMVs|2wy>42qiwpK9qi;AzKwQiushnL!FSR38tml<_C-Hx z@Kdy3g9H4`FC63$hdIJge&rayMaT6-^t%RsL?<=)Gx|$|Q_*StI|_f%`b@G!XK9d? zv&qIeWG4qXIhS1Ij`C=bmwe=p&eKEzJ5kUM3Z*D)CyLmK^X)`YJ5kIIic^A;l%g~j za3L2_hO%5tIm&Yhmr{X>RH8DMQH9H?$`w?jIyJbGnp{OKuBJA1s7t*lO|OaSYtVp( zT+4MSuD63m(G8lo(Y}eBX-pHE(u`YZ9^I-zi>Rdrt)kW%w29hk(2n+Wpd+2QjoZ0{ zJEOZa=$ztiJ8_R4+#B7e!TnJe4Z21TXwWTsP=kk}hc$R4dQ^k%Q4b9si+XC%D|%dm z-ccV7`bJM^@MP3agZ|L~4F*PoG#DHW(cr1*X?=!g8Okt*^Bm7Jf{~13G%qlQvAoDj zjAJ}6^9rx>8WWhvBqsAZQ<%y$-r!B9^A>M2gLjz8EZ*fk-sb~m^C5GX%RJ_@fQ2k# zF-urVIvHfLjODCgC9C*|k6FzptYIym@)_$`&jvo{3%+C{o7l`(Y+);3vyJWSU?<=3 zExXvw9=_vy_VNS!_>rI3&jEhs7Y=fW!yMr#zjBP<IL--v=MPTuCx3B@)BH_%Q;IXm z!dYbHY_f3<*~vjp&LtPQ$wOZ9k)QJ@KtT#om?E4{QHoKV5|pGArMZ9$xrj29<zmWF zo=dot3RI*LmAQ;6TuxQ4pc>Vw!IjkHDr#{xwW&j0>XF7Z)TaRrxt8m=o<`ijjoie| zG^PnnX~r!y=T=(Kl2){)4Q**hdpgjOPTa=r+`*mPMQ85j9`5Bn?xzb~d4O&_$U{8L zBRooXdhi%M>BZyprVo92f+y)me+Dp+K@4UHPw_O*@GL_a#&DkFc}6gjQH<sV#xRx_ zd5Lk1=Ve~uRbFEP6Pd(hUS|qZnZ_Hu$#mZ0ZD#NeGnvJ^yvO@|z-&Hb4s)5ud={{f zMJ#3sOGzh#OqQ{n6|7_xAMr7(`GhsB<x@Um9qZY^=X}AJY-AIg`HC%U<!iRFogM7t z8@^>1yV=8ce9vBfU>`s76Z<*9&-}tc4sn<x9OYMz@f*iE!SDRRN&e(7PH~#Q32#Vq zCRsR(tej0Y&LKNF$jQ0nA~$)+OFr^*9t9{!AqrE3^C?O(ic^A;l%g~ja3L2_hO%5t zIm&Yhmr{X>RH8DMQH9H?$`w?jIyJbGnp{OKuBJA1s7pQ4xQ6;Ppdr_C9oN%{8@Q31 zxS7T@p()L{h34E!3tG~O*0iB5?PyO2I?{>TxScz=le_55-Q2^y+{gWNp(_v2jR$#% zhk1lY=}r$GqbI$1oZj@IFHi6!{pimC1~Q1j4B;uB<{6%4D8m@eb3D%oMly=gyucX7 z@**!Wj`6(AE4<2UOkg6Dn9S=;VJg#jgEyJZTfEH--eD%Qc$fEhpAVSLhs<Fv^O(;9 z7P5%NEMY0>WRS@+ma~GDtl}d+W;LI%hP8akXRKpA8~B_r_>zrmVl!W{g{^$eHny{a zoqWT$>|!^2_>S+{%Ma}1M}A^I2l$y^ILILmbA+S($}xW9I4Ag>KRC&s{KY9w^Ecs5 zsLmt{XOWe&$;LTkCkHt>mt5o~4|&N)e$Jx+1t~;fif}$fDMoQhP?A!V<^nF{BFa#f ziz!EWF5yxtP?1Vh<}#{qIaRrWYE-8NS5lL!sKwRPrVe$fM;g~qp9VDKTCU@I8gT<R zauYYxm?ku(8Mn}!TWLW{TG5&|w51*G=|D$1aT~XD2X}H8ow=KPxR?95pDuLe0lM)Z z5AiUM@F?Bs!DIBK7mw4MKJ?`Yo}?fB8NfgWF_<Ad#nU{)vkYYz!+DP98No<KF`5?` z!&qMACB`wHmwAO(d5sB7WD=8koheLZ8gK9>(|L=xnZY~EWESu89`Ex3v-yxY%w-<) zS-?UTv6v++C7ld1S;lf!u##1L#K)}W6V|YnPx*{>tY-tC^95hBkxgvoE4Hweui3_S zcCeFg_?BJlW)I)-J$w0qef-Ez?B@VK^9u(##9@wblwUc<Zye_Yzw-wt`IEmm#cBQ~ zyaC;rWZ^8bayHpGhwS7aC+Cuj+~grI`N+?C6rdo5C`=K~rzpiJP6<j<iqc%bg<M1# z%5pK~D9<HaN(CxXiOO6?6)vYLS5S@W)Zj{Lauv0>n%dN%F7-&`8tT)4hFr^aTu&oz z;6`rZW*XCkrZnRgnsX~HXh|zt(}uRRqdgtyNGERNcJAO#?xHhya}W1&ANSLRt~@|D z9^@e&<`EvHJ3V-ep7i2zdeeu#Ji(Lnqdx-}$RGwYgr|6#XLy#O3}ZOY@jN3K$tXti z0%I7<i@d}*#`7|-@G7q{fr(6FGOsg*sZ8Sy-efv&@isGfhndXcUEbq;K43N<GKaa$ zV?GO5$RZZAgr%gDK_<&s&I(qtijVl1)qKJl*77Nzv5xg@;B&s<OE$8J&3wfcw(>RG z*v<}i@(tgzi{0$uJHBTxKd_G<`HB4;;Aei}Acr{25svaJ$M}uooZxr<;3R+Y7pFMQ z--I`xJd-S(MOMxx8|RRn9OUF&a*>-n<Ru^Zqw_Q<KtT#om?E4{QHoKV5|pGArMZ9$ zxrj29<zmWFo=dot3RI*LmAQ;6TuxQ4pc>Vw!IjkHDr#{xwW&j0>XF7Z)TaRrxt8m= zo<`ijjoie|G^PnnX~r!y=T=(Kl2){)4Q**hdpgjOPTa=r+`*mPMQ85j9`5Bn?xzb~ zd4O&_$U{8LBRooXdhi%M>BZyprVo92f+wSX8uX6_XfTjL3}y&V@ifoyY&2AZVGNI+ z)8P4Nga#uS#pvh-4aP8*7o(Rn7{~bNWql=jRfE@}2|AHUOy>1yicV!(^o9m+M$<KT zi?^A<JIst`>ATT;8obX3%;rPpL~}Km7tPmT0Sj5gVwSL!bTY_{mT9m&TA{&8Rz)9a z@G-0TBwC}vT0Z5oXq^V@qYe5wUqoN(Mm9y8HTWvpqQTbaYuy%Y*I-AqQ-g1!Z#CEz z?bcvV^qmIZM|(B+A=;<GkI_#W?2is;@N@Kw1_z@<8XS&}XmB+8RfA*EZyFqrPH6CZ z^oIr~qdztHD>|jY>F93_{`023`MthISu{8+%BsQHQ8o?EiLz^uBg(14xlt|+az}YI z$Q$L;Ab)h81_h#m8Wf5OYfvOQUxT7iF%61GB{V1*mC~Rz7jPjLQHHWyOgYMP371lV zid3R9mr;ewshZ*nJ5kL}RJRi~?8KFJqNbg=%1+d>6Ia`{sY6}rk;XODrvVL9Tx%z; zvlG|biAHwf20L-1ow&(P+-xTr+leN2qN$x|W+!g36V2_!t#+b?ooHz%TG@%#cA|}) zXlp0h*@^acqJy32XeT<^iQDYp_UH}`?u_ozpmTJ$2KPkwYH(k4zXn~Rt{OZLb<^O% z=phXrjvmqA(WtuyJ)*}n=o$6W;PI%p27TxoJ)uuV{WRzw4bWg<G)RNN3`y~nop{=Q zhG$a@wG+ea;XKFlDMr|dk@hG?^8#ZS%Zt3kIL7lbukb3bF@cFpVluBYg{e&A4c=sW z^p*y1M>8~dCz`3jtQ7CsiTCW_{pbS?W=9`tFejR;!Mqgn?Zg5*SeRmwomgxqme`4< zb|T#lGNMdPEVGxhf|ab|BR*y|pRk6te9C96V?7)AoG<t?#YQ`^$xdvx6JObhEp}q7 zo%q^LY_k*F?Zgf{vC~d`V<*0~6T9rhZacBZPJCx4zPA&5?ZgjuVxOJ((N6qiC-&Qk z19swPJMoL1IA|vh*@?q;;)tC%YA1fR6UXetZ+7Ci9h``M*Wi!nqy~RRe`#<kI<3Lq z(SP3j|2#h{L|HUAE6S?D*-<tP&WW;XkR!^e!MRZ`4RS|$G{_s}(;$Czo(2V?f*KS` zQP@rtu@mRpiK2E;jN+6?QPNJ7vP*M8iVN+;MRu7KW$nbpb~(y(371lVid3R9mr;ew zsmc{pqdGOXlA2saEv}|Eb*M|dC{2TFqWT&%h#G2eZHnvc;QFYMCT_5U8>5>vxH)R9 zL6fMdCYsraTkJ%0J8`R>XkjN>+KE<nqO~2giP~z=E^4nqhp3|loub<`xIMZ<gFB<U zv@>^e5BEm*X>dPX=$hgIJLncYsKG-#%p=jG8g!>e^qBUHdg<fzrVo92B6?DTeo=o7 z21Elj7!(cGU`X_o22V%N=(7xE7{hrkdR~JOj7%}gPK>r+U<_lU7xkqS<LtzE`{fj` z*srE|&7QzSCPkC=b*4m9H8IV8gEv!5w}ZEMn;E>rOlI+JiudgI`GDDc$Q<S}kNGTM zA&Xed5|)xq2AM2lIV+--8m!_YK4vwau!gmK%4e)&JsbF(FZhy;Y+^HCv4yRC%{I2P zgPnZCx9nm!d-#s;*~<^?<41mCKL_}kUpUAi4s(Q~{K_$Y<2Wbyoj*9qpZvusPV+b6 z7sH%M7S19oXOoR{$W9J&axS^ZO&;=+kNliR0SZ!x!W7|ric*Z?l%OP~D9r_2$VHT) zEEiLb@?65DRG=c2sLW+l;c}{S1=Xld4X&gnS5b?rsZAZ~QjavQp?=gr8*(kzaXpQ= zfg8Drn`ulFn$nD0XwI#)pe3znO&i+Mj`nn*Bb~U7+qr`~xr@%+%{|=9ecVqMy7B<s zc#wy9IC?}Mr8_-%jGpx3@u;`<p)XHFPijB<Gk}2%VlYE^il=#oXBo;chVvZHGlG$f zVl*!>hOxXDy`;f7#`7|-M6YV_8WW<48cbp`uSZjKYBWvXh~CucycNBzGop8NCbLq! zYX|S~eu@w5*?gE{j-8lm&r31iPAsq!3++WLW(iA4Cxc9uv78mGWECIrF{}B6HLT@R zK4Ts0*}&&~!Ix}g6Px*pEo|j$wy~WZ?BpB1Wf!~I!*_hoUVdO-^rHqpMf){45dEyd zFVR5_4n>DGI1(Mz;8%{N_{}~ZozUR-=noA}Mt^GX7pJ1r8vLCi{IaVvqbwSn6=l`n zY_f3<*~vjp&LtPQ$wOZ9k)QJ@KtT#om?E4{QHoKV5|pGArMZ9$xrj29<zmWFo=dot z3RI*LmAQ;6TuxQ4pc>Vw!IjkHDr#{xwW&j0>XF7Z)TaRrxt8m=o<`ijjoie|G^Pnn zX~r!y=T=(Kl2){)4Q**hdpgjOPTa=r+`*mPMQ85j9`5Bn?xzb~d4O&_$U{8LBRooX zdhi%M>BZyprVo92f+y)me+Dp+K@4UHPw_O*@GL_a#&DkFc}6gjQH<sV#xRx_d5Lk1 z=Ve~uRbFEP6Pd(hUS|qZnZ_Hu$#mZ0ZD#NeGnvJ^yvO@|z-&Hb4s)5ud={{fMJ#3s zOGzh#OqQ{n6|7_xAMr7(`GhsB<x@Um9qZY^=X}AJY-AIg`HC%U<!iRFogM7t8@^>1 zyV=8ce9vBfU>`s76Z<*9&-}tc4sn<x9OYMz@f*iE!SDRRN&e(7PH~#Q3BUO6OtNqm zSvi|*oI`eUkdt%CMQ-wtmwe>sJPJ^dLKLP5=Tnqo6sH6wDMe{6;6g5<3}v~Pa+K#1 zE~Nq$sYGQiqY9T(l`E)5b!u=WHMxpfTup82P?vh7aSiopKtrzOI<BV?H*h02aWjo+ zLQ|S?3(dKe7PO=lt!YDB+R>g4bfgovaXWW#CwI}AySayZxsUtlLRTK38xQgj5Az6* z(w!bWMo)V2IKAmZU!LGe`q7^O3}g_48NyRM%`-g9P=+y_=XjnGjARs}d4VyE<wag% z9OHSJS9q1zn7~9PF`3ty!c?a525&N*w|JWwyu(ap@h<Q2J|8ff51GSU<}sfIEMyUj zS;A7%$sm(uEN2BPS;a?u%xXSi4Qu(7&sfKLHt;!L@Fg4B#Ad!?3tRb`ZER-;JNbrh z*~M=5@EzZ?mmk>2kNm`b4)8O-aF9bB<_Jgmm1F$IaZd0%e{hmN`HNGW=5N9;y*!gF zoJCg7CL8CFogC!kTyl|{Jme)G`8kgQ6r>P^DZ=>_r5MF2K}kwcnhUs)izq``E~Xsi zxr9rpKt(E1nailc<y7Sgs!^R9TuDu?q83+En>y5`9%)=deHze^Yq^f=X~YfO$W7c# zW17&EX52z^Zlwh+X+>+=(3W<zrvn}7#BJQp9o)%XbmngE;a={G?$@A8)K!BAqHY>I z$U{8LBRooXdPI+DqNm-9$D`gF^ojcF6FeF9)1W^CqJcVy!3^Okp5~e8Sq+9p!!#Hk zJ*UC*(FhGjMx%5zFEEC&ycoTt!8peAGOzF|uceq^CnnmHn4IEudkRyT7QLZwGCjpx zcH(V&2Jb{Obr$dPUW)ha517q|%waC`n9l+hvWUejVJYckkjXNZvx1eZ;v+t0HJ`AC zwS3BFtYbYJ_?$2Jl8tO)GheZVt$fWkwzGqse8acwVmEvEj_=va5A5Sdequid_?cfg z$RQ4Mgroe*F@EDXC-|K|ILV*<#VJnnH{loZo=FzYA}eQ;jdRFO4svoXxyVf(@{*7I zoJRo)Qi#G7;e3ixjN+7_B&8_L1zgBQl%XsaQ;zan!lhK8B9*AjWmMsEs&WO@s7?*8 zq$XEUi>s+k9qLk#G_IjO4QR-<T*vh^;s$QyCT^xNO=wE9=oW3xt+b$J)Jj{^CTgqg zXio<^(uv!+ojbUbyXef_+{3-x$NhAnD-Y0(2YHBxd4xx!?%IRLqMjP`iXPYA^ojav z@B~lNFY2!YqJcUn8mvR2r!;t)XQF3yD8r)R8a&7IjEF{RFpAO93p$3eyvR$8V>~bO z3a|1S6PU;(Ci6N|n94NX;7z9U7H>0ycbLg6-sL^s=L2T*A#<3^Jm#~2g)Cw*OIS*J zl%YXpv`mBL(FzS#MyoXVDEe4~)zK#!tclj@r_pB`tc%ubup#<fgD?0p+Ni;%XtRFB z7Pj&=+t|(ycJdA1vWwm9;XA%(FF&x4ANh&>9N=eu;UI@N%n^?AE64ba<DB4k{@^5k z@)xH#&EJGy8h$2OIE$>DO*YOUJ2}Y7x#S`@dB{sX@^c;qC`cg+Q-t#=N->I4f|8V? zG#79o7g2_?TueF2a|xGHfr?b3GM7<>%c;s0RHHgIxRRP&MJ=wTHg%{=J<_;_`ZS;+ z*K!@#(})|mk(;=g#x$WR&A5f;+)4{t(u&r!p)KubPX{{EiQBlHJGhg(=*->R!@b<c z{dA!#573PVd5DL3gh%O44<4f@y?C77^r0_L@Fe}{&j1E8h`|iuDW2vTo@FS*7|wG% z&j>~`iqX8l7{>A<FENhsyv!@S%4<wuB9oZR>r7!P(|Ch7na*3h%?#dQCbM{#_jsQV zn9YaGVJ`ES&jJ>*h{Y^nDd}X8$ugF+f|ab|BR*y|pRk6te9C96V?7)AoG<v2jcj5w zU$KR)e9bntvxA*{!?)~WH+%Sw@7c=_?Bhp%Vm}A?nO``_Ar5ndqx{M-e&aYN_?<sE z$)EhiDNge@XB74QPZrK1D`%69bI48(a&j)Y$W0#dl8^kHM*#{_h{6=%e2P+x;*_8y zr6|n>T*yU~p)40uj`Cc>rBt9Im8i^RRN-=}as}0>P7SW4CRb65tEo*L>Qaw1uAx2+ zXvno($MrPg25#ggZl*C!Xi76~p*gqGf|j(RHEn21JKEEMj&$NSZs!i}<SsgMH}`Na z_i;a6=*k0h<3S$cVIJX8y3>Ql=t(agr#F4*%M(0FKl(F(fed0WLwJg(d4^{h$}ooW z9M3a?k&I$AFEEC&yvR$8V>~bO3a|1S6PU;(Ci6N|n94NX;7z9U7H>0ycbLg6-sL^s z=L2T*A#<3^Jm#~2g)Cw*OIS)e8Dz4I<*Z;OtN4hIS<NS`VJ)BX8S7Zj20rHtzGNet z*vwaKVJly=jqU7UC*SZbyV%VhzT<oL@&o($k)PPl0e<Ee4swXY9N{Rxa*W?N&Ix|! z4^HwYe{qV_{LLA~eE*Y$v&hQXWaAvNlY^X`OD=MghrHw?Kj%?^f)t`KML3_L6r(sL zC`l<wa{(7}5oIXL#gwBwmvAW+s7NI$a~V~*oT^+wHL6pCE2+s<)Z%JtQ-`|LBaLgQ zPXiiqE!S~9jktjuxrv);OcR>Yj9X~Vt+b#et!Paf+R~2pbf6=hxQ*MngFCs4&fLvC z+{=C3PZzrK0Nr?yhj^Grc$Dt+;4ymAi^u6rANukHPtuS6DF)byfp%h$ofvEfLsC3t z2Tw=OXz*+_RD)sBa1EY|p4VVRG*T0z?8In0@q!(UiN<R1Vv3jSU|cj_gO{UMH1Vn( zycSK+U}7{$gUQkB8cd0%YA`K&LxVS?=^DHhy{*BF=p7AaMzb_{H+oNl_oELqm>qqn z!JKHW2J@o%8Z3wwYOp9;tcfLdurx)woyf3*%xIY=mfOLK6f5n-Dm(Zn`dAaI?ZhW` zVvU_xYX_f3pJ}izTCc%|=yMIeh`!WdW3)+w&Cyqy*kT7;qpvmC7H!vHM~a<x@J;ls z2D_r&n%H9p-$mbRu=oG4cNbt*RqG$ek?!v9?q+7r-hgyUcXxM4i==>*NVn1@APpiS z3KB{x-QA7U|N9Q>#dXhr1_s1?_1^J$KF{x6Yp=C-o->Wcc~V?3E|TJsahViXjH{%$ zW?U!54dW&$ZW*^pamTnzihIU=QarFcq*jlp)$i2evGIfyPmO1!cy5G9#K#=GhmZ(` z&<KOD2#4^9fQX2M$cTcdh=%BhftZMe*ocF;h==${fP_ed#7KgqNQUG{fs{yv)J7UI zEz%)9G8h?2kqMcR1zC{|*^vV|kqfzz2YHbX`B4Bq@P!{daNwdK3ZXFGM-dc7F%(A$ zltd|%Mj4bvIh4l-sDO&7gvzLbs;GwQsDYZOh1#ftx~PZxXn=-jgvMxsrf7!dXn~e! zh1O_;wrGd;=zxysgwE)KuIPsD_z*peo@6idMj!M=KYWD#_!t8)5Q8unLogJdU>JsD z1U|(`jKXM)!B~8TarhkLF#!`X36n7eQ!x$GF#|I(3$yVBzQi2N#XQW%0xZNLEXEQn z#WH+_<ye80_!_IQ8f&l?>#!ahuo0W^4L0LjY{7Tfitn)vKj24f#}532o!Eul*n^+( z3-)3k_TvB!;t+ntZ#ax2IErI9juSYEQ#g$?IE!;Qj|;enOSp_HxQc7IjvKg%Teyuo zxQlzZj|X^&NBA9&@dQut49^iFG4BTmiBJfQFbIoq2#*Meh)9TxD2R$^h>jSDiCBn@ zIEagQh>rwFh(t(?BuI*6NRAXpiBw39G)RkdNRJH2h)l?gEXay%$c`MyiCoByJjjcD z$d3Z>fiL{vfddx>Q3!?cK8m0yilI14pd?D6G|HeX%Aq_yKm}ApB~(TgR7EvZM-9|O zE!0LG)I~kiM*}oOBQ!=6G(|HsM+>w>E3`%%v_(6#M+bC7Cv-*^bVWCG$A{>Fp6G?% z=!3rKhmX)7A7cOpVh{#n2!`Sl48w4Yz^53AQ5cOe7>my^4xeK@CSW2aVKSy*DyCsN zW?&{}VK%<NmzaaOn1}gTfQ49u#aM!+Scb2#94oLAUt<+kV-40~9oAz5HewUL!Df7m zE%**w@jbTT2mFZb*nyw06T7e*d+;-U!CvgcejLC-9Kx^o4To_AM{x|taRMiC3a4=f zXK@baaRC=`372sNS8)y3aRWDT3%79xcX1E*@c<9;2)`ST$tQS<XLybfNq7%HNQ6RY zgh5z@LwH0$L_|VlL_t(ULv+MIOvFNL#6eudLwqDaLL@?BBtcRnLvo}*N~A(+q(NGw zLwaODMr1-}WI<MBLw4jqPUJ#v<UwBKLw*#14}9SV4;;8Ch(aig_fZ5zQ4GaV0wqxj zrBMcDQ4Zzt0V<#(Dxor}pem}NI%=RMYN0mjpf2j6J{q7Q8lf?opedT6Ia;74TA?-C zpe@>=JvyKxI-xVVpewqeJ3d4Y^h7W8Mj!M=KYWD#_!t8)5Q8w-7($An_{11S4mU=S zpBf{{Q5cOe7>my^4xeK@CSW2aVKSy*DyCsNW?&{}VK%<NmzaaOn1}gTfQ49OEGCy2 zOUY&U3d@ZZq*#fsvC3FYiZ#YsQmn&zY%n&GVw3R=DK;D5l41+K!&c*aQfxDRAjOZy zc2evxej>$A?80vB!O!>wd$AAujRT}Oh(q|*_>B~YjU%Kuietuc@`Q1c6sK?+XN<F? zIEVANU|b}{C0xc8T*Wn9H*S#Prg4iDw~agGUEITcJTM-TkBr~R$9RIL#xwFcLL}w= z3n38-p%DgQ5f0%I0TB_&h)jwoMpRNnLv+MIOvFNL#6eudLwqDaLL@?BBtcRnLvo}r zQj#K-k(v}~kQV8X9vP4knUEP-kQLdG9XXH_xsV%qkQe!o9|hn8U--cT2QCVt5DMdc z6hToGLvf=7SrVmC8f8!x<xn0UpaLqQ5-OvLQI)J_R3}9Zqb4b8p|(+ntc!Z6j|OOn zMn+>&G%=czqM6a0Y+<w{TcI`Dpe@>=JvyKxI-xVVpewqeJ3d4Y^h7W8Mj!M=KYWD# z_!t9>futCO!5D&}_yof+93${4Mq(63V+_XPGmOLM7>@~<h)I}?DVU0Bn2s5kiCLJ9 zFYqPiU@qoiJ{Djh7GW`#U@4a2D=fzfti;z?h1FPtwOD7YCpTatHsKp=#<$pl@30l$ zV;g?JkJyeK_z63)3%jugKjRnd#XjuE0UX33{EFXj*f>IpqsB2(95+so;-qnk6sK_p zXK@baaRC=`372sNS8)y3aRWDT3%79xcX1E*@c<9;2*2Yop5Q5-;W<Ji<NXIA5elIZ z24NA-5}sN`pjHv7RU~Q=*%F0XL^Yz3BDxWS6fuohq=;?AAw^sx9x37*2}qI9NJNUn zMiNpaHIk7cxsietDUDR5NNuDcRa$D5j#{OsRvD;8Mk5m`G8<V)k=4jXitI)XQsgvp zks`N|hZK2@e5A;46d;9<;Y$iX!$S(ka7j_nC`5|F#`~lwViYAsF{3ysN*E<cQOYPy zsxs87EVU{}t;$o24~z<=sAyCoMP;K3DXJRPNKxIWL5iA2EmG7r>X4$YQI8b$jRvG> zXfz^4W1|Tvni|bW(cIF4TD7EBt*BLNYSo5Xv^Cn1qP@|96djFDr08sPAw^fC8!5UQ zACjVn(UTOtjNYW^WAr6OKjR}(^fx{x#Q<X<DFzvXNioD2N{Ua6VWb#tj3C9Q#z<0( zGDeePj4_rJpBdvw@wqXc6cdbzq?lw(CdCwEDk-KJ(@8PIm`RFR#%xl2VSGu7ImTR4 z%roYbVu7)c6pM_-q*!7sCB-u1D^e^sR*+()@ii${8LLUL##l>=b;f#9Y%n&GVw3R= zDK;D5l46VT9VxaN-;-jS@dGJ-G`5pshw&3Bb{e}#vD?@~il2>NNU_)0M~eN%0a6?^ z4w2$l<2O<qHja?usBw%G$Bh%DIBA?B#cAUVDb5<_NO9h{K#GgTB~n~Au8`uYag7w$ zjT@x6Y1|^kZQ~9p?i%+<ao>1AiigG{Qv7Z_CdCuuDJh;A&q)y?`3vunBBT+D6rqhU zqzG$-BSm;40x2RIkw_8Qh(d~}Ml@1HH)4<?rV)!2v5h#Sh-<_nReWk&0@?|Y$V+0{ zNstuDEXk==3Tl;-I+Z0gbs9@r>U2nN$v~|#QfESDOBQO8)yPJQ?3NtVBBz&Jv~9U* zi#$eNQsgu8lcIp(LkeHRj}#s+4sDxD+g6aatq^TnVcNF$Y1@j>wiTsqD@NN^oVKk5 zZCgp&wo<fhrD@yB(6*JOZ7WCHR-U%{fLc|cRu!pLC2CcfT2-O0ifX9tr3P(VP1?0A zwW(DdYE_q7)HCXn4baeNM2f~n6H+uanvu<o7Gz7K6)9Sy4cZ#*$oA-9bR<P5bT+z> zU5##}=x%&SiXP}`^dd!XqYo+idg({o_7QDcf7;?>V*n`z8iPnN*cd{Jp~feq7-kG7 z#RxB-(iS6)QKW4&ZQB^ywz0HrpV79Bqy0I?8xzQh#w1cqHl~nbsxgfe(~TLVn2A}K zjW3KZ$vK#dd6;i3AjLvs5h)fMOGvTQSVoGkjOC<QVXP#@*TyPxHP#qw$#uqhasxJE z6TZP_e2Xpk4qNd(w&4f-i0#;cpRg0Vup4{uGk(Ed?8AN>z(E|sulNmzaRf(k499T- zCvgg=aRz5`4(D+J7jX%faRpa#4cBo4H*pKMjXR{cYuqEneLTQJJi_mIj3;=CXLybf zDfn28kO+m)2!pT)hwzAih=_#9h=QnyhUkcan23egh-1VhMLZ)uDH0e7Ns-7%Oo}8% zQc@%{l9M8Zk&+atjMSt^W27ZTIwL(PG8h?2kqMcR1zC{|*^vV|kqfzz2YHbX`B4Bq z@P!{daNwdK3ZXFGM-dc7F{3zH!YE0WLTRH6DaxXpQJ(w&6;KhCP}!(LimIq)R3~eo zrcsL&wNb~YOV%^$lMT?&Xhe#}Xks)an;Ff?7Dh`_v@%+gqK(m(6zz=mr08IDBt<8q zGby?lT}jc+=uV0cjUJ@viC*Z9KIn^n_z3;+F$Q2D24OIUU?@JpFw1c25%?4%G0HNU zT8uHqlAjsl$j^=O<OEE_Bx5oureG?jVLE1DCT3wazOZ~rJqL3!5A%%$<U%Ym7L!Yi zrQ|YvWh^Jv3Tm~IT76Bu%CeeTt)X6vby#m~AZ;6I+cwcw-%zW~)aqMmwT0UD9c{Ih zT76Hgwo$7esBJ&ewr!`ac2KLIsBJrGt6kJ;H??gKZQIYZZNJb~d#U$fzj1&R2aQ9d z_|@_owK`0#j!=uEmSfcFIJG)KElwJzNOhW8ouL+IjdP?pZ@ECNE>eq2#${4np%zyy z*QmvH;|8g2Qj1%b+tlKYahDYLjQgZ|K&>89t4Gx8cWU*RT0NmwPpQ>2YW192g-FTA zOyfP$7Lv9t6m1onT7{ujVX1B5XxqZmwnd<=B2ueJ)V9d9RTOGlRN5*UwJkbrTMXJN zCbcaVZCh;Gwm7s^Txu1MTE(ZfC7`VmQri;Iwk4*ml2F@{(zYd|ZA(tumV&k|C2f_8 zTBWA8rJ=3TQrpteR_Up28EC7F)G8CTEi-MEh1!;tw#r6r%TC*tgSIUvZIz4KmYcRM z4{eo~+Ln*DEkA8r0opbn+BRR>%8%OSp>1<$+g#eVg0yXgXsg21>V0ZegjyA)R>i1Q zacWh9T9u?$rKnYDYE_0>m8G_oqpiwQs}HDE1!`51T2-P}m8n$~YE_k5RijqbsZ|YX zRg>CQi?*swt?E##y41FMv{ij-)qvX8khW?>ZEH+hHKA5bsYNqOb86LsTC}vZq86=< zHl%24X-6&ETRKpSjz%X^bT+z>qN~x36y1#vNzudTNs3-ZZ&LN4R(+{OKjR}(^tXIW zEe03^Ni~RC4W?E@sMSzv^$E2aMy-ZZs}a=VQ)48lMp3KL)M^a18cQucvy7t_pBv*z zHGx`8G$xUgF$GgG%`%-@&7c-Djaj6cO|8D5R$o%v=FnDiscrLU+vd}@Eud{%NZYoE zwrw$O+Y;KgrL=9!XsfTNZOdufR?xPsq;30}wrv${wVGP3p;l|DZR=>O_0(zuwc1Fn zHc{KYp>5ktTYXEt#qu4s+Da|Hw``+UKTxY5skdW?@e{cdyDYn@)gJ1f@eB4E`$)0h za)A1vaftlY_>DYlIYO<DQmbRs;y6xNPExB=)TeO<XK@baaRC=`372sNS8)y3aRWDT z3%79xcX1E*@c<9;2*2Yop5Q5-;W<L2;&WSsL?|OPDZ&_GNfFKnPl^aeL{daDB9kJD z5tS6tjOe6@VZ<awEF(54;uvvB5zmNEiUdYNQY11GlOl<cloZK~<fKSpq$EWuBQ+_~ z7->n7&PY#+3`Ry$WHK_7B8!og6xodIq{w09Bt<SGH!1QMc}bDa$WMv_h7T!x4L?$N z42Kl1QIHgcjKZXN-zY+gqDC=N6gNtcqNGuZ6s3(aq$q2YBSm@R15#8lDw3j-QJEA~ zjH;xlW>hCd4WlM0Y8kajQOBrDih4$UQZz6clA@8(m=sNnrle?QG$%z1qa`U?8Ldgt z#%N25c1C+rbTB%SqLa~?6kUw2r08aJC&h<G4^s3rdXb{H(T5a$jeex~$mmaskBtGO z7-$S4#b9FyDTW%KkYboIoD?IBPf0P-7)6TF#u!qJH9jN7IOB6tj5j8bVxlpL6qAi9 zq?l?<BgJ%M1}SD5vq&-9_<|H)8goc7*O*6&`NjfLEHoC8VzIG=6iba|r1;8MPKp)A zN>Y4ntRlr~V+|?R8tX{0-q=8jjm9QYd}C}T#ka;5QhaA@CB^r~Hd6dx{78!J#tu^a zWb7oxE@L+-_832t;um8tDfSurNpZk9NQy(oucY|RI82Ho#!*rnGmewugmID-r;O92 zIAfe8#W~|VDJ~cnNpZ=zOo}VURZ?6tu9M=1ag!9cjN7ERW85XhJ>xzp9vBZv@yPg{ z6pxK3q<CsPBgJzgL~1_n<2@rJDMA^cNfE{fONwwtcv3_#B9bDK5t$TGjHslDW<)1N z3?n8fVj(u-ATHt|J`x}y5+N~?ASsd|IZ_}cQXw_cAT81%Ju)C8G9fdvAS<#VJ8~c= zav?YJATRPEKMKGHzVL$w4qOyOAr!{@D1xFWhT<rJk|>4JD1)*nhw}IU6;KhCP#INF z71dB3HBb|^P#bkn7xhpd4bTvc&=^h76wS~aEzlCJ&>C&f7VXd;9ncY-&>3CO72VJs zAEF0(q8ECj5Bj1XK0<$di~$&kK^Tl77>Z9Y48t)3pJF6NVKl~IEIz|He2(#$fQgud z$(Vwvn1<<?fti?v+4urqVh-kF9_C{K7Ge<=V+odG8NR}DtiVcqja68UHCT&vSdR_Z zh)wtgoAE8S;5%%^_t=IX@FTWk2Y$j%?80vB!O!>wd$AAuaR3K#2*2Vt9L5nG#W5Vm z37o_!oW>cP#W|eE1zf}>T*eh##Wh^V4cx>n+{PW;#Xa1|13bhd{Eo+Xf~R<f=LnI8 z_Ys6dD1=5Bghe=nM+8JfBt%9OL`5`2M-0S7EW}0}#6>*BM*<{7A|yr<Bt<eLM+&4w zDx^jlq(wTUM+Rg>CS*nyWJNY)M-JpfF62fY<V8N@M*;Z27k==-fs2ADgu-|qMNkyQ zP#h&t5~WZYWl$F7P#zzk0xF^sDx(Ujq8h5B25O=fYNHP7q8{p_0UDwa8lwrCq8XZ_ z1zMsNTB8lxq8-|!13ID;I-?7^q8qy7L-asT^g?g+L0|O4N9d1_F#rQG2!k;ML-7fQ zVK_$MQ;ftYjK&y@#b+3Y&oLeoFcFh58B;J7(=Z(~FcY&d8(-i{%)wmD!+b2jLM*~! zEWuJN!&g|26<CR{u?nlP25Yen>#@PuNQzDP#@I}XZ?Og68Cyy5J+|Qo{Ag?^#SZ+0 zo!Eul*n^+(3-)3k_TvB!;t+ntZ#ax2IErI9juSYEQ#g$?IE!;Qj|;enOSp_HxQc7W zbyD0gZj$1bahnu(jJu?`XWS>n1LGkn9vQ!r;<53B6i<z3q<C(GNXz>T-ZMgyB9sxD z6k&|8qzGq(Cq)D!A}Jynkx3B+Q4tN%5d$$13$YOgaS;#kkpKyi2#JvdNs$c6kpd}^ z3aOC>X^{@;kpUTz37L@vS&<FdkpnrA3%QX8d65tKQ2;*hg&#a{;G!T3p)lS@5fnu+ z6h{e^L@AU;8I(mil*b3CfQqPu%BX^>sD|pOftsj=+NguNsE7J!fQD#<#%O}3Xolu! zftF~6)@XyaXovRbfR5;d&gg=!=!Wk25IxWnz0ezd&=>vi5&Gj}48TAP!e9)+P<(=6 z7>*J66eBSTqcH|!@fpV9bBxCXOvEHi#uQA&G)%_~%)~6r#uxY!b1)b4FdqxB5R0%F zORyBn@D-M01y&kglVX*zniOk{wWL^QtS7|=V<Rax8Q+j%v+*q{wiw@$VyoqQYPF48 z{XngLq*mLh)edU)6Sdk&t#(nX-PCFiwfdP_{X(twQmcK`YCrV>9K<2~ir;V;M{pF! za2zLa5~pw)XK)tha2^+M5tncoS8x^Aa2+>r6Sr_1cW@W?a32rw5RdRX9^(m~;u)SJ zL^|H@5E7vf8etF?;Se4X5D}3O*@!}ls75qWL^ooPBBl|G6tRssq=;+8BSm~80Vxt1 ziAa&yNJ5IFMlw<)H&T!yrICshsf{$GNNc1cMS3FxDKZ+FNRipdLW-<LHd16aa*!gY zk&6_$jXb2tYvdzEexm>>d<<Vw_!%BjIEG7#f<_@y6gJ)`MG>PYDT*1zNl^kNQ3|C| z24ztW<?#V3pdu=vGOC~|s-Ze+peAaeHtL`*>Y+XwpdlKeF`A$$nxQ#bpe0(NHQJyp z+Mzu<pd&h=GrFKFx}iHhL=W^tFZ4zq^hG~>g#P##127PSFc?EH6rW%ihGPUi#Yl|8 zXpF&Fe1>uO9OE$o6EO*sF$GgG4bw3LGcgOZ@ddub9L&W$%*O&O#3C%l5-i0se1+v$ zftC0gtFRhtuommE9viR`oA3=b<6CUOci4*Wu?;`qM{LIq{Dhs@h27YLpYaR!VjuS7 z01o01e#LJ%j3YRTV>pfzIEhm@jWallb2yI+xQI)*j4QZ`Yq*XZxQSc1jXSuDd$^AW zc!)>%9gpz@Pw@=T5h6YBcL<442#qiZi*N{!2#APCh>R$RifD+A7>J2jh>bXii+G5S z1W1TPNQ@*%ieyNR6iA6wNR2c|i*!hj49JK~$c!w=ifqV^9LR}W$c;S6i+sqB0`P$^ z{NRBD7X?uWh4DU$peTx=I7*--N})8$pe)LvJU&1LR753IMio>=HB?6p)I=@RMjg~e zJ=8}7G(;mbMiVqeGc-pFv_vbkMjNz6JG4g!bVMg~Mi+ENH+08`=z*T-h2H3czUYUK z&>tUT00v?Z24e_@;u8$RaE!pG7>Q9BjWHOD&oB<3V>~8cA|_!nreG?jVLE1DCT3wa zzQC85gSnW8`B;F3ScJt`f~8o7udo~|uo7Qm6;@*n)?yvjV*@r~6TZP_e2Xpk4qNd( zwi!Q=;zwgUDRvk?kz%K@ixj(!J*4>A_=OaEjeVrpZyX@SLE{i9el>n0#bM(JDUKS) zNO9aaL5h>cDN>v^&XD4)agG${jSHl>Xj~%2W#bAdt{T@!aoxB<ikrqQQrtG~km9a! zj}-Tf2c&ptJR-&K#$!@EF`km*nem(yAu_!19w|Z^p-2(h2t$gnMmSQ0HzJTCA|fF& zq97`wAv$6pCSoBr;vg>KAwCiyArc`mk{~IPAvsbYB~l?Z(jYC;Aw4o6BQhZ~vLGw6 zAv<y)CvqV-@*pqrAwLSh2fpxw2M$~mL?IN$`zV5<D2C!Ffs!bN(kO$nD2MX+02NRX zl~5T~P!-is9W_uBwNM*%P#5)39}UnDjnEiP&=k$k94*iit<V~6&=&2`9v#pTozNLw z&=uX#9Ur0xdZHJ4qYwI`A3j2Ve2f7Yh(Q>PAsC8JFbu;n0-s_eMqxC@U@ShvIDC%r zn1G3xgvpqKshEc8n1Pv?h1vK5Ut$jCVjkvW0TyBr7GnvPVi~@|a;(5ge2rCDjWt+{ zby$xL*oaN|2AlCMw%|K##rN2TAMhi#V+Vf1PVB;N?7`3Y1$(g%`*8pVaR|TSHyp+h z9K|sl#|fOoDV)X`oW(hu#|2!(C0xc8T*Wn9#|_-XE!@T(+{HcI#{)dXBm9oXc!H;R zhUW;8k@p9LL@0zt7=%SQghvEKL?lE;6huWdL`Mw7L@dNc9K=OD#76=oL?R?c5+p@3 zBu5IQL@K048l*)!q(=s1L?&cL7Gy;>WJeC<L@wk;9^^$n<VOMcz!!e-z=4Z`D1^dz zA4O0U#ZVk2P!gq38f8!x<xn0UpaLqQ5-Ot#s-haIqXufC7HXpo>Y^U%qX8PC5gMZj znxYw+qXk-`6<VVW+M*rWqXRmk6FQ>{x}qDp<3sd7PxL}>^g&<r!$;_kk1+rPF$jY( z1Vix&hG95H;8TpmD2&D!jKyadhtDw{6EG2zFd0)Y71J;sGcXggFdJXsOU%Js%)@*v zz(Op-Vl2T@EW=k=julvmudxcNu?B0g4(qW28?g!BU^BkO7JP@T_#WHv1AfGI?7&ah ziCx%@J@^^FU@!JzKMvp^4&hh)hQm05qd11+IDwNmh0{2Lvp9$IxPXhegv+>stGI^i zxPhCvh1<A;ySRt@cz}m^gx~QPPw*7a@EjpB@%l$dghFV9L0E)Cctk)%L_%alK~zLT zbi_bR#6oPuL0rT`d?Y|ZBtl{&K~f|`a-={?q(W+>L0Y6kdSpOGWI|?SK~`i#cH}@# z<U(%bL0;rTeiVQYeBlQV9JnZmLMV*)Q3OR%48>6bB~c2cQ3hpE4(0IyDxe}Np)#tV zDypG6YM>@+p*HHEF6yB^8lWK>p)s1EDVm`<TA(Fbp*7l|E!v?yI-nyup)<OmE4raO zK12`nL@)G4AM`~(e1!h^7y~d6gD@CFFchC)7=~j6KE+6k!f1@aSbT<Y_#ERg0TVF^ zlQG4ZN{VU5bW+SPW|Cr-F`E=$7+;cNjxm=M^NjhVSYRw9#Uf)dDVAU<mf<Tb#|o^( z*I0$sScA1#hxOQijo5^5uo>TC3%<ive2;DT0Y73pcHk%M#4hZ{9{h}7u-Di}iv7j` zQXDi6k>Xe5H&Prnj*#N0af}qljT59eX`CX(Y2yqj&Kl=Pao)H<ii^f2Qd~B!km9Ow zjTG078>F~t+#<zo;|?kA8uv(X-*`ZZhsGmP{BArZ#S`NxDV`b6Nf9FR3-6I4q!Ee~ zp^Y%42y28RMR+3uDIyw?ND<kHLW-zHG*U!2Vvr)H5sMVDjX0!;Ys4c(d?NuV5*mp} zk=RH=iljy|QY1H0kRqj#iWI4hG^9vtq$5RoBLgWi8ktCu*~mhQtVT9cWH)k<BBzmy z6uFH&q{wUJBSn6r04aP7UsCuP9#S}lONxR<AyO1J-X}#7qbMng8O2Fa!YE0KQbuV~ zlrhSZqMT8l6dxEBNKw(KM2gBr6;f0+s*$3)QG*mUjasCrZPXz}U85c;>KhG6(GZQ$ z7){U=&Cnbz&=RfC8g0-P?a&?_&=H-`8C}p7-OwE$q6d1S7kZ-)`l25`LVtXW0T_ru z7>pqpicc^M!!ZJ%VkAakG{#^oKEpVCj`5g)iI{}Rn1ZR8hJ3sQh@>X9{kqigny(xG zS8UgPYsx;P&TY;``vdCxv&W-rCko<q)A8OJl;a4>937+Az+TthX7~RmYdt1SITpQ^ zn!3$9b^DthzpkV6yxZFUu2R<5XHnL)+q&<d=If3r59{ZJjI(R+d5Nv<b}i%Vwq5HQ zcAs5)&-HHW@o4JYca?g4?<(~={+ac>*YIu!b?tzzQBHFY1KK9n_+9kd`}lX(a_sTV zImmwPTDIB8qT94z(k5f2t>d(<8PGQA)9pb?850;?OYez{3u<le+k1|^&EB`}?{%qj zbey)|Me3T~8I-k?m}_aLUCSDFTWY&)Z`ay;yB>$m_1>;+9rwD_@d2gX_o`a9*<Q6z zT_><H_Bz4!zh2k>=IfEwJVV~;ea^4juH%C`PR9r5U-PVa-v@1bUvKT#)a~AF?GMhs z=6(fV*Wl|K&@&((uccpJk2dc<@3uYmRdrD2=@?B}PwQOfxZWiH%v{;G_r6|re)cxq zucmz-_Bij_dw*}*mi2Uwy|(sA>M=<MMPO^%>uYVVt$p5UAB${z)3*0|L2bY3eq_AP z3F<zAI!>=sP{s%K7<61vQ}(T6?b`0s<Fos;ei!*BYslDlLC-ayeZT4Yx|Zg<So2Mf z;h#L-zHaul`#YYK9_#DgGiBVX#_0B-=Bw6v*W3P%*FE@{-p%{of75lee@>y_r}pl9 zRoi=;tl{1Fy0-V6SB=+gnt{!I-S*eb)A?_jfvx*j^=IRH%g>$uUHPhg$u_0OV~^Ks z`Bz<wceQ>%=b(MBOFeJz%+9rW6Z{iHA>^M0vFFH|c3W!xsqGLlR_f%Ce~M7kyOy@y zr)%-g0{GAO-k)x_Goa(r?Rp&APG;7Xwj8JSOX@bs<Yrr7wT_o@_86U~>*_W+N3HF- zc5Pn=9c%Z=+OKNca{{XaTjO=(?d`gTo}*qzJEb;%;v7Q$^iOL|>(69DXss!~8YaxI z$iB=h^zkbrA?%b|pA}8>PuKY0TkW%-5q+lg*|4|CaSPq1ZAm#_ZQI+mw%4(1`*;GY z?eTW)eJrv~k3(v?o^suEoV2A5EOn0VL*~kLw%bzMYX-DG9b?avb@cqCmU|^_dwsi> zb-m|n+j}j!kFuV3>i%?JdcU<__Mx?m38<~tOP^D{meRJj1y<`bZEx2;`#RazT58=U ze+nYC%#nT}ecox0*Xyd+NzP4PGcrcE*|oh*)|Gjh0ln6A4cVsGTwiOlub|ZSJo_Hl zwf8!D-Q?J`{<G<Q9p#+7`-0k*>lV=U3anq&4Q!iUM@{>B*|l!>&Va_~Gi+x-&yt*j zl6&C2wtQSy@|w|)^MUp07~QVp<>Q9dy3M=KyRGAsGxt>=@BS{^<rtM*2Yp`knUd=) z*I1u>8KbXFsrCKFu4N6GukR^3UY{qOqvLdKdDi4!dXLxbvQ3Xs*YJLylexMdsdXQE zKC%y4Pu7xid)2<)=Jl=nk+rqf^nNW#zxLU+KF@Nl`ngL$wLWW-I!@ExCUdndbwFz+ z_Znl5_kPCh`7%$}lzXDJJtnZ)UN^8YdK~gKjtcDSlAwMaBx}mo9lDOD^y@Y|z5Bhl z$y#=wwgc<a^#V(s|E^N^qw8rqIA7ei;Op?ebshBet{If~4IQf)lsVpG{%+5i9N(J= z^@ihvvbL_NsdKa)Sn9a9O<nhO^L3nezG_}j$Lcs)%dP`k`)z*@I<WQLreBX!Q~#bo z+uo_$HQ#2RZ!^dHIAjg&3rekH1IxgUNq*lru=^yx*Q?v@TGz7s>{_<lZMzO=uJ?HF zed_!-P2HDfVCSjZ?R=B5_B^R|uBP{P@3#KVx}0}lwVwOywg)s$`(BrUt^HT`%W>&G zG^Nk(x35iLV|0!^PseJ$YMYLERm!%&$lCUCzDce73~Ww7`+VDT323di?bBn><G1rw zYlbw}QB%fBt?hvFRoivGomvO9mTY?yfvxdp`t^J?13DgEKcH>i?<0Y=<#RyU7M#J? zA)x0#pBw$$LE2gemiC;4=K0dTSEa6}W4zn1>zD01C#dPYW?=Jl-0M>3zs<1(G*|bh z+cdTRRjFe&b*#1}_5OI*GS<5<u(5&l>;C>OspqZdW~Y6O-sf$Pv$xrE0;+X?Z<_(F zY4-)R?yK%aK;vb-|MvbIoMW)yYY_Yl1V00>dIsY0J`pVV8U#NB@8%hZ%j+pv@HP0e z&%mqRvxBz<e@y?oJOjZWH{Q+14f{Ig<6}s$;A;^43<N&||E_1i`}<-4uKfn@C+N?( z{A|&i{CrgU0!#1lcH4W-tJcx6I$ztGuj;qQXziUkUsJbxx3%9pb)2Sdm$ufLI!06b z14|tjSOzvv`(>Win!1*@H3RDpZ2RlR>pabXjzzZx=c`{!|4Y~BUA-^MHPhew`K#-o z9P?j&4F5~(>$(0nrF|}TEzj`l+6?jkPoH;b*!7F8|JoPOcJFyQCMeJMpBW?jmHF~t zP*aah=Gb*m=X;N{*RX3HXZO8nt!rrNd}+T6`h3V*!S#!4`cJqHdW`=oDZe|X=Ngn+ z$1?5ZfBM>y4!hO?cAs5)kGHqIi`U?*){uS6cKI);>3w|m+*fUT-TL<2zoNGH|E_<} zQP#HU-v;P@ber^RpZ6H;*Rk5xl>WeKoujGa-gWBwc6#qawt1hYjtOYq>&Dw_d5;Zj zJ?Yndde8S>L&w=`*>ynk?d^Z2)_rUKnYCUw_dTvju)pUukbCz}y*Kjuc-^rFG$x?F z*RAt5+jT#h_8Qu!DciKx)bVyZu-cxlwZ1O3Ew6R0^}fq`_IrSCx5w)Cz_!`_x~}y7 z6Y2H+tJ1z!dVStxUwVB5n&W-HbzcFc?mIaDna^qPeG9&C!OuYOGZ6d?1V018&%i(P z8Swr+kJq*J^E>a9&jqDVQa@MMF}kLX(YE(?yWg&LoSnM;&!)Ym*4}GsznwD1J|C@h zjJ;j^Bz0}=v&Y%By<Ka~fX3;zze@(cAN(`l58md!$+I8OJnw$*c0hC9RiF31wC$a` zzt{E4I31(4yw<eVwEOh6sM|DO)vseD|7rC4{MBh+qoC}|z9#|A{ij{$;N$)0y*7gH zS@1pkyFCMZhzb5L_zL{#E1;jx1n0m09z^i<2)-Wg;u(<N$<p7`4@w=-SnYdP`6kEV zy-$0t_crhLn~e3I``^|M=vvr)cI|!c0d2GU?Am*-wB`TVE5G*_)LO^>RcRkjQ1|gB zbKYcZQ1|~=kF$?Cu=;I|LI3^5ze~!q8ql$5zh*#Vg8Kr#cHY;;zJ>|7-ob*e!QcHE z@P3Aa+d+G+2VbY)>lDy4V1En<XnSy9@N*N;GZ4#sex@m7f>H;xmUo}5^DgKy>2Z0l zsoOPmyS4*M9VaOtFW)3}?wic>J`P<YuncUxcfWUA*3&*++xs}*wqNJz`aww<W3!J> zkIQ>qZNF*idV%Get{2$&z}DCPz~=qC`~S@G*mJcGEakj(TVUs?+h3P~ttIpR3ikf~ ziuM1~YwG#^Cyzsq;cfFjdF<Z%)^iBz_t)(2@96h*0_xLk|FpEvB`Ebj?fm}g;|<C+ zv&a0^$Mf%6-#(`|t^Zxe7`&f9ex4Q3&l-ZSPw@2#elGs_dD}nn^&r2a?*0E^k@K*B z9<F1&`(=!7dsXedEugk{pS`YZ3v9cN^G<ubZqwrrtgZcjHea`&|Ml(my?L8j<|w^a zfnC#}t{<B<<#nJbwcXbKz|tOT*E-&NJ@2+X&aU<R0!vvZux;M``tQ|f|LfX1PLC(B z)Nw&g?|bDv&wKmZw&i%0-jl%2;Z6E=O?!^rXZP!V|Ekpe>iYJ+b=!Yq#xeIcu>4P+ zb705xckTaoUaMC<r@Bp3j?1pSkJI~l%69G3vD()39%J|0+wA_=)w=yZoqGIo9B(Q- zb0P#XFD(7CUDgbPa8|ymmTfXe*Nte}uRFF^9g7}^t`XW=Q;t*nC3Tym9JlrbRKISU zuIoKl&r$c`-S%Erub=eWwfB5`TTp86`QGio)_B`--t)ZM_WtzR>HP^TBXLb4oBI@4 zt=pq8E~*(DSgqTmn{m;|fNJfFX~t>BpdC=H&#|UF-&$+h&#*rK`s~`<>}#Rh?LN77 z0k!S1THEW|wS9bn)%JM1mVHZGkHfo``y|^W^*CjW)Vl3ewT#tqQp@ql{nTeh`lK!W zTFW-Ow%d9fvOS<RWF2`9bep#2zR4VI>zdNGYwx)-NBU%(tfAYbmgh(223G4F9j9%X zqqX-o@3xH9>#MH~y`Iu9$LGEMb#0k%ucfv3JXu@smDYOx+SY3q*lX18mpQU;UDJD; z-InX4`;vX=J&@}o>jbu4Uh6VeU-Po2-L}_~b?j}rrq0#-s_zkR+m?NL&-K3l-rKb; zb7idFGre}&mhFFaZQqyI)q3q-H%^W_urc;Mc~`aUE3mcXnbLb~*Ln{E+7{GtuUf;t zZ~7Xv`|RtZAM5Nsz1H4oA6r1juAfK#RVkk<=-PIzect)1G4|&fe`T#}Ys&NaCUrn# zwNKMtQ~TueN#*@o4(ML%{nYmlnWOKAQtQVAT}#?JM&IA1t$nf&S<7zAGbnB8m)DFu z!`jyOOx?dcYqCw}=>BzI`drIA*_W)R`;s}*CvE#&r7h!RAG*G_WgUG@$vFEs^xEia zNY~c3j1R2V{p)K<+up|}$Dw2FTE@SsZNDaEP5pe@yVlo+{hA1DtjrZUN87I(Z_kmj z(zfSFTb@r{PoE+0arPYVTIYKA>$-Bxe+R)o-}-0&d@K0=1>e6syq5$&2f@!l@N*FS zI{2r(59H*%E7*U}HITp63ijV~4gT)0&A<Dz_IJO2fgRu9{ks0Uk54|X%04yi+U|Q* z|LeBN_WvY3kN?FC>~#>_|KIbu$v^d8%Ii^%{Xd=h^`#ukKdJtw-uIv$_ka4i2;To+ z`})-11rN?YelI@wS_EH<;AbHC8TfC02K4`56Pz!e^Wf|7uh+r;cW3_U`tSB{#s?oy z@c+jk_!$U(27;e~;AbHC83=v`{wdEuT)ubucO&1w)9>g09g@TOTmAQUyFS6k^Y?mQ zgYQT1{rD^2H*@fA_`fDZh<>h^)@Pb0OZL|Owf4O#R~>8Tj0s=FZ9VIpvm<MiAkTZ% zns2(TLFv1m&$>2nyGD-bw|jMO|6^FU_qj7CNgf}`P;n1A&pXF<6SaNrlsXr~SCU)I zIPv1V-!_MiIpD0%8^@hGBdO<poUX53uWg3Do)%HsyE)c>;xwP-<K|s_*=aIA;%n!< zI6ggQ&HsPwBe!&MYL6`JzuwO~cRCX$CV07a?DNGu(?)lC*?!w|ewXv~xzXz=Yj0e1 z$<usC!<W}ow`uAe9rvck<Nb{5J$ci0f;!%Q7G+Mr&*6)Es^_N9g}%P@d3oJFljpwV zES_-2*|l@0Cq&2l&aRpVU)2BqIp;Od&%6#KU)Jutd@DV1ZtwNq7H4(nd=H-K>*dAs zwtf6jPo%>?I(!Y_exK>2C-S`?{A)S3%<&(4?iKh}*LBO4spK54@wxNtxvmkym3emi zkJq9;*KeCIj_-BXD5%@}Jdf(6C|LVXy<WW6@NNh7SoE5WPSx7&e`cCT+R3Nh%;)>$ zkL#+}vHtyvZr`-I%{}=4*RrdR>&71Tk&|v-cemW*%YIwJ^>Rl=>*J^MbB=H2b}TmA zv%iX;+jCr0&j+DeIc3Lu=(bNkKVSCYyZriOtmpn*H?&{D<o7)n+NO4!70%;4ey@Q4 z{<_pC>G@^<d1uksU;S11Dv5vp?)nWp=k}d(N~}8XWSg?viC!y?fB%LpL;dzQdf+tg z5yOqU*>y@*?Lq&G`&hYkGf(ZW209~_Wpy)t5Z}2wX0P+G$SJ2-fxhlHqa*t6o7Ub( z#wIx8`b7A-uN!|{Ten!XVIG|?*|cd>*Z;LZ-E(ke&xHo7opFN_xJggubGN#qUhd0Y z|Hb@*a^IaY2m81s4}a#X*FWN+*-p>cS>0B1le!td+Tx75Ti+c}>*2rb)84<-X|g?Y zM20pOeIrzO=7?{59`ZeRq=(z<aTve+k>2;a7_*i;vc(h6jVBBJu3U-eUXFFfxi`2W z_oSa&FGmwM=ghsH6%X$EgijpXEf(*fv!_aRU)gqTZEt75X#Zn<`J7IgIMK<KE0;TR z%ROgJ(lGw#-`xK?l;ORg4E<d^hi12bIlgM?%1)+hrCzqZkN<7jS1aUq241P)=59RE zIbSx{%M99DFRr~_^A~eo^o0oVA|v1L>#i=7tbnc;l6&>+xyw0(@E7W3yPyAgo$A-Y z?@57P?yUmf`Q<qOVF2g)V&0?YeVvf(<5ZI=em^Jf8Nj#~>*;<qZ?W&B{_mmkK3Y)b zX$G|p^1gJR!5Q$q_+Py)eUJ2YD~65fv-eqFw|=Ve`HDU4>uyc^AiwwZm{FvG`|R*N zPse_Z-A+%A1p3|;_VcRl`MGHv9q+wPaQol${H@r~*X=TCkk5wR4cufg?|PDCDdB!n zy57r=U3wpMocH!RrCPd47cUO<KI{D8{P*0?;OqRqd7ZsKXR)7y(Ba4AZ~wUO%g+Jo z7MbMfygKOLhtaiqG@k5tH1(@LZ&^08uUlo>2A}u*`Z>=}$>&Tj?#JT$ecZ3-5AdBc zx0l;LZdJcNH;TET3O9Dv7pUjPPY}xg^CJ2DNWON{&&?#49ZusXpL^Av)x~+_*TnUW ze~|Z@5Ul&+>pU4VB2yFh^VtVII#;*r=SuQ9m#nSF5|q^Q2-l&f8|TDm|Id|QfBr9y zYx*~h-Eg4}dnOKU<QDkujCEWE<$An4$5@ftxy|Pe_OzSCdvMC1{J-9)&d1jTBlhvD za4)W#WT^1H-SE#neih>Pb-!HF%-8$c+G7K%2R!fV7TNKLe?s|>H3O^lS&3eyW$q`; z^B$+?w&hVv_d$+%|L<Ptwby%fwP0&^?!&1s$9b<8)VA(#c;X)Jl(rjqCSE)zx<5_b z-vOT<Zly2R_}{mn?&D3y1$KSB*VuBhx7%S)xYr(so>#kx`P@{yMmhRy=<}fGW8X`= z*8SMek{*k$A#Gh>_ouH*eI4rSQ~UM0j*Ae}J$Utqqpw>XCu@2?pW4=A*5_7_=g+3k z`JJ8ujhgyDoAULyejP6PrfUZ@KcK!hUH5-wygnCyobQYGz(3lrf6w_ljg7XWuUmI( zHUIbGfR0N)Pu9<S_3Iq{yjZ`U(XVd;S|hmcpY==x->-LnzcyYS;S5T9){)ff8*AAx z=g9Pnj->PrOx?uU)Fz65O52`e*E-+3?{)3ht!dA%RQRN4)q_Uv%J{$d=jn;JeS7)r z^{k<<Q16qzy1jVG-~6{9PF~Nq^NAz=^?_QEeLwCt+|w?9WB0+(RG#Ebdw8xEZ0x2V zR>-6C-ZuAMOXw*!tF<e6tb1n9+4e16$ty9ld1fbR=}JzYnAEc?b8A=9uI(|;SJ&}` zDB0MR?6<A9CwsHTuH>k!B|X^=H+3ajL@ea_`gk)}@>HC9Ztr=aoQBEvdt&u!;zm4_ z%JD?3=GJdo#{H;iIVVHykq+Odbz?6n?k*|bAkemN>qPFbblc^7$Nt|xZh0=In<>v> zM^pRdURAA9%bl|zrvJ~J0{fV+AG>9|)`>DFc5YwF;YzmuHn~$`dNx<me!jNvtm{mk z7~Pe$$241C)G3oPi7OfDN*kwV#0air%3K+pcIPv?lIdH`aV|Gc<i?9U%(HLgaR0jT zhqpaL!p-upM@^dIX>)a`fBih{Q%~lsCH-qjyVmD8MxAY*y1ARZ(dRPbBJ^@MPwMSA zd_`|JRFYVJ3;XqOzqq{gwV!wDJ~f9<N$Z<vP<FpE<9of_|2MS<_!fK6=Ve>Q9xVQo z@8@%J`5l_n({0xxv+wvyeci}wtNZNT{^DzfDLaxC2*vl&bzMpCzO>Prd7_T&;O2M~ zrofB`|2o#5C-u&XxBWIJURmH=)$aeYrff?)qnLBQTDh0~1=fZ2i+AqD&+2nT@8CXu z()Q)|r}E71=QLg7x|fSYar0$4?ey{N^=;Cwf_q|19KRyxvpd=Ahj)|S`N4^rQ@&>D z=XU<`uBT$F25yF;>zvldQu^=Xh+hb|<RJOk*o*hYS&0t%gniP(9gt+K-|}R6e3z_` z?@9Ab7q@e|0Z#WG1>7A4KJ{CFv4r2RKXr7AhEL%c&DSn`f#*hhuee`%r<L0%%Lq@U ztWTYT&EIo7L<r#~z4qMc&(~gs?mx+!hH<MHUnNcmx9WlC&e&-ke2$0e?9P1b>lu|` zzHgU^&D`%2ZuHpwI`+o($Ig)OA>F3m-gU}O591~)a>w`dvc~R;B0qWJ4qfFt;cOFk zNyqO!eKXy53SJHy;PL1=w#-)3Nz=Kc+bm>nH%3$U<#TnnM$>!=&DV*?21n0(lzRE( z_X?cnem*W9)~DU^7x(pttSNmuAL{FtOS{bH+T1_x^?+(CbN|kqs9z=U`RunB{mFYq z@EzE-uRHHq7T=H+U-aFKT*fW5v%C}TgGlbJdY7D^A};ouer20;I7K{n>gdL9+)hV4 zLpFWqsa<}))Bj{lH^=o=&cz|A-6Xeay2E^9JF|RJx-+`e^ozcFrT=|v*r1TRs*SG` zIajZj&qk_6J=~=|7x<ss(P!=4Q|=zWMjhjOQZISvSMGQ*H&Tb9&e%nf-7Ssxc;@d~ z?p&Ty*;8{5-=o-d#<?(KhSM|rDBoTqv%0?Bk9w{bPvpj_IL4Wf`l{1zN@gefh>cFz zTa%ovx!-fomMZF8Xqv#iow&c#FJoLMWqH?Ww5pg}yiPpN`8pX~C-!Wo#q(KyOUqn$ zLY-~o={Eb0Q)y92-vrT~I6E$XoWJtj_uNMlA3LFPg>*-!dgA1}{+|2Zt%pv(!J*tS zQ|>#Hcg!kKXKHA-!NV}_7j@%0y_ZjN?j1bs*XevR*Ap>io^ZJ~J1f4-;!axm#lP&k z&i7$F(=x?&YaA@(DgX5nr`6L`ZpJWcoLn7~x?Rtg@?>8!--)(Abb(skGP$Wrl=93N zG017UV65NHgr(d)pH*|>pA78@S*xh~d##fHa<1v8G;zul5A9~Wp3Rf6bRFmXwTOP1 z+T?M4caL&r^(*IY$~e>~*_9&B<lH^nd9By_-CEw+z4>!)&!CXq-Ly-e`}H03so(Y3 z&D^UiW_x_MUGq)x!>7)f&3XUjI#<tB#dEVq6*pD=OP-ZScjQ0oepKMv@Sg74cpv&5 zi}%zgR=mN^!nS_yh>zFi|0PFBcW>tc&Z=u?{5;#{`L5dC!AUv%eK+5h!g+g?h~_-- ztL2uz+TM5T#+H676Sa41jC<d+KhGm4Zj(^1XTl-Bi4B^%S)+{iRG#_Fsk$_T+p*MI z=ZBi9+<qZjI4kQFbcf$t=r^$berMyJIBxv}qdf%<wQ<i>T9LnNrvc8n`uF^tM0wrM zX2*4ZU9;DT5;nGb;m#pv;)3Mv?gg8iEpxkj5_M_sZWyyS@2|z@I<aeKcDJ>w?#|d4 z&zZ9R8{exf!}uf}H{Y-A&`r*awu#&-lNuH1e{rkl^v6xy+AS~oMxPnNnI6^0`RQ~n z&xJT?-G?LN`?YBl-ksC=vNL>bIQPQvo6g0-5!~!IuR6(3PxN#j(aK$xa<cD`=gEAd zM}N;fIsJ*VC+aij=<mNfBX`vG8$ac#Q=racC&RY-epAn-_PbIhl>5xN>nzF>&7J$% zDJNdZh;HKZmz||w5B8Z>Fs|Q{wh`S~?aw>AGL7<!`{Q%xTE9C^zv$O|Yvw8C*LiIi zx2^AW=Rn_ZZn~#8opcR%=JOkv*!k*sb+<<BInKU&ncYG4BD!}9UU7<Sn&BLuk<HyW zHIh4M>qY0gkP+M-zh846ex1(gAG4}^VV$q1Vv)}7gdgH~2G8#57V46~?GtC0Q}I+9 z_eT7cPTn=63k;c9%9&Q9touvOxz2>9ncZ8@M?2v|<a2ipP3Shiy2D9(Gmi7%<C<=% z-K#u#)3$Jv%{uMbu&|N4U|2YJ(Z!q2iQ*C5_uF4{23^kJ)E!vGJyCOlGiq-xw?XH5 z&d=Xxau<h;<bL`4CFlIjqP}U;4RU&=^>b6ZO`N>Tin$9SMsccatnJS3b>7oDdn0$i zxwy{sVl~~v%}e?9DjU(=662gxV0=TLp+myCvwGijQuTVzc`&1%yD9rbXJ)fpu9IVp z)9^wnxB9IKeqq-{a*u~N;aq>et`nwR3IC5lW1e>PDYT`p+dXY>-`_&Mc#ph%q=V1U z@A|sGtytzeaoWFryq5Rz7!ktxKIq=pJs5AD?=Qpt*nYEO6SsHs1D^g-D!Y%iXY+r5 zoEyEN`+biao~NzLx{=D1a^ihe#hv4u;pN9XS+BXLqFXOwKIhK5;m*7XiQIeTZoYgk zozks`)9Ae@?r;4o_|K_*FOy%M<+<D|zGMB{4WIbBe&L2VZLSV<c0};FDKdWS+-T{z zt;&veO4rEeCXYJRx!FC(%UoJyp);>eM)z9BDb6R`a=1FLtM6&QG}pVkA)Ei=x4H9& zZkD}+ol9~3+)k-NdbS_y=6Wh5@?0&|)lKzV5l`FYo!mXMhIr;&Y5TIhdEp!<`GU;u zfZM}8%Nn$G`xZ~^8RFaZ<$8lYs^c^B#~0UEKNd>r$36RFob=o8_x5}ItKQf3J>2{K z+WY<3`+e8@ebxIt(EEMPes8nis{(po@_x_peqVXh*SGiUH=x(4z8<|_clPVcem}Ec z4}Ob_y0IG!_6(hr#wk%el$-M61LywSBEI8`4EC(tUdjEj&0+s%v)QAKPT5c?+=WBu zIvIU4yQjB!Tu+YyPM-ed+>8&3IuB~)bYqm5{PH<Zas0mXP2{^yocZZJD>8iVgxplY z^J}mD`Dd4i?*BT>xMEnoi+s;s?){ng-}rvsgx~LI-`&yI#>hpJoi!P9y7uRc`ni-o zPr0i!b?)V=@2sv9)wTDhbM19yPMmbE$H_m!H|d>@Za~MR>o%@a)G1dXi7VMH{tzd| zo*Vut+wHGA0;~1wC-1LKWqzZ6eccN_&wcW*Yv~rry5QyO-pSC%eNg|3|L+f7YTeg8 z884Q9-EdAHH`AU)zE5uTapQ#??E6L3`tI>hp8L=Hb!=R>!moRso+Y}u6}m@yxt5+s zK&fAU>erk4^^Si1qhAl{*NpmgrhZ+iUzcj?K6IS6gY(^g?<e@0{xhzrzV7Ysa|QN2 zEgh>F*!Q9W`<|2ieWri<^Ko-V9KT-kUwr@JU7bshpTavSchzy97HjAkb)<v;#~WF@ z#-U+;#b)+&N38nPS@%VLcX{}T&c5Dt+<U%ToG_=8z8v?q#}U84N4_JU{_(kDVC!@^ zygJ_~J`VO<QQa@+)Lw45vupiMX7BOJ{STee%sCdn7-K>h0lzLfjV$e?N?g{g_3E*5 zeB+$!o-FwrzH;AzoyWWC*XyRwg8n^$wspIv{*8x@dsoNtx^?tE+0T_eYcf}#E2-^g zN}n^mhkD=j{PcMUZ2w0hop)|;=IccHTLRYhBA<Uj?zQC0+JD^CqlY~QN^IwMMnbsL zV}vR&<%a$)KtDHXoy(q$&A<1bYyT~QuJ4=<=bVVT;pN{HENalmNnid`)7EF}&*s0L z&zn4tqdUZPrZlSQeLaHI*14K`&Vl8?>hbwGX9)M;isw#($nyK(A>0`^9y(<PuJJh* zs<j*W`4sNWi))cE-Vonr*IjpMm|jko1Tp-_=IZv?+@lb#{+@s7?P2`lZtm*Nj(^TC z+WboHceQf79HVP#>fZunKeN}9rCfG*Rh24E)5k0Qd~<Yms~y|w_ha-Po<)%=yG16Q z_N+Pbp%Xe~eAhE2jZ=KlZ~o4fOW-6dvc>=RYaX@T<Mb%9&p8$LoKw0*G-vtIUH-?u zZ^%yP%tt+)E|tQ&C9*eiDhzGm-+yTLX?d>PucJP6<~$6=_0@a+;@-vDQ{I#K=Z<cJ zouz%^uV3wSNtycP-va3M)X$H#EvY~E(BEPDV}1T!;N)uGf}{Gl@1Oj_^Po{Hxu+aM z!I%3kRj07CxOsUuL5J;5C%%8EKjX01_pT!qeC7z>$0vLj)qm!QN(=V*j?X#BbD~{q zcUh;LepfbEcMc>k>gGN^&TnM$%TC6L;oLs6tN4GPv-{4X&YhIy+;AuM`BbcW%BeFv zs=MRE628AoFYIpW*Tw%D+55~;I~qUFIpzO%VDk51FMjubr$;l{z*hV$Xg1ea&a0oZ zDsBU}e5nVtUtHIBk@9y2@^c|st7A<5o}~3$kLK&w4`HtNi{txaym!C%cD+}cI=-Kr zr@x$I!+Lgo-tA>u`}Oz!y`M4N{^~5q-!sYYuDv)O{ab`T`d;+2h8gpJ?0t7w70J>! z2!e<N6;Kf*2`ZxGbk1}YDvB5|fDsiH%mEce3<weoAeeIkQ89oC#K4&W6K2eqFk--j zm@uJyGe<@nR(JQlyZ7$B-@_mMRCRTAb#?WxyJybK>G^ry@u54U<@|U?^80Om>(5`; zQ7Dh~H!98vF%CP%e1T@3im1$dgs+2?up$3{qt}W*-s=<f{wn>|yJCOU?*D3iaU4V{ z_M>wCkK|&xNX79J$5V{EC>O_Dl#BRk8<g(S@6)&6P|kFG2l{=hqvFRH2#b{9{gEx9 z{SY7i-&Ffy|6Q~1bL-9Rbxe4JC})KlzyCg}*hWtM*Rb}D%J=$K_j{4sGben{i+W;T ze&p%7@D0Z|6<0~WoSuQT=FE|>nS$Tn<T~}EB@@{&?57_iJ^hTnX8u-wDsdXb)oX<- z?{+5dO@i>uTMMQ|z@NWQ7}j#NbmPfycD-8Vl04_3I5)i?+3zp`<L?v`%?E?fu(dh4 zvwafQKex#F27f(n+$DjT{bed{J+X|*^!yg9<J%0G9&>-R+oW1LQ|vbt`!7&+x&P(2 zzjgjB7MZPm$(4>1Fpqy`v@z+&n&*=JUK*x715?UA!Iqi{j6iRylt7<FMns@utkTTC zfbU`_MxYTlKftZ|4;X>g(JF&FMdPFb4PWsEtnW5p1o|oUGvvF)Fao{(G#eJi82x1I z=&}0G@-&8rcXX0wc>cfz9X~oQVywjRp!-PI`58ap$~D)A5BO*9l`tsASEQmZB4$PT z&ur2%5icS(=<%Y*MH~wee{XtegVIx9Y+teo@|9bB$6wgh5~i(Z$oIM7w9Afha|}gs z&NSS%NV@&T3=}cG(#?+f;uQLQuB=+Th{UCiL2(Y94C@1$37+5E5!)5l4RIY2+ZE@F z*sh3Qv0V|zV!PtJ65AEmA+g=c>k%EhD*it^_p0Ju74IqxRAHbB163HP!ax-UsxVN6 zfhr7CVW0{FRT!wkKoti5yD*?2|GilJ{qDcZw<@gsd_2C5*^l2&E9ZYNZf?Tw)Zd@q zeY0P={?Bv-o0ath*{|eo<?Z~eT%p{SP(~*=s*WI6_=7~(6?iwQe&xEAbt{)w&R5p2 zoOdg4OQZ^wd=>O7mkBZ<DU>I%ys}&@7pYk8Ce-K0PRxttzoNAMuXL*9KgOdf7C*2R zUXIoO8@*P;0y-6?5#g*Gr8A1~d046Z9Som3ZQwvgket7>sT0f{-dWB!?2mB1?MylE zt7!yY1&8E3KQ_WMy7KkvSNtFQIR4{)Fx1c#Y+=UUcv!Mzu$=#}?gkh|E#=!%KvkDV zkcD1yUj6kgxavGde)gzrV;0QGkhhIdJEP%4!bEx9^0_GIX?cK!DvllM&%eVJ4v8*# z;CFm0uM-X>Cr!|2*DKzBIFv4GiAKZa=Xb)G-Yszj6DOD7Z)J=xi@(VE!0Uyu&|<l~ zu7W}~PlXf?v^?`oZS47QOZk70AHmR}-`-*KUgn5h+}g<H_IKOkI@{;u9RF^cp0+1O z?s-atcZFVAJK@#qZgQPlPZY84#}mJ?L(7F2(P@H?2^wByp~esi7CXkmyI5zeSGWMo zW;a0Dt24Z>74^mZ-bhVc_Ca{x>03F@bi{}+OW<XxC$_EC8<JbMMgMmrLFU>N=g!;t zT~E{(=~$PJ*shT`H1%wWJI5r!Hkba`(@-6ZU;AO0vjW@+^~Q)AcCZXw@p42Q9Gj_& zlS(f`=Tu!By6N)wJRehZx)+9Bx|hh$*qrk^45!5Pa^00M1Ggmaly++}6(8wlGV5<n z#%k@Vkv_F%;KfTHrD9&FU;e*vShcc21zsroGv$9)N3{2MQt?0S|04ZOU;oAWVw^<! zNA`YI{%7Q38zPn0`MYA+;e8nqQj2PCc)hI=cuf4ZcJ(oqfa}&+a+H_nb#aGLi-wU0 z6Wnk>4_oLIHiu-dYK=)vHK9<8B{wd)qxyiiL`b29tt;@+nO}*JjJmmD|G?Q$oH-VH zu2jGc=XXMSQzMA%tbo2(&cjZJeT3V=zk_=1I@E1Ble~OU4P%}ihyC%ZNWlIYI45Q! zY_F*RwfAda`-S6RaM~Ei8_U0kNb&Ij(?CcEI#<Kfn@+%#Eqg$=I|_<hmqJ<DbkHWz zP++Bp*%`Ir=BXIaNHD}@$9Iylvnyb?EkCbrZz9U(DbR1DGTzZwg6qxp!t+CC;h5c0 z@KRq}fxj^?6NKdTXpVf{64x$mPc=-H9F(s`opYLFK=?>GKVFBAqelZdpMTN~ttRNn zdAG+ca7F1L5Z1S|8XrI*>#|%<^MY;BzPNsfbhon}u3c~m0&lfM)3zJn(Qzwu7`GXW z3bgUC>+N5zKVtpaR@L#<=65i^pc&qGNrBj@fX`}1!pK1qY(Zk7^ll@p0f&ESXM6L; zxP8k$c<}+TiDoz`Ozn<e>p6ki${u)gbu*|_+#dH~Ke#{G8W~9<6z6N8ak~fK>7bPw zh-V+bBa1MUHRvNf$G?Yhecp9fpQmA{<e%yqG9V1^%{GxfSh3zAtjlzCF&fQWt^dp= zaqA@PU)-2PR?~OsSU3UC_;jnlKb$oU1I*^j-^=_n>(lS8fxlPwcg@3J+4(=NOZ2)T zt{Wo#y)sefSCp>%@8G|;E8?><jWc-<l0an?znLIX@p}p)ZRTn~#xTK%X8Pnz|KEP^ zLHuukc#gjq|4HNsJnQkyHNQ=x@835NeGuCcb;Y`(Pl8-*U*Lb$wooS46>a~DifxKi zv@cTeTM?X99pZ57xBV2_8l1Trx|rHg*FWJHRvZZptrw8nidIPXS<n~L-3HqkyX0^G zJ9+&gowOeO1canr{E?I$x(h-QbS-9WWzMI40wD=`+O}v*ptL<9FZxxvzEDQD_ainx ze537F_J=O}tGwv5NdKz6s`@`4!~f>E+|ufTG1+b8*#2+!^Jl)P@MqPA^jiO$v&CuM zpXvNeM%VfKcsF6a;bSXO8Xuxeq(Yg<i&T)&^55fszbqj144nB?A8$vrlk)eN^8HP) zefY&;h`L!Fua7<^+}q0A+q5<XmIUvC<IfUc`?hW0lf3-FE>K!<1ir+^0?auI)3w#m z&UX`;#$~|Ek2k<-e!u@oEQx*pu^zis8ao9(|FiTfJy9;!5%b~r_||DSommercGWGv zh7)x}D(Y6IVtF{_i>M>uEW13(&onC^<8O6-jQMwc`B?wxw_vj>RmGqR163HP!ax-U zsxVN6fhr9AyD{MNUYo=g2jjB%L?-slR2)5IKk<1p91YdVNPeS%I8Qs7yfhqzy=;|W zo4wyJuhGQce17(Ohj`Y4s3W!^_DyU<)Dz^QKcY@$D(dFsM3bf-fheBuaAbBoG?KYc z*QW|{J}Yx6n3y`^(_C9pr(hyhJgcK3&YWK9z@8(0vE_%$u7e)_{C|cnJ*F^W{d^&= zO<No|{U8Jmx<oegsPR2Ms}|met5ye?GcSI~gg#WZN$dU0j_3>Bf4Xg2Ud2}&$EtYz z`{N<}meIBQZ+`=+EU%pZ_l}L5Fb}EU0mOV|D#quJ<bs~4Q;`?%Yeg#bi{^#=yeDTt zqRv169eoy7dH(nou^#^{d=mdmoYsGO_6(@=&x-%O@e%s)cP9njCY{`bHuy0RsaPiF zMOs<@^E@4+AMJ=XL@L%5sVEPpeETM=Xiq4wN>wqa!ax-UsxVN6fhr7CVW0{FRT%j1 zzyN&~U{p_g{yC`vS}%P9p@HAdJv4c6t-?8i;`MQIsf<6<S^+g{ec`Xe6{u_Azs}RP z=`$JWvl@TZCf$c$>4<W=kD}~fr9aN``s@9s+x~airQ4u+b*=VN;q0^ffnUFmCw<1{ z&&tL6My3noxCwcG^Lt(TOv;~?i*<!IH(5TH`gAFk*OeWf%Ut$<FXwXy4k8aP70Aye z-E~rt9M5_A-M(1=@1}x3#%qh6rTjU3m2Lmt*>H3pD%Yd)f{j1w%l~!k|F89E|9-{` zKF6rtV21d;mXC$V3%Zl~c#;d3AN?j)KeO|5*?-46DC|ccG`!K|ggxJviay=gZiJn- zWP{G`iI`jD@cmtq%6e7#igEjSJj8YK&*)a^{5*zLajA++6$Yv>@V|+Hs(ti-bKL&v z`PM@^9Sxh0XN>y=<0qmozYcqPZ3-sdKPrFMbmH3nXdR;_zkYLXF&rN(<^GXtHD{mN zlI=IYJ=^cEY9RgSU-3DAp-D5CwXX;6?>7OX9QuCuQG3M%tP$3e%<bxjx7cdXq38zO zoKpuE4DJm5k~@8Wj?{3j2A+EH0J<NY2Upj+@^Uw!jPJKd6)N42i+HOn7xQiv>WlXg zOPOxCMMDZN`w%qi6#bj);>vh9+&T!0E_EbgKg4n|24a83{+B%&j5T%@%KKk?gcoM| zwkvPrn_r?IqMaXk(cf^vZycXF7^gRWN*qsj$L5zDe(I+f!=Y)@F~`E2Y4>Ob`rn!- z9lUV{);O0c{aDO@e|7vg`G0Z6_5`ZJpUG_|$&$Z^zwGfq^gi<8`*;cE^jOpN{v7|U zpFh7Z63V{y@2}JUR6Bpo-yU`yG1<xcr{niWF`&mr<V8G)c14^BwrKumwtvj6Z?O~e z;@tazMWN4PeE(Yif9A)}WE*Z|!p=ITIAYgo@^<d%zY!<@8UKIQCtBuvZ#TJeWW+z( zuOG4fHnw73jJ-JiKYabB_apz`5lcF*TCGdq{_WL_@OzFdW;et=H2|R>jW){Q*gh40 z-YMYG2Jc~;f4p2r#B~|3L$a;yg?ggw@1lZD!G~Yjt6W|=|EqeUys|#?^%I1-81vT) z3aEGI2yBiNzSpXNgYSKYtCy7I^1e;Z!Medm<Z{tY75z5$;j2D@=`Jhg3qNKa21npg z{2O_kcCF0?oGbj#N&(H{Kf?m4raYEn+{AGZsVEoezbY5!pIBd{qMcurSJo5re?-&x z{?_xU=OpMoZt@OR&P<ih5oNEP@ZR4<j^CzwB`|62I(ffU1{{PpZPb5>>pyC*s{HR? zYpP;e71JsV{O@C+i{(xjygd;Fs`nsO&Nnekk_x<dy>s_NBKY$<Z}q&1z>9K$()EAE zSJo5qB>}tSZEbn^qn+QYU)e_TrAH*z+#f5`t-QP+FTddjPGVUCFS~KOKW^@mAXU!} zX9OL4-GS(?9wF_jt;C3Wf0YV$L+knA!Y|0ozvo7T{95B4_@qHYCUB0cJTKeO1MldS zO6zZPk>@iy_rw8rtr$sL)8FU|ewUu<g;DL5r4jBeh~VFl3w?2n_iM={zt8f1RJK>Q z&<B@hw_*kjvzO}!zv_i|g6x@I0V-sr$xBkY5AeX7os7U+Zd)rKgT{*U<b36Ej+^$H zeBt$N8ZTu8zIcZs2=!eft4Z~SDMID)p&^^(IGNX|ArbhzxDt8&31%Z0fme@+kk@~f zcgN+{)R}UA(bAgIqG1v6nYY_&M1pIhW@ABUGj88L#%DKw&Kl3p>k}y5{;8{6zGP`v z{<<jq`~A$|t>1jI-ttHy@JGW^<v#3edqpbng06+1pWMzWrFz73#0WX>o^gvQU9Kx{ z*IN6I{G2%9I;ZAUGko4{|96aw`RCnSAo^K1{#%6K$}8uEcKCOdiSUg@nisw)`kA*Y z`b_K4dbFJ8`7=())ueI4nJPb}f{kC5(ekjjolyIlI(+qUl?rlor5>2_IiIAMZFd&( zmCNZie{~%w`uS()%^%G>p}g{ZsEltqUwJ+Vc^dCx%zx}t0&c`L+f5iJeq8=2Us*5w zJNACmrDfq55&jyovs6&)Mi<Ol?gqQJ1Y+>P2$E$x2DK(E`w7;*`5<0ri}4n*BVtaB zx0o0EN9So?EdT$F9(mUkr|Il~lBWIm@1tscr=t9y?62s9QS>tyPimq_MY%{txkxL^ z|7^ap-oI+^KN%|#|3aJMoDka=^WvNl<l;OMb!b|7?1eH>ChCcKkyh5B<#ZV>|07<E zzeq*>e>E@G6RB8Vq?P5B^J1U>uk`K_3#rO58zy1-bZUM3wyrgJa!Yb=bsOopv;4Or z+gV8udWT`7K}N1MOTIme88p4O<lf0|JS`V}c^0+Q#fSg@S?-}Q=99v2?TdOMZSNAp z^ncjNbsYa4dQm3Qd8ziK$+3yw<%=i2mDa2G?HiUFjlJMY@Q-IZ?B@5Rsrn$)@H_$^ zdaQx30~5fePdm6ZqBamMON?!r1&8;}k#_BCB)4btA{d;XUj<wKTpM<_5ffB<F-bR) ze^>c?dz%|%yD0F_F|6HMNa9RRL*9TQX^Ua?(V&hNv+ku8?u>ZI)abex=J+2XjSkEP zh4*G?oTMNbbm5xRq2&ye6?}ne559nT4OJ$sT`5d@t$>&8MoO(-*fJr*y5r%M)5&hv zYh-E02Z&hw0fGiRV_Gcw3_*OVl@Z50S84*=ZYDdvf}Y40euCU(pTJjj3*((sPjY)m z1DrSRIWx+H1B1HDrL&fK;X>oBq~XD9WDWTQc9x157=Bawd-X01c?)`Dt7C!^CwarY z0{5N#J{EOf;+4N$Iwi3;j;VK$d?cgE+cA%&emnc1d-Nf4zjj+v*?+ok;@I8G)OLNx zV@B$~maOz1jsEW5<lyNEXjHZs#wj>qW`@5r%nQY3`wSQxS(!`sl<8>lygL)TNYiQL zfN3agxr8}7b{Zx&S;S<mRF*tCGaW5M-5JyIsS=CqY1p#;ROayRMiLwCsW@Eu0Mjya z3c9R1!8qEC#C|h&ke5<LNw#e-Jh9IdI#pZi(5aR$X6Duf*C*p};^^^2C3rO6=(2_s z=?}uWP2ZEcjp|74B7352n;8s>d?PvDW-uPD`;<KEzZlfJIblSo9jqVdjqEg4#yF}W z)Ku(+BlkUmP8)0CM<o+-*+Ly^S$Jd51_rS0V{dHtF$8uVYK4K%hd|znRnqh>Z86CB zI^+b_#k=7aFw511*mUajJsx6wUPhNO7nMSA!>wMhyhaD?=GYbvs&A7n8PFLEq|c=3 zxl+h??1EdLOo3%uE@Z8;6J9^~nPCR4fO)T)<JwcrVd0hr(%nHm_)0f~_{Qykx6Tc4 z)8pw-cl&;_cULpq-q04RFI^0ai`1~o`^^v>p#hm@YM5TSmiWC&f=my6blfoqibIuP z#7TXe;+Fthk}O;%4A=yBnS+p4FBuF2lc4NvB1D-OkS7CoLaV5~kf*;IUL6mD6KBK0 zB)J;8S!BY&``MuKJ`(n~@dCFHRo6wA`$O<69bA&X8wTCl;h=E32izeAFj4yzyt%Rv zUW{%Ei{~YgwSHS5D8&eLA1dLco?D>nLk6OpK0?Fcxxie@fEDw5!Nt&*4DECFb#?SR zJs&<Q>4U@TeN3!YG=#m2Be4gXV{B>-Y?!kFRAb6W_R%b+DH<~a_Kku1p%aMj6T1pA zS*JKs>bhtJjEs6idi2vl3pYhnzdi?sWxgQNI}ga?86j}OW25U<l`+KovmLJ9dKY$S zZ)Q@b*2Ir4^I@sSW$C+vPPjH<H(YgeW^QzEj4yX@m+pEH1K~%HGRE5Wc+b^cI?Cx8 z`EYp<j*6AIcyw?8odI^zCNAA^Psc0F<-S+oyweDBT1TP6I8N;23Gc_&!n}boF6pBq z;Bkf~2B$9rmw8H1ZE7O3+szInmfG08nx@mUm|0L<N0V_FSsNQ)c+R|haS|eiULaDb zG3MN`mO7lD3s?Hxh8>|#p=4=3dD-D9NX|ZozU!07!;+ay`<pe<(8!4x4m}Mw2Zq4x z&o@B*@)oEU{)l*aa}d1088gXG5w(q?A?XBvHf;SYSijVUxE$2R3u%2^v?iQ@(@U!3 z@LPwWtl&8DyRL>UbF-m)X)0N9!308#moe=p-iAkR$6;p^B@ExT8rs)lAo9d#CSdv- z_|m$!Q*urzEb3?q@gx~~<SL=ZCRMz-?ljbu#gmh#?4=)#K1ug_)q=}+1K@U+37(Cp zi|rR3hQ+Tf$lHhRQuC=dVZn^UuwK(0B1YbmT5F#KHa7)Et)2xw7B$d%{RTMYl0lAG zPbU`LWKc)40ZvRzgpjW?=E$Z6aQ!eRIXT1@?{bRLT=NU?a?cr<<<T03ty5xx7F~d9 z&ksZMlV0#FIT_A2*$h4B=rGmirNV-{sbG9`JFE|{&v-3QgsiVSz%_3!s5L(h7c?`# zd&4TYrfe_i^KJ(`@4ZLrTXQ35%$);HN#`MvG-4KeUV!A02Vq~@0GOS<7hWl)Lc5F0 zU_#T*jMLq>(Bas1aNCpN96#U~>2u;UtgDd+O=bH@FVD50f7T2)6!a!dUTQ=51^ztR zrOQeF!PW59#1e^`0(my88qQsL9l{1j6K`!roZj><sO}p>dOdO^t|_B&V9Hl!`X>`O zC-Xu*&syZs8ZBZ!m49BE-IUaNRRdF0_rc5F`K09LN=V<*2%|eBkuSrW!(6rn-bpZo z*raN>`c@pAiT8KqLi>RFgILJvZjB_ZIeBTPj-^L4V71R_GCwqx1VewEZP<-izSe>! zS>5oHdt);DOD-vW(FNBm+D#^2y##$)$zVvXA0$7Ig7pOk=(3_3e3?-LhDJ8WkwKmy zJCg(Li?&0VdmLExm<{${)bQ3oPgqg12NYK=gW-W0kWk$Yc6HFlgmVFKWL|w~M_n&a ziqyv7>0{vP=Ufu^&IDiem;*PaWDzBn!5Up!z-Rl%B*&!*K8*;3<aB*zZ?{YELUAXI zOC1j`Bf}vgKo94vG>2s#_sQ#FZ7`5ggh@s&k^y-)p|i#jm>1p(8r_Y7zUJ?t-n(fK zk<yN7H)Ah6y}STMPfi1Sqvqh_rH`S>qrm=Apd{EM1Ya+F`F-CjJ`y6;Sv?hXqvIH* zr6VL$GJ~=125lnlbzht8kgh47ip57qGu>jwqk``+BJOYfn~cJG$2JqoKJO%3)rMp5 zTbbYYykn)yr7z!i!2tuMAl^gtdB)F&7zRaJS^lehWqIZLwuf7QAUocmHY&O~$a$Zs zTHo)L#QGvVn@Jc!f5>9j-}qwlC>qA85^SNj)5SnF5-uYknKnUkIBE@Ce_(?>kM)*1 zhAx26zD^hxlqQX?za2`PEODqwPz4>ev1{P`F<Ufz+rfplnbYJxbEqf;5BXeR`c9gH z7X4<!=4nz4@aQQW>DG|6_6Ww0dCOe3)T>4cZcWB!#-`3UkGqp<X+gNdSHYQGI)`|^ z7>l%Qq{M*q<<I4<^Kc#+;6E0F6E{P4k`-R*?cyr7Go^ih$&M2h-*pnMqv&fS`Wi^Q z#u2Yw=)IlZ&*?q9@}5oa&6W4w%6n|(y|eOuSb4vyyeC!Ob1Ls2mG=UApQyavS6;I# zuZ@-0&dO^gy(ZFYAHCjHUcczIjb5kdb%$P$D(^Fu*Bg4?3*&rX{TwK1p2-}|bHonK zj=<D*`$4)O>igWx8e&O=Iq{*u7WFqR0+*wDc+<0tbg@o^xb-!#rCG!8zd3$hXbv-1 z_xyejQ=`u;C_5hopRT-x>()7B`jhUAUy=X!a-n^3&KAB+l-85Yz?3zCkZY`l26sov z?TYt7g06U7FYvS;-Oi3D!^z46gURW({wUfM^fN{}F+R^{N$%XAj=%Cn(EI1ox8LS| z{MJ{MuZl$#2C6Vng@GyzRAHbB1OILeg#UxrK2>f1bJv|!v9F4K6$Yv>@V|foH(`(B ze-{v`;Iqh!RFM6i{Ey1S`u`MlEAOKMPw6DeMM{?m{2$5xuJXTXNAQ(SqCJs@3;nN3 zRWbOl!$41GZN@Y!6rY){fY>5?G&<;jhhq8XpXv2+;qqLlqvFgwF$+aePn3&z7t6)` zF>?c)lztrgxXuS3e-{*~C>QOE?OkeF0)sr?zyNR{ZB6xXu7wQ7B{O8N-6wG0dVmq= zsOE2BpeG>$ZJ+i^o+h0RAaq??$Me|>U^guw0zEtb9atzeAp%`^^R+xZZP%U9c4&RN zUD_YIE^YJw_jx_rb}Xz5a>t|Eqv70VcZ|5P6|(9y$7j(SL7jg-dFsJ1IIGeQKlK|4 zhljVt4$D@+&2)Q|wps)JcWl4QMLS|WQ7`H9CukW_4SOGZ4nAwua6;T!@NjK_qFiiG zw3lUZ6cV2se%BN0iSoMD8sUx4M<Dy54u(7A!Kc(BP}*7pMR}C!eSlI;6y>6xC{KB8 zhRHVk^MdR8IJfgDSl6QjY_BMzD6ePz1SSqwM^P^7iE`zFy7=Dp8tjWz$Hj$((01J! zxV@_Zit<GZkASmtBNXMLo+v-(r-6gq9>ReE)iJ*HJBS&-8KnF-Sw*=!|Ll8!gEfkB zQBRbM;~<WUIBsJ6E6e|X$8S~ts;)b#Fi?eoDhyP{fI@|P7V-ZRA{DRa{)qlr{lBVL zx&E*6mF1%UqFkh+yoy%D!H;-U#!FScY7MEvKoth6Fi?eoDhyO%pb7(382B?7P^fU9 z@#FgPpOXI>pZ}9O|5O~R+WqITSTzP!WAIO7ApF1XndHBFU*!+cRS-TJq{=4;KB@6Z zgHM`#(&m#EpX%~Sk53KwRGUwA_@u)pT|U+0Q++<^^Qj@99QmZqr&@fn<C6`a?D-@d z(pQsDDtzM4BT*3AHQ<vmpG^2<#wSxgS@5YDpRD-Qm`~<>YQm?ce6r+Ib3V1;Q%gSa z2LmfK;*$}dZ29EOCkdYn`J}`rWj<Bsli)Ld7K+?&feMK~KeOzUW4o+J4I{X9X>BsU zIJU!mjYq?il_fj|vhBC5aFc1d1PlAM!X0A;1;%+enZ-@wGU^^f_o;J;ZOkyP=bFR# zvh#lO{6HTrG3yj62FxL2Z6<P^%1&Wi?iVI(!&Gi}=cBmP-hdbzhjZPVp2o4&NLo8d zIA>~b8XtwbrgeWdl~Xxz1l!egB!VvyhNm%okuIsxYzAk2=m<{TCrx`lVg{%1=rCq< zwoN<sVGMWnK^BHZXcO;iqqw5;*%-GZn>2aoz)dl_fDcZcBWbk@So7+6nDKcPxgX-h zr3Br;clHZOocRb2=U>9<HH=7Xv+kUWbv{0vZJhRMx;GctF(04mx~BDRJ(b(>`ZAvD zXG|t~OyyR-xr{35wTM|_53X8^R8-MwLZa5&aC6#k!Y(#TNyhx<Ty&dFXsSDtG*tBF z)SIMY{a~}SMTWgO3x`yE>!F^u^`$L$&0`Z@)$2;8^cu`PS+^6<oZ3JVW(RWbpYFvC zj&;cG)swgf>oQPz*e7Q1im}|7-n+3lv;pz)590iavM}DtDJ^d6B<`_77HZsgP8;4Y zgnM}^1LKD~r^T+B%yntB2V)$(;H{c7*J4^WKH2I6r_vj9AM0e}>h=A=WqLiX@4jRB z{%KE$%5Tc`-;#s5837=fQp!HaJcZXX{h;r2b*|IcGx$7tBn&v5!8)3s#h?$vpwELW zwnx-C%(&tSakUxl{J`V*%u5-DKkd(r-gy$csaJ!@24lHH3Wu>?QY-iZ9k{&GY+Sp! zJ4BzZ$DOb^i(O8u!XRe{uHDmf=u*%Z(l=aXFEHnERzDr+`LdYp(d{xu9_RqGAKGz= zHv2KDQFlmMV$2PhupgZVzbD<3hH|qe9l($}3rOpNvD}0&hw!37A2_*LjeFs_3;Q(g z2ctiKVE38t!L{K-LArGwJNHEjUOYJjq!VYcFNW;I$Cm;i4C68fTcu)Ip+B@&e4e>@ z^G@`>H3VwT?n|8K?nc)w{@_xgPa12c;j)1NaK>%}x$|j1l9~Z9{KG^tVdDYx+%ODM z+AkuR7Y?EI;$iT)um^c)eh61zl98nDuh@~Zui&&Ld3)Af`^u_cxPpc~YNf@lu;=c4 zzK&K8Vo7Ef2d=c>dIf)IpBumMh6MeM?7@g+lq~BD#j6w<=WWRq{4`DRgsWLMNo2QF z?DXmc+3(h$>-p*wx_r4z2E20M1{z*K_2zd;jq{&a=do9C(j9;W`t7*2+6S@c@z12g zSZ}VW#y;$wzn3iU-j7QhnU1R$ui^hk>B04UmxA*@SVEzn6}KTYrNX$-F{iPi>>LPF zwBu!ihvZ`6BvW`XMPC*<`~qGM)rPk=*V*+(m(eHK5!}Yr0Obk$D#X^-+X@~9^JfS6 zW><)9`<yYLKHr7xksZh30ga$W_$m^!>m<@`y-*8;vCf$?4TCeNZCpSg;uR@roP*m> zd?6RD^!e}AXJOuo1*F?pO~`+H1Wy*{lCf!~&?}cit=>w|>Z1ktuGohUSI;F~OeNqk zc|WG9l#vHtTf(&WsTemmmIMbept>pz&%31(%~6KjG~10hS)(4bYxIR}ylMlwY7;1( zF^@G`n}9|yI)NUuo~d~)0pGkru-$Np1ehjax0nXdL8m@+Xq${5S~n*81pw|g=@slZ zJ3E)$&a?t6+3pHH=zV-h)=Mm4@rjfQb`*zcLTGYb*siv@Lc6p-n^SB+sbCU&cHw#q zwI%RQx}GV`Szp1oXY;J(e)g=r0UaM%kyT4fIeVv#Xku9{ZAOe4cgSTU;=U()_RrSj z_Kr@%8A~jQ%@z&LW_VJCnBb+&B;jlg4*Dcjh|i%wb!cvKn{_>(SYb`3*J^t1&~v1; zG<T17{%cm&JFmi=qV;K>wn^8e_Yr!3q4%j@?ML+f<>2Z{9(9|+WmVcE4s?}}yU{&3 z>9PC@`wP9-&^q+KN$;oh`bN)ddcULhL3&@H_X~RL=rN`DFM4mHu}!Z7^u9*#cl5eJ zuP5{xPV@BMMDG#wx<v0y^j<^nP4u2ZuRrvjLa#aW{z7AeUK{D_2YUUa$BQ0!`kH|r zUpj_#tPb4VV3!$h2_{eXAU((X8c!u*R~^79Xfw`=&#?0{kihxy%}CF8dXCfcm!8+% z2U)?sNCVazmt)8~0(17T%tH6&NYCqw?V3R5rCTJq?{YLcQA~ELnZiQ9<rU^KJ;$f& zD!O<`PO_IeEyrA)7UWo)lWZNY<w(!*4mY+Czuw2#x4fL5<37`C!m%0a*;XFQQOzKP zMA$gU+gj5~(Pj7^XE{$_3(?m+^z}@e;%vL_Uag^{(q5!vNUxvIEt?bnYYb>D-(O)3 z*UdRjW+d7|(9o<3YyLE@K1pch3ilspAzhc=7wEcbA$`caY1(jSPELh=gqC|0p0itI z<OR-$_M&}Jp52>m-q7pJe!QDslk}V08Lp@A$9GP($(L|<IA4^GB>I}&_~$;b@=6w7 zZ2Oiu?$ia$K5`ZIg$`kc<U>tQFyFbqf}fw?*CbQ@JHXoLETsEF^R&*OwU_K}*6Icu z=Vjy9`TOnsc1vNu^bpcM)4tKMrQ=WQ(EXzQr0dc?(0!!+q2oaNb|z%D-I<p<aBY7M z9#K&wogV0NeR8Lx@zGP{(LFV;p>-&xIBg--2j;Nxy<>4>xD}aP{WROuBNhdWjoRr9 zHHXEbuYL%LZs8#3%O(erqq-Kb{A)Cx4B2A0;Y&-XJ$4qhI9^OLRZO8FudiRy6l8sG zlho0%I6LPn(a~-I=QU>IlfM3BhkXN3j+lYhYcI8H%%7d~(s?=#*HLt7;&qyhDTu*+ zC9n4cU(w~#&rHR)^Aw<DxHddH7Qvq%<N|lMA0Y1CqR?^@1G)8cm~O*kv1CtMC~Py6 z88bf$?T1=Jl6if$#4i>n>~IHdb3HboaWszdP=nl~>)1v8V=?SWL(o6Jku}eqg*O9? z_B@}SEDP`18$+!PZBKk2LZT(UxZ=oY=FEYCq}Qju=r=`|fxz7|ot$3Ct_dQ=1{%=+ z`9v(R3AUSMsSXQ`$6<dTE4#zCH_7V0gRr+um*ApXWJ7Czd?{JMTz{~iy{YGmno|<? zNJegD`=9Akp<UX3UA<al;}kv4BRc?xco*+6$*#+_tr>td_gx^C3$?h!gF|rPBs=J= zdW?N}aWIaWXak%29bwx9Oh(fMUXajl9y^8YiVEAkp~ywT&bm7aEu$r{`SDeD!|~4e zFiQ#(=j5`<Hg;%f(+*VPr?dAj*`j89KbShD8{@co98Sr2P1=`KhwXWja7@q6uxr&O zqMSVjJ7u<j?a$7W;NW4{LsCSp_b(<bj|AYcBQ+p1zl020(hnD2eoZ=dP=Y~)UGTNL zF)8ejOq8a2;N=i&=F;h#O#Z>P7{8`2?9=$l-d)}a&!1=jd0EBm{L6ju-eVn@9q@$( zV>^@tpCZQh6}X)J{MlnJXGxPy3LIx|hbOx^k-7Sh*t6$5qN`FT(z^LG_UJ@Ayr+}G zSbD8ybId)_eauScVD|(zX{a4W<RX*twJW=d*LiTrhsivt%5Iq24ts~Hl36KB$mjk} zct3w3^TINMNg860w$^#1XzE8Yw@w=zm>WTYB<Dz=qZH?F+(M3>SK!t@_pM-uw%^~t z2J$ENV8*L!qQEEC&&>=ASH?LKQ*hYUh*>^e858pipm^#!Mt5#aobttnC}^2T^YuT& z>&3H(Y@RlAZ>%!9nHQ3_8Sj|2fy%f-<pG%&wUnuT_!I12FM+c?-pMpAOCb50Gu$b! z>!(}?eDA3c{U~jO5syi;uF51}a1B(hd6$%_=#!i$ni$^M6^?Y2vRpM)L@xpv`E%He zwQnFZ`5tL}l_9HN>*82TRcJB48Cg-Ri~S1}$$bT6_t#LxbvdrYvXi-NG4Gr4aBFg{ z+=uWsR-`9yXX&9gaQ5LGGHT2MCO5JshRsPNC*!rrT2>3~ChjE`$(H1uk1k3#X~U*9 zZ`tHnGi0aNhHGt#*=Z#z_$i_pOghc6)849J{o{_%!~ZzjBFYRu+T}85>nE|62h7m9 zl#uFXEW1oi6~~X-NKAE#*@1UeaATwXq>1VawmPqK<;58?e(y)N&So<-h<rk36ntje zg{Y$27k$_irNF5U{QznoU4Y$_$IiS^4AV^B5MKjTj;#9xA%}L8S7nOag<c=ww7(ZQ zcK8ara^-8#nA{5L6pUs!O*cc|RtuTNwR^C}!_Ck-Fqc`#b!RtP)vgd9I&QQM9XC3j zGm<6b-q#k)iZTs+y|^DycyWhuP^pU<J=c)JY4yqO=JnCqvVa7Z5wc!aA4iVSh0~Mu ziQ-6J-pw4cd~=u*RUHgnXAa#rxG_dMX2H?E4d8a?NXATa8N_9^0hh)Lq+=higflf5 z(A+#p`lwYLzy7v{g@bR&`mI<48J#<U=e#AduY0#Z!@fPCkn>|t&(4DFKApkTC!T$H zd@q=8w})MYuVo!0SHOH702{Y8?7ow`VVlkXcoCh=VtgJ%d-a3{arf9UUCzRYkpQlD zzOpS~88owFpw!rh)!Y{HOFQZ_J>ZM)8y26P1e!NeYz>>AHR7)890YZ>LSi}8nz^48 z3!&*|Fs|o~11Dd0g!7*tl06zTnOQ+?q1BLnQ1?|Mu4B$4IA!Mvy(Epf6u*KBe3K+o zP^#_5jn;bt)AH-Vg`-`$<>_aD|JesxpK{>tS3e8a^`$&M8gUZ>UPF|h5d;@mamjB> zAmG_Ya&DbH7kKzRjNV*I#y9Q2kqJ-0b7eaDe7Ys~aAOG^Q$Ii^7`Nu`nHR$7T{f_9 z8*p1+XF!*Uj&NzFEw^|~BD}Qng}9xqxzhoqaB6mY;7B_zb=#*3^4`URVA>d4&Ucq0 z=56wY&h_26qTuTIp-V4#<=2@T^S&B7D|&+4jINyJh-ygN(VOlAcSm&K-u6|(1~N~W z9NvllEutD~==p<6nHqP?un1`Tbbm8D61Z@~iF?GB!QNE}s;}I+^cKoU%jvdgAFLDH z;dHn$NBotLo@>9dPwUY0wC=sO(2sTCp4?JF+UBq3?D%viu)OcYI7KDG8XYre6yKCd z*WCo&v;g*M=*jw~?}o_G7SM2S6WQc0d*OQZLL&PR%d9$|0Kyu3pkb607o<R3T|?;o zN?A62XgcUViX&TiehSZzn?H&iwKSGRzS;|CulFZiN=;bv4ky9tVLQ0fr6s%A-~?p% zvIVAG{&f`tzQ<Rwp_A`G<Q*@V^>70l-}80_+|qM)&zFT{oYoQ7ve5(vzMf4ERWCTm zeCz~G-t{KxBv}^s*ciIF7(-Uw0?E8UDS(bWgndnym7Ft!ixzERReZGUDE}?L`VRpV zr$oqZ_%(y<YL2jS<T_cquQlPxqDSO>{Y*w<W(!E=$G6j59oY%vP8E1spSJIlD228b zGPYRJ5MuOQK{9?d>)o$9yiREaPrr^}m(J)8&pS$C?3yBWd&&gZ?Cc0TIv8?;JBC5V zNIQ65OM_FhCxCq%z~iVIcRyGgMl=H=-L;mT8nPRP@E;&FFfEoHd$|HG4|62*vwE@i zD$}9N(v$RiT*hi#S_+daZAs3;*X%*vlMs0!k5LP|%UY~I1G~ReBRFP0TTr&Qf=ya~ z{=1GOc4Z^3rpf_WoXwCYS*F~~!h4XV;72|xJ99Uj&p^PQz0BK523(7s4=U(9Sl*np z?$egj4fqImjZ>Jw8E)LU_)l<g+a!{tX2i|Sd<E*O2a@}Dow?V#We~Gbmo(XOU1qdo zZH0dICJ|&}Mjhs!_bjMc*pgsbJ87Tsaj>pr2UDy&h^=`(3!a=TV5(h;m6;#h3Kq}I z$@nJ2*wssWgW56=Vw+LSx*1Fc7j`B&b<u|NUYh`miYJnzzD8W=;Be@yB_U;X_Ok}- z4dCIf!9;RflN+x<D&U94Rm!O5#P_t3Os3HpXx}taw8;7M*QM>^SAl_S9m(4`gNc5y z6oRs1i1V_x%#{|K;QEBNgwq_z>^PPPO*>kU=Y6$gDbhU^_D$W<?MQ=+6|92hUAPod z!Zh8xo^={~8ys_PFa}wV*quGzK=!+u<h_4$mW@9FjzglE`+YffvsWH$7}%a!>Z;1+ zaL=Jr<{ieW)QHnrql5$PC8S}B38(0$gjlCP6Xt2n4dE1!jz2vv^gd3@X*((X9Ej0% z2d<Wr3hLJLBDHV0b6#;u6>KJ$Taiu;T)46|)$x!sklD-HaC?%Ku%x65SyY%L>v%&2 zp5(ie#L)HZ+to@y%V%Ba1^RQ{xT)^dalLnEIHKjmeV(O=k>k3;+MCW?!7l!qC!-te zLkBL#UlmiUwSnq&-MJCnlq;;;A18ajlfEvTN+%Vx8|VYKHX3tIjg&FkPMfH7bmT^U zQb5gdHyEw1?Kv1#4WpMD61OiMxO<j7PwCL|=4K}3^%pO0*D6J%abDzbgb6k8$oYO! zL|TW&KdnC`HH#@)0$gG{W$g4efvNd{aIJ<Y<E6RP$j2NfuJCI03gb0r#Aimw)}DJb zLxsPm_%XhXW_~2kw0d&3#pgiw<}h&z>dH0pI|H=?;>fKa!sWHgsKAG{{Xh(A5pKwc z{qU>0^n7t@|DK%4ape3>k}B-W^fdszN4L>^L(W#W;5=GIR#?+UzkW&d%o=d(2K1@0 zzR~lMo`Yc$A6Vr6l=U@w1N7L@>oyr!M4bEUa-DXytFTVmOzKKh($%>0%39E~w;H*m z87)(MECu_^jY;tvf0=WmCKY&Eho0lK9eR&A@pLNj&F?`HFMfn6#qngpk&&dZsfzr* z<K^YWr0vn_a^A^(Hc8~KpM!d?Bx`r;k=$E#<no0^&B)DedUF1A{b&L=G%?2@m6+BI zAP@3tRk+8|9qL6EZJWd#Jfw;tIa|s3*>@SNn<w9Y6QCA(6LC?_s|~ehcE%io!?h#G z1g>A^v{C2e^7>7^$$?rA!Ea<7*?H1b&d<tX$Zi~xnRV)Mg}U^fPVeKiO?n@XI_6Ar z6AEQo2k!uFlfG`J@7L({ZO*F}#6D^^8`7x|=zAi1{VC{Z4*unF_Ki1y)#Y(^4$*)X z<*^#*TMxFE$5v;I4ID3z6@9PQ*GvmOm&fhE7gJDVzr|-%H$ymD9+Qkb2e2uR39Un4 z+c@hw!H)9&($_6?UAkTR-ZOQL1X8o+u)ZA%fxgb6?<?u+I$<nCoY458@gV3}MJbc@ zeyaGZIMDGI^u_yP+Rrz+jbZ9#H7=%GKJnLhOkNx`;_9`0M4s^c*mow}>nBR&IDckv zT9mq+Crf4#k)Ne7lT0kHYy6}qnWLY?=G4DN>S_!kO%|oFLS2)QzN9Q^CtI}f-oXYu zztqiE&If8fCd(;a)Y0f+3(+w(*=q+c6J2jxh$y$2a;haXFSogg=RfCY$nER#ZM`Yy z;a*P?US3yqM^ECxrZetOa)`s*fy6XtoK*0Kw*PRDEjX9!q-->W6=TmcSF_Y1U!@5s zx4bS3u4xPpYK0S#r|lQ;@*bDgu>;o`K%R>)dEVZW97?)(@Z%77GR7#L<f`94DD*L6 zX)Gz@`!4XomYs+Yhg4THSaf6+(XoC<CT)F0R`LAocj_R-KV7SkDJ#=~$W3;zfS1R> zLDJwV|2#0<mI(fL>fs2^M^};Tg-WDrU^H36>l`0nLR_pn6TxN=?`#rqVGdba-j}^2 zOu)!kh1=1<2zv1L4TJRLe3`BpJnE*&3H}Jab?s;_=ZoxZKyl-@@e<@0w>HldbUI6H zptzhDbl%7w%EY=w<vblLp)CjRNiu713!uk{j_rLu&b`ZH*w8bIf423_pAH_eMD$r` zYgIW;`rjN#&c3yl$05F3TjI*c;ft~|3FZB?w$&y1<$bAH$AuAmOX=!M8aMpLKXCLV zXLWSs@xOn*C1f4@hKFZw9br`Yc)7XRz~l09G)yysD=n3|esw&dJ>QpSj&<bx(DZmB z$^|}4mdZw5X%B;W{$;m1>>z$WqIn?>0nAC6K7Vhb$J=~Yu0!)eTZhZ-l=42DDECu{ zxmLOV!rT$#yp`|Qy7IC3)m)%4FT}w!FIKwcL0_gZZ|7=VEmq*^cm_E85|55HgyZFO zZ1o2avg#QBF3Z8b42?Y+lk0e&TbI`j?CuOpc>U+RJ{@PFFUI9Q&^`;}d#BtV+BX4v zqFms`wSrzl=(;pc=(R$Si+HAW=rxU=3-r22&kI^kuYojfY5iZVfpov<{?g+s==^M~ zX&rh@1$~$D*b2NjXK9?!@&DCat}GYhFT_op?=((?c{f<ijtE$y=O8`TXl(on+m+=a zPAd0HoY#V%;=G{a@T>Vw%W0qKzR+v9(5|>v)9X2{L(hxP{2Kn0Uwd88^<{**;+jv_ zrRT-3)*M<+$BkZ>23!p!i)S<dy;T{cW&2dJW}E~hxA&97YqpSmquii{g)(6r`jF<Y z48h)9nXJ6inp_JiAo2HPWI#zXqHbP5tQsqm)p3p>%KeTvgN%C5N%Yq@WNO<-Wd5s7 z<Z6_1roew5dzqZ#`6-%G5cpjulrs&?`A@v?Iw$g!GiUQUw=T8@J3EeyO4I_;AM5wE zLGWikDv=Gm&fztkp@eT&(4R>xV3^V;IWN{#Nu5PBCH3HbW`SJZA>$J{y0|7R_%NOv zDfjKwaVdOlTtM~`C9<=NCG0ilf49}#Pn2Jpf@*nP+J_~4TXP!J0F~%(eHj+}l+@$- z+&8vF;F}#+&K!KUja+9L$LoBs1|e=)pj08Abe!pa(fYJ+WA8{o*XIG*m)MtS=-~ji zNt*CwV_$}jzvYT%#HL(_9<O;HJ%~%Wew3vn2>yHWzFj@x3Vq6b7W(yYkS8=<-6r#c zyEcT~LC8vKlPSn;w(;M>ncgO|rgI8;&c6e+gO|rdc**6$yOyNu7}8>U3)sB9O=ieU zMn2ZUIC|f*l8?18zQVX~JanIAALz@_eW5WxV}r&6twUp;o+C8I=(_Zr`jv0AoQ~nI z{HJy3aTk0L@jzpM)}hBji0#@L8nBIz35_edE<M)28arA}$F}nLifz$8(BnvtH9e-Z z4vhgp|7VyP`^pkTJkb8%+-L^^mITbuI<%bLi)lH1Z%*Gw)4%yFp7NA9zn#YJsxPVV z8!7#pC;ht+{d+9^yQ|xSLSk5I!dYIi0-tUs(B(*NuJdIhaBwt$&>_kk8QmTP9jz5w zoJQ?#(DkAne5_TSi$A6WZlhX)-!>&K%*zBW)Ukx_S9G|PkRl@JPibw*d917fOSZOv z7w=!PBd!9}9<Y*#HZPgaCt_RMJbDw+W@6iEM6~muU<48EuX#F}h<57vcO_t~z&{I0 zAp@HQkhw#ONJyWPB;a8OGR>fr92|9-oQ!cHk-b#Fsnr2u{y3T_89XOLi}?AyJCG=T z`A9b3eMy}AtRp8BK9Tm1N=bvc@ubms{+&Y8YM^;LoeXVJ6B_QU2B!m)$ffOC&|g~x z%0?d{QVo4*U;8Wh`g#}17}f~XQma9LQ4Ue?YYH9T7LqeTX~bktbLe*H6>(=|WNIh= z9&G1n654JX8S~j5PA|(Nxg)j^GTsiB=<gs)?k*>0>W=WtB$H&mpHFViXb!tfR}ej$ znPk?AmY~6HCOHo$kn7zV!QpN5$<al<$<_X*kbiF-DLCGPC{56W?eCY7f%6C{N~{Yr zw`{7=cRD71ZMu*;uaw|R@2kYSp&L1Kq9$lO&8`p=lg(pDsy6>Ty?RlFm~5Uumt^_Z zfZI2}5;`V!7grIr&^nNnQVr;sWPRF1a+4c@-l4JzF?piCg@3oF8FXLtvO-KAOim!q zQ*2<M+4TxBnb~e3S<}ZBlqVmq5R)5qLrIK^6+|ZNt`L)>@qLNg3lq3)y1hb7l8HN+ zc32m>X6_>HL#B`h;Rawf>lTUc?+7kDmbUO%O7xb3fEfoKGo>;o5V7=Wlnn?No6KWO zIi>}O_&FM30V1w)Y)wJL&t6Y`5OFn*s|Nypdhz)2Qq=+xS9zt{AmZn8mMVz2njq5x z0Y3wH{3H!k0TEYv-Z~)S$GNvU2)K&kaaCiMAqe;>;_)-Kl`aUlTF&FD)9t1p;%CxS z6A*Bf#^Wlfn>~ETkIV{0TrqVeAmXRLvI7XXO6GAz$0R(^6^@l-CUlb{h*+Xyb+%SZ z5b;CDDr`q%5b;CDN}^!^O6B;WV^tEO2O@sxSPdGd3j%)pc>K_@3Xn7a5kGXSbS@c# zfFBheKXj~oZ7o5>4;`xneti@1L&xgbP#2g~jvqQ!Du&HL#8Qn7AuwmWA!le>@f~>j z{q{qJV_@cXMeb<Lv<mOHk1ZJu^XzA{ttanB9gESR)mVXyu91V9qZUF7{S}P$hC>+O z76YdZ)yabhw!*vX^n28I3|9c`doJtam{Z}u02;@Z!s!JY*iUN5EBtqW{(r%&!rAb= zUM;S%`e9T_i-%_;AG02(k5%|TLd40LpnRqt*JBimhMylnyks7mB-xHZuTMeI^-=7a zLuvTYEC*cp_r?RSr=i-zyD%>H61&GU1q)>9V0*46mt?vJ&C*T)SGzh_tdoMznr#F_ z)Z!jC+lkqII2hTzI_D6z6{}xa0e!|kVW-{Lj>n&I(C%#>`{mt6v`$?L`+{b(SBGsw z_1>9q%shq-n3Pn3r*)cMUJV}>oRr1w--eS$=fFM1BH6-=8*pb~65Q?jR(i#EJFeKY z8$KlLVhkswqQjy*$PcxZb&XBJys#{&X40Cu@o*<5%)Ae>(Hmra6E<OOy{FK+l`5;f za0~WN&4KDTShhQRH~PNZ2kqT^utft7qGZD^=yCQw>*kQje|LQYbbF!81=T%(CaN~L zw8<e>b!rr*S=wUA*z>FsMB~PMOKf@a0y|o5F8Vt+Lyx`LY`Vc5Y+Y=E6Kz(qZH~vF zW@=M>b8$U8Epj&MxirQed$ZWWjj<R|YJ=(8iLC3INc0$IiJ?AI*{z#q<E|6-=vc2G zd$BA6(@o59?CnYHhodp5a@i8!KW@cdd@u{cH#(qM<D0Uv(GjShY>upsJ<-`e1ASUG z#tR|VB)aDe{N!(jPZYdK>E#&+;pRAEaVK)3dsqc|cr*Szn1Mq{tbRB)de<07&F~}7 zb;B#@AN%TnCs$rz?M!B2{U#FZ{B9dN(tZ{`HgZ7QVLMpk#<A$GWR0;qFR(W4VlXPo z8jWtGupg7+vAeS+4k|dwc8!h0q$dmpd>GDlJr<2i=R4t%JHhNon^?S2Xp1+!!`W$E zJnlZt;9%32GK+1|*d^Hs%`y~O|EV!}>8UNQJ*m##QjN!MttGhPYi{PjQPEhf$N>jB z=*l#_=VJcDmUv>NqRipIJlry)DL&gUj#)c%E^a*96k}$Vx{k=1hmB5K;o5eDS@d`g z<{H?d$ND1a*UPgo)3X`c=q6^aE{nv{;}$q$<!9NnkI|TuZ-!GeSIIKg&cY2I=Gav= zICE=s6xQC#zn^q&8?#{8Oq}RwhWiWeNF4`7<L+%H*#GG@#?c}IZwzgU`L9kg$A`|u zbV&;|;lG_3&?gE{53;}=wYD+q8qdVtubSdz9|aOsCjt-ZS)uIu1g4ErG)A3jhV|mp zm=BwyE68d6^#)C`XFpvM6c&kvai*wpMTJ~g5Q)av7+=9kCg@!>dOf$mqmwQ$K2Ec6 zV@q@Nm}f%5Zbkmm=fg>kh-S*t(Y{gG_LvJERhTC!F^j|xMULoq^|eH@BogmlY>oSM zwq#zbH34&++hFf{(_}YqjmJo?6&_gAS9W;cc$Ca<g&zVhW~%Y>afjS-r=cmER~m?) zirul7LvMCbVIYp3(FOyic4BK@48(Qw+u-xermXdeKpdvp3Y+haV{goyfNsy-&~Vj8 z_R7Kus6Pc!Q8|&_@N5EdV-VkmEMe7a1!1c?1X+)(Y)5Vq-rFI?1e1&GFrQ$&dqs*- z`lnc}e!;lE8^JV%<80}pNqFIkJ#LLZ&z{VQ#O59CF?!x%wv6wi*Kk)HHaCMUJ{*M$ z-Z|lk-WS<w2cmEW$6){2GuR8&qOhl_6rblOvMGU4sC0o~|27(I_54Wux{~0aO+KvF z#YoI5lA_kl)XX+pBN3i4m^p8k?DCb!3h{h0*BNWacFG+7d?xmN?SSX&HO=f-7*Qe4 zjz!KmU3HVpa^6gAKHLSjj#Ff#X3oUD<6O{tUuX8t#+m58&Kb=eCbA1kW}<hpBlc8S z%SHr6VB9`uR6V?lUDZDlPlULjjU<`Xw2H*-b)?wx+-NpFBm$fElwz9i0Cs_A1Qv9c zV!U;+>?9L`Z^|TCC+?K&jU)m~2Ll!@PL>s22*m`>4ehrF$v#Gf<1k-0R4{IuX*fO{ zZw>*xTkEA{vfd2T&}OjJh~5Xa{P^!BS7$K3>1^3mjp=yT6LD0&KRbWrbli%q@Y#g+ zY~9i@Y<Q#<4m($qbvPGR!G|p|h>^yhWYyPA$B`ifYqze)-nugt`=2J*s$NgFw%Rm& z_>sYa)?3-R)-&+zXv8-z>sh^$a7-#d9I|aTyYEVPh5p741^hC6Dx2ao19v1y(Ib5p zJ7L>&?DR&0^U4xf$)V}^c8)V%A9#Vi6BdTrk6bX}(H*vV$8fZ7CB;+2ud|&$%)~4c z25;@mW>+4ZiD~T}Fvw~bYsZfr9rI`XCAd)QAggZ|j^kcAW0y@VJI9~@E?&=8__?gV z?A+^6oZ;FE*QM)acFqsQ7FQ9Q3=NaD{WK9>HXvS{-Z8WL>xua0Lo0k=$Af*CI2~K{ zYK?6bbl5I8rem|tZE*7*E%u}=2n#o~!pUBZ*qeJMVCm{sSSQPe)qODmw`;j!eg8yu z%&}0sneT=T6l2+51)<n>jT>%18pUo`n~YKW05|QQ&-NY=j8XhJ+V$PYn$-@*m-!MT z+%>jGqbaz*RD!ApPq6AvQ_$Rx$MeuztVLirhP-ERm);S!Egzpt{JI@9Je&2;pMp<< z+hB%m4_ORv=SrtGIK*y%EaXZEcG}SjjTWzx*?R?}65ARB^XF!6doT%GzHN=RMmm`< zHie*VySCWzWjFTWk|1of%pK>P_F_2_jJpe4WAc(A?BY8?xYD&PI%S%&TZ4k|+Dmt= zu42fBj19)gdaZHJ)g-pr++a+;(+Z!y*vOWZhG3VEh&yMeuqQZv9XQ<@&28qh^;3h< zW^Zdum^hF1sx<}EHUjq2xW&$ipMu#<0Y6&ZVQ)uF$2$EOY}2QJ4c;*Y_v8V_PRn7Z zCi34?%mtKo=HG{3JiWpiSmNl8#IuL2gpa@1G5$N6xmPkh6oRm`F~1(>FL(X?|0sLw zuq>YMeH;vIz-|RB6cELRXXe<QScr|-n223i2nv!42r3|=0!k<n&kWruNT`Sin22IG z{$}ynm$UEd>ves8|D9_&bLPxF=iIyduzRoSP6-DJ?*Z?-Je!n%*$Omb0z`G!CdyB? zN_g+t(Xnu=r4LD(V+o!mW5JT`SHH<p-aD4h_U>LW>0h}MI)A`0LNlFAQQZYj?3<CF zXN42%-p;VEyf5_ZlSt&%j!+)l4+2l6knmn-AoPna1UC#JO?Eqi@;yx$_Tnai;b*|c zTMG^p-6U0d_R!&>2B;NUk{uIILx;7RFl~$*F|Iug&ewXvjHC9%VTS{Zncou*%pXUd zk8*%g=HIM&t=!4X0Rp#Zz}NYG$e`7yA@^%vh;wKox3O>l7u()YUAkLdmU#wNmuW+G z&rrGDb|+{zMi-vWwvxA9bp~E;)`7XTdgSC$XMpMYF!)wya%Ytz5N93mx3?vi1D&DQ zD19(1I8GWpbp&h8eh|^L7jmC-1ROyNEPu6U?+_k=nc<qS%XbX=(Blw%%+!KgxBH{C zQwJf*K@;rQ|A!n~9|qS;y&?TbALMjf>d&9=_;VS5p5o6hJm2yh`!8PQ`IF~Ko&$NV z<9Uqd8J-jPe&lP9?|r@>`TpYj1uYv44t7&xK7Bq4TIuW=>y(Qz{Yp;3n+?6e;&4M* zUhPR3X{7~)J@(39A$!Tb&ot434-aP%i^X<emaPRRSBJ-RPql&MI8FGi<RDL5ZU?#Z zv>|w)5qTVU0;<b3pjf?9-st)%NzL%rB>XiS@2_!46Gr#!L1wwx!qEeoU}jt>pWnt- zG8dl%|K9P_4twygy|ZNF+uwrulPvK{*?IX!^)Sgh%ly3_|BkacwZ=P=zsS12zax2P zdC?#@tamA0R+1kMGe%s-srv3RO}7ZxInNgV#$#nlmZ30si8Y>Q>M2+GaucFWcHtH; zPmrAfQro9$KVG#!nNB?v3VS!(<EvU4bh5#1FdH6%)%DiJyciNGvH5$MTL#s5m#ZD| zj}3&J(ki^CNhJx?42JlOkNBfT2}x)7K~H1r*mM57Np_=aV0EkpPjxAjM<rf`b}fG6 zOG;PdtCnAZ&+%0_v0$cryq!PHtow*h-pz`MiSmVQ_QiNb>$I3hHNLPS{V97^-!*23 z_C@%)su*v486)34-W$eOB;#w#Qsplm_`vk;x!7lL0a<Hy3Cx1!c!6U%>0$2&=lrAb znYXs&+j?J^SD1s<t{);<11?DJRrz~T{yvVszvJ%#`FlqGK9s-r<nL$sd)Rq81P}C8 zqqzDiq;yHge%;lmU*jOj{Vbn<%Knzn!_JI2UcLgOPB(%ZM>mtJBd)=qabNMFaqr39 z-~fnEYXXa=l#~1|{&2QP8{*EmlV#Rt!74}_rflrXt})Jn*WgCbu9vP{qxlu6W8bsi z-@dba|K!VX+qw^w4`?I5lj{mK2Y%qRiNq+<(FYQ)G=PAinzGE*7XiKP0cvlIjp_=W z;GpRX+_c*<Bb(XY|MVX=@dMtr<)+b$Qcua)kGKmQHE@uxp=aRG(MsHYmxp}GLU(wv zrUbXJJteOmb{>ul?F3en`jMcg4)7@L5pMb2mNY1FhoNn&@DSs-<nYS#pd4I)CwzTR z^1?4d*@|4O+y5vr@970mww)lYu`{{f><nyPuM9y6EvWWnUx-`V7c5W-anp5!-r2SI z!J)P^{Oko7m97DrLDgi4jWc*zb%jq(8DzMLBUHEV535EFAU=oP;KAhnaBbOH@+`~^ z+D+1dk&(`%&rMgTRn-BL27O5EL08z?t{+%G&LjRuTp{L{Hrzj%PTGaIz>9WT5MWb5 z5{5d%rLNs!Tuu^MG}{rHb?*uNU6RPM=rdrny*JcUl#+chPEa$e3;1<)BzrrafvCpa z;D??w`LWvpTK?<|VOcsP=A8p%T<Z$8%0tMjvC`vdZ@a?&?w94QuAYGnZrx#Lb)Y;y zRqCHRN&{9|os90k&k589YJt-0HZcX493fb%FN8IkC@<7<g^Az$L5a&md1W^j*tKi` z3@&BYB*R@`xpH4{&3;H$ZgrBJ>-lQ{GiP1s7~PY+dEo*#vvt9-s}qUu>?%2*^5@*R z$r{jzUFWPeJ|np{==r)ESoCrwp6q^{zXq6X+YOX<3@2}s?IqU({Be^*J>c=@YjTZ# z((45N`oYnn7aW{e5<Rn(qvSfFXm)@2>N-T;ZJ)E`nt|WPf7J}XzkD6?d&<`~zo&d( z@cYR39lv+H&HM1Z%<n1B1AJ}sT*22l-!FV^^PIzT5zq5H|MQ%~b3V^AJm>S=!gD_F z!;j^8gFi3uoWOGhe~#eK1$-~_J<j(s-=}>4@_owpCU5io$oC!JYy9tl{JEGvzw_sP z{<p;czvp`XI$>hdN<7E24IO*d2hPu|#a#>3>4kHbB^=B9RLsl6sUrr^^gw@j(kBk* zdbOcBNxqV?5f2|>yI0zD?VYQV^VFrT&#=|}_Vk`w5ZoD-i2IDup-L53K}#(fs}AZ) zN6)+h{-1KOT6TYG>k$anz3yXu-EMT0S}^FFM6zE*d(kF&f$(eFZT9|2TUy~50NOq* z&Qwk6)Ak0O8(xSfoKUCl4&IPl1MvIK*C&77!pG-h^5<y&+|B2}pRf5G`1tcitRtf4 zQY-V5MATOLG$WFTnoBeGo+P3c6Uq4{7d4lHhjb&N=2Dh(dm`#7Eo(lEh&oH>j;Iq( zLy2fAG?bKvIuTJTiT>~;qJ~mYMlSJJXe&82?MXxprRPgDh^Up+^;SzFY9;Bmw<e+{ z(!xP*MAS;^q}Gp!8cMG_%qF5HlK$H7a#8yza#$N8Y9igw@Fk*FlFGr(MASrLni8}| zp?6gGY5^5>jeIXIp`zZ=+iUY^qCy9$EM_^KtI#+qj4-Eq3hg7NBSGgVG>$$5Y@qWM z+DG!jDOA)u>ftwrepcujnY3s?4=}x>D5iJBbdad1gTyqBsHkz|cg2{B+DA--f{GeP zP-#j<?W5~GjH#DG<A`ZxP*MA6g4q``U7>e$yp1Cf^^TVJUP6~EG>(`K4;8hK*!4d( zP-q-69U*F<&^}@sM>JCDkH!(xKB8~&AMGP{uR*6NG>(||5$&STK4Kb2bgx3=h-n|u zLWTAb(>S84FaKy9G3_IIOQC(_Tp%Zc-qCiZcQmx>6uI?R*XX~wn0^r*dH#=n5z{rI z?h0KaK2JV}u0d1iQ-!Y4!gpze(={TZu2JoPa`HX*kFL@F$C%nGbdAhYe~@tsU8A#K z2T)PJ=(39!5p|8sN^cWU?}*2o$CIxIrX@l}{i3&4S~N+aYs55&=pu#Q5swwqIHHpj z8b>@<Oyh`(8b?gmh;~)z8kw2*pz2K5$oh}2(SI@7|KsQsg|1OUjY=Zu8ol|WYeeoV zbdB=e9SNsvL^xd|I!U2x^!U6j5p|8OsQf0Pu91!HDI)3`F)brHN}*+Re{?Wus?a!M zT1Iq`Ld%G03ek@WjU%ROMB%Tl5uKyZHL4!ln~1tbTG_TtSL~0L5kD8xHX)*x5uXp! zIiW`tT1HGO>A#qK4ov@q3ffA7ei73@q2DV0=o<YiH>Q6=1^p#K*J#2sT_Wllopv2S zMExRO^Mu#T;c=K$aD{NXM*m@zwxtCXb&YtQ<a>ed5uQJJZ6f|S@6X%3o)|xt=lp;1 zJbx~jK57&Z^^17k=J`BpwjmL<jCh;(;m<*QpYnXgpPTq|4bS2Hxq#mz9)JGa!Jkw9 z)z>@^@IB7kJa6#a&Yx3w{^!pxJh$`b6rS684&nKq=M$dC_!?juME`Le(<b`wyv*+f zzmNRB@L2H}&eqsVPB5(@U|K_bZ}NS|_a@(K>~U3kO`$2IGE0|UQ)mtGJ;?W(`{cef zO`$bZXY-b<OV_B^{Nej<{5@SFY6|gMLwrB-eb+GhDp{=18shtIpha^UtI!(C+V3wn z-#ijO-{uZe<on3iuEXl>XNxb9>!%FrbNJWw#*+a$MAQ-Dd5q^zrV;cX$Ev5Kl4A;e zp{=wN5jBPQIJ`g4)ylgU5m8f!kHa5-KD;#%^@0jYn-ft-D00F_xu_S!=gH3thq@C{ zJBZKi&6nmx)DHUBaXu!W18?&_{9JsV{9Js_Ydc&ejTE{)+DREi(DUiW^n40bl!>VG z(`B?S5%qj#vHIDVqJeuceIBOCL%J$7d9pwCqoP(1ujj+-^OTvcBBE~3r(KpLL!tlU z+;$JqY%vrszhei{rk6<YNrQTgAYQ|V*Y;t0KJ?dLJs<i)q32T@Hi0%B|3|~8(P|le zqtNzY8a}kKLc^!k0)6VC(Dph0vMcSR(D0c)q8ZIf`lIc`>-h}Z(_TJGq1$7YXd%yK zdOq`*o)53{!)y3NdRY=d+h-Ni_L(7XPXrC00H)!?Yx{gRbeBI;==t#R`FVMrA6~;p zvqMWFYWpxfA0q1cFbyAifob>v)9_*1K6Dz>_NigoK1|PtdjHk)p)ddH`A|{MhiUlG zI{QBwK1|z(u2E?FFg+g{^H<M@%=)Y6L!+3UPeZ2XGuiMBdB!w+beM+E#27sqsnGVJ ziA`y`LeJ;uz4ydeq32_}TVF0}_>_*<Aa51gK1|Pta(X_rN}=cT;CVahrqJ_Y8a_l% zq2V)pX9nq~(DoV9a5@n+d{X8NC+8H}KIgW8d{V|mV%2dtq_hi?4^(LT=x_3n$0@XZ zrsse>rtXink6-*ec})5rZ6A55ll-ef&u7AcCggO`ADy51IY)@7=hIuii2P9K{5V{` zN<?iRJ`NwB>G{y^R)4g8n1&Bk+IK<LmTCAfZ67+BY5TY`Z6Co$U!nPP?AIXTqpHb1 zWBEgPFO}?4X!tN~A2Lm$?eody1PNlAKjlnUhrPo{mDT_FM_x3f2~1<B1=IO4Y1D?U zVcI?&n6?ko^C8WfbU}$s&xh&!5PgNt57YLc;R<b^i8B!uw0**uw$Hi&Oxs4G=fiY< z$Y6!ek8!0k5w(5n$LW$K%-@-5_~@+DCpC(B9aBb;<_gW9eJ6d$U4@=c+S8Ln)cMif zahnWc+CE?YX!}r6+lOiRP-BILkMhy}belrkCux6cDro-fVVXZy8!r=4!^iL^A}tl# zK5NY4<lhe6B28+0!o?m-$uNbsPnAKAJXfIw#B_cLr}INjDRh3+zm24Vw$DDM?KA0D z7b<A}G-U5ApVa(71f8EzOy|csK9mSLKiN#@=i#cEgwy$<%@sO7W5zhi`zv&Q+HJ{^ zi#k6%COlS~0}RO*g@(^#mnB49q2a@Hd&mKWZqJPcUgW((&xdLF(1(9DeCSh!h7YgN z%0F|+KTpWt%kcL;%%5s0o>83lQy=G!4MC5GGhJxa!Fc7i2pP7@hdKJ|umN5xyVf=j zhU{L04I7_A7ah{Uxz94Z?db(HJ%K>;CE9q;v5#oybqc#`bn%dx>e%u_Ea*n8#JY_N z(3*C!u=jv2UY@j8mgJEuiO<jbVuKF;{nHVhsYrts6We3s+pXxh<UFXEHwzzn)0kE} zWP{C9W4!2)I{m&X4|WxI#(jQuqzNYqBtFi27h<E7SaNT9F7#=!7&o*^BeyK`C1dC3 z>tdIbPNYxILh$v`!h_#tk&&^5694Jv%yIVSKE%jAA6|^s#vWrd$+eF8AXD#wH||d& zUUB)7v3$%hm6f=4-+=_S=E9u|=D6gc+~`@aYzdxxe10wb8hIReACKo|cuT^3l+`~~ zvM)UT{J!ve!Ta$0$ouT;UQCu1O{dZ8L!mIU9~JH1#oE+$Xir-3AOs$%6cW*%{6(97 zu&E}_ns;GWGi@sGuSC~DK1}p2BDWQGXv#ez`b0L@qk&Jm(g6)`f^M}Atvfc8+W6mu zi?4KO(vg*Pn@be9H_)Tc26d)iyG6nP<#!};^(Ly75?XJUxbLUF;n7fczYFDU-skSF zLo@`%*ZYWescsHw{7{{qFe30oIhUYKtLVA9Sorifhlum4hh&j*Zr)wjcF{=F)cQE0 z{oXE%<V|WuT`J<C@uM7a)^{;2{*erm8-5`7KAX~mDcSJ3q%#%mzTZ1jcYSl3G9(Kg z#Jwk?Ju@Yr$d#0+vs)^RRV^fMSB#|_k7U8BriDbm=`^~QX-c=eo=-MzZ$MwPOQ~P` z`|hpj#PNmo`SAADlp)kPv!LEbwAb&=Bo5<V5b`(&(l2I_OH)dTyKO$?l;x1mN?*ut zjeAg?nN2bxyVA3}^I=b71zDT7loqrNgQBmRRJ7xmzqm)=v>uXpvV(rz6b*v?bJPl| zvmvD34rf~Ejlag#+beRmP}TOSP&A>Oyl*~_-anfSQJ)@@jao}-OXaM3pNC_c(erip z>TM@h2QQ8nfXz}ZdZuS9+N4DR^!@&Xi1rZS?~0tgcj(eYMa~`4`%rPLU<)x_Sj-2n zbtp+6OY=`<L3eh1@zMG8bW}E&6=_ou+lb}8sF=^q5xuCG=k@|^`dP6T9a$W4fBo+3 zP_br&nBsZ`TU@VTi}(n(h!6JsL|RN)Pm>M9VTXMuD%ypII@5>2ZK>aArj3951F2Bh zLT&F^wv>+eoeeQ;@5FvleWOF;cTS`8e`LT)T|IhtTLZeZeF_Y1uSdn2+~uuD#eE;$ zLyxNd{!N;kO@&e8b*WJQ4y^tUf9X$!+Vf<!=hJuq6>BV(_2!=Wf9iyvm#+bVA3|== zpocHstmlDeZ8fN)`px=%6xS=%Qq;|5)Pw26^ZhH}uvB{kJ+(EozJ|q~6)+Kx^SB9h zD8}KrLf|Da2cAy^juP_`I7+nnoOyoZd5q7Q?*%?*ejoYceE$6Y^8UOJzb?Ml__6#N z|Cfiwb@7}m;4IdR<wM44iu!-NJBx@lAoQ%*3j)sjla^8Yep&T<;c{^e9kD4(QdfMv z@x8;>3?GN@DWQhNm^=pxd5Xt*J`{2j^WnLo<NX{G&1!x+t9hOqJ(gq<vHp3U<k!pN zz;i6my*ws7U-5YI+|KtV&+`HfBDOrA@La@m3*Vc3Kk_}u^PX^SwGa463>(}7;hg)- zu!3B!%m<$L1pchKuR@1Ey(c+G2t2cDP%FAkvruv#5jaOYF5n<?vcSD!9R7SEoYTb| z_;ZSIei!lyV)^j7@j3I?2K+SxpEJ+@e9r&NlVZ+1XYx7o=MFyS|Gg#=bLOv4db{t% zJKCm_gGxD&+T9*&=H!qkX4%kt_8HtT(~?BG<-n5agLt9oTGD8KE^Lq4fptQaDN)LV zx(z3Bd><9M$|D25jM|Kq?zgA=&68nItu+pG??Ru+lA-n6EqHdP-gM2;I4G#vjpyd~ zr6m($q3v!*tY7UUcQa?_DZj(G*~^1+A&2+ifCI-alkN7(fcpau<Kpp~Wx`z1`)%>C zQ*F@LG0CvE^8xlsr8*MkDt>+pf8IL<X|tFaqYmRAmJ^ULm;328ID33MdaO7J%x12` zXFRm1c77~-HgyX=?9hk$SW`HC(HWoUs!caPj)LKv{P6CGp43z=3P!&0$3}XZbk(~k zc<kbaw_NK_ePW^^=0^lx`L0#H&+(U$c*qE~dY^-1;&I0ZRYVxu>1hJ)n)8eZW0!tS zz};>Zl7@@#z=fO?yw%@{EPfLK#}}kw4`pYvD(?<_KA(h#wYW!GqDYWUO~Jp^yVd)b z7N+7sTQ%yBo4O?7TN_`?h4_X}a(wdrY(v4mxq#x>;dX|?Ty;HC@W7haa={+zeI37< z8z&QdW>f{?D_fFe!g1ShPdxH!XC$oGc9S>WHLn{I)|Kb$jJ=oZpq45z@WjmxYp4!H z*)L)s%jYD1F=z}r@JtRP3r}JDo#Rp8>rBq{{9%0EX)+pfn1auYJ^0GPu}Hwy<AD`k zZlj6>%pVTig9lV?lv#Rb!0Wzy@iEK&@&n=7&>(sjwyHHJFIwk9z(h;DqhT@;j&H!5 z@WHuCRPaBC{cs!nfOux7L%=70oYLqBF$~FoC;h!}|AH3uxO*zB$#ldwV|r4fZi!$! z_9!mt-k<KgMxaad6&$T{MLs$<9n|~y;)4C7Wo-|qLe)NZtm3AMynZG?w@ZicDBFJY z{8Kq(oQ%PtH_FNE@_5+h6pJ@#og!;mC%}z_Q0)1;B^^>82Xk6q!XGPo(uwXAR*$mB zVXPj;J&%F)_bBdosz@Fl77z26+`;FXI2c(w$HD0t0k~%U6WP_F6w*}eaJDYHXJ{A$ zmoKK^?hhR6Yr}i<F+49wizc6m1qeQl%lizVBjRJ>xz}-g%SxN(O^64TrN{8?2O4yr zK|K6Ae-a07>`U*vC4kjA8@%{x4|<q=7wJ=}JuY(TO<^I!VYEH23G7B6TO`8fFD`hK zMK5Z!AQ9dcxM1H+U1`R~M2Mg4fg{HEqD@^Az{kM@myhjA_j@EjZ*wnf)UP-FJ|-T{ zJ@>*thj*i<1LNW74llf;xDPcWv0(7c3!iV=g9e?7g{@W|c*~Q1bkQaXx2XsIVW>eb zYEsxd)D;^?^`{>K2?Vrv#p_3C(b01VeCq6ggUbidFF^#1j@V-#t6p@eF@XzdC-L^C zI&{ER_Q|AF8@%&UFY3#d!(-AZ)&>`z(xG#!W5GSt27l-~fR5CSmtfUg#}2>Q#qP(( zBuKEjW$l0s-}j~4pGdL#e#!+;s_R4D%M&D6^{zdK_dV*v?&%UFSbaL|iCx_L(zgBM zC0JQ8El8_h{ixoHSP53Y+qq+#p#C&GpGvTrPhGH{fe!s>AjL}UmIK!8t4ni+PzhEq zX4&D_6Lo3bJu1Pf(F`ZNFGZJTdB%b6Ku;V2jFX?H!ROxIScf#EZimt#bgdWGE&oXF z?#+O4W**pW#~ZTcV>+-Od$8(|$Hcj5CagC(kK1-BCR+9xVA{hMPac~^iW+1>Z@Y{5 zcW46nb|M3oG!MYnHR6f>#tgV#d>NO8N04)s>0lHTh`VRRk&zqH+4HN{@bLu^M4pod zeN%4W-Saa^-uN_#)D6ZT!s5wA=TxvddJ{*#eMH=*q{8K|!T2UAB%h9^fO%*zcJpHQ zlQAh^*&ql*ry62doearY*Vr?k4XI;%3dH3F;C^vRjBk@6uKY6ISKO2iUz7^^M}2Xx zSQVP>ngW&h5-x7gjOv-D!Rh1P_)U!py>u;Af=K{e#8;X$pr`E9VS(QToE-L%{9ckF z!3y`jgb!v_kQVtF60C+U_QQ*`3&`ATDOQmi1Msjf>7>JKDONvmAojbNPG0SkV&$F_ zj5Eyh$t7DURxdZ)VDI8TA-$rdST%YTg#80Pkd6~lC0Ma9e&I5IWtz+I<gv2x^~Y<l z3T>5|D#2=8t`9acQ=wzdr%AA?ycmED$Q!a^aXKigT&Ab?A0ajJY*;bIt==Bzd>2M0 zI?_}tccTHpxzMW0o4)OJ&gk^oEI7UPB(-qai`157f^o4kJ*Be~*%zikc*oK7G>hZe zq73R12G`qumSvEBd?+nnp&PR&v=p+^#!|<<n`5rAZ=x+xn@@M|--B*B=0Mx#Q|ReF z&rp-4DUkMlCCxnW98DdU3@r?H)83|gQPB2mke?k%Uq&B5S^>Gx#BwCPiE~izw`maC zZwUQ5?P!dZ<$d@NF^D>_9NG_m2=Qx&)#vc!ULg$g89||aOmwIH_u$Fzk#zU4WoTfx zdy<&mrnBf#gPDl@D3JJkzP*fYwd!Ux&ZGdU?H17P%|fCR*Ob7$BWCsSUr#TD-Oo(_ ztbNY|37$M|8v<RaQ*cVm&?D*avA;(>&f7O-NHCP!o}wY2Mxk2^QsA4@aq1EpkFM-b zg0n-csc-ptv@j%5vi9=>hSN!(C!kcHEHLRejP`gPgrYj7O5*eLcJ#EQ<@TELl}TAp zanGtg=dr!mKMuHgjY>DtC*uu}OF)_=CO?;D1bZ&%_$g$*GX;hppF|T{B%t`9B-pTe z1SJu=$WOV1{hw$eok_Hjc}_8SMjWl5ORKH`%#T~so{8Iy+G*v(keR!w&xZ%-_NJtN zuJ_Kv9dr_eqE1?g@X~)It=(}vW@neX5YYe6{yH7Vm*l|L()HEL=#ihXXu5x*q^|gR z`S^THel9)^U(bA<^J^FOJz!W9D)fsH>!T5)n^2*TgnrrBWHc4}Md+h-nq#QYM?zn~ z@n1yf3n6}|v%iVZFG7z5JRD7h9uaz>b=xsi=mnuib{g%ZLXUJ|y|dtq6%~3%mG#Aw z^XsY57ec>GsUAaxei7<_rHV2Y>R;%WB}qSt&@V4oFFbE%NX1?d{rTgUSzionHk=B5 z@s8F1zHZ7?sDGg^R=#OOg}&I#YI}skS0dClzxG&GS0BF(qC!3MYxiXJTxKzw3iT}1 z`TY5-s8Hv8{z5%_zc-;mJqxwh{reCq)VWZ@3sP%|P{aJZV_DtCx6-FV-SYGDafDjk zcw`k7YE`IV4VX-Y8s_5*`zX7vM}-<TXEj_Ns7r+!Ud!s%W0DFL>(=!17An@Qn7>d< z`rQ^&p;q}d*0Q?I_4!GJy5;wa&xhaBP*%5Td(Eg&w|q>YZpC@|n7lt<Km1x8lwzpv zp$_ulrqR%SXCf`R-iSQC7YRSqQfcj@7xD&&<S^Bo($W(F(Pe3J=rG_U?SG&LDs)W( z^}$<ck?}UPmtDK6hgr~$#z)cKxdcMSonhzX!D!Xp1c+XFi5_jXpY$G|35)%`soBrF z@<8_t&?yU{+X^$}Pnx8IiS{jO&3wwvq(gejIjXVrwb20ObSO2wN_B^Il^tg1!FTUG z=z%GQsBh<3DAYbgjdvbH>l(#C=elEb{gT7zk!Lh~nsuHAWDP=n+z2GarPG5f=D@l* z2sBQrw{^{upv)tVp1GbNAD*2E=i4UJiEGm2*`aZ;U{VCFjn|VMyqW-bTnx=Myl({M z?053vY4u~1aw6fmYi7OuIY$n6-M#A9Rd7EY8iFT1Qu<o1H7s4SMt<!Uey;S_nEi&n zg{hJ?Hl2Ke+I@c`TTq-R!M69MO|+=fBy?#Q!<NHYiG5Ra^_Ruy^IN$Db8DM@RCUJ+ zG{inyf)Bqh{Mgwm-03OvrpR>`yC&yw<MH(TeuPeFY=Y97Mnh!xaGEC9GVFaYR)P<I zd^wJw<sGVHY~rOg!{a$-?QI%7)=K^`HX0U<A++;^j^sjZq@?!vn(VYLz8>=)Ny0a+ z{_X`Ihxg}m=GP+lc#e8WggO`MdHu$3M5t$>&Xx1yiBRW4{kOgqRbT%?4XZC6K!q9> zFw6`FD%7^H7rPc2QlaLBUTAr_4;6YrsOR4E(uq*dLY;54OC>^`3-uhlwlNj!xpia{ zD%7)p`CImkx=^b^p6?7W6>3<h?Uyi`3bp--)qMAJx>Tt73#?YF-=-6xR)reAzbumo zH9VHps#{JYD%7e_!)4`7sZhgw4nlpd%8w&Lee(GTHL22|jtDi$uSKZIHdS4zP?P+6 zby!V)&CsXyHOXNj)YXLs!>CY`Cs`dPYYwME9rDL{4EZ%)U^Ui8WhfPDjK_h;XD+MN zitZXzs8xQwLhb#S$-arnYLd5kAAYaRSberKsUbpr3iYGA@(~g0kgpBC29~n={IDjZ zzCL*$e(b;U&s%;B=Pc@r8mx{7^7%OKkuwg>-Wm_5RZd{sc?z2NDi$7WJ%%5((nSez zv2d=VE$*N{1=*gZaE;pFG^VG2+n9p=LI=F9`FNy}$L^!o*yCc)zUcFQ0+W}yVv80= z$RLYAYLyE<@Uk0{?<Qcy?&TMsAA}yBqCoet`}*sx(a=d0dLHw_-A?pFp$}uBO%VH@ z&66fbJv0^;vithZMp`IwWjwSz?}cybH9(W*$HS~u9=JyzEp+&H0t}hqfq%7cfaWD8 z!1P|OxNb^6^lD!s$oyS!`lTkQtw$obb#uTUCJ#b+hZ3QEKYOfh+!{^rPJ|7wPvXu| zhNxd$0%$tg;1b7fs4yo%g2}S3Co%ds8Rg842Mg_!c=FsCD7rQK{e;6RGQ<v_TRj8m zu<zFKSe;ZkgTM8eg67SaVs%u>759xCgW59;d8{T+amTkik3z<^RD#vlXit2}V=xMA z94Eo*Rj?=aG1Nn`lj0><`Sfwe+qL!3!W9V;tTJ<5@awgM(ZEKD60GtH9dL5tNMznb zij}Ip9qzkh4C=Q&L4wutL?@ijzR3|26$ks$y|JHFgnaMm3^<c<3BO$LE+5-C6WVRQ zh(n?p$P3nFfQqpf9=~9)JpM^KjCQ+(N9Ac6-dmmyYL4FcQhZkQwv;qbd*_Fho?bM{ z7@h_e1ATDl>4`>bPNcGZzlyacY&9BZlnQr;Ucn7wo*1s%l>*D>2IGN6gJJ?gQowI& zARY`?W7=0FL;s=>+~v)5c~5x?sI<L_-(5Z|-})vQZWx4Nw_`+p)-)9k+J)ev&1G_J zj}$oAf_($&i!!lanFgDu-^7u9+Y{?ssStEC7&qS3mRzz+hfX&FapfoWp2o*CxYqa@ z`woyQ>B)X`xDs#$AMw;8M;fww>KT`DLh=iFw0b5ybn?L($5qHZ#<4smYtwwOm#V#d zc}@mgyy}Cq7B-ikoR%TMYOR+qJ~lffdc}4rR_12@SmUs&QQHGjtX9je;a^ug43`8; zu`<vK#+|c{$2>Pom0-2DX$W?_FiF0Ae5wR1eeF=(CoE7tg58hvSZx>@f@?~i%GX>< zlVG)eb1-hPP??0grAx3{?RpJ&*!`V-`#3{_)ukK$7;VgzmlR8}x@vzNCl=3_7cEQ& ztCQAL`=CD>ygv=*F0rPLo5GNCyL7nF?l7%$i${U4QejEI!?aPsZS;WEL%Qm2>h~rG zJ?qJAmtAzq&?K~KWeOO&Sx~*IBBcH*1?~>tNT;V}p;i4-;6m;SdU9Sda#_gkH*J>D z(WA4GnRg0oe7cZYYUZJ?)7WnvHS_4LgUKktFBQfa&ZBQeCL*(==>Xqm)75A1ph2t# zE~YP_2i0$($e;``i<wI=j|o6FLo=Xp)iPRn=L$NoD-$esE}@p??x;>R6Rs}ZK+O^^ zplQLGu&`hqoj1b~)lJR>)N3alV9YcVA(Q>yXhjd*JA>-j?>Spr9ik(S`=cq-GuXSX zhv;Xwb0{DyU4n^s(?c}-Lj>AAHXSxr@23NIC!!bA)1+7#?xeR4<e)?TQmjtKS<pV} zg{aA%R0&qEo2;V67KLbcL8=6+g@KFduf4g*$tz8QRid8>9hRSjHeN`VVAU|*lxEL} zL_b_uopV^V*uIj^W*WifMwt?<9#?OmMYpe@(zQ~o_FdjV2Q9jSHnx&t)lqpr{W>)W z8IPA@rDJPB{W21f@tt&7^kND<-|Y>0JTnf8`vR?!=OWKN6fE10q%u;0Y7S6%G-EiO z;QftpK6`~@mLYxKy$Qa!AXYM#KmNS&I6B$36@FUFuCKbzq-#x7@w6Rr@b0V$O`6*b zUn6m_<oa?tDBw4m$+)q4%St*l^#xk9E)M!`UP>=&-$R$#wGeMt+?hu!=A@$K6JsIF zcM826o{VY}D5Sn0Nc+2$qaKMdFlwj~eHIvt++t#&{}UbBqDvzzn<a<hy9RW_r}lWg zA%V;nV`z3;P3$p&N{&}|Vb59Y)xxNMEF2uSmL5;<j3-}>h1z45v}|58OfSWP!`Yqm zVe@L_!=4Q*_uoQ0&Pzo*`cruCu!2tR7>dUAAd=(xOJ>l_DL2qnLpkjHI*6_s`2u<0 zkA$f`f!-OBfZpUq!jw&Vbm-6K*kWH4yOtP66Fqz4uXfR}>d{1cd>hl5jE#YqCQE6e z+CXfQB8P3ix6uPCy>Yum1T@+nrn)Mv@zU7@qDrjk-02^Y!wor91n;BTYMH3{#TZyV zW&^#xG87%!5G^^b+;JWq*yjeizA6d|JP>{F`2`u-MgV>|h5CgSp)l(R&^u{JYrWL) zqV{*7boUrKYqusop%e*uXJ*r|v+Vo9EutjHzr?SiTYu@{#c!kF=qoF_YI+~Md2=*; zZ*NT#ire9;HPMiL;RrQus*LG_D5#!(kd`beL!NIV;ma`g+)ej1w7%+&<alwzCDd_N zGD=pu1Dkiup~*8F<Djj#;jWDd9pe23EwZ=`c{gU!M5>Nm*|&7PLgrFc)vkEilnAC> zwuElkqlqt9Mo5k~+rO6DOx9x0Z?kW>f7wQ>$92c+Lhit<7JF!HVq4rYh#k+{OXKG@ z#eLZS`!sTQ(we3}(W-(7DD1SE4lsC&x{r#G91m)^iq^Q)pqsaE!}{TCsd_tA-0Pv# zKDT!V-8$h8T6!WLPQ`AZyKaS|D>@0_XR(o*?~X+0<|csg9ZO1v6O^734^tklpj8j< zpf>RdP+n(7TSpL7lb-;Kb}XWe+oqw5JrZF^$Pzl@WF`t=zf0JiSU~4DDnmnc5@FO} zQ<`H~hL-6ig3kjJ>Y4ok9jQ!!VR}obab_)=TAKi^?k=YWS<3j9X#%w9W=6-3u0!Gb z5<uhhdV0&X5#Dh-9&WAKK*t<X#!uhGgV|O~y4hM8H`QSOOS-q6K8*W?&TNTizyIu| z5gG5%-h?<9&}$Ekd-E0*^^6D2<OB4;{ZjPkb{zEf-AB919-$8H+5f+`?xW+?Q_-1U zaiD!=4-E*+Ktqh<AwYjSJ?qW%&e`?$m#Xy?9^XMj-^atiT`TFwZUi0KmH^h;i)r(> z8A!%3vAJeKulYP;-y=)_JAYHEXHbjE92h>XD`@wCUubfd1Zetr9ldR!jQ85d!`<oI zXhgqXsJCi7>^{GXI?R8IENL8U@3NPE_AN!>;c>9D$8KuXCIjWw#=*g5DX1r%j*VLc z!=2(gXlj!|IDTOeG_wjpmA)Nu>r-;b|3OhC``()$Ch(@F2yJxgfX`+H!n9MlsF~?c z^!#@WMBZ+Sy(g++)0jY5(Wo)DNUA~C-^9T76Iyt!MGxF{U=U~)_Q2npsNjt&<xra5 z9}n+kgoB<0!Ld$#aW2)uzuK`L$6atck9oM*A{f@$cfbKdWw_@h0(HN?p~}j|xb4AU znCbl<?LRaQn}-rf{(PSNTKF}VK4^f)xedcHUO|$z@cHvO^Lg^Q@%ixc^0=M2TY+A` z?2MCc$|YE>fBqY7nxuxm@0Uxk;_(^(swIxyrGbrW<q~{&OwQ4t2zSxJ-FguTCRyKG z;P*@?_i6KZuz&m=wS3(he_+pB?tfp7!eiRv^BHllr)eE>@7xUApNj)NAO8532^C1c zYbV^fk^pb>>*B}qIrBO2F?su6WBGMi8~jAJ)B59W3n=h0d7Gb?AIs;-=g-IF?SG98 z9h!$~26V#(Ct@L2^A(!7SP$!bXXntMSY$O9aQ|E?u{Xr}qxQW9;=79}@MC%W`F-JI z^7j8_ERO@f7T)G#^7HbT^eDf90>A0t{q6+DWT&CJ{s`Y|K_xaHlON0H$*-M{$=m-L zJ9xJf8W}tlA9x-L(^m%~r$>u%p=lU27<voo`J3P^)1>yJiJs`;j!C#<3Daoe#_~Dv zd&I}&?f=VI9+Q9N!^h<3<;U_k@cHvLAOBxt`8D$S^EMxopO>!(eoy(ic$;4fKbGG| zzOVT@=WV`D_^~N5H&E<_vH0O}%HCNBK_@<q#0&Sv!o-<(kaDph-p-!i@U6Zre8(Gi zjiFH4f}+)4gYer?anR&z0(uuU1cwcbgDV>M(63w_JkBW&9;6i_LqC1oZ4Wzs^EKLg zUk86;*WT?SUZEL*`Z#$(9Q1Hj!p0GUaCRoU&hPybway!YpX9N*lvVJTPNVSKN(#@z z8(^bPhImYiSU5JgF&>dH7VmgVz_CFCEFUxue=wxbE&L}k?m7*Z>JwPJ_$zuaV=4|m zM_}QFXDIynEPS#=4oB^tA}8~ic*+a{CTclIRyGS4DG`|BoriWUVc&Y+LZHYq3awV2 zhU>i9b3yvCD0;+HeEJiC(F<>*qY0z2?J^2AQ4vVlW+W~d7z^R65>VCp!MGE9mTA+_ zLZmlW4<G3k2MLU$Mk_e#^_d^2(c!@ucErM+^=vKvBXP(L3Tq>k@y+tlcu^UFpDABZ z%CAZ6_ca0?K3Aaw?WW@!?7Z`;X&&0paynLNOW=+tMOU6r!tWVB@Xv_y&w29Cg7VLc zc33!?YUO-GnT3h4tJ@4J53WLnO_Lz+-58oWBNd%(#-9Jt9Y%FFmm=-r1lZjesPXe^ zq%<#9a{SB7$+Xv)d}L%F2fV!_a~iEqEkZ*XKl5Wd51LB-{TkuR#&N*sz|Y0o{~Fu% z^8#Af?<4!}OdR;Pn@79)yhV>s#Y<xH@%efAv3#C<{(MZ{{?}N~s_As(^H_A~Ydnlq zGod<@9-&@e65zh|X8M`k`wv%^+JhIaq76G=K`ssAfgj7`&+iK#lehmbV|g6-weU6{ zlb@Hzq(FNmebM_STC#}!t~l3%RvybjN+$6Vn~%wl<@4m%&d22Ke~le_>I5BdHvy$B zkARaJr>Vx^a%8dW4s020N8QdoLnCHM?XF(O=$YZ^$aQuE@MHNL_&wrd^7j8_ERV^* z^5J9h^YUYP9Qgcsn~(pmvHTkO{CS&?$<NEz1HY&IT)fS%g&)iBBj4A2o%1$dC;Zr^ zhg4AXqqaCNb`5B6Yl-}~YTyuL0msK}L7j)F;^_-F!iUeAC?-G|pSZOWdhhW<E6yn6 zo!{26_qDGfc$bgHd8~r~RUM?-BN3T<u7EjNi3Xb;$7AK6wy+`F7WMoz0>2HmgJDYz z(AXd&oaucKqH2gi&o_Vv{yqTtH&Rdp`)*X+w}a4gMHbp0ppDn3*g<z@PdncUU+_Ey zO3Mn7f5C6my6+))w%Zp~=<8#RTXwKuuP-_|yayg)a2os*HyL~@YJ$%_Sq2U+wgyHX z9q`%{=D@F!Ul$)IG1V4*S=<Yo%{(oM+1kz%RX*3kSHcbfR%vapV`mET4O=RSKf?69 zL7h);>|whRc>nwBeGEEn?2oO_o`wVCwh$4|?%P@t5oe`CDkM&UfAwcgBI0~mRfni6 z@XS|X56>!a*4X1kMEnOVH6S9MtC`k{h;z=36e8mJVQC=|aqGMyi->p%wup22ZeQ|J zfv53aUn1hk=f>y%FaOw7TOwlE%FdIBxbgP%S*5bJD@<_TU)C^YcCu_`qmlT)9&0FU zA(v^Djlipi9|80Ad9t(z^YO*&N7(zqC9-~(R^tA9PebRQ6|$8_*5cpJr(uuUQ(4D5 zYj7RY;^U9={)u~@$lUg?#2(CNz4Agd+ReP)pC8Nn=#83>BIYm0yP5yY>_sSS`ttgD zRUAyvEaTPq3!9gZ!~3r|xd6TWupYPmc?Mpi8ky#=jkp=JSB|fdHEm{rgTG4iA8={` z(oot^f1HoMz<myC0t>J{!-qf4=aZQ`A5E~CTaS;*fJta;#V~BnFf6|`4gInmhFgs| z0=kR6&@a7Z_+tlq_&o9~vVA%iuRU-CMh5yA6&5eT3z&U3ajVgkL+1Dw^C^Ee+35A2 zk=Voh2=r+dXeetn3_E9?hOHgWq6vEkVn1frUUNVx;Rd*r`S3PBmbZDIkn!%Q^OAvB z&DsV0-@Bq6ZS?THyXT<MEwkuG2Z!JTIp@H4i$&D*M#J#+!!EF(%|$dk)C707bODbu z?#TSjY8<i79(rByK%srin5Ks-%vUNiT6uRPrtEmryRn9PbC%cp8+?v5GSypG?-O{) z6|H_T7i*7qhs%S`BGhm?wz+y1GOOf9@wXS@!R&a^{fkDY?E%-lbC={6xZWOp{yqx# zeD5yF(+0K}eQ#}CA1Cp|9n`5+JL>iG5;*9-t+xaFUV;_NKckEp--us#A4q0Cg5A57 zF9`kvqSfe=YHygj{XxCGb-8!FPuCq^$$e9ANb)X1g5A8-tNys=+H%rz@kQw0rwR$S zQP2g6EyNdn_I*^v3j^EI0=YMM4R4E$?7or*S1*8bXal^;M2(Jae;({NDdAHgU&xhn zo-k{3Q+(0yF)^C!C9yxZE(nt=a^8KrHcVXOa--_7UW)wNpUe*vb9R`X7$)Yx+uKI; z!6U7kQI#WJP^jM%tNyMctu}i@&csgGKB+m~@W2CR|7e9TcKJx|FY$n0{nT-mT`}3* z>Ab`a2pfqlY|6=?b?4#qjs7^2J<~hruoo;}I0*X>eMZm$clIp~4SZry3Ay<491O=@ z@sNwD#OASw#MWLl9v`Ivq`JZr8k*_hU8Ap(%(h-o`5WVT9|Fj`l5=2Utb_MiTqP4$ zor7)48hDfMRT6LMA+aCj&cW)dy^OYwJ`b@uhS+C<tC7hzFSuwi9Y62rVRUe~JG6=& zi6<X-GRlZM$Nu-Bhu8LXFq(MRLt=MworB%lm&rWGc|wh|Azo<pQ?_F9c_<h(9Xs_t zC3|=D9Lzd85}*IMN4B%uIaq0+hi|Fhl0E+EF0p^B&%w0=r=rij-Qj_nA-;ZN1KOVC z4$;BWaElYwvI5_;pszF%YjwUWJG1#LOung$wb*wz?(8`yvG@0!jiH-0I=Ijomh~8g zZw_!pXO}wzl265>zH6W)Q)dWL9f8-3Z-W+?IYSoF!8UW}p@`K|J8+i?df;43He7ar zP-YK)(Tv`*bg#D!8#JbQ-tHjy^qBpu-sfX@<bVF3na%r)HXoDs7i=-kS7wXx`8eTh zu6fVf(fl8mK(MQwI@6Z}eCq9HN0e!Gm2bWM)mw?8aer*lM~KPWyuWDwua7vFa9oTj z*rLCXgN|<pid4Pp=N&3<O-)ArvBl$p|G#X}-^Xntdf1^A?a;{`eqE0L&;HHqn>)Hv zZ(VQjV?Ls->>rQN$ksH=!yAOLqRsp8V|kwo%zxE`26V=8_xiEoy!=?+M~EZ(^SSXk z^FDlTd=C8BtP^*L$VGxJaunm+dRyRI#>4eK0uKv5B3~`s{-E9#_*OXH>M!3Ck#B|L zB9Ae?t+xff{nv5d;ccnNu}40t(%A~`^$2Z1IliR=-`@Pgx76t`-~MNp>i1;tNB`kQ z#+g*)OvaP+gn}m*{%A!xo}?U4{%1Si=ug8G+{ieSik!J-;UMa+;K|GB8g%zxo}_*L z^5lOu<3?(!;6}!obf1DVU;f5)7URipe|VDa{mYYd&0n7U&t}|6TTlGMjf^wt83kuD zo}}wK{l}9u?k`W$`+s@zKbvtQ-KOA1#+mfCf-@OU($K#=N$>vUNqX-uPyS~!Zluu) zZe*NEmGu8`W_a*4I#|Jz+Daqo*uOkU_5bqZe>USrdPl*HM|#etlNo1PG0tQ>NvHhf zNox6*C#maSp8U^_+GRpSo)m16$0)N!9uw>V3jX{S9x3q`$MQaP%;*2*&maHAe8l)d zOmW_LHkZg(f-UluV2d0m*do6PF-0GxTagkU-e2?){Kfc!zZi!f%f}Sv5;;(?Mcxzq z`QxH39RGj$gt|>6B46ENw#bJ~{p0_$8#7z<X~ygk3ZCSB__0Dvkw1C+e|^N5H<-W3 zhrG?_#^<2IauEG_oA=>!<8#hm-4H*qi6bkZ2xdI&i0>XA7qdmD0G_{B!ryvj8I_u` zcWN%aM5Q}i$)!!jpnSVIzP{`l>eeC)j4wYyw_E~{|I{2X{+@}pFRMZAUZ%m%&i-hU zZV8%mITM=gUW7#bx~$zc23c?0;gZM{=&rlgpjg%zD|Jf;&9|eGvEDDF$KDm?^(w0} za#6TKL)d(466!p^h{W{02fXdtC^;-q^C=m({oX&v^7->)`8D!unXQ_K@;@F$V_h@B z*0ma$jA<@E^*B$mE<R_QF$2+|v?3H?oeKU@=a9jVFw{#wU9v{=_rnZAyeiSxM=8Ls zi)lP!Q8V_1l@_j1XvVHH?}3{#tyepy^{TE>i3Cm8&rH*`$lVc%I<9=4{Jf42524U# z547V=24vOVMhX7Qk-uM-1h=S921wQ>mtf~2;4$Ra!sk5Fw}HX0&M_$GYC7!NrG&6; z7z!^)m*7+V=pJ$$(^Edr_$~}F^F<x9yoq{nAvhS&uws)E^0K&yX{!94_vy^mXklRz zDQx@z+WLiuH3~{4Nm>si{`_1X1~sx-qx{j(s2sR)U==dD<ba0n&V_%ix8bu3=!EHP zRHc3w?58H9lLtS<3_V;3e4g6N+8fNQN=J=5X2OaxRfF7wBsB0wHkg;?%R<;U*zZ<n z!=><2*_pZV=+zkZd|Ki;<aWWH3{tx<StGv|HKS5l?(FMi{r3B?|Eh0TbZHP-;dEcJ zMt&{bYwyb5+;%}XrsTqbSyRxsPFARHQl4au{8}zuJ&D%cG(by&?*e<N5EZ{nj*%}d zl&tY`&F#TQ($1r7m0W0k;Ry0uzMDiJFOlTW?<tQ1zg`}H-sXLHtoU{D$9ZgdOn9tH zhULgE-M>n9>@R{@&OTu&eF90gW03?C9;-bC$+Gs>5%N&Wfm6ydbi}3&s!q<4V8UZH z$mt-OkryIc6PFA7O3$ODVOQh{Okaq{Dlp1_&<X#^DE?`-1h?(Vmgqt7G4g43A?R*# zL{{msXq@adWI1^tvoBHTfXPe9QCWsa-|uMe^_TF_W<N@b%0xFqYhaM|FPTYh6-r5b z3#PIpna0hQ_|oQAV6w^Dpt`?0J{I{3<~WWuc<WSyT3@M!)R=k5@j@{gXa5EwO@|}v z295CdcP}A?%}Mtla_`_<m_8*B#m3Jh4;H?LI|tb_LDt7*CDzq2v{3?D-ONW8ck2yQ zUiC$_cq7SjuZ53MAt<?lEeUU41KK4?VcYIk5WUbhP-kL{R%<4c&wby(o#tau#Y1=Y zEz$Q--TG44l(eg4`pFMKX4)e<s95IF@&i1y^FRT^8j?}9@4+(b3Np5PEpO8DJ&fIW z8I4$xDAUe=2j8rxhE)`FBriQaL)(c4?AyTY$o0vez@=gcDlq#jd)4d{oQSy-qIta` zvRwUHk|!TuEx!O|`p+av3tvFt%0v`=aJ%f~h3D|u;123#=}bxvzJNr-qOjuWb>v*o z3pio97-iTNk)79H{Bw^aYvJ}NHu@ZD5D|&K=|2Pcy;ZXLLsfBi#*G)Rjg;A5?S*}p zmBHh0{<4s|p169!Be)t?E}NmDiZ}QdK|;fW21TP)afMS6%s%L8@cctB9N<<46Z}04 zoF@0e(<~puqqRE?a-jv@lU@ma*Lus&?`e!3k5$&s^#rtV<L_lqUhr6U(BKE!(z*f) zt8!$9QQdL(phxh<Sp|g~wy4j?F`^&3?UjLkSQf&sqS+|oVHsLv^91ty%t7vEeyDhT zk)#gCpEpHk4=Lf9cb>uiRJm;Y{?^zp=NX)?vN3QO-yYlFeFoFd4Mp3vnqq^@XW%~j zF1l|&j3nNxfM<``Gix(!NUsMKFnC*5*o=}l<oweLD0;aV8OA4*Ar;K0Bof7**cfBc z>>=oMO++JY!i@@-K7l5Iv0)E_9uV(ok0J8oOw>>9HYt~v)vs&6R!h7&p#Ut(8le$J z*=UMy0o=TPOx8sGC2Hc9Uyq64<8!P43RWY7+Xr4EJJWo~_1|qE9ACS-0QhzBdv|if z4zy|GO;phO8R#GHkBlO!P~>9i+MgI4l-ZB@g3d2^22Gvj85~UefyOP8Vp2Hv3Nm#* zjy^oAg57&<QPJiDXh?^rVAs<ZO`&!ut7RoD8hZ?lo^%q8A6yAl2OZG&r(wwT(-VM< zRp`WUAB0USBzyGLs~=MS7>(w4tdPXv=j!3(jn;+rM3aI`Br!jAvqyag??ZE)izRh( z{3nr(ewBy1@2Zg06<=?+dYc&7p07jXcO^U@{K}}{=oeJP>X6?Te!qGL1%_?u5<|L1 zKY|ItGL-z#n`BOX1iOx2L3f7jAdQnBf&ML5RP=5sDL7gRa~@qrAwBG3;;Qe1U8+5r z)~f@1&!rf$`ffqhJy)XH#*EMR8nWMkJW;z|g<v7SA^Y$`6~A0{4`jNgGG%6u8+i{p zUOQx<_FNUWVAps;{fl)X^rKi0ygwg@uMIv9--ALNvDf&%=6ja!JHFrf9^`wU=T)AU zcn;_Li|2E`zj$nUe>Janva~ku&<c}huxGnR*rK@?NK{!VxGo)ldM>vk2hWsB_K4p* zevdkKJ&IDIXOPpM9)f-=C!}re8#Ch6eaYUvd$<pEcWsH%niYfE{P`&7!E97pUMSf| z$^Pc_LM_ak&<>A#lKp-CtVDM3a3Ja%^zR-ob)F#m&@K{n=_Kv(O8dqJE7lS;q%>c0 z4ZvR;ES&aUMqaxUCHoR+-pnhk$9i8<bgcyVbF|ld3)HV_6KV0LSaPoCuK^ycJc=?8 z*~&t%<ioAWPUwUBLiyk(g>dM^8f2vrgOXgU;6n=g?zG`uG=1Jv;JGEe(H>M{5rXbD ze+os5UdwD`?B3_bQwSXwAS?b{jqbx!;CY7M$C|tyve%y~QTwzin6R{i%uD?(I#*Ez z9vPcun<C55!^hG-ZRXGi>AO~-_qU%)I4!a`LN@t&I&v6Y1;?h`l#LymhANb*U}kBe ztf6HVYH_v-nmwtJRkz7S>8Vw4cUd<S?w^eev#Y>s)F3qWWh$EEQw6!|fSRt1M>}U# z!Plyds9<CWI#N{$yCzRWx_&Wefm#)`9={(MKk!G{8ddP{{d|NHLy`Uyb}o2lgjNQ` zp}c%4AMzZ?^C!=NWu{ta!RJh*98d{7k0sSs%l!0nP~ELc;JHgPd8UENurH|diz>Li z*#LcCu7-X(+=Z!oO=M~o7U+0L9`Lo7#nmTY^Z%-I{#>y0YI`(qV<h^>FyVWL?>oL9 z`Rh;qx|FZ;C#G`;A6c@G-N)qtf1SzKe45Wk_D=S(s4e=HU^(Iqs@!HB9c=L&M$CVY zwvAmR&*}Ue^uB*YLt4km@Ar8In@)T}THim(zpz>w-Ss2#*wBDD=~RMuVl6W5_*Q<` z@d^B%^co$W5iY+gD~D;#pCjx3AfL79F_arrpnY45N2PRp3?|PWp?B?O$i{Dc3{SQ_ zM0HoAWZ_H7p~0~SX!G;;GSfRxAi8lWdN`v2%9&FMJ(@m7Y3FKX7O$$HGPM#V2i=kx z;Ae2=!wdAhn@pD1_c=5e`5J97_mc1W^g@z9zb>VZPZ5r|9KG?tONi}Ti;@SoAj>_Z zYi#wY7WF$bn5=VpDp_y0ls9NeAR^<3RZ7-An!H2@p6d|z(sBt7s$~`EfUPq5Sy3jz zq_6Hn6mr8xu6p^A1fRJP1&HWwH5_2{NP^YoQ`xBK(mC1f#77d`CLT*i%a1lg@m-`C zhU`g09U2=TlkQI>c=lMGfj--gMprE>CD<yD&P6LH4nl8}pGt5}(kep7A{(Pj`dor} zVV^S8l-SAMG<_+-Kgj$E+CS-re6!t4SQGISZQIzHj8c68f%_kzxTufOUwXWP69bdc zZ?(ZOM;u;3E@UA?BO-st?lqnS<e^@JdK2xHFCfq98QSn+EO9G(%AO~zLd&1bBF5t? zp`-O(q~$w{q&0sADm59X@YfPDU|uDhI$efZEtZj~x5}Z_mm*YWph~Lk%OJL06xuRl zGI94Uhaa;-QDfSXv|UjKC#`eP&Ru8amxn%rZL?F*7^`lEB&ig%3M0|-Z@%(~&!w<_ zPYC+9yfWh3ky2=MG8U0NJ~AuQN08kq200hBMS6K<Fyizz)Mn~s**48bu&9wgQgiQw z;;)y%oDWf`e-)q+N>89yYdI<jnT6m~C0sA@Lr^gho%~V`yBl6XbnikG>Q@Q(HpZje z9|)DQYse;z(@_sUHFRXe3+Qkt5QUVCN3v<pAbwIfy4s-~>TLf4mXzH^q?wD%<KjyQ zUnECIFSyDKo4$gbH5LZVk2JwsUsc0cr_%<jKXt-BIyG?W>KYl!>xn<LsfIA)v$6>t zTH<}jU&2HqH`#oX-^e-S1ME*RHSk@ige#LiK>K@b42D*uq6yR9!)WGHvo-~J4P*CQ zTuk1dkHgP(up$!4Y~G{!Hnq^vwE!i~bw_iX)j)=39NJ=>i5z;qfZla}Xp2=F96an5 zXb^X_Zv7+Fb@g*NJ?I8%{@WJS6}^$<z~?_b%o(X}>xiv;|9fm-V_$UN<2_oL{0?}V zAIsy$$LDe2*TUz_+x)ts%@feWZ>s2l<x?nrkck#)H$<Pqo`UYCVzk%$u*~h_3uxB< zE*iRQmF&~um%zv8v9i=kLo?^klwB@k_v7{ib^p>4jWYlLDErQ+D4OSM6vPY)f}$Xj zL`)!vq@8XB6jaO^bIuVlCxW1$s0ii&DhennVrHsGR50h9Fkrw0=Euz2v(8BE@BIDn zeydZby1Kgh_MP3~vi(eFEY6AJ|1~eJ4d=xD$72s#5@FPbkKmZ}n0~jryYINBEYrXA zn6_<~yKlnM0=Ts8F`Z=EO_*>s8+OikOr1TG_PsSogB_u-wei_JUbcJ9@)7RDet?47 zuW5LKoiK>*(%L7=#|V=R*Fi7e$8<@bEyBwk7q#}?;4Ol|x{FZQ>=iv`93xEov=$Dy zy`q^jmI~uwCCuvfnBU*NOIS7~7Uo`fM7xyF6*^DZp|va5PZ3^@Jf)3M{a4Pv_!}?V zoq8@6T3lKQ2amj@yK1Hgjx$cd0P!Wo_29X1&VSX3^Wglr{tsi12?Oj0!lR%^wA|yn zf<?P&I`;A7&!`$B+qNB;u;zA&DDHkps|k06Cr!$MY!7(<Qt&UV0XwXp(jVe^Vb^wJ ztzFKZ2t&^NfVI~i(^t#$_qk@5V-{tf(2jLC3E6qK;Ya9W8amNiNZ#`uwqATich%n{ z{O10iA70YAYxDP69WTe)*}tammOR^cnN()3E1y$ns}V-m)n~Q4JlDyI=fe4C*=`aX zPZdCu{m<wC&r?FrQ(5q~?bE+|B=;Zp>c98fgszjWLP*3jiu<hYoxHy|9%I9m<D^{g zyAYi8jN&|ak8n=hbL#Lw$etGsAN33V?uFcQ+*`8ou`oT@2^PM7tkZuyFP`hzWMARr zkeb9K`8^$fbiiNRYWP%Pen$&Jt=`j+jx&Yl)RF{sdq=Grjupn-tV{MK7t>m+It#}4 ztx0^}Vro{l#a}->aQquz?NsBxc`O1=goc|8i1C#o`uv=QFvd!c)H38byIBgC7uO-< z;@?xV24=#b8`dOc>^pkkgSSvU_`7iW(mUGqgO6Y@)*=_X@^@=qBmVmDcn$ySx7i!< zH)r&?@V_}LPKo|IZ<Vr9fAjBeIa9c^vI6Oo^OklWG+k)F!H$HC`m-)q`%0uj&$rq& zI@NX{W@U@%oY#)RBPIU+Ij6tz|MKIt;5EuUff!4&q{DlPZMkpubF9hoh<7@Dz+-VA z<h|41T$}W|@}6QF=ls`L+_$lO-_<<W#yRo4cr5O-HOGv)E^OnR{~C+;MaG-j2W;b< zcwRgf?_(W~)l?H(^7~3L#Wv3Qudy<=)qR)kj<xK_&DcNKP;HzO&x^-moXBTHtq0rx zn_rz*XDm7w7$?}qIq_H=gRvpo>KVtj9Iu}De~rc1kZqMiu#I!#dGT0`4a`5-#yS5r z7Gnc*7q)RuJTD%Lu_4=PAFz#c{%b782Ifp`<D7V2JobOFq4KTlS8bg0Ut=*gWLxEM zY~!4GUOX1#;eT<W_6q03W7ieE(+s^-hum*hOn>$>6jZx=+3G@>97|$ashHLs$G@+* z)g||~7tz3(RfGdGtjU^AMKtL8Z;jtKYhvA`h*miGRHOR)UB0PN<6m#Rr&03+uglTw zT4h42y?jd_{yeQ|JE$6YxuA$XoN-Pg-mxOv{fg<P@h3GuKU<S4`-<r4<u5fGij0Wf z(<1sg_LatBrX_LQQcRy!t|X}bPH`0l)ql4~Z9&a>r>2FV=CmwdS5W7jyU|im^J9Pi z;iiJLs0LXvls|W7ng|wGY{+c4B8ubX^-k+x#{X~Yt#<7Pm)Mf}Ws2y72RAk9*jEQ` zYt*rLEqIM`Pd@jmOD@<HQ*8I-eQR*mnk29yoj%~PxDWE)^&eqH5{DF1Y~!5&8jJfT z@4K1@+c+nV$Gw$t@<Uk*wsD?+jm5o{F{Z8^+c+nl7mvmJ)tcio&De%?8CgWJjdT8M zth~SKp0?pOS#Cpa`xjAc<D7V2JQia>J{M{|*v2{kH5TIsV*}ebC!QC_U_8jSdLFTj z&+Na(Vm!#U$`#ngIq|%BEXIax|6h4<490+LtMy|W=lR!Ii~-qJISSi2C!QCN#TdYR zh;5wnUt|9l11guwcu;Me6VHpsVhqT(%EQ>kIsY{l?>oi=wsB58uZ?v%;rWP*!g}E; zz1#AmW<mA|;dH_?njK{?$o5UoXLMXS7p<N8xPac+SWRmWd;Wyhn0QVbKhU>;?wY(` zYcE~<l)kob6D-*-VSL6jIw`SGBiq%RKc}6F{Ivcr2McJ-M>DN$AMk`84&1GcId<U* zeY|;z)}|+)(nlZk*mV0p+ORhFYO=@k|7ga}4cBKk6)oAG%`f4)q8V$w?J<aoPVD>s zN^HNPANygE0;*1|<M(s0K+%ukyG`p9w}k&o8-_JY{U)7+DvCA?+xVVbtSiHQ9FJ?p zYvdX*a8@*6enyw!o}vxI>%wbUe`GayC>pS^R!u?GhT*l~8t^^8_}*}Q-#5P38{ZF$ z>yh3afNP4@YsS6#a9GiR;d=0T*=JX9Ry1I^&WY3Ypp~NUavHJ)OcWg#*G<7BMc;*c zg7bXnSRGVN7tVw0;o2>rigs(I>szt2qUpl*<GGf%%Y^_%yTx@-5T|Im)@9un<G3#C zG1p}c%)csTDtawkbKeuIVWpzi!nN7^+!rq>8ZBG{u5DJQwh*Xjv1-1%BB~lKTm!C+ zrtE-JMT^CCM=)N|XyF=+Hig4RMT>>|gV%!nxHh~-9FP52TZJ`LFWoPSn-y&pUOQeR z{~H!WD;g^PH!M-rR^hedHO{@i9*!y+Dz_E$pqHYp!fVItomD0T?kE~6r-{p9rlO&` z89fK`6s^=5!vUabsLrlf3nLV5l|$GsQPohj)0`Al4b|S@7NF{*a<aRFs+-z>MuLNi zR*Gw)AXL#r9iDd@_9$8@uAzcMiiYazk-czC(MP>V-2#P*Zc3`u3LYw&sEU2M!eB)! z#dSn*M$trZ?Gpqj+NY`Kw}Y>uiFy#T7B(wdDXx8jd`0_Y(Z&_pDw-%9gXg_9_yk;3 z^iEs{1-Xh2>bvV9uvWBBD?<8$s&~Tu#C^kc;y#N<SA&6~cUpgasHp0l*6e#Es=B62 z-%><X?-ZKmDXKasIbPLKM5Nh^s+KAD=|xf1EM30#P*k-{#qoxq>X()tbcDl-e(8ck z7g(=omcHKX462q1V}Py?hK-7TY1}DMRP{^#tDA$WSxV`A1+FNXrPmJ*K_5l4RPeGd zv`}<PT$=<l6>ZYX+lPTDnxzw;I)a^|O_J+ZH7D{KRn19CdZegolSbqlfT~%-wKZJm z1gh33YRpuaq-c<EpK<*;uJc4ygT((n4tErN5!V7ie?@oH(>D@)6@Aen>n+e;(H(i8 z9m@ar_K&{k$-FrDspyVy4?k~kgtCg(2#@9ZA{ejei||}H57!z&V?}E;>nDh+z6kFr z-uJ9#ud-E55$<Q_3=JGtv_n{zg0)7oBeugHMN`!6!8Qm}bVP3Z6X2SnFFIR)BD_;{ zL|lIYofUl%*Azi7MN`yQ+%2k_qB@O(MO9OT_w-*ec(4D3b9@#s&hdG{ILCZ~&n)IB z%v~7I7{j<fIHqL%dr{Q|;XZHZ-w>=6T@dae?yYOp74UWFAN^0AIuVeg=z_Q|0_+t1 z5AHMWKi37p6-5_>`_Hu&P({%K;WP5$`E60v0^xIXCBC(&>VNQa3hQ|WxBnm>Rdhc1 z`Ng$8;H+qS@G}KJkJ1BIK*j2R^gNdaM?jvU^TE%lSy3ZkhNAO1X)qJ+DtaD#e&6K< zfvW#G*XNCxpy+&X|M6Mg?zcl!^*>Gen~SQp=l12PqN@49=OyCo1X0!e7{ob%s`J5o zGPCU-(O=Q_WZXI^wo^1ef%i{{28zzd;PG2g)%jc;U<s<uXRVhD_$fM{3)Lu8Qgl9F zo{oj<iq2<pU>j(n=zNU)=Rh|_=X2*n51@+9=gNB@7^3KWFfU>5!n|}R*cN&#+8)eB zm`{$rdo8LuAB-Q28LsUSO%!cU>I7F%H9r`u7|$4=lT*#0r=sD(ILBuMYk2Ty9{gDd zW0mW3AR^|EK8I^^ppBx*;hGlMIO&g8hwF2|R?+9oiuw#DrTQFLQL4{@cBT3pm{_XM zfu4#!r^xjQgirme&jCxbzxo_7O8cwNfqA9+94IK&=fLe!eGc3!)#pHYtH1gj=%MIy zxDE%(9QdQd!E3>5#Opd={~ds$)#3UauvYXr|5`8C>Ogl@s{=0~v{aw-fA)cEbs$vH z>TrDyB$euO{?Gn!tqvS(`bVq7^*QjoRG;&I_Kj<GV5Fke;rbk?TdL3bzxz4-Ec{lq zI$WOvqf7NU|7V}MRtJ_SS{<&>0jpAd&forXeGZH*)#t$IQhg4v!+-QSSNVTVH&iq^ z(M@w9T+!+j?YIneO7%G~q*R{+y-M{tP+QUGRC;?BE-3n(HB0iLT&X?>z9{;f6E%*& zNJXDh(kT;u!5@9js<4YNLeb|;?VJa#r~lFC*xxt|ofLh}*qM9b*XAdxJ_jz8>T_US zsXhm6OZ7QmR;tf|W~KTZcvPy-f!3w^9LOux=fJH}eGb$w)#t$BQhg5WE!F41g;ISE z|33IfpR=XwDpA$m3`!j#s+yb@K8d2L!;$SGMQ`)3m@_uVAVks6aIFZOQgk)5o*V{M zZ&UC0R#0^{cwU@;vCD3L@9iIrjWw(RReOW&z<u$cYHVz~ZUI$GgU9|W2G5J@`B$BI zU0kCA1&V%#>tvw2qLc9+e+yz1{S4Qrz+gpJgLC4Zgxa2l38nfOa8UF!I1kQ`<8gi* zkNd;*Gk<g9n(<ivXBbfRGqX**!5Bp+voyhu{~zQZ4a|^PKA>u2R`lV&d!uMzPL+>= ziHbJnq;U*{C>oeY!CT<JwSTlR2WBjVv8o=XehNHObT2*1=R%O8hcTCSL9C*aQT?(8 zBdcZ#*eSY~ZatSmb43rM#>+9d23(s7nhV!}Yr{3;{CHlj$AIdJ2IkAyW6(p<#;CTe z$53Nr+o1!4MWuQexU1-4O2qT9P0_$`{RU_hZH%cs0aXvvt?nk+t!QBO)!ziF?j?Mp zH>i4;vu!n?YF+TyFxyR_YFcof;hv|UtD<lD^?n<uIu^V}+;iMF)i3K?a6HcA$@lte zuRr=0+}nTc1=qB|p;ArD-`?UL;{I@b3rsB4xBTrVo)^zm*SZ{hRNfUIh_Z)p<^AxD zmLJ71<-PHUaxPlG{I2-w#%dt@<#)x#6VGX5<afn8ChynU^1I^a7H(jryel4_SSZT2 z{H{2t$WQB+-xWuHG}GGhyW-t}yR|X$yW;zsmuPMIU2&znbwW<XzO3f^Sb8G1eik$6 z&w@w9(%VJWS?gDJWxXyfrh4a-gf+c8F}r(<Y0$emSruCcG22JsG~Pc+=<6TEHarZc zCgwG>BG>z~FZ{Q^sMmU7W`;kz{&gOWO|MB>R`qAwq<Qp<bzSnYq#c`mFPsMMu1iAi z2C=G^F|=B&6`2{d1<d&G9X-jkCVp9)!RXs!>e0}Gv}M8U;LTXB)wChLPg}9IjaJe# zn=Od-{`Rc;vIH8GWlbK;*a~sN3c9aPO|oX>PVh3DPn+->Hg`$`xd!ad2~FD9Z)zF@ zeV<1|A13bO8a@y&h0!9u#<a{e@a#$$^;niDOn=;g)mxuH{j+Li{dNpsWZz0!!Cc%o z-1G+Y^yk0j;*}tbuY3dCxosM>PDpsN7v}v=q=Vd3_E~(|3$A*rsJWgwp$)IYqQKSk zeZD2RV08eTUMA|;c<ud$tP(Qk_hxfvgj3nB*`OoKpB_$&k6aZz75g!_7x9>d{}VHM zU!qXEus3sFxR@UJmLNQI?96(8UPN6##S1Go4QJP)W9aIBiNd|pz1bL(CG^VpYeLNq zSK(6hYMRgOMuq3$`@A)@+pufGxOZJxj%6Y}!Tla9g4l^o3AFF-#J@3KrxJzy|GKb- zwG(M&?yop(FOc%9Xb`v6oI|<YdPE9bJ++Fy;du&%r9hR_tLXB~MB!F^5Sz$z7CPP( z<|?%vl&<})O`iAj;Jwg>=bU4EUAUvH<;Li1f{n69+>;u4>p;bDrSnOkVs)c`5~%oW z>$M(26ilv2ugSa>O#ZU2%ifk^lBt+1%(P}21&4f(*c1hyq@e{vm}EW*CNFQcU@9iN zWm&UZ3MP;AsmbCMOk&%O*Rx*1=LcSMih@1gWr?6-&mw3YELU*V!z%$)ym4HyW~I1d zxuv-JYvY<n3|R##u6W-dT*1#zZmYPGW2z|_!?yG-0aPqa-IoX|#x$SeLB&;azeGT| z0u=)sW1!+^@UUwzT)`E`1JqUU=65O)R4fhJod_xpt8=@Yf~%3-_EoUdjoWH|InP4{ zS8Fp9LB-Vx=^9*DaQ@km|G%k%F^(&EUy3VGafSQvWc0PaYusP<nh;-`vW`U=bVW|4 z;C<bjCFSj;F9IZ?YVX$U<C%2YiEI0FI<;j6XLr#vqf!LFYcA}gWg7Lknk7^;)-eAr zsq{@irf@sgj(y#+onE=gguU;b*`$iw>1pSyLhD8~S>tLcbj{!g!dqg`isQD?Tb)V- zw_!%?*70rhbFx11v9M%~1GdqAf#zi6*~;wD^%QEir52gH$AS%QokDLH)+fc)s<Gie zchFze8jyxNtk~4nJ7`n0CgfxF+N}Eabb8=i6Vl>ceO8C1(Sr_-WPr6Jt6C?64r<$g zBvy4}MdfzUt(oS8|1L4Rvu`(jrEfvH93yPvf()8wqem)*X;@ReJ@lrD0nvZnhPj^3 zpm(o572GDaW($U=QT^fh!VS-stbN&3dgFm1$>`XIrI_xd`y9UrL(>A-`$*kh;T{G( zIxW0D=*t4)(y76Y0-<7qHf(mgT{=A+Tg-&~RBskCI#s8KZTSCI53cXRK26xJ)5DIx zo(O&P>a$JtQ*?SbHBFxw71w3`3b*O>u>WH-Vsp!q6`V}b>ERZCJJKz%9;+F)L#Kzf zLIX0gX9M;rB~7P?J3{Tq)7$)Blcb$GJ#5&*oIL!kVaE!0>GW`HWdq_;&7bKzX6URP z_XMvUuXlRFQ{mWHFP3<8JH_kGIr3SEzw64(o~KZ}-f^1@$^L+*>=L9<yx!%bOvtM@ zjafv{c8b><YEp-oIy$pYV|P%z-V1H(k|q6{Gp9?b6tB05YaOz(p$~g#o=)+4!#A6d zGuf?Juh;1muXk1PC*jQxH}+!ZcG~)74bu9wH}khhrx)|9leLxtOCFX^58W*iTsya5 z{{L;KxyL^X3u2oyuQuEHbN01h!|z-D@AP)M`f*L-rKe$2E2LAs^(N$crIySmHeDwM zkHz!;D?iSOYr|u444xO)kH_K|TtBV>kIgB24VEbU)1SYiP<iG<fCMW4tjoy+m6uvw z&4RKD=Uf?;0xB2XxyeA~oKFFnpmI?PzoSp(9L`0cauMeorgF~HP9>mn5$7B>P2n8Q zMQpXgMf%knFqL!i3+uC&3KxmznlNXDb2t|<m5WBSZNOB{0S8CcTj8Sj`WEaj=VY2Q zm5c717%-J{_Son#m5W|ndkQN5aGn8`XYM~RWZM<~sWv<xR9?b8tiGcFRG#Vi=rpMO zgL^xzn87WDb8v4v^1o54oP&GI&meSFI0yH3cA7p@IS2QapFyT_4(@H5za8tKa1QP* zKZ8u=9Nb%e2H69Jb8v5)wJ>KY=iuH>u57?m&cVIKeZc*}ec+q}M^(;2eYkk!GpL+{ z`!HpbA<IxW2lrw1C=;e~4(`JolR8Z09NdTNZR;|Xb8sJ;yVhY#70$tZSiISU9alI9 z_W`e+pJjNi@XyJ+MWFJ`jr{6N<sW{28C7^`g8OSwIp^x}&!BP<=K<!b@K5>mCQRiY z9FOzkd2t?W;}~26o(tPJ2G@`4!8VS;wc(nBJSwvDCpSTS|5&=AVRiN{dLOLgwn;k; z8#u8EY#A6!tM+teYaMFA7jDzCyP?bEC-A1@YFcA-1{_#i0K<C6(vgFkLd9OMVL_W% zy5eI~h>my(V>+y+_SRvZnLl5``}V8px{nJyqwBtboF_4KmRT9k0Piz!Eoe3Mzup*f z{my_1&-t&h`bSftZ|_|A#AE(hgLx_#49bHzUQg|ojbVDZbI>3_x3*C=%6K|<JO?oa zF*^0&wcB+xVHPd3;C;Yq+H_ncCe7Ont+<W-^?wPh$H!)Hfvnc)m0_pGEG@zkx>5c+ zq9|r<v+dA)ek)SQzjx=kZii;!t;nQ-t7&|>aESKuCv@@}+PqRYtaI}xfm>tf1u0!j zPYEEv{ZAoXv`h*hX<K4wl1G^5e&ayxSlLdi5~$6I^Wgl?`zAqptSec;=V~j?hOc$p z`ETv6q37qMh{Gm$YHd8%hE`=fNA2^_#^bsEw+3}yIezRO4}PClEbTWfMVuV$Nv`oa z<4tFRP37if;Gr0ubsY^(f{aD3+IZZP4#p*5{h~4X#{1K!S_zoFYOGyjr|4oBn^%w6 z@%;aa`ORZS@!yk`*Vt^T7b~;qwXk6v{~hx8UTk``*FufHtLcT$j!X>B7c#j2UomR} z>$B6>9tb;vSJT&|J$pO+s3v4oEZwNzfh8AbYC7`w00zS~tf*F=rVID~E5@NfU}^h6 zvx3JzZdaXrQqI)afQsaza@O2NIFqf)nd&u0Lq;lR?O*35>Pb^UJzsmLIt%LgN=wTS z)H8U+cekLPO?<v^PCWKvjV6M6?(o=lcT<Id%30ghB2_4-oGCmPu4mhV#)5j*@EONv z4fkR61QTMboG)y5pHqqCDraqq6(Pfw^M(6^{apw1d+?OArf(D`tR3sG#Y~f`VM5|4 zf9<(AcJY_+INn9;pLF4u@P3&KdCxIsefph{S<zOD861Q2RJ5ESgu67?#^9WNYtIlC zHfgTKFwWWJ)H@;D(3aHUSWRE$MLtIV!Qo6(Z=&K5`)hw`KvYa#ZR1F?73|^omv$Y< z90hwG1KX1e3MR4LFjPY>Dwv${Ss;rP?BTKaY~nL};nghYcE5+P?&>#^V)&H5>xvfE zjrgjy-(FuS_@69CXTOVs*b`%f7Yz)l9P_o-Lc#m4k=Bm0b`oxNF{jgdu7$)*bK$}R z6MEJ%1FTGk2?aN+P^%FgVRCw?=1@*~8u`lwl8tP9?$rK4=H{hAZuBFK#`Gr1s~!%Q zS-<QVV=rmvtvJF>vnM83Yi}e~gyQh4Wbl}!kaosaI9TPG)^FaRo7Rq#G|;)_@a*if zFLcJ@oEFcQ!m;-T;>;2IwK1u6B7J<8?;?wHJs>}+P^@zFA-R30KlJ)(!~ZsRhTxpI z=0>BO;cbu4V&#TkNbLJ2;1d}QGlB|<-MBVjeQ*tYtNMs6^=l0M?k|G)oR8$*(2kIM z{06LD`+>Y_@4$vCeI62L$<{0V9MQKX+o|-;V@6fhQ0d!_+a9b;wLiV8Gv0+=ReCts z&Y1mB`gY`(Ei-{XeH+`wik(#YBi?MzT<D*kB$!&ULCV^3{Dof4n3u9%!K?+_s`LSm zJ-peQ9aq+i>nXQh!}^|D2h*lMB>Ojbv)$4n=+Ul_wCO0YgM97#Hhv`4zIig(cN1n` zd8h5UiW3<>PLT$}`hn$juz~S|dxF=#hL4>dnW!mu{5!$>f@`ZZv@?);dL+HZF5zH| zCoJw|NLsWyBJ_FI4rW{a6poI)F7$932CIe_2{Zbf5$b171mj=dgzb-tg}N^mLN&`b z!ib{hg301IaG0!5TG^H*Zhbbv4ZZI|;Paotsfk<R+D>EAznUSbl)oRwHK|1E>?upW zf7lB!vM#BZQI`A|cLIE?)+T|~e+#)GS<ql#Bhn@3y)e)^56Ta0K-zyQ6sEUHhw(q$ z$hlQF1wkXite|Ejd=LNs|3|B#VP$vn+9q2#GddN7$*v@!_HMz*B@Ck0G$mEpc46Ot z%i!L;Mr5z;8X+sbH{9xPOYT43BpiG;1@3gIOOB^66FM&u;B&Gm2}?~8Zl3A^`csU^ z&i_{F^u(`DOE`bJ5~=#?n9$X)6PUc$C%<~%(&?4?_VJKWO`i-dSESRcP0JR8G_(TA zzxP|GS52?3gNk!ah_tIL!M)1<o&q;^)FtLQB?9i%)5@tZFWHH7jW5>e)r09t;4#yM z46?hU)2rESR=|cn&4|JD<2t>%U^*9881g$?lQMOBbto<vTJpau<lFAl>D4;HA7&pn zBb~GN>h#KE_)M@^U`gzv9td&$-I<J~RF0+ZV_lexnduxeU&Izn#Zq!NA0}h0ImZ}; z*Jmnz3}Tuv6;}t^)@CYx@|xK)6;}b}jhTv{(X1wuan+0C>bg{(srb44vl>%zwPA!I zQ}HuaG-fic25?-t^sdZg{6up67<a3|R9ua0WyWOutmgQs5M{+=TorL#h0d~JGJdi+ ze%j<WU`rHS6^M=5BLzQOySOnGSG^3HGZ{ZSIDRyy-b}?6UOVo|+!S|ap<rpjL@%ad z4EH3jN>ird3io9GZhNNU3irgjswGo#g?myw!<?zO!aWI|WX5D%4dl4OJ?Zal!Bkw~ zp47NjkIA?)<ha5;>D#O!Q*niRl62LT1t_?}J$XIClc~5Wv24Vw6)c^vpkd9nhx!z> zT1pZmKQ_>QxzE@aYstxA3zpv@LSt>TibQU5VEwnW)L8G1B9+5^*@__##NKN*kbT`d zF#GOt@Z{71VjJ9(J!AvnbhJdELlEn<BtiUrAeA)O>BdqDKZt=5Ysjh^gt@fb0Q=8m zlGu(tnZ?q_Fs9Q5l38N_d%N%$c*fn-iFa|;u>b0Hhw|w&$fPlZc|H6MPGpr%9+R*D z_O9<o@OgcPG%n-IHovaRZqztRu-~F$Ay|)a);!!AOD_L-20N;TY37HtCUf`Ov5GzK z9yw9mo?Lcq%X)d+v$TN)q~q{@%=CR-7LfOx-|J49&)McIzuW~9cE2XOa<Vg9z5hIE zzSWlfs@9T?Hh-xzcEvzzHnFHN+xF=Td0yLx&9<q_CJy^RW^VrplN+>SEvCFAlV5*> zOPk!-=;Qy9o@@8Rk8@2~{<bgt{>URRrJgUl=TJyO_PVgW>4a_naFFz$>dvl(HDk-h zCzD@|`?9D#zASgxPjV$XkTIbROHco<<2UTwi@hJ%fsOvJEPasDm$j+YlD(c*jt+k} zm`xqujP=@EhPE!#mU+$V%$!D-<@Y9+=CPX7o!uGTj(rT)r}f0PZ2E#A*8Ou?ow26o zLs`l1itLtEk<J=Vw-?yCyDeA&l#mnaC@cTopJg>M_~%?WzD1HhJGY=7^B$^Cu^;yk zKfAFV@T)dUiPU5I{PQ8sQ}1zW)&rWe!Uu+Qk<CZwYgwLoZTe2a_<PIuC1u!!Uf;;% z{VkaLlNK7+$Yipmh8=T?YoOU{mO^?P6P8-lT<o<!lf=wz!s;Aw6sLDOK=9`l`7?w1 zne9%wLOAp_R<rtY62YJA@aMM~%f`afhV{hx?+*~SXKmR1PEBFC<!ORH^DKVYkwre+ z0?|G53I05T&mhL_@DI^2&#>UA`?nx+@Yf2MQ{{x$*Kq=I{@fdEgdJk^i+aSrh8vsz zd%yVZk{#*kS&vDk1>OrM`Vi}9gx`M`E?yhxMDEmY&0^vficr;uyo`Si$7*G3s)jWo zr^>psgfW{$`nwX@&-b_G;u>O3y&xSM$Hdh3VxE)NL$`kANN}<bYh7Q2cV(<}YWUXP zhfUZ}1Uq+4A>VejVsC$shPZiM35;=NZ>m&f`fdWr@Nj3T?X1|4_VY=bKFwLc$%^dB zv}(kpQCr~m;6lY~iRAG}cUUd;g2sk($fV*v;As0!JYKwp%yc5)w|65<pOHxxHEafX zD?Y#>vokt=_Ny%Tk6#9lN)C`sS8j?G=RX45&F4wV=k^f0wk|7gctmGx>M;$xlx*4T z!pG#g-az<Z;K6QsoF_5+4v3#ZEm^}oPYI6sxw;Yf_G!&bhJ7QIZFY$h=e1;K;=U8R z^@HHvBM(+&RzjYohr))6)@)(+d!70dx0!)&>K)NCVIvtJghRiBCYt<iQN*mUDIEXZ z#;51xrR4jW0@3PPtmtqwjbwe<Eq*r}43#cR#Bx;tG&}eXyey}a=C2)KzT-$pNbF5~ zAq>u5bz$8$CXtkPQ{iM^Yc_Yt0`ht95b(}7Vq^Kwb`LQ2hVrI|!E&>u4t_Ak4vlRD zlg?R-2dZ|^sm)H@1UcL0X~Lf-5|drV5PkWMPn)=PWV#dswyRoet~N;_F74|>jlRZW zs?R=>KczKnG8&}WnVYQheWY{VUC~l{4rx6;lEN8ZM3)1b!EHjm&Ucx!pDRJh&_)1p zr%9*b3&q#L43awDBu@qfiiuw3`MvLNNT{1P)Y)aj^jhlEDcKLj#y_oDwGH|-#-zVE zzpXPH%JeAi|G)MHe^<geaeTv?9ijSNf7W5CKF#UZ9IWp&XBAr*(mNgmqF4E`%pLml zutQ@AvhZZTHk6~E?)$^mxtrnbdVTWkODEV`xK(U@*HFh^a-|omy|^Wt=3kC(@5b){ zHEzMaN0p&5llb%Jo(Frf*N|Et?85fa=4{c>@^pV$KYstaKO5e~K!>;WW(2T;U{7Wc zWJo;+b!QK@)no2;4d@!zYGByjosIggN0Sn*pyjW2>`}wA)N9gR(YSLU6ULU+@%!1? zz=vNQ+3s~^D8@GSTezPP=Q^}!!QXXbF#e}}N)ju56__yGfG*FF#G(YkHnuUKg^SC= zx4ahY>8)})d$fD>53xowH}+(nq0T-w3i}36jeD}D?=F$EACE(ekj|{m!1Kgv*iv{9 zBCu<14(j-E{F2sR!K{kFhKxR}6Ym%JALQh@vq3gnb<PWZ?*Hq#+{Nr8Tqswc`L~MD z;V#T+Gd~oAxt#@DJ)qA&&)`z;?kwK_74)|LNbr7Pe#U$#3@QST{$?y_ZyVwl+8GS@ zS7etBjLCrB6`{~*q4@o|5AnHf4~CzHiY|2>b!;4i&o$12pApG3UxE9l*^pMtn_vv% zcw7&D7T}uk^9AD{KSy3xeE}0b+prHW^@X9_etXoK)ol7)_<qrz&AMKZ&FykuIQ89z zWkpuj#u!x{3=Z+TK#sS2*%P8_Z-u;Cw}n`}Fi_)3LKLX+mSg(DkF9&4XxrnX6OCTz z*zql!Y5moC%reE^b+#$9Q}Ua2YsS?4ReLmJvtug3?W5NPIp$qnRc#GUp9aBzyh%QC zJwG#gLKoPt33!<&cs}k4bCr0x=8sA|&hygHkr_0-BaW(6k7RALWvLS`Yi>!E$+N-D zn40HRl?70P$4ulgFSs3iZ4>m_WJz%TJkP%HDX^`uck7=uMl=i(<n<2W>s^!>tF>Pa z_lNP;al)?3PmaocmW&HEB_%b;$h7CM;lw&2`g3Kn-OG-x;dTw@&q7cSccwYHPB^hb zUog4Vl*KJ*Cdg}yNO5JWc}xsBDg;hk2npOiHTjD$=*lA4s?^`exr5f<v)eI29Bsp_ z>lv~g7S=?b*DAzZYa5!|@$Y&@Os=!Y&4qnKd(@e~t5WyNIjvE)YUhj3L^b}JVt4R% zVMVEpvaj<zJ$Qc7EmU;sR-fR$;r`>E%eLCjI&CB2xl&KpfLKs#{>*Dj<k+xDd3-dY zOKXsO^2@+L=z4Du-1y|I?TL&lp_!Ss&o|xs!i^d=wDzXXeW7(7PtAP=dyPyyHPv{Y zCzqSDy$WVte{yG&_`YoA`_i(d3;U1n<7U2(@>*WIo3I`xZHYbCdfjMhz&dez;{G_0 zZP`D8+j(LJ%)JpvMsxeWE+!Dn`9U5#Msr3q<)0O?--_q?ti;GUPbg!tzYXtauu}6E zUe7(g7P+^{d@Tc%y^zm~yccp$@L9lpw&5|iOpPJ+X|P7_!|0o_KC+F^OHYr!(5bzP zz_=gxv&sMg*5$4f-W(0q;GSblPVDNzHYhQhc%5C9JQ%AoHj<TjanEJET~}(u_2Zf` zC&>G&a)oTG>%!Q;IsezMVjFV{#y{paIlqd3%#GN_F&MZ1;yuinxPIAI&lKL%|Ludi z*BAqMPqAOliO=jrrT_Sx;(ft>xrgex#{I;8j2V2^<ayOIDBI&Jx(YJhForQsupeU{ z*M|LaPWAlCwz@8S#&J)u|9|ULYm@V+T#Y##uMzt(hvPGX{h0HMIJbY`{M__Xum<xC zK0DZt`3Lt3`^62ZaA<5x(xkqD&>%1aHcav+-uZ`xZnq}F+IbeleBD8zaq~XV=)Dzj zb1)FPd~t%x{11|i?G1#*4}IZwNP!T?f1_dGDJOQK<{M$*?~lUzrS44i&uaY~65po? z7b6X_Egd}AN^YONX^=hB$cO!ya9!AY+8|qw(b_!5>A&hsuIDh-7ltJpGqoN$=D}58 z;_AwT1a6<%(1Cp6HOT%jp*|U@|6TaCD+-MGUD8jo3$%VUUXJN?@VjtwWhD~zbuwI0 z>U@97hyAuM5Dp0X!mlD*rjFgysUbVyU_tVY4(rqq&GRg>s6Y%C8f169;HR}$F@x-5 z{O^h*V_ykQr~a%(w&j?Rug*;Fn?&@5fAtx!7suBLXwE#h8j)Yyf;AH!`Y^lhPlZFt z!5UmM-iz96oWMninfEOK)UkN)Zk_gGYMt{Mx-)q#T!oq~uj|?1wxq#&KdtSNZc4o7 z_+@|fuf`TWq(s{4mu=v&3qHQ5WH+~)bRG{)b~Yi~clu?|5AO&rJbqJ_U$)<a#((ya z@9Bsz4J_w-eTVP0-2ZJkPx$Xs2Ww<o-D`{iyhiNDn87&5emSR#F?>dF4fuRvKdu?~ z5c~hPeszEGzT>gjk8y(c1^Y3sWP9VhswAEF3hxod1NP%R#XZD+oKv>d{l$BSYr}rL z*BAqG9u+efCnMiCWX%<9;F|Akb7k_pGET6K<MA^Z$Fx5_i@>V#u<y%48kQYQJhKYK z?jZ~5mz}|6UH`jcxn@x`sQ(P2cV7=`Z;PVC%7&AQt17_04NGWNK_ppy#2CUemeB0k zkz{XJHIVNO$9^2|@hptgG_DHrz2W`Gg_Bc1L$vXDERJcmeLguAGYKa0__k5=Nph`F z?Yt>@;Y2tYs+||-!STmxFC>y@D9HDQJDWt4U|(~P?+veCE1JZ%H3#|La9rofdJ9Pa z4b}Q_{*7tVNbO2vwEe+;T+izK5Ym6}cx`{0ZRknX_v-<}cn`le>PdQJ^??lMC~6ut zhZtp~!R7i(DUF;$ZoW;1JJX_Qud?$<V7!+o+l%@~lC(vxq8y`N*pIy1^CWxVfGB$I zNFQ=>v1Rs-=S%1s&kn@@?s|~z7Du}fAL~SrW3Y|KVjIVdH0VHL%WMMq-tgE5?aAr6 z>)<@UH@v=AZ{i|3Wy^PncYEB2)T_7qs2tPe!!+_Fd?(2FhL3OyC&#UKfP8Owi}nl1 z+?6{(zBjyIK{QF6GeMN^4PWsvjO@KzUX<gP)r}(hBYKH)%+57aNXr&UAm1B)Fm(*M zwJizcd&75KoJ%@?ZzIb0h8tcSN|qPb6b<?P;JCK-75b33<r6`^Hyqb#-G3T+#A=Ij zp4%&?lKy393o@SD#darsS`HUvJZIJJPDsLNLB?~{oXN!BZJuDl@tinpE}85QA;@^% zdmxNBCPWA_o+tGWBk>vGf{bVE$MKo5bBWcH1%iy{0ShBYyE3-gcsv%zjC`|zbRSk% zn8D-ys)mv3Z!NU*+PsM%PAzTt|7b1I$%EsM*Nh^kUpNXfp4XO%B>VeB2r{0}8Ap=A z!y*J3&$!Mo>nQT-qodZ3^AEo^gNW(1wEe+;Tu-^_)5y|m)dl&y>p$pCMn5bg$awyI zsW%B5^<5+5xpq_pvHlvu@2yx$cXpjaf|6%yWDM5|m_&S~G~o)jja$tkhN+o?95W%N z6EPgOL6EWfzD#@a&2+0EW7x-v<IO48N4ASw^(8%<H_^y3*v4bAjbq-m=}lhD-r^%; z)t;Zh`6JHx$aoG+ZA+H#OBQ52N1ba&u6px(4tUIqN@2t$HBcktvs#5{a(wI>jf~q| z|Ai!B+Y*h8)%qr3g!$|dWSqCzIhE8HnI*{aGrP?r4x9G~a?BvBIV37PLL=ijB6BMF zdaI8{#$liSlgQx;se+8>W_Nm$_hUB*GM;g50d_-3m+9R#GM;gr-^Pt1CcRPxIS=P& zma6bG=VA8xo*u}!<^0TMD*ViOo7GZyn{yfqQ#hG(FZ-1EhpRcqvW*HqbB<+Y6&}Vh zcr52twol<_kL~l>0fmS0Se%pdAzQ5QGmgi3IDfK+3U9lbM6&>elQ~zjWQD6aKeLch ze*U`_JeG4cb5*#S^D`@7%FloEZ^{p0?G#SNwRvvn$zn_SnfWUG%z2o7Sn-F4IX|=W z3O{q+X5|##=KRdMDg4YineAEhhm$$SvOx-03rD*!SA~-~S2K;m)!2{YImfa`R)08_ za~iA0{%|knJ$6jtWX{zrLgDIv<>CCyZYliCIhjpWIC+d)I6JIxHRosMUdqpGP$@sN zjNyOynR7C`pm1{Lnkmd(;p(i5b6GispK)!Rt68AJ)m<y}VNXl>`R`gdKeOcuKR;YC zl}%Fkne#B~rSLH4XVyjGXU^Mfw8Gn*(^xZwlR5XY*$P*4j%6Dae&!s@92FkMF?cNJ zXEspbXU?l^jKafsEY8XKkl8EzjN@@0&Yz5O-j<&ioRb+-IGJ-b%U8IX^D`S)%Fln- zg2!^MW_q9ga5d*=cBzz~|K{hM%r+~WjBDfk%x0GIGfP(Zne#B~pztu~XSQ15XU^L! zRN-yT&#bz_&zzH4nHqmMnR6^NQn;FPEL*K`GUsY`tdy(&`f)txSaw(8Sk7r|jl#X0 z_n6+uKb*|DnoXbchpTaZoQLx>i&FTRb25_@PUc+A-YQ(p`I((A<!5G9%FoPM;b+dt z%<uLePUc+AG8L}o{LFF`e#W(Nu4X?JuIBvAR+RGd-?ealX0;W5w%am;Et+h_tZWa{ zg2M4EY-bsEvQicuXy1<w{P7hIaj`^t-L7myLOnKo%3-?r%QzP477gChGwIbc!<p;U zD0n-353Nyu9J9686UJ4@qs}WwGNYG0gl7&pbVAD*cE_r+@H8B#_1G26ul5>^^OhX? z#%c|-JM>2E<DN&~R-DM%dSr`LEzi^1xryx5@-6Va;wk!Z#~9Y*_(5=YxIk|l9LAc= z{0UF9&(a!MaqRV&7Z7kRmnIZOvu8D{F#F2K>6Xp?nCG0DEcj3^El%ssPVBd5-%O6t zm1n}3!TFl3$5@~fiw`kx{~r9#)1$QGmc1<C!V?H=o=uPT*}}TKHDe*BN2pioP}crS zZNc6si<T4)Wry|NWUt)5hfWU&VO=!q#j(})QN5Zonbqu08h^9>I(@+X5h@L1v%XFh zrffSxr?4=#IQKtIoeziTWS2zNB<YOi@zpFk*kc>J;Jij-lX#FW?Y@{*qQ066A(^yw zzcAJ*c%5kU-yZt1_jFeEWfV-?p=)1$I)@GIS%$TnpGo5<EM>{I^;n?m0XnV4UN*1s zsO&<w!_@J|bGFob32gP=Nll+UVv}O8L3-O=w7PvBYv^(Zrr*h;(I3vT{5xY|LrxZL zl69ILu3nD4tFepzC+=tVmnyNXw)^PWK8y|RT8=f3Ors@E+gMF%%$_;zp;ulr=K1L+ z7=GDCEpDt~?I*m1*>`tRv)<WEa)^Opp<Ah6Mk3o65)F?=rtA1;jLT!$Ws1bbSGQ2j z_4TZ1`5AHP;dGsN&-j}xb8a)SbL>{SD<zYCP1>ueKP7{nDBQ~Qx_t7v(RU|J3VXt~ zjN2jxC#BHW^Cf0$<Ey#*Y!98Bk;m?mA>z?vnY6n3E9Ty+JXBbbs)GUCE8Ihj2fRmk z?=XJ;fA<UT^&!{SEF>WYQly>qiS(Oozdr+V4bo`N*-z|Kz1xt(YrcK|DVtfo0Cw7B z(9p=Ytl`QV;*k@nw0h+dwm@&Y*mvM|`X=Wo3%}M;^odEK?SFq_)vlb+-gjgRoxJoG zdsyvs_Jg-u=%6#t*eJh*?6D0t)4(UWEN;LlvG8s()f;w;b$*#G&hXzzM`wtv?ea%p zwsb4)Y;}nxH@gNSha}P98y8uX^!aeU;U>B*<tSTJycoWX-tupZp`PPC!h4D_fU$(} zgE4uw_8GR(%9w5C|6km<5irLs#?1Y7st!JJ{Wxd*%?8r0WouwS*ec3K)|Undw;{1{ zBAqb0jI`@`Wo8|?g~I9bQc&ARaCTw}Jvpa}WE3+5qPK0QP5i#H`F<bZO2!WAzQjP< z5HSH#J<{m<W(LwV+s0z8O55qLqKZ-jGYfG};5Pbl?hiIP0DSf?Po`{pS?No28_kK~ zo9XP}LN>!P(kHs}M%t{+NA`8%9-j{Pxv&bw;IUq3>Pe=%UPGhkcxrXw9lJZ<lx3~j zL|>1%&0Z~v6<@orr!yi7*!O8`#qPb<&<Cd<Fr)8$UvBaL<r#E|HE@c6Vb&XHg^X*g z_16z@Icqa*Zu*otbS;J%gV)m|i)%^Q<>KK^#btC&XdS6w#aU?4dpQknUP~Gn;0Rlv z#nF$XwiM_ZCyrpts8C#2n)I%#&+i*6bnMJ92Pv?jiFoKz0-d_6fz)_xeQ4Bv6)iM# zl3IE;gyaQ@wAiST)U>PvNb?e?NkAj1-r;y~*poo-1UgA;2CRbT`x0sPuLe@iqBBrq z?@BtMhNCp%;bqtu&VSpXhOM+N`UxCw9#6fd*h>$e+=r0t6|}sSwPd#PB=kJGjBc)D zCAnWb34J;*rw7V$#YvNR_%I`mzUfq3imS66X4PCq&!*LpZj^C@SH5wy@=ptC_4!7S z{a)9`F=G;~B$wAa#jB^{=*i+bQY))%V%5}T^rBZiDQD86qxEL5pvFyYCFhqW+1HYm z(=^-qQXPXf;tksb>igYMYO=D8SYWx5h7M>b)w-Vtvs$dAD_S&^9(BrsF#C8q_fdVx z*x>|-ub0z-W$H^&7w$ptNh|1(_{P$kBi2w<$iM4NXe2dw*8~<t#MA8fM$*!yi(&oF zc)I68V`+Mw6_8_*K=rQMNc9W%0By01LSQ}Vb5I`i@4AdGOS6_dB9=nj)HrJO#!?El zOMrFd<EYTXTI$uq5Awa@Xvf8t(xZ?TP@KC|$Hp=F_v%R}D!vm}42h#X=hu}IzNCru z9OLN9#r9H<`!mG+b9}CGc2dihw~uz@?+1qGH<0F9XNoaXR?wTBoutMIZldMvc%6O3 z`-QQGF^~5SV-@cm#wy+;j9a{47{l0)_YUJ3$74KWoMQ}Qp1~N#oP+rU^E~GNfAI|F ze9RS?^D)o-D+WIcFrVOO0p<|Q|M<Cpx#eGH9G~ldonL%r@fpN6K9Bg^;j`AZLILZt z&V>1{N~WtjzGHQ+Rb!i0Z=*v!oTP>ajsaLMqFe4alnl>YfpHZV(|rw_N&P2W27R)S z)+_HKg*xUy`B{;azO#{fxU2=gQ!%uLr@hqtfCPoxVri9(2GZ55n_+fDG#&iYMM|ia z3|<=|=<d^Q(r5F2aJ3|yww}~bqTOdfT1qtCYhx!h%MS&;+!#84TXQMi?w&YdVK^;& zy`hx(q7__y8b!@_I7l~YxCwO*&!b)o9HjXxgM=$x=hM$a?W7XDZbF$G^Jw>0_R@<P z&cc$O^K|?;-r}>pv|!#q;f>h>I@ifgavn57h^@VV=KgLjC9S;z-ZoLxPv2RZwC4(V zwTYq6teZ>KNA8At_OY~%qqo%Pb2?0Mi=q*c&Qi&pUGQyd9PRAE*HUl>I>#=h@yl9B z5f7)q7?)VO^`%B~`Z@}F=Psmo3Y$sU-4;Lui=!QOw2&ShC<8-h#n8RyG}0}bVzFuZ zLVEdCGb#8?Wq8i{=l9#@lE0goShd??+RfKn^89%*`{>w(^xm_k()~4MMB&I1nmVt6 zv}Eff&Bn0B)cRawi3A9m_!o=l_LB{yPpf}=P0m|FFIqN}>LnNX{JtK=@5pnKN=%cp z*Ox@lEddTviNUn&w1ts0@4lVnWVB8^xG{?UJXK%%z2=8F``bcVJ<U$~dMRDAd}J8E zkKRU#e|1~qUO$}9aJQ2ly?p57K6oL$J)(hR`QeP_)QB*8W^jF}xJtTam3<gJ?A=7_ zw051(us)GA^L+#9b9X%<(j=UU=8dKPcc*Cl^cT{|vrf{GxGc@P?F;F8%LY<NKQkd@ ze#AfH3zynT_BRZLE6XG3wx$l!$R#$y{09*<=na2HOuM4#-Xe<DqxMn@x>ghNd7)07 zxc=O&?$RSi1D|nyBkAuVcS-N@2XF6$2-+dnQ#xL8iFb)z1buPUS4yg$ntiRx6xwoG zD@kws)$9rnCey{NmE^lVScF59=_L<8>5<uN@h10=%kh_HTG_&-pA+e(Wq#6;>;~X` zdLkV?&rfom6$F*8PNZMn`Aas<d&9EAiF8c)R#N%QrEoWF3T5M|ba_Ss7*z?OwP#Z4 zk$y64dClj2(^C4rb{pJYF@?4^5u_~vx1bXXrBW9`+NyU7N}h+(!W%x)tlDS6yx%nX zc(;$V(&j3R>pqR%y5T0p#a)Ioc@eZxdpBv=lH(w+tJ5eiDPZwI_<B5&CVp-qW%RxZ zWsgMCc}yeKj-Cg1%SO^*TOaBC{bblRF_M;C7Ni<}RiWJd2>NTSAk|9g4#rm_=<y;S z>GJK2Y`?S!+Um7NvR|@SynaKshq$->J~Wq#O&Vl(D-5Tv7kfx8qk^(Wy$Pe5A`j`2 zVT#yrNf>n=<tYuFR0bl$!swAno|4(24xCTIXuu{9>6P15SpFr9cH7}DdFpM1@Q`pC zcgRC}nzNVxk9-8ZGQ(3c_1*zSjXBSl_(+8p$3Yzb&925heWcL717LaEa9YsSM=I<5 zPCTOtr~j3BOVgH|6<>RY)2*zfv^On8{1&-@mKjPU+m$=SmsjS}aeZ4#oohG9wwk<v znpD$BC%g1MT4~@M`fxar>eeduo?<?amMf=`E;vSuSF6sU+h{9k=afJ&`#GQHx22NZ z{h?e}J%?JHXeBvasst{V=F>4V1nF9<n(*M^EV?6xN^h*ci+Y>p=+xHdoFM%+?+Mi_ z&Zbw#QR#-~W-$M<fIj=Ckxuxg!4l_rbXx(HTBS$Bp&JWy)|;8+BiZhcg4yYF=&}(+ z+B0evWVDz^JACw(hLt3NkTZwYc<w1JeEyJs{#-!6F7lArpeyiX{(Rb^l@E`<10BAG z(Oesiba>A(SbH>#W(78vx-{m$vBvjq)_V`hB?VyV(E0Rje{X4`@lmMlx<F?y^n13F zhW_p^p7=1AhIzG;l6RYD2i~7cTil}3(P8sNzwcA2u!Tz1r?=1U{9!8n__dXE#3TTo zC(og+dihG_^lCuoyL0ICEv+PeDJb0AH-$QN@RP>uGlr952>r3Xm2`)7hZ=9E&~)RL z()%IFFg|xKeQ>{}RHPRRy$a^i`G<%!^YAk0JzyGby`iNPbutq6RGd!3`QB9w-Ug1< zr*TcPx8%%jL!Y|*(Eaq5J{~y@#w}*jrUNxn(ufC8f8qi<=Rb|K()<Lp=DoVhxq9%Z zV=(gmOj<O}PjYkVAx7~$U3T;J#;+5dI!>c^gZ!imE(62~H)hZ(;44kKvp9Rl(@_4q zaK2J;ts2=cQ)bZ2LSJcI!f;smFof1!<u7$Q*AbX7jW%x6S~4o`0{ICcbgfrw>Bmu9 zNDB#}cZ&U`+;UbhW5P7r;Tx3}M(=|2Y#QDAu$3gf-3BE;XV7WpzS4+WTfuShG<x`) zuk_n_8JK5GqfHL@N;9V}fuJfgY0Z8bsYRaxn7(@^&22!WH;o@cLHHbca2t^{RUbfX z+)R4tCXvR^&V%{MGij5H{48|HgT$3{Xo<VOloHTG{K9*Vd9Q1(pA>lRMz*hB2<=+0 zm9(tt8m})#)982iHd4E7o#EbplXQ3w4z`vSST%rek0#OQ5x&y$D#>uNONb8Ft-I|j zb>@5L7#KnqUL}&l^;_Ul!1obxpzTK@+1Q+cE=JRJzAt3{*H~JizZXiTFQ*SP9HkYp zd5~qdOy_$<^hR50<jp<sw8>JP?*(T3GyK!*AuzSg5}nWg_&b96NE^wuRU&kKw}kGT zSWmjp!vS1|FQNGJ|D~_>r3!H-V)VE;TBB8C$-Z-_XgYM6&S!r7y#RlIp+U}4nf(@U zXy|fk=jAK~URwwT&z9?auL-kpl&)8>6V`MIr^~3V6!*(aFd7?9Kc2Id&Kz(OF2v5G zZL@5om@Tb@FLmeB_#}JjX}E*1;y^gfiL;S5j_E6`t-e4f20!ocvkX6{@N)<AE#_Fv ztC&kMXJT%|9EkZ1a~I|r%mes5V(j7bj?X4OclaC$1DZ*lquOPE{t`hQ&e%zMxtp^c zZ^zQ2G4|5e1^SxH?-uFoZ}U)FsYcyd;wxb(ZP(jY%DUGH#`TS%LoV1#lZRzxTb+ug zxyNjzWqNVq>47oyV)q8pl%_sVcq~c>Gp`@jlcrTG5Pzn{Qv8_&e`dommh)|-vetE> zSK?wCHrGaa(dCBN!(_3}T(}1Oz2lj~F?M=`3A=c53w_!BGCSqbke%6?Lh*M2xc7j? zyyCxkbSPEld%^ZP&sk^>Gj`p0m(F`02jioxyh|O{vg3A|?S6tev}(lko}|)UpD(cr z7o6CFwL58~-5uuK*phh}XV5ZJ4ls`zrtHb`9n`J&VYZOkvGSL9(niUAY&#p4Y`U9n zY;l9Nj;h99&fBf?ZVkV)!teU<cSD?0=iL{2Cx++3_2B%t20Yg@^R}dpSsn6rBmb<M z?n1UaD@#sR2&1-1&gA%VeZum?XmrCiB*nNk895}J68%oZ?x`*LnYNOywdhVNviig) zZzWC3?M6!8I*{*&R_pk2eC~}-WJMWU63JuoH;o`&j7+uhcr1?TpEiWFs$)#L^7xYF zLrF-G5&6XD?K^%XNgZTLT=~2>4~{=ncMP!_Rg)aux|)8q?M*6;b0Yn@z1q7sxxdhf z-1JJ&sngqI3|YINCb`J{IRCmMeM!q97074aAMD5VL>>+%nbXT@`*S+Nk1Q~JB;4RV ztmfiR%s)I3=06OhSHFdl$U)zQJAD)QeW2q=vkz|tYv*vf{<R00o79NN_FzXsimlwq z6CU#{$(ne7tWJ8EhSQP^3*u~QLbjGqptB!zCF7Q53bI}ISXVML6odgh2HSWnwsDM* z-i?fVyhjL5T2C`3cOi?a?-lMxBvGTHTIBqWYUCQX8{Mi!CO<MEU3g5}ZXsm&j$$Ed z`Fffo&LoQ^1G4>a0@Wl;Co{X3AuTdD&`yV26W0fxMB@I4GoGYmrYn)-y9fD_?gv|t zCOpRB%vjRRzE~JmE}3SVjwDsQ9}6aKn`uC#C%ISLkjVbApB%`sVdkXY*<_vC96WlF zW2R??Q0~WdURu(OeBzo<IZuynZ-wLix@hqn^YpT?p}MOU&*rl(3QxMaYVo{dRiRLC zKqu{fnceyzOgR~>#k0ZsZ^FnXgS2?IS^G^`)_ov(&#{O7IKE1m&%$%>U^0itoVGM0 zGy8Sd;u(*{F(p?_$Xx$Uq#cjn`pJ|mx!F;R=hZo8Wbo(iT0G-CIDXDUb8;Z34@u@2 zzS^inm|uCA*0%0lB3vWGNIu6cuCw|xbJF4>*I;o!&c8O>h?p#Fqs24!<9e#zFd_vL z{j~kLe@c&BuIET(JpafoLmCgOPh>o2(?+D{h}J~L^XUY8vfW*y#qjaa93lB&FmdE~ zuGu$Fcy)fb7SGl_whMbqytQ~fV7*>gW#XyDbCuyWiREK+tsT+Gj8q?CNn|`@8;`{{ zjyW=^7HKfpoXB{7(A}K0$uJ`_p7XNT30r5i(Bj$n=NjS1LQgH8?RGaLHdCk;pRY_B zleHH*Xz^^=rV(+x)mDq=xa(Jh?B8RxcpluG34O;6*2WL~@4Vo0a+DU&$w%zS*M%A_ zZp|;)kZHY}YjFtGP6(d@g0=otzjq7eXSLMg8P|5DR!!pm#E!^##&upAazro~(@mR) z^E0zm_?h!C+o|v{=Vx|C;b+d<ELGv{c#G~_!|;cbIrlP^t2xIqm7h7svNZ}1;}|@a z^D67D@H6LCrt&Zzi*s^5WHS|h#_>20=TEjr;cd>zOyy+G)lB8;<=(wnfx^$Y9z2$F zHA_;sdgYP64Ds{d{G5}S%E`Dk&d&_-GgJ9F;k5@-d6@GvBMLvC`xeSpD7@X*k^i5y z!q1$OnaaueN!Co|YR<7NOyOkC)of}hSO4|nc+Rm*<yg*XOyyqA$!xj8$(*a%RE4W? zew>H%GYe7pnR7BzIhk`cTdr_*+rzDyS1CU;m7hBX`LezWKkqjk$y83}T+Ie4T+R8J zJyG}>*T%V;sa(zZnVl)+=f7*={LH?W@-v)P_<7x`LQr{_^E0UYJm=|U*sAb0=QL0` znR73wTy47c8>syJTkkWxQFs`~;ITQDW=!ShZ&ys1%ENdp&bi@}DT`P58OP&1%X7?_ z%G<e(N<igg&ecriYLnh2aHo`?|E>j(t^CZK2?|%oXB#mKg`aVZ;SD49O5tQ&8|P<+ z_?fBv452xo@-XLTmZ9)7=WV9)wsGG)c(3sDUhDOsa<WAaeqWoy)tqCQ%E_Fo8RF`{ zejH!n=NeEs_E`2hNLRR*^Bz+<dEca3Oyz2vALrrx%p4VdE@|C}HBmU3b2Zzna5d*= zQ2Ckvv;e65-1Wcn;Gyud@dX<;SK;J!N9<UM!qo?>oq+EOKjYe#|K8324)BMoIX^Rv z!q0dur-vMYN(w*s9aJK8+r>Ylx^<=<)1Aqii=Tu(?}PYv(ucz0c@>C-n=g&)JzrS3 zsZe<4>P<%{6$ta*ZWhMAwWL*h#S70fmk3>>Ytzhb|Btcnj*4P=!o>urppq07FaRnb z5)?()t`86q6%hpkIVb`G20#TxMa7&mX0AEs2s;DDYs7?N&N=Hf$Jfi<<=6Y(x#zsU zs;0NPy1we_>YCl1o)kKC!e8OqrU#U+q4b9T&VK4_5XS%Aoy;zelA0WFL4#KHSdXTD z?D%L?#MgbGu&la5G3t*YdcV8sSwA;l;d9vq6Rn>qZq3}n8brI{<bghv<FJ$s_}(3R zecI6dXkXTQs~L23Ey+}x&SqU`fZ~a*>C&R-?AMEU^!XD?4bAgdf>A1R3X<r|r(lKk z`@!gOIh;Ztxk#r+4#at8NcCOyX<%76T%4}5HzU8Xsm2{JxAX(++J&Fv^sGBXpNM{l zDH+ewJ<hYiZk}2`d2nm4;<f#F#hUom=sQ}EP1?GE{fKO<g+;^|Q0PcoUS43shbJJl zcQ@L(bRDZ&oT_ENh^v-=G>y#ap>SI^1Ug%S>5aRGH0fTl7A_I*@uT`wc<VEZT@ay# zcYFyH`+o;XOEX+?DX@uWBga6gRWlc@ITGit>6}2ykC-84NkOo8_9NX{+0p|(NB?ER zpus*ge#|~aSj}2m`d?N1=(#L4L`t4+jZbPmiSzq=FK5q2nX_FE=J+r_g6X`zt7xNZ zq7^4%j73^F)2)nNilJP;Qx97z3O}LvtY@kf8=?*3SY3LqR@@GDmQLvFA@X4*_EZPb zLC!l3E>X;tdrE6t8bP!(+<UIV#;BLnIMEsdQ_bkihz6|EKyx_RKV*adFt*C9f!10O zV{*&}4|e~zqau&TwixFtPqb(D0k+EdgQ~(==f0x&N^GHu7u!YKM4LtVtfM}3c#4Zu z6s(7wZtdx4S5HZ<%yDu5{AFHJI5wv$?ho>z%1zg}M{xeX+6_l|lkvk8X<fFpmL5^R z<LUq!F)c=_ecT!%-!0~k6sFD_duQF1=BRT;r_E0CcXbY_)MuXbTAd$w-jJrK^G15# zvC=$sJ_)maro69S?|a@}Eo`LD1739>C|juWgI=q8Qm8s_a6ikI>b1Ykr;YqkofCMj zkf*701<wO=Gj$%|>qx$*&JTQz$n`$|n-h4xlB@pxZ@${h`J?LGb<{Ofeyz@3Ja5Q> z>b!A^8On{+dBeu(s`NvhH$?2BPbQRpkb0`~Nw1Rek|uA6*p;{DD!;1phKODCNypK8 z(hPMz@hfzc532Kqh)cxF^ND<j=aVWtpYXgP7pn7yh+V|R*RuRvoliuJ@=<;Hlsbn5 zlt5Xi&Kvi;H7T_DU*3@GsB=5d5AyGs|K<mtH{=!SydnBi980tzaj=iPL7g`;t9>k7 zqs|r1Jy$F5sn={Bo%_nw>h;27Tdw5uZ*22em3OJv0*_C5usT+^_g*f2Q0Epg4#ily zJ3m6Iqs}>ejmVb6{>?3-Jz|XUoFhM0=N!>aZ|}KEJ9Vxw9bBT+<dg0XD@hO3c}B#- z^ND;@olnGg7S{;RGty{vo)Oo=pbZ|<7j<qCeKO}nd#Q#xw}`wbBibO^Ci+nHt;#1( z>U_fUjJ)T6d8VRWlow@qZjo!KbBj1H;#j;ksE8kNKe`YVqd2f<wUpP%1-_|E6a_u= zr8NUwA?{yy9)Xkrm!(FFwD&J@pL$&6Nf}d0qz%rlNZDPNT<=wqC(U!g{imihx&JSI z4yG%5c`~+v-bqcix**}^X|}m`Rr%f$7c_D|$C|Ixk>%E|XkR6O`8d3kj`4j{+#?M8 zuTz{nuufW~V*}A<5sT+?4_cRUR@#5s8lugjJ?_^`=;Zxh(%XyH_~-T+cCJGudCF^R zEqg>epXLOy{c#_q=X_jopZexnqBv*1MzTL-4be8yX3uqXXx;LU(gwc&n*Z%az54wv zIp$hJv{ST4+#|&Nf93UAHgw-N$#}iC&7y5<ts+@-z1LDTZjYEZ#C+nEx<py5p5LWW zF-oO+-np-2&HVCtln1EiQOq-9{BVEDn)$u))Kp%mp5N}COxmlS-_}(EB+WeX`IQ{i z^V{#{X-PBh;<^@X7H#|5Z=Ld-dfvI;<iFJO%l#%_QO~1jkBH^{?K4uTdVcTc1W8BL z^C;RW+9T!`(KgYBN3JEx^Xhr$^DArSSF}g8lh3={Q$6qhwNCl`N}BmyWfdv8Y35O| zS;WF#^`yXVEu^+-E_nSZmUavck!n<mMb7>-3Ys~NMefT$+qejd>pq#;PItlkrZXuo zG>dg5XBc<Oqd`|v*@VP&oO(5z&g@T;T=z!fW5N^~HjhbBw$A_ASCkQL5XTa25XTa2 z5cP;Qh*(7Z?mLnx(A-OEi+=bTKawV{jbk-CWN6_P`-<b{6wap+&4bydpmZ%?iR0SD z%%JFn-KFaRaS(ZNTv5N+F3LasG>$?(R8^R@?GABV(PmLb>?_KPGGbqGTv0~UBjW0$ zn<6(^@j>z6PD^}l#?RY4)lE|I>6j@GQx2CFyR||?rv<XX!F+{^kEy#{KI6Gmk?uVJ zdz&qk7k<x@RJ>3BT-kM9s<bRR3onAF%QK(sR;YO0wF~5wpiEY4hco6yERwG{WwI`Y z!MIv)ko<R_xvXQ`Fj%}xkw^YDhxO^}q&2R|rCIXAO~a*mgZVw|;f3;v+xZF=FWO_f zY?5qstVB}j54#g2mvt$SRC-Kwd&-j*9FkP}w*^m;Q%XxD)wm*F_9<DuVD&{2*eM*Z z%%WuTsa+)%FZw~WU$j%iBFc!kj5kNiv$o7<J@%!e<V=JdxL=2LcrskePSJkRW)Vx4 z@oafo;uWcML_9`SA1fCopOH314}*X0L^;s<gMu|1fiF&Ba+z+Rq~b@v3Y4AV{3O*_ z;<%@82Fk`Jg;M8F>G03%ARqQRAgOE<^^AQGF3)T6N@3}l3k&`%TkQQAtZJoP%y>Oe zX4hvkRbNr(mFGe7h^SABdrr9!`-(b6dC@0*Wd5FlW7FCDe<ncGBg%;5iuQ<oMeHKR zc0*m|-tp_Dq;~w-@M>M;+htv(O-U2AuqQ6Jlb76BB28;L38K8HNA&0J+g@_5ZLOt! z!4o0&75yp7i?)e2h<dtxUM#omGKy_9=#NuRmddZ6%u^h`(G!+m=F3&rjh0k=%Im3e z`%dR1l}u#A6|%f|G*iXHs&UKYdI=-h@XQdcbtJ}>82_R__2OpA!HTi0?}}j%c~QR@ z=i(X^?G$Yg*Q{v2XhT8fO!=lxnWVB=jBT-9^uO3H+AppJ(dXh^h_NKv`R8><dFuKj zidg=Bji)m`<*UcXF}MBG(WRrOeE;LW@5>NntUEZ%vx~C+9~rT)DD$~beOXa+wv;|$ zIu@0-k(GQeR`CY?jQCmEqsw_wX3yQ0@<d;~|3^mbE6OxzIg`A%uTsPf4}w|1A{u^t zhGN6E3Ha`?fEw*cEo^R@gGp=#-I{x)VA#+gSmjQoE7q-~B_AVU(s?rds8U_JIW-6^ z>rJIQ-RBhK%@4xpA=7DNe2B8srda&&nN362x)yqujMS15b&6woWzC{*)BKrYbPyKh zEvBre#LRb108>n*aaUgyH0_>)<=Io{aN|n_V=c4sHgr7gyIDnk@+cFFpG~H17puz8 zH)Wzy_i1Dp@Q*b6_c%0A=2C-x@1-P*@mP>Bo+h38C|x)`94<7G#x3lqw4RxaCqXl) z&)i^T^4DYxoj8?FP5C7C4I2Tki0R~9uuQS$*#s^Bh_;>FID@9A`LUHRwPnP<q8~*2 z|BjtV6BDjUvxkgFU(*>hC+W82eQ2DP4Xx~_P(RDBQr#CLV7GKU={tXx7TIQMVF~$} zODk^Pm5wUMA$Ha@!twjk_Lbwbbc$n%*c)z`K#K3A{PiPNYwkp!h%#Y?<H-AT3#n6= zD6M!9=UtR(rZbjmZLT6MxgDexGh!@>^S*fM1gc#-i0%9*2%>LApNsw!?ffqvE?F{& zjulCY4Y57&vM_~eov7wn7|{dQ^0MjE!*=ecr{-W<N)B}|+pGw-&c(xr>GXZDwPe0L z3Qd(G$YY_M@<dP^F6gI|x916u`kp=DFlaD!$^WSgcIkn&(c`GP=lMfx`i;`kDUK!f zjch%XF3j)4auR!>=Am(v{H_}-Y?h0iJ;(5K4BkqU_<v<DEy|+eXO-pQO|sCq%Lux6 z^qsWi?Fjha&8BM!j>-cwQ?&Yu_KUn|+xVDlieGb0`ch@Qmd-Y&BWYTfkCGgl2~j4e zbPUyae_L8{W1QBwqEAF#^qa_wzWOihqMaf}5xZ!c80TXAi|bwF#hmb8eMP+DT!_4= zQyf?9EBaHMN0AqG{#Rddy^Fa{<VBt0xME*1hlqJn<VBtT)mQYJ=ueRsb&BI=Z%d_j zzcwo8W<=v&@CZsiQH_1qNyLp$8MJtmKJ$B#hR<gQ(~qdXl%2}b;M*XP_DsrETKGmo z>?_LrS{YADyK&08N3`X|_OQpvwAaCuHMyJylc7WDQzdgY`9gvgFUpAah<4Wc!oOE9 z{HZvpI|I6H6yz0OtSp{4U5meF*NPe?ZBgD^$=@?B@Y`p((!ysS6!G<EK;%W8cQYr_ zn6yty%LTFU*_}&OcD++(oR7fQ9}`JAv!QYi_d~s%ljufEdu5BA{j~V5KI14K4V5!r z^n*#w9J>GGwQ^!fEJU3xXXVg>d;?|uvC()kWeg4Vc&@x&o$up<yr@T%5$!SjmP>h^ z9i*!JV==z&SPGccTpIK)7Qt*HO^CFX)}4-nC?nb+j-|h9EV0#%B*SX`wEBuVMVVQT zC(?i}-6h-cNhlhTL*}!)O4F1{urQuPkB&2GXG#)8nSix9w5*1QWVS(DM(iuf++Q@A zJ{6ltIVT3AuHAUrT&<4uNM{I)k4&Zp<8CQy#tnif;}<fXrq;Nk9J+jvmW<d}lu2wg zo=QS&rNd?k_)WQFRoqOP@@D`hmF3d7Lsn9O-ax$N=W#U;w3Oai4n*TVxpc?YQu^|K z0H*r!u?iYWj`|6xa%Ma^9jz&Kte1r4H*;x5D?_Pvr6esGaV$}%*w>`tByt_HTKO?A z1=%%nY1WceO8XrtxVLB`*|5FJSM>%$lo9O|$Mxgq7mXaSOWCB=K&`%_PEqFQ(n-X> z04OZ@HW2pHa>=IGpMn>)laYULBDI6N@=xtVh%z-cPM|k)U6t*cC2GlteMK43SE3I^ zpNszaFPZm^zeo-1*-=at8Bb30y|>t$4n8f!qRBU<Ri&2HyS5TZ^-HAuf@ZX8wi0XV zpOsi07jpBHAodm8y^XF)bLx0d{mL?qhCG*A_5|tAmC-R$M;?;`+HzLL)894Z%)TCE zxK75eeMa)|G#5H%BjfQtWBG<fb8;FaY4Jt{hVo<!EArW`L?832^7|X+6mG4=vqh(+ zjtd*otH48eH1Mso@RTvJ8i#Nrc#rh-w>>p-EI`QZ9g^o`1@%fQ#GA&4rHt$Vy0~4b z)t)-$fmDBSFN$3+Vfy%L@{VJ@XtSY=`LF89y8Nu)s;4B>on<ZepUvpv3nijE+sf59 zInc80g_ya)LcU;R!E<7PR(r|UnzF+eW12nm5bj<(DRud$DP0(|AL-HmNWN#xX@=8& zjQ_b!>Q>Z-lE)sv<DZ+Pi32;+%vT5D`bv^qlfx;he*uirA4&b+#1k7|h^ST7Wj*Tw zG~rtz{(4{~SN;)B*j$K`pqBEVR$XZ8rUI-CY9$v>aHDC8L-^U(Ms6^{nsyyKpw&Lb z%t(Ir$DD4i-;e6YuS&t6T&QNuUhrr2q!o5{6yI<!UXLr1-bQ&7(LRi-sg$~O45o~c z`%$<1IVt;A9DOS~pw&KU>l>-@mt@L0a1eP*_<PQ6Qs|=9A>>!#?}7;JM-Dd*!fu_N zocuPJzWz9X<QNCJUUeTjQnVlWa#Q&lf1i=x$bDMvH)<Qpt^3%~{_%SeoBvL_xzLwt z<nF=Q_m$-<<3Rl*_Mo}zL+RG2Zq&8vUi5LjFAcrehwc^Zg^vA8>CD9#IyZcuR(nS3 zZz<Mf04b~O$J*yL`1@4`P_*}cV7i&Sr+zFQs=ptRJ{Iz!)_rNnl6~mv!+*EE(~TZJ z*ozT<=JL_ozVx}-Uaj{1Yir5PmV@;2_F$E)C%csOq8+w-wfICnFFQL})0jsxbelJq zA8&3*|D+co)2o?Wc+!fFZ!Ury){_4|XiF2Ei%@D~DTlk&r^<%KXm-d_4%}%$&W^?C z_|;h6Kiz`1O)ADILo+#UN+Y_xpcoP1HD$L`HvGNs#W0*(OTIs|8T~w747<Mi^5BC` zG--1&-u~e-cbzD4PchP@8gg2)2Q}<kjEOaB$qjzFQ^UAols++%SydleS6GB&Hl}ju zaL|LNMKF2ZP%g>xrA1APV7=8sJ~zvo2FDj+nOQS=fVDS0+$bZfkF8v^pXl%}8M(V1 z<&Tfu34>+0l{&~CyV}tjzV>(RbCwG}J5r5_GQ#3p@!!E)QM<b``c-j|>+H6nVdrF6 zKDUuixm(fxPDMBqYavHAwxA}bi!f-vi9GPD6`gk}#+LSm@`GQt^qJedU}FurZFeV% z4JwBH9s{{WsymteDMHdYV>$5&(V5&L91dwHU-|7tF_nu@Psc_sZbr0csf-)h_OgGI zcKo<M8Sf1p<xl4wsYSL7Go6Rh1M_BNF#j-Y<w|mLR#UqC*I}fL{wd{+HKM5z#c-%} zORCd||Hq<RG0r+alFqfTq3XYsTJ2qID#;c$7IcT_SdqWjyRz&*tuZaEDQWdR;Pg_; zZ|X)}e6(#4#}avQT(K{%R+Ag%y3pMq8O3X=^8ZgdQlrjATDU}v|J7HtQ?y^yDe~gD zV&8?q{C&g;rqqJZX^qPU@~T){N}IuBGP0SR8Es38`C1V9oI6eBt?{PRtCb9~ujqeq zUPPTD|Nqlh^n-{+<VBt0xS~%^uD6m`8ky6~JPFjSsXU^l9hKacwRlmd*jKbu#4hR- z`Ty!0RGG^Ezjsl0FOHA%mcJ(lQNw_Jn6pSB&&=&X+dFCVP3!UB$ESHwYURBU`-(P* z^CIdL`Tw83qEG(I9#N+_uGm-fgJ{3Vi~9eouZU5!U*tud;<#cwh;u5ACGsK`v9CCf z;<^^&T;#<#5&I_A<o~Zb%*e%i3+CKV(7S3aDdhJi*e$cAft9OJRQw@SI_pVEvMG6P zEWoyUo@6$!HmyCj5x8bejV#Zx?G6WV|8yXAZ~B2f>beo>)7z0>!+iE;_W^uJN};X& zUb4$KHX_%)7v)7PVOP8lBEH)=Doxd+otB%?FFcu+lqy+4?je-%dx0JIttqC@7Wi4E zQb*+{7AF@VYx59V6z4&W`LkNa$)Qv)+KBAi6+*OMv{S?)%4{x(rn`sg({IDgT3AH; zMVm!CMcYJs#BoKx9UACKBl^5zJ!1}O`RY3JCO5A$%=_{|EnkWLIXk@<-5qz8otSz^ z%Riz|wjS(G7E8XcvbqIYK5^REol*)8v$aDc>@4j}(H9=DcfTY^liX<AtTNWGlLWUg zPdbpfpVcc+LbOM0-?ghf1$TJDa&rqH@**y=uV}MqgQ!#F|EsTvYwe$I{Ji$}Oy9E* zqE3+)#})gEc8d0kIz|4!`UdE?p-#ac*taf9ptnE0TJVcasw83RS#Pq}ZAhmFDYf|7 zV;reZycu;oSO~GN=znouM4h6%C?nz(Z5DY^kJwkl-ow|K!tIS|_=5s;ndeK*&(x#u zd4*cMs8j4K+9qNYb&C9d_3f7ELHC_}sZyJr@Y)|pg%>*0tQR|RCM$?6N_^>Zkv4zP zK|x&{L4nnGLhLKrAkKxTQ{?}D`iegJFMC9t;<#d8(GQ~iA}{Lyuf8Hi(SDH^b&BJP z@gUBrIF`tZSj4{KJc{dAjAxM-<3#MM^GHGYZ<^Aau1f6BZ$~r3>r+G(e&*yvPr7!@ zoI>kK@T}xT<6bwW10(rbYvfLywi?p@aT0#N^Q3p@`TG?38I{)=QD?q4$!jG%Ywk^Z z4ppPFd<pye`cu2Kugs*Mgx1G8)7b}q*u6vv>kEP@)%P>=D^bFGL@<ri`_0Vx{rHpK zk<?pXhrDYkv2{Z@#XDD_Y(FK~(l{EttU3+rU5Jy`F{Bq-lWuG(M1I3KQg$(;hSv)4 z{6I8S2{a=|DunK@a4PuNh)nhs;A>78b?R?L!Ho;y{GbOtm74K~kP5K<Q4gBb(uTVB zEkw5*KRQv`oTg7N#CjKha%x~pCS`^2o=>#+L?iypof0<nJoqzz_2|nEC8|vDAiYh7 zw6>vyr-wkN=T)UK?IpMixyY}2Pug(k2P+z{#IE*XG`@OeYH*j|<L`^2dagAn)29&k zJ4ca0b5kn4T7Y-Pp%lq1>HEO~Y#km%E2>%3`*#IcchryYk2M_{T!@!9`q8#K7g-mB zvuNF+KP}jMoVm3)3*)p<^2^=CQa7H&f-Ze2?(iPA-v1;HbV#PxBWJKLIv3I7VG>ct zNo;k@1^hiGnZKLRi|Ky6grNK+x?b9bMGU{BB_sB2`5~C*9u8)f&n{z)QBS(_v=eJI z@Um84QRmOrLDXsI99Aj$qL#d<r>R9S&FZ*_h5opReHT(_@~J=;nsOP*;l1frlUOG8 zF2zCX6f*Of#m@r0sD(xByKz%5x*ffkEuMJ^|4a*@uK_pN;$LSW%B0WlLTGe>t#dsG z(Y6&zFDmXPu`h~KICdB``_CR$W%nuYvm~h~;Rrie?F_0qw<FgYx7pk6=g@eh2c0jP z&%zE~0<+4Y+!uq`xku;mtMwpib}OCv);)zwwNq$ex0P(@qrY*y>JS=rLZ6NEIfF+n zThi~g2bt-p(>OoFj`|;8$U^U&0e{ab9h7|7f#xMzGNK+)UL5OXv^!bs{iJxIe-#7G z?dagubDombCETzFg>8SLhzTvj`DLK<mGhY0sLO~8%%P<LquA?f7qH}L4lS=UMqzDy z87-EjQOrU;rH{>dG`yEXuX_zsoL*mwn`_!pP8~hZ%}cMsn?L^)yJ|w=VvlQh<(Ewh z%cdx6t-gZJwH@d$&ppbOV@h%2-cX9VQCph5;WCnXw4sn&g-X+ASG8n}cMPRLPmQHU zt1sgH<dJmEr=9Z7qstK6Cw+M$S^jJyTVH8OjoZ(Zx*s)?{Yo2A^w7o9==iF#bBaHy zWa{SCmUWGKkoTYv>6<|{dGhfpG_J+~DSC4iIWw>cd8UkzdR{S=S7yFpD)}rQd)aG= zKD9AQl3ss#E5(%&-JyoEM(3}v#<FIt?>Aj!jm}XPcCtp#iws9uqo4M)lr?%TH&0^= zp4OqxE3d#VGLan}S%<dgUx8<O3Og5TO#JXi9Bz4s4e2+I1v=b@J6q4TJu@V^UKy@7 zU&xvSn9!EIYuFokl)Vm^$3iFHMYYF+*vvsD^wRS>KFJH1&Y^j1&g6TztJjv5p%&Tf zyM{9FAZ9#lJTu*U7mI=$u#+uysb7aOSe&$BUp;!V(}Qno@uEzj+=5wt`^DDGzk)G| zp6o<JTh{6H4OmVKV-w83vbTdv5qKh(4cTPOrs-VAiZ(OY!4bdM*_cwe_T0zjPPAsl z&#obO?`pQ@R5kKVy@C_@*Vv}B-I?L68(J6_e_F|Qyf>iQ)yuGV_Z;Rq)QIA`T+_l{ zaAq+3Jky9aU%IA+ePXZ|%kVIymT}j#uzzv2V~?_RDaWx)3%ifPjcv=;A+zIGAY$Be zE{gRq`pFhuEY-qT(_<=I@25lWj+JU-th}5xwAZET>#k^F6tP_1x`@rst4pTdSJArR zG&W{-1L_)~jdA|iL{_%30VS7~LByE5iCEFKy5u>u3?jyPo$T2M9!oB<S0Q2)c~Pd# z!#2!tWlfrDeTAQd{6Fj$CWf-v8P(}sKq*A*qbE*aX@hFgS?^Ma*iB6qu-_}|P_W(= zxC+=sjFHc0v6geqD9z<6x`a(+wHBK5XWPrPurD2!#DX{S=gIq*LBt-owln+5pVdEN zUIr2SO=}Mp#*FAz=c^EL*}3_!ZS4&C9(@HO#^**+tYBVEzQ313#OTvEhh>=<(&DY9 z5HZ$%JA*x_W<+Owu0X^nV)<!0kG-5-hx#nIiYc|HuqKC0$Z~j@7RLU*sjSaA6MB55 z3?fFe=UrKyqx{T=No5c*ZrSL`a&-;p?Y65BF}|?$W%}p!Xv<EXD+G+IgJao#GhLch z?FvMUIp@bSlTCWG?Pn=OjINdEu)b$&Qj4WmAYv4;Jl!~fEm>cSXv9_Q7&eA=HK;>% zZ)#)AHXO_pW_2i~S{X!)2LfZ5t5l2Mn_Pv6aZ#gC=CaO!7LLCP5o5uv2v+%I4O(G* z6(UBr6G`k<)f)8k#1)7bhh60VFFR0!43A!ch_RzQo@GrppbdOq6ETWd>c@{{5rHP; zZE%(U=90m-wlJlZJbpxs*A^zT#;r_Ax8GHW7>yUjv6c}gw5!`yh!{7wj$$><jLE^| zDnyL?N5!!F@9WU@k}D7~ig{kdDDDL!#-n~&EUKC@ojQ31B1Umv*w^A5+t8h{^)>Fm zFZmQpdDnm?bh@RLSKlt*#o+K=(c9ssRvzwte-67b=%J#&=S}UrZJf$<yZ=;FA9718 z&l_EgWcmv%*bVnPT6=`JcZf0(O-8YG#l(z@?`rKk4c0GX=XQj!eS!D1_Nn$}h0M?@ zgnjz!uGYRLV%%JOp3T0uQBhQS7Z(?tWi?wyDlB_zW4De!$o{_c*0W>$ZHU<StXa;2 z_O153nsyr^cE@g$*fY~Fp0hIVV1<Bv<L0p}pfFDH^v7L@xI|u*`QS5yh4kE_*xu<r zMC_r**RkKZ7ZiEL_aS00O(|x7&pfYa)apJ&>|(r$F)7Ba7#m_7ig7N+;hE-XlBV8h zot`3HR@WF!A`>M|?ZM+p%23xEyCaWE@6~n1rREDIO}){Et(P=)$VYhrKlkz98spca zLDGD6?NRC-B$=vfj558p(rtC^!Q({wp{_Az1vij{+M}YK*A>z!bzQMvZXwyL>kUz! z*BH`pb&XMPT9~A%J$Q{FEm7APOWMqkG_?n>F{Hif8Y6J;YDrUjh*(67J9p2KH1)>( zPb(!&9U@}feP*zvsXauDql3L9P3<At{MOY@($pRzE)Rv9q^UhbEL+Y+Nt)V2#G>ah zRnpWRB9>N_mrI)3L$q1M;?!`Oq^UPbwl0#Es_PID%k;5{lBV_$v1D%|NmF}>Sf+Kd zmo&A9*e>E~`LK<osW(J<5#z~;p^~Qd5HV&=oFHjx4-sQ+lLeBd_7Jg%82!Q~N}75j z^!Y5QwYm-wG0q#7Bx!075u@MQ&XT6~5N*C}?ICGu4-r=rHy=q;dx%)>8%0T)+C#)b zeRCvD?IB{R`F4h+sXauSMJ&0sr${Z-^~P7zdD44z9U@|h@J*F8wTFns@Of9MuDbRR zv8>tXDQRjC5z7NhUrAGYh**{e$4Z*oL&TDOe!QfqJwz<6D$kLk)wPFcvxsHGurX3k zb-nR$;{-`lhlp4*3<pb^+C#*$BQQqN)E*+1S&c#^P3<9K*?lWQ($pRz7RM7wlBV_$ zv7}zil04P5hls^n9xrKX57A~3%k7^T(jIlaVH7`7($pa$mJ17$B~9%iVyUqxPSVsK zB9_&yqa;o3A!6A+Dn`=O9wHVo&x=^ZeL=)h=$9pFY7cQ=5OXQ7H>3=8y}|crX@|NF z5%VzLf2Ho~+C$9SeE*dmt7{K2=kxtnGE&zb;(o#RT*>f%wMWH%A?`JN&y}{Q>kUy} z+^6{dD_v379^xLy_g~3OU3-XFM2wdfoRu8Z^#-p)q*dxVM8s$le^AoD{BP|cV%)c8 zxs;=>Jw%L7-6l!(%>J!CM4PwpcYwtHulA_GE@I^Mh7_f)H$-_6Bd<Lq{fYn99wJ6w zdq`#K+Cz*nF%HGJ72`pSJu#le*bDWR<oX@!Nh{wSgm=O|d7IBL<;^1gUn$xz->dtw zaPna#4qEP!Pb!;w*o-McP)wdYy}v$N&|QMQ|0H?Z_cw~(Wk->+W`X?6JKJORmA}h* z-O9fu6|a&pe$-G_$prJh4=fwYs=g|nKLUSADxFoZRPJ}FSZeBas+=Ex>y=W)M{?W# z8L+e5wm5E&Vc*x1${v-SEn{y>Dm#Z2?vuA(*Oi=1kH8^6RsMR~NzQjG!piUCWn<ko z@=5&y=-4L7D=WLnpWiAmW%4Nbc$2nr>zM^u%4IrM>&sL!HoWgu^G;0FcN~|gl@Y^K zGOE7uU&5KH@5Q|3@`UQy(&g)?%E#TZ{9yUGhkhKC$MJTrpd&C(JS>mlyw$OTcyl(N zZQ7M5J-#>&!|pEJ-B`+#l;_9c!`Xakow{A*>rA(l(*jmYX6?q~*{(*iV$Uk6*0-rz zd@z51eOcxjX%?G{_jfGh<Cgm*yXOnFbc%gN8Ii9auvD7!V5c<Z_d>+Dt=nDyBR}(5 zXOR|f60nplP|NVXbWS~%s7LH8%80l`c~M5>1NQL$NvUx?*wu(SsImWFdMa!XWkf%V z@}dm)EoG^FE6R&9ae;|6dr4Ed#ib(T%@{!Ed`;!tvSTQyHIPh47|8j9j$!=Cfz<kY zeK~7x5e8B!jS1F~(^s6vl)y9^z3HQ*_<RZ*{L(3-%5iD*o^x2ivS{1QBB|Q_v#4A! zf`+~8FFi9lk52p@sXadpkiNN;;8nAcl$)NdRLL8y7)#sYmnsdp{LNNbWdA5xq0(Qs z&1ib(s-tMg^)I<GjG`ykVk+Af{~AHMQ*I~%h8)9R-LhzXA0MW&{}vlbTNYTc7Ym9o zYgrC$p6k!Nb7cG+mqT~;Y*>R78E5~RLeHGN+2|*HO?{e7S$39e-%lkjte!_Jq8*rl zF8{sq%v^phsUEw~q7YN}EG74i_1U1ihmbXR3EkWHMnO#r&}PMEdJ|l%2&;VvulH}H zgU2T*W=uE)kGV>k@*&7W)&BnWAv!g6Mxp=lLkOFHjP@qKQmWePKRZk|(FW4j!-t^g za)N%<v5=~SAAoE3qhx31B%N(`5GzYg(2#X=rSLcV(d*<<8ZvH<lz8p{BEKFXiyc?W z<$Z@2Q>{Cvq&_wWF~<8a)w}UXQtAKOyoe^<DU)s%A41`e{S^D&P*%0iKe(5Cb@k<) zCk~-)>Ke-2->AHOvi)i*TUt;4#_gZ6Y938$*g{s}EpnenmFqQ<Kh`V2N!@95u4N1P zpDKkI$fi+=VI%oM?Lt`OkEQlgo6E}{E1}yghc=~J$tlm22s}QRa%S1ee~ptdz<nrn zn{6R)PmobKV<WY;A1AE~JfU@tfp{j5cvg>ievWt!&)vp4I^kE&u?+Wmu-|x%HT!Ok z9y%{s?|vpQ47<#JyPLrGbOBrItB=VRMQnj<RrI~TfhBwVOOGwnN0%MNY)d^8ykB0# z-Wi+Y+rkYj@v1r8I0YJFnClVNaY6$)c<WHzQ?-!##gtwwuK~wHpIGJ)eOP8(XQ!tb z!Y-|dWe0p9mHsD5|I#<-ev-%GB3AdrPg+rOmj<O*$L6W`Xws3|i0=4=tiIRAcEiV{ zJES@qL|>;q0sqqavudMk-2;jW)x+QGpVFb-m9Z!PF2yvjj1~{?(5sKt(6z}u3aa^q zRQ--A{-x8LDwpdS_^=vAEtA-KQyV0?on%M4+2B;_1s34m1g$epu#I~g<N577j7C|( z@zGTlG20SlFW$2*R+gx#^Og<2+z>C<{iZv8UeSq9?<lY2IURibmhMdcNM_4_lGpT4 zw5fe1<ZOLFaqT~njniGKG@%M|zTY7CP2Xv)vXmCr<NjRU0);nDu@jjsFgf%st@qTy zgQ`!+!u=zy`E->Pzif&8z&otpGY42F{$$^aTVa2#-|S?9BL=swL;fpUp+W!JRMXcH zdxIO(R!=Vfr6J83-~gkk&1s~43%s^!N|7ba(IMWJ{Ciu&N53(>*<+1MhwrlQ=O2{M z$J$#D%jvuyujo+xMfS+>HC5|qNZXhznkBquhI3pHVseL7?&pTE#M<<}TU#(YYdX2z z2~AG6rDoZ!v2VvqGLL>rl=PNLciy6`+>aC#bcwc2_(}Gi|4{3&C>Hh74%G)cv6r=5 zBJQ^f8?ns=r=Klje||cnu;oV9GouBTUOU2Ov~C3hdvjXd-WVtTZc3~7n8Wabf&$)| z!ThZ&>AM)B>kU6ra{nZ6ZAED(>~XDOSK2H!!*w5LYCYBliY*TG;A$hp@!z4>T(pAC z2?H7wZ-Fhj)rgr`!tPom`L}C|JMSZ?@~7r_`7xD}-dLmWf_U-|YXO~M;Z$dkBbx0> zqiHQ1k?9vsrLEdv-Lo{BG|w4HQ6a2ZtUKOqUc;;!w+H-gu>QwA@MA+A`r6$S7I$39 zYLo|tAL&Y_qugN`J%-l)bgJm@&^3dUeOxQ__Wl@6Zu|^7jr{WW-O1ok`wD#;{bx$A zGo&bB@u)U=z2a0oj;)m&9ed!3!pT1r2PV1WmE2rW-KKpxRXp%O+Y>shS}Z?LPi?o| z><~86(WAotX;{q+UU*cjTg^I7$Tg;~x2i+O@e6x;NDsMd8_>1wm9gEYUOCl#uA!QK z8aYkA(BzNOX@%_V{(5M;Xambsm{;VN<a33Ls+&O0I?8rWFhJvBMeIHdFtO%!R!dh8 zzrI~%LF;rYsHQ#M{so;ic}jIW9@FMsA4s!)H1SyF@4J-O=2LkdSh?U|s>%mqelT@3 z!jw7pNJTaIN0m2JdFJwzXXWi<KR>0FzpGc|BTasaoc@BY_Nj`y^qwB1RmNo_9pp5r zR6#%W)WN$(pDXf$W<6vlRO0pUE7If<`FdsSeDt6qZyan~4P74GsK^`3dj25a?UyR@ zM{f0x)LTAZvCi}kyr#;ow<^}3#y=W=YVxio4{LB~aJ;vhLMQLK@b|?08<&rUWRU#3 zJyh*MPuoKipPIPT#GfV}Z;ZUpa>{%#^JXoo(YOON@i;HRjY1}NfNs}bbgGtbMI5T) zQx%sgx+lE@YMrjmHq7e)O<c-#5?EQ!4$#Eqn!K&d<d+Xjex#APqi?xgE_od)_5n@a zSIwI$zpLz?GRvu)s&Hx6U+U9Q<o2v3=9>*6!_$@+^DT*V+wlBi7*C4V_0TghhxGq3 z$Hl56DW{uNMY~4sQR{5_dzLZI=B3fzr6$l^&vKYTE4$i3Ma}e@BTE`bR`r_0+-)2s z{QS4w;9e6fnl+w`lA4x3+jeKEJvQynp+WVV<I$sRYD&#fWAr$B{HO_%du7w!jZM(A zP7cL%Y+TW<(jOAhq<owsF^$TpYFy1Ys^{2LdR1~&$J$r4YwXdCr;*c)r?E@aud=t3 zDIc%Dc{%lZV+@;nt}NzxG}b0gWu8GXNc}yXP3hko^*p1>=^8~csjfqVBg$zj?@)^N z3xlftxn&q8pXyZJKG5E|oLaQ#KwEo-BB*63IaY}-mn*mvjaqt@%k`<~zSJ00y5vQN zgCp?rj4fS=4#&6$)yw<W{YRf1_?adJO>ULTkLmZE^>q)&yNP?tuLI3w_QE9$SKd#c zCzA%F-ngL@QjmhWy9QBVPHK7kUcVve`?)v$3W+Np|97?iNb8tP8Q&9ew_Ox9YLtY> zyw-KUoeHDE2a1rVsR*n)SaEgY;BvadeF(DRoLPe*iRE@*@<{|o%Ep!?;(M1PY-sI) zsNd=cYnmH}dQ0!IkIjdm_3fAJ^pbw)wf-nOzF;UiH$2DQ+K$46k{2xc<4E+JQ=J?( z#DR*uY2)2keDZ5bC5`)G?H@<7xi|nOGrVc8ej>&X_Mpml24Zd`Q9$ruv}_+qeVx<M zws#u6`;-C4)O9Q^APuISHZ%Q}shD(r3#)f=6wIYuc6nABs??jxzIbOt`l~(rJvbd5 zioDpet=YIS^^2lgSqAFJ4-~y`W|!mC+5az{f0@5?DkPF-_-CQ?>kuk!Jqnc;dz0t& zbky43oh<D~pjz2b7I7t|+`j>Lhn3UNHQBHp?u6GPhr#ATE4cCVbH<)=MnBsul%>1C zb<1$PGgTm|T{c{1dmuhA3;8qM;I=9g^Y^<!Cw&yGN43Pa@7XvR;)JgCvJt-16$N$~ z7_`_8#ttJ;<&7I|Y|B9I7JEK-nOL``1st44qsJ{b?0h;D|H!SO|7R#apTUH`^D+~c z?$*ZGUs;GwG{#&mx96T2UOJA(_z(|RmJG-G8}4Y;KLcrR+o7*}8gBJziWcuv(6C=q z4EZnuRgc&LW|`Q!r5U0uQnBWdDJF0~Pt!5S`>!MLS0fAPJRgDUbL*q~trYzBw8GIl zDg51WjSzES1io);iaft;eA;G<r&mT}?e#{;*)s|~s##+3(@`*MULW<`M`PC+dxXwP z#VAu_Y&@C@KVK7MPtQP)i|(M83(25|0>$eWQq+5fsMOh%UPhSFU^J4OGR)hMg-3Y` ztlK#Z9fo;=qSN7w_9$^5inFKPuq%8B!h>9K%z7vyd2M4>D;?vzIiui12)vuQB4Aig z40mwCkzYYr<>Z8@D#5rN<Op`AJHDi}!kn+&_<MC*qH1Votod$_MSpdHVp&V{eH(<e z`|U7kN>?a;+GD|dUraNy!;`fgVH_Naua|?cvn&#Ym3m|1h#2S?^@RJ4NbDQg4SUx% zNAr$;_?jG!Yajh_pl@Ha`Pl{0o^JRZ5`sOoU9ezF7*Yqi;a+GsQfoIykG5V==GfwD zC2u$-^~F?wUz}bXf&m?Taco;Kj`i|Kde=V4d)f)H`+8%;Y;TMT48fJh-Z*=(2L_t> z;N+PeSUJxZ<~H47_tP66T)U&mP+vqY?uBg@U9s&+FN}{1#Hw6d?ELPDW_PVI@-GFR zxA#U;ax5C3r*ewNgj3u4!PeQkoZe~Op@OR9CN}j(;*Wk%wX5jxR(7bf0kF?&j;L;) z`1*HKtatW;VV$PXk7qdM=w9AGhf`Jm`&HUjP}MkR{Ty(o&;y}U9Wf^XXfU@Go^SL- zpu!P@8n(yKrhVW%iD8p>2$E(I-j{lm>$~`p*MwZ(;jumNyO`j2IS?tUi2ujX8AI%X z@brNT+DhFK_R0y0-vKbxb-~=B0l4kthC4fgFg(l+S+Rj=V(p6JJpm}4=Z;z%1F$co zJraWh;Ps?EQtkXPb8jmoB>AK5SZBzs{qZ!v6?*4%z`i<;XmPRw8a#>xT?xglh<<qD z)C<Eqx5w7M!;$n?d&tAWFyG4qb=OBCyt@mw)`~!5KW7w8;<0nV5j9SRqk%&!qz6Uf zkdZTj-$r3MkBf*=k?3){73}+kp=FgAOl=>ArzMeS>lKZw2~n`kj6~73zOb(xf$+?} zs5&?rJC;Ns>11EbDd~&i4!vO9pf~*TgYiV_g^=BS@%3j27JUmxlzvAvtJ@8At$bjg z(gVF_`(j8)FFcLtjJCUiV1CjEGvfT<VCRjPf{qB~b24#W7o_d=LVQM7G+ELKx6b)v z(c&)nS*<IA&UJxroG)T@0`TcWC*)V{fb3~r7+<X;zV-4(VU!=NPAl+xkT1rx;W<+7 zgbN;C=+(s^dqWup=`rNxcgN=E4Bk(I&>+Br=erQR>FkM~-+IDl0>j6yo#A=I6Wy+N z!_yHR@#uFS3|`h5I>j8*vjEi13Pj5#0ce&QjMzGz5&ke70~ZHi+1kFSF{%T97Bv!X zkzSZ@5Q-{xK4`Qk6k~e>5raeU(cBZ&o(I9r%^h((U&smW*jd;et*^DmbRI`tM|+_1 z(*ShkdFWajAU(+wE8}_n_D2Da5<dUw1gi{Sz;aKxMEmo730S$(7fmEDxIX}{H1dLL z9Zy*CBV<a_JTRrF4-)5kVsMrMCy%>h?r#tD<?E&r_wC5V3{O`DVA5aS_&e4KrYW&_ zyxa-)e4QNhb}gr|zOLo%4R<@CE?<A0+qjlfOLt!!ZyJs3J31rKBO2CoJ#eyaG-4l8 z`8ti*qrkL1@u;;@QGPvpj-q@WMYne^zgDeF)q3u9z@wZF;P+~(_0?{K1HyL4BQw~p ze4LCP&C97-SnKlk2NT+qU#qCfP8C(zJ*u-^`L#-3)!vQl%G*`fs?Wpuy}ru+#5jlY z&%HJ{mS684=urN7=UtBF?H21D%daiA^uW-T{;0K@$4at4{NlPH(yc4}duCw&z|N@I zH4B4SXYA*D^N{5o;4ck_#X(<eFHXm7sT<rpvv8?TH(0eBgI4~X@$T~|^xxx)pKHeO zJ-8d(D`(;Bx?s339)qP3A#l5qiKVUjqNB$c4F3}b<IHr_aR`BxRXXx6gyFAY4(OZ( zm|V8QfJ&bDZX1mOJ;L$(cqVN1_~+hZ&^soI+mVLI+$eZG@<HRj!=R|&0s37dFl7** zhp0&C+*DxqT)tOa^Tg5CVOa4k097p_;CVR;t>#8R3gbE6-GiF%_Cn+8t;meuJL~AR zqEDQb+IrCAA704+(SRafD6saT8FhK7K;xLElrRyfbI^v)9q5S0I~7E0e6cg#fz~Vq z?kxx=v$qO(oe3d>cMAUfP7JN&dq&ky{5yp=3M^0PMAuGu!E3rdeR}E(ox%X>e|HF$ z4)sRk=R>eEk>?D`z)RN-Fj|*^lvBWro5NAt&I_gP!|~5$1*WECpk%El<jmpF4Q-F^ z<{5ai#2o=EvT*3D0tc&Q;oUAzbaBc;>dE#<tDKDxOAnZgbw`k|2kA6xk6e>hG`oif za*J%};B|L|@MmUbwQ<AQi4GLsv<=!E=g--9@IcP8V7m689sDarQm9#bj?bTNe{6%C zk^pL5I~8po0!}k{4dUMcdxs`t+9w5`DF@=2rx$WNrlR)|PrlAlF=v-MPAZa7H>Ev> zEKS4+r6*GUNr3Th1;$KCg!6^=NZB8cG+PhMi4Vk(fo*8=zAm`NpLd%4p%XH*0;qdn zAR-zB(D@oYQEcNui#CSfomV$%T)z`iT11iq1!B&$2)Y*63p4bisCZ(1jM?Rnhy*hP zjrT{$C^M{i8i-Q|>SN%JK(w<kLdMBJT;=Dko1gbbjUof=-{g<*Lk3v6JP=M7vhnI| zCR%X%;pH$)U6xr+=WwcO|GvHnR<-lTf}fUHmF170R{Y*@U?5JIG(`i8K%Dc_gYrgy z^s+KUgYE<H;*B9bEQy7ssXjiO<oRc@71~rDfZ0neak^J57JaP`zgBVZ>Cynw?Ewh+ zs*laazG!D!9gj2pamT<Ae;@Y6xr^Db>zIs|?M9<tSrU$LdrV*Qb4EBl&^{UK%^M(X zMI_$tH^cSXQRr}*<L(@XanCI<>{bM3PHKvkHKR~`wh2D>4(IpxMo2vxiTmqn;kIog zdM-7>-tKW&?o}Vg*L=}B)QrFTxFdFUABNAo-dEvY5jX~K24s}`LFJbn{Jpo?{CYE| z&pBN*F&$HQdmg9Th8m$$<pk8aWrkDJ2cY>;eVE4t!f{6vT)fx;tyWs%EUyFa>SdSf zA2G-XzdrclHP`cz`@P;BeH@t^g`wHiVR9@So4DSe^HQ;#(}IY>JZEHMH>VdlZI_pd z#~Ie}?h=dMIvI%K{@EU%fu`JFm8#T-_jGT(>t=?hyS-tz#0Ztwdc&$}EgbFcjjjeY zU{J>!bvhX1uEjuPzc7PI<$>^@S0B56Ct>f*#t10&g6CojJhAo0IBuUKA8(BcHy_`c zkFUbJkkg&q536HrkRRM1Ej~u0Q&a+uUXMUzWCB)|MZn`(B8>E6u;5i9?AM1PAv^&M zw{rR@5q^()BcNLXMm+6}XZ$+nBVW5A{5=gG?$G0MRxRDJgSWqa>w)Hv6Y<yYHaN`n z`s%o01=suRp$pdW@lITDLABS3<#v_q&M2P`71hMCCazU}zQEfx{$BIU5%>BeV9h~C zIPr5;23&G3r$OuOP}nm8C&$>8Uyt5ui|=g`P$$W@{Ca1H6a@0?y7q|}%jNQe6LF&M zK(O&C<+R1yekkR7S6cNizgESE${v;9G*sn3P25E1N8&K=KQ1J?oG#~b<EIV5Jl;=5 zHF2l$_e73k7;o3a;p6dq|K|4BXvg<aPBl0+@oCD}QC@Ni_HcbI`lnRHl_ritxV~xp zbIm-*?cn#5T+gwvcI8wvp2i+cJZj=WW3MJY!?VM1l;e?`N0d{|xEeb&>sqspO}6*> z*MD_G%W1D(qoKb$5#IdXch`Z$igmBa1FfE?mw&E_`&x(HQHR@WYv)l;HFz}Z!K7Lp z%;d4QYM?RJT8F^!v>~r0df@c&nz(nG=hm0C_}M~XsNq%vd)M^Eo*)Z!c^!(;W)0BP zCk)EfnaG%#fFe%oyo<+y_58i8oQA$i$G+(anEKKmw?@XH#UejAEr`R<l8&%+O2F<n z{y4+qbHQvg*e>pk>p5l^6B&$y`9@f{vkxleo1sqqFxWa6A#)(F^FK63nonO0Gj52g zhkN7P<oc*Nvk&U8Fo&*w2(Iz*^8@*Lcbq<2-Vb3@Mk9^Ww(Uown742AYJ{cy+|6ON z_`Qm40(8B*LU(Q)c3W6N`W*!6q&F5K0q6f=a0*O--4}*3zP>z1c;V#pM7)0#jNbh7 zf_uT`>oeXs2zt&5=-96Z#_;v#UONLyK2Ap|9m#y$2iy)**9g2_F&t-ZMBpyJ#>;4Y zST_>6JO{|tN24jfZa6L*XD#`eeW9bv{dH>PXw2aLJH_Q+DEmVvFC9?_`&al?<L9W+ zp5^gps?W-)X5KY%p_v!WJZR!ZGmieb5S-_6c(zaPayoC@Xe9D+{_pWM?HYe-{5z<9 zPh95xCyov-r#G67#@5EM<v2$*kFA&wjsNfQB7Ot^T;nIRP=X1M%abd3jmN15r^bIO zf2s6n^lJR2@nhiJKs@8)pUMv^r$_(pT22?e^)IJ&%>2q}USNlEsu{nMA_I-N-`5|@ zz$xx`&GntCvE}Pa*W0^XenLhPB5w7=vrDP)J`sn}Us7?IfB)zclY}L6qw(fJe>|=q zgLmHXcu}_>GD7)xhE*c5sAm#nzi<pmiN_lMNWeA;Yd>^B)tQ6vuAnO(R~du{Z~d^m zSrYyv`r+}sp)l$kh~m5<Xj`W%PJbJW+AVo(*(Bkfd3UT@G6dg8bwaJq{qg0MA1X=x zu<t-u%-<J-%D#b^+AR*Bng?Oiu2>Y+?22l8Vlj3^Crp}93oY9W$GyddDE7#}@(Tud zaz6v{6ATd%%WL=ZHTm}xY5aS)nlOHwj^H)b@%B_2mR+ch`ltE3r#I>00zV_!pocz2 zX7lg4l67I3GYoZO^w8?sFf8@Z#ktKRu**XaD@TvOJzG6AUz-Kn*Lu+Tm5GIK^iliK zNR01P9qZm^p<#oX7;8ET_g~dOgy~5Bor)n=wHOJT6a%EhW}$X)E$oWU#QG>hl;~zw z*r~C5Oq>D#kI^t(_+)^-BZpVmU8Q49gbvTBu>0ck>UiEKqr&b_+w}Q-XH?j|^@$!D zRUckqx6?^IWb_|VVRw&keWc{`y+v*J!OZIDotRZ&_wCCyuyRsXh21-A8=&n!|Fe5i znE~>zjKG_y8VGtj9Bu7&@v(9WdfMxut#b<6-PS|N&Vl%8ribO#dHlDl4qZ8k$Cf@; zoJvHW+ci*YNfK7osEG%8iFguWfQ+sKaigjsPUa?|w3{JXZb-&tpIWf$o(zX{Lo5$S zg-?1d+{jABU&RLaer6D^Og2RG^ue$hP!p5n!7wPQi7&f{@b>{%hsVRg$eCXqVGsE} z>8%ex=fP;Rl>6b!U{vX@hmBWKF)vIP<68}?u>0i!J+$eZf}pNk-Y~fW$Gybr@bCCP z99G9_@HIQI0>|e+HBq-<U<D4(zYSo1Ex7{6j>iT_Zk<|zBfBS`=fQ(2aQtdh6N+~K z!*T9<b&T#cxB`dHN`06f8B~G8@v0uO*QQqBxD!|d9x~tGPc=Y>tqvXdWsYmrUa`mz z{5RuIzuAG^b#d)aRhqTX2#p<nG8MI{uS;J)I^){DL;TEkXSm;ez*gF{#zEf~tj%Li z|31NLHFLm)Jsa6SbsUg4`zBi%Z;QP38`$yB&G7Zrb+)uiQ)IT-$xN*p;p>57R(7p1 z>Wp~A+P>iLyV!k${cy9ukk*&jw>Oq}*5N(7ddLm$(zY<=FE@CFGd6X$6P)?;xVOJL zL8ojL8~1>J4;Wy<!p3s?Eth@1V1t}*wOHPH8|Yk|z)A-;;^)1Xuq!@|u(96~wl}Cg z^0(D5r#opW>)fpeG*s1I!z2Lr#y4gqAzkp*dkgDb(g`}to3YO4J78yTXVz#bzX#1e zz{1W0b22?yrRrX|)>mTFrh4Ln-9e`J#1r|O!5sK+Nv3Cv$$pIu@)GLM5ZA`=8d;mp z#tndCk2mcakN}&PUUbJl0b3`zP+$K6e1CJHmsk6vzljZ{-S3Zl16L{@Hvm5!ZOQ0% zf8@3ErHGJz2$<wbTYAMIbDbY`-rEl`ldQ?ZFb>XbTT{ZBXk4q(iK@@&1N|zFRC|6O z^#5s3#(R1r<g*>kdDt5*vK*<n*%;`*ccD%TMkDC8GlldR4c|?!^dfsS4EDC+?`BJc zFF!A0?!aUm>*!0fnkHk&99ODTnuw4SF7&QyGFs?0qvGR<*qd%kRy78}pn6BL9h8cU z@2=!lEfwzkS@QY0LtvWPfqwlMjF8r?X)FH?Xu+pu6uUMJ3sU&A^R8)_W7?Xm8m2+# zv@LZ$HH`na(3UnWNXH|OMl{HD7+#q;(19lz@Os&r_Dqe$qmwSw)-wi;pE{CdD*tUQ zsRf;17RlF-1AXothOHm%=!AD9w$5lq1!KaHZ^Xwl3ghpscczQKBXDqCJKE{NzY{5T zB=;wwn6s}nxps?yb9g)QI5q-P);rQjpAqQm>_X2PkHn*ot*Oe3EZn>4L`!b->nANp zaU>JUDYn$Whu_EjWk-GqBe8X4ONwclg}s(dsD05Wq_{Mrj1d`VIh1IiK?e4&??5pJ zGT^+%i+1qe*mRNxP^nEg_ICR}?7jJ4kK5M=T%n>tl7!Hq5+xy-uKiw_GiNBINs^Fc zJZ5psL`W)AGG&gFWJ(AjBy&RMnaopo)^&Z){@maD+^^>!cwWy>@7LPb+QZtzHSE3K z>k3CZ%YjrpA`Cy5`cZV7A#iUSNG|zN978yWo*fvC4!wiOe%2^VTop+3pG9Kqh7byU z!CdMCgDH2?NJJ+LChsaE@Sw(EirqaN7&VlFy~D7<c_@DiheD6PnQa|H(Jv;9+@B7? zg84(qy+J2LuLz@${$A+6X*gM3@Ir6HVU(|Q!i8BQsavNmX!B+S-JIVUC!C`A-rN~8 z_D0ftuP(^?J%)laI^f2F(PY1?6HXrXr=2~#uw_O7MOk;j%L4&q>)Qd=PQ2HY(g6n^ z1ycTmZpgC<rs#P77jEhxDh};|GRHz_)9miJ9vDgyAG;#Nbp*Aa-W@JYN6?zX-BGV@ zBz3#S`gW1z=GOye4Mvk^-EL^ocr<x4pWSZc7;-z|gM;nHQtC%<yzerOt`6;q>w^bU zi_U!z=*n?dm-xUnJb+rf=!a*sBKg~EAo@m*qVS`>*p<xpdOKeXSr|lC=Xzp(VIWx~ z@_%*D1yNL6e@wL;L<y?`5H)lJ>CGO1Lx~ZT>%p;ZW{;$Z+kNq}S_oY|?u`xAL&$6T z0KBcu<1xSwRqKaR_ImzzGr!aKKi(I=z7HkaVSVwf@i0<idm*dEa5CN38=sdBA(!r5 z(AIPad3*PS&5|LctnkI>p?sfc;R7GuM|@`F1M73V-(}hd9iQ?%2?>GseLpJg6pVJe zMo}uqM|^oPipnnY!`VN$pCiKId@GQ~MGr$*xnPP~HymphMex4eKs4k1rdM<Qu<4Hw zigFu*JcGfsGiV6DeBv_^^DvYhH<V241mk;77>&Cfgr%nZZ0+ZZRU8wv)UY2S48zFn zYY_Ui9#1<%gRp<^I4UaZ4=0~-WV|*Q&8;U;>ec{`PdlEvRq(?UezxXxAC8Y9QRHSA zhMno7sH9*RD0?)8+6+U?u+j8tPAKL*j-aB2VK~muq={)EFs>9qo6N$npWid1&kez` zypd#6Cj@=(gwrDoLMVT`$5ju&-+zQt_N8EC-5W;Z`2Wd6-VUQ@-2)I-Jf8BZ4#C3v z<0;s7Ft!9vpqz3cSmWwP306V)W-ywH$3(%dHls--TE8Dn#%)F-(~j?7t4E@H&yh6I zW(1NyjHIYl!;zjA&hHaLak>oeb>xPk%gSNYEiV*#{0uj>tA^qu;bh#dIx>0xE_zUH z%*-E7P9e1sRm$rvq8eIu52H*@e_J+`KBm@0TI(ScJi8{AjT%B9k5xrwUcXakRRKN^ zqKHkEF)}`crhcxDhP;m(-k=)FJB*>Iqn7A4BZ{K>RKd@NqiJzuO^A7sWMNztspa`y z#<w<_&WoVZ?l#!7KZ5!$sEv{jlc}#$W7N*!`%#+)XzJFF>@4eHN=82le&>Wkho(`! zS0fa)o5K1H(Hzssy_qXsT%SNU?FQpyFFwQd9feN4xE{XW?BI7Yi{3-Aq0A848QT++ zD1?qw>4p0<f+)DUH{8eYeamV9f|raZJ)X~T*9MV&zW~fTH=3*(_s4j{AvAleAC@nS zB+niFu-}o_Ir*Y`B-^(w43$<7r;o;i@F8OYwOBh4Z8r0BB`Oq`QvFHKIuz}8^Zf%O zV6iWh7LN{tQ+fbBI{~D>9Y_6JRmY-36Dav_J4|vNM|n0?aCg~Qa<5VmL2pB7@!C45 zbNo-T>1GR~ZWH*N)*Acv52E>p8)0k;KWBb1$2xpGJz|b@h<N~ix3}egdHRzR$A}(2 zco4-ksDafvgD9tG9W>t*Ou77z>-KKJWIVYhrtJ!(T#LGJoY#u%5}ygjM=fb_S3P8x z6=d45EG`ZcbTi_kxZa?R_8z68`d-!Vh6j1=`7Ab!Z%*F#Zi<Mp9u!(+in+g=kj)x% z)STXuT68gmPXX_<mp6l!@45MZ-pd#bUszMwSEg7trv}+F@6alX-;WkmLip#_q_=Ce z^4Z*j_t7^h$3F16*Wc#&ajpXu-7kYCyr-Bx!wPG=d67$0Ep!~yjqFowaPM7LN>6vh z#ju`~7sGKmeS6Zx8}%@(TW`9$i@EsUd(*4d4lpk3OKyE@BfF9hIq8`rGRvR3{W8N@ z6Mr&(`9q9~>`zu>xt^8-s9R1II1lSgv%i?Y^+88USYm*s^ShDKpb8=e^d#?b)~Lp3 z*?E3e$T-=T+#8x8Bx)ep6@L&-9s5(?dwOW_ydxD?y(><-dQohvJaKz<C$boSN>sJ) zNa2?YMdZb<^p$;M=f3Jn#cMM}agFhmeZfw6xQ-{g!<UuVJCUTfZh_MK*(l0?Us3$5 zGnyuvT@=;Ww?f4(KPHi0?=s@s_DK{y+F2xjn53l-9XOrO`^pOyqxLn?P}QGwuODUm zd{QRzS*LnkMfG~uSN-^YQBRXqy)f(kS~+2T29n!#3$b2rAbIXOsoZ=pP)mOs#Oo&V zi!!lVC<X6&ru<kLO3^2r75ATkWOp%IX>J>=>BW5-L9w<*qUK?~KXSRP-w&ni&=O_9 zvT#k_8WO7EJ$^3QWj+z#^G9mf>J#I*H)2_LPG{`9l;ctJ^^unuSvJ`<RFm81hHB_p zc8He#wo15$o)`Fxp7pQ4VPyS)Z`>}HHDvjI=`>B=893!X>4O+$x~lIvQA=-EpOIzv zW4zD6`KR(egDTsV@O^UD2hl7bT*Kh7aPoZnQ&e{tp<%(0(OUW)y+{q`JMevjuVXa7 z2QXG>GDJ(ac^<0Cj{3Z(#^rS_AEL=>J5^alRbOqdDwp$`qT#)sQ*`O-^-mRfzmu=O zGoPrXuedf&lYK7o`zK$&v60VXmR}M7?)Q>$p<22euL|{pHCc|c(Q6)m&L`(Xf?0n} zR_Bd6o+_%>)p;gSO_%d<(}PJ`x}2})M~~NJIgf|e9IeT6ex#m^&}2F9<vIvxKAwvG z;+1{u!=)G9Pm%M!Cco!KpFgAg_k1s2SE$H&?$m{!7hxy0`L3qRc`xU4^Syq&pSWB% zZ{<Ah=rEY{YUH<We1^|dM%7j1Je2cN&O_aN`)B_Bule@h^XZ@YCFhfzN5Oj<klvIQ z$|*kwieC7ub?ZW+>}nGfXSengt=C=oy`>RFj~Sy(Z`+OZ>UB`m@4oEcilTlGs_68l zHf0+cD1&QwaeLb+<!r*KxWP>2nCA#8c8XOFjVw#~ADSUyn=wUiXpSSRjcIBld*tse zOKG#}A|ue0g6}s+_w^=pHP#*`buGxWuLq3wnp5xu_Q@X1-{bwNVtrgW>UPHl!+M$U z{fXrmGqPAx4Q?HcNw3fZfu&{X<EhHnQ{II7zBa+VD07OfX@#C!^yy=@I;a(6Kv7HF z@z;h*v?jGFJZ@E@{G8gl{4$@%sS2c5)&MVt8<D4-K0dB3N5SXIVAZ=aq*wEaP<EJ6 z={N%vC>2T1=ZWakZ>FfqyoYj|{}k((=P;wcm(XM0!&c*wBIlb8MSYFacn>YM#A>{U zV@sEc<;-vBJ#C5T!h8p#Z;Qp-S=A}1S55IC*PI?kj1Uu;$57*b6VXWJHN1{f3Yq7y z$U9c!HO$eE)p!hXZwoXYLv-2&sJw-OiFq22VV-+|#%u7i$=7%bX1A|sJcSuGuV}o5 z;Z@ITJccK03N+qAxyAR<zOp^t^tp#Ff7{Xc8%22K@dqt@d>6sp?CDy|+xQhzlfqix z!o5kg=vk9%s8&#enoYclSG?EV(I#EvCs^0X(D(@BZ=TTj2_tfkL**+J%+Aty3AekX zLFFlYvdYwW32vD?pz;*N)Vm1((}{k$+(+zcC)yEuQsXD|Ihd#M6Nvq6%RY6cS<P-^ z=nEHWIqEWog*BwdH!oxTF;}|pc@}AH8&a!Vxp=+Cl^njDfcp?<s(LmXy<54^%!kKN z_Ch@x=6V#h>O0YeH`!RZuP*iR%);xwbtzvzSmP(uI5bt`BLwU{tML(zuFuu@2j-V< zLggb^f4>TqpV0MKmc~c8^EO@MBTO<sqwx_w^gXHZ5i(n5X?%p4tuiz|!n*k%q4E*Z z20Vw#Kd5f?9V#EeAnZF-e!|~gPoVM<POrTOm5=ZcIT|0quP8&~9~8gbtML)^O0qP5 z!mgj08V}*<lbsqbVP=y|jfe2%)OL-R&~^GDjgN3}^bU=WaBt~3ScKZra<_{ps#KG1 z4&9*f5xx{|(D(>{4oKAa2*($!)%XY_6H_!kg71%bjgPQ3Ek)xathg7i@ev${J%!3c zsFC{#Dlg&f?=u<?!S}>1jy=|jiXLTXe1z07+ciEyU;AYmAHmx-UgIIia`q2M)_4fA ze9M8U8V^C{ljU9;l&kR%{=Rz)Dj(tB_2lR5*Z2q--StT2BgEF!Bb9&fWnno|{k~OH z`3bVUrN=)(<s(Qt404`A<s-=TX7#O+Sa;Bf&dyF%UKW+ttv?I%o{Gvxkn2%imw0C7 zEbY3~vr1VZRxtnI-|M|<&<as#T$#qFEfT$%fABSZshH0EgA0LC;`1g$nxsUCjB-Xg zl<9dZay9;eoNsb{ILyAF@evw*DbV-_a$U>&z~+Vp8n3{w**Oj6eL~(h_MJJW@eQsv z$<_D;y=NTP_yzNl_Ce(rNR;zgu5&M&eNg!Za{ae_y9X-IK(6z>6?Q@88OU{hXlg1{ zo`GEdD@Gj9cm{I4>`Kqlcm{GEIUAkQcm}dRWPi!~ptM8UHM&N;#v_pPOwK1c&*VI^ zdy=d12AY1l0hLD}=armCe<bhMcmx5vH)}isIiEIG{|%Klpw1_iM<C~yoKN|qKS1RX z$oZ7j@G(>#!I9sKF~P7MB^Sk`Yom7L(qT1B?c3A8@6T?*%Qe1$Trab0CcySwO}e&W zEqXIwAlZ2}Y?(h`mAw?^%o}*@umX#iHz2QDaQVlWC$PwTIW9AAK<Z1mY@MYVKOix2 ziN+WBD>p{t2b6Y=MKSyF$3I%8@dAb<FV%Pg{w~WkUO>gdB^poQe8*UgA0TC!PnIiD zrpt0<eKMb{Hzw|d=2x%Z>LpsTf4_Z;FHrscPvyPS(nI!a)3B=EPR(!s<MjQSeDl*P z&A(s8LwtUw|0`MZ=U@6ES@Zv&FnqnH7Z#SHp;w=uQ2qK<RQUof&bu`Ke)rvnH2?k$ z)z4~v{m)Z!wd);QUxDh^e|*t(O}=J+7ph<XwlT$;+#_Xy=HIWP>d(Krb-d=^zwSz$ z=I^hzOZDsjX_Erg&%f2gbx{5KN4{I7`T0AqErsgef7GlDss8*bs{Z{G!+%5d_gCAg z`t{$M$6P}8^Y_hp3Dv(p#rO_Xzy9I+ccA+DZyb3Is(*hGKgU)7{<!T$Q2qPo7Z*VF z>+jRO5UQWQUS6)|-@h<@r{>?kC+dji-(UCQPR*~sUtEUf=Rd+fP4n*`G-S8t-)}N3 zPV?)J{jyH;^S{^P5mf*FP=kk1{rfv4KY;4rAJ*d~RKNavp|7C&`L~(+394WJ$Dq$p z{rsEX`pwUSDYU4@FQ|V09oSCQ&tJ7$_48Lz_47Ycb*1LtzyJ9<&EMbg=w{8oKQ(u! z=I`H$d5fx_zuNDrpTCN#pZ{3DUYei(QU9KrUw^f7-kP6(lwNPm?|=K@_L`r6x$0dt zzy6PHyJ~*^gWGh}{Ql2R>81JiNBQ*C{QX<l_0atMmp|yD`S;gr*;VuRuk7Hf`T4(b z>96_uCs*pO`S*AF*hTaA-#CHy2YXJWr*DUAe*I0tBQ-z&(<M=w-~a1RoizXc%2PXP z{{D6Edue|D2Pg7(7W?@>xA)Wh`s2+9YJUEcMh0qr{~y!%%%1)FP4d}ifc^Z3^S)2P z>PR|*p_-q6$;%NM4<M0!Ayj{V>u!TIfB*G$25Nr(Np%7>zyD{SdH?6{Db(rwV9nou z`nI8(zyD+2k5K*nZI481{{B7K?@smiufMyU=Fe~Ut&Qg2zqfgN&9C2gU<b{w{|x&Q ztN#2$mUYtn`<3V(nqR*F|3{Pk`ez!|!mKKGWY?%VT9x~Q_EtB6{>GY=Jmfr5Hq@ln zZ;!*t%8o|dKFR;S_=B3+RV06}?@%$l`Wt*-#Qq`wpqg%9z5>;mXGq_+Ris+u4K@7} z@nuQXQ?ag9C7OQYjV`||Z)u%M>~r-U!+KYw#bNpU&RT)o$LDM1Tl!tq^i^~kWz1ZF ztJuBJm|m^FtzGYX`#&i4uKswW>C1G9YI^qum1tAoW4yAiL>({Q*6FG3P_Iv!W=utH zk8ynt<FEg1pDb6cN3}=AG{;J`yW;<}Z{T`kvY+uoyDs}lwcE<F67_ibKmDNAr>2i? zY)oOR|0msOh9S+Q2IQM<K(iSuZZ;r;3Ju9O$&mCJca-_b|2Zs2NBaMSWu_qwjWQq= zUnd!mntr@u3Cfgrr0);E067j6@aH$oKUJH`<-dW)Ks&nrN}uWsx7YAy%i2_B!7oUZ z>Bo|4Xz42YE~r3557<(0Kv_yPu%*4@%aU4NpR?tu*+1olw6W3jRlNJA0tJ+-Mw921 zrOZh-6n9IX+B#RJX6JuFVq#}2EnUUci_6pLR+Xu5gR+{QiZVUR)rv}fFmL)#6S_V8 z7bJ$1G1t;nwESd5r`Ma2agHI?{>y|!^K#UuqX~`W_Ui93qgGW7X^C%rvUMt>VE~mQ zwO^LMGoW$(YEz>HWhktR1NFUVKt|hY(6V9!%7qPC95m3{qoUfL-RsKGGk+8ED>0yu zyJl3@{TJ^cGT+?5fK<fCFHq}!xb+*<ddtizg{l|i@B?Z-ANq#YZ7r!zSgD5V>wkw@ zZd22rI#l~dO;_<kzi&|c?**5)gZsTQbK=$Z#cwEu+P)PtN->e!AME{u|25}8`NPUl z&SfY1>slENJGJ?ZF>8#d?o@sDhceRoPpyAk{qm&Fj|h*iDC<{+5{zGKSZ2;EsN=SJ z;(Mt5c|7rr)=qQp*9hhDw;u8q@jOl{#`3uM-u{T8+~3}pjOc+wLrPn2MBm@l=d)rX ziZ*LNMhlFnpu~lSzcD1Y<4zQK&X7u9I??B>a^zOliQLo5(d0Hx6cAm8Tv)bUT1Jy! zdK*wv*8eolfPS<7o}Kz+@V-9Hf1*zdx!l@O`t*Y93(nA|Yh1ppM^~?0KmV*3S+AT2 zvR>I=QkM10{*%{bx@?b}M^aC=ORiVhF1c>i`K$K({$*t~T==NGhFyOdXn6PR53T>z zb*PSq+P~YUSZVV>qB>7xzpL{_O_%dVU015CqN=B^H&s?qmDTyH%5om7>r0jYd!4DW zx(?O#rXor$wd)eq`6$<^T8^5oqMEMOqssri&Q)2iceS0WtfHLXsx0TZYL_ajsLrqA z*WXb**N`qA{(*5DjL6ES6jtMm=uONI{N8CuDXu@^Kh~HcqkiH9j7k65FT6ZuOsz_P z;m|x|I-jafs+_h?pHzAF90T%Y{kTvA%4Yr7C_|B4?n#R>WXa{e*j$F<xxSk|W#|)^ zFYA%@%KNOm@5*}R`j_>}^(O0;>rU1y?-R0KdEb`x%KP`x*=MlNH3ikC=Hm4It(dtw zAE_6%Xqet`14_0XL*SiF&>wUhPfl!u#k&l6|FIoTcQT=OX%|dd?}cCUG~C;nhN$X) zqf`1#6tCZkto^qz;ll=mT)&6He%tVQ)qNDr+62dtXE5%~`Fvj>;@~#;t}4M~{-#{Y z&yl&Ad*HcpKfL;ELx+WXFlP52JWkyWi-r5ps`WlRqvP<McL3G{PUF-C-Y=SP3idbu z#;om399w-1JvN`ifDze9n0gkW#iw!cMILHLok8Y;^C+Bm7H&b8G`sxG@-<wOb`ke3 zpM}M@3+O%V20k{pgci;>P?&Q8k)DP4H8&4!hTg}=n&&V%t{7AG&SH7&Eu=R-k5>WD zVSM2f;u}0ek0&{3_V*j~K9G%8jbFpkG#jHYlwe)a5j?Vci&jBL@Z9G;mVeAZlf5O_ z{WJqV=DmkOoqedY^BvsV?cslfy+peHHq@H%0O>O}!tjqmBxNOQ?R@chJw{uc!KSy# zNa1~^3THQB;elKfaNn!rl{qvGB{fbUxamIRaXg#wCFy8BDGm0c4&cj}o2XD}FJ9NY zhgXmHA~y0V+BQr_lcT#a&hG%GpUXw~iep+iCk`FM;;|=S_caUA-40=~VHSEl+>2Q+ zkKo<#n~0io3@7g0#p#Dx$gB1g<K7>|lWJ-B>~&Pjul#);M|K%fwBv8()(9gi=}}I6 zU_UOq8ZQ)wYep2@?W$5SwmcPoxUEczE>F>$k1IXySD@nW50zSi_itO~DeWGcP`-hl zxU|BQqFvu9oqbIywxgA};ABSm-7AZR)~1y2Ute^&YD!TyjfAa-3E44s`0-BmGhEPK z)OcT>(hhnGdwt%oeb`-8+F(p2DT=trF=o7@y+k2DoAfrhieCJjC^q*HN1WOJFr>O@ zHh`ZS{xyVbw;s1Qng6}JCB~RM8-7-#9cc;W$!_ioogGVdSD@rS-s$W(J)7HKv#gMI zyuQ!Rtb8jW?WnekWj9Bi9aBDX{`jUkJEGaI&~rpfogIH)F{W5+51k!@e;QHLq6RuU z>LnYIMPW6a9W{@a=X12G!qJ`E|NF6W`!eJFFUqzOV+t<0r_gT3N2itWPF(NkJ4&rF z-2aIul?IbdD0zR0ve1xYU+CXaHhY+oUY82O{I@B&IT(t8T};Vye{E5*ni+Wp*Ab8R zn2-f?@jrLxefqVnMgFo1e4Y+*^=bujYtvO&wB~kvBGJ!+V|P60CWJAMgSUscJB9nZ zfv3pmYQ!<y>_yMN3@LxMlepBJ?f76Wsthxv>`taaw!1=oV@h79Cqk<5e93#Qv*T1F z9^b5&Iy+{%aQoN&(Ajb6j0w5Ln+j=%?M=QeYU%9I8^Ce}SDhWNBPvi@ZgZU-%X^n+ zPGk$69XEWq--_IHc1%5FL~d2;=<KMx-H2i%EOd6raR^vmfUhm<A(+vtvNgO%=0LAZ zRm`fEgOVQ(a6ZrbxiQtze{BZ7_He{t)@yNPyBNwC{bHTyzWx;KHl~UjLr){QLAr<w zN{8JzJ-qeYgq?xrn6_#&tQOdy&GZcTFE_`9Nqdo9<E7X?ZwuycFN1fpKcl#>qnI}A zBRq$V64i^pBRPDONSVxWg6!&w$uCM_H}$A8%TAv>=Wkc)`5#1oj|bvu)ePJ`a!m{y zb`qI!??uSeQwaZlS@h&~<*t1td>QS=oD*wPtSEWy5aGAFGL?L&B;tek{6w#ouxFmQ znr{Ejf|6|$mG^ZjQnJ}G<wQp_ihgaYq+a3m?G~*Rtu9B|QyMD=AM^9_?ggcIFpt0W zeC1}V0;I>gVcPaH2>sd^Q_XWR)wUDb*%cslkQZY4p5#qUd2jd#qKn$WasNKpuI~+} zhDUI-WB@$e4<PnfTMXxW<IVM*Q9h0Lbt)Ve0g*=#b@rU-&F%MkTMpy>bMPwA81dO# zQP$%RICR(ny-M|vGG;%nT6y4U!9FN+TcS<VGsyQ2LfbM0j3Kb>$>&x9gOyF}uNrOg zvvrR$709!muW~$#=c#hO^>{wF((`!M+AGb3JU<Rrp5OU}DDL;#ZS}}|fTK91zZcOC zZBS$LdqmB*7u6P)XyenT?N=mszO5`ZxsU#(4%m617@<608qR-%IG!J#es2)FxH__r z@cD>yy68XW9xOJcinN>(MDx7(wdD=0cplVS!uv)GZE$~#9>oQlqvQHt+I&de@d0`~ zKOCp=xZhYS;^%!vGS-O5x4i#kmMs(qee%AZBleoUh4;~GVr1@1xHW$uoKo*$;*ZOs z+2Q-hT=`zK@~=cC@$n*HRb_J8u||YhR;28z86y0Z1;v&*CRRS;`^DWeVp_Br#ooRm zvM!XP@Hsa`^9hFJ)bhMYdt^WshYyQ*_aa13V4mWcBBc2?!Kc`#C|%tiyZ?HM^q)=9 zW$ZhAJkSSr*FK==LKjrGd5!3_c4+_dDZ<nJFn!z$WSblp4Kto0_}n=WlFR)SWQ@z9 zKjFsX*|PW>Hd)lew-_#GT`QP>eghZl=2&*C2($MFVbE_Q=EN3>iIMz#=zWR**HD2n zkKPepjy#_8E{WB7{9Fpk6V5M9$i}Bo1hmtm<d$p1$L=4{tw&oN-})XC9oC999lzph zLZ<lp(HSVt@z_%B0xWAKVCK3!6#rh1q+h2I+jlvv?;k|$#tHDZPlIW<$!L(d3#s<g z(P#HT*tM7rW48j#&KZsTy62JBatwl+<l$q*Xl(7m=^Tq?e&ZbGdX7cX@l!C~GXpjS znfQKk4kFI)f<ceJF!<DNB%hs)V{Z?@`|~_(pH_h4fiYM)yZ{l8=40#a^C(+u0lJ?& zj|ZVKX#61uzWe86#G@Rfu8cvgJq38<kbplE3vhSea&)OzfQfZS;{DBY@Y*<1*Dl%4 zh|H7tx^k4RU7y+=MCs%)Iy-YZ?Lk7hKXvwwwB8A;Wm9!_cmKQtA9MfGwO{s!)VupC z1Kn;f(AgvH`{1_=7WQ*-%i;u%1TEFIU&`CY<e=|`6}o<x_HE&JN6Um&XuBd0fpwE~ z<0QvzdS(GE`X%Z5LF&uvvR>H^->^II%v*_r_3pyy%`((naTEJ4EXS4hH_@K=b_d^o z0p<Ku)VTT??w_Z?d%#E7cunL!c!9+&#^Xi^>m8keWN`~u&y7a5M=`>yj>V>eyO{WV zI`%(%g^9{MoPGBR&-VX?-uFLavimHwd;bz&%g@0vk6TD`iouN^H?isQeAKlr#+W~1 z5dYvF@;lAfmD}RaTd-+7Qdj=A^~H!i5UFd&%vvvDYcyKdz7bBJaP`ADUAqU5`ih&K zCZpA%uR!uFNLkt?+x2tU7v$>A(Y05$-{$*kG^o8m*S^Rv50G?q2_(vP%YHn3tQbYT zR-o_CyV&Hs3bLPNzv>s=#MF{RUAol!cm1`BOei?%rt(aE-Uq%`sydmH_e~@5^d;j< z12LzUDWy5o6m#mBk@xRfqQ-f?Uq5ye-lO?F$f%{r$z*=Tc_DTh@%w~v7x8Owc?urv zDf~L}eSU0r;pW8e1>c*CZ=3mjz`w2dHh|xA3mip_cti5cau%oE`2A~kC2=~)kYcx0 z6gAZ6#eyHoJqshU>+n(;e3svD4&7HKP3CgioK@^<RbYRMBIQ(Te!m%hLf7usmH0jP z&R6BmVSevgUO`AZ^zL%HovqFek5MKRHN-_{N4*$+uQ6<{vt#%;ejlsPv3CBk!-IVZ z^jbI3+0pGZ+hJp`vqNm+_Aa#4*`ZgN+u7bgXNS=zehzkgtFt4^tOD8Tz0}zu--G7) z^ZTI13FWw2f2Sg4U~UD<j(wnb*_u$a|2d`4HRb_&{#33^=l98Zua)#Zrj#9LDMB6i zeZiuV*z*U=m+Fbp4|&{78;YcE{2slbg_wAbu|+#EjO&e^%dvwT*xn7@#ifJB6g5bQ zM?;J$e`;rOeJ6j9RB#jh%J6&Vv*u!oE02q{t+?RN-vLQA#Z2ZKW#2Xw$JZHB@_K!- zycze4<tt?ukC)w}>$-L~nZ@Iu`$ExA;`ipyZ*_KT<2}RRZw5lzk#~>BX+&iq?O2$> z^Xj?1&W<;R{C;q%iO!CnzqwyJw$$0t<QeZN?Do*vF{c9Cv(H&)M??zyp?KEN*|GgR zzgHhGud}1o6dtF%FN(B7j>G8yGfI9HD>n1|epY{(=vtlo`}P_U_ky3-{gTC~$~+!x zH;ZzyY|q0TB8B-{$yK+BhC6utCZ>rw4UH*b;1;2mWkmDu>=YfCU!>=-PQ-QN`CcJK zJm464!CRM$oP*^!R>E>I>L<%z=8F0a4asimUt(uj{tg&5Rg9a*`Cjq=mpJC8UdVW{ zeFVR6Cx?mW&-uCgc(Rzl>ovM~q;NFg_rx7@#I19@9#7BIwY$b!6YAe}nW(arpU<z8 zbaqU?Sb_RGr0DDzx4t~(8f@0t;XcBcvX7_e?C_dxM8-c?>+G2C#Qi#Fxz3KAQ9NHB z&ez!y+}W7CcFxq<;laEuyOq;)b_DL^?;x|8Iy*Y8Fk%1fc{)2DEh<kppDq)ThnmnM ze*UO<vtSJ}MmD8=Th}1Q+?^IWuEEWD?qu6&HG1`IMUnPNcs{cQWwG4!M+>sAw+3cw zT2jZ<HQM!vD{HXUptUBC+}K*Xo^8wVm{`B$m77+M64sbzak({&n$UKx=Vk%d*J{01 z|HQ!c`1#14;!dxF(}!l1aCt5A?ORa$GwZP4n*C@C*5b2AOX}Nty;h%1(0Uvl+FFzE zaQqWhul#&LU0CnRQa4KFayHFuL>XL;UP@!Fp8WSsDdpq_tv(gEyEfD0$Fn`?Bg^); zo0F2W0cKTOYN*<+%7^B))^OQLMZ?mn(2&VwTK>!LTs5?r)mXzvY}cA@o3wf^I&DIw z$L_Q}dlLlPwPycjoMyW`k8jfK^2peXcWjqO_f48z6Y6i$>{4abE-%(o?P|q(FWD}& zoD*zUGM8h)b}i?6@_5{m?`_fQi%Q>u6du34;H~(^<JYP`$I<2S3Lmsp8^3&()p0}d z7Og(>{acXC<EF~$xP`KwI&K$PuRo91X)ee3wHvvy?8xJm^iMs0gSTn<zcY?+(TIN4 zU4>?5?2p%fC6;hpvm>)tV#Fs`YHPX*7Gqs$+{YDY*4>r7ed5r4MMG-aZv_@E;XUn3 zEAV)m3zcqPfz&fDlwlo*VV|7I^Hv=0G<0Dfu9a}u;!G8m#iRENXEI(IkI>7`G}k`? zuI!_<*g64=M!3+z>_p62?n19RB%*WIhIBe02@QHRq(|oyk?!uw=SfMZWaCN;XD7nr zxhtKxoqz{>UFrL*1a$o9N~I2~FzOPwbKOc*>E=q-qv8+|(~xRCUxB%&U1*|P9QM1o zka?4paDDDfIjQj|XYN8>+!8Q&nG0<XN`#qrLrQs^h!Sg8>as2oC(>N$(3%7+^>!hv zm06e)<f_9bu{*VN6+<H3v~(38vD|SQ$K_#t6;-+RVvd8uvWlwwE6GEXRaE8M+gfO{ zimJRnvy~>RsLGqpD4MLID)(Anhaxj_G1=0ADpWaxZ$)(|`^Rx~^|qsou+vDG!SUCk zk7LAEJDUCA2&PxBOP@UtGp~brf3Zi=uazS`ns5Sco{r=gkp|JufnIFcfje93QbNpb zBo@~p^IhA}uR6zdWBJ=OJMFsh%-Wj1ntr;=J}o_>@qSI;+xdW&UrkrbQ`4JzIZ=9Y z5}X+=P1mAKR(&#N{Bg9tmYzPZA=!Cu#A;WL{d;X4PPTTT>pm$uyy)XXOOiK2>NV$b zIy%Mc%9Z6v{KDm`*QK8K83(%gWg~{1cA!JsQ$R`f<UVP=4*!a?C)W=fA@vrXu1^=2 z<Uqx;o+ok5+v$H{0n0i6TvzoR*`BC6>+!pj6D?t^$2g|qMjh_t>jo@KJ!!w}51CKm zzxBr4aG-9{|I=P+hs1A-9cgOi4Ul@W-O=3sf=5}n&+WbWUnuR7dTyc4RPZVpvYp@S zH=yc&Z-hiS9#U`Rsrt08Gz}@eoajBH0b_9HUL6kLdc9bdda_*EFEXFR|2Mr3x9U+6 zx8t$_&!2l~I+XcjdD1><udH99Y@gJVcFA_h`Xw6HZ9tFirs?dL{VV%hwo9UHht!k( zrJK*C&Q#W8Jx>0EvLB^heq)a7<+ch*hK(p8bS1u?b)|yXmALrEmHcg1VLZnrT&x#| zRUKU^a!?!&EN)1B2d}^fUN;kOuRyPjE@XXR1<a1~x~UV#`JAcu<2ZQMbD=={l~}ai znQYg_BmJQ>)mj~o^XHr?K0E=-ja_J6odlGGa;)vVM7&(&LWaE)v72LXUmuo)IQ~)g z_Zx|@cIDXI)=3y&$(6RmCSuhCSGxN&0d05ieQ;?4cD&~6O;+J*F1K_0N=)hCO0HAl zaD8q=a{sgfZ;!c9oDzrHjxJ=2mHa*FOhxJO7-ht<vy}v#Ug$zOBN8#8b3;1uE)o4K zTq$^aBI<1Cen?G#dhV~DFWT>_pkaOMavFwqE2H86e}DP^?=R~8RjxyMe~>8GwOsE~ zPp;qpuisy$q?IT8?}zYvOL?-5$w0fRMr1fV6F>PpC41@#1XM1^F*c9k;PEnK_vcB( z4K${4GjehHf+_vFl8D#)IIhBq1WbCv@vk1G;wq=#?X(S#o%P7PU@sO=`3k#X8*wb* z6G}@`Fd@AZv+~kWZ`u#MIGK!1ufAaW@pX8>`MxKez*ENP=%Y9mS)TIhAH{%0hScQo zVTkZ@<ZYY)hpC3Nctjkgu)j;7Qyda%8IaA{-CDi9$DP&iW5*-7&E;fX%)r3Fa&+2o zo7UbX{C+xWwk27yeQ6&nYW6mLSy8k9_(BVM#rE2HvL6-Or(alw0@>by^R1{i+uwSZ z1zE6thn`tdB-?vyR5c1=`{uQ&L66v;=u5R|?z<FJ39Ly8Y;UhSHK=z^GLkmeB-<0~ zpx@AfzOp_37L_T2?HSe7ilEx#Z$+ML$Mo8jX*%2GGOa54vpoUAig_*DFz0(;N}2N> zJ1jUZ=lbtha@&Uz`g}*`Mjtw&yhmZa4>kB)gaQ*EGTl~$;wwHJ8>|2i4*GBmlR{LA z^`#>Lh1j{omkK$(*XCZ7VR0EV>iJNK`DKh}e3ftswwyja@e<YvZ%PO%L`LOalu)k_ z$G&+}*ig>Lry$Q5w;t?8j!O%$y0Q;lk162!;X_N>-NKcoKJ=uZ5OWUoqBretVMbCf zioIHhns<7U=fd}Bag6KTS%l%=y(#}k5#BfLMep0ZM>5Bub=&wIMZdktZoqeh><*yP zGEcGWWdPNB_5)*>|8DW*2Ts~>tTp|oD0UdZ=X*b~_C*9)K6#2wSNf4Z@6jLHIDmHc z{fQUMquyWBfRt@v)Q-`-$_UzC`xlNp37|0cXR?3Zk0!6Ug}mzhY4Nyxte(R098z<! z=SBqWn|%wbIOdIGjY7P438c2oo}kDwkQ{H`#FoS`+S&98I-VFxv#J-O^}aBgb>k*V zIOdM^^vgKIF&aGv6`;=MFy@nAM&`IM8h+qBoVo;1;Feqr>KRDWGtT40`Upy5Kfrkt zI3`+10WM??pv+#bbT)%yJT`Zw-ID{TYA0v%E*?OI!kHFW`ceC&#uP35DRgCHy65Ic zL##P=W~e`TH*lw;F9wi%fCufF>91jvy8#>{#fj!m_S108{vfKT--z6Q2h-3TXUYo= zqBUkssN(w|%5!(8zg&a0d{xgd-<R|C_v=Z<9h|8P^E(TNx$-w*PwKjXzv=t+q?2au z{7u(W)4#-es{T~J5E^jDmD0puGT+JHbT0<cm$Qw@rfvu+7VflfP>7~qI(@LF@0dG; zu4MAFd-V|Nwau9t?;Ju2uNqTczz{lA#hseF4AJykEE}Tf8~zHXt@B*T<l0c0G0d5g zf`?IdHpkFr{$#Bh?lkNr$3tNI`=;<Xa(mvC;do(Q%*&xMbiI!=-Pt~tJo`7M%Z<iT z{OhLlaMl=2|M;9Sn*OaZ<LPT<SE@N+Jek&Xrpx{u!#kugJul)oX>Xg-UxUYK`j<Cy zEN?EqQshLkGIOO`W|L@Kb7vY@`%jwd+nCmjpFoaQ?(9!ELDT=N&oOmaKO%1$joRo+ z7pu;oR#TkGwBr=s$7oD9=1!(2cJB0{%oI)kQ~&9j{=2`b()Vh-7qEzZ?$0-;1<VsZ z|F}6_du>gB2XJ~%TUuc!XpXNfxfV3n>FM(Qb3O5qEj{CS%CA1#QuQ~@b^1$wSW|Ml zdgK{jl`i$GM++BMrLTAEQk@6ZwD5CXUHTS(TMFarVf-(VCwyJ%$#kDDw)CNGJvv;m zCV6l^sW)S3RjNG6nf5-jrny1RB;`}g0g9UFOcGa`)TE3+XIfUTD#g@vr^sAeierps ztnkg1wsE>X;}Vvm_cYXGiE6skbGciE`QNT&$vCC1yRJN$e;$`(H?$cI=W<k(^~idk zSE@zJIbSK`FD^%xEA=jYYflS$yV9hq?Fr!6wyoOGc3z(aKRDiT3s*X}wms$X`dm7u zEg8f&ri#<sQzEa=p<UY2I$oc_C);b|yUMw(hWlE#*T(tgO-~KWW(fMu>+*Xk=r^y^ zuU&{j%$tze5s*tWcWO8tTD}z=cU7HFSN?2G0ldzh_EYFMuRGsU3iUq6^KYR-QM}&% z?xJY=M_Tg!9P59r){;i?I&1o(1vwsc<=8SU=`*i4rDsd}#p~_zjFy^y4X2ixe!Ke~ zWWehzAf5k#!|Sedk7ne~>+MZ-4@#@<PG^pKX!`xCHrMpiCb*D?k2AI1?Mw!p`94s_ znKF63J><Eb$LlT8!9~-5=kB8EFAu0s-n`B#Q+<v%;7YxFv2P`>x1x*nX#%ge4V@Zj z`XyECYx*|Z9O$lxGdZ<$r0J%v<h7(8dGUIy@8Luhc)cC&&OVpC{_PJsX!@yZYisLl z^+P*t-CYi=tF5=w_V(I(JHY!Fs{Xb?cA9>fCYBUv&avdrSkjR`g3@nU(sSM;?8X1& z(a&y9Sz%_B!!f6&o=mS8X-2~j{?BzO2lIPJ!j<N<mE)7m>MAJXJ^KJYs!M)emUJkO z*9lot+Ya@pYM~|FaH~htMw!uRPS>AgMhToQuS<QKQ>Nt0`Fq^uI8u%4>GWj20i7(V zcbGFd@INcobaN)NF=lj=WtmRrO{snN|4Hw(!;<|7+^G-a$0x27Rl$tjF%Dy##_6gY zzP6z*UF!8`eKq~UNB$ScD_329S>9PrA6LnpRN2_4nTBdTvfL0ZS51GO&F4m}C(~v9 zUpf6QmmBb*Cz1#9zh*}DKwI_+?$okBZW{c=#*_VVsO)Qu@7Nom6^+TqH~=NQ=ikO; z5X>)dUV~xSx4S%DJ3baJN#+zkWj0K1nbU5@aWVW(xp@M{CYw-f@f@^zxEf1oD8|fK zhr?Zl<8EoP4p;E?_q@;iZ@mGH2Erh4qfRfrtPkF_+=rwYLAYyw0w3MOVH<r66_y7h zDPb@Aej9<XNoQbsV-mc6oP*xVX~@}s8a?}ufoI`KEZ}<Jo2TLRoHOX3;saPeM*pZz z?8o?A!-A`&8a`v+vKzJoQ6a&MKDXlkjx@HQ)i3^1dhfl2x0miKFHT>>D66vK-1E!m zuy2=A@-YuzcPA<qHrr5UkCS*4u^kKiMv51Xn~}~wVXs6XdIXFV?eE^!&?Vy<;?}ef zcVAz{wyt(cd)F-NtT#-_O*)DT^$V3+rhByfS3|eq(Yw)zd~uDrbdmV#d>Ka?42GBM zW$b2D(>M8S)}i<Hi`eM79wmQY!Xdw8Exl(kpGC0VlgA0jdUXliel0?iq4{{zjL&E} zJ!7REVt=1S3Zv(|(|EL@Dq??~f}2lO^xt+CD4Y&|gUfgv!vB+D{faHDkXe5N7Br}e zCb1h45Nn6(eg1=mFOu;z+8V7^o<!O0RZ-0U+S@g$B2t2nVSXDkL=HQS8%xR|Z{|_V z>Rlc#rH668xD1qEdy%{2r|{apS8GSa?i0A^Rsr7=w&MLdLu`7p87H}Y6FTMT+AG_q zoVCKMz2_lOrb|1FI7UqHnH-&6(#{w0<?xI-xEq}-YB;i1MSLD!2sND};bFM3x0ZfA zeSn6S`}K$4(pxZm(;XML-oo0-O|^8B_Z>BybGJP{Zoh>|mQCOha|@TO2W#nvRqTHY z0eLkw`RIq5@cn%YPPhIRQQypj{i~xQxc&ph^hS#C9B@SWIAoj1zh@(Svlk0HXFIXf zZJx+Jx?70}878tf?b5KMY8~M)WW9(*E%DAFQP{QEuT*)wTP$wZ2`{eg5OK%6(bfHq zNc+ZdlTO_eZh4*YqWWf0+OaK89$O<`C3S~d-lj(S=)8Hg=%4pn)cBMjlJQ8W=_R)w zitDaVh1-!<_;~)H&>Ptr;>TfO9}RSIc_czN5WcdWTl*8DWkS4|xG_hxuv;ZOv*NV; zxoL4?{KX8BT=jwYn6pphpFAzTFWn*1n);(gVv#7KKxBm^3e)U?T03m}R>H>pYsJmT ziWvCD6jt55kvYQzPA&tm<>4+dvCT@6mRk{C54s?IlnF|Pga8~H&0x-4gw(4Ko9W~6 z=CUK^-<gO-_3NOA|6II%>5PcQb8(w7ZSyz{kHn3^8J4@{4TcNHB$yZ%%0HxV!p$k; zp!n55+-r`P6Xk%ft0p39pdHpMn2VQdE5jvd0UWMbqUe1j%1kuD8t?f?oWrq<l>Uf1 zRvi-ygW)=2o`_CqsEto_eLLl#Wuovb>ZTkIPZLfK5ty5_PUJm__>a9-f53QWvPi3B zhn#ZxBAoxt<ni&EupJSlT`%!>L636D;>d3oe3@1k@n#EA*}Ez{UN7cbSRJJPwFEvd z9bvnBAvUu;=_8hEcJ(k^gdHDhVCMik_*SyU#FPg3iR#eHc1EX>wc+019>WgU<Lkp3 zxOB-8?X&;DW#No$yZ@k9Np&c@t#Bl@2^wFvf$6;_IJVXb*_E5)(ghoo)^Co82iC}o z5vXoZ0}1x65ntC9?Tg!?WrN!A=i5a>6$6BK8iA-JeJr*PgLlX~kyT+1JVupArdcHF zoz>?v(YeU}SqH&aJ7Gs}dn|s?2FBl=u(Pl;%Dr=j?WC?K)pJ2<H7|61Tc6L)I>Ea0 zLg6y=PaNynQ-mf(!tzTOQ9NTjPG-*&W$RAE-YJ_!!hoqLt++{?-p!GZ>Rl3<um1uD zyc0))=Aml~eZ+QLfW?hX;Bsssww$-e@UR7V6j~2ck1o*qFXQzBU4P5|mDi=dI)BuD zR#DYg=a)LK<UEq|QO-L#pXB_M^GeRswDhCGbIlLYcjR&L?13rvXIR49w-Z*psD;?e z!LUxMiKxJSSX%#-$lFni|6O`qyh?F}X<{veFRz94f;w<nQwJGg&SFBBnOJsvsKDb{ zSUe<BINHvH+X81{v1}SPKU^qYT%3&xb7l*_{c{l4ccEAk7lTpTmx)&sW3YMaU!uu| zIP9o9NlZ>zh2pxi#Cw|rT=~5~_@9Y`<IynD&1p4`4IM2^53YvK*xuse(6z9*Gf?=K zOUAL(w!$Jj1%K2PV*9jp@O#@pEF7Hzr^U`9_Qg6x58W%ed`-ac(<g*+gG7uwcv>8) z60fCCtPqdf`*+0Wa!FX^b5|7l#-n1eKF%4eK~BCUUe#TTXEEkjyd{z6tUk=!C17*e zfzZ3VRM~coWA?S}tyJ3L1J7b3C1?X<nJ8uP=ZVnU*+xmLGabpx7Av`(W<jrRXQh)q z|9@@r@7A`vW<YQ6QKe(Gzqp(uO6395Q0(<u@$sAuyWAhjNq*ky{aIgGQEwFV+84Br z=Kt2&Ib2gZj~<6)t0Kj5>^OMpol|x-;`fWcGL<<+90Tp~W~JnM7^0VLRT{A`sprtW z%JLJw@NAl{^j#Z-<gr;w?(SYlcG#kPzStjj;U&tOE`#7%bWz!4*b&Kz*A@38y-;ji zRvb9i26_ueDOZ~fLR6-;Xvi_V?6Mvy26x6F_)ujL#rLA%@E6MB=y}MF_@qo{)O(Vx zocv(}>pv4QD%BB3nkL|bHLv&W%h1@V7EaV$j+*BBNWQZScQ#bSxx348TCs-9wdGLr zM~{wFmd*%Aa^WeZr1gFAVs0$D1zi*kf@8ID%JGav`LESs?7SAKJL=+U<{Fspb3&J$ z%P{nbGtLDiAm^zw+?%aI(L-mL$1dY}>L^mL^}sY+dl7rBEzHVTim1=+@Oft$k$<}* zjCy}kjElP9TA%ky^o*W}nOdq8ne>I*_3~oz$$oGgSWQfXAJY3fi=x|p91l>4xa$Mp zd8(@@`Ra?a5k6wghu+wIwVx<$*8_pw`Utlzow0IECz1K61J3I;7qP?J;l|+d!ut_) z^~?7B-d$G|R}@$^_?cpF_CM{K(e0A*?6;S$eWl*#6wjQVx^~VjE>sr#`s&*IXV4GD z^!7kqyAz$QM7PKwUHePMxQaDnf^~MZJme+1W$|<HAA54w1`4~iemc7@G>s5$$$fS9 zeQgjWyz;v1?EG~+Tm;wbq_cM-+y8Y@8=c)1`;f3PgU){Ezsrea{?Ewf#<vx#@on%T zrLJ&FYK1G!?S-=61FK7ZD>+qK;$>luQhXT*4$M+YJiTzs=%AANt0zh<Hz=ibI-zyi zO6B8uZ@g`rr#u?g4<AmJDDG<m;JqPPv2`1WAqAI}{zijQE2)ww${hrU{6@m~aR|<D zHWMy$hTzV?Cc-l#4Brd83%%FD=v@#df}8up<hhTCrBIBlJyvvE8;H)MCkVGN9~fSm zEc&nRj@Rk4M9wN-H1(V#Tt;`tiXme}?5_^6HwqH5I|*C=j26nI_9z!QTy*=YV1Zpb z(SC1hyg1NV*#FT27F8`#JZ`D-#@Z5|9zxmHssi+Cc`6>aj8WV^NeShcuGveziHT)h z@YUcy`0Sk_l8c*Q6O3@Ybv0zpDi94Bqff07rVlKj_j!%DmT8I9hzH_{c`vLPS_XUE z`oO=FHQMzE#k2ZWFt8tralvJ9>QxJP^_U}!5*0*8yNRP_brI`bPxPK#7ZwNSh@J~y z3cVi_lt1S_7s00Am1AeRAm>pPWF>Y%?lgTArau!=N4JQAX>UdB;YZ@6cTKp>9H-0g z!LmiqdSXNOyCN-Uk8pnSMA*E&FTPnk62)HgmCZ4?gk4=dF{b4pls(Z9fdN5izp^3P zRPKxX=dSP%>y7NOjqq<fHr4En=wwB>|L6(3-D8B*llgY`^+t=@js8!0vYrZkLNM;R z3x?W8AT7pHr`O}tdMux{9K#nRAb0D3aCeoJFe=!934H(e<@7OYqY=PZICvgH*R99* z7W44JJQ?TS%|!9w&3LnQ6&#;$hKI`vTwT2xzTNm9*ncx-otlN7e=bBT$HTZkDF%_V z4kGo=Vzkd>pX06zaOg?~vL7u%<R<2;O^ty)cHsBig>W@Vg}LW^zP>|O{<LeG@%8yC z91Pup?BEsur@sB&w_tYfc}TCd1yk4YGv=TAD_)F+TS+FYcE_Uq;S5|X7mG2g_Mq;A zSe%}`3k~_1n!ENO&)=2s8+rf@o5Ug2iDUmPh(r6^yV3F0didM^r(aIHFUO>i&G@x_ zIU226kBOV-!P99otUt`t`sde{c?jly$|+ckjyu+)WAS3GU)6lF9GO4HnZHSWV{q@( zBJ}99PuCC9?v)+q!*npW<DY(#{U+^{{ru_0W+Vj0VDX|Y$QU1^>lfKi((Whgmm<E; z-#YuHorzmk;A^LJo&B;rIi8&?GdOm#o(QbAM?*vAD3%n}71jA4=J{v+L@lG8@Qj%w z3RdnzRJo-h!Tz8oKVE+X*|~n=`LM&tzFk+;J-;3;u4joyqf%f~n8nZ06#k!kvS^jZ z{WvXIRI9>1Uw5*^M#lcLlSROxt#G@WB|aV83hz0|VtLSZ?RvYw?b`M2Wp^Q*%gHd< zg<>ve=C(b^<nlwd?t$C%Wbw2+x2GUWM08_b<D_Kq>|Hu+&SYtr%GZk=*TU{XmWHZq z!@hcY>C;8L!#e0?br(71*PwW6KONd#T?4z`Q~r<Mf{;X{oo^_H#v~xRx~C3hep#N> z+v2=J(?89=3sI~uQRe@*US{|bSa5sR&E|M9+#ZQCpDa)6_3Il0Z?>cNp`}RX_DYob z{;hXt6vvl&5GOk5Ek|rbj1FZ!S)SCZ-YK5>4r_&q&(^Haq0Ikpz35tNV8P}8j!8m) zE??q*=U2;<dU70Oe@m44q@GNd{p@=w33^TeLgL)W)v)lJB>t@@`?-6i1VkP0A|%Ru zvOK9L`}zA+9xv9HDD(YWPxkYVtYt{%_DGcZWO-6g_H%LVWpLy6N|gEjttb1r%k$;1 zvsxe|%6zgssrTRg99t5jjhBit-@o-_KY!npsFg2KEl1{8$6e~l{+0bLQRb6+HpUsS zyR9ecRo<gvxntW9oM12F7o;+8c%WEmz;SZU%n^fP_94H;QW0Ro&kC0RT*iE|fPuo% z|FEX-+%E;$QCG#rl#Os3eN~uj+=$$Hr$o8_DTrmf_Ii_cz08|Un%uVK79@<iDhgX{ zf!EwqV*YIQ`5bvwJp5}bp8a)7L|jV6&7oH{beeritgX-S*alw}E61%vi{V$rp7HBo zG4ns^>h({@)@%90j<4tM|5IYA$p(aT`4>z#z=F#kwKoFE)5nX<4I|(-DnK|d9R|0S zAv(169gh5~WB-p{-w$DkJ=$GZ*9k+(5nmn3{IWc$SMg>ry!pP+Y1<%8U!u$}udl1` zk78~IDS=u$Buf2%>s_ffP-}mW@c~*pCCYrVJgIlTULgASnIncV*DEb`rVeGkf9tJ% zJQ&8)76=Xho~=WfUzR8JhHf0Dm7iBFTq|GV|H{whNj=&BvY#c&d{R%Q%l<9r7mg@{ zAwuGc&s<;881ZjC*}wX!LlFISppYo@$?~M0>}Q|4At?UxKl(CV_G_2XL0bJ1rT)M5 zWWQd%8mP5TqRc1DlX|jWXT%31+H{7HDD(YW@4x#s`T0z3d{mVAWO-6g_G`ZTP_2B4 z>UEjln8#V_$^Ml6D^cc?dcO_M!R?BkNFR6}df2NB@Hq{;bElPWKXMSf%0wvJa}isv zzSzWZIJ2pi_)`87lB>T`UXDKj&$IKDO{epaU8kjTWA8Dfy|osd=?v@!_7Ntrmswwk zYJIQ5GyIye@%9?LDEkw`ve{R3V=4aTxMq5RFYs49ryIV8*SI9y{bfkiudRolg)z;W z5C;x+%Ky(zKqjBRbhKWI5I%P~uqg)f{_C7Yo~ImP-@-UPXOTGej|3=u{vyv=q%5xo z)n5l=K5yv&jt#-*EKB}ejfH%!Qg_QLxbr#7eZ4g}!RIc$a#ms-pR??bTh8x6C$aSN zV!YyWmY8cxFow@vqU){0RGY_W=D8V1{GMxQdZSds;uK@D9JU%4_*`Y`fED=6=PFMJ z<q3a2SNZhzxG3dwlu^BRh`W5Q^6FW-P|sP$zBw(N_*_N5OrrS6=PLQ_lf*|pPdRD6 zOg!WBlg*bhgcF~awD-st=lJ~OO0Qc&Jx^INxUY6z(Ryq@?cC&ZuP;J9zv#TCoR<D) zfe}p8FF{TB;&YQLD=f71$It6)xUs)0?D(8y(0nW0<#Q9|dVRR@dB}hT^%277BiEO9 z(DcHmbV3(CABlbDf*d{<8TYw9{P<j?-u4D4jys9U&zmAT{5U?PHO9`MV<<DTK0==z z$I#WS5yE~~A${7S$=`c%z)K*kbT9VbXpYn0597?NR@nD?Grqj@Kr)|$v=4E?Y4x1r zpLR%D%xefoKHre-lGmji-6L5$cTh2RSRp3HtVWAbg}6FvwU&Oweu9S6X(9^vTw~$2 zk=i*&+ldic`rViX8ZI|q2pc}vII=YwWp~`diPkf;^w*8!G(1*24%U3GVOICL68+gs zOndWNiM?wh$i_@$`yNqT3wJ5We>_mewreTU8rX@!q3yMEjarlKM0WH2%J6TMMKSaE zXS+t@DxYKQel--c`P|}Qvtjtk=NOUiqmj?&8jlamhAr<0d}pqrO{ccFT4<-8TYQ*Y zLp#U#f7pA^u&S12Z4@J@fT)0osEB}MQ4k4p)(e7wBoPr6Ng_Fk62y#IF`=S@B4AjU zGlpfvoKVqaj_5K+%vo>Eu~*N%ulrf|oO8eXo$vlQzuu>Nbg1g88gtC*?y7g3!=sq@ zExdn^r4zhQarXQO%FHDi^kgL8(RZOXlZ~Z)ibVw`@-p7H*pPKyrr4ht*XxvQ7w=c> zn3zabt`StX{&>2{`xV{iOeSsKr-%)0DeX^$-SwfFyg%U*=tl*-Kau$Tg{+YGCvG?N zrW)R#m>%WF|D~g;{GKh<=lzMV8@f^o??)6i=u9hlf1=N38)?5{_|Z<%zJn*nCeG)5 z2&?!mWL20$(?-jvhW8=Xjp|0_y#LV6(SxFR|Dj>HAD!TRho3(^$nb3%#rqK1%KOtq zEjiuf{fD?$?$Z9l=rUf<>wdD!OUBVO-gn4yn?#CzhlQ!l<dwYNka9VNQh1-C&DkMT z!21q9yPHe<450(;X(R757(cfqE8bVQ*0?KG^FBl76jw^;eTVx~ovAF<keoETkyVN@ z8F<Rb?~5fZj&dcH#hfqUNN1Y#tTp|yt`k)qZ%_Bih~o)zew&@$$*@lss`rJ+&!QWZ znz&Q(MF(2_T1HXkF4WY(jn<Em)67dQ^zDv2-8}0^pH2|f+1HmY@;*ZM_L20E_YaC4 zLg*&%CoJMzC~BH%G_-LDJ>`9bek<)r`>`7h_-;??*SskChYhK{>PdaHZ79Xsi~i_4 zozioM)BBIpDc5KWIZU6&@4+lG`7xI&i_*w<`UKuD8BMd~>2#U*3;N!lK#Ki?iAzH0 z2=5oDm`2ib-anYT!jJcQ^5||8JDR}z2AhZ3QXcOch;{q5UaaG<@)mj^<Sq0=$UAq} zMwvJ72b5hdm3`y=fTManNTr__J?rXB7kM8b{(&QX<9&f|5AtQzydMyzQ6^JaVMC+u zb)&+vw)6+<Q_NZ;I&!62mfm1IJ)U<<HmQ07$0!&ttGjU$?F#Ud74(}$x5rGBEgw3I zZX8=It64ai8h0v{O~@%Aohy@N50@8ExLUdF?2AS8Lbg{nI&%?4>r}~trY)h}!|%#! zKP{%EXWq+>TrVX$Utg~0zLZ*ow2)i%T26Z!=*zQ{N@$DjINJKMP{QXb3+a7oCgrFv zB(sEU+H6=vgUS*pG+-eOzL7vl-;3x=Y6x}twuI`bhtMQGhaQQZ95=9t;(mD0%63a> z+}LGQc4LlA-*zSC{um-VY0cl;H&taH78Fx1f@EVS&!gN;ZZci|KdCbAr;GmYGpUmO z{Zn4eA=h~`Wt$((pvpUYWeFBs-nvhAsxpsiPJWgB7R>)|+3z1aXOZOZ|1*V={rw|P z6i^iV`R_4ScDN*4!2X)bpC@H*PZmi2{(H@fB!7SLf+do_zuC2=lE1&AbOqIPs*ug- zQY!iTGtJA%)u>#yg5xZ!#MR374=j=V{fob^Bf~|PW#0@pQtpHyvbRR%l&@M}KJNsN zx9`3zB(8*Nck0Ry&09dVzqgRrPF*DV`}ND5D5&*3`m))MrmUGu=Ej}rSeHUt#6H`~ zj3P?y=uLI6&!bj*Lg>@wxnwxgjUvv^qtJtkCBMF-Wjy7L&8NDH(@C#iz9b)6w|ufN zwx{5o#kA^*jJ|YSN@sLB(fW0BY2YZ1V|p=w3N;tg-uLb_>hvPYx!9fhUgO^p_TSI{ zTuc==e5eQif3ao%ebJO+3S<BMgceJv>QF!W!>EW7<e{YhC*Lu<9!l+36_CoM0kn$u z90EUv(1kL#!`DG{wa;AA>mI;IGUk%&%AS<XzP3;IdeGIh1yn!LoeGSW(CR;le6KB{ zo0@VZ9fB@F&y^EPX|uXJ{TxtA3jh7D^vzgPN(w)IQdtRwvH$*8dgX<zPuB<1#uG)9 zlN$MN^jD5sNWnv+=#s;Hnz=XP-}sq0lKp;5Lh0`D*>rVj@W1h=*^}!}`ctCA95QUp z`<lP-+dFtJRZn-LgE0j(x(O-yzf{O^gxP=pdPxaA&UB-@*B6m-ku$jk7E>_$?c+`? zV*iT+W!5Pph5!CTLK(ed|Gf#vnmWS%`-Af3<k!KA7QJ0gnN@*gnO8~*|NT?9rF5b= zoH}|ervmohU$JF>8T;=K=r5*E#|P2pJ_~96pV4Gpw3wnM#ZpY&g>=6nj#kW@M~=^; z=uQUn(KU<?@?OtMc?`9GI*ZmXjv%|-S(H1tFHL<nlXeyQQ`==T=y5>^1^&n**ED~s zS9dn4eCt7N((=i1E$ET$Op3|&pyWDpsPesx9G<biYLg2^>dmKwc8>HhxHUy}Uo1<1 z+lo|Lxyq(QnouD7>)p*vD4qTDANF&O752kh6||T9@{O_|$&JmlY53Lpbiao#o&DU9 zGUMt|#mT#J+lYF!rz7VAV!!+Nc`d27cSpIC<~Mm%o~?Yt_BxakG+DkUxfA6!{35GJ zv?15pY?;*%4ca@p4q5OymPvo=(8S;Q_i*=p`R3L{j(f}HV!Xfxpt2Wt<p+AX)3oqS z@(j~1ROUWSmYL9vat&4Foy%UxT`R3gdqo54Kdck^e5l9YgEr*f|Ft}SzO|B0L3e3` z^Kz|iGI_NBCGIy&F4~L!S1VNMahp!c{^I%BYggo2Gn<n^>NEMSM^+@}74uAOGnY!( z|9;bT4vl7i`>}d+={Eb-`()0gx=vGRpZN?v>oK2NY??t0S1)2-XV6Oat6$5W!Eu4v z&t5v70@%N<e|iF4WPiHX(6N$#{jB2{$>092b1sctxq*&co=DHxpMH7HcnW6!`s}V_ zB!9aYSIlF|-yFBu=EulqQ1hpYl=FyrU%t(weD<$DJCa8w>~9}lolQ3ESC7okCPVhK z+b3qzTK20iX`e%W>}S_5Nu!zUUw3JnMn>#kFV`PJ&#!N!6(@#JH2c|Sn$D#-_OFL+ zo<Rod=27a?8Dz!&^iiYc(iHZuXU5N^Aoin+cIN#1af1EkqJ3##E=92ayngjW>cakV z!KdK+*L4wex1X9v7ua8ZpyLeM!Txixp1-bx+KU{@Wxu)LQ}89|UvMX#cCr6l@F&I- z<GA_!DgBSt{q&G>`Ty(0*LNw3|IcRkeoQs|Keq9T`_li|^x`{I#{XkmxZmdZQqN^e zt~}-T(_|~A)JXqh3zxj0&98OkFEk$VnV3HEmwRtW|6|{Ly2|_4mt@li@|pAZ+W7v5 z4aQpNNO(J37bD8;VG^b*m1ENM(Q`ZBpN`X)%7GaM7{AaS9;pWS+0_|~`E2!)U}t1I z=p!q^83m1XvBl6Gq1W``ALEXVU3H;*zzN^JX=Ct5XVi_+Lgq6k)NiVV3_o}HTxo{s zyZOBDI0M|tv&ZZrW3+nbgn3hprTJ30tf0@Xr72$Qx5r&wQ_cl#5AT;v(eNVIpZy0u zb>SES{q0dIQ$vRmd#u{sP<kHldqZq_!sE?UgZeUOv<*~6qfOnRsooUbQ<&~HrkHnD z8%LenVG<+#Y=_NFT0+LSmhlwVJ2vJu;@p}ecW9%gUTYYcXhU;&YiJ+Q#$+{pj)Ti_ zwqjagN^wg}FmHmb8ZF_V-2|6gaQ|&B(5R>-#~EpXpek+1xPII*Z7kZ}0?iGyv5;d| zjOY6+1>CP>pEiz#HiExFOB`an<ED-G+^?H%OJwsr7R~g~IJOm@@8fy6pW*hF&}BMK zc4&!vOxLG#oZG~m>GU&~<T|a6xg^IeZ_H55@*CC6T$0<zp&cZ-MfT|+$*l+-FpuSS z++81~EHB@w`Uqh8y?opOpIB}cn~m^euog=8c7O`YZRJ3HbZ5Dxy<nPHZa21Zf0kFv zHs+H2nm#eZLzYufEZ-kyIlX9PF3H2Mm$@XLLHoHq%cG%c2T2~yKkM^7=BC*0(gDL+ z9=iLraFN&jb*?5ZGrnZ>W_jpyy&q%3gl5oWKF7s3Lp$c*__7ving6^KT3E>I)a!6F zd}Vp)*J@xMuWSBW&XddQcp`_#V|mn$)kJregYhvfl(QUyDz)It<^1$!DCc!mJ*S1s zy#5xwnqfKj4@%eMyj_iO#-|zTujRW(qcot+a!AkC#5A67+gT0dala{7G+@m1tk|o8 z=1kwE1ddV6bj=CRp@&hA$!bPA860>)#YWkr|Hn&mZa<pOxjv<PMnmWr#~>Q3nMF76 zy(QV?O!}1kg>Kl4Aj7;*)Y@$vrT6_oBPw!f{q(P7>oSFAHu}kVJSX${u5aY+Ka<+_ z|3>|i^EfWq7xHq*C;cxUXim~BGJE)*^q%I^%Seu8_HGtUxm-(@PO~Y!*Hb$CC%->C zJtzNL)2RR8ht%@;RPyZfgnuU|koTqsw07qNvj6QdX`UNRHw|h@)^0Re^?ggTdQ7Ar zHqYr~uUx7f`$EZw;A`U6;S|C#Hv8L*p|fGnlze^Io=xiyzE$$&Kbp_;)cd65Yf_!@ zbnM_4C11~$Pv$+{uS&j(?oX%ku+K`qMlPR8b&K9B`I=!ki?Tn~D*0MQGpJzOb0uF+ zIa8_X^Ajasv#w5{gb{px_%AvI-GWX*pYMUOr0)BH1bt(^^Y5YECld4>?mC&mW_%(+ z-)zfi<m2*@1bu(BV7V-PM}oesEGNy_*X*tP2YuUHPbb$QFG<k%$CxQ}bINlP^r@X0 zPla1PkYDLkx>@m(Hf)(fYgJ!T`kh<~tN(!(ULQ}(gE{sz<&vS<2l^tLMmF<a(!R1O zR1o_@Sufg&@qX<u`iXf&J5evj6Z4C9qF&4|#ue?Z&$Xbi50A<0EXT_8eMV=htY~z? zE0V`_p?SeC>2(dCX~=m;xmBE__SHL@U1?5b?LL!rk`3k5`AWm5v?rT(e7=2S2YUGQ z2fd1GNv><YQR5N1RJZge9n{mL>cTJdM{r{*eDRHZ_0_0k)CcyH)urM&AL&U$Rce^> zn!2>ELxJyW>1f9$H1EiBYB8oE)!ctdT?e(GV@ICQS^H*mgnx52bK6k4^ApldZA+CN z4{4yGDS2<LrQ4hnF--d<^@=f|DDH1sZA#0ZzE$$o?4Suba}2N=nI#?C{z}PbhLaT; z^n0h|(;&l)G>bkd`HXsQNV0za<a5TFmNezkS0$h3rcFur&1WT_X=@u%j?D)ppZ*)w z=<3YZN<IyTsq>l37fL>Bf3zUSIsfFd7qy|=nopH{3VH?og5I{a#x$ko0||QL-?int z>7Pi@dvBs1T`>Gif?m(U=5(z3BMEvBAJ?S&UEY(R_eV=j%KP$~1idP|v}i~DR~)nQ zAM_r1tHa-QFG$cU=<MCM9s3JE(lp!lR8{nW>dw?5!=*3j!sZqf=JSg74l|;%eIH2f z+>VT&exxB;&1q%FSM+Fu4rzaVp?og-i}6HzfudfFE5;Eh>c#wGe1W1~%p>S(JoO3X zzv_dXgP&0Lh9G=iaf2+@2jSMM8)Vfa7!N&}x07C|?(>nlZ45#$jt@ESXb^rTtDw$N zFANQCfXRyI0~$cDT_3FEKPsDBc%pQm3N#phZC6?UBf-b>-^P9Q{R5r03PxRD6)emS zR?ZV>-vIqD2P?-HbhdSWLi>+-K_le}?VRWdQP$jYgO=R!Qu5Jh@=Y>o<_S^X%y$VH zZ4E;AK>puf=7oM87g5-GPZV)%13UjdILK#KRk_@QeONgGeXw-gG`d&nh4Yi9(bw%k z%J!naheI)Ky59q9#w?<l4n0t(^DHv7@1Y!L+Q+GUj=P6)95JpK?_%p|yzdc=VKV+^ ze;bT**^4Otb+D42@mj^yC?yzz?p-$JRHr-$jd&l}y21;^ndPMB5sY8!ttXdLijF7D zw(g`Eg+b7%+DQ&)yf~ciP8v2o_}}WEbH1(fTY6yco+>`;6NGKNXOdp!h2ul2Xin$g zf2-fNzKXuNc%oHGiTnra1#T~uw|d<NtGqADSE}<}=Mk6WCs?1-n)=8Zp7KKHh2F9e ztREIDRpidcf^c7}j(ipC&m@_@++|Y`^4I#yr*pf+dcHCbZBJ!C(Qa$Yy7G0bPomxZ zy}jhlzMiP}w3qx3>tN+LV*FMu>&ab)2P@}o@~XFN6YG(ncU*0W-06fD1kUs?k(*BT zM1bcd`NX?kO8P~4{-^Wue4an=N(No}-3t?*XHf8pAe{XiLeIH;p;15Du__3a_xe)1 z4xY+-(f*KU2H7|ERQCH4n?Wo31S|Vp{MeT|%7d|U51$Jx4Z?sKU1$xjhbSLiVn=q- z!C3Lojt*Yzp?q#{tVZL{dErZe8ac7u3Y^`c5uIbXrLR}xvyGk*?TThBCbjD!P~;a< z<T2V8>V_&uXL|o!#`&q8NrzEI)rLB5b%kLg8}fN3gJF~rg+Jx|x94@}!B<z5ebuM< z$$-`_W1<xv*qmWWXLk00A^VY5ECy-{`cTO?H`IS0#<53b$o&#UI<I7KJsnI}kGaBi z2Ky3U%1|8dMeiSZaDH4rin)`H#Y5fD>^IJ{eG*8gOg!u24#OwuC`s_ZMaOKs{X>SC zH?q;x+!fPPGI4gL3wr5g;$;!XI?KsM!vRj%)nEi_x46J>=?MJ(Nd})zBanK+3B&4+ zMsOQvv>4}zKo4j3zdK=43me*X%@M&3ThpB0&X{z-m|~6WVSiLcv+cX0YO*Eub$3SY zl0J0xUN?Bx38w)%PRyS--FnA&T+jMZr<ti3<?Rl;rm1lF6L`Eg36EV|Q86?bdGBSI z)FYL1&AH%&EE&2fPI$oizw@^^BIRv7n*ZRto}90G_+A%`oyK`htDTUtBNoF<oRJ?J zfb=AL>J<=xFnvFo`o;@6BN(^);OZ79I@g$W&Dfb1t`0`6t3UDW0p#a}kzp$@q?m=% z)#$#MsTM&~CThaUJ{z$UH4ru^8^wH|@!{P})GX3KrE?}aWH&+cR~axk$MMj=48xM@ zMrd^^1ARD-->Z|upx#>zBS&YV?HZ03xIF{99QV-XY8HkiH$<D<ENpRBMah`qSnS*o zXVwmf$qSCt_dSPW7O0}*$`P30)d;`68i55ISEA|tk+}Q3F~YP*qP0H%*VG;b;}mtI z3>tx?78)ou8;SA=4V-P5gQk5nu_ZD`Nq6;ob@U&Zjj_>uf0DA4eAMgF1Ou}F$;Ww) zhyJ8rrjn2M8#tc)vrHu)>mRD3U88IzADvF9A~R;Vl8@dT7bB%CN6E)7j@K8G@J~K& z{m~dDQ${HH*xXbd4sUamd`!8bj<QR`m3+L6;CP^~vf*IS5bx@8Zg7r&SllQH-EOJk z?B*l{S*XInHU)p&R>RVh2{_TM5gKxi@6yIiaIY`{{cbgeW>F%p*Vn*_Nr`wErjAVC zBuwqDiMG9xanWA`R;!ZHJ%ewTjYx%M2LGS*OU0$B8t9lY1j{Np9>;0U;eDV9K5{O2 z<G3c6vVRD2=Ql#=pXoSS*$B>m4uSn*UWboEFxpLxL*)&@yikq@Vv~k?y;QOKQmT?p zL3bd>>G#w~#xst0Y2PzNNq0>`BY5{nQqtY_NMl?#O;XbR;b#-*a?W-^x65&L=v_@# z(!J?{I+E>Dm2{5|VtEfqQ_}t2z6oUAhA8PibFC4^^!+E@DkYrf_0T`*w!W;2(JNDN zJD@R~Ik$ajr%s5d*9X~_op9)TAlyv5a31m?Oz^kG?l-}>#c|=}r+Z<=7tUq3%m>do z-ctPmJ@GNc2Kk@-AzNaF{;vYDa)&vlO!Gw^`z;=>>;c&~3lwlp@5#fXpu)MdH(v?I zo;o3D-e&+l{SgSq>*3fw(w}ofbwtM=p4i#HKkUEx;8XHITz%(_NSCho5gd%vq^_tL zFc90Cc1FRvQ0&b$!R0z`NNw5?y&YVU;oA>|kGybXLmwRJ>y1;3f)VHLfli72G2Pn( zqXL3)>46&tZ4be!Ic_+?aXCun@!j@az1haPL(jMu%=z8?rb{ohAL@bdMSZcsz!w`H z_Qizg0F+KL;rD<GOz(8S$YnA-adJaq@*tSly5Z!8!N3EO(C{2d^|$TZrLqDQ?Is(! zA>r#_D9Q@7DC~#`e-~uim_ut7@aeb_%57btp=AU$j%#ql+EMC%x1NI%731V`y#lK| zEpdB~GXiARNNerHF>Gw`WVH(hOt(gUJP_KmAEv*Q!;$&Uze70x%vtL9`l7Qmp6<Bb z2-O7k91XyLTE0#-%oge9fp~PUGaUByLg@2Okp1w3M#IjSJJb*DJ9I(iHa}#CcEyN6 z0l3wvD{gNJ#Kn1z&|K{Y*N09>HTTB$U?(K>@x!bN8^kAi!(p5)_S<p2mNm>yxZ_b7 z-|5eF$IY<8c-W~g^zRP>T^fMIWlq?i6^iVhPFR0@Am+O|L$^E}h8&;rz?5(d?A00T zHN&89X@iVF)}d-^G(Is9#jF=$qr&lfGh6g|6@lKTY+x}s6jt@3Fx@E>kIsg}!8H;C zbNZwHkVqW3+8-8m!*Dr10wy`($Uoa3mF|79sVEGIC;H>zK8{1PwLhBchrp9_Uw`@* zjD?>$*IQUmIBW?--#H#g5AF-yw%uWo(i;(KJz%Qq54{uJF*Di|!zx@6o9T-IEQ87O zd|+wLaTIp<z`{j7_}0J|?Tfr{^Ncs=MDT$}v<IS8{P3QC!^-NrV|1P?CN$`Q&wbsn zCxXA-Ps#8j%>!fYW$5eUjfw$sB<|<`6wa<#`$P`6hk;1ryZeP@y`b;s%z5&H@v^52 zf<6bq<+=;}ulb|<L^<C1_Qa4SJ)u$=j7P(J;Qo((Soqivx+4N$RpbZL)ILaB<cB3I z`(uz+PYnEXAR3QyM+vWU*Kk+NS08|S=H1b5;Q)*a0m6m^qia`3MDzRMot_ICJPE}9 zct>pB!?9Gxu)p|`AMCC=VFv4yZ=noV?E(D^LfcH>%1;@b&$=Tc(FG;3?uaXPLFY(s z)N2Wplz5>1K36#21KQ>h&JJ_NrFO39qUC~VLEVus*9CKbIHNz?%@B?&dg7=f9+moG z$}%@h3h~8<hjJVr#PQ@(24Ro~$Dd@}<<<ojY@ZK`J4x8nz6*5O{#tMCB;mD9JrUp> zi8hWNIBFD$4s)GxLN^kF{v^px!?wwgw=EW$B{HczCtoJnPoxvaBjs@v_NhRxoz4=* zrN|^ZYqZN6p<82-*}J1OPfj0m3GYp`SE7P0MOi_oqMf2Vs;9Yxin5~KpUfpph_;mK z2XgEK1^uq8tR>u<WGOxGxy4#~ZcuJ5l?~SQ#!xG7XfE%CwaMNbi^m_~U47xbFB=BC zJg_5j1k#J$(ZqKI()iSzcTgsFB=tmBml3$o&mS8rGcaeLKWaaWLd-S~wCy$)Hr_q) zZN*rmE%JwB-4XcoTOT+s8jHnY!RX;U7TG^T(e-)`7Td7><YYk0G8k>!W}vV-6w9(K z(Q^dQ;tzAg)p5ZWlSst%9*AXbV-XS+fgeZt+d?&z=^KXdNf8|LxH}AwheFoM9cmnV zXj&Ste?&M`Zpg58F8?-Mb-`h~P%QoIhx!I#aQPzwHgm(!o#W>e&5gvEkE#6a5Q)bZ zQsH(i8WS@U5q5JhUfzqrgH}<fb&JJQ-N9HGl!*PF1Ccp^zYRDxQhG`(R(OXac$5xS zJmPQ6cpU^z@J8k2Rv5d*8z*<RLei!H4E$XkCB*?~d_WyL)_CKxRWs<F^F}v=X2?7d zfKJt;@%&W|@|WaDIGyp$vn-f#y#l|rZ3~U002F*{gVGV+_)^{;rQN)7tc4Nu4Fb?c zTMchc48qfw8hBGQ2z}dXK)+WU&UmU~?{(&3QCry8jYD@IeeB~HQVTz|f~QS1<}7Z5 zQ+)>^_>&seHuu17bqyRp=z(t9jqo7H8)wdshIx-<9AJ8OIwj)}qxQ2zSalnN!B-OD zev0|-8I4yvba1U{1j_aFF>Gl#Dy!P#L&!kPnqq{KCJ`9_!~j`0!(i##45^315wy4& zDtblZ?r)m7WfG2J*H&nL)dO||bl_gE2R8T0!UxVr`Z6w4xh_is#zL_!n|5+uRmQ@} z8F<3a7c!1!T+8*EH+67wMjSQ_Z3eHp@#uJ%<FG{qz<N`AoImdlo02xD;_r()s-vax zho?2e_ctDR!TsOyIu9M)2rZ5bL`(jTJTx}~Yj~b-^HOo1<<PA#m34D8wuTKsG1u>A ze301zZa#w$qLPUSUXP8jnK0t@s`b~wqpfbJQ?C`=X1Kw;s2S?6bVJ+vnmF9c4ZiA) zp|0h|xiEFmqHYqj+?(T$K@z;@wZfJkiEvrOafVFXP%+C8eivP_Lct%;H=fa&=~%#Y zY-WBtFe=tzd6Y5A`ozHOT_n6B;?Ybs3I)#-P<kZ{&W{st_*xjk!{gC<{Q$(@Pk==^ z<G^?fe-whpT=u*l0zdzF<i6wocERy@@yZz;A8<@5D@SbN=c&$)Q04X>DqXRZ$6NNp z9tU~6W7VC};6(x+|JfP8@w^Ip&Th?A>aEaYg}fB?Vx1LO&E>cYw&>K7^XKyWPr}F6 zsOcAv6JyP#a$vbR_5{U4i{tPro{w2?f-m;**zC@^XBp)aQgBQ+iFr?uP}d>><G6iE z+Zd^A_G&OL@_1r?p*LdP1ij;fBXN+&i7X43u$cLnke9ApXQ6lVm=8t0(6`CVM;4bG zcjNao)AwKk|6VW({)B#NvmF&CrzrJE=+!nJ&nzZIDc4{gFOS<D3GIgFJWlkct`drQ zgdPa}6Z9zc@-MpgcMQW}=4asOPzl96!j6Sq3%caG1Elq8v9X_oefy4q+SUZ6oeR5n zE6u@{oty{xFMYRp!tuqpor$?Kw3uGagN_mkK7>7JoYLUmrrsz`YL1m1g3+RZ7G|-| zojS_-2Tlc}aaYbSyP`j8pJ_tZJQQPe^kLLJ6x#v~;PYYt_Abvs=B#)Oc%FgnGvcwc zJOh(!V{w4%wHUvh?SVF(;$gPX6P-Bs?(}EgxH&Q!TVHzPH0x!-937Y}3c;?jW>~Pf zAFk!<U~G6F)G5<}R;y5$ST;jWQYhxXG334H{x~zW6`IWIhpgtUQU72FS}oN>L$zRB z<@w42qT%2)29=DV)5dV#&B3VV`umKlUE5)CPB5}G`CHf|9u3`m(Qq!)VbBKqegtCQ z2{$Z2JY0sm;>42#n17Vx3ftGYw{mm}h{x;ueGtOWch~fh?6k*Vjzh@y7TY`!s<!dy zu`dJ3Jdb13Ozh?P@A16aUBYmO5ziv=YH2o3Uk}5Z-$r5*+kETsqfx~%`Sv#&10#NZ zvSbWq@_HE!7$dFYN$&S_Z;Wys#k#5#W*}l$47AnclKw@Eagk8STgXAkMd*bXSLjbw zzYv^bJybixK3T?j8^$1k#}#yl`NjH)^%U(UkLiOyxL=x6kc8Jw$6&qTAm#cCc_{cF z)p3w=U26E_aTT{av6R0dSTA)3kc5ISv5umjSU<5&VxE&_9Osee511Pu;o;-H5-xn@ zEuj|sh852X1KcGP^VX4NvcH7$q5p;DM>27e<#4<HAj!TOy17a1ACA<6*7!H1HCGSE z7Js4IfvxZ(;0x&+w}PqT8<O>Ig)c+?q;50yaNX!n@(SkfiaS@y%efUcm)1~*mOk>Y z)R1OVeXQmBZ6-RHl6QsfuF}JiX;<hn<KE_%X*|~lwz$l97&+eNwHj(uppCd?HDo+e z8;*B5cMjL@WmI+6!56h_^kcpr)~a5keT-rI?vQ<j9(MTMrN{ida{nFrQ(p&B0e5L! zxDM8HJkBEMaQ=ip=?sromh~qES7;+j{)SZi_<6|}^2pW3%-}C{!lpf{#=M|+$?Y-w z&#!bj+yYbXex;5@7Pvj~1$mU)AlmOc)lIg=y~vlO8r&Kdu`j8eaU1AyoXdda?J=Zv zU6gR#?XUWE(YB-uJR3K_l}r-^4bs50#Mbc9s3Dsrtr7O}GJX4Mfp_iCQM3NGnDFBc zeVJ&;zTFxM-q0S+H$5lU`TU*I`wlhMw?OWO=d`N3B|`XlX&27T%=LXr+T-EJD`Z*K z4r({9(qt107<{@y?cSTix$^~@dCCwr{3rg<x%LRKy+Fo>wn(bEOpiYBcQ@zC`H$r5 z`j>p2{)_T`_?LXI|1Zk-&@b|R`ip!g{vVcao4@3HndR&E{~+HMe<NS_|0ekgdlmL8 z>{-~Yuw!Ar!d`{_3VRmzE9_O+udrufzrtRH{R(>)b}Q`oSNj!qEA04J`xSO8?D$vv z74|CZSJ<<#Utzbxj)mO{JO0&vg<T4}5%whP_>o;JOl!e8qz9OyDnSFneudo%JN`TS z6?QA^SlF+4KL|S(_AA~OzuNEL$yeB|u;c%#e1-iAd;YJ=_gDKB@)dUctNs3W%U9Ut z-^uq+mhS|XZx+k<*uThE*zNyr`EEO@k4zI4+PPI1SAW*0@HaZpd;dee^Sd6dHh3<d zy`UM4TQwvF8d`pne|l$&tJ{B<+dr_wuH(n#CB}>%Pvt%uws5?2PySZR5`}Ya$TdwZ zQN3-o{OAW$e0qLOUJ}cBM9Npm7yB3?$859Q;b{lxZM`nPa@7!8!|%(r+qT1}ot5&h zT{$kS-39sQmu>La{k7b3oCUN`Hz$h~#wd)}qVz6?a2?r{Os6`-u;{V;Y@!@jQ{Krd z>&u~TU7t+vJ7K1;3SG8vljv2Tg8pS$oKNV^Re8TF4)EUeL7tM~fS8-=H05U(=oM>H zo3T!C^iik27kGcNk;XszKhgXL-;518?r#0(>NIz9YZyS2wD)&{?Tlu0`S-4<9kxz> z>r*GFTq%`LpTqSR?d5yFcZKUfxjb|n`>Q`sl8?W~=w~1=JZB7*^AqJCs*RERSyO(A z&s?q^TqM7k)DD4lId4}Wf7j4r3ClLLlK1rQEtSs(vyb0xoxE`iKh#Vxl<F1F+bw4Q z>gb*Fp6A@LImA{Ta@Gqf#isH)ja)fL{XTi<IUqmBMXvhL1!Zd?&ztUoYV%$451J0V zU%En;@WBNt8<xn9hMI7`wI41~n=GI*%2DQW9jI)TEwi-sK(30v>}Po=<PIAq8{6Fv zDjj>s6m(Vol*ttID$wj@JC09YS2nn{H&j}?$qu|_|LZnQTI%NwtMs<ig?$bc<Fx7P zsUEm_w;p*8^MmnnJ-YMS7ZnwzbT+ORs%EvKx*@%gbEP9C`UT<Q23>Ob5`^b2CREw1 zFU(XlNv(beY=hg;$tGb?d-heHwm%GhKQyR|(*XD#(V-z}{h^&vk1P{=V$#PZWOL6G zg|q9@oN0cLS?Ev-$FUB~)TLIuw^9|VO*;+;!``|HMW+vhVa;2)ooRmr-%%lpC!VNj zd0XDn*b@oough;N@q$*?QTbsTZ{#~y$)`N`Ma|M3^0c$Q_;m1q{JYUm<Y=6gx7m{- zVZr-k<Qu5UgB}k-^_!;hn$}sUJYy)&zm*1+lIb!Bn=BaaIWP11Isz&|_2i$|jzI2E zOL_djvFvwlBw_m2F7gp~`f*<6_cGt-{gA$>qdbRw?238?D%uU;xYvq#UEai_GNx8m zsxlC+8xG6j`V55aWi9!u$Vfz`eU#aMkAUIXT-nzJF~~h+Da&aUgQyLUW!(&-r2ea- zV<fzKZ=i&6y8R_o%%d1zL6-u{-j0y4)yOOf?{ppt!(9*MbNv}JU&@`|r%L#xnvv^M z&nHRc;5m$3Zn7a>!dE&8QoU>aSP4BOm*Uk>_5{TW7XAO4x?=5ZzD^4)J^q<RSz z^@B!9&(}vVD%!i|Na$|P$j|K$@c$65AI<+i6lKHOB$!QjE7vzkhU=^E@~F533A=_T zNc9(Dhe}98hf4L+OwuI0rIIGq>ph8)%8k3kN@d?h(Nfv8PP9~3(5V<#fr@z)bP80| z-|00<dfvc$lvMv(Ge;`FZ_0iUZr}H8rc|DPiG4_1zOsV%^XL5`ug#2+P{>Khy|H<e zR4?SH`hw-o?S&i*HTp~Cf0d`=`M=6lQC@j(gw#&RSIGPH&@8E5$UCXcP^m2Ref8lK zsVwwf==WC7bg1O^lZAK7LQUwxf7ACih9i-C`nc?0^}VL#x=iT1&~F7Q>dk!mAu8^$ zQop-x31$DoJf&WDJ|2O}Asu9%CWHC?Q|%)3{8zmc`uMB<3B42g_N#sgeG+=qKraC` z7UN|HT$52_mM`n?9mjr!&UD*59_y!crY&(CfBu;(RYk`^w#|*6U5-Ia3uCGrABS(& zCN%7B49e8IP_tVxDD37z>-t6`=QmFZ3my!=DP5>%#b88D=|J(PBXPB!7ddN0!`8u$ z8qMs-F}tlP|IZMZjj*QX+d>e`ce<O-?}wOg7F20E7HY3M)6>yopkBdu=6a8T2geTc zDj0*n7q)czeF8kH+^EjQ1Oy-JOtX!Wk)Gd$<|ZZMNDmK=Wt0pvRa2@wnt+N76EaCl zMdp_-)V4A2{Wt1CT^pprai1xD|2hQ0c6Ky>QaZF#-D&;gAt>OOr{lW}L%y~h4O%%2 z1u3r7w)HTmoHC)FC$lhZstKiOXW@AZOIlNqf%|-xapyzU_h)vrZF)HFpXf~ImW1;@ zz9qFujl{}CGjec=g5e`;`VbO|_3zAS_t;RBH8Z7SZsAxz)074^3x&!>TiWc*dmnsn z>HLo{?E0-6IX)bK{Ox?!);|ok1H18g>*1JIZcX)`jzG<gPV|`d@BTYG8rgj~`rCG< zqFY>kXhxp#Be8y@73p_p|N1g>k{!yy-f1QjWi$d6Z8)#<fl-{N%#<>RXToYI$D!Mq z$@wZ=DM>vO73J=<sWa1)7)Rgdgd*21mfV{UL``xWT{Iqu3jYMM?;ZiG>U7Fk6oF}v z)2K&KB#b8vq29xJ?`7vu%2*bSn5QXpuk~Q$Z%m@x!odjCNu~um2jj$uRH7mAhzg9O zezW3W|0tGJcrU}iB!-q*#<Q<7hNe&B{0A0Zlsi8T@4~#P|H>q2pYf)khKZ<_dC{2( zsqpjiA-9*wxH_#T9WqPjvm`xf+?F&<^Y)?rKZhY|M-RF(eJJNp@}k3g!mvKTn{>^1 zFKKxXdbTqh1|dDDd>rrn==#vk`w^(l_M<AjDC92mr}EW<P{Vhi>m7*3%1QooIU)ur z?|doRCK(=M{mIHM8O3}2sbhyU_+8@mhH0=34Im8*e&2TRqb~e=5}4;lzq@B(^}9ea zOdST>Lw)IuPbMzL_o4`!FnpTbmo5(;2*;j%$R;5ij!*khaM}<g><gjC6VlihK9Dw) zv5(p?gknxbBE5SUO}icet)fth&5MNgsa`a?`5+W73a8ygeCEWVFQvyPLuJwcx-%&i zDK~=YS*vJVJjihb+wr;&2&HBE(eNHSfLfZzpt3ZSete0CL1HkCW}j>SgTeH<b0TE< zy*XZD64bYHT;n;hu=4kz5AkgOj(tgQb}VG`L#VrYECK_2QD5FKe5~4+bWia)HT6E^ z`H1x-I+_CShT@x76uEC0g4JIK(zCPas6RK9EU!f%GdGb=az2yllmv=v5QX%TBw9Kn zh0og!q^^7(?D>>Xs;WB}>my@nW&3EP+s4wz_k&TT8AtUq<DqU8MPH7@A@fEg%~4O} zeSr{KWRrw%4f|0_!#LP}illxnSy&$vNoIXBp|&)Nwr|PA&H7=~O*b2>SA|nSSr+^n zhtm3rA)H?{k={k8!?s}@jp8#wNBolrl|vDum&kbohvNC<7*cDNf|VL^bdb-?<ZO<n zsSi?cGcS&|^FCwlsaQHtl?pwhXxi33f%EJ}Q4H^;6zGRj@T~;gr$My;P9ic>22t#* zL_GEnr@Xsah%y*VaWz?}Y8gxA5!pD>AexG8LQ$w4Nrvr)qNYh2eXh$mES+55427Co zD*5+HMUGxF?K0%|*^*Q$dz;GNQ%QWUFcB3eVyI$s0-tw^C!Yn0@T-cUDn47JZrF;( zSM&EmbUWI`=j(C@wWFH72~cy_Cnx_n?Ba6zH@3r+R`jZV4BoA7LoL`|M^Dh9xkF;{ z?m$c0>=KKpNo^=~VKhd6(C3S<gOIYa1zGdHZGuHB`ffcGGt=6T-?((7_tBw7Cc}`v zuQ|!5ra?=M?|?QM0`-t~v}t<^f~U75yQzHk%U_Rb-;PAES!Zf@gx^PQ7Bp%H|31Dp zBRkuEFl^qDZn}@+_SUp}_ZU=rccN}I7WQ3j=;`HbTs0g_hkFmh&5$AF)tl$x_su#! zE2b3`Ps{4XVtsxu8i8o+)#*)l$MN^0ejwQo<M)>K0E(KO1r^rcf=iqqre8QsJv9{C zo%>T(!&pqp2&H*>{JpfUA8j{fJ4XoVr!hZk;;7k@B)n4_L~nOw!*S_Aa{G;cPts%P z-0Co>=*E!yMt*+~$G6@ZgP9yl)~q5Nj}H-5yvjs>XMLKnI~!%&4C(gV4A|>5r4crn zsM6D+$XC&rxzvb^4i1N&p8=`*W%D^KUD~>R5T@<vL^l(%aKD8HWi034ogd98S~HyY zOS;ob$1s@L%P48^AQV`%rX@!P;RxS-=(aKnC+ZlHhiw$pMz*0b8zOK*s{`#$t&i%r z9CKnzeQci4f#cSwVKm3+E?lFA+-2R!zqAQ1<{R^!NzQA0w;QQ$(L_|X5jE+c1@&MD zDlKRLzgv2=d@!FY>(`PJdvpHaGcBofmIkzDx1xw|_3`d#3$pd({Lj~$a44N72!7Fo z?(n^={5IOuc2-@a&*pQS<#q6`l@U2yYliA0?P%h%W+>*E3ZmcBB+esjSce>ravtyc zb(Q11TiO6or|Z$8*Y%*%=Am4+P6OXE>(T{TQ>gTPDBqdyfWil_>1MeD0)Kv{{X@H9 z_O{RT*r^+~7Qd!u@!b$T;2bqv?f_ChM=g@N;ogZO)H1Lew5L~*yQw4IRaVh0&U34I z@(4|GvBT4h!?bOm1I&gUrqzsw-wskQuCHJ`|3_z3AF86~Yr5c6UKQ2O>4M@@M`+x| z&M-WEgs%6pL&TdSbZU(QG+!T~e8$T1(^UVI1N0rv(C>kEoTuqDZLzh(k#1)wFvE_2 z2VPTrUpu^PdXARncR~Hga~vC~3mz_eO=kw#!G`aRX)Wvm&EG%M0uR78{u&(}59oP+ zr4<?8(DwYwc@n(g8gq@B@Abpu&EM#3ZU8)cUZ=~6PM95VonCMrm6a9WsNF7L^O-tG zhBw?9yFT?p+s)sprV@B+ql&(qM`i1W(^O}R6OLTrd;!gRqJI;P_n8`ihmTIv$s$7N z*edF97|1TXO3l{r88nyEbfc3uY8GCl;r)AJ_n0b5^Y+FL=hM`o0tmQ!m_FZ?Bjv~u z3UTp9E|*_6_C|^Rei~3iSlDO}&3gcBZMC1?cMZVVlZR-Rx(`MkJwpFg`D*_!%J;%A z@_qf6d?)=E<-7GiDc?VSk?+F)kLByg^3`Yg-eUPa|34_-`Tv1@g}n;<74|IbR@kwy zUtzDpeuX^?`xW*o>{r;cuwP-X!hVH43%eC|{Hy&6yA^i)tNjYQ6?Xiq{R(>(_ABgJ z*sri#VaLL5g&qHDzrrqs-3WUUcAUg#>Js*R=QuasFt$^LuwP-f!jAvWeudo%I~MjU z-Vef#h5d^6#jp1JpOvq$-~YGr74|FaRoL%;R=&b+|FiP_)qa1KudwI;UGj}(`9}RW z$XD3!ukwAXYX#dI?)0&v8C1Uaq_?HkxEaxxYB|T>B#vY9&d3@sPfnx_s-2NDc{0_} zZ;M*;q1MY=qT-1^z4@dE`!QL3Pm|9_%BNF8N;kZ_JBz-Jc1A__p&aMCEB3BVAhXC0 zxXAwpC-NQi?0wVdc>{B}+DxX;#iqzFv!rhtMi^~iLbn>X;r}C?gJPc^p4(Z|%0LTL z_Hv*v#hepuLLXYCXN}^U-8p{$Kj;?pst)Rc+BOkNx@X;ShOI1>oZfUrZksqI9fGca z4W{tx+>!U)jbM1Ky>fm*PrVlgs2Sa!)_Le*bFGDv9zoxlI~MS(<-1OQ(KmO1D{L(? zNP#s=vz6;2*2%M47d0&cNG{iddSd3kjccFOf&cf;QubGjbG5-FsjR@E=WS8)B9BIX zvV(;i-#!0py@g!V4j5z7(>Y}P+7wZGvy|)nuj4Alxvt9hmYNihPpS<1GZs+9YtA{A zI!8Ir3C=5bb>1ZUEy5gQGxBIxYd)vyI$fy;LT-<(9r)Z@zEa-3&pU#iEg*viPN@4k z=X?IEEanmOiszS)wS|^$0Uesa=OaTF(9$7Bd=F&-d2qh=+*R}ct$d+PD|ly3R<;-Y z`?c0b(5;Ci@K?PMdM(yT=(Esop`Su8g#L>475oal6?!c6Rp^V*3t=Auh5Y|cpN0Mk zx`lrKojwaX1>Hiwg+2><1bsrkg+2>91wBH)g&qsN{yTjZ`YZHV@F&I*<NlrA3Hb{- z|0+kJ=R#gW4npsRo{RB?T!h{WyAgUU^!rym6#6aXEA&F>yU+un=Ynpb*8)Yo&~Gu1 z;7jl+^!xAhUDOLb7y2y55${>wu%8s>GMv1t>Oz6^rY<VgvM4j<C)t{0QBsYzR4>{K zc^%rVjlDgyD5qRYdajwTh5Bw;q#mX!l}n*6;c|a<RCmpy&~d5=ZqDO6{iNk~lW0Y4 zT_{k@E9giz(~;`Mykh(=`?RF`vHjE~6yuBejxAG_>caznlB@n?n%T4-PS{OW&Lie^ z`%MeShVk<jI?%MAOkzGU{;%t`F-jdZ8IwuOE9S}BrV6v5$t36&>m}At@Fn;V>m}At ztf%1b*Yy+YCDu>yEBFxeih0C({>qOSU(oR@A7cH)_+tIUJYrn2o?`vPdWreOdj8$| ziS-ieC+IkMD2o3dZzctnaV&i6Jt5HUG(kc|{qj7%Yx5T>>c^IQ;qrqy5-REy?ZtC} zI|7bK^#VmZMSsP30u}X&@dPTyJ=wFnG`<2A^*37#!r79Uq&g`C7k1|==@ayd@#LIm zTJc=;7j*9J;l+76XOTd=n(k6rwEJ0|gSJO6(uI3tCEUsPE_Tg3DU}Up?IXo=1^#Qj zX#cPEqMaB|v={RVdbS3nfmWD8?PwNCSDB)CQWknFZI4&;)39i9d%P@3!>(JJ=p)O* z*qfU8RGx)H!D?u;nEUln!|Yc{nAE&I_N+;Qj~C~t^@@c)=N@+`jYUXGd*yhlOR_NX zy$<q|({SaTj&l40zISp=uRZ(=d4D*wJsLh3i+cr}yL`$B6!ICvcYGJ8O2-5{Y$9Qi z%egrphCqvP;MEY6w=_}CZ!shZW9OMF=@4|ijO4p^_nTvM_rW+mTMhTrBT*fq3Y}9U zaCLzx#QbHmgJA!%Iqu~I!ByWF#cOl0wRuzAILdUmHbPW-8Xk?R51(sUkd3R4+BI3w zn^F(uWof9LP!HSrUQFwCjqurS9IW`x=>D$(XmYCsLT&`WqrV0!^nFphOasdeeNkn| zIeZ%iqJKpTe7f8VGuvq>+lhW}_)hx%nJtjl&<910bg<0Whwn~kpiZ7A^gpO8>&19t ze9`X5MNb@RV2r5SK8SZVLG$LmNV?P-YRO*kDmFkstuGF@Gl9lWUufmDRz4T)RqywL z%k~aPDe48Mo(9TxqF>VK9_V$Z1H?RH+)g7sF{!r!yx;QO-Q1>lJTDDyavfaBVLzpd z4nB7qfmY+1VrWz{erPvEv?|{{S*{I-kinR(Ypj%qkbiA>5^{^{BWHOM8ksjzqUbO5 zPUw}GPmC+{PRuXHeP}!aqnBwb<t)nmn~y{g`$9#z!YmHCiyA5Qz;OfL2kfhg%I-lp z!*^+OEn~5GZ6hTgYF`3Sw_FwDTKeK5w;TAZ7e)<Gg{b#v<%6-08sZJFQ(?D%wiET= zoqXYE+Y+I9UI<*<5;r^eVQ~e=bNj14rm7d(_V{PLXxCxBC$_n?#MJ6^JnpZ8@crpX zD!E4H=h84~)@?d|J58z|_&64`Z)~AE?AJf_;dlBN%V(>zcG3DvgVE4(Bkkh20v^pz z(nYOItWR4*Nn<jUs1kQZDl5iU)GNk6GnxJ7T)&#{y8m!EMOl1DJL(6=O4mw)Gvm!> zNeJ<tO{=(mv)62jdNl-QrN2=xMpNtGY0t(q=-$~y_4cLVMCxx;GbIakb1q8r2vp3| zm+KX%m{(CR+C{HR!}_p18pz{CCH@01Yc8cno6}&>b*XaP@DFL&(d0L2e)YpEm2@cj z9co!Z{T`<wwDh0-6!nU61f2?WoOOU47Nntg?g1s;qTZLEuWWmiqWQgfU;n7Gov8QZ z=exAe(iDEau+dp%I|V<A_3Xs_DezzURPgKAF&6m^N+|na4By3E^>2J_a2YA}%dj3T zp{jf|O7d>gW&e@Vdabe^i9^G;P`JZrL~PkWgAR^`!Cj8aXgV4(V}GamN3#+0<piCb zJzSEb0<RBRL+8I{OQ<L-=u)79o|N(N*yTB!XhJ*!zZcR)%c0mh<Tr}xG!#Erj-s6c z6><`oVmcIl{qv}a%}{K#TdM5$^JO~XG=Edp|MnrB^<$}Wylp*)B6$7*66onO6w5mt zC4n`*LwUdKtTfNR(z)aJk<ebUl+>I?vD{ZF=M(eCG*7|_i<uO0Dgi0xGnM)&^i=5W zuk9k3?|U6*D%U}*hv+B9bIjoV$c)+4Ff$Ij&5M-lCDu*!6Yci!x)!%yLOyIKg$7HM zb|mac^!v5l1GcjiZZGUjpy(&Yd)_t~YL-Q$X2|CuGG{C8Qt&DIiFP*nSvVF@#JSo= zpenwA-n1Bjd!1*~5?em+MYC!CLXH^`Q$(VjsP{|e`(FmLY1E}L*n6^&9?Td6XU=!& z{QC%8|2m62cZ`5~M1c}Ty%=B2cXMYBqP7pA`Rn+6lW)2bLw97r@p&5coID092U2Op zp%GYF{ZADA+AT}Mo6JMxRhfkKe#fX&aROFvJVGm{CBUK0K{8#MfV9eK<hdzPiLS#Z zN%aa0=JQEmn~qTG@g%;Ve~h}X=5aXJ#OXN+c**?_kB-B}7gOo+?06*x445d@EAYzV zWGweTNTD3NL9N3f<+zIZ6yqx}p!)==UV)?TBx5(X`?4$<Apr-aadXd%kj7JB+xjVR zxUq*cGE?BWV~^CodgBPGzXHuhrJ$DUyEjR}V{WIQORrs;)L(%n7ZXwJxQp)XOyYZ& zJEZ=GP1B_Q3RF3eg#6kaL^qf|r(M+GQ4-G19Z%~6l9jm2cdS&eKt=to#uNTg{tMHu zPn7BvIDJeKmao}DS#y(+*KRA(_GD;w*h2gGoP_qs%~HF^L0M9N1%B<%=M)xfpe+9s zxE@<iqf7a`j>;CA)FBxGUYn(Meha5a{S?^BEd{eLt*0q{c)bp7km_yUrAqA-*kM2t z`fpxGIy|ny&^1#1?cnKBI|VN5oQ%a~Ysi3Oab*5jCp}m2Blr@0i*>MxNrGSG78;P5 zgppUaP}=S;xZh#1gjX*Vb8cNbY+Y4Mvo!7bzDzM)ooWw*PD`kFFK46~FQzBsIR+1x z?Y=s~xMMMC6g$Clb+Pn3<&R=oTGvG?r>=03o>v;kP|59UpW8~~$l^L<0*~8TwF}nr zJXbI9e9ooP{5cV&^!>g)3XYYK+1sutJinBxdB4)*cnOv2^7-HkOX-7y6M|hzrTO$C zOKD%ci&VbF_vaPu8cmbKhui%z#}=!3oR#A{VF!<+vb?i2PxTu+EI+(VnoogiZMsV3 z2a_D|j?2b3x<Phi8ELe1l2F07qP%;mi-dCz%Ow2Pk|g9HDpLRRuWcmMo6uRp`^;Cd z-%4qovt}!)*#mp5tz1cR=Bs%7Z*+|Lay__G;>%&jZ}gh^a`0a%@s(}9QsPTdR`BJ` z?G$`DbGv8Emtvel%vTwYqs4s9<9VuBZe@4MrTNk;%4s>vuPSO4eP;PN_g^i^D`C(o zNq*H_R>+NN%BA@<x0h2H%S};M$SsE3DdcvR+x2I89piD-Uf9Bx%cd;1#edBcI(UuL z{|jT5V<-IRu!y>9@HyoE3utz=4fal2K*{fI&|Q5IX=T_T^WA*v>TiR<z6Inz-x}Tf z&8NKC)`&VcpB}8S!nd{aId_&7cCf!Q@x3KnuNBZOYb$u_Eg+L}OEjLlkb<6CLTwJm zf<JGGDPe_V)6@zxbqi@mvK8_wi)ivZD?IN}L_K}2aV&f>S@gEX{nJHMVQ+)FjTcih zJsadrDk6s`HaK*nknU}<!Iuez<oV79-%J+KkaJ9D$pX^xvw`lA0!o=>jkZtb)0AUY z$gwS;?N(OM?6QDto>=0@>V?!m(+WPeg*14s71l-;kw&03mOm(>T3s9XloZjS%{JIw zTu64_W~eAzOqPtz)%kmFzd6U7T}of~nM?H*Q>|g>x`LM2Sfk=n2_1H^!sWipm3X$V z6=s*MAknTHkK<{!P&uv`N8m>uSMgl53p{Rus~=ZT>@gGUUb~#I*ckRBN|iXVz!)}f zSCD9zcg&o>m5z`C>$@JNOMzzpH@v{*BY!<tv@>OX(v3>#r<WOKGj?Pg)|B(u{DtfJ zd0j4xc7lJg9-^PXU)v44!uP9k|4FalL*VC`rWoCVb0PiJPSBmp^k2BYpYAffSN{bC zKcby&j3q8SFC#(c7rwuzzikBx6!H-5792H4$v5`n^ftpA#=4AAyS6BC0MF~qWzkNI zE7n8w6Zm)SdR*&>#Z1Tfx~xBUHY-u|6XOZ~1ixZ_fr38KPVgn@67vge*uet#Z*Nxe zFV<JAx1dX)phL71>!sA^Z<eU<P)djYLa~mb-JC!xXfN1LqatmT_%MGxDe4s%on|Z5 zEAT#-J;!i76mG9TMY-Kf-dE$Y0u|*Siyfr00u|*OYaFGr0u|-$yPT!60u|+z$7NDk zfr@hPQX{18I6)(uo1n4Iar%7I2$f$Cl5e0PcElZ{!g1}8n|qLwR~cf`y}dM6zXLwF z?%{KFe2*r7AN6xK#r^C<Wb0}Q)0E95cQ?V)@^y5pyaNhnZKR?aBWP||L;ZLkM^XMf z#!z~$Hol$IUQvI{XRB17(s{eoKG1Tf)L&7r7*A3EKkt?Q+<Qg5PsIB{y#Itg3l#b* z+KKmruq$Cd0{`bd@{jlA|6krC)txzBlI<c|+^`c0V;0b-lQy`JzktrZv_Y8OBFaj! z!A#C!yU5c9X@d%A=S*t^51vnN`S&;H2JgqNu!8Q+`J{1>e}9b%xSu709u$ykM=L}a zFQ6HvmM~blkShMPL|e|0clwki7A6$ZJT)tn7!^`&j1|hNis;!4D>Mu$qKzKbxSY6{ z3Vf{b<w_Ch+Sou}cQIu(vq5=&5iPoBgWHb^srx#9@69Qsbuaii$Edw{g6UklfJXJO zfz7A_x;(`i_V4G@s{>XjkQGonQ!5zI0$O;_5;rRr(hyZEM9T{4Se_M*Bo|S3Piq`{ zT}1t~Y!J1!h>X_qI;<{K-uM2W`=bB2&%Z9K6Yf`j{I`4k;$CnC=a%q1{ZV<(|JVD$ zZvxw+=yHAd54V8R_4>;Dzv6!Ie{@e&+&>lf`Twi;fyI5~U+)Er`>ZfY#L725s6UJS z`@4Pdpk5m8z4An{X(E0mc;dmlp=j1K0F{O5_`fK7^LVPhFMb#i(qJltlq4yVOmWX% zsH8z<C?$ndB4jG_)T~K^q)8g3L1yBfy(-PKM5Re-)<ly&P0yy!`TTCr>-j#f=ehr^ z_uhA%eb?E0?f1FooW0kwQXUVNzAc0vLs%>igFtB1oCLeKg~31ZW1#!kIq>z36G-#^ zP+C47HkbN>%&3Ww<}w>T51b5ng?@la<3X<250azDz`5P2#H=WR%Nw<Xq<oCwB3xMc zR3ultG>sUYk|vvG?I4p6{gE#(f9R<9ee!{8ueW!4*ik+-@?l3=3NLq*=O4WMr)+tm zqkKo{k6hMd($QW9{UepD4N3d&bZs&0sJ{`T+fm+mNVlV`IZVByoHbLuqkO2jOGnvW zS&3L23MXNA0=dliD3;%M0oPqQmV`w*bL9rnWU{P1w^}2WgvE{EPAR04l%A#>xwM@0 zjU3I5%v-_oP>Z-P!K=uJ^Ygf6HEG0b`W(*j%u4d%?F!CIK8?g=q;co_EF%TOGC1eF zWn^;9Hg1xC5;6Lf!JS>6NX$aEbA?+LlN+t8xQ9cch|TXc+@QX@$f~PKBuXxai2jvr zhh#~6eO8`qN4=Ti_YOT}rSDw3-kp<gI?6ex-gJ~d#69dN`!4z;rOHe?j?1a|BTsr8 zb+o6<Wc%?3HvKxv&LjH$(Npi;Q4Z_byQ8eoqS{ej#pKF@$)v6J9QVGT2g%Yr%bn7h zLUIa@bH87^l9QQ7xdGIhY*?4W-5fWAn5k~(hDQYu<ulpbCALQ*=lxc$&@PPF8z12e zheVP)rn#KXw+J%-BXYx1S)R9JC%FN0LW%F(TJGolFp`pVhiln0hkTfKpVMiYLu?Y7 zxZWeZh}5ZiZnWt%l9PJ>KRbRcnno%HRC9{mr<0ebi~qB0dekg(fj{)0U2ZIIafK-N zKf7|1gUPhd$N#fy?WRzo%<{1dcB#%@KsG$O@}FH<!E;DsTJ3*!<$UxelZ&qZXP00{ z=oXf5m^;Na&0uS<23P)P*Q7<h<YjaTC)nlw+@F|TDdGgXW~l~{tPiD}V3$e~%kLW^ z<^;PgC9(XqBdR&UF7>r@$jJfcIl(Snc|T${^Bmh3`o}JJ;{>w7B!xTYkV2&Dqq&G7 zDdc2II2Usuo=7zWb8guwti52)(=UnK*y7C%o}Ee>V}iI#tC_#|_vBJ^SS~=-5bo>w zrNmy*hcjBdg!o>F;A9>yBPVx<{WsrljA3ga?xk`957<vwLX;1#<U((ykQ|2uPO&(d zRD55-wOnJlpwc^&A&-}m;LJbr<?ZgIy}sl|_m28Iy)-(?Pt`R#%Dygo9c5XzzoY%Q zTN?*<l%;kL>?qH_Xwp#@q?Gbyu3axh{f~6seXrwp3pU>SQ$OHMN4amWHyvfO!#_I8 zAGZDAT)Hy;vg<)UKZqf3Cj5~Fn|qS>dNIoZ&|d%azII1hmdW<=NhAG^@>(X_%lD&= zI?9dVMjhoCOOuXrh2bAL|7$bXt|vA7O^4L{)b{6hH??(?Kb@56&{y9k({a3lykbXL z`LzNO#zz=8VLXL?7RE~$Z(+QIaS?b~;Aw%M+oizA?ffk8b$h+Q%K}gT$IJinbUQD% z>r4I1)9w5$$;a*d-2Qz#U$@r_ye#mvz{>(pxAStlemhSK{4DUXz|R6-3%o4ww7|;( zPYb*(@U+0o0#6IPEbz3z%K}deye#mvz|WF=+|JJeU$@r_ye#mvz{>(pxAStlzQEJ% z{M>QezkJ-z&+Xs0^L2Z@z{>(p3%s23FHg7ga=U&zPYe7k@Ug(p0$&TfEbz3z%K}de zye#mvz{>(33cM`vw7|;(PYb*(@U-x|f*k@s3p^><A@HGKhrow|9ReQ;b_jeZ*dg$t zV28kmf*k@M3coAZA@H-n*Mc1aPYZSkJT2HE@U&ouz|(>q0#6He2s|y=A@H=o&jKF{ z^I4d`0xt{mUEpPb2LxUg=Donn!n_xFS(xtvFAIDi@Up-k0zXUgaXUW?eBE9z@Up<u z0xt_ZE%36y)9t+6e!L_<x3?qkaXUW?eBE9z@N&w(Jl)RA?ccZaw7}1jeB92@?R?tK z*X{KJFAF>^@Up<u0xt_Z-OkJH#|u2&&d(jc^DiH_^RvL$?ezjL3q0M<%kAH{^RzH7 z!gvYeDfF)}PQv&K<7EG!1Ptc-61_X6Ab#pazI`kOvyW3qfN>d2GoM5vQ_G=o?pU&7 zL^*gYv?k%5%HU0$CE4=65PqNq>3OaI`dU~KrP&2wr0z^wvI`+&@kEmMxd`^BTaY*3 zN}%Me1zAvA1nOOViTjm8csgzhdC^!1zK-no?v_B9-FR{=_&BV6WkW{&%!jZsPUP~P zeE6U#B2rKDL4D^)^72asOzz=KcI~JD*(_U<-0K8<S}>X<3^@U3-f+bJYcX61wjftp zieTF7afE+b3`cXulYw`NVZu^BBIMH(^6LqC+XN}(V-xbi2~x=aCgg1s^o8$*dO-^L z-`ex_wddm#q>!gi$jc|_3*QU%Li@t^LcJh`Jc2^LK|x>mUZ@w&SNLA27xEPf-wXAl zS05)4`NxU<mQv#Ep7);=>h~fgT`uk;f(%zaPximhA%aZZaf7`6vYQC9bH4_%o#k{D zWS_-PNJ;WOBFNf3&7?#+j|fu#XbZ6zd7KFH`^r`#qhCY>`D#il+4QN52r~TY2a<hX zOay6J{EoPlpCp2OGxHTuxO$cd(jnk6`J{V^2r|^Zf&5y*_SO9>-4bt;PsZ1YAluKw zyW5S9^J$k2D=)J9wCn%LIgRJYwbxgOAYliRi3ctbK~7y+PI^s0M+9kWS43XIDI&<{ zS_R~bGfxC*&gYXTuW};DXNU5M^6DZY$R4Y2klDc}{@ai6e_!V;tV<TwH%tBdaX6(0 zqhiNn-6x=1Mys$r3=XIekVkh~xxku_npl^7OtjaE#qd+IM~zOIVzsA!^uqE*7<b8% z++Dkc9<GVPq6QmL(y{(SKYUL{-)JlG``gBaS94>rE`2uX-l7a8|G42p`$Vzvs>9^h zFn5eO`--kU+N)^1>Ll#7q8Ap-wJ`rS-W_MGQpTlfp`>@<X!NSmz|4sufLgohZ9`A; z*&-Ys*+<i<S3^kZfmvX%{470?y^AC~b_V{4I$roOlhnV<qx*EnV#`rEc-yD{FrC6F znESOW+-==pwth`GPTtAhTQAr^do;~O?H5PMoI`6kBW?=%Zt99|AB(sN!QKcCQus#e zE%*BA4Al1hO-q_La>L(FL5E-^^taeoAaCJ;m(6?N*q}XT3&+jC+r4D*>c(B9_bxx| zx4oPud^k*owamkdAJ@>8Ir60Ta{{_0?B?Bu942Q-Fv|Fip_Vg|%eat)OZ^)~?Ze>l zFd6%f?Zma?N30J|J+~G$o!eA6XIv7F8uNy4{j?C4x8&2O*VpjU6$@dKX92COPvh<7 zBOs;MLE81}ck%MtaCmH;OA9ti^R0^)f!xux)NtP>ZlxnzSE-*)XGElOvNz)4&<8EL z*!D7aHzgjPNA#uP>#lRErk}_&`w5tHNlfxjXAwoinK<O?b&|AYDbZ4jM*sUB+)Dkg zB&v@uems6gG-N7^59zFjdx8w%Z0vC|bG;#o5=_9-_!04Um%@EB06Oh1B?WGs@qo4y zINlEdgOn;tEhh7_TSKALr-Ba38^n)tIzd$S`=Ms|4(e5r#Vxs?gg<H*aQ*UQ;DAab zb-lQ=s`?I#d!*+>xA?5KTj-n&BabfQLv*#c5c^~(7A@w}jU2cqCzE0HVVf$&8N<2C zykxK{*AuTAJ&`+~nFJx}oB0F3c5qfZlOQ#FC4YF%e(u)oWazh7nvXDFB#vxI2C0#` z;yHsKh*Q;*VM1Yo=t=rvo|jGr=f?G-9=QelGWiBN-J=JnezpWVUc<`zjv@@H@PwM@ zqb>6vc7hSXGoaz3GF9EJ2Ah7lfU_)%)$S_A-7bu$w*%(FCRtaibp9e$h@Az$R~)2| z9#eYKIvOHR#&KDesnnu00G5?k6O}!L%H3!AG32^HlEyv0Q1cn*aMd4I$2?)rj}u5l zs{x)KKLTnWttReU<?$--!eW8kBK=-X!Z}qnl;2rPzKj}!+uya&4Wrdyd6gNS+}TJ6 z-+e~r=(?cR+Dp{KO9r?FjwtJPoj#fRnfM%>fXZu5P_=(7Age$Yef+=B35WBE`;I1V z`6u>_PVX?O?o>jCb@PQOMR{br#bFZEWi|vX5R>_ST}Wf<0$4I}FdW**L7(eM+*_8f z<LTu=FzjS1uXMZ<bRIJn(p`>|6fb?K|1JU@p9So>(mk@^v@!VK(gwxNVlrxjDL7o{ z2eTd~!xO$uY-%}BRR1CwOsCh0cP#o|rR9=E(vLa85SCcuMMD88`Z5D<Tb?2>R9uMD z_{l6Mj1t?-yo!_-`NQJ3JejLeN0ML7g_)aJ+%>h?B%8%(8S?HHSMJsgnxm#b!pfu( zJ(AqWe3>}-wk(x<=YE`=^_qlU)gNi5vl4{J48h?2Qn-@EVri~9OnVw%q7^x@P@mC< z%TD*98`(3<%*|Iw6V~yUN+!YQFlBH_)nR+{2l59G4TVo{N8qeoBdOIEb11uDhO6&y zqm#l1!j95mSnuFX=brY0`8`@`to<^&KVm8z_x(bfUVZ1}MotI)f=+lRPnrCPcLmG6 z-SLs*Co;UIo=fxd!E190Nzd;)sqLrPST^?tIsPk^=4AV#<?2>a-}e-^$jBEHqHnN# z*dIx^>@k>Se}P;`l7pE3j<{v&TG0-rOuD%u3h9fl$4iPbsO{G%jG5RnbUE2V|9KpR z^}W+XwqaYT#*!$U9mQ4Vx@J@3s7TZ}TT?Z3>OML$I|46WIVEbdEuojw7UKBrR$Ps} zm~xjxa9iYh`rW7xv^a@ios2$u87M$+Wo3|@JCbvxDI$(@%~ZqnnUg`l8yJ4Z>fKrW zCWe2nPv#mtl<=1E)c;3(lhudXS`8~X;)~9qpNZUw6ZHDwxp=l`Dv`WSNnVd2N)grW zcw)%9*CNU5*V)tZc+7Mndaqyk*EK?GQy(1G#R$U^@Beju39ZZIzd5LY{U=x0FLtIW zhx@~zX#_MX8>ma^80;_qnoO0GMZ2T{82h0I<mTR|Fwz*;>*;`bze}|9hB3IOt&M2v z45e>Z4Z|Aa;UHzUx$sGg3Er!<gVkzX%)h=fMee07{LVI{Zc~TjzDL8rW6^iBE>$uZ z)7u*xFIjQ3$IGLP{B-=}WXMHk%ArW#3%lPsP@q#UjWv6`QPQ_1d0-OC!Il_6mAy4o zx4$NY?6Seyab<t;h9sXza>bz@ZctjIjKw~=yovM_*mAZTR$Y?jj}DvyJ2rMh^GRRC zvnRVkdYuZssz1!9B)P+#Y$d$?LYd^mO$9$yMZCI{#dO?b4*7{)@SOh#qNZ#M2ZB^E zx$rExu}2$H`)1KAi6Zza(*s_845Yrg6JT$`7Gm7Tni#AM1ADX0B>SN|Sro7kxc9xt zKSMXud!r-ZoccS_m!|!+A4EV}NxJxaZzI%{bAaP<->MD=8X#DYV)-ywj<_TxoYb4e zBOWjq?7j}i!9g*k<aXR~eLpEU$nxGuj<3(|RIc;r?zq#^1EsT9avOJd#U?TZlMY_7 zSU4sLUZ}j~9_JKrPwyl_x_&>-^6X5axGomn#d&epysB)Mj7bKwRol4xxQH&V@PW>u zcc|llU!<q?EKm{w`%je&mz7GyTfKLQ<qvwpowT=<q`A_K9`nJj`U0K#TZ@VqH%^%J zK-|)@PTUyg2d>vzNOrw8-yU}*VBuGCZ`N}D{W>{F_woXwyGcCcU@%vtx&Y-eE>N>{ z@3OXELHMZmWjd)#n?-Wk0{qJA<+VPFwxtE*{SnplM1&Jj$e)j9U3nVH;(m#y1mUxf zr8HXWGig2QiXUF?p~j!t9<=IF*t8&v>QAyI-OJ)Zd#j~*LF;g?syG>Z)%J;_kMH0# zl_uiQW4&;j<{|E%72~kiU~Qy9+l%I18H1y`^~Ip$Lx;cYE(aq^yl~PmX^YS^YGBaS z6=yuT$nAAag03$@I46}m+!3}1Br$&~7q`WoWX+EQ&-o`rN7;V2OMR!pz`{~nUv>>v z>wA<mOutRv&X`2xI*kQ~>pdZVz+JBFLn1uQTgN>a?F>ad^X-mB>VYcD4^%rqLp+}C zW&M~p3La}7;kG2OeBM9pVdQ8vqS(g(j$gGRk2`t5M=1qZHlt@ridGDa4o#ripA>Bi z1|`Ax*Pr-4OKr*B?=i6Lml~aA<U%Yug@e_t)%0@j`L_No$zXHis5p0;B{}yj9yEUE zi6b2r!<Qec$+I#k{>8GzpgcT{sIK`W+W&Mhtf*T-?rai^$Q2e}{*DiE-%`w(4TuHq z>@>10yquFfuYn6!5)nU}3>?d10Ij-a9@saQyqd^z*LfT=H$W9oUF-(tv%VGI_WVXX zxBB4J{KK5>0|$6`a{x+Sn<V?c?tvjpDP>N$$cpN-HGJ0Bt-->{m!CSp4Bo}sz?R+n z`65e0aCYXPCe4b9O1r>JkrTX~oJ)?jc7f_XPQa<;5+8-(#kZ8*;qXIc7LUE(@Gfoc zkhZ4BU$))b-#9$G#t}}d83I3O1n0FN7RUYaBV6}=<W*)cwzhhb-;Hz0g6g^0$MZDd zL&l4uZU$h9&Rz1-?;KZ>6AeDy!f4?cmh1R^INS~2LVvy=K=%7Zf~@ySdPM!0XroaK z*ldcUt8=~*O@1cyeIi9)nRr6blrHdIyAOA2XJ@dEoC3=ohtRK{)+9qC5`LUpN|WBL zDk;d1f_3XM>4qyO%ecA#%r?495(nO}YWNtB5wk3b@`10!G0h8dYe&<ndT*A8=r<WT za6cD!D;~~BO%grcWlhcp$3SzfA7@e-M)U%`;Csex+VjvZGI3e}Joej8=jQGpf$OB< z+?|PdHDNpX>8lMf@2!xi7ZK?dJ1kdGJ-chalX1t7HCFB)kB}|>!qK=zAG`E?M8t3O zF>2cc3=LYykM6I92fe$KM8^;qzNd)Np*u_0e47uSt!~l5hpfuls#qSm77@n9p5dQt z_lM9y %9^G<x0Dj6FiZ+X{nm0XPNsVh3qvY>Ow(q-S9#<jfk1F?G)5iffEV@^+ z`yKC2xLjvB*{>3YC|*DhozjCFU&i1k#lxcJi^ITdxdkc(sFDNEJRsJx8@@cUlxsUO z7e<Y_N1a0-aQa8Bq2PuYDtMpZejRXu#zmTV>$q)I&cG<}-n@-krR9mA9*>86yVr{j zy4jMTe{#saF`;lo8tDCH9F(y5_gS+`xvM>TlRb}TK(BrOkicdq?qy;!B-k17xz=sm z_xw1x8*E6##jW)E9A8+_>j-!5(r|2xv4lxWm-7+1aX94jD024Z3jT&;G|_R0K}%~j z&fdO+gnkXc-o{~MM^*+g`yPdDPHMIfbTau{F3Fgd(Pp>NGmkgWOGdqQ3#)ub8RDL= z1k)RP5$jMnG>Z1Z0X<bjTJiJo$IN=#c|y;s{D-qKIQ0$97_P!ao=Za0&DH#_!FeKh zorEiAmGbC#S*#g64HME8z<<~yvCfVJ%-+?5q>jqvQ^Z|x^P{P7VxtKccGL)W^^GKs zRaUSnc^ZwI9E*ubdAwvhlI>fcl7<&2-C^+Z82V_9Kiu<sOa=^-A*QX}pe)7%j;6-) zt4G}<19r}Yk+_ULb&kXBiGiH9)+B<mGU#`X<%06w$Pc#ZFQOSNXUFm=>hZOdMr;~E zJ7W;~=O)2ehZ-*7-7~wDzoWq``I<;vl0b^Po+Xd2%mIg%1=QGMi%4!|EF>$<p^LPd zM9H}<H`3#9Dz`Tg%B_C!Q>OWHZtls@ET78XbXDWNCmD)9_DF>1Q+m@6cQz28T@h^m zp9Y<{C=n0DD{vF*m1wsSerVF~BXNCRCO+t&gh6yWH^nWF56Vr%sE8Z<&U>YN!mfL? zh2^eI_@|6+%-cn0xdedR)+{=`ZW-0nSPb*JQQp@45cz&69GmNZi(k`sWMPgE-ul>` zy+dU=Rjg%DXW%m~!FfCkVDn6rf1i)5^}$ay?`f#H3^mG_hzj}|m^~$3oG5jjM(ztl zGu_1;)XQU44^KSv_&J}xcQn7VI2pT!?yDSpq?^dLAPJquUE}V5`c7t?az}R-8{%72 zFdXW$hjxyiMr7Xh=U(Z=B1`^B4&9<Obx|Pd9vw<9ioEf0oD5Em(HGsSi-fmP8|l=a zjeNzHMOc@+f;PI`<fG*lqwSA{bf$T)zxqeA-z0S;`%SVx&uvq{Wm*m}_)ax_^YkG# z$?}5CE}Q5vvtv}YCJZWN>&0vLJ+YhkGZ|#6(N1<GTX(oL0OoudPe1niO7@#DZd^8z zzMl4z+*W1z5&c$B(-Y;~rQ1m?58H2X49lOVIIkOYT`EOQRtyK#-IGbbr>3YN#rEuW zI!RrQD`4TqMX<Qb1|sEGFIHlCUA1IGNru+AN*SZ^V0v3jAD;V4wQE`Iwdi?tPxm`i z;f60<QeI1sytqIwYQzJ%H;Q~7FT?daz~V&vRnzA!Pw3<iNwDEvCck917hn2nF<fKM zkRDV>k^j|>+o>5ay{3RZF*{8q@tg1%h`lz8+P=NTUwMDRZhl!3%({MsAF$;y>61AJ z+{=0H1B-F3ayJ=_738?*R~*4*ek<K(&_w;@<Y9}d3qEb$@E4X{`i$(fnT!DqJh>W? zM^;P>$2of~`2(>mH@Jf`8qVq@_FJop&`BPbRj{?0Y%j;^H&5u#Z62T(e9i7oKUo~> zI0J@_bQA^j4n*w@wPg0SV^lOl2Inmv2YJhG(`!<m_%7x+QLX$z7G_LEE+T~X{m}=S zPurv3jajry{V=FHp^sw&j?xd;D`}haILzt$<F9(fb1`t;lNVVBhmp0;29WB`(>c;Z zU_|{lQj+D4Tlc3E`}DQ+nnMJR5t|apcDmKBqU(R;(vcqnV7a)Ii*8s?2VGz}u6z<; zy^<=i%q`(0+m}3F^V$SVmG47S4!sfoDCDr}+z0wJ_%o5Lm;5bB8#34S#p>WUWJX3` z$Y{3a=8WkE{Y|F8|7u@S=c3Lb@>1cgIHfQgUa89Co30h2O#kU1+2$<%mEE1I^?XA{ z639>9NPBAi<U5B%!cI3zvV8+!hw^mtT_&4*%J$y8wmU;i=Y1mvBORf}^8s<a@`1Cr zb%WQf-Qin+lSqA29AwOQC8`UqiFWt&hRE$QAU|Hj4WB+0@?w;Liw+c>)pUi<xoRLa zF_%BppXH`(Q->!gLsgECg9UFj;etvh*jH`|n~#1a`+5!|TiLT0%?BC~b|#p`_Z<nh zSNDeX4|>3Jd$xC>*Eb^Rw~}-Av-?51wlxq8LSpIb+RyZ*FN<+FMul7QbUHqq_nVxa zGmx6CNhdz1=R%`PK7Bvd9V}<bfNEJRoiV}>1|PdiPG6W#k9${>wHF5gy=j2<-QJMJ zo4=6!s{}(V--v7%2E*G^)pYykUThEZNGLR0MI^DLzGVC7#wWqDv&;DflTPyoo?j&a zmabyUnL(&hoeZ|`e~8`UzlcLz5}@s^K2={5!k60*g(U}uqyM+D^vF~b*m8FSmMr_i z=Z!o{{5xx5>lj-+8Z!?!)NiD=YYtI$mw9Ng(2a(UIZKUN;*kvMLt+z)xZ(NnXw}(< zCf!lu&rX|$wnr~gPWc2K_>U9rI(eJEuz61xc{pR?q+7J+{97v7rlfu(iNM{fvg!HW z$m`wsN_P$N#HGQpRO!-4bS*Q$w-yRq^e=O4tX0H?^&hCDj*iV95=kfHhSD}F>tcf6 zhV{eI{i<o#5x0r5zYgY{91Pp7VqrtsJnFZuAE%mRk2e<Gq~$H0Q1ZM|i`CJP?PGUX zPUxFj6U<!8;^(GY;JXuvD3{-vO!}Q8&YvHHCf^p5x9UqpjdjVmEnk&S`&@79JUtF? zEu2EHehU|uC1~KlrZMQrxzJzZ^fB<611?kUOXUV9<23~<eo<B$U)0S6ZN}T-o6RM> zr2k0zRrEtWbYuIDRM<WiN!vnY#vtjY3tQZ})8?iczWR0|^l;wGXD=$`huVchueArr z`hh02K`sHBOC9*Ni=;7hkR6OpdQC2dFXMMdsDQbw8#E4ENaxwwgS0^(@EzY1>&_T} z<LRGdfrScQTA>N8>s3I>xGRP#n89|#Pvr1}M1)73$o3=a?CjPg;r%&9T%>$FC;$Bh zJ+9vgbRrzUDpeCk&Z#AzXPLpHwpg^Cry|NK_a>74FF7uf_DI%Cwv(COLaJ1X#H|PX zU{r|-+aIHV2L?<3HKzT|Lh0qjfESGPpjd}eyMzxkw~Gs;sC=M}J#Ud0C1Y^dge!FM z)4Afx(jb(qf82bZj<fBFst#t5sV*(n)g6EXb4Eh)5nmcHb1dFHtp-(ALFDe2@tk>6 z4Ak)@MCtr1I<JT8U%V|Jq(OQGI---gKAcZIPhMVAVL7-*K%2@r@dblHsH$ua2E{<Q zeHGN}bs(J4G^X=BGUx%9@V|5<>x2I>A$v??@VS;Hk@RyTsm|zdc`^=9O(2pwlKwBL zzv1{^a#gn<_FiWRb#W%RHK3ek1{%Q3BFeo9a7A@jmA}TzXJ;g>+w?)?nid0+<Li^A zB~Ce-j2C;4=M^;eQQL(P=rCpwKUwAry?1dsp6~BPCGq)XAM9@L2*W`)^6CFNR&u_y z#Z45Am5#%n?`BZR>$2p30Lg3gP-lJ7l+b8&9J!QAa+;4>m?-%*yMH+q`WL@R&PT~P zIKfLEKE3G!?@ZPI8aqke-gtIXRWAcCT>4E8C3$k6<4LMAQUlelSmExNK=fO_pA1~H zgl-B|gcAi5Ao5Nck;IZZl5<?L9m#7%<I<t%B5MtuGP_cR9R@fvUj#L#Q;3^QYRTEk zWYDw~ac&hMCGKI-Fx6!#{g$bL;%inAHWW$os>7nI(&ORtLv46|V4Y|l+y6b?r-5wk z-3233oM2kFL*x`2pYsvN$Y`x$yk7~skC^g^?3r#ul;nTYEo3Mxa!|k(BKOi47Vgmf zurhXb9a4JF!whKV2wc3!5Jw&94US&T^q>kURec`_Yd>D6D-|@cEYk$els=$ULuR0N za|7AAE`ySnTBWI_iQrnGKwm`%ls;UX2=!-rP^U5l+_=jF8f5foL!}dLH`a!;(}&S* zm!r{RWdUcpHk^(a5Qn99?>WU*OX_SLk7u-ga;xPvsO0~4$@?{Bc1;OBG@I&1h0~<5 z3Ak<6SN^Qdr@!urB<~~cH4K9kX$y$@-J8noFo4;tpYvEhAKu*=o@KL~+IP!{gOW1j zz31S|kxJsekLA5x{)lK(8&cvL4BA(b=q@SbH?3+QPxLL}#t>zc{b&fm>RsTHj{^2P zuLV<I4Tma&YI;A|2WBmKMAnr1(3(mo*vrnBvh(%dAq#!0J>hG5Pa3=^1_qrmA&>hH zrF4A+40T*j4r=SupC4jC>PKHPWVRWVyvLNh_bi^44ADniIK$7A_|HxW!1f=Irp6m0 z$@@yl`>ZBuNAB>eSp2<n8jGd1j<4wHi&N#<yMx3?(y%rREnmfx487%|SE|vtrFuCz zRXvElS+NLz{s<y`L?U&_4aTB18AP)GCGU$R?Q}gg7JM%1V3L0Vr*$~fuHZ@%E@(W< z4T*hgH+Oq7wsfD(4NM;c^Yr_oNhdk3@wGE5g!IA1W97JUkH(>%x;Cm>Z{*6JCgR~@ z<SQQ)aeLB}aBs<NK2>{I$GhY9cg9juDfmbJzvGctl0cMtOQijSa?YuVFyz1ke)-B` zPF91(uvp*5s~XsgUVlsmg`Im(Y#O^ul>I3gb>%!Nx#d}+m`h2xNcN`4oaL}NyEOre z-;5U>kuxL?Uy||3_<ofZhU-L<?PGiboGCsfnh`LNIR9dMLcAA{+vA6`+?!LuU~2(6 z^r4>ISmKFE&H1F{T^*5Z-*`hj4$@e}pJVZ=Bc5y9jJEt*(SD9rHMTaPrD`WS&ewNO zc_**M<?T2lYG1j$c}xdhWjq928s>5zUy0y~aX+zdtu*=4oCsS&V#RwBw~)XaQBe3Z z8sc-d@am5uh)PQm*q9&ZqecIS>O<n;$~H@CvLS`L-!K4kx@mB$&O1V<(#076I-4g~ z*#7)8gK+$|X!2&NCEV^m4i-vlqwcB8TwMGbyA+i~>=E6Y{C^pX|GzqtebrdK+fMtk z9hm%M0+M4S*|!_VBtZDG`FvPQ|G(_{9z7mM57k6b+qaJO27l~G!RV7o820@nzhn11 zk<<1#wD0Rgi!@ho{qFQNdebvxczZvWd$<}czmna7N7i33zr1Cyd3*iQ=beWqZtrH= zj)#3_@6#`Cue1)$5Sd7gDF502N5|MT_up4)YT37A>?WKa3kSv8=(Ul(It<bkg}h0^ zI~kRnw83Nyd#8qqV>WVgD-!YD=_c{hX>w%O^)Xm5tp{XGUjG+9YurtwkjCDlCodu0 zl}Ce=uNu5HS@##N^-X{eM_ej(_6;T%o_8*OH~NpA%>E+5{{J-=|7$Kt`h3{gWNb1r ztDLB1!qrqK<Ku5Fm8Kp;Im!OC(@(+=vMu~>uI{hC-QXUN?ktQ!u)aDc>3fnsxiCEm zs?XQ(gM#jhR{V^I^x~nk&%FVhWIqR<O@_v@A(cr6CY+?r73`j<BH~Tu-ngOM{EI0T z`=ouL>)o$(m2<E~F2gbm&)w(OQ7`vz{oem{-VATo`BVRYuq0O`o=k+rv!!UX=@8~i zDIoNtB&RKWH40+G^ilQm_P=<q&(xQ8b8aS~e?|3Q^^zQT)y4@;ZuZ5w8ap{jeMt_i zh9q>)e#96058`?mDwmviI3L#>y+sp8RFqJLqZm$ly0-&IGdy_j=i+vq^$h=H&)MrT zEGtJolpWE=aF1Sbm2$nCPJB!>vEU!hhd8D)TT`k7C;i{Bj-kzeI+9rOSk^vlUSnB# z_;IHbtbMQ_6IYqC>FEeb8wA{L^Rq)+s&<sj2OqyWdTVD=<pV_)TV>20dL=KpvX<dl z43C<;s;cz<e8?@jMbF=@v-@;!KC~6yV*g(**eSAO9oVt$zdJwLw(^%oUBxGc^OaUq zE=W|dUAgzE^=AM1Sa_zMTF1^W|2cO)I#t$FwYdL-HP&>o>BMvfoUf-{I)5&f`xmb} zaJEc1_B-pVj9IpoZTVwHd||kC#)?YI8Eq$YO`C1$%LQ0<^BiqxzH7H(QV7;dpQP^3 zTkLLj4Z$ksQ*;J>Wn0H|#xk9(h8T=d3Z{#P4d+XO7NM2WO8TgzfgiXrT;$ob0PHTD zqt7P1u4<S(4~8c_qIFl^R)xCGgB|gY=<r?}MP>>iu-N<*O)kr<*xeKim$gsRf~=uc z!4DPyFMpo?Fo}i8!~QfVZ!Qnji{a~;mDFY@ik@8^DDI;af^N*790Lony-Nr_`Hi$z zV;1iAc|pD&_aJFMrBODS#mpC%lk`Vw=yZNEjP9<?-M-+5=bGM<E>HGw`$tEkZdon& zyjvt$>6nZWzW$v3Di3b8TQuliDCS(Y#gHJDul?|pXWZoa5%BPIot0Nzo>e<fs=m2t zwa(%XUU_j-MWRtZoA&y9R@*D|`b_G;!_;Pp?hl&>O|Kr2wiDlpd%P2TYP&=x4DSJ& zqgcM@k-NE?+TP;qYsoNbSa0rw)@aelMn#x+%o8M!H7U?X*%^)G6t53{xtDAspPP_x z?D}xPzy!bM{pKz*+inFV!<oxtxz3p)ZolO$XoKg(Y?~)}Z`}{3UTz|DWcq`o4Klv3 zEzey$W!Y}?^9|1|os}<i;5#q;Y_^xXShv@oJ}}FsY*$hT?)Kdu`rK|J8;nnJlKm;! z&ywdQsV`}pWppwOpShIl_3%^G)vJr)<AastTq+Su_W#Q1$=K)k2Cm7fr&w~l5)Lm$ zc)yC&D#(b7N`or~OmXY5E!}Tn#nJ209e9zfWwA<_TE{hO{Z5^VsnckA`?=^I99$Tp zf2#wV2kF?zuK80xW38dhII~_I^}GIgVim8swxb<u?<5<!$9+1+@kv>@O-<v-4*Yv? znq3OZA#*jdj!r$^M?5`!4t&}0oGNUW7wd{x?7JsT)am0YyNOIEH>!^A*^~$q7b;Lq zeMSE5<ODFSA4Kt(9QSPGmU7ck;dsmJ2>oYVj&)auaEx#~Ld|Rb;24G<NZ%;G#&pJ+ z9HGW%ipuL5R%h7$RA{*+!w1;0Cl)4R?OJ8pkREBfZCC>KFB(KYY#zbK&A(`y$8ypb zzH6fSFYa3N%jQ7th3B+Ld9z(>Neo8si=Yl6CSqTecr>A7sAzsKF@HJ^6`r}!{c0I@ z%}l3?={#K#jXGVD$%p5&`Du1B=re5rkt;gPuS+zto9i6{A1)w`40>kwu__#1CLW^S zZ#LOoVz@2o5H;U^)Ou!6FyscDp_#9ji3hP*MkeRa&=Q;_-rybrNp(nThDAeLP72vK zHjQtc9Rs;1B1zYy7W}1o*KNOEh{I1gF7$g>t~|jo9?N~4XlcMhJDuHOco6gHUB5K( zbD2fh+c1MZ-9A_RdrTBw`<g{}9c#4vm>q_$C-bRJDZ!{?29POhN$jE)p^o21B5ST7 zzA!)vH!hk9>+j2P+6Rw|b#EpCd*#kscYjSZto$MFX%N5p;zao3*$c#lu3T88gI%yk z6lT_B(LF1clrJ2#2wmrGrush~l?`$I<1=s97*?o`{o_mRJ~w-usI=cTuriHW#BvI4 zBqoCu#FF>slK0V)&wQRb4;1Bw-{R$VB%$OpQptOH$>&0n&toN@yA~^Nvh!OIfmti} zlY5uDLcjqRO!*Z^K3e}Gp=#stpM@o)+GCeR$e20!sPYBrx6BdBKlZ_w9;3;u9u`nz zW`Y>tLry)@fT^d(VBe5&<gv_D(MZEM)N-6oisu?bZoVmg!R_Rm^)I@RwfT&-8Bow2 z&902c;Q8T1cbOwn)@G+Eqlx_)Eu8b(3FGeC6Z;+(_@1@@n6+Ox*BFnocHXmgjt%m_ zZA0JD-()xK6l8|$4qD^%T{WB>!)Xi$Fr3G9GMSDd?4~Y>HFR$?V4RU0_%WQra5TfN z50~&Kk9R|lOb>`)7#W_zaF*T@@_6qE%3HAK{0yJ_7fa7;CU2`(vA8|cK=of7%<$mn zzla{&yWcIgE0{B^#;`WSQUT?pE+H5eZ|y?9%qu4i3@>GPn?nxw>{JxA?b<-sF#Lq! zUfCPy%+gh~>k3D>DAvFLhUFQ)#<0=3o_IHrts|ddg+myA!0;4?{R79LQB@2t_eC3L zGkl6+d4@%%5qNoAe{vya1NoFX8?Q}t=5~yHOJ;_7W1yoJ@wwba?k$;*_ZEkd->!v3 zwbw`tn9!ZGUNHb-M59pLt2?n=))$(l=-|_-UpcMm&fwy2h|MjoMBdX59*k+BX3SRu z&Q5{6r(KY`<&meyM#DP2YI<DZ3y~i_4w~&+X<Wk>(&dZ@qBm7iy&xm7sxkt4pqZ-A z?E_gq^ue<EE<Im93JxFnL;{~lqn<hQr{rH`yI)s)?&%D-pJb9*TD|f24=cFjSVoHa z4aY`T7K0^LpM<wsqeEvyFyEEJ@)u6U5o;BIrr+h<!rgKDT{#%{(38}@2*Kts78gxb zn>1O^#a3fV%vZ#d&2b}e8T$|L*j5hq5AuLr%um#qpB!R%EyKDDzYjEn-OQJUF<)wB zIGf?`J8QUEi8W*!^Pl8DzC^MZPGz{?!zElL^PlO=f6N)K`WH{vTS5;o|GCI~$%o;h zf3fDgX8M)+QULRxcHG2p5W};c|DuY_e^i<OcrvWPu)-f-qIa49jQQhB9e69lQ|xp2 zHs(LOm@m2ii}x_>Rl16NUhW95nE$vl+`{k&hME7sSLQzxnEx=p0-dCD#EIegf#cvo zWehLP{3n><>kR+;tc}j55n#-GDWCb$vnBH(koimt^O;#;-eAal$(#Aox7697%zSJE z^RY!Db}zvE$By|=w_YP*$oTG@i1`)sAK1+NN16Fg?Gzo*W`1SF{3_#V7l>j0Ba=TG zV#c(PyS^J)9HS}l*{+p%Gymzq{AaITHA!K9rNaE`!GUJd?mugo|CDd4BpS@GOqgFK zJ(Gsc%zxf9|4C}TOA47^l`y|@)#?o@KdqpM`A@Q6SCF6P3@eylEpD|2j`>e-=0D7@ z;4$;7Qs!6Q;qEY*`HwvFADLTIq1~^Xm|s1%o(n(z^`9FrLf{AUt2E|US#cvE>|bB{ zcqM$qKZ@~qW0x~k5eIV9UPNG`)NZ<b>snG<DurgZTv6KDiz=xN!Yz|+u-VBUx<&V+ zzkD9hJN4JOt+f_(;@&vyGOiPR*=-J!6j*H258Yvyv@JMGUnTld_es&^x$xrr1#aFQ zX$ZXK24Cct5U&qv@LYX6X&decZrdy%a^`k2#KHg$)M`PUY9LKF8U;6A*n)ewFSRNh z0H4L3AgGf*HfXBD+ev5Gx;t-7>UV_X)?Xzt>C>?wKA*&zXhUWnO+3ru@xI{Jk)!5O zSk<qUdt@?~+>2j~D<AeIwi_IvYS3qHLK(|*v1L4LZM@5!xuOXgn&$8<tBoF5DG$3x zTf@xjWz=??7QCJ$CZ{NSkLTEjT$MXWR_$Dfn`U(-*G<;&Z>ELge8XHC<)}=Tx&`5R z<5P6^#dmah=PoF_ayS-#{7O}0rSNsMH7>U3jYkwdi_?csz<CEXaJFr=IM8U~UszJ- z+(lI!VYP?c&2d1#_&e0BSr%sYC#d@L8qJC|gQ{jNG<xpMeJ_rKk5yyn95s0ozAp?+ zwfE4Ovfl`-o&r-?UX-_~?}*B<*<flinhRWP3bS3b0XEf;xlzO5p@|giI3WvbDyD+9 ztqd8sS{|}@TSCF6OVpFa<lfSDoaA(#g&}?wM6uEUWuxxVByWA3xNIj?tqsJDd1-W| z<96EiF&y_zm!@@^ebH`0S3EboJ3h}3z`0ki@!p$isf)r;+#PhO>hd*PeEdug%h!#< z(7~$orkO78Kflp-bN6wWRBePxmLs^P0rqH`s)6rAazvxYPsIFnqw%}vU}~hUi%Rqi z_1C{i)l1#+$$K>{+T>yP&zs5EiH+Z}&<&!)(_L_7*g4K{mO4GFo`4bS{dto!Qt;!7 zH@dGK2*!IplkMAj{#D<(uAVp8lmxNOw&GC=pUJzOJ|OeCjF;4peRi0r{#<|sC&!XW zohF0*YH7@1v2Utb?)B~Q-Lbjy8BsLzBe&N?VBDJ!(qpX=+~aj|h3f;-iCpG3+Q;Ez zPeLXeFN8KTBl@xDUQ!e`4Vt<>;?3*XdgpbX@b-BpYNFE_&c2)jLmMWO*FCO~QH3tx z@p~CD@23b?yE=n>*S+LMo+4ze(1Y4zCUDR8JV|cU2Jd(_Z-%`i_kT#kv=LTNv$&1? zR!HY%ugnGGD-X%Ep%eM&pEE(a=qEY5<O10{Xa>tYca+>zzD~05%!ldEs=250MB)`Q z<S;eG3yVkJr8AWqsQm`!s}?S7zf&eno+^iRmI~N&o(4Y9)yB3*t@N&iAzm}r#Br^O zsM%V}*Br{==TtAk*rKJ>#^VVedd37~GaTsqTuaQD*GTSut|2a`C*TQxHFEuSPuwtS z0xG`pgP`x1Nwi`L4Kf-I*+)$weZe%UGP5(3wYq~|z&IjVFR4E=Mi2O6d#F(KB3pWn z!!Ng9k#h<+iMswMbl%lU#ydYG7jNY84hl11!8I9ZJfcGjUi!m=J@?4}vU%W?&cr4^ z5#GFO77r5f+@oztP^>hD^O2FI_B|t^&VLhK((f=?&(`GDXbr<g^-A(;ZEqa9-xBq^ zU7^7#HMF^}8)_ES)ARG|h|}VU_(^&v(J0pk>#de})-Ht%W&35if49MeZm;OokP;f= z;flQ;^K@nFB{G$*iCMXBZ&ht*KhVo}LeuOWT-@t^m^o!MYRnjjo0Bil=IQ|`Ya+tQ z;tKMmRTUp@ohaVGo(rTc^G3ZuJG`2nK-<#wF^$c~!6Rfq9It`>_cd{jL=PGRozOeG zhQ97Q8)a((>BMwPoRGDWj&~f0qHpXu+`HFwf>CEOxTTO7&6tV%OHPoN{S)B!BVD?v zIEPcXGYRBD9p_!z%2nQtguuvUBx-^I`5m|rvb2logDt+Cr;|Rkcn^eonYHBPz9d+& zHG#WUe~6Rp&!UHFSbj|h4EuM%v*bRVo74k}j4V;IpUqxM;WoBM30_adA?Iu8ldFqJ z?sz{O`?Hxo4lSmE6_YVL{{@XMo<_9J&cxq+8z?@_p&mo0qxug`*te~o4E%12Qw`$D zm2@90O1n)DX&S<hyZ2cf-M+}(-b>s^dZC5OEjmB{2Z{Hxhqh6T)TBTOTxNB}&vyEF zVO$qt+&>Y2tV-p(KlFlblONGTm`-}%vxMSz+HhoT39+}{z-2kHy<P#gMQ3FPV`jY} z3~VZ=?Q2fMhjhn5#gA#v-`SjO?_{hQBE?PB91BkUyJ7kBbW(W51=dF^f$X#>B56ZV z>Qd2-x$HS+i88$q;D9fVydeK%w$ix;)>uolP};4G9?pL)9@UtPo!_y|EhQsB=e#!V zsn}1POJ=~&!g`{UzLiLx??8{?q?2nr=&5bvi){_D-i`eq`B6`!t(|ds(I<L<UZGz< zd19Ztd*~6zhm<SLrB__TF=66TzO_IToSs_Xs&}V}PR2}FJNOY%$Vwpd%j&6Tgg%L? zo%2_pC(Sk`*DT^eX;KB>Ls1ho%vl_?pD$>&zBhPWe?vDK%p}40M}hqXE%1BdLtOd| z!6Ul8Q8V>EUH*PJ>bZ7?;8&k%WXdFvn$;P1DlBKYguNm0*n85sbQC#uwva2Zj)&$O zL+P{q=GfI+5#GOVr9(GzI6mh$?d18K`ff3W#oLBqx?u=;Q9B=+)|8Q?&t61yQJZ`D zFb*CMccx)??6E?r3%ojWl0IEC3AI)>)6xDX=%I$mIHUe4HEXP*mZu%CuW1)peN0R} z!*yWQ&=J_YYCqXp=LT8Re~}^<SA4d&x9D+30w`D;QeU>#>f5L_)PA%E@o1O_`x`D$ z?@J@d$^Et@Q#Kx>0=Do$i7xOUT@#k>6^pVyi~(n}KG0{}2`*E4D(va>gW4BH6OH8Y z(0igHdW_geeycQBWm_g=m0=Dq-#Qa|&H7H}amP9NPcz}46>rHkVoQ21WAUdp^uw<& zc8k_{SVMP*!8qs1c;cVdQ#}7#66)ri;T6^g!=QlEq}IxcKQhT5G`rs;ku5{W_Lt6Z zVp|`qo3TQ?R?!?9Rt`h+DtnfPRGr59#9;qIC)zw@DqOVf3I^g4c8%$Nu%@Yrd^pyh zNOIr`!!YQ-c?I347(f%vJlGmqS$NSllg?o8_A1xKfzkjwD#?L253)S&O*}2bk#w{E zbQl=kLRNQ=rjooTYvKs*m%h_3ZyTr-Hwuof`bbVazfUE3ujDL&9MkV~EWDu8Ub%p_ z@q3aiEv9c2v|+ltDW1G>lgKaK&K-Y~fSNj8$WYmA-r`aME>q}6^e5>+wz@H%EVxgs z4-7!3JAj?<^q>l!6R^-w6PNwGz(=Y3;uY|uqOT8W)T{s;Td{{8c(9pP51)<hzjEnT zg(Gy~h-mC&n#{>}PNiA?L8#w!l~hmYV>j3<8cTW>a(8ybP?gz}*?aWakZE{_q&+O4 zUUO!`{`Hk)Q`=$k=KKgy`=tc|A8(VeCTkeEzZ+Pz42A<!RuU)EVKAV<4s_^l;*iuE zT84}OhYbVh)4PM=c%%~;z3WTI?$v>Hxk{k5W)h@sm`(<VxZs?qH{^ZnDY9($1Z+sM z<cfmW+A>}C4Bclx)m$|l;|j;1yo(;hPgudf|7A%Py3PS-?fSp;C9ijq*D}fLl;rhA zl5ZtB_J8rJB!5csq$CGQa-AfPN%D*&CrHjmN#B#4`;zlfa(+q97jDQ>s?|M?yboE3 zqjiVi8V_SQrGJoU?jC`4^?I=TR0c_XI~vFB=nb95IT6WmKel=zZr*Z?4(7ko#O_I0 z-@TFBs5_5e^=lzkcP%2uS%KnenOJJjtcRVyayagLJia%wAc6P&MUp-v`JY7cKbxd} zqTw7|p_f6gJt(3-)`VhO*-Gx=@iHp;Taq>`cODL}&iy3mDV=b12q6t=17UEs9i~+j zaCcvpl66j@cxb5`e0t|V=FL<@$$LG?d%)Hghsc6@wvOL;54|y{E3BK~3e$I5(aMN5 zqJV#5VTQIhy~UpKmubxbr`N6AQT8AHnX^6Y3s%Il^~QM2vzT1BH$v&tWASYHdC{Us z-M_HPyv`VQwHu}e55QjaGIYLmBBmK^;cG0dfmmvS*MTaMHFE%r%<Bu)OCOR}>50IT zcU+l#PjCpn&Kdq*Nvy+IPNJ!ss#GVYlMmI4z-QS2kRCjQ4oD&pdF&;r*Bwsuw)wyW zyUTpp+5wQU!vU7<4<Z(9>HMbq{QxhA((BpmzTaOBuKJAS;)X7QA!-|mf5v{w1%^Uc z+)%O~Mbs`o7L?_`@!czXpr@P>q<5Caz+)V$o-%^o37zQsK|R>I=JnLKVGQ=XlZX># z4eX+}%F<M_5T86g#!Y!!K(Eaij0*k<qON@i_E~<PhODh8Rl6rZMoR@f;9f)qhs^}j z!&+?p{!^0tp2fx<rHKE~%cN!lfpsryX#&gV7^<KK*;>Z<sHPV@3~DB?zJ;Me4+oMs zEuCmiiN#%Z%H#~o1-@iY0ev-mFF!eCAuKlZL$WZvs@tKD<a>`m9BOt=ba!Db891+n zj@@U*mYDc~WIK}f->T^g)0K2NpASy#ez_}X9ly(eZ{O!I;3`oWXozRl4S*+UKS|TJ zZg?$qFg)I53x@IIXy2OyL1T#xgpFE5s%`rNw;`WQn8fmI_tu5|UXMtNr4?v@=nBKe zeI-+FIf7C712W2WhuwLbSh&zRh$zp=<%-i2Va?|!oK@CgKC?6d`W;oGUSVnU?(Q%+ z@Y0k1Fa5F8jOnR=f}!f&F)DfNK!>|@byj~kW@mu)D?ZW#U0aBi4ME#mx;RbyE0MC- z!v!o(#0-`3#7uq`?)%aMXK!$%Q{^UN-oR(HZ>%m}9At=I`&e9tS$%QUn(kOP*c5{w zkEdd`mUUj`9eU$M8eI@E6Ls!pk>$^V&@*BMxn3g&M;3@MRdk<Ruc+e-hb~6B+o^Q+ zt8DIE_XNxg>PsJ2WzhFOhoJUC6O7n17|gX($*O(k;FE6yH$z<MMV~<s_u2+R@9EL( z=po=`H5eY$ZX{Ayhr*2bo^Vdz5$DawAS?U~L1wlgRuo<&lP)3mZAS>^1y|60W6x0Y zszIp3*0`;&%b{u4tZ}W39=6Aj+O#MNH43b#p;(jcomxR<wH)yu4>e4R+C!y{9T0!% zVC{ebr1Qto_&%*S1{S^MdVL%FSN-edN~k|c19I#%QA<$)=jExh_Yt~(>F@froL_Ad z1GaO*>4w*H#GYs4LG!u|)zWJvXM9Hk@7qAeEo~)kbToU8dWUplaW-bE=%NCYa*1!w zl3Sa+aKXwVYO<gQ^o+SlGqr5+81D|>e;lCGm7A&Kf?zmOpGKmZ){vCBk&s38=+NG2 z<hE=eOjS?dmmjX7YU={vzWYn=Q{qi}?s_CYtcx)kRuhEWJTik@MR!*P;GLeUX@=}p zYIHaV(-Zd**U56!Y(f|&l<Z`2JSK9zeIil6^EP5#V#N<oi2AEueQpR{b@2<4n>Y>K z4jdvGOBG4E!@|GxbyiFv$6k2Dv4UpWsI3THS~rsg{l}wpZ*yoVw+6REzeMu-PT(|i zGl`t5jBXRzx}|J;ykstegOf_g?Lu30*6W4U6>4NYcZYV-n2Vt$14xC=Q+hhk51S_* zWd9zG=#RX3bZf}v#2O>0+sioovU~&A^=ciL^EnaM*2Qz3t7^Eb#z|<#XK;y%7l=l4 z5Za_H<BmS5A@^U+N7vOX=Y%nfu@I?+2{TIBK9NyuZ@uDQSW>5|uOsB_HiXlbJ^3*c zoS|^O9t`pBC2pD=2~Q#eh}l{%a>btgf4()3e3<M_CiGhblk5l6?r~w{XZRv8nW;s; zO^haM^PQltVn6gcZOLEaC&B40J#m1_ce^9*TS=+KLb|Sh2&}2O#h;xMNs>g-EH-cu zzbU<#o3J$rVvgS?#d#^TTQ472`8JHUEzpNO2_mqW=tVUGv|-*qBia5Do^CR80(*~6 zaC2xG?J~$2)^_a#*Ir9wmAnhYRPH6Y$scIf)o##f(taYTBYEt-s4+P0lnxA9q)0q7 z+%PYv2kdX+xozS&<j<LsAKZQ3^cCBirGA`Ro8F=~G<|WI>MpiN52<W;0@l>2lbELc zyhlqn*rvCf`1*~5C22a)U4J}v(j3M1zI-J8czg8MdPQFETv7Goc09rfYufm;js9PR zy?H!U-TVKKl#*l$MH5nzN`yFjU5N})38^GQ$*h!=S%XURD9xob(4aykXRk}MXrAYp zq<M~}-*t-5+kHRozQ6yTkM&sg*=Oz7TF%~kt>-#&(FR?cf9GaXtWbOYN?x35h@W@b z;o>qScE7CqKlnmG51dNQow{W&d6Ssoe3@?o`D_ctW`p-KIWI?ucWMbiavzzdVgQcT zelNVx?`UUtaT0z~-^tH?IKV~*he5L`(X3tddhto8WYFr=kxy}A5Hh@uZ!dq&&VFx= z#n+11n=XLevOD5ZA3L#ih4VkSs!J8mcG1K$<QG`;{t_S9q8}87sG{OpA090?88=s@ zap%AYwxQV+9MN?UTWDFxZ+1V&YZi{gL6)0@TXRR^Gd(5j+hwgZye=A(;-oyJS`mA* z_uSIT3U|b`gq(do_^r2B$@P7ly;6-vIp<`d`Bn$8x^kAUn<WpI54DBmTbkj}zU@F` zbQ1sBdm5^|&ll_HzUopJav)4P#<e=s3e``eF>K`lb_BOGCH=1WUYGV8*^$d%>Q2J> zJ;DX6*Pa;A_Z=T+m(6?atdKa~4##P)F0i-l%b1O8ORR0pAU@F&{acFCh^c*X=l0f^ zm8~!GU0&!OWdr)@mZGw`Ihf5gg4wf8czG&->$3M;{S`pO(wA(e&SQS>xE&-7QiR7# z9&;993-UjjLQ+Z{cWEL(ZT>6fZ!U)$Ev><6NG<Cf+yu+ydP5cMVJNrj0e|4$3pBmk zz~bIjeCJOSc=lEo$hm|A$hmZvoJ%{bOwgL#N-+wnq#LXT;~a7>El=4a$r`ARSDXHE zF|~Rc#AME;*gwuCCUY*8k#or`Bab)ul*qG$GSAW#@+{5MoWL6#N?V3R<05h>?IefN z%ttPmze@`X$(6KVn?HU_KgrjTLrI}8tuZFIk|nK+yYM=fH8_;WmBbocNsD(b5RJ)| zG?rXRU0yB|dyx~#ft*O=+r1KHt|Z;SUwqkz1LBZ+htmCJ8@LuZk$R95iQGrL!F@zd zB;Mden)f!3_as-+F>)nYjzO`(iA265Z15eC*9aTDM&vuf2Hz2RkWl79Dj^RNIgU`3 z97plwI3o8Ee%rN>yOaCq&h#X_Opc>8avU|in1n0IeUw4&qwYOF@*46T1(NS5-QWwC zd5wnbJ0aPWIg4wP@96k#Z(-xH)x5p&7_2^ffoUe>^GI?W`I6%(!RG<5a_NZc$bHmd zQxP9Wj-#vOIO@>-0god0Q4YC}$Z>=Xjw5m(VT1d~+o_nh&Iv+g@*SxZuNGy#qpnvY z1#%qWhYkVU%YVL|;of-MMDC-F<?BnxafIE;ag<DsBXS>M6LKF7C-)IKj?ngCN9j^> z9FhA7%eUE-sFVB1a(yZ`IF87DgbnT^avWiU<A~fx*x){L>_~GLcde7Ge4QiiH%LSO z%Yq~=X}dVS>221Fd`H*Gccfje#-47}gnfU!Mp$0&H6niz9<BEmsU-O0r+Tju`HpZJ zJxf$2-;sGyC@vtckuG_S<n9i~edIM-KwhKhww0m-d5sduYqa!KGT%<mY44NQsM~}2 zyd`;!+Va6rdFU!{Ltdj*<TX0F{tB0QjaHG@XoRl<_N(_7^}1Eb$CB4bpS(s{12r+Z zq&FTX-_cv2Pki`xcQpOuHNsW<6fuOnMg#NqavSm*%_XmqU!;_KlfURO`HMUc<nrO< zH3}oI(anx|{3`j5dXw*{rjp?cavAj|mr=?PQ`|$2BVBSFCHNZPoo^B_B$v^zy-lz= zt+U%sj-&kdclbo|8iilgqu<_AK8U<VPJg^cID@=KuPlFijqupWYf{Up-%5VEujVt! zYve#)qkFga@x7l%!yED%>1zz;eaLI1c(^6>JdnW;k=JN4d5uQsT;nszYcyiHIy<I0 zmdm_G&g3;J^lXK1rVIz)b-%qvJea&j0kdZa>s(r5B)N<tbL8-=S3Z|Hjz*B<h+IZ! zp4s8I%V?p|XuMzVI9g&Hj+@DAbnTDV2;Y;}D2%*DoxXP!3dn2pl)OfZ?yh0O>Rm<& z8yr~QddJbM{^_j2W%ShEj|GwAD2g0M<+*D7C%KF)$z^or`8QGKIO;@>Bk~&Y!S!Av z@)yx_@<09}aXhWDBCpX#@)}(W-p@6@t>-r6JDND{BHu<{BUSPmE$&~&WnQC1@)}k6 zER?RU_Zq3|&6CRfMY`lKYV0*?>^rK66l@#3My@9=*)@2Lo}WD`ZSWd}ueA~zyhcg1 z=ipWH8tFPq{?Qj2_mK)Y1KP%;IowoN1J^}q;yjO*xXsK5-0L}qxN-T335lZjDotEL zjw2a2_>LONW$vTKV?KF}n9OU$$!kRZB9Qru;{W)I{_lUm@ncFL^B0Z!<1hNZal7$& zPA(&`AeT`Txr`1=U04!1i@J|w<mp)@e5!XDHJ9FI&uI<W-extdhhaIJz2uLlXv2=X zOy)0ILH;7Uri$Q1UZdIMH6nizdsFW(B2N*Md5X4>r>K{+vDn}vGOn-^gX=v-jdQ4P zsEac1&~@?-k&g(M#{=q;kLYjxy74&BxR2+z_QXBpBbq=yq8N{1m_**8ndBYX)^#{; zB_B~W`G}0=hvWK_tx&&$JVl8<=t&NuWO5KKPW8f*8(ZQ*auan_v&D_%APOW0QB`&y z%q2I`4ssJUYtkAm$U)@a-W{H0>tT0t6P-zsfY5sdk0S?B0y&7%lQVfpy_;zC*H=<q zau5wA2hot1+PtRc3f|diGPupCwaX$0k%zS-d^xy8Qb2B^ZsaEFu0)=W)IUC=Q(a8a z=F1-+QRC|(A$MISd50d5cWCvd8Db0a5v?X4(e`bD{77H|v~1!p+~2%UlsSm33_A-( z)!+H741ah$cB8Ze<5&iHhrUPO<j)?bVVZn_wB_q<QgiYSK4E3jpaXf*O>SYBBrW47 zYTNPT4Sx7G=@ox5!js3H3B-L5Kd_x=>_ll-fAmZL#tu$gBW|f^juvA_!uY~@b{7vu ziDl}MD8IUlw@~~b)tDEB3nj<@;Tme}AhMt4#9QnN!=r6QE*9H!Rj&v%Ry@cpG(Yhl z+lS#$^)0;Oxf)s{%{R(h%`dGwFWpBzxT#CJNu7Kr^3)~q5S!#FTv&OCo3D2VpLd^G zcK$k1hrB};f4oCtgLjBLLSlnQNagVvQRWv~NPeM^OfN2T3Uwx@(3ry`uqSzhZjeWa z_JhX@oqQm6Uy<#D(L;GNatg6OP9d?uDRh6J3oh6D;}rV!qdzvdgFfau;?H`gkm@-X zlp5$rhn(sFx#z6-6LJc@C8yAwZiBfQ`GSU#FKEC-JN~IE9?F}x;ga4qd}3J=<m_E8 z^9A7t@&!F6Ul2Khu)z^T?jV%8gLKFpM2;X@i1Wu0MD8GLa0fL$XYvK{247I)G2AOZ zPYfn6P#$@KHr_MFndJZZMgE_-zQ&k9o*%9GR@}?IH@+kP&rS0GkQWI1kryb7yg)WZ z${0ZYpBnQ2?08S_6zlyz=Z=i$S4zj@wh6~r>sDKN2>E<6e~n<i_WeXR^8DzL=ZE)o zllCW{&&Kw&|FA|&472xvJ>4?Ic|TfU&{i*)*uD!NVc~-|b6bL*wXe|F=hN8Fb9aO_ zUqs#>)6=tfhqv9ivHB!P*_g?@X>0QxTG5dAYd_bCn9l9mL_+`T>v>~`Ph+=_uiICC zJ(m7YDLe9rR6m?zB?qOB`NELkc+7YaB&>3r#CGN+;fY7Fk}hd>Y_mrw>Uyo^g-_P8 ztKPm?y6^^HX}FP`@On7-krm$XIlvyI$m9G=LvZnpwg2$>Ok3j)9+4A83Hd})-x+`j z`F#Az=hN8p)7as&+)tIu+&)(1_Sq1BLU>IM9}jZ)G<N%R56oq2$mjEdd_Ikj-`MBV z*z?oa;nQhmh*&~yA0=}8EYY9MWj>z+<nwuR#vFUm`_$(l8f@#)j(COKJ|4<>lC72A zm_k0EYvl8(+cloNq<?%q#=EU?H~D<Nk1iHAcAbI|<nWP_!>7si!FZS4K9L2sCFJwL z$D0>RR+G<XXx(PMlYBmh<$+&I7w`!Ad_u_Qv+TK(_&g;I0&I=MqpIzA%A?UxL2jQ| ztFPiO^7-gT8?!3~@7XEx`D`Sg4>^3G!zV|UOAep2<reUs+&=o`_PIA;8khNe;>hPC z^e^P$<nx(CKA(N7S8`MG`Mj~$w9OllE65x^{pU|CIj6r$khy(MXMVMNF<l<i&--ED zQG=w3_YGjiz5Y0OaCfG(BLFttB=5wLpQ72>NI2K?6p!27L$K{I2t=>e*!19ZKI~!| zd~4+@T~nhe_OD5WJaYRuklTlRJ}`enYnDnrpLS6rA%Q$UE6MW{x4Ro0CZCTT`F!R{ zm0>Y?e)f{*XI0urmgJFuuTygWah%4-w>v72HKktgJw2YsI^Ln!i~&<}_?W+Mg@@z4 z!6hw0yuDx?zN~ltJa<Wi@oC}0T-~9};!6>GSMTsiw=$F#liSB~&J@01Q2`>z`7?{0 zKQn(#!?xt}X;zfXXssotlIJJybEVxDm6QAtxqXI`+oyx>6RFJSbD4ZT*Ss>N3Ud?S z0(pLvwxpo8)lYHLs6fHPD-Em2?GxsyDLlEkln0Z~r;>a=j;Y2{ndj#Od49-I13wd+ z3k%5YLk=HULJpt!J4GU`bp;1<`xKMg=Z8%Y_>uGH;LC&3?A#4(B>8;0lFw)IhC58= z`I$qWpXh7ptUbAXI*{APxzA4imE1l><o222;)Wfl&ov{5&$D^H7(;HK0CM|$;jeiV zIe*TP^T+Sf88+j61TJmrBs_UE6sDZl!dVu>Ma5D6@Y3`<AKPcF&_l19S$7OZ$(&qi zzEJ?ESeEjAKH02r%RoWq`B@da^~ky0R#M5nRBS??A6j#YIrVOz4<EmAZ*u;4kn^Ya zD?{-Wd43eg^Rw(KXLHH(^Lke=Rx0s>H{|*0H`PFL>sl<{BF|4J^89pYk^;V6^>|S4 z8PeS2)1daJC9m|e=8fB=aa$c((;OC%!^h^2!-tuW!zYg%J_|NKE|GbAvX7zNq27C# z9Qk|}G`%i;FyJVUB8Sfna`-&y{DtS%JABg4r^1<2^3nmfPKYB`q(c6!0IAZeYhq(B zEAju`%QzlL#R)piq=I-()FWrY>{*{m<Tl+BvlEZ9kPI6r<ytV-xPVn%e!)Im@qmKC zhgoUdCwA(oJ8V31i}mYb138;i;7w9Hw!5mBl?FxPiPv`Q@yZh{D>oE1UemjuQ>9Ev zB^(0}sj`*Y2WijjD2&!mLR04-!r8-Zne;^>nm3hWBd51#P79K-GG2iliB@LM7bjuq z#HMVgu@ZABOA_buFr4({GPh`wEWVl*hHg)<@ap$TVxN^^Xt3c54?mP7T3rZ3)wP%T z;IstLOnEI<KXu^K>L~BIhWw?98NW9s0R}j<<LP1#t~4wG)*4(B9kPb-tS{v3KJrG` zbu|)nn%rVVSzbK1Gzgr(on<?d-1u_&@vx<&fcdz~v8juqVVaPDLsE2^b5C<NNOc<C z+|Yqt2p!2LO`V44L))<Y+2p<+nSdi!=`yd}o(w~iU}S_cUw5DxxfxTS&-asJnAr=_ z;cGIiyHX)eZ1YCEKPw6H9<|`vZ<_EUEv_;L;QZA=Z<z7(A`9Gqlo#ythNK76aP`(> zf-*+2f%B(fRnvT7{+Bq`Z&C`3`y~}ejJPePPNY6+MdO(FBXN{_5>9KX#bRoIlBYHa zvlnVHPipH&<8@%n&i+t6h<s^>6+y9y6U@&)!Uk?gfvpuM#prz}#K4s)&?)e=Sn=_s zxZbzCU|c5f(}_v=pco2<*YnvQ9tC5QPK$wMsVH1`FBn(PZ7w7h9=&7?&3X-htMY3K z{kyBf*}I<bWAtZ>VB(X+vFr0JA5onbJ!!2jty!Ktd!1CtL$~CWM+zp~Xw7vdw-BY6 zgndG-`LYXdqzSZUdGwXhQlF_kB<(leWRt3b@O{1~@1VAd>7Aa8+ZKEkiFpGXZoJ7S z)YtjAXdO$O6N|52j}YE1TF2vwk$Cs_G)M{TDAoCFT2gu=8P50X#I<~j?C^dPw7qG` z@7{kdef22~_I-<!UJTQc<mGK(0sSIy^77eiN8Sc5<2Yia+BCTGYp`^&&-)U?FUeq8 zrNbY;>@1YxR<<_V0ow+*hKsnBuO@CooT0v$#QRQIeM22)t1o5(@pIx{be#PQ-J~h1 zZ|zKJ&v@e&)#9esTLigl$uRJ<JpaC5D%en+OZo277lqI57N&<Vy_n5B(ku#YWrXmS z6F2kW#Itf|@HwYiVU4PrjA{R2x}PF`_#zF~F550WW)vpTPfLR@&jQ4YBfd$x?@a>t zOBtd^P*3*0OFU@acqiH)^kZQ=3koL9xX$%s!+x(-kErLhu_=(}uENj#Y$7hFx#dgy z=wX6ZzBsxp5T5zH;s^CUh+&I{04nQX%Eph9*ft)peQ0aE^U#R7UhsjuOAmQgNDj-n z>Iyecf9J7JOW2W}4pe^(*IB9uFFskp#NEZ*PQNW|a?mT(+j53A^N0ksTm3CQXP=>c zk|RONlhFLsba8t`Pu3+m9#6LVDeltqX8m4TqgwM4?lMmY3I^DtLG1{x__YJPe3yiC z3styNc%|TD<A?*Ue&l=R-eKRaCSxMC?XCk-A@`~)UZ(SjqVpMY!3WpSc`l{%?6M#Q zAJes{P}?F@%cWphGaa6Mu%poSbTVc>@61mQj<*}TVF-5ps*PF`UrNr`4aN2;tx;#D z5gT}N5c;2Jhl5`27H|6m;f|Xx_=F|TMcKOB9V0v8OS)HY%)>@y^!YqLh50JQ!#wlp zmK%u!h-a;v!=F91#$Hd2K;dl~`0g&0Zo8FZJ4rDG=Ll*%wO5o-MSVmyGDG?z&dT=l z*EAfw&PUoI^hU|u7in0zW4rWjyD-V#cWF3b#t!MC`-@8`|EM0*QEH>zqr|K>4fQs; zNgXJAlrg+}%w4Lz|GC}%RPw1r1d27*-y|hjU2J<cD--j`iMTCfg2c(&lP{f>h;ewt zu63v@zw$E?*R1GRGQ$6~IFH5zCAD_KhO6IrV7@=v`#qH0+x3-e><Ylyes2q_z8lbd z%z=0#srJZ=H3m5Q$UwZ7+w;gGn#caOuM;XQJyg;m$N=T42jYmOHB!xt&-@+);?5{j zvB&H$-10^MI$Up2BINt>_d1C<WwEPN*KGvX8jy%TOMY568+cZ<C{9I-{KO-z49|*L z#6MoAp@-WM$&wXCN74=_qmiZ|vwYV<x^H<BUK${<c~fnq4RtE1POGpGjFsMJ?{sfT z`)B##>^ymxe*C*MGR76>>}wDA3)+eS#F@lq#IoyHGKa<jwS?b%g!p1T|5y2#7*|+B ze``yBs}&Xk!|Ahz(`OCI@`FkASy3mxOZ}+MTB`Gb>dZKt46ii|*_-zrr2CgAK{TE7 z=4m$4pRd#4!Js3O&$o+?(D_3?vEe!Tj_c;IYRZfmWyXWnA%5+s!nLC-1j+!sp0-13 z_<C{4t0fK)H|{H6_uv*AT<D4Ms?Bg$w;*yt=J55jIL`582|Jmw)^6AJcWgU3MW)~S zCYcaX&6<842QP<QlU#oCjOiH#!yAi*cAc)iV@WwdFnW_NJ9o2+1-J#l!VRsMTD!;W z{M)f0UwK>DKSvGnW)Fi@rQ3o>rYd}<{{@>jR*ToBw}Sm6z2Mqfd2Uv#3O@IT!Q4~L zc$iuxvxplD*0mbk@YyrgdO#2)&8v{6EUjU>)5bydsaMjvCNJ1`k8z;TV_`{igZFF| z&A;>Sy0)ae(|dNBxM%b_yPNwIaCb*P^oTnuQ7!ny)zc|UgSJSd{XX$va*<yQUSX$C zb<8{Yp{HCk_Uch3pW-|g$MyLpD7ii0+$I={WA6$Pp{>!}(G!b@o)-)s({J~5FVxU^ zA*wf5K{FR`%)&3?HXBv6SnY{>r&No*w?E~*EXSeFI5}Q0_8E_FI~F&eS|`0Q`3oPZ z7KjC-4oP?1{KCJz4#4=2OG^q*Dqygt9~Qk?UE)PNk9c#ueo5hTb4b^)ft|&oT_-<n z2=6r%%03L2Jh`q9!Gi~ZWnd>s%Vo5$b(A&ml^w;Ii3gd%w+Y}IeM5T8y@a(knE+ps zTOYFJ8EitqR1mFVY-e<w&w9?B3R@~Z+CIEBpH+v_Z*jjOySXdpu{A4co$mQ>lB(iT z7OWf%YvWyo6LBKjkQxmIhdxRtchrI_J3K&sp<Bt`;cda?mpgpg<6WY+vp4M@&<_>| z4Yl2Kp*IwDCP&yn+Ph)LQsMBAThbHvr$NhJQOsh+NwH{ZBA9zQvYa0q#ls$H(6Pf} zVbHG<>4SBH;9_-a$U76qpV+$5GqBdMM0qkl`f)2ey~Q6^k0|9+4y<R3Uj)FX=u+P1 zS`Keo;16%ykmrxzz{TtU*hXv2{iY5=<56l*loiV}Tf3o;e{1Ofa0;)!I}JOwk7jf8 zj*5>KBw|dRJu5WaB91mo!yTvB2`zq{llnWSVZhxbg7LB&(n*pxVxQSpd9S(<XyLSk zEwH-7)9XgVW=koXmQg1?`aT+}R$Ghr+TOO?D@}v5-@W;)aS|;4Xau#BuL-{t9BGZ8 z0ZjB+!e4#~ME{2;S#S3l;>VLwxa=#kNfD!Xv+t8}-mhr(Vt#=b@jMyd9a3QTw2Ih| z*PNYRGa4!#hKklvcUj4S5E!;Ik;UXlpzpBGu=c_s@#cMds94<vDpI}(wt11z%#>8* zpVav=i*Oijd5T4Qmk52Drb5}ZU4pIZL2>F2+N<N~XjXoql)oA1htGLF%NR!MDqBy) zg9VoC+=za>E-4AsC-xVT73WIQ`zK)ZhcK@5bUMrF7=n*85Ape$`&m?<Xw;aY!>vdC z6vq0eV3E}_(YlQ?bU#M(D~8?RUvj&`_<0QdtD5rhOLRc#iWRC_BOe?!4t$!u;9qC! zNNW#x!zx-g*lp1v{=Fg`K1?kX<+3ZdMW+-nEGQA%7QGYiXM{u3lgD_IY(1VoG8mN7 zGg<cjef;FcILJ7V&bGXGEUq@8`3MJ<A!hpy-glJ=48PD7=5H(Jc?Awomt_D?T_201 z&Q69|c3arUHR=+>ahKV^VWVK0bsirU_>I+F7!5UL+C06-IMz=khTNkWJXpwPs|+SV zO~Gr?UZVvw{4fo!9rNLiuj1K+s%dcEG*s-@#$4z+EE$45y7C$YQ}*698LnOXC~d;z z#N*e};Ong=(!<u?yfx+C)TuQKjZWZmhlhiSn9IsaW^y|dS6FDJ1_R6%@|9<34Wncf zz=S1y;H3K!+#UzZAMWKP=4ZL*{Za7p4d>`4LE)?#G#jQ1Q_IhD`KRVEWSkjfJQ^hG z)!4xu=M$`as{<Z9r3lxH^_XAuWGsKSlx5ocil@e>VejJJLg|t2U{kt|O)=;Rn`blw z;bd=^F!v`LsF}}7H->_${7hzju^mrHOvcXlGsF*i-cU$uxDUr)WM1S0U3_4MINbU= z>%CbMmelk|y=B>~jpr&h3Mb+dS4Vb!ZMbCqt2Ep`X`Mv+E)dSC&11?z<+N8+A9!PI z0wseM)4S}Ktc-pyD!=<7xD6M@1viuNmYY1cEKY#9xjCZTg<))AMmT!=9^gr(emsV_ z#pnZkAn~k+5m<F)F^}u9j13^ZOl;M28GClg6c;>n=F2p#A&&UheP`ZQ%NjN{kK>o; zeH7L9OogbXaols(M{zXqfiZKK-uM;bWuK{VmH2z;3bBkhM%w~D2G0?FyIH~2HZ&JB zbdLCvI6i&~ta*G<jL2Ke@`)cjxF~kcUCj8!IPi$?#hojH_#5J!xL&+zc@Wn>W(9XQ z&*UxM8RLbcR?s7RCLcn4GI%NLH!+v%%nQNo^{h+0<y#=XS9p}`S%hG-?}6N>=qUfu zCj`B_bi>deCwP>iF{T=I!y!LU@Sns!!gl^jXEJtUb0wO-VLY~Z0$#T3FFZ4i;8&W* zVyhi~Y)#Y-E;l3s-+zl?gPXMBUC+=x`j^9Og<BvwR%maa;9D&A<Nkh$!gw@!_Jnz~ z{2=WWG7<xpHixs<&DagYARM*l33IwTfW6c3!UK`bq2<giOlwsj?izlWty*@Rjq~-y z!OL&5b-T_plag`RiPjNpuKdoPPxQg;(-YX{Wfz!ZNjSR4_Y;=2{>ir5`r}9cNXf(6 z9M-=s2KOC5C$2qlij{2%#ZVOsUb^0rJs=0clX3}H-{Hna8pfcx+cJKy?1|lg%}J;; zO2QxR+AWQZi$fEIWjwyQ8lP&Gj3b9uh#N1D;!Vt^VxL%ZuDl6_-Vw>D>fef0`Rm}- zjDBdUSHu#C4d?YkFXHR3jB%GwKJRa021x8UJf9a5r>vL5qt7l2_fC!mZ{oeL{;<nQ zTdt?{oqc~Y3KpHP<*%B5XVZx_=Z|B@R@gu`&28OGyp6b!xJ5uai1M|CT=MOI_HPF^ z#8)(Suq|6g!|sO)FjHZuc#t@OxUS_;ak6<N3|CQP7PS3>8}Tz$MV3Om{GlTpRo=qg zyQ`uCagfRuzK;0gvq~1ZoBZuA^!uZ_lGzdWC4Td<ub^W$5jR~c<ooOT3YNrQt`>5$ zKD&8olS!D8CQ9Ra@8+tClTdMyC|y5#1dGTt$2OyTgO}0<c4U$<`h7HqJ?YC?c5qYl zx;+>Y)Fo`!?q(=i;SH9-yIJewB5%EV3?NHms=m4Wf<ibvD}KVdzn#L1Kl*|Ew9{<G z4@17EXBfP{t_5dqb>a8ueVm?=IxM%16TLk>LHl@LxDsi|9Wr}?+haRWo*O1+IGI7` z^KPI&Y68FYOBE{9MnZbH9-mvQ0G6u5;J#Bat;?xmc^&~^kg=7gWr!@Zy(1hjZh|YN zr&w(I5YRZ@1pV_?vf$Wm;C#*qxqKNrLC>xIV|$^F$10|f&=h{Gu)&(W&uPwQ9c$ak z6-A|EY>ECE_Qk9px(2Ajgz6kt@XQtKRGUH4v^LOg#2fzWr3oB$x5n&lEiCsJ^?`G` z?eWUE?v{f)4+4#DnkY~60H3Scz%}`<*fjej8(wP+0ariqwnp6{ZHWf7daI0;UMA2Y zT@e(ne&w0LV<hH90pPlLESIl1Wl^~!0Sd>5@)aE}v4J6Dq2h82n!mM+op0&{8t<3$ zss{t0$9*mEGZgqn4;PTP(}lG=GI;t!S5Us(3VL;0!vhBQfQjAAz^rEv-Zm~2Mz%Y{ zVph`s^qnq{tD*~)OVXf)_6T9o%FEIcx?foOY{QW;WhK(KtJC0u+5X}W3qr)7)6?Lz z`2vY+pE$9Wo|B6jYJ$<g5b1OWdj5d^f|uP$;oCYx%$`GQz2>fFix2nYmX(u0+I$If z9o`qadF8XYiXA|q*?7#W4rZ}!PO&_??>3pEZMP%B2o?_<i$zllC42h5VWl)Lw%whY zLy_JF*x$t&kDQ(>8M(C+&NpyDo2IiR+gEhN-Bf2+&whtzP@V5R2V?P@DR!&cw8fxV zgV4UaS;>nv`gpdx60X^)#lBhk;GlV}@xJ*EiN<p;T(oR5OpeWD22nH*wG%y0-5o95 z-WnskzcLYqOj*Zz-!bRjYag)QIk6={ZXx(&&IuN1xt}|A8;#16Di$>U0N*s<6ORYH zWefZMJTkudSPYr6mMM+Vz%#=fP~(!wmR{1t$u_p=cWob=VAK<}XLiAm8&%9GSO+ED zOi?j%JKJ-lBMy1p7YAKk#rS12bnVgu+nUPp&D~vK!U%mZJM@K{`}Bl9hgCqY*HJz% zu9e*d&1l%Ce2~xlaGJ%99R-iXOMJ*}XDHwDj(H7{N5>V8aIfSH`^vMKw|`ffTi+X1 z)poMi);-X-)C5C>Z;Y?a;U=C#@t63XJ&IE)92pXXv-&p$Mfv97-q94bK?7QHWq4QK z9>0g`u*6NY50uGpJgI8WltgvNzvGVPLAm0Sv#;3w!$Fu~F^E5}$!CL=BXJ$Mss_zS zEZo>?Y>7(+?e%tbg>*!|hB!NPJ!{$26yFq>;pLWTu<Y70A==$p5KgDTqHgPt1dZt~ zoTvTTJ{A-RQC>GnZvN>n+>82)7WJd1Ey}p8A8GyRFW8Lwiy!qPJ)`a@>qkLt6w!3T zA->Pt8QxNVS=-?f?@#^3<WC>LuGB|*P+#yL+yi5%FBDN9Nqgvu&8d$>P~XY&a6u*N zJNDEsYInNe0qPeEsK2y{3&kPSUw+P@?~*l7Iwo+6xL`#ZSPEX^r>KikSzjpCP!rqM z_XWjLe^H>mkohP7h?M`I)Gs#7>5KcQUzpQ-w|iYC@$yl~w$d8GaRvMMe8Ubf&d3Gl z9!r;wUDgqkot@D+daiU#PN#-E+sX1Q%lVEsQ%Y7+&fO@_W#&7ivOLRjzImq>m*so` zWqVd^CjSuGl)s}qkDaoP>r<Y4QqI5Zjuwwm&LeL>WjEIput~X|xTX6kHYBEisSKw* zrzp2Mmoy=WavSp}&v2UZyqhu{X4DguD8t(*s~MNgAd0g3IAS}yc%&m(Q-)*yWE<=# z+Z`#xTe`boqYPs&%J9u&v<~xS86T!F3O@hIElMf3l0Ugced!ri)_Nx^vF-uuD61<d z!(RSfVKQYnhH_i7HiyY_OS|Mi3$BcxD4(g6+h20c(Tj4smGb#rs*c5!&qtKo*iGay zrQAkSKEKrDb6Gy&Pj2~L%B?J)hpw!U_)<PsP(I5QO~Itl4DH&bLDK<?#EYNpe`oST zL4o*&GO6cjhkNF!!|?P{jz9hI{ig@a<I{9r*De(8e_UeH3yM6&-5co#2$*az<yBLx zxZdCZ=x6$zNfTD_U#8KZcO`~Zz4PRg)FwmkpVL|0ydXaLR|woG5Si!FY_2)*qs96c zlVRM6CA?4IIyPE29M+Vopk2idrn%1%zD>}<_4dA&eZz);!OH>s{;=+F?wk#blU(5A zpO}JbO$Uhna+V);4TIG^ny?WQ{rMZeSh)RsEE`cfi(BlCh1k<3%qORoPwN%{YPHVd zvW^L~rl!C$A0yfN5&pQm|9;Ehle7jU%L9KUo?t-<_nE1D2>QLQV3T_Z?7+wNs6W{b zjJK~~L8SsNFz5!xEmc`HJ^ORle{WfQ)sqLTNyF4umn?f3jThYx4Ts{NC4~cDtAIhN z4{R=(Au5F`Lx1}ba5X+vG~dwzreF4kc*TOkn@+0WC2@n`jB+tLt1WzZ<PN2`M6o(Y z2UZ_&fskRD;=ar6p=PlQy{lX)o~QpQ6F-j!wXYJP@W=xe?;inXFCIz~rk`VzUPptu z?ReIq?<%Hf5DR<CCG2p<4AyVw8zx`+h`F|M#E<hIu#a9ZS*v{m@o20GC^o;&T%0>% z#uigJrE!7f2pzHW(&IcRW`cCak|<o0Tf#4>c}o3ECZLmYE4=jmg-}a-CtQtG!vVVL ztVH60#Vw+F!h0n?`_NSU@jRZF54kEr)l{6Xznt0R1;NL)rF`3@Lu`SXKO8FE$MueH zVs5l9tf`R4wO`C*_UnS7Z0%t_*MBG5ZZe0xcMQXo8&z4afst(Js;QW&WWbyTc4ftb z5^xQauzcEcAbe67F0?L_nm%;1h<=%dI+qvNJ?$HOAe7vG%7INF{W;Bnao@wuOzyKD zbt7TM#P$5TZV>rZ9<l}c0l4r}Uv{nH1-X#?u_NU?cb+=Raz35%ToT`$-l>`LpOka! zAD8$+%K1sk|Km>&xGevZ#|87E!Vv5~kTb_F?tHgZEIK@lqjT*}zx5{LNT0=Q{~c?t z;6|IK#=K?gD9`2<JGd;*p_KDpf$O*|=dwKC9o8K$QJ#(aU*KC+O!3);j<9l96<5;= z#w)rJG{1N@ztk-X`Lt#1dC?>u{cRGist956Nhf&zya+72|5E5dS#^6|!DU&kq6~jZ zJi%odE;zx^K&LAzeQL>E>^h=VQ(GMApUE64hg0HH1z8RaDW7pAv{xME^K{T)IB`=d zWPjI&kQ6sCRp&z8^tLd7xq$JY4Z=|84zNqr1<Xt`g*#h1z%<HU#*2s2S(LpP%B1mE ziMWR{*@UuJLiaBFDSNU^+Srcg>Xb>K9M<6@F3Vwk-ncAp^*Q9S9KNG`)_J|;vV4wv ztcWQQ&G<R1k@$WY?NxM)*5zr@T$|j}{7tZuq+@X;=IkryJ-b^97cWMjVof~HA97WY zWlxsL$?uhzER(Vv+U5n}E6QP4${Sl3jAtot%9KNo>*G*?ayW<bxlGNUJRbXaI^}SW z$sGQHa=7A8-ncApF_go>1G{or4(CulB?BY52jx?nGS;hZBrd0nDNy$2J$J>Sl)Z(N zH`9oRT$Z={ANw-JvoH8D%3JdlV{uhB?em<sjMXh4i*2?@nGx|qry!i0c#~P|rZv&T zrNl{l$M9^i6P|u|lj(NuibIL5h_i?TTD$T=4@71V5QaZmy7E5vM8=7^{u-7xmom6B z9F5zrVeK;(vw6gp(teQd(u;lC+8sBP^n)huz1Y~C?zn^YevOLRB&@j;!*3EhL~Rm! z--_YJho{1?uPABOCWCns_kM+v^O_mVw->Fw%Q-B0UTOhTdRoDdO@}4dj#|Kr&?PK2 za;=d3lb#cVEn#gV)(RoSim`q?_>L*lcBW?wll{2aJyWJaJjK-rUGFSpOC7A?q>B;m zAl7xXhQL8nx!$bF@N@(DuDiA7lgr~_DWz~)Xe(}$ngSbJ@06q|PT`j}#DnC5qBQI4 zNHJ?!3QT(`&#mt%@O=m4!HBu@3-Vkrl1qRoO?-LVbxFdYGn3)fpiTT+m)UHq!X$Vo zj^;OW7PFb*Veln#Gw)w{p7}{bVbHc_{8#X6*3aJ$()>O7j4xl=rn~@%3=fmMo~{9f zPlv(S-Ls`iT3^}2FTQZB)Q-)4sSZ^YZqU!dgAGeL%c7t9!hG*sHrwF^OF!TS3a!dn zmxnXh!MFhE6LO8c51!B5HV=cZ+48h^;68Hgg+hDB>r89oDB<(3(O}<40jk<WiH{G* zz`3GbOi7L2jkgG+`<`?3d&G`q86?tkrF%k|8M#-qE=%n)eBlFe*A|zh2E=ujJEPHE z+W&ikF&rmePuz5(F&Hjxfd?15fX3@htRJ!5A{TIdxrx@k&gQKWro#Kfi^OZh-{Pl2 z&*O{43!UqP)bZhP{YDwTZB!>rCO%8te~kikx?%)<f2iY|)e3NfIRCpk&P#HK<cuix z)mjy|6E~d`#Wd-Cz@1LvFm~z~-h>tM4aBC?#_;A)$X)Jwz^w0@m{=GtExF?Xo<B6P z$&7Gm3^^5cRokP7s+9Q=ml10bchl>{u3xi6!y~<6fPN>ome`ZH!Z@1uo&At69_$aZ z4WhZ`oQHe^ak|eO7T{OFlFUND>rNrNYH^&^7W&eBqip8l*c?3CyF%hPUuN{EB|V=W z3ez6#XS2x%R9#JbY)+fW2BcWR_$U*&u=x=i+R7Rhyix|$sikbf1{d0Q;s-1Fqz*Y- z$ZaKepS>K=66ziefXfF8+3x8U@F`J`<{}`y^R)u!%SPaIcp+Oc#U17@f5S!`J<7B! zN5H(#FWHHvOPN2--+TsJ*rX3n85|o2xFUl+JS?)QuLpxokTZL*r!~CmFbb|uxhEu? zR0In(E7&)x1v``58#D}Tp~aGS5@B^O=>9?rtmO5Wf0jGAwrdR&BD{qjw`p&H(kiC3 zc^ZrRHX63+oo25`o3UZnLSaA$eHhxSiuttZ3WZ5&I6e1~T`Tt)!XDxT{>X0L&>2F? zf?yOBx3WyDt=yfsThp!V1o24M*7)Rz4%j<t;Ut&V*t|rC94T7(%BN5~x!N9H*LJ~5 z_d?O1IJ2$`dedI=rq3MU(ieFwmhCG~ypVWzM+bPS)B%PpaptbXW1Dw?mc;Ff!(o?w zAxrP##hi!(`qT9@_F__URIYs8MHstS8-|n*flF_?2$_qt;ccrAtj)NI{E5vdC{+2t zB7-OLuKh+q^Gs*ETN5jI|CbT4@}sle^$8U`p7=?(&%Aewi+pyC6Sx!iY<`h`H#<S) z!;$FglFnBjc*S-QYr3X$y@FS4zK1qyE;j(J>2fg4>=(Ce(+i}*&B6QoOMXvb5cwj{ zvj;Pjv3l-6sCL}N^g;{xiQ*vmP?XIM4k+g;!-An`c@WDga^NrSPK22!GugJX{ycxz zR5-kP06Ss#L~5H81NORmnN7rTN!i|Mp#NYxJG<$GpnZEBY%+by?tGN68qH9UYMf@D z6117^3wP*xObZ71OlKDdyF!meY7o=;sUZF^2ZvLA;qJI$Z0AU0h={O*c~h4h$#!lB zr(E5^J8GhEbg2?7&KU{$eT;amp$dF;@PzmWI=o+44LcSZ2;EL@<58np!f<^j*t_H~ zzciwnDR1@wOZ`eN?V<~l)J?&Qo{g1OC_?9SGx)iHagScE@ZgI!+^F2jS{$Fw-&_fY z$T~G>^{g#!@m7Orzii>`mt*{gfjZnw9|%`wz7$s&cY^3*Gx*^8LpVLM-#`Agae1@4 z4@|mr0b5i%9IEmInQxCw<~(Ks*dIP7Ej6~Fy;hQ-UqpX?Uc*)_F-?MXX%T$1{wCg| zTNL#2Y{@sBR>AB~p8sGo+qpu^sy-M!+zLKT+{U2L8jrne524B7;BmZyn@%kkMs+m; z$JzmS?;HwvGZC<<q0rUKg`LXug3}TA+36vNSm#OK*#o_vaQcZdG%mMPTqHQPu!3FW z<V)(4$M@Y+ggL8S!FfVE%x>F}^>uK8>*e$eB5Ns6PU!_}=PKf94>Md-(-a=(N_ZdZ zC|u#Uhczy5elU(5HJXBwqy1QI#2BzYn9bvgPjiKVs<5k*9R{B$=i4NcAk<63!n!Zv zyCWPyH`D-*eJvHczd6aA`cgj#eJ#w8FB97gh=m1-S*$(H&7aZ94vJ2cv$}{eSVfuL zReYKiN+#i9PYLhaeF@tU;fN}s23Y>RR2cf^B=6fd0-uDx78{q(X;LPb4T#0Ege-11 zp&g89+mR1&a6#WbdF;bIMf6|oimS^_p(1N3%S!2m+vY05eGfB;si7R@O4wlQDA4rV zL$1C5l}8<n<A;o<K*G^}JgBP?I@Jz<-4!T~Ne;&q$1B+GDdpn%n~9jMU?_Tcy6~-; zUf3t{KCc{dh)<gIo!`>yiF=<YW8?C;CW}PB7FL)=4$gwG{!B&JRwy@3!ZXFkB-O?i zJhCnci>61gi~5^bbNc-)=hc$UIIRMEK6#=b%oT&G`hd!CtACXDjoHRS3#}pjU3=_P zr-rMawFOsiH5~oR7T0_|#_k)a<HhuWcrg8?kZIfrTNaz4irWvd!>E23TK9n)EnC3H z)(-zi`P_Yh+_Xm~A2?<LUaZ{82OOWys>!d{n4`bE<>B-EQR7rQzP0;9>F%GYIAX$X z;YyE7+)3>eZ?@G77A3XEnCm-u;9_g&P;`?$=sX(t%dcizhq>`v8*}(<#c0sqHvsnQ z*7DK4?lL(a6VdR4E;p%8h7GrZ!LoXkBz#OITlP9nGQQ6)!9yht3irFh^hpX3uDzd~ zQm&DHpuN6c-<u3yYu~c3w2s5Ov>h9_(~{e%ePN3?j|PRG4<zk>rNV2M-Qt!GCwS^k zW!SkGz^nKs&+j}Mj(^YM{jTcZ=cgaoMN?xKl|KLv>(;WL=6Cr=wf>lTWE~sptPPiM z2BXiDQPRx7O1|v-Q2cmynQ*~S3l`+NV(=sdT-|9u|K;s~tLhB-8jnseWw#}J+WHHh zxOp_zwLigXb}8eig@8U+binV~2QHc#<7(Rf$>+#A{>WJyQ@;%b`3uX$L0z<PsHX$u zy)tC`ygQ+1VteR*VF%M)W{u0cUt){2PqB_$yf9Sa#x~{Vu+vSVab=i^koQ5CwXIIZ zw|n!XcPw{_UMgwml2s!)X_3uy@6*0FHwR<*Tx}RuTp&Ddl|rstHEydFC{_`F4pZaL zGy}yLsuMzW1gayiq>G<2X|Jm`CR~pA1Mvgmp*Ff~#kY8z)XtipCth67kv9iJ)Ld=! zDlQNw5Qh@eaYXto7!t0=l(hoM|DFOr!qix<W}u+1qzlh8UEy*Y6Q)62RnHf!b@}RV z@i48OHM6wQ<tyvC@%cACPkrY~iK4f_YU$m%<G@OZy_diglap|*OQoc3J(~}%l$<A) zy<fjLv{GVB+=S{#231PRJO$RA_$1XIN8E}ykB+mjfd^Dd?$*~y@UN84876Rz<RnlU zQz`xICGby4Ns!`ODK#A~@M_|)5tY(;#7~HyI9E!2iED^EdsIqKc?<j%ahsu)QaT^m z`+f)=R4Mf%mZxKGa;cQApyRh8_K;LcGlvSi5Ah4)NGfkfY&oD(T12cvtTFhp^xSHJ zhbJU~oa<xh<+TDIMr<<Vv9v#xPb9YWd@QwFCGdH~HO+KUew8Z@(>CGNe_^^Vc%H8H zaUByb<8zHzRxYJ-x)#5$wFX_^zi}YdnMN5%raEK)!oGCfkJ5FYr)5HO@BYchsC+4v zQx4%X@p{V1-<Yz86Y8_wn8O>D%ko2+gzc2=|Ke>_p3tL^58S#~Q2#su{>_f{<qu2? z`DfxDROj)(_$!t7q;l1awitUdi~S<sKm-41#Io{FbKBxHs-y1wcmCW=7rxSW@2zdZ zWL!sV(uif{I@CV*s9c}8E%AeTZe0HIK_|w~6bN50CE?$A$D>Z{SvidjR7b|u#82zF ziufV1Hsyi(DW0Tp;BQ<@xq3%+Vku+)#ZgqA-ltNM=p(R4)E^u8!N2%?&q|5v2!Y+E z^1t!hDem~frxjc<iDQ4`hg9b~)p<vC{>?w?%R5uM-KBP`pp3~_)}H@ndn!Lg<#|-+ z-+a2h{E3Y_#22VwXN6R{ANa$1|H0F!PDA;BF<m=+N^MBz!2iawF<CY~zoI%nsm=e3 zsm|~G9HMjn8>>(qx?T`Xbz1#}W#{mWK5I$+`N%TxZ!V*A=tN`7KC1IK9!z^;_MYm_ zB*T(L^G%bmPnah!N=j$>RU)sfsb-cAL*b~>DeiR62v#>Y0mH7{a0cDSFPWtPzb;MY zPXaU9RqJTbp5esxM0>n`z9XDHyI0z~Xb^kwAQ7Gi<*+X!>~X1!24q(Tu$xhC?C0_+ zaQ7#`4}(^?qEiXW7=E4o9KDJyrso|nDiL<ax|4S+S@<}r8N3@@!>UDVpmT$!(Vpyl zLOTEMtN>Q2U7&TkI+%6s265J^ur*x){j^KjTF0T#rR_6zd4>}+=Jqh_Tt~dy$B?}n z7zzsKD_G^&9B%Jp5Az3UU_iHR;(hH<&<wrFqJ9F-?%WE>jZ653olE$gqeH-s?yo!h zHNzD58eS%~ru#pcH>V34&r-(`ZAy8u!%#G8|BR38W5`1WhT_VL6})HLZNi>5p?D|i zCJ)%YgiSp<1Y=JrqD9M7Y`|F~%xrFg*)<|Fc~;Fw)8GHRJej2jXL57vXiT}dSCXGS zh~Igbhy$tu_~{roUb=h=h7G>X2L-R<9pwD*kV+1d%}2GT`KVKA4*Z+i@zU(Umu!vR zCBw(j8hnael<@YBClr2fiU(5z*cXi)CfP8Z+gu8VOtl>5N}NNyUNeXFBkn-_vrP`` zMttC6IJnWh!vwl_NTz#-299sUvT}W@6GwHP{s+g_mmj2i4F$T_7*kg&%2<)uzY)vI z&r|t>5Cic1{&(KzsEYob?cmU{a@N2F|6*ObXSq)IEYpvdv%m3nx@Xa$dzNE$rGo4} zrGaJTZR*R*iQk79;IP_Kp@E0~i;Yy*N{gr0@|~#x@NbsZm+PslmCjDB<xXh<Amf>h zSXS;r<t=pbc>7bGaiYD&Z`S({w%5($k*7Q3XRx4W0sqbE^xf6yyPKaZXMba)HY}hz zO{tEI_x}gm%Mav!V+)v3ZUi>4;eW9DxB~WT=bt)l8gWCp31uUlGBA^}VM;uwo@M0? z+?jYimAg`%zp>@Btz7xobatKYasJJ%>dRL?-O7FGK1ly+IR1?fy7tA2iQRE&NeufN z=TM#JRHp~k`5PancK+GX4$jbh@v*<KY+ZW}wQU&Hk@0roNaB`__}f5B*nFxx{CpG7 z|HdtyEMYO#(RdrrmFroBxN*5HwP6aiA$=B?aT+mw)<4*t%A=`V)@T18jEQufPIR7B z2a_9dL-`acZ%gHNlph(l`wy0<&w5CowdHs@{~OPyI<oQMIMr#)l-u9srBt5xdK;5= zat9?Z1w7a{mkoCu1@}U)@UpxbmRB+i%p&*k!?&-p>S5K)smv8$zU>JHZ=1p%a;w}q z;|$485$xn=Eu5cli#ZI@XSZX5Q5~CF9+pJFsg>uM_R4*%>l+_f`s6zEURK1ktmv8c z&JkQ={0{Rj<et4^<jMI*d-#>r9(J_w=N9q3Vdb-Su;D`m+smE7^XLxNg`V}zz7qqB zKdoT)hJE?0qqkVutRc`&>oUuaUC(G%0nGGwhT11}7Ml+?0jKoQcp%;0a?85W^!%&| zHvW!{zgOeq>~V5nHHj)v<nKZ5*8d$dx_=XBx0}|_o{ZvR7ZVGIYpTpUE#)7_Z((R` znPm|HUHN(5xc>OWjpilS^q{<*8yv~2;d|@bb7$XN?n~`_o7#Ev>usD<`?sL>KXCgh ze_7woa}#dyLG|r<>x?sIQ9B=}c7Fc0CmK`x@1pj1URK0)>f2Lg<vuQJ=T+3s)Sf77 z&unT>YByX~-)_{N7)b5ek=nCod~aM=-_FyI-r}<MY)|dEF?KyaT;HCJ&#m$K|E>OP zCkI|dZFq#*Fsy$QY+v7Qjrm02XP&jW1IURTa9*Vz4!xw$vLw#9e`f+N?ekb@!5n#M zVJv!nSj4s}Hsz0v5-~zLirM;4EaClVf1U}3Fr#iMH>~J|o7XF|A2+O^ae3qVrL@+3 z=+H>v^?V!9?qC6~g$pDRx2&M?-!`sOQ_&l)FQWC($u`h$AI(o2>m&?n+g6(1(*v^Z z$b&`e<-GB68rPp_L2mP1ZD6cNE8q)j`RBf75a!+rOjT*U*E@Ik@urwJKF{~p+rjy$ zzHs7mF>ieQ!ayxhIHUv)6FXqz^2X;gq%;X8HEG6d_sDVGfKIUDjFYgrt21tRln8G} zjuq`o9Qf@$W8hfoMHZUBl3N9JgmV2l<~&m$Yg;Pggsp8L-9ir?kGtbbnqxS>>ndJg zq>mmKn&3#Qb~sC=KmKT9f_E+2h%GyHfp)<T_&k9G94hjVGe{rT2I*sCZv3~6xpAGl z&$@$BCd08ibS1YH+rYBVRv4Xeip^?kg>93y(bDB48^q|{hwnNu{ED+Q`B5s&Y?&>r zOdKNkJW_&){Z{Z+wT6cT8NiSP0Wx<7(|dvQ{6XCya96J3b7<YG;jM9O);Tj_aR)in zGw^{MdxB}*jy{AXSF!%LjKL<6_HPy4#VK7+3H}?Y9j-Q`cL!Zzk53bfYO+lnbJ7<Y zpIeUa9oBxDEq}0VEHpmPh(RfMJgP|O;rBu~ba%F3L(a&hm2}O_W-;BpG*{U~4&v@! zXFBnlS)`^fB!%A=_MF(kI(f!Gi2rs`#}P2|Q8$b`N3NIqjyPRj1D7oRERHNMVkf<# zX^qG|o|PeGHK#nW&ZoUyF0BQ<+;gck<a&Ue!uvGXR<m8wm>bveeSC=K#{}W!a~oJD z%E8g*OW9JJVNkh#2XEm*&!~0VVy+IYd+W1=bvtH*m01aVcfm9`F>0>RnEN<RvG8c0 z&-N~f0rk!83NIIoK_xjkP+luvn02`yo@vt?Wp#Z2)WKOceJr<Rq(N)FX<}nuBGA0T z72R-HR1PyPjb^&?x7pW+0ibE6z<TIAVEzmP%p|{u%gotAjk6C{ZcxUzZAQSXr=O*b zxz}x9*kf{pFG>`dT+5-7NgGQUr+H2z=QaoJW=iNag!aPmI?AijNVLBag^Q<qVAW0y z$hDV>jk$|u5U8Av;axXfVX9>dxs%o{;X?KlIC8NEjE2d)>S-UGQL>i{era}ZH^<=M z8wr@2FoHe16D~I9VB0ZppcQRpw^t6_9;NcCjaqEKQ5-DrW>6hy&3!)5y+`C3-sO@p zccl5{wH2vYS-4j?A=(Lzx%F~C&~A~&x=en|vfnJ>>hmA5>khu)an%AQ++M@Ox_80; z%S-t|xW#AQ_r#>9X;`>N#dg!sSCYnjPdXgfo#(8$-v%~$)_i`64TA6+DxiJ90gico z=V2GG@+a5tb5)1lST|h@TZ~M_Wofg80h77Vn8QUc=&RcjPD(Uc=D~D+FEk3uZZ2ha zwCrHzOCz*x70M0buhU$2f7Ig{`~~gxT-te`AiZcUG-lbJbob^R-~Z+DSxXr|E37E! zoGJe1b;-P7{Z{^)WosAp?wuo+lS@BJdyMwD#$`PF|Cgu3`O%vTRt)qmqT~PGPgd{V z;NLvhdVLXpu=+R8Q{7SY+-JRv(fs~Ri_k9pe}C>2=4^4MuKjNgO~|u!%|8EouVTf> zV#^DsW)jQE4Q@UT->rE0drxE;f2`+TRX_P>MgQNQ`9J>Op0*9=BRj_bgVD^B_08VY zwLo@mPkVd!J^a{~SWa%j_f+)OJ@|Vqr;LaH=Knr^y4TvmFMgBoW=<YgIBZx{OMISq zhW?(y&-LZ9W6Jn3mCM+;GMgvS`vMtvCr<tk{$HKxm}l~{u!5$f%g$44=CY!duD5@4 zMEuO65l4>yX1ONE3Nz-Y7wp+S+S25CHoI_lGX57|YE&*`S^Iom{I=-yv{}EeS8e>R zBBRZwzq#L-!$mFgB)|Fo<R3+|zb`1dcz3qgkH*{OG~P}Kzb)>kakT@DtC4rF^Y%2} zPN4C&zZtn1X&f$~aoEp)yU>Ql+bkMyN1t24G-<qD^Jlyj8phjA`uA8Ejkmg|J<;5| zeMugTw~uMO?R-6;M3KhZ+~?aRe=A>sa=4Yo*i0H@Cp<pHpU~KQp2psh8+NeM&UUzp z#@k~$2JnH#+n+~m@Mcy5la04MeCG;{*}gQIx1_Q0GmVWjW@1koGe^>xd91Gj*Q0Ur z6pfSTG+MMB2`G)|grREFa;PWE~BS=yMFv>GZ6{r?zy52z@Xt$!O46%<JdiV+mW zfaJ_{ZAl7>0xE)_AW4EC!GuUMVE`3TF-L-mS;@>)VZa<fF=0Ry0}>Q5EAs7;nS17* z|Mgq%S?eyJTdTUKr)KxBhn}aaFdNG-8}+L_Ste#?GG^wdWLb8tOE>lubF%xibHuDf zOQ452c__&R@-Qd2*zpCDtaBxmSYS5Zz-%04?90wy>d4Hr3LREOqG|tEhODIY1evlw z(dsqkq{D+Huo-hwzcxf5$x~_*NR22P{VZoO1I)}2%*^G}2us79^v9emnR}J^VNRN3 zPX4@}0E;mvYcVG!`SAOVM3{|Ln2mkYXEHg=%<h<(o2!hNHs+)r=H$rqG7>lT5q0ax zNgzArEf2c>$;tn4@``o1E=NZ;zTmqtGtA60n3)64*y8W4zo<Lr<fr@3NDAhp59Xx2 zM*`?!PL@PbPLfLsR+2}UjfI$vF@mW~6EpKPX6EzWR%|2Yq%r2?#F+b}RmYo|cH|^% z#++mwIr$$J)_>q3l`}TE>Lx-Ko|D%D`~6|JrwVz;eklCm4VU}oRp<%1BO4w6?>WgF zNTpF&l6}7L{B8gF$Yj^Im3cyry?@=LOmW*E7VcM^pF-~V?|)~G@Hh<;zMs($Jk}TX z`zHgXq?{!(Q<8;!zWvF}B&N$#HCf#_@=x}z&>v~+IJ~RyJ+hSn1B`uiGXJzM*wWAB zaL;NZ;cH<|=3`F&Va&;V%t_>qob1R($;?c`OcDS04-4~9GAG4(D4Czat;G2`=73k8 zFaw3z_`g_~pThQk@-qn}vhn}GQc}X4?8v|lzWXN+|KD~|PO{Sly7@UVqyBu3^3A>T zch6J*!^1Xg%s<8!{NXv#yYn0Cmgn0k<8%DGR?%&23b>8b0iS+rNT)mcki4^<{4OgZ zD{~!T+t=>kWNuipxP3bK<@SW>?}tP65g8ac;R?yI84a!1G~qkWZ+h8y8VnOWBXwV= zlPS1%V)m+DaPp=psl|EfT5+Db$63#f_Ey@!`Ch}pC{xNf=q;}J;yVzgN3?R!Jto7> z@ZM10D@xG0QwWgvm89`6JliEwAlncOylHocp9BlryNcSc6a+9SeIqjI!Ci8BTqv`M zh$XeXvk2cdi0Sxykxj;wOpS<QC%JE&U=_}{_S=ieJCCFl7rv59+h?#*S1svHxi+Gn z8_7<T^&ssZ_mN%t!&up|r}$gACS0<<O!HjT*o`wLK%bY;<;i_njFuUEJFdxwWW1yw z_YHxq?XS;n&K|=;`tiWFpyuqPG99Ma#Dh)Y5oG+8MtZr$6W+WT3DptFG-r|#<nml0 z#mbc=)yqM*nIquAhkkG@`xOa)Tt`mndq9x<HUbAJIbRnDmw!c&{#UEGew)-lb?PKI zyy+a*BL$s@Cnm7++X=4vw=S$rvw&f5-*c6T@(}!TDmZOuB|Sb&qDE$3U}&pA>>AwJ z%4!*4+w=01G^5zv)}v&|sU*()q%o|?G=`S$a>jw#96bFz8g5UQGd@~k0Wx~}@OJ8I zE`Est$Q7Bvu><o6bh%8P83w>w`z<*C`w{Y@H4rSe_kaT$-2~^urbE}a*YXcy&GOzI zAUSW#$=Y2$tn=n=<brAn`7|S(9UZ)q*z8}H-;Q4Jm+`BK{`61z^OY8`Eh~1Cp8d1Q z_KD$;9&Lwnr<^1~-NS%nm=gWAdSci<6D|aK5u?^y#D9!Gq<{7!^Nx;!-mwPIG&Ggi z8CXG+(Lm^_x}BUeiGjLL4@;Z3$C68D7Q^8!(!^)H4|yHgH{aAa0S1l!$X&mhVVtU% z0I=&PCtasP`tC<ZX>21mph%5W>|P4Z&M&!)N(bo2lVcVq_K`DwQ{l&?PjpAuo#afm zEq~#xOp?4K8j@U2m3IGqgv?$N1!tsp8Lm#uA-`3lA>!(xQ@OLUh|YZM(?y+stf-aD z8|(|6OiTDG1DeUs4Sw*JJhU*pD+_(RJwUd<A1|(04gxQ_!;ki{yy9)L;E><}w#qws zUxT_qtnm!+zrU96UC>Mp&GW<G*|Yf%jy8}jCjOutd()_*zL})Y^@IFjnu2H3Z;`hu zp&&3CAgIB4%)3P3TvA7#ncTeM0d*r~S!0TUX<TP_2x{rh`u9~N{8ckxueLO^*6&WF zmApXrVmrNJ6bA8QDDmo9#Tj@7LzY`5IkE0Mm$Nzo9t0gFTHETl!*P)iurix`Jyg$0 zyVe$aY-%C0g}%`Jn4+<pSu@$V(+?D~b{bbdNW^DN6}ijC$<(`L5lCgf;g#sFq>tJc z!Q(fM+#;iW#*X(B!EvApcl1|RmK3?2&M29P&+9LzFSGX3;9;S#F>5V-?0cNX+?xaQ zPWND8nn!4xwmo=RE@83!^V|(KjVzLKWLAr&(%XwvLE6HNjh^U8KS#*G^f^md&d%@L z^AH<SwYmRU+f94v{gC-^BRlx4$>Brv>We5?gzI;13D<^AGyHg3u{Nws26HRjo+GDb zK;?)=a`V(OQezhk8_(Y-@^?S*21c2}q4Y6uV2U|OePRy$8hlQTJtytOXNa@&Xc+iG z8-6;ck-=?2kURST>FhSvsH<)itT}#^RNxA#$)-k7amy4|hbqC1kbz*J(i1Lu|0b{A zPJxD_Da6QO1{~?Ojyk@5OCnSwAm!Os>O5o$X}GWyUfY?HQHgS#&7BBv%_f8$-bNnG z)PjkjGA#9(67*ee1OeklGPZmTF(0@ful6)PAMxoaxt{W#2=pf7I*}#hru;S1=S_b$ zV5mME+<5n_&$!`iUJkAgZLbd5w)lP2!xj#z41tioM)ZQ5H55&B1Xi9QI3PC=7R%T| z)3yLoaI!xfi`#Q1&u}h%sl5brCl-^@*XK~1O+j$Axt#0@OCsTh{!lr}(a7)Za&jtu zF-RV#<o@$kEe6kEoP*%#O8&C+SXgz_fwa3v3y$0bn3+71*%fd+S%<VdtE-7DD@2=X zZkL8fwO;H+b2jg9pONHyk^GFteVz-6yi26kf$~jjd+@3j#Djf_BK<wuiDwub4J;vx zE**J@yPg#V$~QA<j~5ep8kgh1X@MqnUlnu0*diY1eO05I+RvVX_-HU4l0`cY?Q7%~ zJ|2#&&;S|F6NWn@rofUb%J6jqKCf#q3I@IC2G-;UnRIa!3~f<_@96|)WN3go7fL4L zGs(Y0kC9jFmysL(OQ6$F7xJXMTrg=<07O*fkVm@v=;}RM@bDvnrn?6C9F-gRDxD`? z({517Iy9EGhAy_+Ag8&Go8AZ4>X|(sI_s$u-|2@846@_kpw%#9HoX(5QBP32_m$gu zZZX`gpF+(IdQ(3|TR0n}!DREa>E6=tyjIm1HY6vGUQli)TOPSHCnaa<-R1`u=nBEA z$ahpZV+qW8;zabdFAEN>U!2zv?7`H|%d)pCt`W5<_UvUrJDrH%9sIu~kQ7%lmbi8j z_-F=`>R~;Z^}sB$sAm|tU^JJl4SLV<ac;7>vysfyDd+UAx=eCpbu=6EWxqk==c7ae zuT=vshHxQYRLH)jI99wpoj-cVGSa+vF=Jnj@QHdL8NXl&yY)4Ld(^B<-k*qL!)ym| z365H%C?Sp!_L#RaZzwU@6UVGeCY|nfT#Ix%8poFDni%l63?cbtaqN;$0IhlA0rx+B zp;6skshX=B_^j#7E}uvea6_FSKT{n(_%!gF>W#qcn+a@?e#?8BmrcG5h{k92)>)0o z%_Q&AqVc|(25~DKOxED~QfI%)l8Vkc=tRWA>!I_ZrD`(?u=y%5zqAM@ZBHh~bF~Gk zUxPsPZfBxC<rbBy^Z@881*=||Q|}~P&nq>X@Gifn3MU>A-7#+5mg_;V`{^0-sXc?6 zqY(kRFYb~xYWp}VqhQEf-eUN!QISOAT$tUelh2Ht(}TRj`SVI|<Nc!r%eWOE0zmR} zk^H<OC-d?Om?oPRK90rIq!8Wv8cZ(Ek~!(<!h?NsOs#7>y|%ZFkkB^TcFvUPe#7rD z#XfXOZ!>1Iek^>_n8t6-9f5OXkAjvnJxI-4D^~f<8II(+ld*<9SmG8^ns74_lH4>n z^WK)FpQ{o<>w7Ow_`TZXaU#@M%5i6&uO&BC=E9upE!0K^xCqlZP<iwjUDU~fn}usq zXU06InV(X~HJp$4;huCl?%a`6Q?~`f=(>A!p3Xk~15a?C5V=Qx?ql@45f3`@UCCyf z6p}r80o>Pb<AM_6$uNUOAjh@*d0oqj1X%d_A{TF1N2(9_!_qr<1xK4|3BNo5w3i+d zq)vE2ey;R|ktSp45w{ma-q{znxf<ZS@c-nhWG+c&xa9dIndg${m*m(^Z&}T~Y#&7K zPl;n^W-a5gb`2uC1LD}WXPeJnditEIw*|7R&zrcj@-5W(r4O@=YvQ`SeNX2Y&1Un) zZ9043><Jw^Ac)nN&L_ERYU%xhvzX$GFk*VMhQ=p(vq4h3Nsdtojra6r2XAj9@z?ou z*=k>Az4`-5DGsE0xDM07TseptTP{eMJDt^?m4UC0bprpMGw@lK*JRGYB&xF5iy55m z4IASp3N}i)u(n<U;FqSNV1CgAcE~52d=J*7zv||(fUD<7+#@-<EFzTISX+>5*G=ff z%*D)k(r8k&$%g73S<I@U(hYlUu%x`gr7VoEaAwX>eCGM`Qa1bhsk|R%^V#t8`^cQz zD@b4>KIgDbKmu13kSRE4NV)M?lG9R^x8gp|a~G{a))zU$SGg{1+s8GeeBC5a|Js{v zTO&h$S1f^TD*L%nuU*KobpXCMMu1Cx1}+ci2jjXnk-ZTfg6}gDVAIHbJel2f+|orO zL7R`y`FfYos8d=HvtSHdO)9{-4g8?*z*l7U%+FkzgAaTS`9XZO8%v|zZ~-?rEAXiv z#6HX6x?WZzpsd=2(d(m0$k+ggoBn_fuii=GmidE6#3`C&*Bf~Idcsi$b(S-#o=i9L z1sf}Q+No$V1bL}JoziS>y!%j4a3v7vK8ehlcZIz5GKZg8D(q6BGEBYX1icDvsI{jm zRCxD+q_qkRdJltRs|~?$_<nMB!*ilm^MT}bv13->1`(xwcZgn7AX~R_7pK_uE7|Ms z!+giA;(|STLcz6Z?8oFgTm`N-R-eFQo2&J}^XLFjKXQe(`dudRz1+dU;T*O9=nu!7 z&J%T9d&wzkAgnsC4T|fYQ^(>?pq*+DHa9PlZm+`N^o-r)_4hzpqt3y`53S^d<|n$k zd@+1IpFql)nqaTrcQU94t_}3<2j!<-Ba7sHV9u#6L}h0)@yhUlmoJp)ck>zKdgDZ} zZcqYzmdG%C^jtXTbd3y_)-h6oc(`*_mB_Xj!2M)BnC3T&4(QZOUaZuE&moG;tVk9X z9(Y3rJuqedt#;71<`&s^pp9naCW2m)g}}0+j2~_>7o6ixkvBzlboE&uuvvb9SVjw| z%$HFHcJlMV@A`h4-ylO)9gTxYHs=L%XG{a0vH}}7VwqrjRx{BG^JB>$&+ydeZ_2a3 zkiatgUFEtQ><rt2J>gRKJg#r?3$o~)Hxxhiq%pdO$ilVXNY-9wRy(XI-#Et_mPKka z%||N6YYbgMaYHZm^Mh5sdt(>)sN=~ZRF^{M!$!nl=?OvH-dOPXXhsaKmvd|I`MKq( z&pE56Biw+PMDUYx<OXGo;*9aWV|)K9s|E4<_<9Wq;MUMq+A^zD5VkuG_-pT4)xXC% zO%^VJhFcT3LYLX}UEM-x$a=}0N?%St<Fong@|L7$b~4SajsX3e2}I3(DGhU+2hM@J zh{6UJT3Q(nPQy+RgBVrXcphC(yF7C6`+h-wX(Y5MpCF68Ecn0j=YvP*UBtbI1@~~k zV%TjHPX_cn#*Mw;1*Rh^1dq>1fz!Svu&2K{=N{oro^DtGlW^WyfW_pM@>IycYxETZ zc}S@8f#=(@Xqt8jiM}2O+vs}1v=PeW^D=KZFusMF#i^61PjT@3ygK#y(2ZNY&;#aM zbY;x_mOwc+7Ltq1as858f~oD!uy<Dr{b75OPJ6Tv#uW^uZm&Y<<Ir)?J}!qAp6|}I z`a}ZJ&lYT}I7U@?Jg}~~FK7uF&8nh9fZ2ED#?G&#dz}oywTmh#s5N5mbo@cnQI8DN zeoW(jkHUFRE|7ckhO#rgyx{}eL5dZw(_%|)_&u=~y!iQ(dZ&58fO{1r&v`#Rg})tc zdSnQj6gJaB^ynX^w-PemnF?NvhBH<ic)oKN)Md_sSG(|j!<|h6`v@cSAoRgn&4k=I z?F&J}Kak4o>71?t2lci}P>UHTe>w=Bow-J;Mh+%3hB-h+4I`t6wv(3DaG0dBjl^vA zBcr4{!-vqV)bq(?_~p_CbSnC@b)XIgb)Sj1Lpqmw!w24$?k27yXL2@E=EFJn!(`gQ z<8&0xk$Aj3mrRTq!}PCd!|JzEFrkwxyH$`z3MRb8`H}qDj_n5p1MT*bUhC(ultsHq zmm#5K?3u+Zr0WyGgai0{ZHo)Dw0ul$%=5^}g8uBsU{j`gb^zIX)`y*$*hov)4<?bu zdTgw_DYG1%M`jspq2Fu$ndPh;vSIg0Zs&j~HqgY29QP}sqk9H3fxJ2CE482NFSnGb zPTNjqrB~ycX`aleES(fEW2m}>b3y2865CzRNWV5e_U2<>^26N{VqHhGy!~5=`V4=_ zI-XA#l<g-9UFL)Ktd;!FF9(t(wsYa`m10`!YCxQD?K7=wuS<>jr^$&NUubU4BvSYs z*Q&P$aO7b>D1GKcz$p}l_QrKjD<g=!r8z8~t_>9jpOO1*Rb<pcC%6*1j%a>)Kz^sr zf^}~f8sGa|O-=^~{khi|Fs_|Ut)Ini8@183eQ%Q6i|pB`(|hTO?aN7MOeiDg&U4nM zF3^XQ=fdvy+6F7<U!-sF-f_s5iDz-nYWi(<7#xgk;BISNq}B&RA(Ymi>gf^;n(7b8 z#Oqq8uXhdxf8U3sO09|WEtvy7%I*>Ct%_vB#yK#3_Z>384(DAk-%G4)1`E{dV_*u; zgUnLBDfk%e2nppmL}@gxJM}~xKHO_0GtT#A(%??VKjB;Q$Hy|={;rH`@5Yw8&Y}C~ z@1%tTC$q*PY39^bniYNF*v8*Av}7*h7FT{E+c*0B*S6j8{!^4vCe40g4~@6VNJg)d z_zc@jcs*(vdHxIM<7~V}@|*A+QuYDoRhNiLO5j<u@m@@KfXsi5Pl2mZUb4&-w%JdG zrM%4{0eJ1$cfXYUtbR`B-kb_`4rhtv@k_q1iiLaWcHT5LF1nf8<mON)p2~J+zoT8l zXVHe|Zmi0!6KipCr|aIjvG+}#*arhG_z|;=o}Fg_7XBk(b>SB3gmYZ(Dvn{zlcH(Z z{7a=j!(v!t<3f60{{}zimId75_R@<}2STo#8$@4OLjAt{COSRv8oj5CCag4vm$plR zIDX*jUiYJcdzM0V<4bNzxEjsQ{YEz7y7Uf>Q(5Z7SLA@^4x*gz{$FEwAXgfm-b^6} znG1W=t2Y;LA&hF)#jsmXdKi|KtfiCF7O|geW%NBJY!DpuO=RDHcnIch>M1CXOJqlE zmKvNnu-A&$p7`f?gZ(zgXhg3l*jODxc6VM!FT_WHv1xZ=`&5Z*!soZ!l+y&cT3rN< zmbf3-$Up2OMW1|#XDZv3;OpTedez(!dhhin>LypYGrM9S*3OnrOl}iAn7D-HWsagh z&Wxn<s$y8fcWrv5N4?-EKKpg{x-lJ_pDh@yv6S^vmx7kqVsg~k5u%=bBEDBYkl{5P zBtj3+Iev_koVA1Rm9n7ZkwCgs;(g&eqsZF>yScWUrHpMKMGR-|<_703WlP$0Nw>oX zxX7@jEXG8StZO*HO$%AdGS^swe&8|E<3wNBW@8BtCmbU+-PIxGtrbjqdyMS9uLi4! z@!;C;V?=4C8l(;53*O1Q(@uIz*qke+f=`hqG@&|{O`E-fbo<>IzyG*`IsT5cwM-cX zZNfP}Qq=`r@%yUZnx$;g$F=;Qe0|zua2zu)AH_{GX(G?}_(89xQqJ*L3t2dOHpJ~o z<K9}Grv^G<?48S+(-$vRQG-Xp%-r}nHz)8E{c&<0t5U$faVI$9Z{gjbahDFfi5$%4 z>0T$B`|!>@+2_S}t?3Lr^--tue<v~?chf5TSQhb}9nBj3C-IK&*mpV};#mMyrDJC2 zkiF|7Sk5kax<bJo>})jIk<)htuU?zMOEp9GqDQCF30s}u+jDhBLTgIresP25$=%p2 zgTCZW9}WVqjbLN56p89J9q4h9$A+mq;Z?044j@a|+`(Ej_2WeJvU@XiJv}P*IvUar z@1qA#IC1?SMnnJa`)Ez%B+hpHe316tM~l9$x9avY8mtB%pjEz_{IppSpyF|sF1X+; z_&z)WcEse-h#`K0`C}KsfN=pdvQ?9M<8zV2m*&!vr`-j?3nIY**L{h6D@|T~iG`U8 zHdOABufVt<7Cd$Ng00c!bbf6NM67b=FIW^ohaC?A2h~ctY4zpOu~{LY7jTOzk6b5M z`pn<x8D^sjW~1<L%%L*D(BSis+)-JTe+k<cW4mSO>ikW}etr+h#1VA`*~s0HA54}m zbj1GSv43y<inEWfeJJ)1zLjkH7+D*+$og2}BIGLUZz~ta66`N<rTf%q@61^&r@|WN zfNCPT$lq>T({N-D>~q8B0>|xDqmGIvX<?T#`fbZhs6!4#Za|)=c#<R_w;}gZI!SgT zKS1t`-xF5hK3j1=gOT?muSRy1i-QK+3tTF`t`G8L<Yjx*Xy`I6nEUw@d9I+xCLt#y ze?so!@zlg>(@Rn{C6K8vxol!A;^bvo%oqDy!amW+5y+2`|JGh@?PS^m$7ky7hvaYU z(8bJD4*PgwpTF_&uqd;U*ry7|S;!;)2QO^WGdqpr`~=7RZ!G+LC*!t8xE~=;lHmVK zyReTbZW}nbvfvfI)=xZUA-|Mhar=TVrG>q*|7h&<H|8f=6o|)1$ii_Dj+JD4zdF}H z?e5tAH{NM-*Hl=0qwu}|jhA|kGS0w06R-~d7f;4^zG<V0J|4pve2-$zmtbLg9gH_^ z!u{OG<M|sGuNrC68TYdk`-nM4#GOR#Uw%C-FciJk-*|qTn@K6Y))9PP|7O0ZeS3s{ zVHxrc>?7u_|KgwlabPwngNqujN&n5}qIM7L6Xck|-5sGxJ&}VYSllkPUJFuLHt8xb zz_~a6UzWl4fg7}-?Ls#BRPuKg*52`156MxPj<pH?%}4&yF4<q$r!`fJy}Fo9?v@(- zhb#ZZcsy(;%_gS&KgaVw8OMZ`jnClDYHQLE<a5X+$dc{TvAv&j26qeF-H`kK58jP_ z-*s;fYTxB8`5R|qAA)@xuut~C*iO_wX~0Q3#^X9Q=;8@~<J!R|=@l33)72CH#<(r% zf%`G**w6puY1l^<`xs-N|HX#bj_(DA;<1Hyys!Vs>Upyu%in`KOTQ(5<LuBvljB&c zHCUg*8fcToyb5?obgt<Z6l42YY=3Dx$V`|6v+#VWsmU`@M0P|L_V+`6=#6vL9+b;} zjr~7iyN8>D**#<f+}7yWP;&?D<BsQP0A5F0@jCKpw;ILk0(*7KnocroBHfXBc&!<P zJQe#G;`OLEUTYTO^<_opG8(#dCZr<oMV^i9j@O#Q$RWtshpZO$`F(H}#Nd9$<9=lD zTJsV2FJ$5M#mMdgXNK38$;fHQ&v5^e?bGmDqx<C)DaUKa%;j1jk9@DE9+T|9<iO>E z>v-KciPxaj53Uv5Lq3Mwn54x9d_6_p;kKXf8kCRMpvlNRsy7z~<2We!KP3O=AW^$# z!G5zbI6h@KK7Zpkxho1^;O8<q@FDp(*NWQL*Uv08z<svkYyFLdpH~s~Z^Qlkn@j%E zF7BTZ6K&RreTL$;Vje8wW^5O-P2GC4*T~lYKkT8DR4D%5^1s*zGyiyFe{*40FT`5< z8&{Q$DRjp7I}hKlkX@0Z|HY3s&L}j-_6BVK8=D$zEu4d|Rf#qHH;$b+tI!YkGXnSX zH$IYCYnF$7u3*iJ`MLxP+r11M&Wc~_Z=4%D+sq#KlZCJKZ?+S)JGd$S>2m=4{Efr# zdJ%`2IT^E2lIKaZM<UxfWN`QJ8YIb467BV=T2O^~{v0!0%rE}M*(q9Z8?QlT)PQA* z*yLX<thZU1EB!imTwngp{UzFk`~|Ng>+u>f0k2=5{=$b-wAkA6Z1NPZBVv9c!NPWY z?<^9>!MbA{{=+y9|6zRZOi9#7*e+(tc1OG})Xnjrhh*N8zws07b91H#Eyq5R{7j<# z5?&*~{W{H;!F#WN;bLs}#6G97&)@jk;FDw^_9?|af8z_-rx*4q!#-kW|6+T*jts!- z$c3(Ni6q;J+RL#0HZlqDpyNCLo$E?mgnk=bbg?f8vY0>@#tefq$9WJlxI0Wkw!?or zo#251a<KUXy1;S*d9`>L3_ihQYX)~`-;i_g-)F~pYy$StvY0^pbceyrs7hjq|8{v0 zMN5#?@m`+-{x1r->|qoQeGo+;vXX@1n&KyQhq0=NN)m|w+T;KKjqShhN0Gpt?Ns($ z5lKNeOmCzPi$!Nl6P>Z1%D7G?x@2e3C0qHmI~y2oSh510u^|(#P@yOG1wAqJ$CwxX z27DL&G4#Z!&=bo<Pi&A(9=(D7*hgGrMsjUa-H29!&<)#xZrDqgNKWi`{hP%;Sl?bz z+*7F#_<;V{-<TEzKqoyTav0q(Y8wRm{Jh9n^ua2}g@P7(VrS433yO#W0q+|(6WuVq z+(>Xl2W%HQVE4Aq0HGVU3Ei;l-(H}B&R7~cW10HHK<W5Xx(?m2563lOFFIhi(E&UC zyo78*H!K3(urlk*q(J11S%pQ=W9WdDqXTyO%}Dkc9k42Nz~XtX>;*bt6df?xnIqV1 zbiiWK0ZV^eN6(@IHV_>!_k)xcqXYH@9k7pAssv`}fOSF#%=*oH!F`eI)#b+tLHBlD za7(iQ=Pl<1lhF-3_t*q}uWzO2-cO=V=zxv3RiLWqfK{LacJWk_U@UrHap-*&PhBlY zK)<US`dve}_h3bu-2}JM<FdBhLglQF5YtbAIG^l1YJ%REj!^*Ye_KuuqSF<bzKvW` zO`)=$;jAAzU7h=9(;et;rJ%c|*LsW2K}TybI$FkU_0$;Mtpn(8jc7bcgGEl)!lR>@ zD!N-&(A~O>_mcC`(Hek`)<u&TR{Qy3>1lMgrW#nWH|TWL_TEnB7pYO9msK+PB{!;0 zh4w>Vs|FgmBYsnv>*P;V7rm^#l@4qe`danJ_mMl<w!FFMXsts>E7bLrl@vN!e&}c^ zbyepb7P(lv)cyFe#d0_gs5?AXcvx(JE|xmFSUl4bo~p>vvTGm9FGLq>0=ih~v$A=2 zMb6c;`)he#A{Xna(oTLWI$Ck)Xek&E;9j6}C4<gYui={9E0K$(uHT)WSM&mv@^*Tv zk0M=<&Q&WqSNTR^>;-yOFXXF)J{9vtpXv$vRGF(I*c<e$erD8hDqg|NYI-H<jQ&+f zV6BC#$g`4kt0Wz&E4t_*qg(YH-Kr|%WFmB~dZ2T4<X2Zn7P(bnr*V!wkwcY|wU#^+ zxmA8^mlLsbg>DthLbvKJx>e{<K?*uluhF4Gw+hTfZq-65M{pK7SF!u8VKX{ZchI5I zj<o@X4wW@JR92^EuxIE{RiHz)`iVIcpev<`uGD}iQ+7n;P(8H^W;@WWD!B83_pA5} zbw!7206J8kobkCnbf}J_LzVCSo7STr^$q=~<WMD6A@Zism13FbN=-snYV4f|7Kl#N zC3K?Dm0~~8mGVbd3LPr8M&wYbFE?UhKdO2r&U=a8)CTmX9>`y#sv;+<GUYujMpr5w zT`Ba4*co)9PM{ODNXC}^K=-Kx-6wRSSOz*#+2}-}%f!6Ul`2P9s=T?J?i0CB1`~^^ z7CKR5(TS4mBl)^X>9|%I`cB<Eq6G!37BhGBpiIz%I(`$FC%RA0=svZ!OS60EJ2j#2 zBsrdv<0g5WlH-iN6I+YEQw#b|QBQmD@1XDGRH8_KJ)FoFdQG#@Yw{j>NN^K<r=I9L zp$Ekmdr)TN2c3e>(lB(EK5gjA5=1W31l?dJH}@E+M`!6%I<BjOE|UhjOxOIEFje%I zUU&FQY(Dx+Ptjj8IN`>EM9xz39xYZaa+xG+z)aSf$)LZ~1^p%aJ}LB~$X_y;-ih@? zXUU+$Sz?#|ah90aS-Pd%PSep-nu4B^QpOUt4BezD=q91FgnuJ<I7`hd@bg7C={dSd zj_-%FsBZ~mExJj*LGJ~^^%3LIK_UaQsMt+PSc~&Mp|kWDoh6-%Ap$><gLLz2hTty# zj@gW^(Zw$~QJQ*(gLH9wI?qt#Cdu0l5QrV5UhFYHMdTnQcXuVd(Jz{Xeo?hg01<mf z8M7OBV!!Cqi6qWS<Q<`3R4Vq1!lmEx#oiIRMpVKzq7Ou_(Tkz;S=W1;$xd{Q&@W;` zM1GOkrA2HOdPfH69ko|@FdKA@63{jBOv2|0(KP~ejnFTmou#(@@r%$qqK@btrK5L* zt`XfLa*fa_q9;X8k>q%;s!5?n=nhGtJ0$58NxDX^I=bv0Iz=kz6d8US$!?%W<bod2 z!@X_P2K}Nh=oh_o9>u<)NAwasBJ_*cTJ(!PqhECIn=`wHPLTyVMJo>wt3-5)hIKea zR$`~f`}ta0haQnOdPL!$QfLkOLb2!zEtj$o_@hU(5j~=wok1Y<iyoq1gkBI8dqHb$ zQs`myg|4746x~!yub~SRfi94>VI8eUN9YtfLNDE3(4Uii;S#z)c@tjH=9Ru+hmMeB zo=Bdvk{KnLU6S>TUeJGPSaN(^TUHCiUeNwo%LHOCXnb6gK<xkAf8HcGhF*{<dO_&_ z&@7SvgPsqKMbBpidOqm?(0%CtBzpQXwHIMj=mjOB7i72k1C2-jCm;PE^n9p~$n&W` zE5mN1|Ko%H&!Jp7HU+()b?62C>@|Q@q4Tp4ou4tMd$S0U3pD%cIl55f{Gba&#V!!~ zKlH*s{trEk{*NyDKa!r0q|bw%4;6YokI?gpyuE_XM*n9#{`QS-59=p#d-fJNvubpH zj-vDPs$vOi@3o&h@WzE~nSkp%8kO?GQ{HfL`~29)(nj(=*jcb;9k9jd|7<SI5PCjL z?D_B=d|0Q@AEX|Ao)<NK_-ySfG7mkU$WvNuDf&MQ{hzP>H_*LmmY{b_gQ-{Vr12u3 zC-eGfD)f93(eo)L$+RJ1I7BWt#kCCTsfWnziNkqU$D;F-i_VX|`%tDVa(k|oyR(f^ za?pQ|DmP=^71}8Be9jl*eCHz1$3?X_+g;#-bHF^}fu|~~Mdv31ou7e$FKL0oS8~wC znzdZ)PFEN|CZqWQLeEDa_I&)ttP)6gJ_4cV^Csbs=flLF&j-KDRP6cKeDr5$(DNDG z;rTEL&xeUUpRTXMSP^<YvOfZ8a`|G`_d){kE>jbr^TWi>&&jlFG!}oK^+UI3o8Naj z1f8EkbbbQMUeg*Gf3P`J$<-}$;13J%fQT|#SleLCoRuz+)IB&i(hNlwG_Q>O?!vLp z-M`UI&3f=Cy*uljugBE;8iJYH3|hWwE=!6zL81)DQP(4hEMTRPU@LjTUygpk81#9( z(C0yihpt42Cl(!^@EOyX6*@f0=<w{yYNkWb;knoH-wqFYJ9H^}I}zyZv>)iqwxiGU zu16jhq<e@Opu<y&4iEY{tPlD*rs(IOlfxFGlVgES4!Sx_=<4XAtAl<H^F%*Ky~EF8 z-~aJ**ktr`KBAu!x;u`Y{m0K?uhGw;9exgz@N<~Z&rwD{=Wuldb45Q#4*i^9$9c>j z{Tx~JbBZd%*>v=C%+SwiI6sfALq8`Q{hYkgNT#52f_(P0;D61Z&%)8q0rYbo3|Pzr z=;ugv_&KZ-`Z-U~&p{7|Wr;i-^mCZl&p~g8{YG!c1-+g5*W;KOIypM%<gBRjVRz8g zS&y#Hk7eF$8~Qo==;zG;6vs-@&yhhtM>RH<*@~Q;bqhUMn8?*}Z+B)J(9h{)capk2 zTF8_{ehxZ0j6)}9CptMbq2pK!x;kgk)#=USG2?&y9ClOW=hW-?GZS=jw9v`f<7CKu z(ACL9S7-6>QS2W2Irq`eIo`{g{XjqG8u~ft<giiqD##&pa*8aqnUqt9t8?<4Hrw)# zpTop{4mvqZ=;WxOlT-3yG%G|`#|>Q_y9gsD;pZ@+pK}%coF1oxSOYpakI~6NSBJe5 zxjNH^Ij~Iha}3eXX>1K=bJ5R9?eKHhyMO!~HWK}u)DAy~hKu|hbaLoqbaHg?Z*+8Z zXd=2gcIfJ$pF<t~@pG7jpF<`594g`GPzgVW3jG`o{TwIrJbLUOKZi>AIWz+O9BcG* z%y90$86rQ2o0UVe{_%5YF8Vn-=;sv5n^RShpQA8sJDrVw&Rg_zMwF$~5|N*?U00Ke z{hS*g`_i8xKj*~$t+c<$&xtDAPgT&*;X3>rD&gl)p`R0re$E*FX?jZJ=d>wbrpf5% z97R9p&@(4G7X6&z=;xfTjG#h4X9@Z_mkvIoPtecNML*|U<T@(!bAF(oV{m#eIg0L0 z2)Z}-joQd^baHN@lQa3;d4avi!x6+b2*ke4tLk3#mh>FZw67xD53~q|{G0<v-Kq$B zCTtb@Gm7ZX^sSF!KIqjrqgT_<Za%9;-$oUEn>$amS*ysa*<sQNA|4VJU;B(IVr_2! zHHqmD>CB=7UEyg=H+Eh=h_))uAo9a^SsvDnWs;mVmkAc2W3vMtn-90j=w@_j%z|e^ zQD#rJuO^H3Icf*P-M7=`r`~WP>k3(6l|Z+o`$7L*SBd2NMQ4VJof&j#sMw{EJWk2? z^<d#%vJ?Fo9{Mw-F76}+J(-W_$y9{RB0_)WA^I~8xjDody_z)iYS5oyt?17bqCd0Y z_iz@Qu#0A2GJqY$F(5ZNng(?EGw=ibnF;96IA5R0W*SbUUA$EweGsrw<74USkU=n{ zhbj~LGpo>_sl_$o7ob1Wfc}jCo~3M5(@Sm!`ZJQ_lQ{7e%|?HwH~KRNa=+0n=+!u) zSCg45&1%t~Ie`95bFbclSt5T1JsEDE$df?_hPt2w(})fXx-m3E<i=cujXbdf^IJKM zD-pRd3VXe&p~!(z-LAwwp&L_<ZVdV`#6#r6p!Y)DMBWSfFyx-dhdG`(inO996Hyhz zl+~q}(1*!IALeVNEHm&(Akyf)EQKD-ROG|Vd-jQXqbH+{p3LSuqv&Um4-;ylN4JQ) zm#{WnswnbdinfoUJdr1}bB!hA(1%e%A0}ZKk3B^1r5AcHtML1@C;Bi4(1+P%W655j zC-VwDncyp>oY;ZcG>p%+h};--V5r!EK{tkq-I$P6bx!ER1a$Z?Jh2ah4vawTz@Qr= z5W6uO_oNAG(T6cYA7-}kb3q6?FyGOEY1yU2>d<=$Men6nA(Q5y4^xXiOzg2NI!olb zSkBI&dqjTAyVqvy89FWZ&}mttV9%`4b=ifk%jB(2>@)f;p6Iur$HK%O%Y!}~^G3gA z68bHXU)<O$^j@OSdwH;aII}{(B?kSLjUOj6CG=ayboeby?6;uD!h{~nJ@i=6Z((A; z1-%z0_Fm9$VG@1|6Z<WGyeKvpotAs(w4m$4)X;TVjIK+_f=FhKeoK6Z-@+vP7G{rr zOD6g)k+m`G*a~O<?he0&3H_EW9exWF`z=zX6@Q+2wjS+JFdy&vx{K})&%=AZi;+*` zedAwvAJ`Z<0`C=vTTY;FME8o5@jmi*<bxgeieV!55#B4FjrV+o_liwB?iG`Z$bCER z6*KX@Vt>4cY>W4VL-F453GDX_?-d8&cDC5B3-%Y@D=zP{mseI2%XsCJXtXS-SB z+D^$Kv~JP6vpyDK?Ddp#y7p*3Z<|sSEBJVnMmS8&TUff3-7vJIYVUjS@(beFbC;oX z{np=SWdr-MokmV<ew;>Wsd<04FMT3g+`BW#JpV;o-x{&1)yC+3=`&rm(Nw8nBD}!) zyq~pAr;k_Q8iQ|2$tWcsYT1wo_JMU4CYHDOEA3l|^hPh{acv5f4nR+dgwwQ*0c2<R zTcQ!H!Hji=z`b%@_gUjAFWN|+lL?T9y^g=hg?b}q28mYJddh>!gy~GOJ;U;qQMVu6 z;ceS=wr&d;uUU)h2$fXQk8R$((k*jgg!L5~a#&SR@fz2`d}R!Ns&jewzUedN7IWB> zFr8<0u9Zs~kpM}T=kNm~<;jQ*@$hLxaPj#3-{iN7H_R`(ZL~8Q=V-#`50dUYB5Ajz z$ri6bn1#>R$nIM}Qpd>t7fZhP#_(S3S6DBmnA)2y>te{>EZb39`^Aif&oe-mw6J9L zT5~q;nF?5@^<pOY_myNHi^1P0SE|9@yz9?aUPxrGO1cU(a319cDjMv?YIBx5U<XyZ zo4~GpyTHY`3@R1=cA@?7P0_igIp%ZT4~CbziugB$9Sp(ibWaOq7OJ8MS?D7=v~4SS zEahZ%_QPPdM@x~cIcx_;6Z)|muF5PRT@ii7B-Zy<KXb3@2=m{#c9gQ-j$*-PH;eDj zb(r0P2V|{ce|Ygs2Q~*kAPuT`|LtcYOPC*J^=p;^&*|_G*s;Qdo!+^dK2b@8lJMi) zkVVaZjx95~xbUvgr@}P+d{<5xC2%_TzO>tCS8$DPqYK`oQ^_&e)pakQVGX-r4KF;F z&rio%y@0iv_n`-0T%Tbv8dl<(jO*Q*wbgXg<fGNbY_zB*l^Z6q$5@jMSd&<XEOB+6 zg%#G}qZL8SM^vAg_AT_=1~1I1Db$IJX36hDXliUIQCwP2=Uo`gzJ&j&NmhV08H+V3 z9U#pPU`?LKnv~>3USjDDtWPDZ&x&8(d~xmRq?hrmRLofE149V554Nxq)z!`)yDbYA zs+0Tu<6-8`r_}dc8+R!q08&(4Sjh26GBZl{zgY5^UxxRBu2@?=v94U6sW3fJ{ooj~ zrJ}l8(ZvwzMfE1hSW9pmYw5Ye3;xc*--r&@*j=o#+bSB+h;^0OQCDyi>#C@uu9$4% zo1%kxbIh@R*og1jN)C5+vKsWTA5+G<nu~RX^~T<b>J4iNZecC?VJ%^eK?c^?I;=5a zeQr!sH4jk^Gw)HW10%7PVzHL6#=ygVM=|f9o5lTSI_x;sRdYvOL64{?D|@UftR+^8 zwe)sjbLq6hL)a!!jR|Wt``d{^?SqZNx?;z$t|nkzNsdF$&#r7d)>shMSQm$zboEbj zrZ-Xv3U3jn<T`|vf15&%Aj=^4|1pJp9)FXb#Xi4BC_%$oA9gOKnp!@Ir00;oq*hbg z>PQ-`JeH-H<GsHqEw&6<%SwaxLvGBjq&>#m=RV`_zuj{xX|CRV4&5~tKQNrzx<8$G zRxM!C!@{{u2hxcS^3EGw!QKd;^@twN{E@YheUO{JctgSSBtjG)()h35aIq$dB=vkq z>(3;@NPAQ6`K3L)H^`eEO*w_)J-iDRv*Cne5N&p;Cb`H@k?mcp$@rhL(98KdEyMMI zERosd@3awl|G9PCc%#wGZyg6^$X>|K$XhG?1aXt2nfCdEbd$_|fnU=s7KC%=eNJ0J z8VVP(hP|%^<CpK@6l9jN(#{sNS7j=3o;;ncQ2R*T@1~NqlcuwlJ|C$m@>b+W$nPpr zi7WQmhJ9AvNhSBOeHON_L%t_sU+n({IT-u&Mt+W5hpbkWO6qajy(%AR9k%y%p3eFr z_dzzqK9kiyQa$9U$k+RRq>0FO$aj#1`|(CTi~Rk5Dv5EL&a$z8#)DK6f$WXE{&p&9 z#y$e<a|u~^Y+sPGaNFMax>c$lX$0~><j2UWc+8Kn&sseGG05+c&5@gM99AO>kD)KN z#~{}uuUfQUu&yeB$!zrD_NZ^C-Vu?k*-f8T96v|D(#fnO^9?P}+d*@$4PhfYo3gL_ zLItzjaqhL-S}ZR8s9?v*4|G`bY?fA)!Rh9XWbexf+oJ7B=4{TVYm`D*!NFz3=Sm;e z3FpXJ#FvJ6r7YUaIkBqBr=%fHg}K@ovYW-0VELqsw&<xag)2(1+@L>G(^6#FE1Yqy zBWV`+W($2g1J`lbtjFY%E>qXlRxnXTmmO7?5zMqzh7}_xu;_d9=<7i;(7wWh74Gj& z_9oPj9=J|ilXN#~zJ50G>9vS$*BMPhZ>16*enwY%f26VZQpr0UXW=-!!_QG2$7Cz= z)0?Rz4Ew}j9}}z%7vvSaKGL4p?v3M|gMI9=zi|8)<Ct&5@fUtxdHr#mc?K|Kr#^!d z9^@SI^d0)_R*46xK;DbIpumI3aRzV_`z+4(AiZA|(sy#<>@4@5%YIu(rIFnxzUPvW z<&d9Dc+cIeE2KY=b9nDLMgJVSX2N5-q}rX`@Xnzw)A8^1hwf}Veg_^q<uUDvzir6R z$)V$H9@F;6?o2Aw2o8;}7tFOYW(CLx4eA9WkWV7J8rBPRkXu5GV7z0!AQBn#hpZLl z&$sb6i7;n=Va{OwfH;5hk(EWc#9!+J%Im8s4>P9@`4MK(7|bHf955GU&H`j{7GdTP zapqta5pfnB(+U@Cz|7Ib%yAnSF4!T;qS-gPGBeB^FU%awA~qda7dh^$H@l3PvjQ^* zvxo_^$R4u@Glz*Y2eXKYvj{VXi8H4hS(rs{FpKPd%Cf7NIW?F$F31{~MFq$g&#e>8 z!pxbBnX?mFm_-4|i4}gFIDdkd?-3|s&RoTuQQEYE3iBrk^Jk^ZeNLE5{+LT@m8n#m zKg|`XRGc%IKUADQm`gMTYp<yzbLd^<*~pkhRCvA%8MA`cAiu@T!7QTUEW*s8;>^J; zqT(#V%%S4U8HB8d+j?N0EJ3zFZWGoyvL<q0Y~TMNm4;yr2O?t@QE?Vw=KMJZVdh{K zQDL44vuGi1tA_PokM&=Ktc)zoqA)yW8RScNoHLPy*)<T4UmsbRIZtp~8RTT-%gC5H zM4UOx7VYPRStO5HbmRCr@?DfaEB1wQKA1VjF>}u6?I6c7i-utqWmaVfgqhQTnS)ux ziL<Eq;4<oqne+R!tuTwIIE!j3pVC&$90$ytc)m1ShFR2rSv2yB5}Svaql}qTQEbTw zX3;y$qNW)GnKould*Wq^S;WLy6lkl=7Gvh@#LSto+KP?EEK=wvBf!j|!pxzVIkkgi zaQ$ZwwhXgq!TQ-$m_IW+@`sA^2Xlssa|ZK=it`6^iHdW{1pCau@!XAL<%sp;gjp1a zS%mpRyI}h%9CL=_AM{WDFme81&M<M#VE!<1{$MUKaV~X!RY;mJTOu)kFlUH3XO6rn z#OD^m*|PEPIRP?<T!UQdmqV^#{={JZ916@KrI<6HF=smAGbXN>KWdmiY2G<x66TU8 z<`U))6Xy@+3=`)J<_{C+59SgR=aPoa)shWPM=hV>_qgPm%O%=n8!cZVU%$|`<RIl) z6(QHJdRUyNVQE#0+%#t%{rDw@UEMU;DxANN>a2`mBO>=$X~hviQ9&XL4(!1T<{1iP zSRy+*z8_EH)=i@azY>{QlLl`)cgENfnZ48FEr>c|(rfG8l6UxB@A+gq%iSLimoy{a zlAmsAp0WQAZ&;X{FL%18q#oNnM?EN!AOFZ)*x%afWJ&GhhZgUV(^g6IM`YDn-fc@{ zTA4pfE04EYenwtqtSiu+X=)X9F_FzG*A?_i9B8G1T)r>K;%DA-%QyI56x$zJDBpN) z`3gDimlFH%V+vcXb)oeAa7E^6GL0pCoyIpe9$dPn_d+XAd@bz~)zW6g<yMoC7isyj zuF<WO96iPFa@&_(l53$cr?>D6Ugee~9^EY5Kb*LpTw-uD-r^f_+mci&H)avUxM>%w zuUbdH%wGf}f;$yYiFhKgUy%SyhZz^=ZKx5<j!6KoFD}Km7JCRnvl3z9(8<LO+S3HG zhZ7;;xl!?r<heWxT-#voS?yxC$xC=4-x6W?^G?Mc>G<T)B1HkucL`Wu2%*PaOav=` z#=yC|Q|P|F3W98}SbzvWI%9h?Uu*pmaQN;>wkfFa-h7UQqrJxAN}xxqrjJ|-5!VPw zOPOHRf8|nGCTB;qog0hp;WKlShRBmuw<}9Lw#BpKpA<<!k$lO>h4Jj6mpoa#{)^?5 zt??}DVGkm|qR^^&dpz@%SD*n0<_d1~jb~qH52RNog$ur{ienQVsnXZ`lmvRJ@yxSY zhlUT872MU0V?$~c*;ky;wEUb}$>WQPOt*3>9I$y;bi5WyOcGX<wBl!!QZ}~a>&l3d zPsls229y*m_b>jAV;i6ARw8%#>L1Q5pUwC^KNB~T8Kp)sv)S`uUr3P#D^1xls<`#A zL&;Cv_TBSd#VhacDHi@M+w;w?k}Ai;rG0QeT(xIO<K#W1=E$la6Is{GUi=)LB);+c zMApDL^IzTG!S~-FRnk(WV|5X?O`NV=vi`Se$9b`Rbn$|ioYE1vZL-N{v)0XLN@bA) zN0(WCH_ftqf&DLTe`tBNc$ei<<k$H%7F)-T`Lmz>SMFH&<Da3z^XqTti>#6@HxI9` z4Zk&cO44TBLVhBf&?wE*GmIiN*JD`uF-<G?ry*pF)e^>r?6Z<Qza-D2g&$%{^j4hu zb51>@b4w2S@A`ADjkG&rxp7HXa~x-Q7@KFgYWdwi=hyprKdffR*I2gWIrZIMiq}*B zr)3Rtx1D3SzRSj1RpB}Ht7Hr}tx(&l0$K8$l04TI4pIi*vnlLWiW`6BL`8V7IgO2K zIbT}7QrBt>FVSiozOJ*kj@8PGDOO{U-D7>B_qdOA_K_|8)B%1FfA>9=Uw4YX;@KKY zr#@@`oKt=79kuj+yyMTgHgmHDxpRIg%#@NYjzX?Po?PCkSh+_R*jnHTU)O7ttQ*k< za<e?)=Ec^cEmo&2hjltwEX<I>!xmbeKa^iAJWm@vtj!BHBwGmo2F)93Z@$tv*+Tet z>WL9!iu#P*@TX>E78w+&>TLSM-?g1B7r(G7!EKq{s!+?7^8^3X>X$}e*m?c~d31!8 zRvhq!ZZ$3Bva46A>1%ll(>XW)Y`bV%ki~0<@qcP^K>RAp?qOR>C*te&Srlt&boFp) zKV;1hiJ*`Z$A6cZ#J`O9&8*(6<i~65<c}F9V>$4Pl~obG?sBU>mX@7NtOUqUZcAI} z%+D<ygxjjP?Kk^bcA(S<dA3hi!Ol|)AS7)oed~LP%iF&ge0oOGpe6$dYr=I{2luBr z8G0sDA{WDqNh@ejZ+(;Ul0=wl$>VzN(gF|kTpM-WNRMU1O(trGz?Sg4WPa3ilb0vQ zK~uOUe9h<s=WyOEA3a94_3IANN#nq;=V20%=L>_~YRI7(=A<DY4Aw+2Vjp%|uzO84 zxj)1Ns&$l@RO@gE>)jo0`^Yk%C?}Jv)AZqXh6QWUOE-C9JQW7zDzQFy)xqMG5e!qf zK;LkyO_bk<z~<K5bkhPKaM@Nvro8p0*JpZ|EX$7v*Hg0ee#to4J*q!kpJ6~J6v#r_ zo@r1kJ%oPyoMiHBQ9Rtfs7S4b#lj)0_nh=c6T0pCVlY^JinB_Mq7G(Dp;En#Thy%& zt#^opz{C)4bzf(a<DUSwbSGCl<%nRJV;tmoe-$_l_#{vuIG5aEKRRjwy1R$)cZ=u> zLCoWPK^bo*ypNS;7K?`PelOBvi<QivZU@dWvP+Bk;doZ!c)rf)!>;1EEyi(M+pjx| z6OG%kq)28Zb%F%z7ztc5eVNCq8Zv~MlNxk%(1wK-*0L=0z;HJ4Xg_fBY@qS7eHlMv z3|!2AN^ke`VuxfOlR-DOP@i2gY}f^N__|S*UMv~M@^MV?heRsa5Y5KgY#_(`523*e zW7vd?V@T~#J^JfI40HLVL3I4|ssEt_mSA1U<$if(wY+^XQ%}6b>zW@&TE@k(v~D^i z<wXTA-y@NoIXa2!^4VG7G8J>J+cH7$lwRETmtibx&;i<YsRtP<Z6nC7U&6lc_8>n7 zuj0Q}S<H@KSViRH=hKI&k&IWrl$3j|=a}kjX5Z~I*>_<iX-;0qzWfR$^P}U5?V&Js zDP;>W`kGH#(k*CL7Rn?)7s+GWJ8~MF*K4LdVISR&T#noixjjT5HsqMGpgombmr#93 zL7su^8(&FwHQ>}@m<`jA_aet4Cp=rum7VO#re#cn&rdtp4SDzA<@EhQ3o0<452uhH zBlD4E<}}cE7uJx7+aB;cuz`LOu`SM}s@gmnl$Xc@AooR<NB%gckUohEgK68klkdpY z$X>|ft@jI_om&87_NGw}<d?|u$U*sQh+MJ_+~oIRz9PPbJmiup+>O6PW_y{kp~xqY zLy$c}CV(YBMxgek{~uOIRzb!;=3wK5q2y6a8hNxFpY>c6NqS8=O*|rJg0&601J}Qi z56k?Z-(&~wsBII8=h?wYH3g!-QUg@gY+<C60;ium3?}&xhn5ys(#_opp12Kwy6IoJ zK{Fg6v#vW_pK^q}K5h^9$F~s9cM}OJcY_A2k7R!J7t;MA4|WZ{Kn}`&A>GhB|CHT8 zeg_PK?Z1Y=lk^hOHFN|RmyUonuR4K@p)u4Z{w5n69+BKaJ19E(iFm2^gZ5vh@W7^k zr1{Fj2X_ZxFEU8<M>DYLIvjfMNg{cgM)2Cz5WJTRA+AwVVcMfEko?S@wB4N!yi{2@ zmG+3MHVXu$(UeR|UP^Af35U*6$4Hh+f07<+0kJ-B$Q#QpaCqc2wgc-&3G1hGs6Jbd zHS=?KB`0P%tRG>Y&7vB^TB6&rewJbV%tg*XPDD0%wp>txwKN0kM^l0w1}`Touzqe~ z{ft5`7BSWj`6{ZP8f0NzEy23-eEpjUYpE;N&opE?<UYt!L51XzsFu1R3u{RSYe~U+ zKldK%r(#bUeK>YM*N9w)Y?!}>{#a!LO;|tXBCbcq`e8q@eq6DBu&!7O@^s{|kO{21 zBu4P-bAJ|$JghWEAceK$pc~E1u$FSMmcB1TziW~MmxeVnD{>|?##-{hT6(!0?{#90 zwYZ)pJ=AQO-b4kCVExSJ*|BJ>D-P@GuG;|CAM0lX)(_Sd+l+OkgmpC+eU{eQo5&`t zpOm`pYzNkr)Cqh1o$LZ#kM+|X>*tx(M;d~4rG#~LF1>_y!TPbn`gxw+K)+*MWno>_ zzI#L)v3}NK{mgjPiH*j(s>Hfl=qt~9csRf|te?s1{g_&tDICVSI-_aCYO#LKWBtT@ zG-DjrRX?mNtRDtgKQ}f$;@qRAG8e2XQ>?4IZ^Bt~<T2uj_4Cp!kafno8iaMVIo5(L z7T1zBKFgi6iY&9#WgAYrvggMYAn|8+s=Db3&m}w&juggnu6;W(CFyCfeQhl5CS}7o zd<M|<q%4yjF_Ddaz^ApBzEZii7&b;`9*LBhP;z|JLKfFOjpX>==l8xlo4s5-hvq9h zq}?lKvx`cp^zfT2R5RO|UGcp@KeW7{SNkkw29NE?%!$&RWdHp7MeNDVaB{Usinx48 zVEdXg1nc}f1(N%ja?Xp*tUN_u>7S>KQ86s>mN#{1suD=HCr!`guNj>PcgO4#yib$j zufLrL#v}W2J-61<q4+z->_P$8KU<cqoan@+nQf%CH*DCX;Eyy@>m~ILpT=s+6<9-4 z7JuWZZL}GG-<`1Uf?!?c3p#z63)ApFM<loXdFdEk)cAsS+BprzrK-TV&fVD7A`KXB zYr_xf7s52t?vgG+w@M#s$}mS8F9^AHoQ(I9W<HB1KziRhWZuu|%&l7iNzeaI)yv)4 zi+90P<JTb8cz!G!T;WZ--#1{T#Y5P*pkwsM?Gp0cVFJt0`1N1yj`wk`v+YwEKWih| z?x4kDrwXW7CmoQx6od0233wyJB8lzBRC2>QnuYLniR6AR-&sR8{5nJ@wFbdRe!gIS z^#(fn%7Xvew%I3+#r9AkKXURo$@ge_HxBf>4Wgg28u>R)bMWZW2O1Fm`LC}f+5cFo z23!kkB=%c0K(bwO|Bdx#f`IWoL3@lFNb>ywhw*uiCVtZCD3ILGXO(X7|Izi{QB@?* z|2K+A77-N?B$^Njl7%~6AW_LEA{a2B1W6(}DkcmVQ8A%lMnyzL!ksR&m{1TgW6lXh zL@+&#%YJ{e&pDqz_MG?Wt!e8{)x2hy>8_fjR3Tb9GY}?=-&DW2*2v$>%Y-)Xwd9fd zFTQ)!JlMcmM-@y9g}mN@B>DVgUO_Dy_<mJn=<IfC;K=T40T0QBE6u#Utsk^}>BZ_i ziFo6{2~d_S59=52wtJpC6{0175#u`(`M4!%u>X`5scC5xr{(&9vQJ;g$L>Vo$XH1D zpavnL16=(NFSt9TAMnbOxa*`P>^sy(NWYPEgX<X3f2azp9xCBWdqa@#-%k9`Mbh!U zj&N`J01#e-!o1D?@RroQodF9brEy!kZy@r<QQ+?zPh-CZK+m?fr0nu4y4S-Ww;%aK zUKq@y`YTq`;4`z}xn~JoHTf)Ed&vOK)epkJQPa`v@Llq-CXl+jyW6$4MX~y{Vp><x z1DES`kd4J`U0Z8^{A2A16{a~vsD(Duqi@pi!f5{Cp)kDQo{8S)7xU}A&+tMYqCC^_ z`v*PhksZY=v+u>SpMHuf(!PlY_zlNGOA%(j?m>^)o8aO-=IGr%hJGEikA9w@j{8mQ zaLtW$uy@vGz2T|&$+9%C+u5J|tbWZUu-d`nM66c!m2<S>)(lv!lut*FDyKK+PJmBJ zm+0QWGyfT%H{K17dpFQK7eCN}9WGFE>Nfpu^NA+EXSJ>#ucQ0BUEzhthEMrTB+LCV z@_ihgGtC7iUDL&rrMK*&f1APUo3a?!$ohB-Y#eL~X$<wjtP|g9hldeJnCapK-LrJN zRSL$G&!)F?bvdI^x2eobP276Q5QP3KWZJ{KgnC->S(4Ql?gLW2-C^ZNf40}r0``^k zAW>~*SQ3^D^6iP_X5WRPkCho9Rnn8dpPgbi){FB~j6W@EpDTWRD+}I~^x-X98*L9S z?+1pj#$cVN6a6t(529W;U}A3_TBc|Ow(fR#Z2fUwiZK#ot@woeWxOzdggMq~q7T>3 zn1M3Cmk52UP^;ohAQO(v-pKP?-C!bWK(A5>x-Mrs7tk6D_QCtfnuKl;VZgrGWWFUE zh8mH3Qt8lq!ht^@w}{&urwnF2*xo=3WuQyc;Mpo=nC8x&A<qp0movXe^vD<zYikb@ zgS4RAa0Q5#F@>W;zLJuM8SuJEk__0BYiGA26B<LxxKimfZr}nnbPTyk<bq8>?Z*vr zNKX<p;~e18_Y_DARTf=5IhhF0|Nn}M&^O_nLi>rwjc`w~3>F%8gQKfI(>%E{@%uf~ z!CjLQyYyzt%Xz{k<7iTt2sqF{8&1EwOuFybA<p{|fd$IV<axgaa{svNfAqa~4~V^O zKh$(E1zn|XBFlk;vENQdP&_z|Bu!!c#LuWevsDCDZFA?$o+ZO&dYtB5ctib_eE-Ak zz;IP+5I!1h&GaCD!A1JHRvA2<N5P^#7eqCK46sjcd(coHPBO;l(XF0yL9PsF>#hpw z{5JeQ<6Aq7Xn}Du_8nkJgt;voca-P}ZdZJ;IV=4?Hp2YRPc?!Ip(pA2@IkP+w1{pV zsEd7aEg|D5<$s3yqLi=le_}+o%_FzhH;a6iCI2UmkITD>l0C9;+xCsTx9uvjvos!6 zpPb_lWV|P>(UZ_CAe;)vh4v%lv+Z7I&&8z62dL2gl~OOeug6odc#t<0UN6G?{{Ol! z$GGW<1EZ7B!g1k$*d=6IY*Vqg+A|rqyRkl!|Kl2jAZcuWuLW(!?A{@Wmypjw9tP;D z@#2CYbiUsMe``_Vyt+SL|7eYQbK>A}+X|xI&4>mJ9R+#LlZd{`FcfN`jqth_&Lg}> z<W5u<5iM!j=Trs?b699E^hbCv5c({<zX<bRcpou#*-)*yn!UH%6vN#tRIcv+I1}Bg zk!wvIgC6|{qKZ#8_r%i`-=*kaZD5D!$yT;5YDNP;gY*}vzsdl;6ftiWdxFb08w<0# zX`=trTyB7!8&o=K<AfuMf9v{o?vw9am+`PD-mLO?a9O7=Up&@)WlZpaPW{jS|HmeD zNG6(m|H_~7(Gne9n1Ss^_xK~v%ekqSGf_gSUgUI%m7o2}z9+mNSGBMIW|2#47PxNN zTD9rfdeKHVR)6V@gI&*?MkM=MCNu=z6b0?2TwO~R47~rmk~J(73FmQnHvv^Pm69#Z zjl}Wy2uz$jhdgj+Js^gsv-L{JqMP?kNNsii%zRfuu7A8mhOJ2hU)2QuBinl*oIj&R zqhd|Zwu;W*GCgRQbwf_#$xhwFrO^7zq4>Xg)N$L2Cj}~%o#W49QbZ{k8%Xqxc(53u zD;jsR8~OGw1LhAOfjjTb;yT`l;8ImOI#~>$8_oT>-Agmk%HTdfY-nOt#+xKeT<^#m z?@A?2_Xfj!MOALe#nB*f&H%b?P9kj+ETQ>MBFIgj!cS{hL>}mm#W~$H@Y|^?Tv6tV z>iNnUD3dhcZ>@}f&ij1quUxqQKw18=|9>pBJ>|>X{EEyv$Dg$NlqGIz`Kyn3yB*68 zf77|%5yh=bju|@s)0^wS=^fQdSL{I4VFbeSCOrSbbH2_s9s4W}<HJAe|Hq#%N$%il zqJ~?(w{y?Kbj<BH6#w-t>{l9`^cqgv3uCxg|4guD-_YfI6xgT*$d%2O`S91Dj<)I} z!OM64wcl5J)$A>|`ER}r-rDQH;;UMJ`_-6!%fiyl+ErRdb4AZut*zzSfBcPI!-g%E z3c5OfV>BpYpg8J%Cce+B;=C@7!M$P)%w0>l-}*j~@KFUlUDtB6Dl%Z%*=J&fKq<2Q zx+@%-s00N*tH{=2iel+yNsyS8{h#sfy`52dnhNwW&Lwrz((yr!XH~ylhOD>4{~Nz| zBL7(I#+tvsrL<`2F_qArf3>y!#$#`WnEdts@#4$J?D|Lk)xv8*c%JLnnl4$HFIC3l zO}JRLzV4>0X_c3{5huJ}M(JgOn$%~0Fu5fXp3gPo(jdqNXtQ2lPI%6RIl1H)s||h3 zgucB$n2TARiFFt2_>FTOh=jQs&emVu%NtRpHpqw*p7RR!ELtD+zRD-f<UiN4nf9h* z`?^hoA9vblj@$cV#Z0#`eOc0L<SwQa?zT~%DaPhSOe--xw*7|rcBVC%F5KJ8qEqWL z-I<r4t#ePT?TE6<U<?hPAwjK7MsPy5#J+LDq*y)FYTfc5z9mn1T^&-NiL)xsazZu= zwa})<#s$plb#S5Tw*PSNEPF<qUhs&&KGT2`GV{oz?Z?WS!Z80(108g0|NrUoyt~Ja zv+*5l+_0$i|8(a!i3)?%s_9FfR{mnT^}J=(XBnwcDh0Y0d{Y?2GkeV;HWrlWRHkQI zs92n0I*Mua$i9DdEYsBn`~TW^+L-J){(rjjyG73Tl&aNZpO0emV~(F?)wl}D%CmbW zA3w(Y*~RQ%6ej%D2bi`wxWR7gaaN;m`Yn3SFURiKgD^N;)<CnXvTSe3hQUPFJM`0` zOxs6Hk6^mYuBKX+*>lYPM&qsOulK{C^(gDx#r~}l`6X5Oy|-=WzZ;fhTXk1-w_>>T zo0IEih9RD7qy|)>q8rm@7aOTOnQ7fVD-6d~HPWAY|4&cWI%U;qe}UPX6z3e1V0sj@ z|HjT$$E+n)52L<UvTuISEy}jau+nvulI^=H@#{HwzWxGjyY!~&7SrRHR(t)qx<Mfd zOIe+5?+<sY^Sq<5rrRl68j%2F<(JYA$M5l*?j^%Y`AFJfYR>OkHCG()Y!2AeT%gMR z)`~4;q9DxdG_Ak>!EToCY$!{6M92HQwX64;4PI=Wf+*j_F7)9XxG#N?_CC1LCjVI^ zywo^DUC$<B^|_^V*k%;{GD^Y7;+gcszFGXot3yRv@=@r={Gs|5qS2mF*z^bK=0_@E zf6)gH_Ug^8`_&D8X1c*{@kwI2bqf2&^_r~M6+kT4O^3~|K9cPpw{iPivf%SZGj6#! zm78gt45HZ;+@Y=EB)q~1AN#-H{2E6=$)_aTCbffG>l{bEbZ;!*Ra;`!c?~^t-eS{R z-`nOd=bP5q>>H>1S6}{7U+#S79~%#IB~)`72Wn0`ICiG#xHK2|`u#FVR-P)pH*z+7 zc=L$ty){5oP@4riMh@W4s5*<`u`Glg4glj)J?Js%F*(iafzbZ>uFF*^FO5jMYdY*2 zWCT5m|8SR?pOtg7@S+^6-4HgBduOeSQ?5KCA>H+%uyP8Phrc2R)&~)x4+fzhPJ}e= z|J$$Z%$}(gZrd}hJAaE-%k+vCMbE!Fc;)L8jRTMTwNbb<6Bj;yPWEtO?th(U;qMjN zU%!@!Ef1HHj`>7vnUsamQx<Y9kG@t5eHO-IX(0QycVrFs)}o&{vp5k%pK{1VneJj? z>{e`zvB}+-^w-a`FC%S|cliF*GoDzOE61w*y=M&>U@$UDui<3p?^?A@(`Ld%`d6Dp zXjb%C@sD=ycv_yOw({?>i7SUxj5Y25*Ct3IuEJx7)8ClxEz7K^+ot_j9~-u;I<+(m zUd_8jHJfv)U70=|e~X^qDlO6w&4TSupV5z{TB5+!A@FU@OWN#{j<;_aQ2E1BT+zA= z{2eVr3-o09BCieBrcP{~w&_8t*#Cxg9n&JCgY<^&u9LkS=Hi^u2WjH{qQ5$f>0T$M zTbnbRa%R8e)j{i<Ob=uB+eW5CH?~jb<+@RPWlRR#T-lqh+ceL1Vc4ar19q$q%ExE) zg2la)bWsTGt9eP4`>wBkcRU%Jcg4{^{qw3{GHt#)j#`KI7m3fLqWcR^8XRdP3RX_T zaOz3}?UKQL;vCX)w3vUoBnb@UvPj*F8T_;4Vb$@IqhN0h(wZB^C!-=FAt>}5ExP`! z`g-+TxR<$~UYq@*`a9FL8T;wZQ&UA7#zn!*TS$ApTO=~_jD$WH&(SY4l5t<<JaYA* z1%G2?5`Nz~pDY-&jL(j~UiGae6-l8dZ9h25I%P;2ehqe^+aj8(HFw0~UM!(erH`vy z3S!asR0*}upC$V38jnxg@@dkvWuj-@6VPl(9)<V>=*7OXWRH{)4>>^~{O}-H-NTaH z7%TxR6Q+Q|Ln&_Pz9S;-dbZ9a7<p6Hn|XlMOnCDwf?s#Z3p)b(LtL3Jr<>$Z9XUQ8 zH`e9Tto-@b(FO_VJ9|B?TQS6@&zOI5M(^h%t5%<Xa*5>}44${(gnIL0E0g#HOk_T6 zHk1+5ciOPC{Rz4GdJy(s?@0<H)F5`4D{4Lma_nFt)TcO7$-8@q<%}4x0~I<lG>_!} zjt40zb8&6<FmQZ10@zM0Ry%Jri4Pe8+uvES=gI#!F0|hs`+}SD*%-W!*g)bfP5x=U z8LEG<0^zYjn=hN+^E>Yv<E}y*D0|i-zSNk74{NuJ4<^=<o__+-Zw1Rq!8}6y`MR<& zbiF>F7_SJL>#g9O$wM;GPZ3moe86Dh4bnTifeQU>U#Ab-FAqk{X`sUSdpN%&6R&IG z_^d%F92feNKIpROU}y%SjS@ZT`?zX;oem}%yW)j!(lq;ZG7kFXL<83ECONhtXgFsV zRgbtuF1{UtEqZ$B%KDYd8nzK#eLbW`s?hP8g9pV$bcEg~ns`+g(!8{=_v2txEodVv z68iDx7Cu-!tS@@pN#JLf>!aeQ=af^|L7^5NE7U?8nlk`rDtqAaM-xR4ogC14P)~gP z<Ps^pDT6L-4eM8#t7KDDFI-nK9zMz&RxOmWuaY{Pg?(hbxIaIJ!rK>pardBa)a-`| z)W0#sbF6RpVrg%PTzi<j8u*R=$lXP*y2L@Pw-Xmt7z}+QACfU8A*7@EDp~z@5RSY% z1TNi|q`v#p@gnORK4QEwyy*Lfh%XF<UWICWg?114%xe7zeKX=GQya&d)RgrN7y7x! z&zcN9kOCUtdyw-1&&d85Z8*U4`9t%w>eJVCpvA})T{C*q=#pgijna`WG`FojHX#E_ zITdOxZN#rTodqqk%*D+LSIP4FAoyloOyAdx;O}2HgAFfPe{{jP&|V_4l^?mq7`C!} z_L}WVILQ&XisiHLSfPzU=tu5VtuZbtvH|z?TgZ@Z@hCN-K%5_90I$jo(Ph~|Dx61X zADn6pHgfmqj$lQoIwB3{j<6b$F^Vw2R}Yj24TUU&1}gM(k)AIsRk}uhBsWmu{Oi?p zSr6<-)R5(~a9rq5Pvc{xNIMGMM=4Q>B0sY8jVeZ4xnf_=jVPNWV*6VsIzmDn;@m`d zFJc$9tkZyzWnXC}%V&SACswT2$zzt!mNGj@;qY0|e7J}zI}Jhm+^6KJrxrdNnT}hZ z7?NQb{rK^_RZwf454zk<;Juc-p>z7N^{XtOg<5#5Pz!BL6}Gd!J@c?H%V#G;IkX8U zn9cI}p{_knZSBcE1zshZ`#kXS6?OP{+OX<s=zg*{d@kzBcyaD0y&=Y~n10v&Mw=E) zgQa)aH%OMxW*3G)3iOBRL%-2U^`_znrCFfo=fs7qF@~ew?3*LYXUSozAa$~Zda!(c z$cj|Vn4W^~Sw1_NQj#`l7<A^d!CXJ;H@Jm7X8A1it-fg)fBw!p8qV@r=%-wcCUw1< z3iH}nKEKn(1&q&kSU!Kcvxk~74!1E5cY6->DC4t!sw3^b-jnWS+>T+~o}WDoGZ>Rw z7?X`d^XL}F>X;tpVp+4%G_i}%2V-CG(-?<6Sl$Y4gvZXmsmXm}d{$)nT)6o?x1Vu% zJL9nMSmB&coE5mDTUj_$WG)uk3+Gvub)Bj*ZjT;YOb4vD!jFu}+KkD2bY)Shi`D4u zgHDXk-U}P3&>!Kk-I?tc#_A)C)ylVC(Ci2;OpzXpLYtG@zElUgX5guleW}p5V$a96 z3mBgh7@y0&Ns}dv&jT5s-5Lj=QWu9UZ0o6mzX8rJ)<Nf_BARR(f@`Yx&?+NU{KNQs zm+|@2_r9Qi&>O}apTh^Lzb7g~bwOQC2dCp87(3=I&FM1`r_N7<X-$??zULfXI4-nr zm)l9M51j`FH5Q`tucYDTY63Ddt`iya(Qr||C+01?KrWZN!+2Q@%nFvZ`(N`EDcak1 z@_8WRv-J-XyvCS(hvo3EA4BmaV|5v0b+)uOE@gav$oTv@cNeW?eBR6W999^NgBhPi zET2!@mn5A`KFf0WSMyc6im}?9<+jOqW$fg0CCg`_Z)bO^abm{mPb{~G@RP}C#%B|j z&%)ob$<LY^Fh2KXe6A08M%OYvSF?Qf53;o@V;rty9A<nb;f&8C=Q~o@=g;iQ7`MB# z809NorQwXpj~J6{q>Z>vR<8{)7w@eZ!BNKNqm0iqqLtHS96rwSS!g3X_Tp?;n#=fX z%knuO<|99oarhqNu<%&noR$&!w0v4TY7Ms#3+;vTXg@K)?JErNoLe!iI3kT@jLCx; zlYgXGBVnx8nx+WA_JUY3KCc?aI4t-r!eia_eDM%tbyZ3O>$RhU0d|k*yPktlXtVrm zF<UbnjayFir9$6Iiu~we#^+?l=dqj{RbYJ9edok>2h>xWE)LsiYM`EX2OY-p`P(m5 z?42({5zA*|nVqzg&tDmz4;%Qxn}>ZMsA3L(yI>GZW<A@oRdq19{0-UD!fM>Je0B(% z%KA(Fpc7a=3&(}_370h>T+1C6lv{}MjRD5UNJHB6>%_XRJe2JuXv*^0P)`va=K15K z@v?URYo7Yh{j`(M`i#$y7EHrMT})=I#!goMV60|*#(()d<)*2qlh0=V@EQN*^JisW zI<1Sz(!*5oclkf8wl$?Ri}AUN<+IQ?)46_RB4hP^md{t4mT{eYj$-*N{4Jw$G>J3g za}?wAXq;QwCYy$Tw!6`Ru0cdz#Q^vFuzkTBSJHvy5;&^C7q?Y~^Aldh;Zlhm)VlFH z?^<ucYDJ~uV3(QblcY-r%zQ|njgdsDon|mYMgnZ_bi?chKaiKnCinl`r>C#Xf;Sgy zI8k#iwC!dKQQfW)i_I1|f65l(ZZQZfn^mw|zb&Mf#b~H}Ws5Fzr%~Ud?0xf1b*$<W zPD_S4v9)NDm@KJ>pVj)p1S1XHuBC?0{G}nNk?pBm9f+sWN?7lub97hOWL&3vkZj~~ zX}MWED(HRTqKszI$7zYkHw_@s6%+7|ZFl0eoW*sAC6=zcOc!|cgQV|ASYO|%cwl-3 z8SZ9|`4@kY<MSm^aiJgfYIYztQ)RJxMJd1S^$D`YB^u8~5&Ci2Q0P-&_n-41JU;~n z3RvRd3xV6L=&4uxX<Xw>)&r-I7ACF`hjygE42{XOVbWt-rXB)U-+tlp`Ex{Sj6K|r zltq=s;qW2g7>RQjhFYh`z=yJnqOI`*|D&^J^@J_g6tO;XFmAflokUt^pw{3Ge7PlC zZ)m9o345xE=Pzee`Fez#cS#4%Ia_1KjdFS-UmYye%<z5wcbdLb8h$E|#m&2~apGPY za8_zBUAHX;H&0O@nm%G$Nh9!^gBH<u>`mtQMPNU})AWnc3hw>HxfnKNAC>vqMtY`5 zU}KUs9=P<8g!E+ngqND*$-Szu!|kltaF`b+TMPg>`Bw1?wwGTxuJigX@t>gtb6YI2 z^->?uvMMCitOu{qzQ@Cxyr?1$)L(C=`aMGVV}1g6q`o6i%G$4Ky&)I_s}SM<fU z88Cd^J#Lw5cPzQ!2i74A$e?*<*d&sIz4Lz(|GT<){_!x_rEr6M>gI*R;3HQl-47C` z491`XI`D2`6UiB*T}^Jx#plZVX_&-Us?sAE)%t(o_Oz7INg-ii7av7TUvJ}{v$`~j zI@&bBh2U)e4!Z5~8&dsK30~Y{YeokHe%YxFzW#PRcg6KT`t;zJ<cOOJUioN@E5Fo{ zX|khW)9hX-nQ)z-{AVfY9h(4IC9moFf#&2velUDnG#LF1N6@Vq1oYC@*|m7BCbef1 z;F#SNj;<UGE4Mnph&>V1Es=xB2f9#vHJYq0aD&@3Rp52-7(Ue`0ZdialGME2#5p_~ z=BAjC3KS6=)|+&hbUUAWm;;s5!=N=;l3G<M0g)O83ww6MjF3zi8eb|lfAE;^ozqTk zzdcHwRXkB~+fX?DNP^qo?||~7V!?K712?*EKP}FFK<=+>BrZEWU{^~888p6(?24HJ z8;aGTAnG|8`^kXS(2<2P{1x(T4S`>;Zj!QE3z#Xx-Y=>ThXr;0;Zfu}QrjL2XL~!4 zbrV+;bN>`Dv+YfyzE~2S!cy{QWDy@86$8g-e<nY+nDTxZ)1h4{96GFOMR#Lv5|bg* z;d|cdYNZ1$MCiY8&XxIQI3hoamM$@Zt1mmK^gJun$Yj0h*fUaTbU1oXSxow8bw~F; z%DB6HFq~!2S^07UxtL}bI5_wk?LKq}p3fZ&72XP{P;!^onK>Q|)|5~eZ!0hvFc30s zH&NT?mSB^s2ns%1t1sE4KuymGGK*WwmzJc%iBJ`?J9Zg4zath5-vrRlI<6$|^&D6_ z;1Cts2#@{#rhvcLD;+~4bXcvvTikwjf3&;3fbMD-2#FePWI1S~{kE^9ZQ>W=l)z!j z#oq9!rz4G><B1Whe{0cWcWS-b0{88bhuKqg&~`;H{I>iBvE4TitM3oSqZ##N#h2xj z)=b6SiR;L+5F_+lWQ4T~pOd>keaVwwQ*jw(oA6i<%bPXUIP>93alrg^*nDLu73yu_ zKj@J64q)i;fW4cr!C0pi<eIHMm=+r1XpIHr{4O(4w=%>ZH`fxoYbGH7)&|Y)Yg4u4 z5%BJ?4Ze!<rOwj~z<&A={Kfv;TgK`arS-#lz0r7oQXc75i~QTIQCJySL47;o=&Xcz zG$^y87PoeiMYYzrue&x*9&?U3R2!f!Tl1dguL73wh4iR_1FjaU!L@@+=t;HF=&@`7 zOg{RS+tfY=d;iu1v%!POmKNv#Xraw{85xK@&=)G755(fd@}T6c%GMXFp{>LcZi!7Y zc!kWRTbn~fQ_iQs%vu{dPU{P;o#qU2)9;a@>@U=jI)i?}9b);!4LRk3ILGz`$MfS* z{ns9<(EA;2n4^RxiS;x^-3HISKToUI1>we}Wi)V3B$hNTBX^&!AnhwdaqhU+TzqCd zt?UtwRVwLxpM!NYa@IVQLv6Zez%tTr{{gy4ltVXGhoa=&dE98Z;izzyV7JU&^rW{G z)$xeMz`o1Lk{+Ar%;E_2>A9JbQY&6ZCLT{6-$smHdT~m@^ZuiSHky0))5i;B$u5T& zESwcZG%tN4>RuD^j)p9&<FcOk=)2?9#s0M6)npi1`i}nAb-~;z>q+FS-uP18jNLn} z!H54XTH)15n+oi4r&)K5K0cU!(0oo$gipuZ3Ke>gyF-8VpM^e|$LY<Zw&<wc9~V8_ z$It6Oin_i|MahYK`4-VI`r$wt<~OGC?NxQ$wc(lQvUCj}aqSkjwKW5!=P%-)KCL75 zZ^Cc|pU3mEHALoJ1TG3XL5sbdV3)KkN-y6|i6I9Kaq9mWxA$<v@-S_%n9*Nctuq>n zcCf#RE&K68dliRyII&?ix$7~R82Zk`&vBu|EhmU*$0eZp6m|N_BZ<t_O+YDoLwYYM zmdH_WoU@@Hrg!^cS5@MIPi1sbqsEed=eLQzFpr@p^`l@utF!8UU_K4#9}L&OMR31Y zALGVs%7p864cyU?c_dSm1oJ<}l9zMzU|YHfBE5r%a;OIQcQ}GsBTqJ&x&Sv`lI=w( zC&~tHuvkG7zQ64T1=60dtg49oFPoED%|v3k9}M!|O`gQNg70Zf_!=)uX6O0A)}2bQ z;VI8;7N>&g1!J<x{sG@@ZaV1S>PzOn+|7SiW8XsiY^O!;NR!_Luo`Sf=o+I28vR)j z8?_e`$LV81dzmJ#(sQS))SRF&u!TMp+v60qH>CLd61yIE*!%DbYg+K<JGpqn250sB zN$uxZL7(M$^h}mM`W~<Yt4q=(zGnD;bf0M>Am+3RxUYRryU+C}OM+6M@cnT<)xCti z^K*heuJX{lc>-A>5r^&1v#8g!2wKoH9vz2{C3_O|;Ob8Wyl|D(s^74Mn5x9#WA*QR zO>{m9o*aQcH!Y`GTeM+i;!|3pFc`m<gtB{TEpNW=CVlxr8%lGXaE)OfI?;V3c<ANY zr4`%YpCuZgaPyemeSdeH_eupwTD@KQXCEvVvGspzRk-OY1Q+BwL)}C})-QV?Iw!M! zoGTQ$N5?(z*_;QYE$0l4+vJPCuBc((m1{)Bfu7j9awrBCwvrq9{qW4vncR!B5@397 zGVV{fz~7kMm!9sM{-1H7y{$|ueYh<cdi^Np=QlKRgV$xk=XP5$eO^orf6c*w(_=_~ z)9Li~ia4D8K8oc1F~jn-UT9hUf|yJC;DqJf@VQ<dky<$nYxse9+xH>aMy~LS?Nf2r zL_+4rPQ+%#NBn|DDM%U~gB`}hXnwyUlARlXGOr}5i)K%-JL-vHe-@EZ>>YN=>kvF~ z&xe@yzDjm0xZx-HBBD|(3&y)OG5yI9ND6#G4ia^go;(t+G+iV6es;sOQC4s#@jF>1 zyPE5LmHmBprHQP`uA#>bCV}k!L!{iqi>(!y0v2VzNZ%=sXx^Y%u<(qSlkgLX#FM0O z`urelv6KO|*{VnfYG9OwCwO~pq{}8qp@s8Za<}(AI(m%<ZhZWOys#L8*=B0!z@Dq- z9$QGG$3NwrzhnTk+~iLk$m3t1GeZ3}4zzloB{t7cq5E(5!xK&(IA``_`n$D`_?+>; zTd$|%@}F0Tw(NWwHO!oSS2qUdITLC3DLwJjmvLYlI+l=RZ9H+z9@6B3$p5n6&~Ge+ zH@qR!W$Q`kK~45<XC{m+x=#ky9pDUQCP8j(cW}{j0`_i*Si3b5p`SwkCmdCz+vj9} zS;99_>>o+8vmfivH)9>^$-wh;b0!?ucI7hlis>OO*6Uh*B&%WBNIKu?mnV4Pe#NVV zWYtksT|Z3h&w7Th9DsVeEwS*|R!YnDAU@v`M?K?7{+G+-?w<+xvG*JDFzPr>8t02K zw)3g(7xrF+)s@&3Q)HJLt;_cExuCm|2;{JWoc`PgQ-g-W>Z}^N@*I2iDA>wdzSG5@ z<DKzro|h=_S2rwPG#R(-e#U>~v_X^A1pU%q2L{`9hm&clxHsI6t<O%U!E5xeTLG(2 zraJ@YTo0$uR#}4e=B0Ga=%LuVeHtcxd`s&MdXi<IkJ39qQ?TYlC3&x(j;4<W(u(6d zIk@AEm836zxwMIExjPRh#4RF+#ttIGBVzFUfMfK+s%f0Hiyl@?X0_)xv1ip?nRseV zI@kTteolA}h3ED{YBQ;<mVwk3bBt(Gf!bP4n4r)44zpgmDYCxw`x{o@;bI-xb~%9@ zbDxfNKiR&U$YZp%!Uye3UJ;ebiRAXVDY!}J9=ZEsCmm%Hh}VCpq4d^9^1Z_tO@^n@ ziq*mBpL3gLsSROu3?7i>sXFL+r-)t{9fW(l8mQlqpY&3oJ@~skrag|x<L_Vv%&^l# zm8KwE?Zf)D($yr^U5*aX&%jwZ3;3w}mN@^T1}LsPPOkJYgrvqHkoN2()v{W{Z)e}~ z%R_F9^cPz|;)q`8dh7|+RvUve^%XJc)oSwdX8|ugfb9V_mf$L`dSYUdJS0wxCx1d6 zVE@5aWWmNSG&y#m_{yvd=zXI1e|+0jY7GVKnm_MbPPZN(h0iW%VAILnWNq17k;~&O zY<=h=g5#5LEX&JBt2Png@AbDG0^`Q%!OWkHG;5qWmGMo3-71^;GuCckcJwP%#jA8^ z`94zUI~Sw87xF5t0Z`poNWVHZ(VL}exZt@3s(d^{^7E#k>hMQo`o?t9bfS@@#p;p$ zH$!l=j2i4P8xDoPUQvT-#`J+j8Vns*!3$$isy7*DTz^l;4W2^QJa9tI8g<Zm8cY&( zN5Hay1Mt)Q2lT`zb2#nO6N=un(oyrhQE_Tdye7MtT&taodk=pi5#>(g^KLVco-7OZ zKe5^!XO8m4Y%l2KdJ|S}gae7fKlH$amo$EZG49(u5|i|!h*d)v_FPd;xRxN2e#agz z$;&~`xl^=Hod)05lnOJ<+~}hf-tcDWJ34koC2hIq1162n>3~Po)bNZ0Of!}PiNj(# zd9EfBlTm1~d^d5q<%bu7ev>SNmBcS_viMG3I+R-vq3%)haKG~k`qW94sPD3+ds!`% z{ICtY+r8OXcCUthyF7~IWq9I&)oNh6Nh}I!cEu=DE%5fK<RZ7ewcBUO-sKM3$&)O1 zwDFQfHJi1hxc3Cq?eUYElq8YNFH>;;<R3)V<_OpQ>l7Tk^aJrHw&e8EexjJ#Ow`|Z zjxQZ=jrI11xcHensbA=V<Jah-aqA9|;i^b1o_&V&9bv`q^`43E74MTvUq+C$HGN4+ za54rSb)m_!X4t-TBrdA5Cn2xh@aJYNydS(od~d`Ad}6BrFN#OmNv)ZVQqP_dwGw?| zH#8P~)-IvYJ(LQ$7j8Npy<~d8x^GkH)(*;_%uR)=!FIH9Zx}9o#?y1`317&)P`yAb zjQLEke-eE&Vl-a3{DXdZe~$`T=gT=^znm80^zs3XWPe)Knf#!w<P{Y%Q1Y!O${Tzl zPybZYaqQjs;Bm(2aHF2w_0q)CeTU<)qYp?QsRGXGayovNRwMx{xA42(r{kpoa-?s7 z2W%XohM9kAc=<hpVZt52!*`XadEaT^XCFXyzBf_dQAwa^k;P%p1vJ)t1}y%)kE+WZ zq=8dIVM;|I6*aA=`aww`(f=qnaa%Giof!e;Pp^@&8rpW7X8Mr#gJwX|&^u)Rm)msw zGixZ_tq37)#q{RIQEV=CXlp7Zx*=1*ZFLo?X*NU$|E1)V@kqFR*A6TA9fZ#u08aB< zQ17D-y;Y<M86!qv_?p3V(mg{syiXnnusr^_Dv*Rkc>*`@Jqb%aO@?STk{-dk>GGUF zjNIV?VX2nftq652m9Qe;<U_zlqmjfMb%g<*+R(>i2`{t}-tUC>GU0tnc;6B7R>)W( zSA{GUGE>M#Ap?bc6S7Ol86gLR*P}4^gx9<9+7w=Q!s{r=CYS{MG$769iTGY~1Y90J z91QgLlCK4$;A^8ctA~_Fgz*)Ba0Z2~1Hf~P3t6??3m$GbOsDZ}G__YIcq={Tg0yDy z6Mx4*qhcA6pBFBk)jfqQW#9Qa`+^H|X6%nNP&Tk22@hwAgwG_xXEveD)*&H~uAN8i zSPzO1E23d><x;M9X*m`CTS6Za79J!<?zOZ@E(rS@NWps3uXNZnOUBAAqVSF=OiK{c zZx%cFyGtkH3k_);6<<MXJfcxPFNK>qQvr=0`eO*E$~Q--qTviF9JXvANSM0fguv5O zJ6nRSH`0Z=!AAIc?ip$^DUEcPCgJukNBFT??flc{QJ9-oMn2(Qs-rm+uc?{9u#bKa zZ26h)wJW5D_Z=W_)#l<A!*DKi?-jBAy>LwXaGiA1s-aWH$m3ll0*a61!1P$LoolZE z)IVbdo8IM!gRRVQ{ZiJ4cc}rLkO{CX(gr)SEciOpkr21`3u$=|uyf6OQjyU?Oe8r_ zEM>hK*E}WK5w<YkmlW(%eM<1G9psJe0ZT_pz(Naa5P7wefDlQjlrV+c*^*#(@DbrX zn7`xuL6zxCvi!FJbTq5M#m~-M!9fo&by3I6rb?Qk(*q(lv%gvEN8lzyYdF%=hQ3-P zjZel0fN9B7UgCoWzLIf=0jK-hUfd)_x49+2<+N=2WMmUfS*HNU?^uCwTxh>`<qul? zr-OX*uz@K<6yS;TBUY!%3WUcBZG81Rh+V-?Dzdc!xxVh8(4>J%+D_Hl{S#ofn+)CR zw2%tt5!!25`$J~jLT+TW0t{Zelw0iX4;xo1fTyDtd2t{Tmc*4&p`TyMBO!FRCb^qa zMuqcltn+|Cec;qI)loPu^v7dNAl%LEfe><^@Ax4JPh6^~9Xp4UpIgDSfkyaJ#fEmb zi-yW!>9n+DIkny93Ekt1#fRsp;mEh!#acT&VJOo#T+^w1Ks0zgT1F#dJuqPRhw3fL z1MnTIBYG+Ks-4lub7C$w%<j`u)*syLi+D?ul6WMu+t8cU%oS+iu|h4hv6{PyoLL-? zuOE&VHGZ2eK9v!PJKvlo``hNA?$m1Aek(7K*!x+yHd2Z^kDu-2Zg|6MseULv#2!U9 zPX$FuU((0nCDl+&0^J%dvSI2(GWVn(xw>d7%r$vQ7x(IiZuRWB#L1GA+^0jz+Y`Yt zcp{nQ?*w-mM)2D{=!2iBEgWXOVFHd;a09;P@Cw?FaOKt@&{lgzCE|0)V#y#7`lkBO zpRC+=k1nvA4njZg7?@%s>%ErK*2XQ=N}w+fIzm3n=Q+=$aAw_ca(jadI-Q)s_JH3f zXO39Y5?6PuWotpo#ZP$`i6H!G(G%o8^|FnX`ama72!!(FY`Xb^Iwq-95I<HsLpUz9 z&o$M<lAdeHQy&|U-7p-2ZUs@PCsrUlR%kQ+x-KZ`uBV6WY+#{%0>oWjN2i?}UH#Kw zE>t8<As4+CQsF#8`z>A$5Z6&oN{=hR^q4r>y}KtA-eUQj&(U;l4nzl(QK6qNIByuh z-kWbwJw}D|%d>rZ32OVv9G1_*aiKp`>{3C-)|Q&iyU*Kh)P(s9bm*~c7c^ZS26yM4 zrZ?AE(^TaIux+p94zYZmE<YM{LUIUYIXq(hRyr?~fIibTXOwX9ST{Jt^7(ZL!Q&ly zl(KwI5XZ1@)W=valXK!t4JS#&^=Pay`63?folDl=1Kh{*S*V4_3boK??bU&xxM~b~ zeH|})QCUdtI!?uvET0GNos8EV_feDF3&fhe`>9^Emv-F!Z1<H*g5?F-^jZnwu10g< ztSA8?_AhDQQxl;~rh|-Sxmt4M6JJy|1Fo`sKJVa<hYc0sGt1|I*fDgGdIIP%o6~-F za7ZJDTxa<_^yeHn-QzSJc)Wt!^|+WSvORx~SUwkw?t#7<Cs>WvAQ1ZYuIeZ`LiW;y zET4sb7S+ze;qUK|<c>CO_h)Cmlg}erKEGKc4Uf7w{H%Ti<aP0RaZ@EpWZVv8%&FZZ zMLL;$kujOE7ye~6V=PJP;xl6`>Ev)T<FL?1c<jU>3V4a}xtQ_!kbVd4&p2$vI4nF? zIOmA+v6wxPJ*TejXDhT9&cj<J;GzZ6^y9*8I%w@uei>u(2F7G9Yk#~lcOhrQSk3rM z|K+pLAK|gB<&kK{SY69leSI5yr&b2stLf?}v>BHWfT0f3s3rG;7y9=7ha^5^d=~w~ zXZ)AXC*N)t=`aotV|n}A+6$$+T^D=is$%~8D0C~!px;zh(ig7jM6Qd^HZQXv(*A|r z^Z8BU8L=L)tl&fSewN#@)|>3M$$Fx#t2%}jZK=NUgt7Zzt5`TLw0{Nha7wh9%-=jx zRO>Yd+Q)|49oln=RIkVu{TLX9SL#lY5%b@Rr?GiHqz@APuXz}s@l_X}8Iw_=i^+`D zIG~Hw5hwlVzkFWWs~>do`N=<grvLIe(9{<9FeZC2CeQYF!gY+*TUl<~e9htH8K1AR zd=~nqruK@wo|i*bvfOTc;7>CdpO>(F7XFq82By%!_`H$vIYBFdyz1g}sjEBu%VEZ6 z_?OQy&!ixfal4UmdzI7&GM+KHk})|@A_$rot4qH2vfX<@9cD5<dow;W#zGw9@JGgB zp^flZ=?%m2Up_OgqDmKsg~tl#4C<SJ=3my+)Aky+LVMvn7p&%@>9nb&=c;VVm`wg< za=w=XCNNf)F;+7^lYjXv^hbCsV>SNE>cwAe@sQ+xBATI&LYsc+DR}jR3w2U|!3%w3 ze8yQ_d^TGihUXZcyRWsTX6v_-e>vPw$`L1&E+OtLpUvLIqqgl8POk4tdhLu7EMk1# z&-i?@CI${%Dx=dDHHlw@5Lm%jeU0Vw%c|A%f{Z;nuzZf5SwVl7MdLV@&%$w`{i-Ed zpyQChSL_=p8Z&A##9rP*Z|uE990wQD0{LJpW%-=<=`1~(6^TJB28sUHJU_T3oXYro zkMUXd)I_|`n9MQWUW(>$3}baDWA&vYpSXf9K3{O~hl7mI3eJ{XT<jRKu#3-($w<4H z%vg=5x>&vMaWU!S^Fx-;Lf;sx!MlsqU#gDMfB7u@ExT%Gfez#IV#epbc4vvzWOm)k zUf}oL?*m_ldc)ce-RK(E#pF<4ICzv4(x0nysK@G1NS#njADvX=)~$<!mc>Q%Nlg^J zS`-F_Ymd@Z9IFZV%aU7DJ)iIQI~fKB%%PuFDDbb66JVp`avJiwjBoklfdiF#!%Jm9 zI&pY1_A{MIe68Q{*H$N@>i8MtjnY8sxyK3}V+|l@=^WZ))>Qao*iJN(#JsMFGqjj# z!P=?1^kdu^(p)|R#E*06<E;j;hywhyd1zM^Hygs+o5=g{?slyYvfv3R7pb_P6D|Fo z1gm<d)1hs0-2S*mQtiw7p`Yr`C2SspE=5nt#C7*c?vr4w+JB4Kb;}?vzo+8KB@N_M z#1eKd^2IL+tiR`!%Oq!n7FzG;$n71DkaSWVpG+G{p3ZawP3;c4;)kcWIxrYc1ghbw zP&KYH+mk&nD&o0|9A~KJ58XZ6=z{Mt;;}l@;QjR^I?P!aq|(NKio-ARO5YVaVlR+y zCs}QxS9eKi@pzb6jP&(h8Tg<v8a5X#C9lty@LQfHz#YCn92;|#uKs2Vb8hv58I8xO zJJ>^0{{`gO<J0_><%uBcZ;i(^Ysrvr%FuMm3ELK4B(I-$gW{kzy6N2J>Pr1-P_w*^ z#y;Ls9o2stTwPx(YRJyQ4f;{M<kinywqFJgKYM@+8uy5cew2Z`F0bJ9LKlmMF3ZBA z;3z)B>KNJjBpkzDj3d8xv)TfCLvgJ2II{d=8jLH@CU5v^{@3_)^#3DC1Ftsm+D)0b z(J4-RM3VA)KT|M8e;l#*pU>xy*hDr&o+QWk8E6x6iR9HP!ok~i=m2#@;ZQTFb9O^o zl|+<=7m`8W*tf2{hxD<Z4Lo=xhc9m{p_$1q5_Hx8r;Vzo@4x*fI?Ek#M!*T0?Q9E^ zLi*!J-)DB~e`TR(>)z_Z+I3X2d>+oqzR&L#@22J3WAVoKH~juRF4&%<j;B=JsDz%L zcuNP{d)X=_RvtHB+|2e-AMzh4Uh<@Z>Kc|4*@KgD<C_Z6%d>mfx|=v`Ff0<S&)r9A z@6N@Hz&NTox12c73T3t0OUO`b4(jjr#g}c>WJA(OSa@CwO=Jp4;N|f!^wfJQ<Ft<~ z9ODNcCw!u-!VmJF7R1oP_9PSsY~V+iC(+8INmy6CjgR{tPgSlY;qcT_zIl5TT_}@` zmu+;(N0|Vc&@%};LTpIAu{&M9D-kFDyuxirjHffkB;k7VGVbp2RH|&5gl`M>(I`nj zuu^QMo*y<)pY49IC$XI#f4`FCX~bjk=?>oF>Jrk>5|58Q{NSnKQquY|9zWmz!TUlk zd94(W>yCEtG2PQ3{k$eM=YH~%c4w&_<Hk3}4W}UywC}ShXvxc??lS$bB-0bdWc8q2 zzx5>PcPPZ)ETC1Z#ntJ-F~FyvphmBAiQN2IVDqb#&iOO~ns=CheGq#Nw@U)Evy;fn z3H|6%-DKF(e-i1>f9IW?oWW|II`qCig?@O*dOk)?f)A~kwDOTTrf)HUaYr3!bK7LL ze&RPtPOjt`2QZRx;5FmG?X3p5jPW6x@qsY`r$D)=7h{5YY!(iArNpKFn8lxZoQzi_ zqUm7nqgeHKGPX|mhg~baC*f?yje(3Co8lVj8O9BsaU*&27;t3V@MqlE>E_F7r2NB& zPrs+adB%-$#*LLvg5e_Li4o%o;|6FlZrowqNI0nu$hh(HA8rtZpZ{><k4GD6>*9k0 z+i$Rdal@E#<7l87EMz<pGoF~-NFvIN8%m5Dvx|}3WqfF1e0W@bl14Lb$Q&FGCHBAQ zcg7R*xfclI2A$i*joSVTs1M`AcE*RKTfNYial?&q<2m0Six^K<F`hg><pg&bE8a6! z^zyfcwTvN#j3K*&+Q{Sco2#oCH_k6_Bjr!FRL3xG$gV3DcXDGN<3`Y|#o|sroM3$T z>Gz2Lmm8<9eC9iOV$67Q+Ugk1?c&DRJ(Lb--0)@G_;xuBC64tcN39xp>AjioZRZ`a zSMMwQ$FXcbd&e*`Z^1eKutyqvI6I7lA34Vl{+)$|PB-oFRz~%Rj4WIo@>FzSOBlcJ zTqbJdE#r&&uH)B^*hDvXv4t^&_UU4X71Ysx*<u`ViFPullrcwf!$WePvE?CSOJu+a zlED}<g)wCAsCx3Gi!C2+E5R_voIu7LFX@Hc*V*j5&-=4t)p7Ghovc_sVW9Z*9v8U7 zcygcdBtpEKAmhv##+f;_>xgU@e;7|lCr{)VPZ&2yKgJDL#*HI}MdFoRJX!FjLj0(U zGY{ITX(vOLGKP4lme5YNG<LFu{av`ciy_i71#|{ui#}t^r0|2>zdUJ6Ddjr3v6OLR zWA!#Jh4G{><H>@64cr*UnQF!v#uNIgiznO7%lJ-is4#8>|GdI?@+5@ugmH#m?c&V$ zf_)@{@x+$#Wa5Vn#FO#lAmhn!v!(R<r+BPLZRZEM<x(@Lc>LY|laG4IYP|Q2N5wNg z`McFi=*Vsfm|)e;t3;)sMXnQ7?faSE7ug--YgK9WuZi$LvmZKS7SP%-dq6oQ>|L^- zrZkR*4gK3`C6T6?s#9RC=TWjXA(0wshrx>{4%}L`7V)0VS<rlFGq>JIj=!aw1?uA~ z$bFerw5Lo6$lo49^q%~ou@?hj#4K5Y^^(|1C&H9Vhw1hYzu7xh57^T?h!4N6goT0Q zKvG_bHyYFjNB{8!VEd0ZF71QdE*B8q%iJ^q@!fVQJT;`6zj1yN#=Y)_x@R~2=icYm zG8)`!^zqW-2L7snBfJY>>qO!n@{gx(BJtPeVUN_!{FA7BqT4VJ@9bggfV{K$R8}+e zyonUQ@yHSW!O=`ivJT`ObtF-)auQBD`A2+h=O<caIs*rvSSEh{Fo%y?dxS4d%S8KT zTl(I<jaRyof}5R<sA1$w{^b5tJbxgFSDbd3Zz<2jfLoRv{_>{JLQ~NuT9d3>El2CN zrDBkx7WrEAj@PnELw@*t?)xGKYWFx5>o0ufyk^+*kKSisj>>DUaT3P|sAOV>@?vq$ zlN8!CDjC;><%?IxCDVak$>=Bg&i8V3rV?%`cw|unZ}M(DeaUL_?TPFTX)L~C7T>k3 zrWkg`v06?E6j^*TS$uD6_5(W>_c|7L7GE04;%my{+iQFUZDMhhWpS)Ow3*N8itmXh z4*ZgT<K8%g);|72m$Uf336Z4*EWS!O5&B;`Os25-zGLwnbZ#l}VsT7jaeOSN#LZ;! z)nf5I)jNpW&f=cQ;x6P5dxn9@UC%Hqz7WsiYsBK~q7ewqEbcWd?w&29(SgOck;V6O zR6f;WaeTw#_;u<g8q4B4l*PBsz!9Hy#l6Zqo9m2kDvNL3&QGL*#ZkI^nHY2=L7v68 zn#DKy$Pw-#i~ArJ_j?a>xUjDHvN&?GU2)8GHX;MN;;YqcOU|*ltFX9--m>J^u=u`W z@jW_xK7WJ7kz;WTRb=(>SbPVt_&P^x(j6@B*I3-QUHHtKv-mz{@pV>t%~!Jc2D13( zDlZldWbu8);+waqf$PcQ_?E>{Q}mr{8STva0;OPFSiWdDi@QFH`vt>H>~*4q8~3P~ zJI8c)rYCl38Kx(6X%(h@{?XubqJ+17RLnDbaA105mv&{^is>_K+@EQ}^tFNm{PSjG zk*Wr(W5447U-ZdX)Q{<TY<%PwW05-31DT%JVk{cKbno{^xFE$W*is*A=fL#jPJJWP z&aP{`nQ7Us@vqG0yZ9tOldYLJ=i$wtWqKCV2biww(npx?!T)1(nd!jPPc(1xGx~d% zBdbr<!7FszLwozi!p*NkXjWSpRUa7%JvV-)TMj*?@*^E#((Ei^F{Xwl*USL7)KJoI zSvj52Ck(Dswu;+71mUN|9{*E!RJV#ZGMhC?J)l!>VR~Jc{&(Eg`3q;Y)*U8*8gy!l zF73*+O_z509K!E(oQDa|w~<a=AkhDg8>uAYR)f>xy9d&UA=4YXv~c{RP7?e67DD}o z$dOM1Egb(HC<VbCl9+913^xtBLuPXiEWK?4JOA9}r^h_yR<*JEF5MRMH9KYLY26I; zFwNmtUX!4Xvsj({uZ_Hf!*#CIF$3q^O~I;R<^13hcOs<{kJHV=XnTb_87y~)21d=M zcN?Zb%+rsQJH3w!kDm^9s)ls->~yfa6I5OQ?KwYmMkXw}ry&ls)}>{&>2Pt*kx@NX z8q)OX>F`6xr#kRyGQO*frn<|IiVHR*<CZn^==eibV)xsuX3JqQzj6hN>&r6n=ZH)E z$;K06Z&gFW=Eo8Dg6x!68WJ`S9@F=+t8vgJ&b8@S6JA#-4xUD$Po-eSut?F;vP{_Q zU(2oAWmF~qD+3yaHE?T6R`YXNk5TvPP%_106)&fn0_|RrBzM8Gs#SM>@w$s<lRlwI z_^(!GTJClhF3Pzo4wSqmp8GrthyPwDUbnSMe1v4dt+iI1Omh~0b!<9lj9(*CFCRe{ z7^ef-7RaS<8cM5^t$6Y)g|_@+b)}iM?$Qwh65!4FHALAVlb0d!5He#ksXDx=Qdw~> zx?Wg8mo$zchTq@Nm+vl6uF(S$-~Hg0cb6j9n$lqOa|2>NBZs$qoCYg?9pO4|M~gP~ z%z`saFS!#f+Q78h4MWm8IUU>j{<IsXV@G}zrs1Xo#iIK3RIJ)?M6}P!kMunrhbyk% z<mO6lAxih+@Y(RCoOgHu`EoA>MUG!9r*#h|!)kO%#D;WS>Z{AYI)90~Ni#6l<^;b| z;WpQ^F$2r{Z{zFt4khvv({XaDE-(D;!gF#;VjdJs-@+dZ-bSBKjf2k$pLqF#%`~h- zi_S#Ww|9da=ZM4Ts)%&>KJ13b^Y#!fGbIZ&W{%~Ws$#h`>nwPoI*!|;F#}JgpQFFq zmy!F?voK)Y0V-DCL|nbcqV&Ai)bLn6nV-pek{ysovuE3h@V9r<>IYXpd0_y1E`NMj z3HnYNhhH8>@xpVpXlg9v-&{{xcLROb-4*Wlk_VaDY`@sIu`pBp4QY?PPR-f(xN_?P za{sd%)mh_4Q@^Id4!N5muK@;haCkZ#u{<Zbzh4qh%T9v4j2Q0YEjiQ*o&eu&uHbgs zsq-u9vS7jV<<$oZGI8|zE4<9CPvWHkDJTw_O{b_fiEZC4Aw51M;+ODQ;z>i&aOU-H zyi2(wF=stYc7BuKWrCG?pSSEC^09i+5G4uQZClvAPGUR#eBh|~;(&P8Q)Dx}sB=!d zq-ZbqOedclUO5kH%jK|eO91O}<pVm4<Y~ml46yGA5&1o`=7t>2f@>!V#S^c8r5)$q zad9uF;@(Z)DZNoFS||?2@7Zm%;9;)FqSrJ8%NF{5{#)+(q+om(@{(?uXGD{d{y)0T z0xYVnZ{OJ6g`(JE2cjO8*-NpzyRa}&5gQe;ySuwZuuv5CT6TALcgHz){GaFZH}5y^ z`G214y07P1_gZ_;uxFTAa&+)FSr<LkB`+4#Qxf=_$RmgJX+28k+}FX(^*FA7jU1)3 zTxxHoR@`PaJ{V+X70qp%HwUb!&iMVVO<(%<%v{BKn}3oX)d8Pdak#%p(`>5lxxmeK zeLidsDQqpQJk->0cre!WF>-w@T%Su3@2fiONPH&I;4HC~vv)Q5s^b62JlJEM+u6l* zd!NsWm++X?!@rs%#j{Y8qs=>e<JOjrKIcPCZ_f|*+G7DKm0tyYWcd-Detv-3UVVUm zP++&-QNFg-^weNgI$)je)x<5Vd-#n0ay!QPHaO~S?)Fb+LL*;U=erg%Dh~eLME_G( zzv`t_gEd9XiH_y;puFDr92#$P^+HKKXMaJJAt1YIIq;nRr@gmIfX|U_aqBhy?BHz@ zE$~sFlf}2*Z7Xg1#x1S}S4m>w{atn69%0YC`}_TR=8g#a72cPRzz^LTVTaw@XuB02 zrdBMCuxr9MdmXCUecWT`9=OB4SSnO?KYha<5^&lMJQu1?rHZw6HQTn|3{#_4)VI^l zS!kzz6lwQL5oU@+cZq3wE7Bf~-rz%*n11M^&<moEn%mx9d$5mL8+W-i1Gk$4-$Q+I zyT{Nk;=aYf?GDe=!T!9zj|oq*+<N^Y(#9UZ1TE<j6P#?gePz=?^ESy4YtoVt_Q$pO z`E2eX)?aCd+vOt$nnDi-Ti4PJxA&sozdqRNHu0`~W5Zq@G&;~cbh~TckB_Hfsvf4> zx}A=(Sr6#ivja`Sdx@<+yAJ6JYrElh(Qj~+eo-hks|P+yEagT=d`Gd^7n$+>(G-6V zwoJj;q*=q%xg8rEHG;iji(t*SoO5Gab+2Pe?r>LL`4+~`Mt`);T^*>cEsvrTt)R{w zRm)jd9k(hjwmMYnqqgk3;uve@TP?5kQNuD_u`U)FX$8e?r<U)YZk@Z@*F>#&V%I-e z2cKseWNtm5t7{)PZugBCY!Z|yr32RQx5NG!YM$5sWWQ}OC3bzsT4s2Fhnh8KrIqbn zakHg(KGk{sHfvI<I%aQj{JhoYMC_ZJjm@jHDb>yJ2zyUz{26=XfbxmnMB4RmJ<l!c z5fksrYWqn+{EpR(U-#4*FwA~2Jj^Vr7gqj98+XT=+xK;!+MU&+)9#Mu{qO5S0i9K^ z9a$Z*>+kEUO*^X}&C@$Ze7~=^RKw^0E;(vX?J&eto0wPkT6olM({YG7G%&Ajw(F?< z7{2Y`yjuAlv$g*aGj42NUHogLBQN%H*NzM*e;)rvuoQZkode1b`V{FXgnoC_pz`OZ zY;jCW7N+W?A6WjX`!IY?#BMwJ+_m<N?1Pkk*k7Nk-p2l?z%Ui?Ji?CGWRpD}J@d~9 zI|M(6i{U<YcZ4JG_D07*^zgG0j!)RH+U)REZ*6qoIdA^n5#iW_HSb=Bnnz}jqd>?G zhsuc0qrCIC!}G%)N8Wz;8EW@S4#(Vmc;5&$t$W{al&x{vF&uvvr#i0TsCivtO2%}s zJr3agFTrvv_G_f=1HWihmzev~<Dh@UZS7ng;i!(=<-Xbt`{%j1KjZMcb>O+04bR){ zFNfM2A_tm8afVnbV5?3%e~V7ku$@U5vPgHlxK*Fc(b1fVx6yHNUBTGDvV^G)J{uf! z=N64Ejpt;YI7?$Qcdlb<>~>dUD;CziuUA;Haf8&Wq#g9#wo9#@Cwi!rXP)Zq%R8Ew zz76bgKTheA_uHG`_aQp|kz+bpw67^TGP&}*yiz~>l*?4UQBoCaaLX<~Y?%2__-Fa? z1@_o$@tNt{vyR{6lOn6*LFxy3oTIaPGc&!zYvz4@xqWB#;>Qs?Ri`1Q)ZDz<d)QGs z6wiUOp?US`H<6Btcuey?7*Kw2`$)&(lws;;iNWQU_zp8i<F0lz^NMtII}mCrpPXrz zK5*ahqX@25j|j(#CL0~o(HjnraJY5f=*ZRdx})^)71pdy!OGcZNG~fs;>}gZ%a1E8 zyGbxU@9Y2Wof}_s9QwS%ir+X`{iz2Xx$Za?y29$vF<3df|G&Cd$zf(*;&4ZS%Nrek z>WPaEGjAs0>o2gukw|(4bXOl<=DJ;d!U`SQG1&a6SJ`sIZu4Y??oc<_ID03TPCqI5 znqBMd3LU@6?_L)@p>(Go8vm-@cFqdj5&u4%y(M}(>GbW<ljHS2>8j24*c+Sdr07Xp zy3>c}9Hz1@-fH(+vB{43L!Ue(RLyozrB&I><#YTDQ7;}g*6qCl9CLRJRwe&=V+TLY zZ!O(FL=9|n#J)8-tF_`nR?}70G~R6v_`aT)%d}lz#k9|Q)7O2N(Nnkdz<bAR`=(bk z{%%W8Q+(5AyTQpJ=J1$8R-Voi>`!Gv%)~1%98D|N)cqe0G<6oFw$fc|sPo^#=g!UR zYh6$G+OEDNtxC4Hfy)2nvhSuHbFAHa`l?lNq8;|s)z<v}!79EAcRa3^RVCh9Q?**N z(RX&X-m2>C$9Ae$>#Sn<|B|;>zPHaETyJe}TUob_4Ke-HP5Z$Ghu)cau(=R%)sA1c zm)XDPvZGYd?Rr7^US`4MYmRL#w(Ia2E9|62!qmkF-F&+gooLVY$6kNTG+(|K|G@iQ zF?lbZjrZbO==}5YF7z7W51@BK&r;LdF=_8nz125RZLZ?&D35*!UDfw?{6wFL9@*I2 z(O}<EJq+F8b>_^@2**Uc&af9m$2lE)(fi@`XFWV_%S?lRkJrFG<KEcObDEg#&y$!+ zW8c_Y(2t^fXnf|$^)9AJ({p+jdSCPlP0s0^xS!$C5%yTzw<z?8T@iL$ypQjz{m9|% zam`AbCO~Dc^T?42JrnxLP9GdiGgMKF#^z8%(Tk#=K|hK65Py4wV;JtkIo`Le5soD2 z>pbV#<C27$!@Cn%9nr_5uSP$C+q$zY!uG&E0mrH^^xWukTK02{zujNWsy#_pYSGUz z7JVD~1)MWqWP~FlzV@@|E70B1`&RlI>o&EOdE7modhho&HZJ-@bnb;ham|Bn|K5|- zLm!Ra%6~z*L`Qv8OvO@WTlNLz;-K$C=g&-X;eF&Bt|$9a^d;z(j!d&_t{Y<VEGT06 z9hzo0M&CWZh?Tq5y4ZFD>zO(aGN`F-*Twpw_d_4oG>_wXcxTn1)ID9WNgl^j^mgcV z4(^W$-(5g0Sgp()dw<L&^gif(9IN25%Y)nE`<)dX;lR&c{^$MW<F*J#wtK(d<GP^l zz}M@empH6Ji|kcl!&J$bC5|Zr7ulQ9`8>>ruW>N0A%BL$=i5MZoL|*PPlm^o{sOM^ zcJvID4%nNDX4Jz|3^fhW3l+<#L(zGE@UtL?Ezhyz=$X*3uDao9RePhg`bLmSxAcbN z2>M!dKF>q&bD?P57M`E#2Rh!P?c_z?+5hy+Xv(~)Z8E!bK399-oYUlMoQ!@8&y&1a zciWDvYwStchM8yaciV@*uC~2AhnZ!mciXFyt+B7d-|*UPdlXq?`=W2aZOyPF>_|Ls zm!OZ^7hxYqFJ&dRvRD7Ao9=3@3c5G6V(+vzRcF1l=GK2=9oS`=6g9qCUK2djjyp+A z!@e2R>p?lyAh!h?zvM%?9_#8i-HoT>w~w}K`?OS5TF<fUjd2~*_w-Yd<JS7V2u|*J zb|Orz-rYqPPO{0q(|eH0yX1h*+Gn;7TZzwp4Lzd=%ui(A@3sD`zo<1^H%;y^A@@8~ z`32+bz)G#no0f4@qgB~ehSb%~+b^qqx87=FRXQJH!Ux@n-4)bcrO@|uCSAg+SUyn2 z-&fZ52|sGN2b5D|iY%}m-_3^KHTl0jVX|mzc_ugYdUXxud2fe(CvzOt=}9Z~*R&t{ zY~)gF!NGbe&Fl&$eW7o$W@vu3qg_q&`mgKypF;PndJ{97;q|JR&qZ2WuD<E|9=iS6 zLFRd|kK^Ky+$!^s?B;UqCptq#Z);BV=BDz9I40MEUTWl#AboQ26usz3i0ZYtt(9l{ zo!C){{nV<aSyi#)-7RZgxK%D!GxfdxHS2|+w;o!(xx%sP)R5dJ$B^vmZ0#pjq6NLo z-6KJk|B@-z+#?|d=h0~o-SM4~82_%eX;yqzM0f4#hs_JuwR1Hyq4lrn_fvmZJ0q6r z2M6n!xwm#WW@V0J7C&ia^3SfIV*dK(yLf1RGqGJwwY=<g>w2Mky6?oy3SY14T)4G% z^)uJ^u$rG8q+a&-u`k?eqbr;bQT{{j_~u@f-Be6nU4`CX9eXpVy}4oEvvS0i&>hPM zn$&yCI+kxbs>=kFGmDEX(9w6Z8CO3cS+qWx$<6FoUBlej(Z!mZY?C8r@F3G=?%LS7 zfyr$=mrU6u2dtL;W?P;s@w<qJp0Re!$KTc4Yng<#XIq_;J5<Me9{=TsEE(s>QmM7- z+$xSq?A}mMxYJrCp8ZlktoKC6iMG@~)xYTn<2}rnJ4w{Oz8Q>rNKWJLw!m7Be;+gS zZaj0aW3<EHr{#b7i!JBqV{7Bu$M^IzZ5@eqk?LQqR=ZmNS66-NnN^7rnUmooby0lw zal7U1Owt$i?e??Mn$sV~=!Va#sz)Qrnvw%f+3O}0ReQQVj@?&xsHuLhpf$ctwB8@F zT=#$Kuj)U)ZQb*4Vs_+@u)dB<hu>vBNZ*~=Up4TnuHsI6uJ7cyYW4gw-S<%2N%o00 zVX9+?Koxs4x8q!eqt=Yf>l{%j^IO+93{lDY)KjMuBvO%4BdtjzzWF|GcGP;&FA$&i z_Q~>G(N2}D+`w^k`e(c4z!WMVV<VNf>SN!?x<l2q2L<)CcN?|ul`Lv&`m$>Li`)81 z`z9)Pt_a=#aB{PMdt#Lxznh>{h3Y23wC7g#{8x3xf~8HB^Si7ri?gUH{(<K1)7*9y z{7m`wq^c(Ql{i+~dY<ZNj_<Jx{g3J=eF9Cp;h!CyLhw7<GBh$hUvIRk;PbZr%2?Ly zIg(uUk4kKo2IMiPy-KT{XLspo%d!~1aaC2qTXFQb#-1i{L|GNy|CFQP#G<C-?6hi9 z{IS-7M^%k`t7t31&gIs|C;lea$aGeNYlE!Nnf*=p&grpv+e~s?ZWCr!e_v~_NSPm> zeKf=*+M3w<Q0}W<wX?Nqw<WQ48a)cVH2e?rrRWdQbCv(9r=T~j>}`$3_jLw*U;nA& zceGm;*2G|qv+wy=$M>lkg4cmw=1%ON`fRM(iZ$_K@5KJ8pT%nh?vE;k*NQ*&q{>?- zsnJ|*9Ue#hspI@c<Mrf}zT@lc=UqBIUt4gWbxZqydlU5eE`H76$$Iw3#Af1D{Qt^7 z^aX<^>vw-AHb17-R)6aF1DVM+<A<($E}QyOFBO&5{5|uB&T%H2Vt?n-oqm5MZ`}sh zrxUKvpZXwQZ+!@Bnqkeq`w{VO4KDZ=9~57e{Mgbsdx?MbSga|JHHF~W9q5InJN-T7 zZN;t8+=LI0W7yr$H@bBC@p$i;i{}p>)Bmr}hc5#^xprb*60bi8cDDXcKj_lwJqst+ z)v@L$UZeih`}YYp$8XNoi5}*`?`r(t9*lkj-VNR#J?hqM-SB=Ms{{IO>8^fYEpPp} zT5}bOYsmf-Jxuy@>4hqI>#ew+`QiW63m@&RUcQ-Y9gZ%n|J~ofpM<Z5HSXvwcK`o9 zgZO2ZxAhv=>H)5&vp;g_^jWKWTb@|c8`m?p^gihHS)IP3xBiLyJOkf5x&PJiIR1}c zQq^0pz}MJzWE|z}{{QMb@tSZP=RAPhWj`rB7X38(A$TvmwnU>JmcG-aJAI0WtM$9$ z-BtTJA=c#09gOd_SJv>TTCwbv&`Y7aVa*4u>54VQa`ZBz;*HjwPmIxd(ZkV0(7PAB zsaI8LY_eV3soS7$K+l4n=HY4!=QlXNe)(Xv^-=ni%^g(PYp-<jowa<~z0v)nYWbGT z(MxrXH`>DaEg$p-=pE3j6ufDLSHbT~ytdP7ioOor3*GhpyWY>Xy?v}F1(#Vb-Ghv8 zu#Xjm{uKQS{0sC)=nv7;6<TK9M9+^km*F3vXF)$K>$xTxo#$DBo(k*lq6cD)7y5bh zHo-nRMM3;d$jm|NR9_$668(yMkXnkq4*eARX!Kj?N6>xx_~^-nmg(K-KXL44^quI< zd;925=r($nUiec8)~CWb@1nm${|2wn^P=a4uNCB@-xOG;bD}pyF9x3peQ!-4{juFL zeIpHS7kvZzOZ3y|N&T1Ui|A=;`RG>YN6`5=cE#g(SRPYn&m;bT__kPc7M;G8OLzLx zc&y*z@%6-G?d+MPzlLYOkLLiN4;RpHyL4AS8IOCdxTCFa$HrK$eF}U%@wm@wH=Y|^ z@!a@RuZidF9XxNZ<9X}sxZVGB`p^ffwO5JmYWb|+y}<v`<F%Wk&j)RD1YYf{5~5%D zKe~ZW8obR>3v2$=yY!3FwH`jOLdG^!9i<OM|C3LJuW>KF#)K!wSSek)t9OT=f;C@o z9sbm_mh56hG|Fw2PB_5)spl!t#cJ9(w^bW!{?zNq^I_`oF`B&xo&*2x1>j@h+sbps z*}Yu+Eqw1B@>*uK&5WPj|Dof1%9<tLch3Im_xIX=eD`Nt^zhFu)rO^qEcRj216+DV z^pWs3*8IDV65jyV@F1R71#k^rdm|VBA$u<s5r4Gx5NrO_vkcy9<$T$~MC~}H*|WQJ z`e=Ahmo@CpHLkrauGO5lqqQ5ZVH@<B|3|L_e*-=**6^`#c2}Pf_kTT}8!vF5T|1vA zc-{UVUmd+N`lI7xtUq<UCgXRHj@A=#TYu_Bv8FNB%)pvr(r5pxw=YuEOl(|U{Rqk9 z=olVgqB3o;Ha?qXIWDZU+xXqEUi1!7=aS&}Uf|#Oj^0*7oo(CRjF^*KAKdWJYLjD{ z-Ed89tG)MNWpB=IigolbLvnw&=Ju-PcylX7?E3I9wfT5$eGi|1Ue^7rbvtLMHDP&b zeYHz}{2r>Q){U1zrpAQkR@-53t-F2m=@Plyss}}is*;V%n|6)z*cTh+S5r5Px3_v$ zP;nvx)b#Wl^t=1hwAtvVn#}s>7}+kjvfH#*zozH5&PF`cy}c`_;<L6{Ef=R!@iu2y z^E-H`WBI=8GP823s%uiJuep+{<40>-qsnzswX&Sm-xJ)nt}Q68(soU+&c~aoGrSDK zzY%V(t9duKPNpoaE^I8MHa5<07KM*@yvSC;lnM7U<0gExf3?YNLP}IH*Jo_gX_uxl zxo74yg;%9Cf%%e}MhS20$a%%h*zW1g&~nXn!{nvSsqjK(cchLTGBKMev#o~d9)Fc1 z%<qP7(L2DLNj=RmGqSeE|5Gq?`q#3j-bvxRDm=`D<qFkVSEjc1b?I*|hrQLqdgrq~ z<Z5eL%`2)_cPXoG_dRPDEH_9EY<I`^^7TRb`=ef}WU|xc8vWd*OSJM(Vf!<wi1CTc zxlLVF-qe?@L{A^auG53mk$%VQlKA{g&vV`?AfSMW9y-aY^QEAQ=T+Kto7>KEUE_Le z>dTo;-qt7e-s&Y(re-<JTyOk4zr?wf>#?rq4991a)p|41O4R(M<+|SWJWZnTyVSFm zQq7t?wYF|ls%T$7{b?S4$Ml?WI<)&3-#QltsP0FVY8RaspJ|oKa=kyU$7Wp~ruVLC zp>8*RWu^bRR!6M}RB<=8wp`bAxZB*sIeEg$Q(}kZdf$qDN@}|0X`tS>uBLM}3^cy^ zw_5*nt6<gXR#Le?E}<qq$)hV~i`8oyc2l9d9oG27o@U$f!s^1HGnU%g6MqMKmv#Es zLHpj6;%ZyX6}tQLd}h~&=~h(6$Bv|z`<ldKdaHETvgm6Km*`r%N|`jvms^AS<TMTO zcO|zCy6T%L*;RY*O8icny4|fEo^vhNHLmAzUGI8Z3xivmWo!FdGm<^FGS=>4PI{KI z_ThJ-4I2}p^S?3H+V7oIrIwcVKh#Mr&2!GmIi;97HM)$-{LIaIx_hwld6`6iPnAVq zIgkHWRH}x~gwOIg^`?PJ_brz-GaCQC{AV|#vL~>1?mB2qp1n!WT$5PGIoL}Lt?#QQ z|BTUlW74SJnVXm-_mAoct&dt=r$4a{J!@fR)*f$N8h%$7pIgc_s*&Qq);up+Mx~4_ zVe&YZ+pm^juQPYLo?oDucJ<TK&Me<Ku#cHKZnbspL~_+*O&v4*XE*C*nV(kQbhXTz zpdD6+kmRKXRqJGS?RjEl8;#Gv{orYyHm+hdO68+&7B6B<mv&a{qfDylzG|jO&ze?r zyr#aD@(nhb{aRQXI~P=2B8r+XW})?_%un49=e&V)w%L->lsQ?;^ynIFr5WvKj>|cH z4&vW#J+Eq-U#no1P32?W<NW{N{98L0G@EdqH#m>Z<fYeTX{p-m`Kjw?_R{sytH=D* zHQl{*SM=QI%NF)jvvsWXzIY?Y0`ze7(j^-?T2@Y_s@~76rX)|RMx$3o4?yoxWv$(> zt%q9Fxu%M!xYk~bJ_-HO(Gq4`<%5<7evbMXeH6MIdfaNm%)92P9OvEdJ2IdLHAv;S zl>WcF>zeNao0^I@C+m_!-|0!{NpDTobwc0i(w`RSjE7I@>)qOz_~@4O(_3OJ-##<- zh1DHQNA%L@&(IHMXsI$Cnd4jVM*{O2z1s0Pz7M`9FbUFo=^Oak>)@JnM1P3xiQXln zmoAH*A@-+Ujb0u78m>=HT(@WFb$9>NA8<V{pdUuxn#xNb&D>IL)<5;M)Lwcs`g8Qm z9$q>>)=a{&7txELw?<Eh^9)44fZJM$>pvNN7J4n5GqXoa^)mXWzKh#Uie3!o?~VIr zVNDa<pT-$}-?xhBwLHCaFZk3rHaeS^9*2Gr>#xu3ri$b~XN9G|?0W}2E&8l<mwn5{ zNv^KV&#h|oPpU4tC0CQslMP6!vPVVPI(1&PzNMdvMxTy;3cX`*Z!>BBRcmDF^!T%e zw`sQEs#Og=qTVpG`q)y(nk1VY>?6^a{U6=A#v8x){PCPXoxAaO-4?wk`sPO8^`~cx zb&n!Db%FRD%z)>MwL5wq^kSc)tP1M~=s=$?CKUbSx&ipTWL->b>87gCwh%|bI?2ol z^vzpC92wE4;u<!=*WLox_A#zud-QtfEpZLApoijGjYRK+J`jEl9*eQKwg-0p)HSkr z>6z#k(68dyJy^r%z!jWxK6)4Qe7U@IcJwgxpE<pBCG-^NU$CY%dI_BK1dd&TJ`#R5 zJRdtgj{V@Dz|Y3x;)BQWC!QN+ZJZPRCi*t?g=xL?46GTC^L$F@rAMNVLBHbO+e}X$ zp<h{3?JekkrHIg#{ifRMTct6bkEb<DN@Ow%(EFh;M&InQ$T75fdNcS)J#*E4k)s@X zB>LMFB~*!pQ92+^PBRKU0R1%jv^$|H>AYnzmzKrT;p{z@#q?YpPxpV+M1B3V*t*^4 znYHy{6Lkdrbboy2`Z|1WSDxEep^Gh4O7wW>9nl;1HM-x-mDbtx?Nm%3qaCwWS|`v; zhqX4vzxw%ZPZU>WK_B$l&-XF<4t$L-@ip=~C&P6}fNK?t>yr`J>Jt1T^wfB~MxguP zI*fqlW7kkRum3^xM7Yk)(0iiCLGOrO1^oh!<zp9(^KZbhjnH{Lo8kK|8G1=PADZHE zPl}!ry%T&xbU&>5EZ>`(aBN*XPwK!YfFBFb`|uOKGHxpjo!`Hia9iQ%bJ54;Xr}sK zO`;kN3bUu9w?p3+7G{@A_}y|(?WeY-ykX5iPk}xFz3Q4LcErF+>fOFv>QML-dkA{m z{kc@WDkY3>Knm4k<tytkx_{>ssw{f;@gZi)@=jK+Ubkbip+})_47eS0;7ucQaq(2U z13vTd*ULtxV$@VSTUbhyHy1uv>1#z@W?oM-)MK@N64y_^LH}#RQmfg8Rd(D7eawkf zORb;i574J<t*pF<G`4oTd6+7ZmDT8w#@7CL9;Wr!_G+`oRPA2&pw$)q5c;LR4q7jp zH&A;zr7`Ey82dB&CiEQWNzFy8|HlR<N$X>Jr@m+nMz4XM<#uwtaB_EZb<1A84t<XF zHia^n#B1xBIAL||Ea+v>zl^ABcf-%~7hO$Z?iRmgRYtFHErr=u?7zF~nk3_2>6drM z>FjNrtD56p>2UP6=moBpa@_vD%GNK3sh-zMIU0XmWgkM1*EF4aeQ~or?XUXk9X?yQ z<E72^Li9c_2C2mxGg@`+vQ}I459rr*S!-LH&Z>o7Ur$YRTpvSEj9wl+@XR^Otz29a zbE%?<LXV5S2K{^A(R%zle1`FSUsJ5#XgvzOIr_uDYnjwHf9hAEk@_wA`x`&?9rTLW zll?tk=}GPbEDL=EdYa7t-Cfu8D&=Jo;kR!#ZR^1P$jf|){oTu7^0bRhI%F079H<gp z^|Vu<d!sk(o<#-D*l#r*Q&ROs4?{1Bz8T*O3eRD_W(MMUUJiX4dRBbz)IjI=8sB&L z`t}6R^A}h%7QH_@-yeDG2dwFf?+d<m8F=hBtPSYgZ!~cCviO=@9&0{j@v^+p`8~UI zVNbJC$Ko@X8aakkPGzcNU(p@=3hXyb4fF}<bFgM7)>znwoT|9iu}Jn9gR87{IQJf3 zkCsp&vd6fBzFzho*kdS9>@gl-j}afeEA}26e(yd0<FT($>9Mb<iG9Uq^t#w@l)-+( zb-mlC1(u)eG0LH5mX1A!_QoFLIrbRm(aXx-<9UXb#>O7wG4>ey(YMRqqeyx$>n^@_ zZ(NgtxIWwu<ihI@-s>$-^j7G2ueV;K|H5k^uc3{e1?$h@8lFUtgl~|>%i4zbj$PPe zj7SZSJ_h}bhnH0pYxp{u54{lj5OnPKtik9pI8OvR9}B*Y9m4IV#A|N>oU;sW%N_kA z-m@-d@Ur;0^D#||UKc$v?%SbkUKStUdsyGo)5{7(&xG?_nAy!#!5$+v!)4#|ZppD{ z$gNUhUxEFGxsF~9`wi?#Og^lsj(tc_RFq>5_83R8$H<1xy~kSghP}O25cU{;*kg1? zUxd9!$nX7z%8ETk59~2E*2CYcK#%&p-}sMjeW9sZjD5vM>??|)r<@z8^I^Z?x*mHB zD<$?A`LM^p-otY4J$ihK()Y2)2*4gAFM3|=J$j>Kk715tkC6d;j9uvYu=gm5jy<!* z_mu9qKBsVf=AggBbvP{7>KXhhT+in4{m^~zoS%zpdkTAuP&_Wv&?C?*;j!TNl)|yt z2U;=c?{RHc<oJE;ck~E!et$K>n$lRqJzf;LFOIE@9*pz*<F?}BoTafIdm$?q`bs>G zb@5z!f#*hl>@oJBr^fn6cpS&3{rx!Z!LeEKT;hA>M)V8rz133eH!fnov8+`Z#XZJa z>?<~*H<!KvYnoyo(gFLB*Y1mKg*`?D_84P57TE*Q!_dd4C}9R;k8uEdjF;$D(EZUj z<KM~`>%J_;!X5*A5A$H|vY6A@dqh5LV)kH<aTR-vK98E1m+0@Y_sG6(o_3QxMmTzi z>^<<;m#s3g$H3mha_&7m!dk0KAN_pqVUJM~z3VqW-)QtE_}cH_Yy1n>%^S~o?ko7` z9qhNQ6X?9oyjFjsKSj6Tx##EgNrm1Go!?W~^IL7u`8t^a*O}iJ+*fRY=RRRE`Zt_^ zI{F#hmKPrP6zJSzq{rhG54{~a_89+jAI4(M3iOun*>LO>bnYk9q2I^zq$+w`^msU@ zbC0nLx5dYc`wi?dOd$3c?+1q2yAyubKU4Xs5bP@|qNl|k;{f`6tf`GPKSzYw7dAa{ zgkp~o4||NKtDiX5p#Q+$<6e~#sx$T&4(u^<p!;F(5rmFChMJ8%MicBeu=h}5=q1sA zylkY(V~>#odyGAA8mY`nrrJHR_XzP=Z5_rQ;{)~>k8-ZIMq}?$5q;OHrTRPe7*DXr zsJ~&U&WHYMd>>OUva-2^J;oO7F~)DLY^q}Kp|SVCe#30U9wRIE8(*6@FdMM1$c23c z_8Vp=`ZaXyL(Cr8haAusb%^XSQk#pqpX@y*-%f5h_ZSJ$x%aq%y+_7E85H*z@36;c zfu0oo*|55{U%}FfdyFXTF|e;t+<QF0-ow>nUxCk&7^hofUy*S9E9<T7H(b|uzh26& zFMEuNS4-KKWbc7JhAD+T#$xO-5;aX{c46-^<@bKWY?S@Rkv5&pli2#&!oFfVx`jQ) zc=VPp2ARa0GFtfLSu6U?InDjXI_xp}qkk{^d+(9I-)L(z_885u$N1QHv^532CHkws zYpGv1e(IapW86m1dGn`!i;g{p8ZUbc>?>5(1xgS6z4!Q!$G$>2_Z7kDaj@TLjQxh| z`fOJ{9o%F1V2=@a$<x8TM-g=FF^qGMQ6HUqkLJJk8y5dO%kQH>c+PVVUl4r)p67h6 z`-*-uotJe)p6BuLy}<oB-?PH;eai360{A}qg=6{Wz8qM8EjUO`uCq?}zm!xj8sVWP z=O|_l?Ky4bhfg>*Qs2tC-LBHyPu*LQz?9B#M7JKi-I^ZS-gJ0_-xD$-#!6iS|5he0 zK07RTDm5!n0kff%oB57DJ5d3(27NEqq^QwOaZOJgJ1Mli;<43m&O0j-sA4$hKvP`h z2no0PJjiYOqvs0=*X-AEAA;+wvv}VMqrV>$X=TZ^-RAwAl%p74D^6QOW;aoGmc=?} z(HHvp&{0;ZU%k}j4`Di?o`}y+>!BLf8Lz9JYG*y&)ki(=-b1%KwaQW*@%zp3_jbS8 z6RlondYI-|a|_3&`PIwZ!m<6arc_6NlQMs_o{nSh?&@R82lmkJe&tk>OzU@?UslY7 z;dZxYS#0rkCwA+kN}s&9qk_*9ee6ewDjVw&6*{%GZq>V@Pu#eDRjVW`{-?)r=}sS< zXN2wEBTTK2Z^!ojLx24!NIhM;%?h|%&i5_)3+b-@{yxi52!D6*Nr8KgfA<37cl=$q zod5Yr)~(6|%%6JyS9SMvlr?|q9=pbuyj^RZb>MxlarQ$loql85`aX^0;O{s2?{Kg; zMDHNIzVvsGg3LvHEe-H>eQ@cnzGmLxvDG^cQzy$maMVMuA>Gw)7+T9GVnvv`9^T6F zr#>mq2nVlo1g`UBm+tCQPwZyKeRWumKkw0BCUrL+Zbz-p8F$%ZH&ip;Z!)XghfC<) zt*V&0#XeelZd}sw5;Zg@^CnVVuK4SV!R5@g207Hops70ii88$kAG0#FNNghiE@I*o zyJNLTo5>8YDw<Rc0v$i_+3Xhsi<=Y|S~@oV!so-MXkgNYj@Knq#xt*f;s29lS+7kx zcXK$ps~Ng)w~jv4Ko54SZ)%Ok-%F}CTkq^2Vj694rccdUX5ZP{#$3zyPNzOvP><f; z%Xns-9Q)&Rv`$eBzk?urhrZMMysmn^v<dO-?N~j*+oXP8*c|(`RM#$7$dn53FfkdQ z_%^Lq%jELRYFhpsq1&e_W6GsSW|CO%V_LmwYG&?9V?qzc>O0we&DnALbn~2Uy3nQW zW<$|ix^$Lv`qs5NrrYM>y5oqA`tZ80Cjb1kI=FKJ)8SVQ(|7X&{rAYTx>ecQW_g9U z=E8?>I>jX)bKKow9zU<*IO<v01SW1~nv5&&d*fbGlm15y6X!!4t53mn`1fJW%;<VW ztyXX2nR9cMnY?hJWB8W*Cfci!IczpMO6N~yzK1k1JIlPbH+v>ERZF!sm8ws)Q{MZg z?N5H@Qnl)iS3UEZ#7SG2sq@A=Zf;I!2Kq$lO+P+Z`4iMNcYdAM)3&5lku6G@25yz~ z;J4w{iqC=gJD2z!Hjh)OE+1-|{sqEy;cls|c>cXi+@kArro&II;kg@|*fWVtNw;2( z4a1t7Rm)%Np)+n<qpMUgqtbbp?mcTbCe*5BQhZ5h($%<O-MmxYl&M+P^k~@AF(pB9 zQ^h}<89DB<H70c-GxbCT^ZaKsM~i!2#`QA+Hq{<t;vCFxb;f6sysA0GoWN(5^u}kE z6b=njaXQ}j9gEK-!Dp4Iht`GiEAUw*aom3YSHHWP8+s1rWT;7CBA5oIf+=7a7KDPK zU}-`(w<TaPSOJ!UWx$cl&CM5-2Ni$<7N`XLKt)g$Q~{Mi4Nx6a1GPadP!rSxbwM4_ z5HtYwK@-pzGy=^*Gtd;Y0xdxc&=#}-twDR>588oFpd;u2x_|)C8FUBTKv&Qc^Z<dN zHwXf~Kwr=Y1cL#fKj;TSz#uRX3<X2LU=Rj|flx3Ki~z&I7%&=)0^`9rFcwS#6Tt*9 z6-)t>!3;1ROarsQEHD$y19QO~un;T&^T9E26dVC3!3l62oB^l7DR3T~182b{a1mSp zSHTr<8QcKZ!8LFj+yXbjJ#ZJ?0T00ga34GYkHI7G96SS0!7K0*yZ~>(8}J%@0Pn#& z@Dcn2{sv#bXYdJp2j9R~@C*C|KS12%c&-9BkO0I7@jzmb2qXl_KvIwdqy#BIa*zh3 z2B|=LkPf5;nLtL60b~K0fjh_svH}l~17ruDAUDVba)NvyFUSMNrNH9}#(;@n0vHcA zrE+uI2sVHSuo;AdtzZj?1UtZXunp`2J3$oK19pRGV1rl?1NH&~G&lhEgMHvII0O!Y zW8f$_0#1Sx;5aw~PJ>h6JU9o=f=l2cxB#w#E8sG?0j`5<;5N7gZi0K@F1Q08f(PI} zcmf`SN8mYl2A+af;3aqg-hwyaHTVGDgLmK~_y_zAzJSl*6Zj6kfv?~f_z8Z1xT*1c z0B#@wh!5g{#2^t!2$F%MAPGnbQh?+j4M+`Af%G69NDF*GN#G62fYP88C<n@dzkmby zg7TmWs0=EB>Yy5^3TlCxpa!T5>VVpy0jLk^fyST_Xb75trl1LE30i>WpbcmZS^<C1 z4zvXwK?l$t1c1(<6X*uIf-ay32n5|h5a<PZf<7P^^aded5EuxCf+1iq2m`}FC>RMw zfZ<>a7!5{&@n9Sn3nqbyU;>y5rhv&{2AB?}f!Sadm<i^AxnK@h2o`|(U<cR^wt-z> zCx`;k9vFk2AO`FKyMYEahz0w=UVu%Q+d*&u><34{VQ>g+%8KttumMDX%^)0X1zSKQ z*a5bKZD1GJ38KIrup2}J8^nSbuooDh!2z%z>;s3vA#e~J14qFTa1xvV$HD4sZf>i< zO0W*B1#7@YumP+Gn?X3(1h#-k5COJ>ZD1?d38KIbup2~!T_6_3fIYwf4Q#L<>;rqj zA#e~J07t<Qa2T8b$H6gh8k_<r!8vdioB<cX1#li*0hhrga2;F&SHUfC6WjoI!5wfL zJOKB>J@6Pj0uRA6@Dw}&FTo4&9J~Rq!7K0{yaR8+Kj3fh0el9Zz(?>6d<9>?Pw)eL z2XQ>{ngM>H7ef{WMSwRb0g8iCzz38Be}OWfG$;?sfwI5?4&Vzaf(k%^%AgYP1JyuP zPzBTkH9&RH0MrNdKx5DdGz85+Q_uvo1T8>w&<3;yt$;sh2ik&;paW<R0zhZb33LNp zK^M>i1cL4$2=oFyK_3tddV~I;ALt7Pfq`HE7y<@^5HJjcf}vmp7!Ja~XfO(l1mnP1 zFa}Hn6To;dDhKAl2rw3m0i(eLFdmEplffh~5ljP9!4xnP%mCBD955Tq0`tK<Fc&NW z3&8@g6f6OY!3wY(ECZ{-DzFk%z-x*Emf(l12%fv)`3If~FOYQau*ZE1-U#oJbW;=I zK7z@@G$h?zFbB*Q=84Ob7<&kiOUR3)D~tWjU!aUo4oP<i90Ui1!{TmW&v6}G6K*2u z?tt6imT*_x1LS>hPk4x=`vN|LPr_GmKak(SH{mCeE)MoIZr~R>iHlB`0K^CJgoNUf zAQOW`LQ*6hK6luyI;bYp6jujX8`Ki&BIz1{`k<cBP+S*e0O%}qMbZU=?x35{LtGHD z7w9SUM$+{KeL%3#PuxJ{0MK6;grvI&E`amGC2?i3FZm0U5y~Oy+JZKqwa`vn2V{HT zFLXrG^~ZCuALuI#K+?Sj@4#E(gSY}|-Q4m6FQFikt|q7fstdKm)kW3;wS{^}y1&xl zzJt<2StMNrpnxS*6jvEp3HS+BkaX2SHBeQkA+9#E7N{xILDJ0!^T1qTfw<+!WnihW z0!g<TtO6^AHR9GI*MYUd1|(fL*aS8To5elIg6|7(Pk4x=djcMVN5WHauaGan3*j}A zPGN6h0f$flNmmK@fr>(9aW#<DK{cT!l5Qzj0u~F)#H~cG0Lz6{NV>IP4OlI#6Son$ z0jw7`A?YH(W)Ln!ihF^*$aC;ac!{Jdg7?V6ppZ}$Nw*v<151S!;tJulz91+d6h_k3 z0kuIbp{}@QcsXeaS_sXNbWA#bp&gQr=?~fnZIN^w`-6_4HK3>CxRZ1y$DM@$q;swn zI*()WIQm+^>AHw>9>X!$a@-Yg%)Afo3Ejofvv(7mYk54o)AvRXl5uS$=Q(EQ8jjg{ zznGls<ua}*V<zXB)d1H!=X#3cxCY>u=^R%_=P}N?9_Vx&HwGLto#UqHoOjLzqBjBb zbR0L5&T#|4c_zo4BMkxFa1aKD2_ulh0h4Z|FiISgZnQ84NynrM5eAE6(hU-ZAnBNN zLxoUrOu7NWKqMWLuAk6f9Fwk(&=*O^qzjhLyd&HdHyZm1cBdbOG2IwRj>oz<`f=jM zOL9ym0J>?C9FwWyCP{KkCIY(2k{pvM;^s+mOy&Z*Ig%Wc+2UqMa!jTJx|xz3lUd>- z@pW$lTZJu1Iwsu?VY@gc-A*A2Nyns%7Iuka((Ms;Bk7oQu|kYECY=^+Bps7(nXp(K zlWwW71WC6Xusi)KarEpfg%!x<U<<AXyVGyQn2xYV2$AB#k?c;t8J+I9B*)~KxTBIB zlOurcuq4Oikhp`A9FqfpZoeeQWS_Xbk{lBQ=(Hrq#1<DL$uWrqbO&(_4uCbnS|lBl zZndyZ+%_D;?)2L+raLXkF*zgdBGz62=Y>m1Iwsv^;fgpW-BsZll8#AtQaB}!Nq0gx zjih7Joe|E8W6~WL&LQbIJ_Zg0I*yOXnCTo}N9VkA?hra1$43FjOy~FpI_DqYda!fu zAv(wGXC-+YJLjC|IfqVn9XtY@V`tKzm*hHj&e3yx0nl9o^z7s+pt~f=F}W!2vLwgk z3ZT0$$uYSn?ye-q<PM;_DakRpA?}tW$K*Dk<Nq9q2jU8GkaSGC_(B44OuB?ZA|zdc zMEEn1i;s^nT|7ySNnCMmk{pvbfNmGg5e>qHrARs^-6mm)I40drm+?$=GEW@mq5#*@ zGdU)lYZ4c))kv=AJjaaz=b0Sa=wvT2f)+>5&b5U7f^bp1^IRMg&Yzb)1L?d!?7R=0 zI|sOyj>$3SIG!S7rgJ<Mo%4j9UlU=UB(U=sj;8_6JI{3to$z*e`<&;xiNZK>Tt69b zj_cX!CIGH=-WEL_kE3TlBFQ<z<DG6iI@dCtYk5D81FkzIo$e^$arA_1=m<O4a-QSy zl5{6r#_V(_UHn3H-UrUH^Vmgzj$?YRPld;sd0Ki(jGgmb!+AQ+pONud>CR*5(_jr@ z=RA9Az~c#f3W1&T9P`|q=P?<P^h}P^$v7^OYdKC2IM3ubEpQ$a2c0<Q*?BDI-2l(Q zF>jNdj^iJ=Ep{fyJdWdE7;`PtInQh3bX@-vaDFl196KH7-T|JA=^VdD=lmPM&N&{( z<N5e-{1$MY=ei0w$1(jU;j_3*I6pm)BfLF2uA^t?wPJGa3mlK-{5R=z<hwY|eHG_{ zW7wUy>y9xU&&N)mSsce1#5?CX=DhQMaLmVy$@|4Qr=!mzj>&O0AuE!O*P|`6jc^5H z=QUz-d`;51rZv_&9h29SnIHZRk~kfc<J-awnPXm;&g5gowKoCBoTp=_<M@_zj_(4_ zpTupR0LO(>NIE9nOW}pMpU61z@ca{gVNA!QizmcI(j`SE0f~gfNIE86d?A52CfyGl zOA?|x-FI>H>|cd%;<L$d91~BB>DamUlkgcy=OuF-ll&Odv2*Q5;R}+^A#)rP3uC%Y zfMe(Sj^YN1=R64kbnINyLFg=Qx+KSB2B2f-+9kp&aU9dv6BZ-sm~{1pMJ}!`dL4oD zT*rC#b^^O|jlYXuh|aZ4uI(z!7ssUQCM-bGaZDc|bP+dRl4CLf(EWpJ$+2_&-x$*k zhofgFBhcyCx#qp_0ZCU%<~Sy$F{WeZ+Bd>mBwaC?<Cql3n2w!mUkmS$bQxrhW0DbL zI(Dv2C7qdCSSgNU`s6|iBps73nUGRkI%HaqMo5pOW71_8a)`@>%mOkC?npW&T~@(E zTux*jkXy)wq+`<M6Y`2HfGi9O2?ddKOuC{%5pgAv-k^lwgQR29DWQV6GRShEtne3- zj!EY$lovMu*&p;11|sR0bR&gP;szr_!BAlcl8#9iCJYld7C8ot7RDjzm~=CRS>h%l zr+~@ABqSY^ZkjMv++5@wFk6_1q+`-86_$xxfm{xH3cZkYOu8P@nL(hpjM+)BxIqbU zjX*!4Ka!3~*H;)Ij!D-;XpN*}(gg~w#I=#+m~g(Q^tMRObKK6waUI8mbG@YdBY6zR z?Ohz#aZETDB)tQY$8g-y#c>_Sq!ZvecCPCUIs<w-jsv7~%+7fx=lX!|!09;d1~^aH zInU%=Fz5oDj^nO?^MsxAYrtx-QdlL9Nw-W`j-+GKEfrRXW6~`amLTbvbPI%q;+S;v zg+)j@CSAC&S==ThyVGw(r&}+{F<B>$o_(#bLA(e4%$yZu5i%j^m~@#1cX8Q}>`w2A zPWKIb1)qg4;+S-wzy|zzcs*DmEJe~W=@tvi#4+h62osTXOuF&HBymi-t-=;0UDCvO zeFw>fWJo$DT`D1^I3`^hAvKbYNtaGYD~?H*K}e6JW71_3GKyo;Wft6#bXh<)kX7&y z$E3?Hcp~YTbUB3_;_@L2fc%0Nl8#ANNGK?dNmoQDjHL4cWk6}6lsG0`S>Z1v9h0uS zP);0^&LQ|B>6mm%u*5OxDhd^lbWFNRf}gm`$ZDXfPz6cHq^luR7ssTlCDcUHG3n|E zwZ$>%>Irp`bWFMiLVa;ex<*1nBwb_B3^Wy*h-1>V5Sk<Dm~^d#mg1OnZG_fHIwoB^ zp{+P3U3<YFNynt?D0C3l3E2e%2%V91OuBADS8+_bK%qO5j!D;3=pl|t7bNsT(lP0R zh2G+rbbW<BNV)?_@N;djSJ;Q7W728Ch_jLGP9KX-N7#1@d&Dv6qJ<bF-CMx!^zX#I zm*kjy0Cay#a!mda_fe8#@(Iv=mgJax5qBDS4xAOvAnBNN*MzI$&Lb~@i^2sY9h2^g za9Lckr1%-Fi%*I%U1CX&NfL42vGyDID*QmwG3iob9Z3b~QYXXfBuFcyLDDhlG6?C# zG3hc18Ig2My3B&RI3}HkkOfJ{q{}8`700B@E_fp8m~=UX9OAkq$MX~f3f+-(OuC*z zu(;mHK7eBq1n8I?JJ<IT*FlnF!uih9+ao#OQIccQNgUS&03O#xIvwdMu2~AaPJk9d zb0i&;u7l8CTq|T-&_-yDq+`-`5;}^zio5}?3)hfzOu8q+V{uHn2f|$>9h2_9a8DeQ z?v8L1NyntSE!+~vq<bVhMACgvjsN%I;=f@`_eGLp@>QH$n%{FAlV5=Dha|`3C!mWX za~zYn7}I^0IgZIEjOqT7<d}RES3f1*UqD@<0g{eM*HCCAt}&9`=?kFK5%wxV6LERP zJJ;vKn2xX~23*VIstHZSRTA$!FUM5{uH`YDs|+}o9nf<P&%sVdngKe_c>=nkfSx^@ zq;rmA&U2gvILFMa0z2n8E&{loV-G-A4A5~dGoa@@$Hf8XId%t}F9GN{ml4o$j$?1Y zd5$vy&T~v(9*;A}^aap4_63~hI6vS#9p}o4<6I#bJCK~`xFFy$bX;3lpyxa(B93$H zT+8HKF_&>s88bQ0Yzw&FIad$8wRk#GUmWMy>Dq|nxDH@C=Q-v)$F%{+Edd?-Uy{x_ zjycb9UEmxuTL`U?T+<Y=JAD&z%_KP{%>f<P@jO04DRJ45?DS;-*EnyRV|tD~fOE{` zIJYF{xh^Z<`8dZ;$1!_KA(e~cx)cKExz2gs9O#7ebj4-N+ax8#(X$5$y~Oi49-kfX zHhKPJ0z2n9P7OHEb;*JA{;)genHdCj&T*U(@c4An>CywvJI}|l^H_GS<y<b{95Xp4 zJptGFq{7duKvAI>l8#B2L&z!46UpxM+0p3;d%Cp0NsFXo(&ZF#An9@gcBjuH&JV{_ z0=b1eNIE86E+MZt`pTf1jH}9+Sw(tdWHZoIXo93;(sdR(iR+4FclvJVbZfyHuu51h zj!CydSc#-#(k&B~i(}F)5tbt9m~@MT#p0NB3xtJ8Iwsv*VV*c9-5g;)l8#BYPFOFl z0NxMtgM5M)l8#B2N60IVNta8=jih7JWfyXYW72sFIgxZsy5d3!aZI|RLNO#Aldh0Z zSR9kCpil%!cNts*SA{F$m~^*<>qt5#-A&<!I40da;VzPnNq0%OD2_=Ni9Hb60_ZkN zclrp7>9i!r#1<DV$uZdl=%OS!COgILkmQ(b2XtE{IVRi0#l!c1LXbd+kECPLB@vQ} zW6~uS*h>oDE<O=D*S^N>a4qNP*y%XVjrU}B!k!E87_Q4C<V4bC2JG})_ezdqa-2ta zhp}_+4LZ-oG5uQ^)5pVl!t-&>OE`Mx{oyfmTtm;!<C&a$A!DAGJQw#=l4J4=(8a}h zT+hKV&&_kDKypmj696~Bc{<)lb~?_*0nYX8^j~ovcIUC|bR5T*&UNlMm-E`P^SW}~ zH^6z0>C*`8^n`1iJ_|h8ewJf-4$g56-4{UTylsx@Iqn8H<~evwS~(BXISxeUd=jj6 zp3k|CE~%Wuc`lCWIqnWP<~ewbr<{lB9QQ!yycgCv&*xl6mtW4|JQv6G9QOhoGlM{3 z!ReTEg#_pMO3Urh({aq(<b7ds%(=4CIqnTO&*YeMBpA?D#d~HIP+6#kq+`-G5*mtY ziez{CX6SSQpd08abP>m->n;Q$>5gT<|4RoagyTp$Cf#e{jkwksv4;dLg*He!Cf#UZ zl(?SA9w1QYg`{KB4Hbrn8;KkNh6}@xbfJKqK1@2@R_SzPo45nW!{Cr`5J|_RJ0hGA zcN}>Va7>N?Iwr@?^+(0UN^(p%Z=}Z{Id4mHOtd(z+Y5NyKIwF1zqnt>xS8-;Ah;pv zm~`=kL`b@XATi*WBmi_wj-Bh{i~EdoagJlc`EPLSpOBpYBFQoNDvs;E1FrocosRqj zbfqxo14;^|k#tNtB~%p0q^khRNIKV)6GzWpR`^RikEslJ4nIkbNhNWXjJcLL09|=W zj)||hU}SF)B=kYjG3kZ~q2icyLqT6j=b8cH=-K-V{lxQ_;eh8DCdn}g6E|4KTuVX# z-9Sl>$slo^-0|}-&|c_(q+`;x6a2+7>DmZwk#tPDmO?9WOu80AYa|_$uBXsT9Fs0k z=z*kT(sdKMi(}FS2wjkLOuEiOS8@H313*8aFOrT)7cBG<7ldSY`rhbtAz%;~C=3?I zq#Gg(Mba_pLWN=C!jSAvKOCKIM`rBvz)m3wNyns%7GlN4AZ@@g*#qd996Q(V7PncF zW5W3@(!-IQkC5b;M2h3Ot$@dElTJsri+hXw0NxAlkaSGCzlG1@J|VvVj>$(r$K=?# z{vUDABsnIWe<}SblJn0cIVLZ}aosDx<6cXrBX7jz%Yr}OfINa1l8#ANT<{jhq$>gP zOFGvS5=YNoP$(dt$CLs*M@dPJiI2EqGUi%R6wnox<d_r@*8$lc_zNA8bWFM)LN9Sl zx}Knuq;pLdarEo~LTB+jCK&J>L6RJk-r@pf%(bLDpzA8hG3h2Q2Du097GjZfOuC)I zE^$n{C?Oh2$E33bEsjYSE^J29G3ho55#pG1k-`=v9g}XGuw5LJZmX~ZNynr!!d`Lv zkO#p5VLy_NNq0y%EbbEWBDer91CE`Yc?DbroMXQW?tojuZE;Mxlfo$^9h2^aa9SLb z?z(UTNyntSCfpRqq&q8|L((zn&IsqlG3lNO&yjR_Jn&~mkW2V1j!Abt$8SDiOh?#1 z3SY#1K(agiKj?IX{hjc)xUWcdr+<%5$E15Jof#kZgZvcdT=yMg!ecnc{ta-R;~#)7 zCyu3OcSC17=Q!p($G>DgAI5pbbIuFU#RG8x*D>QrXYxGs?3}A5j$`(mGG^!bICggC z1Ys<a^Gv$&!Z>kEx+%g$Bps7(vM@;;lWw#y21z#(usi)Iao)%hpg1TAIA-^eF?&PM z0Mr*6iDS|=7MdXGm~_pA=Hi%iO@$Uny1Ibf>FbE2XRj^P6Tbzy9c&Y}BI%fPJA^24 zOuA#jQ6$|z;4}Cnd=$r|E0y&(K1jMR;5+yxd=<x}D}!~UG@wg@Ob(I>Ns)9+Iwe@* zQXo@<R6<H59h0u2P(fTSWL}U*$c?09(s>E_#4+g#2>Fq8bwM3aTc{_FN!JLp2mXML z<A%~XX6O7Q>CW}^bYw2z8qQ4wbdx1HCR4<XMvej_g)vAvCf!tFnz*sZ31GZ14oSzP zTO+I$$D~^?tV7aW0$0Hm;j%a;-F@L6lI|L~32q42#WCp~3J;KUaXs;8KoDPuhoocD zB@z;fW6~uN5+muDbjgII;+S+Pgycv%CS58ar8p*C8X+~3j!BnJNGom^awmuqqLFk= zx_!a{aZI}XV7H`mO{_S2_84K0cph^Y@EivvIVOk1?Ugat5(DULNsfsYcMW+RTotY$ z>6mn<gwx_KAuj@sId>kMlg_*V&H%3C8g}Pe_RD~CJeF(EN@sGONq-M;E!_>_rnm>l z$ADwPc{(2R61)Hp0UhU_NvGr7UBI=3owv!kr+{nk06NY&?-L#8xaNuQTpZ8IPX9>K zxsGGbbIjY|nCGQqC-(szlVh%Pj(NKr-vXTHn8`7}Hl}m_Hah2-&Uxq9c^#RYkIjzf z7uYTALDDhlb_vnqm~=aYC?p+|Zo9Bk9Fy*la2QF)q&pxS6vw37C+tVkG3m5m#4+h? zVK0*IKDY<&2zSLX>23+Pk#tPD>%t9jOuB2rO(Y$Y?uGDD9Fy*u@El3Uq<bPf700A| zC_F;aG3g!%kHuBM9#jE`U?J(4bmawKaZI|hLOCQIldiN-MjVr_l<*glj!9Qds4k94 zS4F6bq+`<g36;b#=_(49k#vngBhWx-D2_>2PpFTiW75?T>WX91)f8$W>6mmigxcbm zbghKeNIE863!$YrCS6mZ8Iq1k*F<P8ZYXjH2oVM&>6mm~g>K@yBiWt43p!nINsjx; zm_1ZFT_?b#|9@QF1+=zx+4XBgy1TnOrMtTu73@y1z(fV5yA7m4rCXE`6_K<HP`XhG zTlYMC=YQ{e>~D<UH|xBvb+7dxAObH>-%;M)?z7R!TiH9@e=f-2KOAiGXPW8AAB?xV zJ2)IvKG1GFBlFZV^u6^|et&siRQJ)qkN#urK3<jaiJ*IBiu`w|@KSiSUWdQ7yJ^b& zJ}ul(z7y3wSe5ZmyY2GNeC!x@DBDMM2UTSp+;0Eq8^asQ>!Z5&RAs!k-91z1k1OHc za(7hsld6on+WojH<IbS_QB}qd+uc!>@q?iIO;yIP+x@C4<Cj7Ai>i#DxBFRD#!rLp z{;G@z+C3coWB5aPD60E?RmShy>G|K52irdqeLOr?9*ydrsLFV<-BVQ=&jua%XUfy< z-aAcx&BD9O`=Yvosxm&@?n6}>9}K#W2G8)&zrX%tQTxZMGCtAH-3Nl_^i+oJjlr$$ zkf5g{9~y6eIy@C*d@ATZSwDKu>M-7SSp4VPdH(_RZg{)T!P`F@bn^byvCDROzaW1u z==j%H$0pn5Hw5|9LC3$XIyTuZzbnX}2|6D7ch<i>YM0+S(YcfHj^OU({Ie*Rhs(-I zQQZku87H<orz+#TpaXwy`9`}-qx|T<8Lzu0TpzA0*S348D&ygx`)5_gzuG+${ZIIJ zc{-}QsVd{fc6$DX@}2f~OrPJ^gddh4M0LNd%J^NoDQ3uD2a5ksc}=oz%Bqalwwoq8 zb(pG58`aHJl`(U>r)SEaTZL!KGf~}3RT(e0dp`Q7@M3u(s(Ym><JES1&740k344^i zqq+mDGTzkg*yu6g=&F2TIj$YmoluUC>ZtD2a#B00JEfc))luE)<+OIU&z8TQFwx(Z zth=Qu<JNZHtIGIp(0!*W<K}iZRb|{5bl`6Y`_7vGjE4Qoeo@^!sxsc$PS3x$yr=!= zqMr?)DThUMpRdaJLc0a?_YkZSRxS%fb@Nqa%-?RcJhw!%ZjEFe_~pv#?UsoyKhZB6 zuLHkP*|^=@dFPtmTjq-D=Bdh<x82&!>qPn2HS=pVZywz&Y+AO6>UOQl*sYzO-?Qx1 z{<b;u-?PH)<<_X~dsP{?w7a}2<FcT;qAKIcc6$CV<)!w|NBPk|7q0{VM0v8^qfvhJ zkHqW#Se5aIcE7L6csS_5KU5xUx6oYq^S_CH;bh$+RT+!6TcRps$)H=VDr5O}f6u#Z zGX9pVd$lU#ukEJIjZMZh$-3#PGNx}gLsiC%LHDmb`_J%?^6#kbKUEq3ZKvmF&a;>) z=%_qfnLVnbx@F3;?G}sjqhCB;2Y#M1Z#$}+tIQqM{VZRbAN^00bq`c!+}}>m-&^i$ ze|MB0{XOxz$Eq?OZ>Q&<Ezh+7Q<NY5pW}7l?<_xVM|D3acSLnmcU8H%-8E5u^w-Ag zz+YFcZ#QLrHm?a&l-EXeQ&nY5-ENkuj9G(jj;f3~+pSoYu|m)-U6rv^yZNg!<_o$7 zsxlUA_q%)_HW|N7*8Qd`<JaweUX}5ypacKQ@{4v)MfuS`9j|+#D&xg=FIQ!}5_CVQ z%DAiDkE$|$7<AvQ%DB1RO;s5;1|9et%6HoRIX{zshkunvqPjm-WjxyMA65C6?Z?gU zC%S*eyQSmy%(?%+&a>`+(VH`}*{7_^Q-#;I(@)*b#_Q&<*I~YPRQC1fo#^CW1-s9{ z>*h(;jZOC4PkS?NWt;p!kbMul&NKE|3h(Cr-nf<B>*Sx;%RdWt@ZNKG)aDNN1>HTt zjSZ8XZKga6?{If-(7V&~I@vpUx3-ysOvgKBjraZOc(-)6pr^9^;l9s%$GddU{V~kZ zXU4tE)7iVtS+DcV($OWt+`*>j=W4bs7TofSheeBCXXF1+wex!FGwPNKOBTIOet%e` z=yg=LaN*A>-<at6bIU>#J?|ahw=6!3PToDpzGo_9&!D4z7W^K;<~cpD+bg)y%~h|n z?H%;s_29>|uaEcK{#Dtwb#N>17wp?KkN3FI+1>H`1h+c7cWo7XZaVT7@pd|P&yUXi z=H1t>PG-0ATEPzfb>R)cuA{QgV_PSTd)~HT`|+$^CvQ~0Z`3=+yJX+1{Kg=AhS%A2 z2NvEY9}w(suF7~zJ9lpiZmI0u*d*vSt{?qI?ezR+Wz+V*i#`+{EWeNH{#BLn?{>4# zlmGmOS<4(z-JDe!bG4g4x?otK%oo+oTa__SyP2yp<_@}9f@k=dnt9CFj>@Z+Rie5X zf@gS4A9Pe+udLf{+UVHbOc!)i-lgo^ZfqY-hP$K6k?r&!3vLgtANL<=M|J0xZ$x#M z1<&xfCg=_bdLG{nx;Iy4e5>7?q6Y>y<4*UX;2C!^ufvCf&i2iqJG3g}(sqYbWn2<; z9}k}4@rj_L@>%7~c4M158SYLhC$`g16WmT!Kki@Kj_S54TSs+M2G8(#P0&$!v$AQs z|K_*-vAdZf=%~DGStdHUEuOqspn6;#bc=?u%Zs#Is48ROpj#p=9hNFfwp*<#WA&h0 zAuJ!3D=W5JsVZaTpnF|dGpte8YPWV(#yUZ_Vb~z7Up8vDaaG19LAQC>Dr{M{Xt!%s z#%@8keb_E+TXtx-V^zjZL3eoga`;j?qTR_=8K(r@vEi6-bUCiw@l_co1l_6OjBt86 zt=)N58RrMxSHoAr+2w2PzFw7aPS9NtE)Ex!3)@{@m2pMT%{X6vUl(R7GemXMRb@=y z?ln~zFU_0ZcB4}SD&tQ<N9DhSDSM}r{~UO{9PCuKy*7Dt@+-lPSA(6(wyBawC;v6r z@wZ^7vJHO^x~a2`UDp4z+dsO?ynWi-dq#%sKlT5O+GXB8O|nkLzuHmRE&d&J>*jX- zuwGdws$07%W36^;R%N^{=+>ypSiRk9RT--W-O5!NtF+s!Dr57Y1HWn6q#f05R5p(4 zHVFLaH*ELy`SaU*IJbN)synAD;~VYt{Q2dA_H!<n-#v!8%Un_2990>!x0|&pW4551 zuPS5ScGFd5OdE7lS7l7oZu+W>8G>$>s*IW2%~+K&Q_#&{m9ap(g`*3F1<N8)-J(?) zi?v%nx?$L$tQXa-Se3CtyXC4fmJhmht1{MUw^mig+CjH!RmLjqR;tQaIq0^k%GkQy zC!(JWhn7R4x=&SQe7fCXRT-ZPy3bT)e72pQ|5*8W`;SEV(SI~v_uufJ@b5CkLjTvT zTa~e1(7iTH8D3MSYPWt>#s)z*ZI~uZU8ZZdVO7RPK{scZBg|grYPWe+#uh>Mt9<T- zqYIT^ChLA(mGPT)dj9e9So<yW{5E0hvQ<>KYgNW>?Y56@7q%@sM0KC3%J^)%&sAj{ z7IgQ8d&52D{&o*mWjqvgKMOw%50sy`d$=m&4?*{Mcq%+uo@n<<RmQ79_us0FDHi^} zPR~zQrfvUH`oDxfmzSfue^+Jvr`^<f&L(4;WZmE6{}%pQ{t?x^rkji@lXcTqWz5iS zs_0B%#`4;z?q7M9%J^rp?!~H%7uxCh=gXhk&zfgv2{V`3qPqF3G8SmJWL3seK{scZ zBg|grYPV=r#$rLYY*of`?dFZn6Xq`SMRki;Wh~Kd`KpW+f^MO(Ojx=s*lyvfj75SD z{HkTOcGE1H-$uf;W$LJIs;Z3Fwwtml<26C|-$njUWlYg-j;f5=gKoB}j9J^wQk5}t z(9KkpF=M;wt1@N?x|PBzVdb)7yA`T3mJhn+sxp>sw{%s;GC{X)RmM8))~?D}E9hQV zm9b{KHL5aJ54u&WGFEGMRP>l|bU8Ar`*Kyrm)adsm2r5`eX%Oz3+)c8%J_WHol=!? za=VkNGENM-6RI+fZ+C1}#&JRSwQx@OdiiR*uT*869du_^Wt`dWjH-;&gYML-jMLg( zT$OQA&|O%SaY4KDt1`|Dx^GlvoZIfM1@hOS7Rz6oD(58Y!2h^<=Y;=8yiDDEy`0<b z%qTzlv*UH(&njoMJ3Y#e{(|_?(bK}ERT*y1ufH&Ar?&HgjgEX#y!|Wf?K(F)`A7Bg z#lfz7C_kGA%Zu&Y*yOK<OM+)$(|xTfyOa3?^XCY>4hJOb-c*(G=5}wb%6LoAy{#(a z?d{%BmGSzZ1HXTHW4kX;k^k(4Bg&Cc-C2Pj{n_o#jGhrrE2l?wrv`rXr?fk%D&xeU z1Ajs}x!t+`UapD$yks5t^UDS8sP4jYQB-$v;75N+yNmPgZ-z_DB~cyK<qysO<6G@y zeSTb1=;XD^x7+O+y)4ME>sG1C`9s?Op7kE&4@v*)Y~Hzc;oZW`62Z;N!Ta3tx)p;? zcAx)P|G&Gtox);4Z<kjJ?!kKpwe38SS8JyBk$0(IHR@S;jfu{kjMalXUwiSeSn&Pu zy2a{WmtPy`?flxoF0a{L&#w`-4{mhwTJ<t-zpmcSUmLC|*SB+PlW{}PZC91OYjpCB z!A@@qZz-drx=jPWS?~^-*BuyiGHjdFZyvSFy!}l<CvQ<5yKH}RRkm#zcx)ByRJLL3 zp!-LD&VLVoEB}n@!2c^Z_;+vrlkVU8^53ZLKiT>Jw@=pnddmE9Cj7SiCaMGfOnJK9 z8F}XHa8@}psssPca%sCW^7lWU9nLCeMs?>0e)Jc$)AJXW3)+7x%8&lr@jCEVm#f<S zH2RD1^YXK(?(x8n{)u+?R%JX8bl~qV_qC(Czm%7vI;#6~dAZ%R)8)S-P4v?x>+YOB zf1gCStNb{s1AkAsyWQh6<-hBNC(9F29r!<&zqGq?=KMVq;XCD~s1E$Yv;7|rMRoUv z2g3d3zIJ;4#oXbApj&K~{BOtMeP!{e4*aZTrgl^}ZQ-}9e>v~7&lsq@LN_;9KIp(N z9lT5CF-_2Up32iz?JuRD>}0oY{u-74Qk89^lV1&Xyb|o-efIxEZSHiuPX2ej%>OHR z#@&B|p31h#ZkF7+rFuKw+it~K^ZVYgR#_pc13zDxzui1he)RLk>%h-C$Nw=)RJTx+ zAN|7dI`B)EW!jybXO0P{1pcJv<D$pb>tuKQ3C;BQdi{w(w@`k&n>#EV_ywEijm}fA zlil(2H`Dp*^$P^uvvcS7bK&XoTvYduz>of)?cR|;QFwQFS9xbtcW~fGe^9#*Rb_lQ z=-yM6@&0yt{(a@W?LQFZNB_Zi-3j6Na9laDot{6loYkJ{&M0R`byRm!Il0{_QGWEN z#_PbJR!(nsSM<^FNVzAf1Alk<NxP?`{OF&F*X^A@>DnvoS@wzQP6+(yPi(hu^z~u? zvR_mO{^W8}y91(c3~wk0Ms=qIe)OlddrS1~;cexuQQhf*AN?8aJ`nwI_)z&^R0sZR z<*V%uiheYFq#PX8fj_5wz1_#6hlEd*k4JUj&n@3*cWCs};Zx<4QQdigAN~35@*g+< zn!zdZyO{rx|ENr%yQM1Q)}Z6v=1&!-$RFDN*X!i`V_W~*W!~=p@#CKN|K!*F&;8&3 zmp}CV@1FX9HslX+Q|R)KH2hCx%-BxPFPlFX!O}rT<t56ZQQb0C8TQ5N7mM0u-Y)aY z7v3)49qd1;*V&c}<9>yBJJs2+V$eOF&-z$+wD3=qC)+*OY@04W6uS=7C+on!ly~C! zpri70?dUVj&(_N?1h>29ncc#UWs|6Gsj3Y74rS-)PG#eXo_D)Z;N8ee2Jc(EDr1Ru z%Qd^z*>tk^@K`q3m#Np;eZ39J=w$tdW&Q4Ye!bv!>EM0yRAs%pb%Q%P^4RIz!E>`$ zWxf0P%Vg(W3lzIMS-(zjJ6rHRD!ZE{j7~pmJ1Wl=+|iNeh_~zJ3^E<J?tN|Dg4OZa z7Ha1+@%n|^$%_O!cG)hk8RSKSj)#8r`o*GlnYYgrbh6(48qG6C?PD96&QNCV&Ad^5 z^z+5*sBY!LdtP28*jEiYU!Tfjr^^@KCa(}YzheEkS*hLjQC{!8s|C;c-guq7OK?MF zo4if%4m$SjCOZALLAQ0i4qLVJPG0AR-y-Pg$XmwSeeKP{*r^Pg&+gW<n+81{dGmPt zT7kED=5=Abhu4F5OWmzqM)!&Q!Q;?yNcnhF2mYf~`=`T4Cc1;_bvQWaJomAnll4cH zBiq^CeJXe_9r=^-_OX2?9(vu;!F$F#k7=hrw%hU1<C=9g-APsXgh0phvRytg$R`IK z554ZRaB4WEoZjxNsto%X^=C)z@|hEzI~iXI?k)-!h6~EY?Wpc&;TIE~d}pxZ$HC6) ze^m6kOTxFpH_N5%sP3Hbz(gm1HQ1^A_2!>O-O{l?75`-WvFRQT)GdAxbl%D9{t$FB zY+nn$9v!zojCZT!-TpD?<a5J#&a>ZW_w%TIJSTfj_Kf^U(DCO5z2|X$&|M$w;~Cj= z^4K43XT!BYM`d@oF6gN2YvBH%yD)#UcR@J6Tolz&-6i4DFgp3-V8=Iuo!5V>=ye-R zl|QD34a@pb9o79O|GfHo6P^6uV8^<_PGuYZ7If=`vCI0uc3Zo<%-h#$C&Tv7?yu`E z^Y%5`$*}F;ea-GNZ+FjcTX;M63!~pAy<1uT_n?!v3Njse>v;Q?fwyf@9k;Sw{zn*@ zZeDnsyjgHBPmw>b95<VGqdMEh6P^68JY&Zu!A@lx{vC8TM{fz=E8mUkUaHD?xgGEJ zw(v^O>*QPOW!_G0-w&^b(aE<5J9s;_T|1GlYNmGjTyQ_OYud?I2bqrie7tAIc4fRy zzAVUe<QL-YW4j_=Ctn_9I`WJ0_OV?buamC}G9CF(@%FLZ7_XCW2r`|_-)Z;fs9X7_ ziO#)@zXW&N=C7yj9Cj+}M|D)UNZ2lnZio2o+u0TkZmGO*S*)FBHwd0{$B%BkiQe-| z7T)u+d(X*Bg>l0#9@Y-t;|_M+x<SulouFH*Ug!BGf@i2aOL$$dk9WzQ8+Wq1S%c@O zJad>k*!5%6%@e%ChS9Cr-tPI8^Uv?B6!_VKcT-vKxzWk9cb}sw&-nlAWY4*oA;>dT zW!vcVKFj!g@_c39Zg$>hr}hOV^8C%zPFD@?$F@-XO6_&>f`JEbr?zRrD#3g7^0dKD z$L(~@c1$01;O8oHwp*bpdyhMvynMa9Vi;eC%1Z~EJDJzX%hk*LvSpcxp5G>TcIDuE z0PlOXZ5h0S%3C+@7#+`18ROR77Qu5{)$2BIXXB~eo$MV{w^`V<dHAu*n{?N06nt(f zd(QVTx((ZnXJohX#z6+ZMzF0Gyo1Vio6N5s#;&vJmd;<$+B@u3mWt|@tje&jRKG;j zzF1YZtsLCSR9>NK$BOOr{HkS@_MX`@c*ol9Y*?q=c<;K&@GiH!XYIQOooBFH(5)Br zW0yU*e7kWc+vMefyi8TLjZR)R*ulTAytf_I9n-u))H|qW?6za;sr>QgL!xe}Tl;u^ z{dkO>_dVG?|B2upymwIBLE+FaIx2gI?ft<mcpJ5SxO}Lcp8sGNcOPh`cJH+v7j#r! zH`w+FIy$mnQ#;i!UdFBLx0mtTjqJBg?|D}knaZ$zp#Ggv_wsutI(IT`zAygW!87vl zVRTf+3Blbn;py;HdA8jjt1|2_)c+xBf21no(RNSNkN(MI9o2c?<6(5(`(k?=@Amn6 zyR6soj|K0LdEJFUCwu0(V5jnf!FEY-D?b$MRQ`Q=xSc!q7nh5ox+{a;`)s^U_BDC8 zwr`e8+u5!PW25pF!RC3H*NyLi$N0S0$NSvlv&we)x*&u9dO4?^JDUvq*UC5A>8}oM zscakBXOyoEcA3h!Cg{NXIZ)f>;es$aKO0_$bA!&^w}R)u+o|oc^6hqd{`@j-y^kOL zdGWdp^FQEh8a4?l1$lV7S=gYx9V@q^^1@|-sE+CuDhsxoE&n?(Kl<5|b&FJGEZT0x zs*II_Zq<6-YR$vb)x&Q2I=hA)%C=G62dXmc+t<G@YNxjCf{l*+{&@So`5L@!-T28{ z*}h*@_MY{kJT?q=D%-G8(0w`gM}{w!!=t({Rb|*eU4KN>E`MU8b0@?0sro~ro{>M< z?$D@y-0OAk&u98@_)vLYR7Z6m3~vvklRpsbcvG-b+4i<DI{B@^jyDH8uYXI?>rM&Z z2&b2m+fm(V;mC<jJ~h~XQm@0^?QCwoRCu@cpM|^1=&0`2;F&K6?*Q-XySXLU-SIlR z?(o9fJYzc|*r@!yU?1<0?ec9wrt*)=9qn$f%HvKae?RcvW&3V3m4Ddm4tKVrKdt{k z)H~dc=XLUr0#D@!ns1J}rDM0<AKX&;-f&MC9hE(2yDzu}Z#%1gJge8qU#*w<uQZ<- z^{jmMMCVTaTGfuPPjqL*d!CM4_im04-fRDS8MpGy!S4Qq;2oafb@E}sEtPGa(|w_g zT^>JIDjyy^b6oHaD*HO}7sI%tGR7@`MDQNZ9vwzUW$&W)bHa&12maVHd8<1n=#C1$ zhRo|^-hU>j?W8igZSvO*whmjBEuy;Zt1|4H)^8iN?@*PoUAryoNAG#vX4Uad@6&<b zq-@@9?<ha|ed2ZC_bdCh+rQbyzahN7xE;Ihz~DLk0nK#eH^$q?_NI8~b#D%D3vVrN zY4`T34Eww4-x0OT@0{q|$#{2gcU}J8s2jr#<@%_O>YfOXh0)2s33mK8*m?c0i(a>N z{(0kV!!~8BsE+EkFWa?SJvw$b`qjcJVU1vyR}OaYdhl+kyH(5RKA-%>@P%?%R7Z73 zl*8M-KRR|d`uBzRgbxI}{O(`}uLtjzx_fUK-LI2>6@F2E8Pz>sm0|x`{R>gM{PT&< zos1`fJKo&`;mM%a$v>@^c{{b;8=eWHlkW?5@OEmuCp;ELC*L3J;O*4*=tO>`ncC^& z!Ts3&5dTzro&3kZgSS6aKkoH9`N4Ym=`il~zinrGxS5XpV)x%o>^e6(c*k$*pN-n( z-%oVzWIPw#&7XfxeW9>mSs<#Ty5-Aq?G}xW-Hm?PZi_|jGH+iZ=;Xz#W0&pn(m`G_ z==i0oW0URjGC>BvaIndXG}DofiMNk!)_9#fTaf9<$Hv>oHcR}RL9df%ua|lI9QET~ zuftryjcui%n>*<Fd8%WR?ekV;+lqn5e8Em-8&(LqJ;Lr`x3XtDs{3*|GOF7vc!r1m zsQSI5cA2;D6Ld0cN7wHgwadJH+n|%Tsg7N?%ZCMdyP)H@uZ~T&%bySOmO;mFQ5~CX zm%k9?t%8o<x;i%5E`Kq|I|LoSV|8q@T|PX>I|UuTb9HR8eV3|iJ0kGdHQ1?a!<T|? zodxpW3B$T&?Wm6GHYn@2TOvAkH~PiHqG8Ekmlp|k@OtoWsk_C>=nhW)X!uAuD5|5n zkC%_NJ0LoCH~Ke**M|dxUEV*~!Rx`hrS9HPMt5ia!K=H%kIRpuI;y+7{G{F0(XqSH zUlpzh*95zKd9Z`mgLg~aU0Fu=_WZp^ZwqfN?}+L?5%|%6u-(V2GVGr$hekgT^t$0c z6z@4|)8oTI_pvZ`S$|OA4-R&j*L@`DWZ2$Q|K6xw=ItL1I{AIovCDS({XqtQNO)7Q z>*NFLW!}DjRmL9eUSE~5XV6i3_ldl3Joam6+bg)$QyI1+!rsBXU4BEbe=dAB*s)L0 zx#M+*1)c1fHwHVEz3ZL9KAw|3H}2%mx8w1yc2xGhFHCgadq8^|?-uV4ZmDehVi=wL z=3obJ*L&|<ihexHkKT=+lYDsatjz1q&wo!lFPvL0i0W<(-w85q3OXvgzdnpkz9`tK zd||n`o$b2dIXZ4HiTBL7lkM`QK?Z+qxuTsrn+*F^VSJ5mx2JCDWx@W<dYxx358g4J zkzu>CT-{F3UlZJaD|nxt*V%a84Z$wMru%vLRrqE3MLYUjc(yzro!n&DpQ`_D)cby2 zmGPT)?w$^w(^J_l|E`&i{QG$OlYzJ4k3mPrbB|AS5664=_?og?`Jo_#e=yh{3En|v z`=eoW`p4QmQLpp-AHsMiuLtjzx_hRK?#2A`Dt`%oE`N&Z7R^6Pu}I(_Xg4<5F5lms z$}6SE3*Fqgzqjyi<@vMO7YO{gnWx=-y&dn8-PoyYd%j+tH=CW;uN)7(?vwckEj}L( zD~CpP^mE~}<%`iTgwHe&|LJ7+?hXl)&&#$?1<%R6PCh(%?#N&pUrVq1a&R}E|5Ch7 zXOnS6(1Smrc!%z^aBA?3&VGF1PY$+YgIiyZ*PRr64ZS;FC!bhPWzX1732v!uAKBNH zsogWjh0#%2?{geeMknk2ymUtg@1nAO<nePosy+3b-kt0@naaPIC;zz)zbikF>V6%5 zRj>PP_{~KASu-8a{4(BiI^KI83A(Y#4+iggs9q=Qp9pTpJD!ZUQ@#C9;l-dIo6a+j z1vk$Io#*7I>Sf-pcmH_NkIuUuEp~UZ-e+~If4cB?*}LuT9u9h+^AABs^}PO%VRZDF z;<@p>ZhS5N`SL=0U(+tzyz{v-I;wL^-S`<{bhGELN6Z)IEwe>+bA>tUb@PO|C-SV# zbUZUhyytYh_bd{0W0U6(-nBrzPS!6G+>UoF8E>b0`$}QOpdXvgGm8Z`%Lbk2<fZCm z-mZ7Qc+ro}yA~~Wce37Rb*o>x@OIg|?d}!~dY^Nlprd+Tzi=2GU8Z<$Jg*yHi(kI1 z(B9Xy%Qo*^u8fZA+)_7wMi|{5@q30H%8pUpPJ!3&R<FbE?QFY-T>`&zu*<w|zvlhx zJ-cr`b*uB->x+Ke?H%ui?p5#II@#?$VeIr>;mzS~!4B`%*$xbz1@C=t33hkh$LkIV zc6UA_uX88Av6+tihIl(2`^e*+Z|W|)lYI^9{co)wo$OZjJ;?6}y0OVV``g=%J9%tW zw!O1n<~@6SI3awge7W6`QC@#+y$;8<vmFzT4*XHUF7vumn@_9v>?!rst<H0&7yY<9 zDc%h|vEI9NvfGox*y;J<tKpnrhj;62X9v%M_r9+MyF2gWb!P>;JD-u)xs%UqrX!yb zZ>M7)dA##0-DP*OuR*>4>-D3P-O9cP`P`rzo9wfHquscZ$3|t_dG#{y*&pWLje1YG zyZj)k`*FClUiXu5*F?UfnT}_E6z@45Ki=cHdjq|%{%29Q;~Clht9IU@dm!k49o&vx z9{c_AZseZ^&*<py!XLvQf*qdKdB)w(gF8C%`2HSD=bi2!s@MG@xbX~?eKz@*6Im~h zukqV>jE?uUy<7L2;5}5fkL+{1d$_&N!Ry@pK6sAGHqVSs_KY3Ar}49pZByp2{Y@XH zE3b*_rVdlp>!uCUOynt=>3HU~@t)K1<2|06A<!A?XN|fY&&c*U+j)m>=AfS|xE;GZ z_L<_{$g>2`=;*v*;jmD!!?QZixSK7wqa%;+Z~k=N>3)HF-R!}QXQ=G6$#YC(y*$3g zJn<ME?`wOvZtmbcRJM=obGuuxz0bkx+|3s}M`fF5Mkjm54&T%GS;)36!&YI#vQfK@ zqr86edL6cCXWJ}n8n&<QQ13?XW|QDKnb+BMJJxR(wadJnZWHu$>w53d$!@j{W2gIt z-NRnN4)4|3b`72d?|pj&yF2gWb-M(+JD-==xs!KprX%kZZ>M7)dAxJC?y@`C*P!0N zXZ`48x3cd+-Y4kBCj0Drw;Olz*r;sVw_fHw`?+vf_(VCR-Jwxl|CxFnKHJXr>F}v= zMD<JcZuD+G89XQRI=k-6^@m68GH<6}2zvVYdhgK5ZoU}CPEQTTg%g7v-m9}66Fdvv z`;HHGcizYAjt+KrJ}<9xCm+>JM?Ny%PRBm-c;~U*Wp}c#LB0Qk`q9a5W#5B*a?p)U z_SsKrH}2%IQQ3A%z07;|r}=AAzX(4sKa1+t$X~BoC5)b5tjs;p^PX8e%Da(y9oB63 z`}DsHzby|&buU+6imsYls>giEI=8%Tg?2Je?O3thoAbNzw}j=(3Q^s1fgk;{?Ut#^ zSUTvItjbub-I`SyuM4_$sxsDXw_a7o`a!orRmO(xHmb_lIOsO1%GfmMHml0mJm@~3 ze>R57_(HM{{1=O#jqdsApTdjfg{Y3|{!;$jZfvjQpD~3y8~<{!%dd7n^)>nPqVS7y zN>oR6f2^l_Px=3CCnw{y;NJE`)N^_&!}g}~XgkljJF}b-)wzE%*mU-D%hxA5`=y2V zjC@HL&rsR+R2cg=;=R-RsBCxlSmDR#_nAlkbi7+x|44Wy=ymer^)hewHO>jXCiwHq zdF^hC@}s{!UiX8*>n{wR^*))`$(!eA%<C@*o|F0UteY)@O@C40-O4`<_C<2XkDEo4 zb+4r3^`5zS;)b{T8oXWRb$GQMmA4FT<d=g?M}8^ZKDMc|>*N=LOh<k;-ab`(JEjRb z@Y4mio_)SN7uC&_jUW9C$vSz)sQlVy&+BYD+1KE)f3W*{(}uB88MXt<vh6(Q`RSYK zWOk=}eQ+x;6Li~z9m5V~>vmMPQ`jnO8{ERC1HXN6M@QZ+-oA5tyUvYH-lbmNJ=l5u zZefq0*U7uq%e<Z1_6_@m(aHM+J9zu=!}H<Fa#cG$e`~n9e%xHs&gSNpa$8ilcmDkg zyx#8lo6G3F*WSCn+sz$pI=7zNHt(alJ>xMtH`^rpnmS%5^ZS$oqPjN+e)Rjb+qa!( zc)c6hdv&`9J-=IZY_eVU`Q*)mj)#7)`aPm{nYYu;f_{stj4j)3U9a0J(D9sXm%Vpn z`u+S&z}xs=1^2(K*WDiM<Fm?o+0S1F@7Kw8dGHQ8-f_i5_w9Juj?041d+rFMqq6tX zvELi-89MgI;~#71{=RxQyxnhGy#0xwlVQ^>nSW2j5@E5jcvQDn{`~?}#@@-gMVj5~ zY&v<-dU>C0c3!_)*rB~nUOn*O?W@#}UDnGh2YLH2Ze{&SfnPP)WnQ;k(8;i^P`_f- zF7tM}e9%+bj^%=G-+XUlm-S0^Te`c<+jq;oXXIttk6pIQ%XZ&2S!aWOm*$<LcA2;D z-cE*X+xqRIcA2;D5p?qQ)v?QVd50kH8FW1KJJs(PwadJH_ApzRwanCx>ShTWOmth+ z>ufUzw^W{?dGCC$Zs^$MErWNsn=yD!)^Am|ZuikVtM{CZ*V*Nd#mjW$ZPMEhNypnf zzj1I&$LF$rJh<IE>=P#MWSg5$ltbHnq`h~*yLIl|^KRvZ^EI(h(7itJqj&S^;2Aoe z*+1T`j(0Ef`xV|UzafnKPfm0;8RP5lp9!9!@~48&Ku7*;yq)Sd&u7>yP<id@cuuy< zekSszQ62ARO2>9dvi+i}Jnr_5$LQ$A!7Y{TH-^#4zQ&%xuPK$?-xS>bt19mn#;yE| zVE62<!S1(FUT1T2LOHe_)g51Wck*$;zGmLT>uf)-mw7w2`79%Ur<vME_C4{-<vF+V zHzzuq>}Nv9zHDwib4xnjhHnKO9nal5(doTwudruT*54M~{<<o=`*s-nZ{qE;{`TTl zXLEB(IkDYu+q;A3bSDS5o^i|T<gv>q1^esrz4AJ^(SaYIXN7jlMETMC%sTLw72fwM z|1jA1Xy@mox9eoTP4RARca|TudoarD-MQbT@P1pgJrvx^y9YN^_S-D{K33<>{Tb!d zc2swI;oZrn1^Zfg2d}d|Trcx>YV)~9{&6$4)0J{-ADi!g>14f5zC7^Y?S2lt{l0cG z?rle9xA#wUUyHZt=>x(3SXH*|7~JksKkjvR6}R5;)u8u`jn~PZ-?{2%&ts=x2k-uE z!RAiK>umCyo2l&X9TVL-@ouNf&q!~FUw0jNf4s%CVf6eoW%~BsVV7Z_um0`X#@D8@ zZT^YfGxEGuJLZ|_-rZ;Exb?2L2H!iC?c@8`&E0o+7v>71dtdLVudVm|yMkw_Y@egM z=P_p(9sO`_)@x^z^*VX|dYRv}Y|?(6>SXo~d81$lzhSU_F!;>iea;UBn_C^P^US(o zyoc8x9(cRV>*OzY|6*0fkzsU4#Cwi<PQPHDrS5pTSQLu{9hKjhZ9KDRGRAH@Ah-o@ zKd`-B*6ZXq)yw?ngPSi!eI4*VubTz3jh)J#p=19-vS;+X&GS0>bJelScKNU%gFiUf z<b#^&$m3^8^?nU8Zax2jc7DBW^82fH95vCsH{LCHzg>@K-V+bK?t<W5p4aobW5Urv z4_<#mRmSr9*^KVOWbdHk*5>ACQShtxnd_6?Qg`-i!|3$aO?0+vg8rw$<{4gRJ1=-1 zyw78I_jK^JsqA^%6G2Buelp%Zo_VUf%>T3MeONr`!2iAb<5BOW<2mmhox6X8@htC_ z+T3Dv?~M07`QF}JuY+G_9hKiw-rA1p{QlDO=LdJP{_EwOiO&9w;FgYjZoFrx=lH9_ zxcx!B&W&E@Jy!=kR?g2#ud{u(+}zIQ=J!$XYlJ)EZ8|FZI<}Xh`YYRwO}?V|%<gU9 z54L-Pe%!2*cj?^xF1Yhvesr?0_vc`@$$zSsdHY|2&1cl{I_Q=R?rbl%r?PFz;C5{C zYub-pwtEkiZBqmuyxsTe`@6gNb=S%IN2`7gyxsPb^3`@!cUN%tNEq+rZGQ_k@6z!) zd9}d58r<5wi`Us+33~9O_v~NWx#Op9XTwrqbT9Xoj$7~YPTf?!9nZ*mH)FTGHrT-1 z@rU5EKTws=3Uu6@Inn(w-Yp%sBR`hz?BMzFjO^A%W!qQkW#0a!e6AzH;o+!oWYEc9 zu9tZ`wH*_V4WpBf4tDT%YCAEU6h<c>7wq8e)OJERJ&aC&d^;PjJFT63YM^76?ec5# zzhla$wBt_>bZoL+o-)YbKiN(GRFLV&pN{wJA?@utH#+&ydigWK&g(xLbn@q#>Bxu0 z+sF3#_%8;%PX0o@%-dg^&pua}vrH4!QQd44dFpsf)y_6ka7*P`C-RKV)J{F`er&VH zW9D{tn+)3=!Pm4+7xZ-GY2)qF2j1qHS;DxbGHmk%cQXXf>3N-v*UcU5GHkky!$-ow zWuta_euJ`Md#YQvtQXZ$-8yCcc2u`**(R!^x*f|7?Wk_&vQtz?b-R{b+ELx^Ww)q~ z>h>&qw4=Jc%U)64m-6=(@S{H>S$B9<hM$vekMPNGXxY0R)qQFr?-h?d+u7b8-0G<e z+o!`m!M$C6Td-64v(2xMx}jsYy(74#@@K;SVRTgXobABi7QF3%`tht@Cx5P9<_~M$ zFX~yDxBD78dDrUL<;m|sw(Syl>=t~FRJM)m=OphQ>@t<HZ_rWs4dspPsP5f`|9E-V zM1N4cTX*_*2A%w#W;*i0@%9ggvFmu9=RZ_0e<ax7+s>x5>EsX8%O4H)_qVh0^n>9O z&HN$tI?s9jeeJ01X0rQOvRnO|y6N1=u)VeZ%~88v_m-m9{XYCI{I;x?|3gu$2Km8Y zmwDZj?PS<i@BUPGnYaJ4o&1|X$1dCDRl>;h*M+yqzY6Z<|3-B$1pT<z|Ec-;s9omW zJR5W}Y%kV77q!d0UFN6C*933prw`+P>h3?z=KpxsAELN3=zdt0{}|}Fd8D15zctu@ z6g+o#RUXej8jsO==C<G+x_g4>Zq5HeE-K@;WZmt7*FDy4JSW>_Ut?r?SK)2)Eq&jb z`M!DG9o>B%cd}mgIY<6Uyys;7?S=O};rs2zdw<YOJx9IA{`cS=p20tY?yq4yXCK|) z;yr7FJDty@=dnhz?lpnez0z$wBimmarVKpvI(M&zk*N%u&%{rYTlez!COVr8o9~Uk zC3r^uZo8Y?k9)oDb@^vU*9mKvHKRJJ+hiiI(M;`ht>Aua8?=*G3^E;grFhSbZT)zi zyh4!a$ScR&Hx0aP-RiiN?ecm-2ES*p$=f#5k++MtZy$Ku4pq;NY?t>6_FaOG-?=(A z*)H!F<XwY~->o_}*)H!MMy4|M2yQkE8;6a`s_nL@%BuuAZnm80R*QE_$L;bHooC(e z8{8}x?BJITn^k3Z`-HuNym_!w**k1I1-IaR9ctUZdG)A!@ZK@*c8rH!=NZ{M-08=S zZL8+3qjs5hGd`cZP5ZIS_BVwC!vW>>?WpdJ<qgrv?cikSZ2U)p_sJg*x{n6^xYvK8 z`D0PL%)9wz_*HnI+~4jORr#(!$IVYBy8GhY{;VpGXMP-y(cKa6U7p7eg6{jloeiV= zUcEcq5_I5i3~uG`7Vpy8ZU|$e@>NwkuAb<wkN2Jn+u3kYyYc*$$#6e9&s<P!zRuTz z-t#yo=)iwH*yXPj@6g%48pcNDZ&mI1b~`;k=gj|icXqsYj%U6Z553Oa?7?$-D$mj0 zj=9?D`2~Z!S%c@~1%jQ*i-+;9+2S#F-m`Xhiv`b7dD-Uqqi*TgJ*S(cjQ!Gn4|d<5 z&!uxWW6*=wd*^&%>~!YB+b-!lJR^H%(cp7Z*)uZ*H{d-t?v_dR{ZP-@Ju^?4yPclD zEYHF_bne{G8+-;j@<Q?Uu`Lqs>r%IN+rmLdM_wY{KAu@R-e;uVF`ikf9d+wD+mb;? zM_w-8zDnS2%U8#(Y+oTvzFQs}UA4R}>R#t&wPM%#yekG99pA_5@ox2F)A=4(3U2B6 z_3>-8ayvc0W*B#CG*dhEKKt0#i^sa{>^2#;P3qT)j?YMC+s47IOlAF6VaqZ)s@tM$ z6xD(E4r<@LdF`m53mv<k<>=gP7(55wEwyddyjIk6bnJeuMyFpt=sdGQ@DA`}r!w4a zUB7A6^D=KgD*x{Cqr=C_$D=x``{+deQ1ii2yG&)c{YcR79=u2Y!7w^1yE`b1oyxm} zJ%Z=4bI^H)*X<Z|GHf3Xo~Pq>r+BwI-mT1UkbfT$cssv-u)jV!`968<bd$1i)HAZ) zozL)wdMf)~@y6t_?H}(s>bd{jPIL#f8_&pY!5<WC2To+YjDv%l1@rF$UckQ_IRDOJ z{3htYFB3g0Q2DpL8TY@N=vL}29k=ICbov#7?!i9ic{~(Gw_<j;kF~Sm$)I~N_#E!t z@;dp2dMc0mRdVN6emvNhZ)fxM>^k_II@`)Yw`|al8~v)y%SG)n@8*eqEngEp|LEv5 z<%rz+Oiy)pXLF;IpRSkrY4QxF4La~Mgf9i}^bYyi?rwPfbM<yvuajpCJovYjw@&o@ z`pwVh&O2n@b29I<Y!Ijnce*dP=htmFHrXz(7v$}Oj)#8DvRXSm@0Qxvn8@44V~2J- z*6ZA@9y~|o-O4WQcCE_eZo7DR#?E`6UH)1a-A?hoCUv7fFN{wA-gY}j?c;fQ>{PaW zy<UD_@cdW8+2NFOYP+viWt<*#CpEj**>v*B_3~-K&g)MM#|6DkKDJ)w?MK&-d%aFR zp<X^FjC=j@;mG!O`KZ8yw_g%24Ht)RhHnR*d_ld;+o|oM@U1X9`NCiaZ@(#gH{4vl z(~jyMnaEef<H~lI)$80n8ayXcS^xL&w=z1a`*ZnaR0rNWsQpjPmq&d~I`(TPI(NSc zo&)ce+WyjfP1JK&RpoK_c)UC6IXd>Sy_60=n%HeJY%iA|w$oo7yo<`Vk$o2V&S3vz z(DBggz87u_x0YMl(WmO4tk?ZK&~g8ViS8HiZgsDQSDN+v<loVSy@Q**>UHiO4xXd( zU(5H~jqRRfxU=y-lU=?e=%{>q_*rnH_t|+Jd^X*^VLV4=yXSupypPKNDbKgl^A9xB z`-5lh3*JS?J8VA<o&#^+FFy<3j&~;Oz<)688{E2sP51UNzK(r#z6ZVC^Y0Fxq4GiH zJ?+N!u4El`OTE)RwzsvD-x6dxvajixvF#DBdq?oOsBHJ^Fgm^8E_AlHhS5>kyXe^W zjQ0#3`^bJ<(|cz3GP;|RZwxn-Yoj`<yS`l4Zfy4?!<~)4H`wI|g6_VcANTs7Hs2q$ z%e<Rc!z<zC^5=F`_fq*wbaI<M|1KlwZ2Szt`{bFs&)9z4>u2dUQ`9c=ZY~O!hD*wY z?Wpd@<*w-Dc0n?9HvZz^eezF&?)sn~_xkTN-w?IS{J7_@ExcX6F1Y7)H-)Q%UMF8u zFY|V4yD?l9Mkikx?BMN}*N=O>4p)S6W4}9mv%OuuER1{JPHjJ!$lq?JcKWU0er$Kd z-`-v)e?Rcx?bP<eaB~=)d`qx{w^Q4XCi3^1shxf|xF6e{@wc|u$+ra_ynUDayO#C{ zyO*7#x?QU>?4K_D;X%J!aJy4gc6UbpefDFgvS*Iy{-t^yz8rL(b#r6x!Rv2`r{hkx z%SU$C@i%w-T>SVfRJL6o+@2M5-b3Xx!gWFC2JUq?)q97m*U8_hKOpbX$v7}s2mY(+ zz8Bn#TiN?;Uu$pUZD+S1&+2vZSL)^O2KQ99dGF}tTZ8?U>ST5+-`3p?|HXV3o_-;? zlRwc+NA`2GkL{UwoqSeQes&`3W!RoB&$Xkve>I;O^&aXOyX~L#RNgr6wLKr)%JYWF zyML#L8@KldH*RrXJJ0CnDV`afXC5fLXJogYk$>7w&wn&M+~~ZIAN_mc$LFFl-W_~a z@UJZ|wA1sxUuvH+oHo&opPkP3n&6ho3kKWi!7X_Ixp4Plu*>>Ws=8Cl=-mD(jE%}u z<!jiyZ+vZ?P5-WV@Or$joqoFD_G9hs)3>u>hIV>>vEXi@;5jP$zDNE=-icrK-L?gS zTRoNijHvx*y|@27OzyJYy}OaA>@zJIe8yiV^E&)0S!dHP9)8o#rnBo{*V%qM(eocq zkMRyVWAJV&+x<*OCx0N=!N0Tq&$)9e^L8rF8Eo>YL7uI<j@MJ$925Bu>E+pjoyyCE znS)(Fw$YuK-aAjJ$`1$kZe(7!MBnAz-n(Sr!P_6q9dF0)lXc*K7wqyw&2(h%u#au+ zc<6OL6F>Ty;&tGC&ZX+zJd&)l!8S`hwYys<*xc&Q3$lLwAfFKI;QefDONa4ZDj(N< z+{u2%wpoL(eNwxz$$sAeez)9wsP~@ZsjulB@?UZ%A2gBwm~MOxD#Q2X>-t`Jo##Bi zUg3SudfhhV9qnxEhOto@Ha|<Zp4%$u>11}J+d8<FdEI0ET)r>76h=oc3_dsYeN5eF z++mtzo!$MT?G|oN-K-w$Zl^77N9S&lVt416HG=JfLGOmjFXwr9kM1Mw-K-Vpc&}`i zy;H{Pf}YB@w};WmYX&=&eJ**+;FgYk<jvE$r}mLO%Wo0f%DnE0elO$udL?;u^wRFs z&-*_??+*VBI=lYypqnr6)>C<<el6V;@o?*zaW{WD*mRy*Ie5qWgWkScb@Zc?-P_%I z=GD9hzLw7R;cid0A2)wZ*4f>yT6pi(>ozNIYiC;}jE%~$`99owZj+#=li7`K)8JO- zb${#U^7-)hpz}TXyx*>;ejRl7e>CgA)%;|1JVRyMC1Ly;Q`vS!@VtCM@Y{g@Oj6nA z=JMiQy1RqkJ8Zm8zPFyrJ|}-qa3jAr-}kt?HrYFLwz;F=eV+%%+jR0=^?pvgZpC(E zlRdY5(2ZN!CNCG2-RV{+ydG|rt*34_XlKKQ?KX<q-NBvC`}I8Zp5fmb>@u&rET7HK z+0VqU3$K%}tf#V{o$Z@p{2Ef(c6D$oUljbB-X8RJ{2=JS-x1CaZpSmS-!4w5$~eBA zo<A;}T$Oq1c5LI1i_~trxZc;}b+#Sz^VqHMJB957Z<l$U>{%W=1pBu2y6plTcd}jf zwdL2h<M$7AY_eVUGaZ@kS9qJeZ*VXBbs8PrtME2?@8B8PuiNP8o@Jk?JDr<rid|>t zKUH`)@+X7+u=;WH`F2!yNbn3D`Lpr%&jj9fRll~+F`m)MR|j5yXz-lO>tz1N>A>6h zyMq1BsBXMVw#$BdmEG!oSa`kslVF$Ke?Qz&9r;JecJQ7XcW=mN(8;{*jZyD?OI6mp zds93{=NZ|idvov{m2F?|yL9ro$vk+w-n+gL5B+$SAH5sjpL|a6tjz1anf=mmNx3kp zqq>XBMeWA+y=1tv@wWuKe0$K{8ua5{|NZ9MqIQ{g^JI7;JYF7YM|F>tN28P5Ka!!d z@&63oC;unt{uT7&UjN_be@E>y@8;Y2cQ9TRt}ItXbyo*|^w+er=`Sz5TlunJUm^dV zHJxWxi`U!r%XhQ$<2@_IyS<~&$Tl}CmeI+2@6&xhcb=oNebuU)k?r!z-DP*OewF(1 zt{b!4sN0d<@izsx^3C19)7}of?$!K#1%C~HDKABJ;Qv<s-tOi0?rm;#@+<ZF59WWX z@r+IX(c}*Vy<IQ!whsp#m8T0I3U2gc8y)p7chd*Y>8NazKhjL)gMv-w$9`~o-GB1+ zykopu*1H+I?KQ!M{{}m+pQ7k>hvn}H`)c?~`D|48>A;Wv>~?zotl-Yg=fY>IGTe>s zi}7wh+0G{GzfeBk?uyy+$B>Es%48k*%Yv_cXz(8J-c4<1PUJ(Hshxf*xF6dY@zCph zjmv|tN#$>aAB8)^_&he9?b~5wD&vR24e##a@PnWqH<z@t@%lU3$(IH?cG)g}GmK2X z-;T=X=bza=FMO}?*VOy>BG}~>^Uwae(a~R3^*nwV?BH(>F9e%A9j}vD4g7P#tzCY$ zUgqt3_s_SJ`TtgJSR#z>ncmWI>s{Wd`%iE?o{{x##%}v}vJJf5-#>hAIIH-3iFLC6 z8$l<ZUi>}LI;!*cP`f)bj5{jZ+?>%&NA~xd+x<Q4ybb3C9Uag4d*nxVe!O>&uPM8g zFAgJL9`8A7*Iyq-cSXDLjO<pvCX9S-yyvK0e_eIl$#(gsAcMa(jOV`-kMFkoe!b4~ zp1HY<&ht8(?zZ4LD%*Y>Mt6I=@to{d{$UvTNAaGccKv-}ba%EJ&&Y1&yTi!$#Cwj~ z^&|V|JboUi{oY_7&&&F;xwZW?*nS;!JoLK!raMLcv9T%gk5~T>e#rzmzp4LkmzSF8 zY;zXgCg%?i|9eJWx!vsT$Gv`~Zu#3!r?AVs8-KXTpH@zh|0#8f-`DHp{LlU44@Xlx z7;n#?V*RhP>D=n%{GT!SpO+sBc3!`FzUGrbuaj2^Ja{{`trngLqmx$+cJTJ4^XDpS zh1Z3(>vi%{fyWZTzD`xflI<3&*DW6Ccuuy<-YIVubo{2(vB`FM;~-Oc^<dL&R5qFD z+-(@#(UIMHX8qt^UL%ZKnb)mZ^$z{I!E-i#bmMk|?l#Y^7kKdY%ku9}zA9W9uC3R} zR|g)K2m801Z91C{R|K8ynxMNb==tlbW0URjjY0lS(DBgUP=8a@F7x(Xr_W!X3A<GH zt=H>zs_OTt-*KYX$#jQ$dFS9+UcYV7$=fy4k@t(Yk8PWHoxFXJ>B#%X+sAfz{K-MD z!xw|j#_Ns_I{Ap|*k!x?r7$x6a=Vk->yB!#<41SoM1Nwpv!i-<I+_1T{=Ds1;g{j% z{CN+rlfPdtKbFm|yQBS+$$I+_+S_%uCxZOL?(*ZoerG$I&h~7Oe-!NUQ^Ee@b~c^u znIPX4?DEsWes?>Y&h~te?+JGKxnRGwolR$ZG|0CEyZlJ7-`38iv+3m90}tLl+bsG0 zdYB{ZTd$L64?Ok@_PLsEI-5?OyI$Tu*m?c3`2)$Df?g*t6?pJ=YFj287)B>A9qi!k zpUfXn-Vxqe__x;|8nw&sYDeY6gWYrQF1%enB-lSzud}@;@YKe8*B8UssqE(S!JW+O z4huS&r*@tEiSqGww$B9{m3>Wjqm#c7?BG8eyu;n6gPzK^$?j9hZgsZL6us_*{6Y7` z@YV8_sP6cn=TEKLaOOmJT)bO4ZjYVlPKo#Yct&<BpAkkrCf;+@u0JY_?&Nmk8QHCT zdKmfWc+XM0{;V)M{n_nKtJj?r+>Uq2dfDB`RDLr5w~d|%4;OyHh5j!;6>pax>aKJ9 zhr-+B)pBQ-|JZKzboz0xf3DlJQM=5$d0~<KHI(q@@JhW-ekt&HG1#APw&`p-{3+;c zF9+SLLC^oSIyTuZ|2@e63_2eAzt#UEYL|KY5&3<^k>SgQ|6cj-ME|9Dx9;>e2c3L$ zGadP;c>CC{kJrh^2bqq1OuYTL_I8~c9gYn;+YLc?OVIOISH~vX<r{-cudBZ`YS%-5 zZMmkMo_A}zty#z45p449&2;4N$J=kp?^}7>mGP6evfaCGj>_P#sHc|)cebmV>14jP z+jpXF?YgUjPCllYj(lvq{iwj(j;?xkWV?J#upjyV(DfEjR$Sc{F48o?wXxt9AP}5} z=Ip(3cMBREf(LhZ4+Mg{yK8q9-Z;S}A;B#W9D?)K$G_{n>N{TU7~fcH&bfA-I=iaQ zX`u680grx+tzL#ENAD2OqXj(rQMP&+njF1TK#vgc=mCG1?MF%_N7Iw%lb>~332iKe zq~f&}@aYTMN(O~}UViDBoog$ad1lI5=*!r?g;a8MIqRYEn_G{pv89pqsCYkEnn=Z? z;x)B2vmO<%l%=#(ypjUF=a;aawiOLZzytb##aNGuH^9<gDjpSYkY%9tsCYvxgQeol z6zDyFmi1=XiiTeWyy>>0VVd=Z*@}jt0^V?2(a_6!`1IW^v#pQD?<q7F@bS<+Y)?hc zv&@x>$F--TS>t*11q6=A3_Tv2zM!pS+;84JN0wLq_k_L^atrkNd^(TMBP$@_G5f96 z`K7W3AFqhOTtR^hU05K;BSQmOA=^{Q7s}7A3xxT?GTY;!7YX#RQXt18TV*x=3aeL3 zB}Xq8n8#ywvGAMxe2h<yUL%mBPfJF=#QNSm{&8Wc_+<F#69V&VtxtZ``sAl<hL1ib zkmKW>lzPs3WM>32eDqm?oJxl8t-&iSpVftgf<kfI<DrWP^biop@yLD>lz>Nu?kbR@ zwLp$X7AhD4j|^Q@AV-%F$cqX1<Rt|>GIW?gjxHsTqw!10XC@lIqSd9vBS%*d$h(V& z&paMkRRP^iAV*gc$c^>L@W`qNXf2SVD+}Z$tVdQ`z$ZtS6v)waq>`iY%L=swJTi0{ zfgD{^AjcysFH{on$k62ka&%>Z9FMG`)%X>xrjmP_`DSu%O@+onE7A0L=q9#Dx0H+= zkF1f<+<Ii_9|UrA3xOPutgX=AdSvJy1#)ydfgF#lweX|$$k1)@1aw<w1w67ALL2Lm zp<Ch!=+?{%cx25jcx32S0y&x<uaD4I7%23zJs!HBKo7kIay+sDLJt9t4BcNKM|T&< z@yG^Sjo;1cK~l-lJq70Rm>r6i^Ta1d4-v?}%u7a&M>b6OGA~|V0X<wGNB0uQ@yJF9 zcw~J9^hkjm-CH0ZF5r{*x4t(&%;xBR0{KwukqxjO8G497jvgqG4;Jvq1_^j%o+d|A z$$ykT=d=@M32khThn_9aLtB9yk8F<6QNSZZ&lSkg9R%|B0=_qokB9DLdo(@sndHwZ z8HMx$eP*A|;Pc3`3V6(>vpS1Z*5Kpi5SYs*kfFa3$nnU~K$hM1RPwU&cjje;(w1^k z@xGV86UV0q{Qb7CFBv&{pY=|P#`os&@v_Qya~2`9Ku^tP`&?4V@bR+SKBrVNe7tXL zpF=7cJ{~%SyoV4Wxj;`%Y5TNN$?)+~+5T&(WcYZgZJ$Oe89pBRlkidaAZ*C+za9_p z)`~~JPAWNiz4cZ}#rNj%*I2z;Dmj{-naxr+2^$6amKpy)jo(akbL)|{5b(&FOKoC% ze7vSof3Q6nJsz1GQ~vxbL|FDn^*ri60gwEw)qAC~27OK-$7A+@fJb)P>its5(Psp5 zJZ29Gcx0!nJ}8wO{hL6J$LwJNkL-liky6RgCk1jmW{(PZWXG&NB9$C{Tp-6|77b*0 zPlU(9KbEJ~3zC0$!y|iUJu-Am$;i>q1@aiyBYR;zGIVr-9Q{%tk7hlxSJop#f3`XL zwLt#KdSw4vj|}}$AV<Fu$Ug{pWN!sLGW2_a9Q{rpr{a-;=k1mMUCTX!YuP6i?}F82 z`>jWYJ};1?4+!Mv1U#~X0v;LqtU!)FB#@sG@W>(sJTmlYfgF8UApcFkBReACk)cls z<mjUU`AGqf?3jQ@hCU&XqmK*ZR6H{9yl2us6`ok0OT`P8KRe-(y|5k`I+kSQ=$8U{ zkoCx3S&s}IQy@pb7RX~*kL+LTk)fjt<mfj7c{J;hy|o@0`m@c^?*#Hs)+2jwJu>u1 zfgJroAgAJyf#)TSEB`hiB(@}ziuaAxWXY{ZhR!aKqeBGpYyuux3IUG{omC)5rxeJu z2zX?v1UxcyW`P`?S|HCP;E|;f@W{{^1#<M)0(k}jk1VZ#M}|%>kfYNH<WxK|@VwH} zml8@^%1FhlZ#7w2>ye?q7s%1&1oC<U9$9$-j|^Q`AV*ga$m<ArWEBNGGIVW$99>Bu zuO;A-RTl8b&@}~ebQOWThJZ&_Rlp-dR~N|9)dX@X9vOIE59zxL-7Gz&;*GVMte5r3 z&|?I0bZ>!tw17v}N5CUPj}pkyeFgH70v=gE0gntlLLf)?7s!VTcw_?vJTmk!fgC+h zARj8=kqr{?$k0Osa`a$<oQg*Vp7&IKG2@Bw*z!!O=TTn>c;rFy3moX@0&CE*1adsG zR{|bc3<3R8AV<d($nnVj74XRT1rhXXfgBxOAjcznE8vlRviglwa`b0`9FN)e)+761 z^*gEL=#K(x@R&sd8D4xjRy-lDC4p4Wqb3sY$TM1<P%3NCnFMk?W|IhbWa+I=ER`Ic zK_JItHkp7&me%T|QpwTj1adrPLj*jsG*%~<N{;?oAje}irGQ74%IXwS$<e6=ay(|y zK!#UCs4i5q)U;k}tI29vj||;PAV=30$Xg0{WOW2QGIR@p99>r+Z!X}G)f4c@(9HyL z^!EaJQvr{xzJN!D{y`u|HxS612zX=-1w1lzV}TsqNFb-;k%8xRl)i(|-qJ}b-cYN_ zI$MtnJwzZ!cM-@33wUHd33z1aK>|6tt3W<bz$5D>;E|yR2;}JQ0(pM{kF1A)M~3bv zkfVDF<b4G^vR(on8M==^j_xgxQ}M{a^E%2em30u>TRKU_8)`LKXX}xnhX~~8E&};r z0gvn_0gntlNFYad703q)cx2rKJTmkEfgIgkAnz~Wk@XPp$k6=+a&%9Dysv;q)=R)6 zL-!HL(Y*z7Djpel-aP5&3Ue&;rFtH9p@2ue$?64CS%cmzkmE7CSimFOVD%!Y<min8 zIUci11w68KRxgoCj$SX2<1xEjz$05@^)jjC=(Pel9<wV2JhD|*uaHWPUM-O0F^dK= zyb$>_YH}f&C52SHtX7kyv>q8ci$IP}C6H$p@W@gNcx32I0y#R3K%P;+Bl}vwBSU8p z$kAy9^7H~8Svmoa%+us(DtU1sOekgvSg(@RWXgJE=!yb4S_|YA1Uxb$;E|!r3*_h$ z0(m(BkF2DCM}{sdkfTcp<YfdrveE(`nWxFoRPw4q6```Fn)Mo6O;+7{Wavf$Il6{G z-cZ0Jt0~}-p&JO~=vo4KeF2ZGwtz>5{$3zQ*Ad9;33z061w1lOlcTBRO@$wXCYEN_ z>ufbybL)|zI|=0I76N%k0gtSufJcVzAdsV53FPesJhIjT9vQlwK#p!BkpC#)k+l`@ z$UIGsrjmCReiFJ^x>;|C)nwhRM}{6OkfVDD<bwn}vYrAS8G4{Vj_xIp4-oLkdJA}D z=>7sZx{pBKPrxJVE8vlNnjB3fKPns%4qJ}-JhBr49{DA!k4t3@`m#Wd$LuKqkL-fg zC#903FAC&%%$^qT$j({)n^bc2d4U{{*|P#3*%_;;<enyfB0LuUu{`y8WX}aW@{d+O zlgb+OCxIM~*_Q$y*?X&BNF_&q5XkYEeJ$XTy|wz4RC4q?fgF$7Hv%5nzgAPpJxv}x zqx{S-e3l+!NFQCmi!KBScw~vJjwzKKome2pV>Vd8BTHa)EUDz^gaSDpvtJ2#Wbv$y zEtMP{Um(Y0Hm-n27RPETxu?mK2}y+{mgGK<EQNqao=HH52&~B@WERNr$WjS-nS=}i zI;B94&M1)Mk);vv$kJJzS}Hj@y+Dq~Y+3=2>}#v3<enzaCS(<|ShD*(vK#^)c|ohc zk;)o$A%Pr^*<1o1S$?Z?N+m}Z5XkYE%`M=O<+b`-spRN<0y!SD-wAkRd90?Adz$>$ zujF?)gsH*|+vA~s5$LJtDOS&x$}H8($)*X+df6=LVW#yQspQ@qnq&NIJ?|K3GW28t z4fGQQ){t+rdXiLfD)~5p9B-?|%h9YOXKuW}Ix2ds)!U^qOZ9TH2?DdQLm;Q3$#&Z6 z&7#TC5dwOh;H}$WJu=uL;H?)}$2|BwGLA9O`mDiY1`j>P_Ph?WYb@S-8entgV6=b- z^rM9S0>|@a(Yy{>KkJjxlTpc53(Vp5wRkz2^C9P)=<!(7N8lJhk546AWpz)ftfP84 zSr36(peLu2trXS@-a7Vx9uK%5@R;i@u#SpeA@mZw<9V6qQ8@;4g9X;%QPDuQTwsoD zkbqA`lMNL-kBSDeWdgGs1@C;RXtLn~vsCm_tA|Ks9o5UpMheVQ(MyD3g6C1utRovC zFbni#RI)_^b9kFAUQV`HU>4|^p^`1IEVQ1Np@Dp!fWJxLb-ee32KE4tx%mR?sOULX zhfC!cR4*r+D=-W6<W#bmmRZ*G*6$V#-Yh-mLC#v{@i;Gh`dzkq8JZkDTktfMdlBf# zmdBO*N7!yFdWqHBq@t<h2d!Qvl^Lp+(=W9?^IHVZqoRTAfWWb+-t1QCSr3~9j!#9C z(Qgv)sT*xiwpZ|SDw>=**J`S#_ef99TFz;oz`0P-tS8$q;8D@uu})f#$}GntJ1*c+ zJ$*uYa&OIV(&I66#qzt)W9|<NIdiPRBV!i-p5?yvsCa)14{YxppS7MxW#&)oc^MiX z&Fi7zs(?>LlhOYr;8U;Jp6rz1<y16~v5(%K;<1kPrv)_Cui1ONGXk^Tb@Dta*A2Lz zm^)<qol;?k^{D7o0<+AWwVbma*=m7VDte_r&g^x|4eL?y9tt;Y@6Dm{(dPv;70qj- zZwbs$y__skV3vyJe9#vJW~p9|zAbPZs+ZH>u|D;#?OA(K@Nz1eoViO@Q$2lIdUEDi ze^}t$sAzA^5$jQzWgXd30gvkGW73m*$J!<R4uQ(CJ<WBX-z_lfy#|_Wjo{@}G?1+n zm<t!Y*QcVHSu1!s6%AypWiCSCyg6Sg8XN(S`E`OfOGN`2$6=N=>jiwOUo(TZL131O z#$TOKjw7tFtdWZMi`8T>)q3R2F0;@x`?Iay9GV&Q6ah^|&lAY-mRdbmDmj&WhTyGP zB0VsRx7cdty)~W}E*^7K*5GrjX#&TlqJI?@3FP=*h6k)CV{W>@I(#Y`$YxpScMJFn z1@9PC^n6>r9L;N>X9{SJMUO{@x4>5X*%rUYnmHD7<~CXFWgA43p*IWUoGU%vMuB5` z$7ddobHJxxZ>yJ~$<gZsG^`Tv>G4-u@I8-v2%md^ie?Qn%PsWYTITSXp>lnJp6u5o z|9daIC*B+H3lBX_Dm}~;$m#K?TMs?MYO1Ga*?gU?XkccZ#aqV=*<9;W(NhIphu4E& z1kal<J;$LkgFo9==3tJ`TOd8NRBzT>zuo#&@3{1w2gh6}u+E!9PZ7v?4KzI-`e)mt z7YXE4*3(ZC$e6>Y$3suHJr%vm>cvvMV^Gm#%LHbr=#`e$)>|T#V>9E;;jtc{9$3#B z`lSLnm2;*iTP}Dx6^*~v_UIJ?>!_@y$7g1Zh0L49V~)xU_X7QT0Uu3|$MwKN(^JU{ zrIX*+7s}X*&Tn;Tsc0&BEvpMkWrphI^aZTXd`ZFcsAwRoDR3;RH(N@2)<X$_<5SUO z^hUs^YTJ`l6TF;?CTFgS)l^Scm7binoKtmybD^SHPgX;~qoTcIHL@O+S&m26K)|DV zx}o&s-kK)T<1y3L@}tjVuAPOPIo9BjF^k{R(#v{Oygov2+k3}nt>;mh>0muCL*t`) zJv6iz@Tq7r`i=rVwUh118Vg=dMFSc8=<O*U>sbGTfTsF2dym&tVAi`%o=4@n0rwMg zwQXNcDwMSz6&)%t%Um-{bL){66_}->iwNY*cD8h}9u=>z@RRMmIW#`Hg@C4_d2Mu8 zff=folhqNJrJ^|>bW4F*s+Xg?2^@#&<@DXHPwioQ*0vJ7oQfuAuC>)vPq&etoH^Fl z6*xC4+FMi4dQ@gvNA|sdNA+}l>B+rgm6yJ(K;_t;<~q<<5SaB|15H*;@Ny~|$chNe zRTR9}r=pn&6TF;?1~S$%S4rT!IbSLoDhqhb7Z<!)DjLW*4zsKY2>4XLW(H3Q%u><# zLu1I_5eaRC;kL&^w-xBA=+;&bk;*LkM}eG*ZZCLiT1pRIPS09$=2{4>1A6l2wkJp9 z<DuKx9!=j>7%Xs1W{2Az4@Ovz`BnlmKu^y4p9C+bqFF~i+CtA7^caDBl<o0Y(?wtg z=)JWgrDv9kN7hO3Jak8a9O%jMIc^6FzPFa%^O@m&pgRk!MbqOIlHXk@C={^JSF?R# zspLg$MUzz*n5Uv^3S@ZsEMAVEU*H&I^mu6c?=1A>=um;2<5v~%YuX;KitX{pn88EW zusxc-uGM*^G7I#)4p|+6Sv)G5*C!8H=*iJqATMTnJk}_I8KC#p7L}e^Djr#w;Cblc z0y)r=<8$0v7JP3lz2`H-`#{$gSc|5|J1jr<M+%1odg>A3g6+wUT8|9>yg-jnJtmy9 zJ=t;Vk>Q^e=<%s1gfq4$J83;K{L=zGKJ}FFo9)Ty@yPbb&xo$zSm^iK{-jiL^gipI zkc#ik<L|fnxKwiV0qY%;ito+iAGG?YRC4qo>m8Ab@6F>!T76h5IhvlC?~=*C+X>%V za!bXd;^h>`@$y-`9GzDnXD*k(I-n<~l6@mEi&wzn<>>qZIdeG#)&V^^l`NZ3P+%S( zon0WOqO%GC!COZbW<9DmOU|4USX*2mM;8*vsc14!^ZIDkkfW(zS?I~og#~iXDYk$Q z^yE~sECRE5aV(jA9&^DKa^_frN5(9^H$#RuL6{^=w2ZgjI9t(^ZN?m$Sv>U5w#OeU zu#Su#Z;XJ4o+6O322GELo@#si(E{tp=<!Agc<5gQGS<K}0T1Y>3(PSySD0rj8kqCE zInpyb+j?Xptw#oAo=4?eyg9NF)*}P59|g{X>dm&3o>@G4W`_xQ=(d8lj<v(B*G4Ki z88GL0RE|N#XAO8>tRT4;gxHo~sd#B^MaL1ynS;0j9@*CdvuSKa#}mkzgZKg-S!#jV zRJNiM2;|H`LIIB~rNC?oThWOGa^@hhfJYW0Fq_;~bP|D_IY=ttQJG6-@jTYxk);z@ zOGZy6qo*=U&-pNi<~;C#_eDmJ&wHY0f5_<Z*c*EGnT#HfJ*KCUU6g-&yCPh+T#}0S zkFDt61#;%#4*`$tk-+RjThUhqa^~Pq0gvo&f!PPPqW==enS*Nr9@%|?*?YF4uM6bN z!3_bA?5@D<9b3^i1#;%#mVifP?zYAASc6A~_gG*(9z7m2^mt_SoD=6jPmZSNz42b? z$<g%e5qm;Uj;3d?*;{&YG(BGIIPwe#aV%d+#Y=B1I-Wqz9K;v!$kGYSrnMEFKp<xh z5(;=^Ukl8pu@#+2AZHE|3wUIy1!hy(icTVsGY3fpJhGGmvngyvClkn-gX97pmAMd$ z=dlKl3@?MgdOUhOX6W(A=s73Ofu0;q&wJy&(37L-*(3IZo*YfjUbDCK<Y;=l9P)1` z-wL@bIi=zmThX}%a^@h9fJdeUW|ghz?*ww@Ag_Q&77&;%ZYw&UK+YWG7x2i!1ZIob ziY_3KGY16)JhGw!v!S-43kl@RL16)p%3KkP=dlKl46lU1dOUhOX6W(A=s73Ofu0;q z&wJy&(37L-*(3IZo*YfjUbDCK<Y;=l20~+@k)@&aezFza#AeLF57r~=A~4(8R&-N= zHOxUX0gtScz-&ib(ai;N=AeauN7g}Lw!N+BmI66*&`Q7~YbP-Kqpj%H0y%TgM!=&o z*Vf{BtidD0>ngAwj~<U1dOR|E&WUrNCr8us-gqzc<Y;>Kh&`bvN7HjH*jsvXG(Fxp zVWKd>GTwTNY(-D98FMh%dSnX)W*69s{#jrRb1+4~BbzTUJI_}1RDqm1_(i}Yn=3Fo z$5!+-ft)#*F5r>P7MPu7EBaS~oH>{w;8B^IY4JSP;E~}i7Fdr*kH-u>9vMC7#5vHD zqv?5Xycc?MG(CI7p3sw{>A4o{Ej>A!{)?Ab{#`|wYndl?v9Q!u^df<rIand!k>Ss= z6^|Z&zQ8f4X#8b@=Pi_;dGA<gX3)z8^a6qP_@1W6Bjb2fGS-0S4U@k+7%7af43~;G z%U1L#ft)!QE#Q&O6quc1D|(DT&K!&t@W_4@n4NAbdYnMc9E=z6$fgO*{$eY7f<Vq3 zOce0QrV7kXu@yZ@AZHFH3wTuKeztfXYw*Zehd<j^e0nN#^qdQG^mv>HJ@1K(9*_4! z&)$&H<FPOF>@gWV9{WpAC8NI>Q~vHoIB&Tm6_1Mdw?K|}#d6ttWDf;qsp$IxIkSIQ zezzXk1A$p8`mR9E?4Opa)+4(oFiS<>7RZ^sX8Fr{WOoE+spy*mIkPt`*R6L;Dmfa+ zJ&(#U@L2muz(doMq3OvvAA0Y#>G619^xk`*$76r!y}h8vW1s20J*D@q2Ys)k^82|$ ze@joPcvQTB0y$nk%Mk04^%j_=q6Z1y`X17I89nRC=$Y#yuny?)sbqtNz5;7JA5HIN z%yKTwkO3LqHn|tK3R^7OrQ%WXjtb;>J1sk`M|MnLmWn<skTbj6vdem8M+9c6=tBZI zvk{hX>ybqY%u>+@1af9wi(@^qg95Wu^ge-{*}axM*4r<Y91Y~2N97o-J1%%@>B)ee z8P0{CS?{&cyeBF-K0WV+z43B1J$u3))03m=*;}9|Um^c3!E#}lWu;U+D&8f59B;K{ zmG#Ij3(Qi{7X)%<*IL$CkL;qrEERoDAZK>HWu5iN&I`;^(Psp5W;a?kSdZ+iz$_L0 zn?TO&X3Hk)k)0NprJ_#?<jiihY_T5MDS=rk`nW*O>~_mG>ye!hn5CkR3gpc0wCu1R z*)f4xD*CWM&g^c>F6)sU5tyZ-4+-SVMp(kFM;0kCOGO_L$eDF5j`he63d~Z``vh`k z_geN?Z@<)i0vgCYkIFHwSfBOu_{`Chqv^>xCwlMo>G61P^xpfR$77G^z5SraW3TDG zeWl0an$dgLhaQh>Pw!o4dc2L+_wE;by!F;UFO>`*Z>{YwN+rX`TW$NxQpxb~R@i=} zR5E-#^rN`)-_!|@E&oWxqvAai$nj#t`yVl-dLDDJL_?6^%~8?8He(K*NZ>f=rvf>z zL5~+(G#(nrUfBM*RB|*u`B$Rx&_MRe_AjN9qv^@xh{i($*}t}bEtMQiPaan^9vaBr z+Ww7Hax^`8JkfY)AbW57cT&mG^yKkH<Dr4<qwPOPB}dbfClHN?2C~n#|0I<hO;4Us zG#(nrqFWtJDmj{-oa=*!1~RTUJ=cvKO^-K6m@mw;%(WgBZ=pcW+$PIrpU2!*%ND8L z92LFIX3U{of#aYT2;{s5J>GT!4-I6CZNEq=Ihvk)hk%C$vZc0PB9$CXPrg&YLj&1z z+b@$!j;1HyCE%ffY^Cj2NF_(plkXPr&_K4@_N%0lqv^@R1w1s6t+o9cspM#S@(2MB z4P@(WzfLMSnx5Pd@X$cE(e@jplB4O#xjuMkAme(|bKS_%^mvyO%J;i)(Q-v9-YZ+t zzYFBd!5;!1*-L@h7q+6W3gpbep8_7)bAj1swxa(M$eDv{0v_2@f!QavqOS|&%)t!- zkL<C)>_4`mZwlnh!7Txg?2*9iLtD|e1#;%#j(|t@x4`TJThVs~a^~QkfJbHSzQyxc zgGUyW=znX;Vo6UW^ECNa0-m=H%`C4;9^Jw@;{}VxX9i*mcvLj&$?;-ZIEMFHaiwP# zk35Ee$GSKI=Rx&r_69GWz$`kxRL`TLfsDPUPbjbkoj|JRQPDugwWUuaum+u2s^?MB zK*qg8pHyHCI*C-zqoRR~dy_tyz#4RNsh&qg0~z-|eTcvs^c$Z?h6Xa8ANscfYtXNK z9vK?Qcz)>L39Lc?D|j9i4P-n&^zQ}Mpg#znM@0h}&ky}4fi>ulg6C1uK*sY!|5;!S zI-0x>&!eJ&jC+xudxte>?kCTqqE97}pXY_smfxh}QStr}$nnlu&RUP`k-#h!{kK5Q z?0L%t>ybSan5Cj02;|IOvRt$t*?oaoD*CQK&g^B&73-1R6PTr<?+E0~{$csudStf+ zW~u0#0y(o+Eq_{%?3TbR6@5b>XZD)qFY8^GN{$9{&!ch-Jl1{?@X#NvrlOf6i<b0% z85QlFM|9D6RA#-o&(ePqs2s~XuII(@tz!-Py<NlkpkoRg7yVWsr=qV~*ekquf|tLs zo|mD?(Oe7kzXBfpD_gw`O^)VTqhAYn^e=7oGBi1wdkOtQz@vX+tCyk4(cG)(X96Dm zV_UrpO^)VSKtC7o=%3o^WoUBrZvr}j>?0n1eCerPh9*bze4yi5k3Nn-^)fWM_bj2~ zT95uKfy%SvX>#vbB9ATL(Z{ltXUEgz-m^p=Ea1@x*~+uyX>#vbBIn-0qvsx?a?g62 zyk9!`dp2Q!rN2}>D&Am$9Pek#6rac3FP5oNy*Vm+n$4I)&l5NfdXPZQYtZ9O7x2(P zHq`b*q>`iQ$$u5_&_Fia_QRx-qv^?K2zY298)^FyQpwTu<TC|4G?0z9{V1vAXnOKl z0v;O3#@c?2RB|*u`D_6X4P@hOKTaw+nx1@)fQJUMiMF30l^jh^K3Bj)1KDKTPm)TG zrYGn6;Guzx>rKyfBS+KYjZZICm}r?G6_1Mdvp|lw$g<eyF}KvRM5;GOMK7}%bLjN~ z$3agP$axKVyyXHO8px*Feu`9bG(GtW0S^si(`^5XRB|*u`APu~4P?LCe!5h0G(Gt$ z0S^siGi^UZDmj{-e6@gw2C~_<pCy$XO;5f?z(WJsT-(o)N{*%{Un}6Dfo#6*=Sd|; z)03|g@X$cE(Dn<YlB4O#xjuMkAme(|bKS_%^mzQ=wT$xlBsH1s1ED{vQEpFnd$L2O zOusQI|G2hpy}A3%ld3z_qg@T$MSG5!=&i=6&iQ({RX!gx6Hk2%3|`#N-Bk6UnO-oh z%9wG8TPw$L(>aFPQZ8(Wn>p=qb9YFwEwvu@bAxvsFy-PFR(HQ1<_=4D+-#j1qQ1&G z$j!U&fa$lR_?Ca$4RWL1-EX#6&A;W)n@;Y@+k4F5VTo1k%N^Xur}vtP)Ap)w?i6zS zW;kPRANx&hNpj1{7VDzf{(iQ)*{6uRw)^kqRlzB0Vzzd!nS9O+_$q@MpR<-*H1Ab& zXLQCb&j!?XyHvhv{thX&rGBY??)vBF&2Nn}svhP0xwBrJH^E!ut1OG^x-s&sGr@_z zQ6m=QbH`LzW~%3#uC`D9)*V@TnaLb7RDB)2wj1x8btYA>EL*0gtM6tnw9dRNA8*U5 zC;8pW<(HXDDQc*`-?wld%->*699ygwj_%_A`}a1pxNuVS*PNd2?fKhHP}_HbZ8JN& zo$7BgPY0$}by{|Jn?BxSCgm=&W#X!y?!9PxOoE%CTYhZZ$9-~ayP5Q3=$7$wd%M-s zZ#Lr!Rnsrygt~e9?==rr)zQbcW_8~t-D~D7XsnA4Na;4*amf7pcRfAgY7V!_%1Co+ zdn+B*_k(jg{Fu2M-c&by6wj^F`Gk42qP_lM|8}Qvwv(p&o3^^a?LAK25x<%37b@zB zNdoTaW{1tgYC-zPzni!nHykxJ<HgX!Q+IavMcZ#uE-9%$>Pqg#4|~nL<+b$4<0;)E z*-x74$7Ac}p@rOXfB$BR-fF0~F23ZP37j^g8YkEFo;-Ex);w>9@2aFn-znfO%D2-j zNncAZnU>LQ-EF4{ZSk+FwWN(Zs^>1#C+W|s)UD2Lw~zbG*|ZJx(dBX6e=2S?4YD@Y z9pArkc4XUZ<_&41i?5pCjQwY=IeWCVF5Y95^H1vy=H9thda#)o-Xixp^Z9;DT_O6T z@L!g1Ftz_|t>cbvs6xkXGR0Q5)J0#XQCSmiF~2rzrB4)CtggM=X;j=+`o}jtRJWzO zOvS}*_1X$kRrr~GChsq8_51sE)tzkn%$#!(YDukUPW#apO#f*YH_yNP$%%L7f=O35 z{+97G3%b|dUop9Fk5}Q<3%MU|U5Ro&{&UXyPi?(0%~EIguoWik*M|D(?C62e)hnW$ zXXdpP^`$+3sNpr&nJUkYsGTL6xb>bLGetk1S3f)}<Tgup#>D&fy87z$J14aB1=I7I z)<35y=gv#K+tfS!URCN`+s%<+hpB&co0?IpvAd}KRx{_9x$1|O<=uL()|$z0a_Rd` zbGwTNu8neC{Cn=dH-bXD=)Q?3MYL#r%G~dnS^v{FO~mjY&zSQA6YH1xt~d)aoHuoP z71kww`br0N+Yx1N^ViO;@Amqv_BPrZWp67)cGB@C7gd`h4x1larPp5#nXSfcJZk)} z^-r8Gx^rlFM1r&@OyZ2Ulpgj>z0MkG)*Sh$&gM>|Czjr0F3$W})$E*5UwwJN9DRC9 zb>5O$e}Bp~iR#DHCEsS(jb`pJcjk;$)ia0b^1XMOEy17F?N8t7{{OBs6UUBMy}Ac< z?Acq)=@RQy!Vc-&{`r@h-U(9ba_K)hS!XXc#S$z1VbBC8!@Pwi!#`DYiok+E+{+8i zi)TjXUwlrr%DlwX9G6;GN}ftrD!anGDV0^FxutcPd|RU&Kj+D@>aXzJI(NjTDCdyk z?H#osEW7^Y$l55!iQYD$9=IZzUK3||l-Kp2&+@hTbj({los&}*n1T6~epP%y;6vns zDChQYLf$XuSue?AQ}}LfHG5iSw_uT_CR45$TLz8G;_fTD)R-L)Ht!sr(B0N?i5WC4 zm&&&?ft&BgB~kXooLjCIp8U$y4VFaNpM728>2EXr<rF);D9UHD|Fhcv?D(IN4<Al# zPJH#b6H)(SlxNC6@9+J`^sn`QkNCe|{NGdm^?l_3{wh?gn7UhYkh|yqd`Il65vHz> ztm_s(bT!KNi~qaEKjZ)2^naiFKi~Y%wg3Ch|2^pcUhsck_^+M+n)<)L{NGLfd)xmx z;QwCpf8Y5(H~gO`{?BlK@BeP{e@FN~m;B#N{_h(9ca#4+#sB%^|4#9L=J>x~{P%|c zv(f+aga7l>f4%(I-TyO#|N8p((7#u^{#aZfd{Qo*>F>?P|BN@x*iQ|<R7e-;zTAwO zw7o#Jv|;-6kmbhzy!)SV|MTmAu4^^Vt#=Gh>(n+gOrKXukJ;=5rj(gs{Ll5-a^L9i zbAPH84QH4PN1m!paWd;EO=m=Tmi^CozmVuf%ZD9x&Q+OVP9@Ky4wXLYB&{~X_@D7g zzpqqH>mPDnitm5M>kNpi4-H!2lq^5P#7Wyn4a-;P%WKUo8NKL_n?t|!{-1^XKlAv1 zo+<rwZ-H9XO6kfmw;BH)`aeG(<@#2&yd2PpX6%ge86FaOSPfc~Uw3b_C(37je>as{ zShASDd2f&Lul0W~_}9ki(?Ct=pIBcT6B*@u#P65C|675n8LH{fecMdI#}^B{SY2Cx ze`2S(el@OYJhrO7vUR6<RV0b}IHZg|{dlWUBQF=|`lybcbzzS=TlQt(aFOad%Ud_f z_d=z?>C~IJ6?L`^JENTE`+wuAel08Mc_a52|9kQG{+Z_U&K3A0eoeh}!d~-f^3DQH zHx<`Ai|;f3bM~K`e{cQ!@1OC%FaLS^*ZR-F{~rD4<KGAWxt-`Uy1<Di$@S%(k>)^f zbXDbch}+=Q0F&|HF?IJw9QW(I1I^kZD^;v!k<O(0<IU0`xmE92$DJJI#~bdk4jV#s z+_vLQqcnZg$UKF<^q+foR|i9~>lvR$nxlPI7Fhi8JDsHSD3j;#QxzVZS${3_X<p~h z5e@%R>pG4%qa#15<cU-3(+NhK2Mt@Q^#xPwpkaf|l_b*(WL=v<KM5UReoP*{=r`4l zJL7JRGdo^C-`wj$h`aSfKl5@zH2wO=#QNc(VW!vCqWb!pU8+pY5hhp9fIgKfGEno! z@#gjBvig4Mp@B}5N0@?b^6DkoQaP`ijyK)bm(hu{rEpqh9cen0kE2f=obOC+GTsb+ z@U>2Jda0A`)F|^us|=eT4OkH|q+We9FmJm2N8YzqBf}b*nFl%sPV8!?zJJ%yH0>J_ z&|Nk~B#->wICHzJr)d-DCXafUTlsnw7?mrYo|5q=)1*%B0{ip-q2@GfZt6#bC^Pj> zwYXGE^CWC$;L7ct&L1fnnS^~8ZVqd|%4u?<L6q0^A3s@&_-bk26mI#wtxW6MPd8`U zo6Id6x0Q*z<BZBRC6T*mcWX1HX8~O`_95rV*%qclk9>Mr;{#6VR=rK;pR4JGjVCyL zof;<En%eqt(J*J!^$sT2$S}S9-X&-8;i~4&p5nU4m{ZP*d<9IdeC2fTqyf&&bNNle z3QcvtzBL1d=lo>)Zhx*SypE;UT<mE&)vKyE&R(X1_I5H=!t>}g4^OLJz1o_(VUN|7 zCQsFO2U?j!2fotbS6{2<(;Ay8=bx*}m164V_p6)dWiqP!l~$;j{mPs3eewp*9seV6 zb$3}aX>KyTBf%%<`iv^(^pVv1;-06@<ns;9jeE)U=vE&cow0xk>vc?Jycx}n+*!qB zD0)(Tvn-nH7A#<n)-0mNrn&2!JYCroi&;gL`u3r7utx!NBl+4uu4;3f$ZQo&nNG6; zyK60Umb58ghMh8j?VoBmvt{P?zB+;Mqp_XE{mPm817oXEYp1FAO^TSCSEmI2$u%sn zq;)})Kkr5LxZhhfHfd?o?9?#TJ?uBtrEqaGdFe`Z=yWu9-lIlQj^jUmleGEt)gE;N zUE?J*^ovrR3LiWq$czcgtP8D9ADA&9$Sk^;RzK}GKM*oDuIc+RpNf_!Q}L^5-s|VT zj8YL35(jQ{4l*UO-B)F|zY5Ij5@cou-&PYwOb^7`|4wgO5T;MoeHD=~*K57va;Uy$ z*ES7GsvF%1R%u2gHoDzCm9s{WYSrQ^6BPHl`W&1_MLtMqhEy%44^%GhxG`cIQ%&jZ zSI0Qp=e^M3D{iQ)mjY_e^AOWHS8SbUa!xh#X^3fZE4sQF%{V*1if!gc7E`&ZWQ+Jk z&Mo7QdDUfm4ns=kR`ujK)Azm5C-00=9XkCSI5j-389Zi@Iyxz_n&%`k1$t~#*;nLJ zuj+)D;>!~2WpiITE5>Ir&VVHPa_Of||JT9h-LRax=W*BR|1#L5I$T)SZF$(qGa`$5 zTi{gSWU3`ju3cG7=m(`@WpSKe<HR;yJ1kY1lRtHuT@N-((>GDy#Qw*LB{LWPIib34 zd+Q`!p2egc{y+`7_1-DhC$=f^F^yg}BAOe!%^Mx(ZBgxPzUT}+^HlfG^g=aC8{1X$ z-|0U4HmPTyqq}Fmf2)tTtfmg_zu?T8^;{?DT~a5#)zMitAd6{Ka!Md;lDbaDAG4Ue zT}}n2xV4<6xsycMAOF7jXZ-u--_JoS!qkmVc>*&(Cos={X{@6Cb1hIPIGNdAZ?3xE zKb6|_Z7P#D*DclMvr-E}(wO$0LiF+8X;k#~;@8Zk_cV$OypEmR44j`$*IHa6kYW8O zeXwC_{a4lDfh-As)f4xW)<v`aT)gwWS^C6R0iAGp&*FDWPL$8zQhG{@KO-8?oU6B2 zt)eSVm=^JA+e-a)!+QF@+tfKedXHXHr>f3eXOeU0@HU-!O+mf!{_}{+!)NNr$+gZ` zVy?5}=q9~7`49S^k$W98>7pK4t)5Oj@rKi>`bpicz1GF9eRA^XUv<s`0sSFk9Vg-H zKL2@~ctgwUkBwe9=HXH8?=wU%rI$ZU?_Np1TgQuYU*&3(H*j;wcs+1y7X4Gb-*+8- zQdysVe@AUjFf=f#ds$twbz`0ES$el}<XwHNKt=t1SXOs!(_2ycZ<b`%F_V;VJEnM` z`(I6|&m64b&e(cF%U}EGQpXCpH)EaDSJD)h`y;*Et<`fqqG<-*>v3*(#mm>a)x)>y zxA_I#F8lx09hZMlU2{}&RksJa;;gOe{qgVIJ4;{dL-BU0ZW&9tH?rN=9XICFJ63CV z)${GTdXK{T+|c~)FP#?YC%GHxi5p6}$6I~S$3|Dst}5rQTm3GIU;k-y-M>?Qx6#Jv z=HjwOx@xKt?&Dsu%$w@p>t{`?x}E-wVM3!<)FlShaC5bbVf@EQF`$mV-ma4SvSCb< zI-;WPJ*0~KT|^9%AVo_Z{5g*MXS&DQe|-P@4X>>9ncs`Jcb(6A+ias_KP%&I%@bt& zzW=rS=a6?{8GU?6Mpw0rY5dRHe;waH<9|+*-6*RYJB8c_e+C=>G5_nC?Ygyy&ULd$ zpvZ_tdT#P8I{l;^fvq9Sbj?IsZ%dFOqT$v}dicOR`s;1qMD(t{O<#$1Uq!qbADDf5 zq2@Do*ViM8o1fR}iOJIG`p<$Q2DI6#L+(ygE2Zx%{ZErSsDrsOMht(pO`p8dL{<Ng z$;npfsLp+-oW555JLi|QNA%wB^Xq{1Kg|y4Mu%rR1AAZ7!>?7-qwXwrCe`~Z%6;p9 zW;cJFqJBzrpxEb*N;i8xTJ4K<Yj@yn75&Yt`YN7U5i#*zMqRyVM!hH5t*{AQiff&` zpdS2bYsBl{vgotf%j(&aMn)V=P+X_FqjmJY!y<lfnp5wMQCQDvKR=?}r?~pT)Vu0* zs_;O9p?UN=xxQ7#CXYChu}YNQKkq+&okhiU+3XR{)9C5+xHQFdSl2mD?Z&b6^R*@Q z-=Eq!(+Abkk17|}o##Gw)~xNOmxmVC>no*mTT~vbx3@2#AH`4L#wn<@X;4U)KN!co z*(<Sbms6|a8|OLw`fSpzpEOWuGe3<u^kk+!-?p%tyyttTVDJF_Iafv1_}*tH!MW+W zXRiDza>{dOcgRsa{LIBboWa+f><dolO&?<@(`mAE>+`lK$MnxnepOkGpOxN?8@x;Z zvNxa}?8)p7y?;aRiPluT4GMLC4?Uq<ZQd4m*)y%1XT$9%Gq-1at4cK}>xQ&?tFLEV z8|X5qg!|j1clzw=o@z;)4DQ(QXFA@TX6okkQ1^MrXFYCdi27#bm52<}=0$m5_0=%d zV|&uTjoPDh-22}t^SNB{23;rW`LEXpo`y7c;-2249~`|Eh;eRwM7G_lboPhYRM&6X zI&-Gi*KvL=ukvqy>Xb;^TNibPs$*yKxwYpl)Kj1KPzM`ja0j*+qN^qfQ=gOWbkZ(J ztM6=Vp~C)3=yr{!qTE0J`)X~6Z&jn?86qMQRMq}-ORzSPI(_;|@p6-9>$DN`)y1WQ z0wZrv*WLGwQ=z|>4P3~xOke3%R=EkA1=b&0q;pixt{yc^6tTAW<|yBrAsx%9)Z1q| z(Gp(Q=lZ-3<k+^rDbo2bT{!ahK-xWboegzg=)JGvs()L4>o}8+=)$c>25vTVo#oXo z>c!0}1f~~@?MAwfbd~UHf!rT5xXI_nG|dWzsjt^&a-)}sX-v{4fx#8?x~<)4#=rmm z>*D_&_xt|itZiIKWw=tvjb9|#gruydlKfuAtu`@clw&T;mRnUxUDW+NH<sBKs@3RU zOS_v_#5Av8S65T-FNvu9d$4|RwTxOcaDnr3PE76hN1gdzrx{zq?N=t2Sx~#GK9H!0 z`+ih(GyJC-dfp$Q?yZgTGtc&#dWR|Gj%yj)tcy`v$4XYlZC5iW%IEgm-sSa!hDF`r zD#4~evpV|Er5W8K>4VJ30*O^{<-%_Jck=(j{-@sqiE31Eb%z*c<n(l^#K%hRja<_E zX8iuQSu&~TAFH_=XGb^w`}}dC1A&3rD!Yx|MK}H#|NZZuZ@q3$;PEu=E-Dvfs=Qnn zi2FvlC0hrXb7Nzuw~<BM`<G%xxn5)1y$>YMU(mffC|LeX@&8@l^h4jOhl%RB`Jeu# zBVO!RMY`8;(>Fb#leC(s{_L*Yi{-XQ=?9m6qteD#ZtHeC^?$APKQBcp{Hu;c7Is@^ zS`y`Z+5a<u|2w*L$P0BcR(7|1$>C8x(>gwXqEci@?au$9L6pxo|MTd71_y`L(NoL( z?KH~pLi?|s|8rY4d#pm6gt%2UmW%Q^nXhLJ6}&Z$dpanQu2(;fI+t){MD%;bb;0vl z)zcR(BSO=E6Q%dh_@8nAas1yANB-`o8eOfc7M*>o`#zndem>A%-OmyH<<A{Y&i|sy z9*p&+FH&Z-S|mR|cds`~&D)eho%%EB7k^5Ioa&F7DZcdYQ;k&m_k<=g?K+h?Su1t> zV*Dt7#tCUtO-)_hGq8JKY||%ll{!88dcY*R_~rX|p^mR!3_JU!kJF}LV8ggWdVi8( zs+-$5ynlz^zWAwf)K<IV-_cFmPgEO@X8zKT+7nQlOzZGH$L>X0>;F#oe~<f*>Hi)d zaVS)sT6jMq(e7*7e@y?+?fyTn`9I&rJj<gBju`Fqsd8WY|4iin{JB**n{H|MxzVJw zdXC-a&^`%t9=lh~8l}{0?A|8tlusYFd*%PLUc)Sj^n1H+yFO;t(VhS8PluZ6^g+8P z+b<T<`RtzfXZ%0ggoYH+>+SpX|J>qV>wjJUpFP*j4b$uPjBy%Oy085|=lK6z>HoQo zYvJ7|{`<#&KQNPfM37q0G`9J#eemx;^WL9}{pb1OR94;Zd>nUN&8w<qf_v(p-5K1J z-`!OYr0@JHll%NZOm+BOCcR}uyf3|)HcEN@sAxk~54$$wgL-OAnk7zTs>>=_g68U* zscRk9W@_I^eO|J`dA#(-?$pvxFOmOC-zDKaHN)3?GYRVE*CWTpbuRBduR?0)*Td{F z*B<*$e`}AqO#1hc3BDXZg}l}a+v^+k)DXKi_WF9Nyt6e>=0T(?^s<@C9Qjjm&c}cJ zJI(X!P&>1BX=XjM^Xb5)J@NF_;BR!$cUK~M#m%U1#~-4+-hcdC;@3Sl-)S~Kt-e^a zk$P02qT09Q#_qSR%cxEnCaF{LZtmti4x2t+eU|r5-z!%Y#XhVnmPJoJFk2<h`%3j( zbyv-ne)Ow&n*HCJ=ziey=j3|$vI6>N@yF@iD)lA#_rM|f73W{2ZebmIaJJezC8ny; zWu%%WGl#prRz>qxRUET!?Y*kinK5dfeJ|VEWzrck2D|H1XV7)!`02W*_|kt4$)fMp zOz3hxoLh~`*}n9T3+B_&m;Ud1;h$agZ8$Sk!}95;wrA!=#GMFl?PJ^f_lnmlRJ&(H z-rCu<{~G!C_NMG}eY=NWR~#Y#w)MaBsZ@Tv^3Ivpnr-isCVw<jCtv3MvJaDLmQ}@M zA3g>Jsey8ydGm*;tM<LbO<FX-xvj0yNM-%{fBo&kjnv8H$-nIX&C}oMJ%|2xKRkR{ zSa-13t3-)>`kuXx>9%Ch7rqN}8z-%(E696!SUBmIzRlK2%Jb>>M67d0T&SR1NdKf} zQm46mANhOsp;h2$L>l?CNeVgUD?8)wd9D5SI3MI3j@a{L&lB16=h^Z0d6m4c`Sx1; z*R$Zi=h=sf7snT0dAngCs~qQ2vP2HOe?MD=Hd5s)=Tolu{=H4}gHp2($?vl4ZW!?2 zd;WWJzMOL@yS7WMP(4lNAIZFbpLs7C?K$|*nd^Jao{#_Bxc5At-utZZe}?$i`tK9} zX9d1@Kl^9=pK1PQ!T-7Ee=hvK|1;2k-}>kO>od^*zWndke|?$x|GU=y8UHn9zNp<> zdheO_-zWb4|F38H|N7qkvv1z>?!QlX?pnktptzU(&!GQV^WPi)b#MP)-@8x#@B8we zYtGYqF8urOU(dVW_n))>z4$-Fd0p?b+W&d(pYcBz@8vW6Z~5#k_FKaMYrW5W|62cZ z@n4@ge&4@u{?DZ!E_G4A3`(t2%-*iPtFTVZ{V7a`{k2o=pSx1+=ukrE$sVKvg&L@D zpQY0UvjwSH*Gj3&-EXN$HzL#zuXCz+*>0)aS%cJ^iG{W2H$9wFZ%_G1jr{aN^(%W< zO@6jaT^bP-PXE61d38+sz6pzK`i)0|!qa98)e~gq$i<-W(K7Sr*;2Yd0atZclt_E$ zllR{wn)BIdVyeY5vwv<?{aRj^`JpPiZX5I6m)=_&yl#|A7?x7s48QfoueAN0I`~Um z{qviy>VQ4BXNQaHPg!rNZ7QbPP(7F4mQDWNHsMYc^dz&6ZP)tGVVb<wnABhC;F14( zFKx&Ftx`&V>P3D<pYw1~c#D&zzs&sV%FLU*ntj`&V@BCe|33TQmw(=WZk?|c*CBOo zs~w9P2EHy|NatUYP=8$7FyP<+Tr+d3e0Iivy(YXZuZr6F5xEL$&cC9Z+odDLbOU?N zystaWE9x9`N{7EGlUNVFX7rvVrNi;_txl$k4JaKRH*~FfB)<c+Ui@*xs(tb2Zz&zF zYIIV0*5uL4*OU(LGc@q!T5}z1|C#&CwdVSA-IwmWsrK$_81TOr|2^QpH~ja5f5v~$ z`=1g2J?3BQf2RKH-2A?O5C7}@{WJdS&N+DZga01z&-kwedpmDX0=-)H#D8D;*ZQyZ ze_cDj@88@1dwspv@}GnMI{L4*|C;(|{PzI!|9|&P=V!UJcR%>g|Bs~wH1`tsjDN=O z`@f6*zW>kW{y#_i|IX)^zJIIGm;IfMsluZC9jX8CJpF$!<p29v|KGcoxP4!x`;f`a zbs@K|Q!|sUejtfk^?U|hsBl_6uyv5DI#$rkB$}DXO^~Ffu5q@2ej7iQJLynNU82Kx zy6Nhe?%-;f^qHi&bgc`?-L-ulE9U!_%H@`y^_8BsDv$o>-zQGHOIj!SVV3fac`n;z z<-OMG^7WN>%tdAUEAKeBZ?#k2@#p^CQF+Hn*|LVx8KcR+1+7)ha<)=qTR&EP8XQ%v z?o?9!(|%C9JDgWX#}!q>zYo?$O72qG?u}G2(>_vd9?SE+sf&vK@vT~Z{fP=~Fkc;s z_D)r}`$451J4vPQD!)^hIfhR7*H+agPh9==h8X&ImnG`lnnb!u;$Z!`;{jDXK^k2l z$tU&c`9`(9ZF(JNT@2kSL!^q<G>5MI^1eFJeT&Mp`CDCc-!oMv5TW{2kw1fNIIaek zTdg|1FQ||IdQqKfw^FID1@yEu>(#XDGgOv%h4sTs;VS&!$?A_m-|CH-XQ~wWhN@9B zztaia<tp+{H+7|EdcA-3WOZ<AeRZixW_|U>e0A$^T@|xiLcQkSUsbaSN<ChbOb=bT zEXsTL?@80r)m74GG4;p#msIVqOQ;h^;_3u{?~Sr2nU;4_>k`Yqr^k96Wlxq*9;^1W z{7V1z$0z0AlLBXFt2hIb>OE^?X#bw<dACfRT9IC-*!MZgo;--RQhv85r>-^iNt8Xg z-Fu-5?VC?G%W@^ko(wHFMa^xHUkCNxA7xK|Pc~4E3(l>FFWeMmPYzCMs7m~kN&l63 zO_V)Zp~|TK`$Ke%@QtcW>%J=WkhD6>s6W-DCWUoTxtCVTy|k!yam_tbNbZ>r5k<6j zFTLxKPjip;mU}E{TpsP+KL>|p*WP^<nLo4k?w@TH(`fI$`pHeHxqrTw`=?s$MB2Nr zE`CU?z5D0<p4i&EuewDf(%e5k$o;dVO|bUvs}!}9Yw!LEtshTwUyYFa>Z?)dH22SA zxqmvB4AI<IGvvOi@>dS+-9J71WzyVNTjai4QnR4`fA61&+}gXZ0?ER(cmFgADx|ru zR>*zj-;*I-is?i4o*B5Tu=egH|6ZMp|DE>kAOBtrUY}Ka_m6+C!V;v_G41{1->cVs zQfTk~@$XghpF%YEPgA*n{Cm|ZEVcITAOBt@KbKK+{{+kZ<KL@B`EzOS{_*eCLiv32 z?jQeNJ#14{_q6wqf3JemeXG5D>8r(k^q8*c+;o|v{tmqV_uKc~@1%#WiS8bZyCur+ zw|9QsQBNp1+9}n0lS!VvqfV4Hn(Fvfq)FIeiq4Z}W+3n4eWq23ar$_=c<S~rC(7@x z`+tx6TDqB9?|2l^pm1cA{}v#@q3Qbg&x@URaSliMZwLJUeZi>vqxGYd@!hQP_M6}> zlk~&(_nh*_4@LR!5r!Qds)J6XbnA9-OuF}X^`x)~&XTY-ru*|_`tg+x&fI-l%-bxH zx~Tl#c$X_%Oq@H{^-tr^Ih!l4HMb(R>ioaOb(dt`Y_e=QqTM91+^5Ocnuj@;>U1WN zdne}xv$uh(+t-Ta78<e2#JVt3H|YGp>Hqs0bNHdF%e}nle0;Uk<Xtyi@8~|-xzu*G ziB~^dAIdh)Y1MN{l-@s+<NO@`=I5gk6L+pQJv&C~8_^#}OgX#QY`DKfU$619_=QGm z%*<t*^qYkn1L?Z0GliyJ)K>@QkEk(ziMcp<kB*V4RN(hJ8_dF?H+4kE#Ssk`E;C6| z{H;rsjO`?zveGnJ7pY^J77?5FZZeIY?9dg;)O8;Ju-k+!-l*%Iyy=uE6mFI`SgdRQ z6XJGHw##ISozG1FW}g$g-w3lMSANr{^Jyoh9%+_d&1JqjddBG(XRK)%n$wiuw%6I3 zc8n?YG?VF(Z<bT~@HmrjT@Lf&>;k9%@X;nk(X6KKwmr`MrQ=Pj5Bbd2#EYC_bBCMq zKjkt5>-2M0EgNk%9w}%Fr)=z;{XEQU&6LG-{;Q|+=HNIJd_I@?_g+co?Cnuz$kIY4 zOV&RkI*%M?(yYj4oa6;n@|}ZBoswD2nLc^d$a;g!yOvqZgJ`wYhx3Ds9+J(p`=yFH zQfqJ&e@IUGJ(y-~)c7<*O!`+@O@~2E)uWIhQRWYQDrAn%I^z_`G|Hs<Cd^cQwc2T4 zaFn^1p^(YncD<7^>v&TpW?nOX!x<-Exp8L1h`c7l?`xg6OD36Gp}9=+TSuK5<0qOW z4+5sun;)GThen#|lZ%)G*Lpea^NlyZ-_LLUs6E8#?@ltCjt5MO%ugb+uO4ZtuP9=& zY>)1=>^IJw`#ZmxcQl^!XY5I)W~neU^V6yD-5o}n7>^5?W`#l`64V}RuHO019GMk8 zqR_4hX62w9=HcR>0`rEBHA@fXFyn@PDAq1=f=Pcox0zQ?1*YB`V@{>bZ^|!tT>R7d zQ6{`%PLnTWQTUwC!_9}o+0CF??<4xZ9cd!3W-)ye&W_kVZ<JYFKAWi#yI1(Ckt0l! zRr32uzpW1Z+;*txQ8<g)dH-7R!p%pTO{+7RCVyWJ6wW@({N5&qx%%vA;BcFvW@}g; zlWFGc;;kBtFvpu`H|yiC4$RLw)NFc|!<?@ZO^rx8%<N8)+eBRH7APHaq#1E6r%5?! zOW@7&kx_jA{DQPOOufb-s{7#K=KjRYCip_II`i{zlhI@~&-AQ7_g5oLwMW^_!JcOV zb&8BKOTWuz%1_9o2LCzyKhJsplETJh2`b*P(FjxaP*HO*+JvyzS%#Z8j|-com!5}( zO&e~mpDkr}CSMtTIes@28Cu%ZPuV}>k3YMb;ciK@Yi`4c{X4pvu*oIOn=WU=<B0#$ zzA|P*y3EeS4_(Z=r)A9dh3Y#~?{_hs2bDIh`c-k_p6z1hPcCg9h39bc9_eD*#x7~T z-89kpeP}mR;!z2cZuU~=!jx_%O<!Z82Q6|IKkR1QPR9J(XPOf)es@zcsWMLaOHO6C zr@67dxLKI#tkbqmFLV7uaWf*#F(*;uUS?-aWwt~+?0mS})10|b(5#wt+Bq6I+<aTP zpcy$~zw`P3q3q4$a(dqX@v>xB_MOTWl?X}QGndM~%a)z8%UTF26<R25s1y|m6%~@Y zXIiyyN@WQlYqIa_Z%*#>GUxsHdOSYA|E|Yz%{A9N=enMAPR{*2Y>iV_kAzk33FJ-s zUhw{C067+=q`}p_;6P=t$kl;dZ?G5UXd1)IsxT70aW6Eyj$n~lE7G{i1%3r0SQash zsFu1w$}3|~y%UpccGd-OtqhV6#>#J$yGZbS?mhzA9GINE`lS=he>V(DI%y>@eC8~{ zdHAalVBaJ{KJcIuXs<SevzwI3UMDBGyvYz|UYSDfpK^lH$45ZlVYbBklM~F091e4o zLWr}CGk9JZ0Zr0lNzft}$gwko!A6m!wT=r!wKax8#n!~j&Kb1k7{kQ{i;4FHXLw|8 z3|@L~<he3uc>mi7+Ir^6-y1o@4@(TM{37MAuJ49WItqqH*~q`{-2<x@i~=Qft>hk? z_rRSM7^+*oHrn3N0a~faz+{a@lIjwBP--j#FD+MjWh;BAo&d0}%8DEcw1=}`0<~Ml zlXgEGp<9LttSW9!h7~(Xaya7w;G+Ib-uSpZthGbX#<UZ;dw(Y^%12<*X%1=AY!^KK zDuYL+XNkL>0~A^Vyf-{SI)2&%Cm#W<IOj^Pl<$$O_rOXFKUeQ0(FP81KGYb-UD{8! zoU@0??~UN#?@(ftW)C0SM!>D5*U5cHM^JlW2%%5z6YWWRV5o^P<gLC%rhIXN6b%{N zy^u-*lbqn<_+en96HD~j-tm~%E;0fi)g;nYe-CVWI|8Of5aMR#2ugEI;QQ}I^5S>9 z!C|Bc9KX~tc}mr8(5(dMztT}Y=9?`Th69w^Pf9j_XAAGYn84?@<H+MMdoY=63S*So zlWDi@VZanKI32G_a^*JgEZhXPPwh$W#BYHg$4sDY$}G~MZVN=Ij)KlsVPyTa-EgOB z6m(HOK;}N$4P$~wK~&~m64h)w?7e~^BJmKhSiBAPvVGK_e~R>OvkhKX83Cd<$?Tpx zAn}J0G)c-KEev)*-zBV`SKcN4Htqqt&oYSZm_f!ce99Pa+pJC{R#iLT`8G317&2S# z!QzxpHiH%Vi{*CZb};$83H0&{k`JA_4H^<t*jVMBe6D6I4EkUSLwdDOu8XjPA!EnD zq}MaZV}Bdyd1N%W<xeFPZG*UHrV#1Bg81FHfxwYtz#v(ZoVBrmo3BShW0fAnZo@X% z-q94?Do>ID?%N>pz6rdjJ4Jr~u!Ct|0WP>klN`!;Am0@F4n9OW$83YamrWtm_8^(s zatB;Ig<)>1yTr|F2c&9Y_^NZC+;g^vwhLuoHt!MHc76xMS711>D~s$5+X4NGFc?o^ z@5B4qOE~b;@X>%K%$9#*_)ooN1{;gYlgBC9z!Y`HhgC;Mes8@^!ht`BkA+>QrjzQ= zn}8;afvY{Vi1LF?65e~_VhWd9hLOw}HV|~v6l~aj^&c<gy}hMu?`~9*0gtvpm-iS( zXylR!t+#`Z!9e&l?ILmN;|sg0`$4b18AM*|4b?IIA?iRDx!C&<#C_I*n1->WiJdnn z-_U^J&n^%!I0UXCny|a#0;$pUgpPOALABh5*p5929am|<B$LC${LMk|J=+VWxOfsT zTQ4w~-3xZlHX~0*dO;QQZ`S;c+{e-jqBg3-m)U*E;1vg<_)9-X^=d13we|u(_dZZt zWhcLve+X9G(}KcYadM9>KG5Do2Odw~DsN|X2%c}yhM8}4iJOZrz+^oba;XcsV&x6Q zR~sTc-N~saU+6tj4=l^}kw%Zb!AYY(BsA@f0%kaaH)w**&kpQ2gw8Paq6TaaH$m@v zI>Lv1O}KP<0LnSw0GVDI;KBZX$h*xR@DJ?+xz2r&&t<7Uf8OzD8Glak=L^rbJjecv zS9$*Ad6MTqp6hrX<9UYX1il~n+T(kl??=AB_<li)hk%#I#N>~kTtG9Iy<?qqBDw#~ z1Mq5XAF$rjP*(EB4GgzxLV3@f@)yWcvhPzZG~xZ7X~cSg2Ur$rg4>FV$vv`N;aaK& z{8sXk=PdDn;#pb{Gsu|SPu&l-)#^~G_DJ67+yP0=@b@JAJsa<@?x+Eydi5mJ4!eWP zZVj+BFPG15>n@p#&w>Bl@#Bs=@XwvoWTQJ=g4yG2@G{vk`8u_D$#0hVXFdKm&daG2 zw!QXQ*6rOD$#0hD4L*!@Lvv*}OE1Ed5vOprUVu#FZ~|<b<&J-2Q<;)Y91L0LglEkU zlB;~a07(|xaf|2s$+k$T9adwHt>!4xiH>owbAu;7qp42E>t6;-gIKJlyE^&V&_s#N zKg(Rwuf^N_JxD}K6ckm};2ljKktmHANXz?xKd9d%x$HUUamp|Dp1&O_Y;+d3?ybWU z{mSK6GtNN!7Qb<*(rLNXlGE@htp;b5O_h)Kh=8fTK47=&1<A=*!(p>$C0^PlC;4t& zI4sS5%-+@aPqx)M0Y9uN@w(^9a=XzXF#6#&e0FiR{Mqd=nB1cnhYcwst1LsoGDeQ) zcvq92o+sgGL=ryq+MRq|6ArV=i?HfBM^Z5Gxa3)te<tOh<M`)0{uz*eX5^nk`Dai5 zd6s{Mouy6ipm0@+YtKMd*IazEhbleUI9l>N%jchE-x7LySQ773r(xv5MsVI`135F| zEDSdLf*sA?k?S#$ke1T~=1r(3r5hvQNQD-p9tt3fosPiPXf2qqt{=O{I0C^#8bSNs zI&$^qr{UMDW?<i;i`;(vDY)#^7pe!gm0v0Lhq~S0an4v`oah|}>8Be&<S-3c{)!WT zUiSpmSLVjQ%6-6L{xjUP`(9($=^_90A3pXy-n{XG@sz3{$=DCLE4b);$yd@t;OO!Q zci0{%UpO}ao~^uzTeu&P*A71h&ciyx)^Ytw^kXl$n{yYp{N_#?+zfzW?P~B)^Vek0 zvSXkeQ-;TUc}Gevo`8Exi?PlC7qYxpFkE%-3^|Q`$*pFGV8a?^h)!=owZ?}->Z*QV zjc$^|I)|Z8;TwG0u^qj5<T#AXRR@jeS~Aqt7lOBTgO5IW#K6KEYC8-7E5m^#Y|ml1 zJ$?Y3U3`Q*i9ZbO$7zFMqA%%t!5`kV)&`3PeMyRgKWu8>ADr%&kO*ggNdBn>x7>0` z`&d7C)?O1LT_2M4VZIRBtp}JDWs-T*y`fo;UNFEflPpd;1jbwXK;6SCvMbpK>ZWyt zlij?@&Q6EmYUA$kUDua<xATIQKe|ACfi_8g>jimdyTKdfq2z_B^m@+gZeZWzl)TlM zL$LO657<^4B`?jE`WKH>2dk}aNdtEIfa)MkP<q)mxh&KhVl?|fe50}Qa!r32`>j9R z^cyRG)ZGuZFCGX(s@Oe=fgdbU?g##bcgV6$K9aMZzX!1N)qze)y~wL)esG~s2fVxa zkhCuTlJk^5b5qBwLnC&dv%>t4<ldmy%kE&^+n)rn=W+fXV7hyEP_i{3udjJZ?g#km z7LGmP{-?8Y_5RZP1pfZP+qyS6jJ=sOwUxKzKA~dz0QllRRNj4;ujHPA-^YK|48Om8 z9rAn1*EYYWd|&YU$oCz;cf8H}@V(6MDbE9ZZS!2g*E!!Wd~Nfb!*dbO^F06aoWpZI z&oeyd^W4I7KJUYi<#~fY7kEzKxq?3<__KiTWxmJxUgrCh?_a)8`QGGhz90F%<9m(& zdmw)n^XEH%?(=_3{QrB_^Y;m3n?Axbg4$BkBVllC>KojxOpP8tdP>5vywAf~B{+M; zK$;sB0T247;^N@8v?w!NGB)APUF`8fi>|tIMsiMtc6)-i&h9{Os7Aw;;TgEEi8fVw zcm_08lW^<7-RP*Pry=5FF;*=cK-~kQz^V5wtf$kRj#P~SJ&Q#47t!9dNl6s^+<ck+ z{-hm!=p6}KVJyx>4I0+&JRCJB$7A-Z(YFrgCHDaQzVr3T-?#Ab`I!6}&7a+T4*Yq| z=fKCGHDWapHJ4f~cO#;<(#I)@MATfGveS)-T1=$qr(D!riW%CSh?+|Uz8#3Dr?j~F za3bm~9d%YCoQ4w7P-rMA4f7$QRucUlL_`gxio9YHq0m<HY1)g38cI(WsuNKwsoSNN zMAS;s>EJ{}O{BSl4--)<sk3T-B5EkT>^Pl>nn-%9zR5-Hqr~BDiKvNmD=(agT1hGn zU5KcO#55&nokH*E*NZt+)HMn}v5<;-N3YM$q8SPuq<hIr=uCyiQF+30s;kgGVmcCZ zhC<`$edJm?TcLd<FP}g~y`!EdP3R|uu8~EH26Q*mJG#pBj+hP-6?Kr9#t{`Yj!vF7 zr=s=|)1aWD#t}T4Petvcb3M&zutMXAX=PAR`)G{iXEIr#ceJmqHxc!Ymh@Rjmnbxj zm<|sWwU5~SKh;-g95Edss;|&KVj4#@QR$Dy5z{`Rukj!4BlfI8Cn+?JnD!Cvs?a`S z8b@@eLgR>OAJKA!_7T%KqOG6*(Kuq-NA!|H`^dLUP6WN9EllrdSj_=)>94NQe{(VY zB5HW-kA4x;HKG9uT_ZkEK8J466X;`wuF>4LIfT<SBBHL*n}OBjTk#)VBm4W9x+`>z zmS=w_W(r-SBVPtmQNQSvUoa7MjV!A!6H)Jo$DGHLuLq_jLPh<e*IPAdrb5?<X%NwQ z3cVv9E2eQo$0;<9c&wPl5fwF#n644+rqDIAT;7waF<m34Ke|T$#bo~<M<*zBjT)*y zB7&~bt3SF%<d#C$s5HQvaJoi>(>0>w6uL(DkGT_3*XXp$ZzAd%xw;=9qOK9sGNL0D zT1K}<#gL{7jU%RIL<cLhjF_en{h-h|V!B2Y{^}ah846vaTGKv6)HTv9bZ5F^f3%GF zxtO*I5w(o?e3;G&bx~*;F|DNkV)8jK{Szu^D+&5VO#g&_efUS$=wG=p{SzwaFA2Iv zW1i>`QP=38|3D(@7x9`Wyk-uM!??23gwr+p538JwEvTq##PcNI3w)38{K;z*@z;5O z-sbhh_^~|a|BL7OvtaVbkwnxl;(43r^MdI{MAS0kZQh4JgZMt>`HDZA__K!RaQ-ad z_lU=zKRfs{<zIcx^8nxDyv_3l&+Yt~!t+0WzVO`6pD8@I^BltSKhGyTkMT9YG>HD= zI;KtZ-?_~11;3B{zVKM_7*1E;N%k|XAz)fVd~fo7$M+`RYwUGZdRCz+q%uv1o>gcK z@jb}*TEO^zG)JK|^vm@%S)Hq1uld9G-RK)SMAQ`GwTAe9<om8+(iyTqp*6(!-5~4c zG)18`RA3(=U%tT*KiwPv6Xd(dmu|!B?I#OD$+-ji^*Q|Oe&fMFZ6fLj@jS-!C({V} zk7L!cvdLbBzR)JxnTVP~d>r1N=W1oUc|_C{;^XkwpBl6wqFzv0RdXWh2qljBAQ$z5 z_&oV}!LbJswS)NFUVUy(MD3t|UFT!+Iq){`!_UR%$<M{-ysG0F(nz7(qm`LQ1U;Yb zOwXrGMVW{?KV3)Z5K+%(8mpgmS?ahq)8}EDJfxdKlc(@we=2JA@OnPHKF_`RRz%e8 z`MBMN<SF!jeB13H8ZCz5C09HkX?`e)anrBY2;wz-cx@l1=R<$~)$^gx6nZ{y;>XaY zqyK35G+H5}uN2xoOv8sZR%rONnxjVp71}=go_C|26&gO1M>L}anSZo>cs-xtJ37cm zDs+1+GpyysOwVT))AQkVes~R^#9$jDX!}?(ZJ#Of4n)xKiDVi+ytdCbqX79`g`N)| zpP!f4`QbHuG&;5<qP7py^C6<157Y3W$C-u?FbyB3?L#LqZJ#=(?ZfnZXvkkZANu^S zo(~oEe3*t0{pI;b!-r}6(3J{pAExI+lmF`ZkZFJQeCSoC=hKks`HVMuMV>GXA8n@L zGd5Y5CMvXjXhu_-tI+dtx$%yeEA)Ka?eyfLhELUKb@E!F?ZfnZD5vK`YZQ7ux1YAB zhZTB0Ov8uhDl~iyw&juj3T>aE4JQ*(!zXKo0XeGB_Bpx{<m2*Akgc5zAgg_}e2_xh zM{j+gJXN9XGr0)l$-n++`<zUhB~Q-%qwOQF@{xa0==qG<-Gm&B{-g6VyU3Y{dOm&h zD#&+*&X3orGep$(;p6b}nVt{rvGtF(57Y3WO1qBB+A$3urtL$=Gi@J#rtKs6=qWUR z_Wm49!dhz>-(uQ6?6-<!yF$Z<Y5R~#3T>Z{e)~x@)BLGsx;pGPj8s|ekALC`Bbv@M zc3Lo<AB#q9=}M;U(~)WWFg+jAyh&G-!SsBX&JWR3==?BkA9_)t?K5^NqJp+hJk$1B zJ&<YJDD-@o&JP))(D^Zcq)bF@A5SwKvXJ@vG7TT?)q12(F|T*lNYY%P`LoL{j9gdf z`Q$uyBcjfaj_qYKm}&cb{-f<fMQtCZ;X}<88a~P{1L$Ujwoj&g8!Bl2>|mNdTi2Z; zqK1#r4@6ojw0%}urpmuMULsB2^nw#T7m?u#ZJ!$bB6+bw3yA6b5KiZZ98l=|sC_l0 zg0{~trtLHCXICm{{xoF2S$5NSPXwKxkxb{uDJ_l&IzNR>=jV>qRKn@}(B=xA9}^QF z`2dB^Py3BUa#81p$ArgfL!=S;tkCee@3)YsDKvbTZV%b5(Cs-tCz!lb==m@WAA0An zh7WzL(D30kTKRVl`S%I=XBqz4hxt=Y#XE|#e(2$1(^z!hfayZF9)g!`PLScPr7%Np zHP*+gWM|uzz)-uD*r@RVbiykaeETlOn;#!XlhX+_U#Nw5?EQeYoujb5P6rR2s)lXe zr+`kvGOW|646SUR0y}r>;3b)>WSN1*lKA|*&(><=-#@(3p@%upVr&O&ez_GjyH)~q zv!-FkSB+_{S0T7QHplZE)#x{?64+kZ1^4~giKg!_llb`VoQsXKQpk-Z#n89K0^D$G z4!LAgDj7SwR0sQIbtZj#l|y)#CLZ#-fEcEfOZ+DvU5*Pk^d-igrSNQ&77jGgAZI(3 zf=sO^UT2?4f>TQ+WBHizD$8)2euD^XDuye^m*bmv<i<~W7fSHt<MV6b*U00*`vg9< z#2eFRqk;k1l6~Rv=l6x*3*Lv{N8V>wk4mz*Vlquy69?t_{i$g8snnwW!+O!O+p%z0 zrJRWN_|IDOy=yJ;)wmAZn`u$`042H_N?~kx1-Y!S<FalL(I>IFE{%HJjSg&h0d#7$ z>94(0scXaqIPpT8W;!pUoBggrKm%R+WN;VyrF$X_RDMe`R;;I*S#kCD%>a8EelZDt z-ReqtoA<fC-I2zkw0a-WuF@$Yjqj+@{l)|yC>Im7-ijXml>#5{7ZGt@wb%ku&CR?0 z>~@+sKf6ATXutC)ASL6PQNM?2(D-f<ITF5rR(`(*;~TywH$Kg$4q1ip>1G!y+Wo$D zp#gf!Y1YsJxSjfri1yU1QX*%c;PO434W_Nj$?K)2be(enST!vtdQB(MRZLU5<+)O_ zZc79DtbJDf+TZnPL&uITug{0K&twgyzWHVKKBB#5XFl;Vdq&9pBFH^aKtd-}kpTBn zD7sffJ}G@BztwL*ZGIuiOYBCE*p<SLjE7`Z$s$_TE*>hrXi(8kW&YwGebu}}(ughn zvOWm}`^U(oRC{e~y?v2sp*Q}LT5m5c+DKb>$cBnB)#P3CS@hPCLb&?zK3S)^h_+NN zsQ0;J+Ke9ib)(+)VRi6qUm3VA(xiuawW3X0ltI654~S?F75-h3bBL`D%~0grF}E)j z#|pL((~rfx{ZgBfTvJ+lpa6QX>kC|F(}PzF!LmY&ir6MB=}pCaE{y0+#XPr^Y0*!L zz39Z^i2Hl;mNpe@Mu;h{SFpwP3bu%kV2k+RppT@*gf;Y<(M7QJ>`X<w+_4M26Vr~K z9L2QpFTW=b6}C{@I~FgZBYqb`GTS?`Us}J?rfJ(I(b?bgV403Cy}r2tUDP29hIP=T zVoh!j(WT<PkLsyQTmSw|njFc7k)w5}Q2$=6{`Y(yK!w^1Vzn36cpw#PEQR&vj@f_e zgrAqM0f8T4FHfO+PF$$xfhX<MskhpN`h67FE7a1}3yWzW(}(B#SHNMB)>?XCQ(S!w zi#;n~B3|cl6Y5Zm!*hkeOJWW@p9mZ!<|A;FX!AMq{KoSbpEKVJe9rtn^4IzN`Tgbn zc^`gVe6R6i`8ED84~y&KIa$D2tQng-jMEhLf8VZvh&3Setk??z&i0v$sb~L!`n~Ww zv67BhUm&R~zTWuW;cJGE!}pX>!(vRH1BE=r>pUL{xrzDkT+!)P5lLb-Kbh4$&y9f# z3y4_%JWulL<#FISmgim`6P~YlJb7;Cdz0sR0S6IVo=<o#;<<(IO}-!b9^`pXI9oj< zKM<n^H$XUZpBOzPryi98&wB!Y*4<K}29Iw@&Io~LtOmEDn>ETM=ZL^L;&lNBk&^}P z731*dg>a^eIq+wSaJ~!qM6-PO-1waNdjtNSfzO%ee?I5`<w-GTo-_HJ`Ll!1`G4<8 z#GLv2lRg1Ev2D9-;-FLn**!e5Mo|%YU|9%#rXRu$^KD4t;UZXA>wxFZUqu?tE`}}1 zwpcq(nG&UZ__fvzr}b5#R)Kl&dE^GHbgKikUw#dCym7)&0bS`6*)?eMdLy3Rxes0G zk_u%tc6erKKYDXa3beEH#(K3r^25v7IdyUmZuZ<kF68hIyl|B1VwqiV9^4wZ2Um{X zAQR?FvUkVB541(5Cf8tRm)-0qm1;<stMchy{AuR|q{U+9jogF3+l)cNTmc7H;=<AG z>E6mru$;OY9}3i@TBRxM-PDbEk5^wB=0xG(317Uwn-<-0|0)=)KZ)%UdeQl+SHbXE z1UA;ypjL0M!hOHPc;ndtG%Ps@lD{Y5Wp7*6`|Nw3h=-0)t@m*-NyD9P*AQWB=f~-| zThS9Dj9v649e2M_P8u$_0>_K8@TLeKvfxz$?3<H=1C@P=Rmm0jbSx7OZ*haPM2R4q zn1z3;b+7lYD$mA)H>uZOpYNB6FRgni7vdZF$g$hI=|+NmVGhM91|CMjT)%o|;X!pT z<$^sd<Q#rAGgT(|OsR>+r#EKGgzN4XgRtS5E=X9f`}z>PeO7lQtg9s47l$m-MlDs6 z;lbg<SiSWiRQN0z3c}p*v%w~4_Y*l7mLI^L+eV{)=a`)7u|4>l&v<0AheFtt9r*NI zQzT#;czY{e;@TPsnBN(+0}rfOC$kC3gO~kw;=MNZ^4%8;p+VAiy!Fj;@~llUM2@w= zwhgZl;rd#<9y`obqJsZXd=j_Cw@FZ8E<}Eez*&u)iBW7GJQxs+2b8s-`vS6IWxhAQ zklc$Jch3NKQx|-*#{jzREP<{`r*V?XY5Ay>Tu|#9j?3&v$=dD7hMHXgSmkhQ6#OF{ zx`#UAk?#HJvBz@Ab4$i?=c~!|>NMEwlY-Z39v~~*q{I32I2`o5B^_Fw3NzY-;tvmd z(Xjy(R*dw-@vI)qo+iVZ8x(gsP$9n<p9ZrRUcpD3co{qSrozD~k+^Qn1KF8j6mnEN zaG?%+W@wlUr%q(y9=E;gYa?XCUOX#WlU_TN0uZwgSN9!AN2H~|)8Kvh(pD{6GA0dF z7VX8CZ>!T?`f2d<m>Z5-*N@&hoDN%$y5a?AdeS}YyGS3aJaL6z9}06B4x>DAT~v2^ z-#P;}eD=fZt$S1BIT`S}%nygJ??&_1WkA~aK%6kTH*M;d4q;w_xZ1QEwGT{(KFfo# zasNK_n@JiReHx5^7<8xe2c?0FZ7{a2>`N_43g~|g#>blWq|pabVAIw>yzxPQI&VFN z%QO&wH&Ul3G$?Es=8w&<4xsO&2t;=9$7@Dt(or)AeC*<dW2y(z&(Q>oojq~b*4}iH zIf3IjZg@*mZ8~rh`(#qKE8Z5`n})OH@R)Q?amD2awCT*+6bOiO#qawKq=q_a60DkQ zd*D~w+4Go5x&*6BPF~pPT|c_zffTE62mJ83Uwvsnb-DzrK5vfVU3dGkXS#F=Rv-5S zVZVTWwB3L-307N~7Ub5S{i*J=6bV+p+XrCR=mGR%DV1O~oBCm0eQo+dUy7CLB`>Ve zPlpx_r4p>3P4mDn$Li2uH>d=wMpJz7t}Go|5R?i!gMx4ZFiw7)1E2bYU~STn9(K%y zxK+Ver}_iAzB3QZECcaj+gD`chg@KP?7^*v-Y33I^I?s}G2E_eCDHWEgZVwf@p#h$ zQqdqE`gokczvI%$*Zq00uz4gtr=CXi*5$#u%2W8>#RPKnQ7#xqN8uiMsl;$?E_;9V zEZ#RKfyj$;pkLN`Y&Scfl#I@SM4cG?K0b|{@Xdy;E*Egp>$~LeglstVB?ez0<>aGF z7A%j8!H0v{^JH=s*ffa7(7BEn)n0>Z1!vhipAD&ZS{9_1MB@IbN{nx>L2C6WysNS) zHJFzTdM@F(cZv!v^v{AvI22blXhwDC=fJ^zA^26D3JpD*Ex{xbPT<o`8qfotxiIJC zaeOWQ1Npr$Pl6Th6N()Q9+DQNc@nIKEjWqiX_b+gg;J~%*G1ytpL0pa=~AqI;3$0Z zLN0l+ONv!MQ4G#oUP?mUrC2>*d!GFk{{iWpB*m)Hi)b7X`JQwdlP$rDeenz5i%_P; z3{M^_*YF6u606Ww+1V1T%!<RXv84(%IhG^A>d}cvtWRE%r3-RFS>+TxVDC)o<b|-* z<Z!)h=6f9sGrVc`)&S#yF~!iTCWOB3ebo5isscE;%8gq4?L?}J^TE8*mmbjGhCIu2 z;9{py^dO59)Z!leN*_{hpR~CLx%-CE>ZLl#JL0OKAjgz?@7$1lmVFa#q3UdEXTJko z@-BjQ%_q=<eV?Evi?Sf+-7=cL`ze}eb`4tS+tEJrccSPmg&;p-NS`O|Mw*eu(8R`& zUcg1D&+8nB>pzr!ndFkZ)#etwPZ&(SSPmTw?m*hA;q^H@xKR$n!$wf(ket-n{suhw zZAk5gFGhp9-;l%%nLmxX=ubuDdzr-N)8)l<)7I|BW)@{o>oJG+Xcn84vGOL|aJH<E z|8jCU*gcv5XYD&~OYr1zTN~w1ePXhbhdJlMhXH~0IB!{>C&5teet^b)9EmQ?$%3yw z`>0=B8ai#C2}g!H(eUbHXl`tVWbMZW8qjf{#-Qx50<h>moc4Sfjjndimc-}h?G$7~ zt35U3%Q6e#;f<~JIh*!o|8c<0Yh1OCJ{YZ!{33HCG5NV{64-k|`wpPx+p@r5-#D7y zA|0hgXTsVQBPdDGK_``Ovi~O<OQ#Yow7jSif)ZTn=hFOD2Fv$3(Owx_jN5CL!qBO9 zH0=Ftba{Q|Ki7NZjx8Mraj3Iq20V{2q;G8ZC2#9`9U=$(*<YXCrIH-@S~|C4F?Ift zf+j~~Na~88mygfK<mck!@b%2sIlp#c-y?@Np+dhHvpyOzstFbPNa&Y!O-50nUxYqd ztzkliJ`(x@_WdM6UkLF#ANfs$ei3>k^3EtK^oY<4ZQ7Yop%;W6*=D?r3O&-5_0F6_ zTdB}Htyy0@IJSlgeIfMAgjy3S^ovmc%T$!9Q2#=|EX@2tgnoI(df{m^BP#ZS=+9q2 z#rk4UGXpC0#amYYySgh=q5g%wSoW$B75ZWWtL+h9Ux-lK{Mu7kU48gEm<sjGuRVy> z^F8b7RH$d6&S%fIqC%bX`3v<N^3H+^^(@q0k8eY%Q0GDo&&hs6gc|1OHDz_1)=G~G zb<5Ao#}R6EowF4cYE`IVbr?^D8s_5*`zSl7ONAO<&T6<iN{0$Hyo%Lr;5Zd3*6sXH z8>v{gV*Wxc>2+T~g<9p;_=eSOao7(c)GfbXd_Mf1#<9B1*=b3Iy5(aEbt}%x$K?I_ z`r+5&rIbu{96QPl<|jdqZ5j0DxklvijYRmanoZx_eI{?<D2Iv5DXrQcnRG8l4jl)& z(E+=AqH_OCP#dz5R+w)_JK4RfTD&#wWbT4?&Lj|Pc8HzHLy*<=bVynjN?n@SlRl&K zVL?O)wfu2i9u<%W+V^7V=JGuGgC@CPp>>HmF`s*fav?YCC{<td(s-b9E>z7wLv@CC zlkH*W;M=!>boT@!)UQhllxsOs^KE<4>PE@X<=0-iX5k)mHz)}{PCG^;3kIXUhY4h+ z=28b1bI`9;h%(Qtw{<Kt;a*@WJ#;QzZcvy3$J$+^V^`+L3*%B@&bS2nCQVo7a3&qF zSu!m)x@8R2?C<0TIrU>RixT0fe}29FsYnjj1A^<<Rdy>E8bT0tu6ilg9G)v#Bfoa* zlm7IliM>&HdA4MYO~>!29^YQc=2T`#u<aANo>p`oheC%lY&o2j*f&L2d|rS)y_QQb zcXHiDTiY&0Lp_ru`0)F}kDb0WfF4-h6!}kM_v9RIJf1<{oavax7AU7_5+wGxNOR<x zMtvMoB>3>xm*50i-LW>=HBDMGJf0@2F4Gv(t@1l5NiffZ&@N*-k>hU?CAG)bWargs z^_cg}6uxQocQ5!jyg#2azZStKXykJu)VWa4Yu0@wLOlz0u3VZ%ggO`Mzs;qq_4O~* zu-bxwRH$JA!~7VaLTw9sv3;Hq6>47Sg_fuKQlS@wdhRnTmk9MN)cHD(Y$DXTP|q=| z8dI^J+axxjLOlzZzh>{K3$-fb`BooOp@xOpeh#CkP}?6_&G$H}Lxq|@&T6&xbuJNV zRjA=xi}Q(4!=|iO4;M9}Lahole6PAG6>6BzL8wow(o`bUC!dc{lPV2<5uqmewFouY zwx$~uYLZ{CHmk`md3v<ICOJ%mx;oxqI2CHrjn&~b4Ff9FA%C66kYD3*R%2~dhEbu$ zcpP|qX0lp+*h8HPwaTwosJ-t~**7s+P4YJH!|$~vtIt*zbwsF7p?-9h-6cXD^0mR& zz#>+k?^njw*C+48kNsEvB}?|=qIvyLgB58&KJCLji_FmUO=)mYWk1GUCZMq|QsDNc zz4&e`9h9D$0!KT!<Bob0koyq|XQ?aBVS4(P%_(@!^}?H*k4EYx>^XX+C$0?Yhd$X8 z7{AybTemPq`UM2CYy9x;=iQOqj=)y-EWhB`V07mI1-gqp*Pm;HhK-}pYi}^_zP~?; zyORQKquKXt9yCE}aVapDJ=b?J)<hZ0(xBzBV0=Nh0U9?u4W?NI;+}mq(VolcFmy^F z{@I}cnw60blY9H)UlaPH7rQb*7U73;Lz|#>ff;bPyBB^xelRL=%zzI4J+Yd38#E>) z1J=HD!(FZ#q5i4qpyBO`Z+dq}<wfZdOcr-@!|20!R5UXUthL<m_?c5sQXBU76Ar7y zSPy)3#T2B?zFWs*<)(57f9*Q~&6+L6%0<Z^_e(TE9T<i@R^ulG;LBY`BJ(#?g4LI# zARHPv1VuGYm0<NECJ2Wa>7tZzX%ei$`Uc=FTDoZN(sT({`Ne+t<*FfQP@@b9Rwd<L z_*%IkTHZv8RclWV+|Sko^<R@N!D>l{4=!cj<Ve1n3cGSc@X4(S@|_3s;80#De!eC^ zZrV5>+HW|4W3M)lm#xeL74u*`dd?7e+JjsebvP7{EYUE!u_PB%y+d$lT0zq0tQ=5% zdlD->K4F|^kOS6(!f@QdvBoR+XS01jgEhx&GBz{LhU>#l;|9qOj8<>Yf+aI!@Suvp z$&s;HaB^Z49s*~QJ3PDw11e&1*H@F}z2sS-((VF&duoq-)2nN6UOyfm-b>_1=4XS0 zM=Y+`a8Irkm<0|k*f)?qD-+LUIj~{!1)SKg197^P4bc~3aO3suNT^3HbUq)2AAMxM z)A*1BXB(eo-vMe(da=JboQ^z=or5%qb3^t_J>?WmzxGU?q?QkNe8RB$J{59<aV(F? zs+@2f+}cyVq$m$goC(7PbDPWECgn-6S`{3Q_fC&ZTDnDw)pE-StiGqUal748tX9a* z;-9AjjTXj8vC`L!!CeaWB|kOFmSDB2X)N|WK2E-5bhZR5J*_z0H$F-}f<2G(Sgjov zi|cMamah!WkzloELkw;)SD9QqoGZa<h5uRH(e4}j_HmvBtI+ci7_BRo->j5kb;k1? z&ZwL%ub7()Tiu+fmO}&@VxI#u7dlbz_3=o#eJ&htzlZ)hoQ9%aWW&P#duXGw%jh<% zhuqe7^yI4|^rRQF{kGEy!!nW8vMew<Y)y4*Dv;WXEVyp4j!w=lKvw;;;CS&;>Ncwq z`ORg|o34xLs8NN;G9(MuJ)TQ#G)hpnN$hVOb+hOthifSPWHy)?&7!XiGmxcAF2L96 zbj6V?XfUgR6S;G!gW4sO7@Y@}$usFGlSt$`EDsvjET)gHoJPC1=Y#dOh18}x0R3v6 z4`&vwrIzW((WIDsm|M1*&YI$levQuu)O#BpXwEbfA)o!daVvGaaR~ilf6v*}%8`!P z7l9^B&SSrIb)=sTA4QP`xe`o5nmW?L_X)_(G#A#@+S5UH8R*&M94S^t+vug;MaVHi zij`ZcHSMcbj+*SqmSFX=i50E1E=P7{*%GYgMlGN}cNQa`;2a5787D31@X}1Q?s%>Q ztA=UwY2lPa^xcouIfqq?Ez9V1rV+f{IA4O*{o1v(;__)!wMvTBu2Z&j@VwJ#T`MV8 zos{kAmx<BHe6$oRZFg&WGA{#}U&)1e&nD1g-Cv>mQ&XX`AJ7_kF$&s2!KR%dm63<2 zZa0OyQw->skgtsM*-tp88PTUbn&1<2QY2&f>rWe-(eduB@Z&e^{;Jzly2_$8o@AQ} zZ;x2e%$d#bS&|A1&n=;YBY&f*j2mk=E~CS;pP`kjQ=#96Mf8N$4Rng#3-R{DE3@ds z8QEyb*c6BlpFmGtyoTPSQ^<Zdhz>Yhje2Gz!^mOA^hs0-I-Hyg10HD87F`=**)%y+ zUe~8<KX$-tj0ogEGogj;G;rV;D!E?UmAz-NQxl^BDd1qXitfwpg2$gpfj4_?=)GCZ zFbz!suOr*&o#wSDjJ+FH9kG#inw5=g2T*wDwUmzU6o<@u63O+_g;Qw$g!AZ(ksP*t z8BDDVpP`Uji7>Gj&?_U-(W{a~n6O@#4*Ss@TkpEc?j?rPjG$ili$@Yz-5pE!ZDu-? zDanxBWD(6!9fU2i<goeoX1ZIY4{kq?fO@+<R7a%^UNoJ+)tgRq=Hw5^>%1Hu#_Xb6 zs`;q-iDXz}vX-7(7Ka?yCP}U<cbY{9^*xWySzU#)Kt$gKeMZLa34rfRpeN%hP`pzD z=(-uvH^HiSUWY4CWoJUC*=gYYN{LW%XgZBQ!oDBe;;Q8O=QJz2>8CDU@cJsayx2;u zCile~HYCBf4o)<^vOTU@nFNK$ovC?KWlV2hh1$su^ya*KDCl(}d>+o;yXldG*3?{) zT(4}nka|zMhOQ}Hfep4Z=(VYharCCkaNX5{4h{K?=2>5clJnDO235oU>|46Qu`_Aw z*4^;p2?<QQY$4saLj#|Blpwj@%zhPh9k0pW-)7%%|Gb&jn)Se|W3Rxp7CUH4MmyXx znq4p1Nz-OF#eLcT_o)|eqjgPxAgi(jDDS+14%B~*dW=kvT#s&OMeF?P(1pvFVU58m zs@A?W?tMpUAKht7H;uW17VS@i11W3i_DgZ-w01h2v|dM-+a;o-Gt<HRiVY<O1m$L> z!Gt?YY0d2`sBKz0RR6N1Z4wBoD@})aw)1G?b~)%o&kPtEyO54>%SVyy?-CyS=g`@W z?xA7Y88C9ld|G654=vWsfUw&ZG^p@Ba(<K!!*v%@^ZYkx;+u46b$todFHpvp=BGo8 z?v~Va)Gu^#S30O4TthGUH^R1;)8Nv|wbaB>89#oN29}#_=msZc+*F<YU($^&^iJwe zbZBE5`}@yMnvnMn?MzRFfxUOo)K{-jMXxl_xVD?_zEy?pUQUHR;k#%z*<IAJ1N;B4 zO}pr5wQO|gXDVo&-a#Xy^3YK8G>FvOLXU(ny>oWI{kdihh5J{~uy<)NX!|nyp*um& zo72HbYXNQkIuFShCaz~K=-IHl?0bai;1MyO>gvBi_q-TB{!3|($e(C@*K}xle>J_V zuZ(wkror{en`uJ-pQumkG_X6ioqElFjcjNtZ0Wj_ehRNb7cZv5ww`u$Yuh|j@+K7= z7H6SebTT$?5d&8$ub_!d2II83(a>ybEP52)3AZ^Qhtls9C9?0mox}uQ)m5N%J{|Fq zf+(1Dpcplq{{ub!oeYVWo8pkMs(5~K6fAAj7+Yu7p>wa2Vat9^yvn*K?lveIG|GG8 zZ%tJ2x@B^x${m0WdK=^D2hp&%b3a^6HSy2(tjBRz+&*v?uC$JU)t()3<S-fT6-waO z@2}|5qXoE~Lkvs}d57#B&G7O#BFUf6lV1zJ#;V&5u-W0^I5{|4vKBsnK4(5pJ~uue zeqJ88{nsC&m(RQ4%nNb}R%@RAM(f9^;&1kH306ElqhGYdDcjYt`5U<eA0CsV^asLS zwQ={}M1o1dw-)#v)5(3@JPkbWe?u)__QCJj`<C|as?o*dcKBFcD(q<b3k7s(hCPp_ z0-q0medCyiNUvLG+~pAg-sacEkL7dbbKqn0_P@sR>vGcnf!rqzz?<h#;A8SOKQBL) z&y&xekICEr8XGsP1l0}fj?4C^K(WRPG<Jb5*8axM(C8Gjbtd2e#Z+RiO^HAqdJn?a z7f|5G^7!-n!pG$8|I1h&2YxNQ&Bx^D<uU15eI7-9)yDP#1WXEZ(60dq-)KQ4HXoB8 z%je0josY@e{~9~Q&IcLBOvJmN#=+zjQOM`+0$e^n9vTe0gmfb;@Wx3}`|j8vbjNla z?sSuBG;w439QZxrWAgU@Wh{@$zw+T@^7Hazc^vrsd7F>_ud)0Z`TTjCkIB!=*8{(& z{9L@vuZ17W?<3#We4X<)Unl(7tmN}3<+v%nvyZahEX1Py9}V%`ohdMO>J_A1X@s}1 z_cy|8FALxC#@&)BJZeGFir~Tc^~h9c@+BR;y*d=f4@!m8>Nn8OVr^{ZlM1(U%8}7Y zJ=}c<yMEy%+IdSGe`NRG?Gs+0DN%a(+MHDA>8pgz69(hLe0HDT=Lc$2G88{3VRI>~ z;Ln{$;@6KTJiXWe8-FyyCM{B6?~ulLM7k-qeNDi-K?5uwY=++(QRsg02Qu$A30LV6 zSg_y=x;<qgzIc?t+~ZHs#i!G-+f6yRcsxcv%ctTAQwUh779rWaX}Cg(z=V(zw0$A_ z*84^R6+u_g3gt=oR|tDANG}B?jhKiJek3qz?q%eXJ_@@prcie^0V%s0;+um~;G$JJ zs#!AxcV_Q0tshp7bZ6>f=kBSH&Nyn6f}>s@`i>gy8G^w!1+J`NYl$$#vF9nQN>s)d zsz>2@_XzyR`i!!Ej$?mcBhc|v4cgs)GCt4Fofl0@(At)hu}V7vSAr-y{d63D$M}JN zN0fihlYbYKe_yoY+)-4s=qt)E&w%aSr%-uJ4Kiw)2_<h$X!ewBbfg)3|3_yy)!tBr zv?|lVt}#&ar?p6FR*K~M=jY>TZ<A7F?3oI@ZJR%d)@E0rVT_;ov0VmFq!A|@;Zx?R zz~{iv#oPZH+wIdFTHgNy`|eCCM6{npyM?_*_Yb5=V)F6%dHJz?o_zj%Oy2(2*r1xp z)bMEva{Q78rm7ZHd)!^r`*S+na@s&Yv1fk+WvM-6t`%+A<uvkZkOur%9)Esc_?W!? ze;Lc;z^{e3`I!8?JSJsY%jmN{7tq3a?C***t?8q^1xU#vO=9yg`LTSS{Mz}Ly#24S z!w&4H1Fxr}oFxh1rhbsB52;4hi?6`OAs+Pbktb-xG^yP!crQI<kc<4MCjdW|&w<|~ zJ|=JfU&iv7{3{<mCO<DfmdAn5pSSt={~F7$k<XvE`I!8?d_C}c%Fo5y{95?2{66x1 z&DS|^^L4_HZR)6klJ2&{B`GUGYjaB!u}K}rB5T-Zwh?t1+8R%uyAIxe(m=_P%6R{! zWzc6wFj{&@8E^Z#n*Cn;EP}VC$SiO*M7GvOt$Svm<v~kfMnQ)D2Jg{W`G-5KEp$h{ zK90bzV?1E^B7I~UZH)6n9N=ml(eL#N@Sxwjq4azfN?_lOO8x2py_Oar`$#RkCd&hQ zFniLm&iHuH0Z>|8jv~r_qc;5<;fY;1dZ?#|)h~I#oSosw&7db9s(%n7GS=&Vt!RRe zK3EK1e(w6lfgSOx{mX%0Bfl;_PDZvn`n;ewww!uU60?m*5PI}f6Q7QE1gz3V-*#IT z3XfkTi9cfgG5ud*eQ==rI^g|ptqIfbylwz?I&u(pn{6Z_o;^0VBqGjAjw&Qofq(5M z4I<)vs<k#zQ{Y*u!d{+L;H<tQn27ifT%=D#JXbKS6%ps6^I1g1^ZlZ7BI4F%X#o-O z6l@XaYP)dqT!E+g&Tt~)$>+xB|1bZPY<D7J*vcb_h`90g<Y`s1c1taAzn@NEGX0ut zStCQddxsO0w~)&;?~TAK44h&4ni5&g?b-OmIcN5J;hVDlq08`qod==IkB72l&a3cm z--ED2^|7qem6iAx)8gZ=^Zpq-9>@;cFT;V%XN~e)H0tp3dVhW_@1r|%HcFVi1luwH zsfF`U{NyF|^Qw4RplRkS@MktJABXo}>NW?xe!m8{`EdwdqB@zz&vm#NvzLvolQnH- zjbpw@^B;I%4pLWITYsI8KPO-YY65ex9>a&f&gYX~JR6O1omr2M%D{1G)5GC-Im56z zbQ1dMJ{-3i;S4$pg3(Xi#rQ)<Pxxeb1i3$+iC67*2E(W@<MPURcn-6#XKXT_;J6(B zWIokT#v8xfVTc2lJ44@QQAV;>!?AC{LD<ys2pY3<5I)K5H)p+2)<u0>#e8_1AIsak zPweOb)Meoytm@<k5%2twZChP@<N8r(bjdQQk;72DyXYu{Z?wKTxzTWZZjT?#X?p@0 z#981jHhvIzC;%;gwE`!s_JrQY15sRGOQz}J53`l-885rO4pVl$>Gc#N-5E>j{q;X3 z8qe2VUGEd+=#N%Bn~AkX2f(SpM-XZ_8M~f20{Jy^<Fw23@DO&r;?@b{gPwqYy$z7$ z7PZC`efl;M_j(r~$<q}!8h>kJULPl8{}t4^ReKuzBNV)JUf0`E{X${sl20ga%2#r- zM;KgVK7!q+RX7O#1CvzggW3?7xaD@ey=h5Ey-zpWFXYzz5XcOvK!V-8D!Bf-#;R)4 za={50(6<H&wsG`vi7mtzeRh3ljps(Sqh<0C2sUVkjXl1Q+h>l0Z(IXxWuZz(bvOo| z>y_|<*w5tj(IA+%p(#Fb@;))187#3swJD32D{{8G{3c#p;}YZA_}+^AJGhm`i#dBu z&WIOt;O)&L`eH+;W>m#F7|Qi};nu%vNUIGYP&BqP_RMTf*WM0<>EB!76J0-$TMGlB zcYifp;8967bUr4rBjXLRwQDsQy!sd%JU;*@vUhq1?+Jz_a|h#yVNVF!9l*ZDp^o<t zzDZ6zKMDr88y<Qho4DQ&l-OEUqp=H(B()ENprNHM-ahIK$!`}7kA7o3>wP47d-Et* zm}}!*)@R5VtD~@4SskwrKSR=N0wwm{;u%<NMX>RvQO6*q$Owmx@i(^E91JI{C*!A` z0*xIE0-#ljAs)Za$2c$bDEq$;UA(HFm+{!^ffBp3{|tP%!#!D$SrF9u8sWKHf5?_D zI0j{dCu5&J2V`$uj>0q-LwxMV4%xQuM`4-1F21C8Np}B7fW-c-HUqyIG!cF369BhW zjqthiYtfd>07#0Ngj?*dm6e4b0X-!{tl8zd?9hfIF#duL)@0w^xU%D@#J2A>9Yc2~ z<S^G47WW*9FAVfYN0#^kl261Vzp10l`Mwa{dIVlMx-FVx=?eu!8@tY&g%Vas?WpY* z=(g`0vi6i8#4&rwvu5;?O+dYE)Sxjf2?+qfr|0x1^*$diCjRIDiP^lrX!9|7f58^x zd||d2pO15q%{A+3ds_NE6a>50rwe^PFs$Bg=B!L>Yr^a8FCj`4nf<XvA0Z}h^Zug! zzdqtz!gVpGV2l1j4%*=zDQX>3KkqPk8){+r#}=;({{ON?|FFYj(VdR1XvfY0@bgsK zfA()?U$E^)Lv%vmB=Zq%<%l$d4BOCxzz`6|iZ<`VkL7)iGk>ew4d|480rg|WdHJ!t zj}S-n=X2w8=6(3w_#F7L1^cfMk&6Ud<S53s^|rvbjEC!e1RfTAM82B4<#xR-@U3vY z)nC3PBHs$vMIK{(TW<?|`>*Ta2JNWGvCbb_)9DKC4UB6*IliR=-(L8`x76n^-~MM; z>Gfj2kN(4rj5DdonT#jteg#j?{oaalJV`m8{Ll71KY+$7xRG%t6*+U|+`%+J!IP(Q z)v4WIo}_*M^5lOu<3?(u;6}!obeDoNpZ~^m8so{Ye|VDa{L7Pc<zJrs&t}|6+l>9g zjf^wtAq8hLo}{Zg|HqRw^)FA-TYq`-KbvtQ-K^k7#+mf8f-@OU(zw4oNw5FqNqXZi zPyS~!Zlp;HZe*NEmGu5_=Eayvbcli{wUi90>0h3tdVhKHKbvtQy`tbo=U&t4c*dDq z8D}z{q!a$~B(?d=lhpq&PyT0L-EKido)m16$0)N!9uw?=3jX|hF;U_#j^%xRF`xgJ zKY#rv^AY0<F~xb)*jyrC3AV^rf-Q2OV2k`F#1ws$E+tBQcz@AH@E79?{$d<{EFV*t zOXNVo7I{zb=dX*laQ*+~6L)wl5&7y8vqe5^8j<#&-I&>;PcvqZQ1B%0!;ckWiu}pj z|LY^hJkR_^KICmaH$DdymV@Ze+q@5-8=rIOiiY@sYbsd^6)@#aCwzU6S@K5hGI;t< z34iTfU|eO%ep7SeIjXYtC!y;rLHTlXd~Wes)V)Okn4fxpF8M{Gh>1mD{w*JESzL$O zKhJ?5T_VspottRJseEW=HxG&Wbp>{=`US7s<C}?D&_idHex<B2R_dM$8m~tobKRdv zm;F|h*Q>0_D@GR;8p6vrWuh*#D@by`8^GKCjjqLKXgnrnTW<VwET2C=mR}>kmg%ia zQ0WI3Wa^&}?*6sN!lb$U!2J@*y7-)3O$H&yoC=iSlnoJAk0Sl=@u;_6u4IkN-woG~ z4Ss~a+|2@hT}<N<i<+^|wrb)!g=XyP<vnpzruFK<v|iQJA0a{0^%K){tqAZ&qK+${ zCqJ+E9Y++G6o_nJ<w3!l%P2i!35qybAi?eGM|~t~TTHNT1@IX1YvFS?3~!+Svr956 zI+F|Aw<{s+9*-`T<x23Wy?X<BoAi>;GQSQ(EyGdAf)Jt>Qx0DGG``Z}CV5_2!8BF= z&ii<38#K2(lax2U4ed@|jBga3O)@oaOZ@q{0`==;(?&+1VONXb{BA2`9O{J(?26%E z>uvbtINCpdI;v5-4xSUQAvcHj$;0-P1D~hX;tu*#YjRQJPWiC(UTgj0^h`A9d?75q zS1OBT-(bI9TL_^St7L~}rlA)m?ESQiqv-H)Pcm5bmSm0mT2zgzWX03Zku_Uxf&H2A z_@t_6vef66WR3h<dc3(Vdv)0lou5z)yQfV+W}Ua9U*k$7Yvk7wdd3Z{zMzj5##{&X zqe4{q{93YnQMqJ|r|K>ban3o03RQ}s`Eh4-a)}*D+ILfuKfk9u4*Ys~{CS)A;j!Y^ z#b4*K<uT#0x;eZ^7JBOpv9+&&X})3cS$(5Op?8G@6CSG_W!GdK&LI@2S_B7_WysmJ zEvmg%B*BEoYOs$3no<%gTbWu6yQ+?%%;Bfy=}cdU$13V-#NhoA<5Ak<LJ4kLlx@)M zn7!oVigM7|=#94KrXVxfODOOOM3$egqTLqHp-5#hBK^Lho#&pz9anplc{Lwhh^vFa zPCsQ9#Wg4^<2B5eWy;hqw8WtsUVz1VC;i$1YItwr3z*?;s{h)j4z)S`2C|c9A@Adr z$jtK<B+fTLP7NC2Z*QMNESr<=K;(wQYnVKt1f`@+CAa6kgewm0ogk-uvYSq|FsxBJ zTG1>_mU`(GJUSDO-r#klAm9yrxEhPDHE<^vo7aKX&CK}Cw;mGRxL5GY!W^y8xJEwp zdj(gTo1lkx0@$}i-$8Ag(D(^CXUJr?_duq4B09KI7TEGV-0=uRk;5C3k#F9CO~Gko z?(tIIq~$v>U3UtNSehZzDt!xIohHUVEbBy`2Y!NfWA)j$f!mXF<3EDm!=b3m@{{aE zvyZSp`AV$DxrWGQ#V1Lge0<f?GL#=Nl_<@92Ib2#P>jPC+4JL1;gkLq)Z50F+;n&b z8AcWHm6LywqtVY`zs&-a=Uzd!oqP7rJ(8@2+oP1Eqo_ebBKoTL1mriYWV460#yuD} zo;YhLb3fA?hcCVd_rFHSVt@6*wR7&mnfPki6!q44ZA1m6H+0ai7}Xj-^r?X94ng`) z-}lCmhws6dh(LXx@xAdRoBMEg)i(WNXn}X+K7x~H`^b*%XpFu0KB}MV0chgJ-|j(m z*?pOV{&%#o%|j@!DUumo?SXql--XY<D(Iq7i~4-L6Z)ge!FlMrO*#Cmn2r+e+(YwR zA3$l}87RQ=B&u9fA*sXB$L6CWj!Jmyl_y}IEtie9Z-Y-3J%NKYuKIqXJ7CZ2Phj%V zVQ7nHQ>>r=1OldCN4GqOlZ+b=;mKY0&e{}L();#97_zw_e#*^P<k;hfQ1N^LGD^Ef zhCXCIHxp6H{&mUL&F+A9w+v+HdeOLi(F14_l@fnD`ZfufbRQBwOhx@wFOzEdz4~?8 zYqrE2(#yd5UL!QZxDZVUFM|u`_R5;5Jx5Irm)2t<_=N2(gR&J!|MKqV$YXvf6i3+U z3)fezC<A_7{NA~(wMFaKT|i}Ro`BxI0mwL^1|=?#uKj_&gUr+9Gdecs2{iSYrSFjQ z9huFOVp48;8qN3Jhu%M_0lS^<sA9uzG_>Pm@aPqeCQuJl(DD(?Gu?|ujdMezhdhEB z2QT#PaXj+>_y8c!3hg%tLwNo}$sT<P?vIo|B%#@z9!lcybM*`hL963?p>Z)cB{4sC z_eA}M>_RhrD<yTZ?+1~MdQpOUY=0=JE56<?^|8=*KlTfe-;dzwkQc^fE}u~at3!TY z`2Fe=9TmT^YclDUbQi|N$k4SrAtZm|UD)n&8eJJ~OB!Fh3woFQQN`Ouq|BuXX52l6 zVtaZdr`FyAk8Dpgsdq>AJC{l*=(iEo_F9Ifn=?M&X~g~x6olIME(dG*dD;7Ct?_fK z8z9q}FH>f=nc)rSbk<Q{^=WI|g5Bc@^)J?m(2rt0@cw)pzBc$cd=Cn7#9rh3n(tY@ z@A!V_dywyao>zHZ;yIk}FP_i&{^GIa{Z)hC%5vJiMN2K7z>Y0}@$+ULCs*%Pf&Zd` zsMit?;&7-+vPb;h@q5&%n+wWHnnDhKyaRfze2~`i@Z=E(Zb|m;?VVkyhkr|y)2tFy zXU|4Ox2K~w)#Z|Xl<aR&Z`8ul2iXSRknHcvCpTpdd!kUk=zsTkmG2nY`}T>bYiDVX zKk{s>zjPHrL#s+9_W=C8!Q4sjWaMQ4QS!VA&6@?s_goWBD$d>n{)`TuZH@ZZtS2pA zRZ7l!{vP1=G8dHZ=q`&pT?&`R`=Iw~bLB&tl!N2`m1wJaGRpL?f%jSLyVFM3(d1c= zf#;UoMmx|=>sWN7`D3V<_fqC6W6wV4A48m3q^$B&ExHAdf#(^1AL~kNWiLNILLG8y zV9cV9vS78>=;*^52+Z3cTc3Cj-MKIA(`H_Mk)HoU^zQOw38y7iCdkI0%SB$JYGCh# z3o=vF9Q07B2BubJ$Qs%dpcY4JpxJ{uS#8^5l$%`x*B5t37b6OhQDF@Pj~t9lpJ$^P zVKq>!2B_(>G_-A64ScCthsq3Nk#o%>*gk$N(m9!o=BU;{o6+{j{B{H?RIh<M?`9*E z5r_01u(RN;F<KUxib_hQe8_Vk&!0R8-kYz9=6uRW%8`$N=dsK;wX&0XMd;V1N5FHJ z#<i*XD#JgcF3)P<@&<kMZHX%S;dLD*?zE7pT3e%iu_eIQUIAC1e9ix>&iS)o+nEk% z*1AOWfnmb;4&QftKl1mV{Cz23=MU!39OAri7kiE?0scOdulfIvvab%S>iND#0b5W6 z6a|qG#6%RSJ2NUM*j?D&iQR;tpeP7-3ko)3bM_ny?C!$A00S_vKE^u-&yjt<&(A;J z|MoM_o;`cktXVf$+;evGC-FboVMoU|$YMbrxg=|1@Uh)vUNMhuAIQY!y`;-luUNhB zpGc#MvUIQJOExyVfY^U8kiG~mHLdoEtR7VyV(MhE^{4VlVC6jN+OntYxBpu*zg?<y zP4|SgDf5a1yD+IkugC0(+cPq2!X2-S%8yykmygJM^L9GF(T~~Fi4VxHq@%jjK2KQj zu=`}(s}H)s!%x{U<A>xyyW-?>rz}>z)MIjXWxj6A>*p-%OcqJsbwKAvU$Uhiv&k!K zo$jjBD^}d|Eg3aroiwc=Td#k-FN04n2tAZ=Z1kKQCOhSm^oC`j|7!g`mM_RB&PyA@ zh?p08`?b!<C4F`h@N>`7+j~>UA#+~UfmIKm=;2_J`Hak2R1AJR%hbcfsqO=^Z%>3| zlJH0mpDu@P5U4xBySC3GJ*>t>T_U$Pt<)Vn^+*r5mSN{e|IpIpL{)tZ_suv<EREer zPn)NDcvc^Jo_t=^lq3aZ>0w)}=@l}tr7Ouxf1!u-Y5UtG?1(YBz+dTMeye6CDFu<b z+)_Du`0pC>l+5<uBaMs9VZ#o+AQMMhftN`(+d2C_Iezrhu`ktMv+(-q<hN<Vw2<i6 z><YU`ynR4=FFtEL-F}rgxH>|uf!XY8%u6!rV{?eV{X+N&pOgMiJ3wdOELJ)A8nNHf z0nV0r$x6ICPj3C}1GT$mv8ctFq<n83v_9~JmH%>^{BkpaH%l^^Y<`rCZx;Zowmf0~ zbx0w`yfRc8kjWMXUnWzht&kELKVlO*W{_r6ti9p%LuP;L2<iWAi*)GoLpE~8KJu-9 z)}e1951G+InZS(Ax+#H=*rh6IB=$xnQtxUe^H`ir%vvYtCfYq>y^Iox>8dK^#EwkX z>Elu2@|+P5gQv`)qD1cQ>p)mk7Ta-mD`C%Cl7(NMu<3@|2%p)5q-@P%H%Ff!SN<d9 zp?D8j()b*yzSWe3cw{rnc{|CzyM9F1<|RAfpGuM}&56~LY}P098iCTwb*ne#u+&}> z3EdE<^Dgz8O?@}UtxQNsI^p#j);wmh+t7k4baS0|EGlW3j$E~+1!iy9{?03OEiB8? zSqpMlOP_dMx1PUA?7oj|c1EDvmL3K)>-0xvansDL@v}3eMVk+-smOUZJcF!r7oWLM zO`MPG;I-yHJ3@33A4s=|d{#N`207Jb73os?9XoG#oQ&^$fkfM8Gsj<B$@nQ|bhrC! zRs&X%5hEXwYC~VK#jbluncs`ZuiLqLJ>dS^?vEuV6D!kT$A8at>b!;ATm69yOn=XC zjOSw9aD9ve-V5#-$9P}IhMXi1zL}8wK`+>y`xi*BT88BF{uiw7*gItA`uV!}PuZ-r z#Wm8n-(X$A{2YesW2}Pg&yx1t+UpWB#pm%QKy1ELCSF5c=*`77asI#7#l7L07=JwX zkToSEK70h{O;6c(hx_|a>WXv2D^FRg*6I7lEy;o_2~XLCN?pjf>uIoa`cu}xbJPBJ zM#->!%A3OcG?A~wJ!blldr==CtLhsT66Zh$uw8}msgjXoVu>}-qxn;|xYrhvv;A^m zd_QmtF<NsOvKzi;$4w*2)K9D7V58S8W%?2_2A0FjE>Fet+jo(rlcHeGr6;UY$#l|j z()Pl*tWzS%8GfcPM;pI(@zvjaCGOCD32Aa=IUG8g!**3pB+k>%KtCym;ePO1xaPn5 z#C33e-2aEs$4NiO{_v#j6K4GMKCx;&RWCky@&(g!l-Rx<C#&xMmZUw8Sp{;BJga96 zO5E>#4)M!2hwZk{*?-bSvTK`ZVQlP3$)I!p!Ri}N+3RJQ``yxvxmEFJtbO$jBrW4E z{5Rz(n=;;;Y~K4FwqAbCb~$Yzzr=X=4>@ek>dgH%CyjY)$2Tm0@r(UeX<6>J{3U}{ zIx@1lA+Or$rCv?E7Op?jegknnlLhq-ykPx2¥CQsG^z=YP*g!5?Gw<$VI_JmES7 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⋑u$(u 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≪dc$8as4XHI<|^9P1A$11Fx%K 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%0AUcYQSvu!p`*tsw7 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⋘r{rTn{ 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/data/Verve/gui/VerveCinematic.gui b/Templates/BaseGame/game/data/Verve/gui/VerveCinematic.gui new file mode 100644 index 000000000..f71a3171c --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/gui/VerveCinematic.gui @@ -0,0 +1,43 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GameTSCtrl(VerveCinematicGui) { + canSaveDynamicFields = "1"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiContentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + cameraZRot = "0"; + forceFOV = "0"; + helpTag = "0"; + noCursor = "1"; + + new VFadeControl( VFadeControlGui ) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; +}; +//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/datablocks/datablockExec.cs b/Templates/BaseGame/game/data/Verve/scripts/datablocks/datablockExec.cs new file mode 100644 index 000000000..d85bb690d --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/datablocks/datablockExec.cs @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Load up all datablocks. This function is called when +// a server is constructed. + +// Do the sounds first -- later scripts/datablocks may need them +exec("./audioProfiles.cs"); + +// LightFlareData and LightAnimData(s) +exec("./lights.cs"); + +// Do the various effects next -- later scripts/datablocks may need them +exec("./particles.cs"); +exec("./environment.cs"); + +exec("./triggers.cs"); + +// Add a rigid example +exec("./rigidShape.cs"); + +exec("./health.cs"); + +// Load our supporting weapon datablocks, effects and such. They must be +// loaded before any weapon that uses them. +exec("./weapon.cs"); +exec("./weapons/grenadefx.cs"); +exec("./weapons/rocketfx.cs"); + +// Load the weapon datablocks +exec("./weapons/Lurker.cs"); +exec("./weapons/Ryder.cs"); +exec("./weapons/ProxMine.cs"); +exec("./weapons/Turret.cs"); + +exec("./teleporter.cs"); + +// Load the default player datablocks +exec("./player.cs"); + +// Load our other player datablocks +exec("./aiPlayer.cs"); + +// Load the vehicle datablocks +exec("./vehicles/cheetahCar.cs"); + +// Load Verve Data. +exec("./verve/VerveActorData.cs"); +exec("./verve/VervePathTutorialData.cs"); \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VerveActorData.cs b/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VerveActorData.cs new file mode 100644 index 000000000..e8bb3324b --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VerveActorData.cs @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function VHumanoidActorData::create( %dataBlock ) +{ + %actorObject = new VHumanoidActor() + { + dataBlock = %dataBlock; + }; + + return %actorObject; +} + +//----------------------------------------------------------------------------- + +datablock VHumanoidActorData( VSoldierActorData ) +{ + Category = "VActor"; + ShapeFile = "data/Verve/art/shapes/actors/Soldier/soldier_rigged.DAE"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VervePathTutorialData.cs b/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VervePathTutorialData.cs new file mode 100644 index 000000000..cd6c7ba23 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/datablocks/verve/VervePathTutorialData.cs @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +datablock StaticShapeData( VervePathTutorial_DoorData ) +{ + Category = "VerveTutorialData"; + shapeFile = "data/Verve/art/shapes/VervePathTutorial/Door.dae"; +}; + +datablock StaticShapeData( VervePathTutorial_ElevatorPlatformData ) +{ + Category = "VerveTutorialData"; + shapeFile = "data/Verve/art/shapes/VervePathTutorial/ElevatorPlatform.dae"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicController.cs b/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicController.cs new file mode 100644 index 000000000..0c5dae601 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicController.cs @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +$Verve::CinematicController = 0; + +//----------------------------------------------------------------------------- + +function Verve::GetCinematicController() +{ + // Valid Controller? + if ( !isObject( $Verve::CinematicController ) ) + { + $Verve::CinematicController = new VController() + { + Class = "VerveCinematicController"; + }; + } + + // Return Controller. + return $Verve::CinematicController; +} + +//----------------------------------------------------------------------------- + +// Verve::PlayCinematic( "sequences/BurgFlythrough.vsf" ); +function Verve::PlayCinematic( %sequenceFile ) +{ + if ( !isFile( %sequenceFile ) ) + { + error ( "Verve::PlayCinematic() - Invalid Sequence File." ); + return 0; + } + + // Fetch Controller. + %controller = Verve::GetCinematicController(); + + // Already Playing? + if ( %controller.isPlaying() ) + { + error ( "Verve::PlayCinematic() - Cinematic in Progress." ); + return 0; + } + + // Load the Sequence. + if ( !%controller.readFile( %sequenceFile ) ) + { + return 0; + } + + // Stop Input. + if ( isObject( moveMap ) ) + { + moveMap.pop(); + } + + // Store the Current Gui. + $Verve::StoredGui = Canvas.getContent(); + + // Valid GUI? + if ( !isObject( VerveCinematicGui ) ) + { + // Execute GUI Script. + exec( "art/gui/VerveCinematic.gui" ); + } + + // Set the Cinematic Gui. + Canvas.setContent( VerveCinematicGui ); + + // Clear First Person. + %clientCount = ClientGroup.getCount(); + for ( %i = 0; %i < %clientCount; %i++ ) + { + // Fetch Client. + %clientConnection = ClientGroup.getObject( %i ); + // Store Status. + %clientConnection.FirstPerson = %clientConnection.isFirstPerson(); + // Clear. + %clientConnection.setFirstPerson( false ); + } + + // Play the Sequence. + %controller.play(); + + // Return the Controller. + return %controller; +} + +//----------------------------------------------------------------------------- + +function VerveCinematicController::onStop( %this ) +{ + // Reset First Person Status. + %clientCount = ClientGroup.getCount(); + for ( %i = 0; %i < %clientCount; %i++ ) + { + // Fetch Client. + %clientConnection = ClientGroup.getObject( %i ); + // Reset. + %clientConnection.setFirstPerson( %clientConnection.FirstPerson ); + } + + // Reset the Canvas. + Canvas.setContent( $Verve::StoredGui ); + + // Resume Input. + if ( isObject( moveMap ) ) + { + moveMap.push(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicTrigger.cs b/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicTrigger.cs new file mode 100644 index 000000000..4cd6df9f1 --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/server/VerveCinematicTrigger.cs @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +datablock TriggerData( VerveCinematicTrigger ) +{ + Field = "Value"; +}; + +//----------------------------------------------------------------------------- + +function VerveCinematicTrigger::onEnterTrigger( %this, %trigger, %object ) +{ + // Play Sequence. + Verve::PlayCinematic( %trigger.SequenceFile ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/scripts/server/VervePathTutorialData.cs b/Templates/BaseGame/game/data/Verve/scripts/server/VervePathTutorialData.cs new file mode 100644 index 000000000..264fec96f --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/scripts/server/VervePathTutorialData.cs @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) 2014 - Violent Tulip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +datablock StaticShapeData( VervePathTutorial_DoorData ) +{ + Category = "VerveTutorialData"; + shapeFile = "art/shapes/VervePathTutorial/Door.dae"; +}; + +datablock StaticShapeData( VervePathTutorial_ElevatorPlatformData ) +{ + Category = "VerveTutorialData"; + shapeFile = "art/shapes/VervePathTutorial/ElevatorPlatform.dae"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup0_Open+Close.vsf b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup0_Open+Close.vsf new file mode 100644 index 000000000..d3305688d --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup0_Open+Close.vsf @@ -0,0 +1,85 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <Properties> + <Time>0</Time> + <Duration>1000</Duration> + <TimeScale>1</TimeScale> + <Loop>1</Loop> + <LoopBackwards>1</LoopBackwards> + <LoopCount>0</LoopCount> + <LoopDelay>500</LoopDelay> + <ResetOnCompletion>1</ResetOnCompletion> + </Properties> + <DataTable> + <DataItem Type="STATIC" Name="DoorGroup0_LeftPath" Value="DoorPath_Left" /> + <DataItem Type="STATIC" Name="DoorGroup0_Left" Value="DoorShape0_Left" /> + <DataItem Type="STATIC" Name="DoorGroup0_RightPath" Value="DoorPath_Right" /> + <DataItem Type="STATIC" Name="DoorGroup0_Right" Value="DoorShape0_Right" /> + </DataTable> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Enabled>1</Enabled> + <Label>DoorGroup0_Left</Label> + <Reference>DoorGroup0_Left</Reference> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionTrack</Label> + <Reference>DoorGroup0_LeftPath</Reference> + <OrientationMode>FREE</OrientationMode> + <OrientationData></OrientationData> + <Relative>0</Relative> + </Properties> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>0</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>1000</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + </VObject> + </VObject> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Enabled>1</Enabled> + <Label>DoorGroup0_Right</Label> + <Reference>DoorGroup0_Right</Reference> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionTrack</Label> + <Reference>DoorGroup0_RightPath</Reference> + <OrientationMode>FREE</OrientationMode> + <OrientationData></OrientationData> + <Relative>0</Relative> + </Properties> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>0</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>1000</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + </VObject> + </VObject> +</VerveControllerSequence> diff --git a/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup1_Open+Close.vsf b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup1_Open+Close.vsf new file mode 100644 index 000000000..a1e0e4d6c --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/DoorGroup1_Open+Close.vsf @@ -0,0 +1,87 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <Properties> + <Time>0</Time> + <Duration>1000</Duration> + <TimeScale>1</TimeScale> + <Loop>1</Loop> + <LoopBackwards>1</LoopBackwards> + <LoopDelay>500</LoopDelay> + <ResetOnCompletion>1</ResetOnCompletion> + <name>VerveEditorController</name> + <parentGroup>RootGroup</parentGroup> + <canSaveDynamicFields>1</canSaveDynamicFields> + </Properties> + <DataTable> + <DataItem Type="STATIC" Name="DoorGroup1_Right" Value="DoorShape1_Right" /> + <DataItem Type="STATIC" Name="DoorGroup1_Left" Value="DoorShape1_Left" /> + <DataItem Type="STATIC" Name="DoorGroup1_RightPath" Value="DoorPath_Right" /> + <DataItem Type="STATIC" Name="DoorGroup1_LeftPath" Value="DoorPath_Left" /> + </DataTable> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Enabled>1</Enabled> + <Label>DoorGroup1_Left</Label> + <Reference>DoorGroup1_Left</Reference> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionTrack</Label> + <Reference>DoorGroup1_LeftPath</Reference> + <OrientationMode>FREE</OrientationMode> + <OrientationData></OrientationData> + <Relative>1</Relative> + </Properties> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>0</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>1000</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + </VObject> + </VObject> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Enabled>1</Enabled> + <Label>DoorGroup1_Right</Label> + <Reference>DoorGroup1_Right</Reference> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionTrack</Label> + <Reference>DoorGroup1_RightPath</Reference> + <OrientationMode>FREE</OrientationMode> + <OrientationData></OrientationData> + <Relative>1</Relative> + </Properties> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>0</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>1000</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + </VObject> + </VObject> +</VerveControllerSequence> diff --git a/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/ElevatorPlatform_Up+Down.vsf b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/ElevatorPlatform_Up+Down.vsf new file mode 100644 index 000000000..33a0e9dfc --- /dev/null +++ b/Templates/BaseGame/game/data/Verve/sequences/VervePathTutorial/ElevatorPlatform_Up+Down.vsf @@ -0,0 +1,53 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <Properties> + <Time>0</Time> + <Duration>5000</Duration> + <TimeScale>1</TimeScale> + <Loop>0</Loop> + <LoopBackwards>0</LoopBackwards> + <LoopCount>-1</LoopCount> + <LoopDelay>0</LoopDelay> + <ResetOnCompletion>0</ResetOnCompletion> + <name>VerveEditorController</name> + <parentGroup>RootGroup</parentGroup> + <canSaveDynamicFields>1</canSaveDynamicFields> + </Properties> + <DataTable> + <DataItem Type="STATIC" Name="ElevatorPlatformGroup" Value="ElevatorPlatformShape" /> + <DataItem Type="STATIC" Name="ElevatorPlatformGroupPath" Value="ElevatorPlatformPath" /> + </DataTable> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Enabled>1</Enabled> + <Label>ElevatorPlatformGroup</Label> + <Reference>ElevatorPlatformGroup</Reference> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionTrack</Label> + <Reference>ElevatorPlatformGroupPath</Reference> + <OrientationMode>FREE</OrientationMode> + <OrientationData></OrientationData> + <Relative>0</Relative> + </Properties> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>0</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + <VObject Type="VMotionEvent"> + <Properties> + <Enabled>1</Enabled> + <Label>MotionEvent</Label> + <TriggerTime>5000</TriggerTime> + <Duration>0</Duration> + </Properties> + </VObject> + </VObject> + </VObject> +</VerveControllerSequence> diff --git a/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_P.hlsl b/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_P.hlsl new file mode 100644 index 000000000..4780388ec --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_P.hlsl @@ -0,0 +1,94 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Base Texture +// Diffuse Color +// Deferred Shading: Empty Specular +// Deferred Shading: Mat Info Flags +// Eye Space Depth (Out) +// Visibility +// GBuffer Conditioner +// Deferred Material + +struct ConnectData +{ + float4 vpos : SV_Position; + float2 texCoord : TEXCOORD0; + float4 wsEyeVec : TEXCOORD1; + float3 gbNormal : TEXCOORD2; +}; + + +struct Fragout +{ + float4 col : SV_Target0; + float4 col1 : SV_Target1; + float4 col2 : SV_Target2; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform SamplerState diffuseMap : register(S0), + uniform Texture2D diffuseMapTex : register(T0), + uniform float4 diffuseMaterialColor : register(C0), + uniform float matInfoFlags : register(C1), + uniform float3 vEye : register(C3), + uniform float4 oneOverFarplane : register(C4), + uniform float visibility : register(C2) +) +{ + Fragout OUT; + + // Vert Position + + // Base Texture +float4 diffuseColor = diffuseMapTex.Sample(diffuseMap, IN.texCoord); + OUT.col1 = diffuseColor; + + // Diffuse Color + OUT.col1 *= diffuseMaterialColor; + + // Deferred Shading: Empty Specular + OUT.col2.g = 1.0; + OUT.col2.ba = 0.0; + + // Deferred Shading: Mat Info Flags + OUT.col2.r = matInfoFlags; + + // Eye Space Depth (Out) +#ifndef CUBE_SHADOW_MAP + float eyeSpaceDepth = dot(vEye, (IN.wsEyeVec.xyz / IN.wsEyeVec.w)); +#else + float eyeSpaceDepth = length( IN.wsEyeVec.xyz / IN.wsEyeVec.w ) * oneOverFarplane.x; +#endif + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // GBuffer Conditioner + float4 normal_depth = float4(normalize(IN.gbNormal), eyeSpaceDepth); + + // output buffer format: GFXFormatR16G16B16A16F + // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo) + float4 _gbConditionedOutput = float4(sqrt(half(2.0/(1.0 - normal_depth.y))) * half2(normal_depth.xz), 0.0, normal_depth.a); + + // Encode depth into hi/lo + float2 _tempDepth = frac(normal_depth.a * float2(1.0, 65535.0)); + _gbConditionedOutput.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/65535.0, 0.0); + + OUT.col = _gbConditionedOutput; + + // Deferred Material + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_V.hlsl b/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_V.hlsl new file mode 100644 index 000000000..a323a9608 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/76d48535f69be600_V.hlsl @@ -0,0 +1,74 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Base Texture +// Diffuse Color +// Deferred Shading: Empty Specular +// Deferred Shading: Mat Info Flags +// Eye Space Depth (Out) +// Visibility +// GBuffer Conditioner +// Deferred Material + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float2 out_texCoord : TEXCOORD0; + float4 wsEyeVec : TEXCOORD1; + float3 gbNormal : TEXCOORD2; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4), + uniform float3 eyePosWorld : register(C12), + uniform float4x4 worldViewOnly : register(C8) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Base Texture + OUT.out_texCoord = (float2)IN.texCoord; + + // Diffuse Color + + // Deferred Shading: Empty Specular + + // Deferred Shading: Mat Info Flags + + // Eye Space Depth (Out) + float3 depthPos = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz; + OUT.wsEyeVec = float4( depthPos.xyz - eyePosWorld, 1 ); + + // Visibility + + // GBuffer Conditioner + OUT.gbNormal = mul(worldViewOnly, float4( normalize(IN.normal), 0.0 ) ).xyz; + + // Deferred Material + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_P.hlsl b/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_P.hlsl new file mode 100644 index 000000000..2c0e0ccda --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_P.hlsl @@ -0,0 +1,52 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Eye Space Depth (Out) +// Visibility + +struct ConnectData +{ + float4 vpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float3 vEye : register(C1), + uniform float4 oneOverFarplane : register(C2), + uniform float visibility : register(C0) +) +{ + Fragout OUT; + + // Vert Position + + // Eye Space Depth (Out) +#ifndef CUBE_SHADOW_MAP + float eyeSpaceDepth = dot(vEye, (IN.wsEyeVec.xyz / IN.wsEyeVec.w)); +#else + float eyeSpaceDepth = length( IN.wsEyeVec.xyz / IN.wsEyeVec.w ) * oneOverFarplane.x; +#endif + OUT.col = float4(eyeSpaceDepth.rrr,1); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_V.hlsl b/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_V.hlsl new file mode 100644 index 000000000..f7db2ba1f --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/7a74ac0558b62462_V.hlsl @@ -0,0 +1,51 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Eye Space Depth (Out) +// Visibility + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4), + uniform float3 eyePosWorld : register(C8) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Eye Space Depth (Out) + float3 depthPos = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz; + OUT.wsEyeVec = float4( depthPos.xyz - eyePosWorld, 1 ); + + // Visibility + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl b/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl new file mode 100644 index 000000000..560f6c23d --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_P.hlsl @@ -0,0 +1,77 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Deferred RT Lighting +// Visibility +// HDR Output + +struct ConnectData +{ + float4 vpos : SV_Position; + float4 screenspacePos : TEXCOORD0; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float4 diffuseMaterialColor : register(C0), + uniform float4 rtParamslightInfoBuffer : register(C2), + uniform SamplerState lightInfoBuffer : register(S0), + uniform Texture2D lightInfoBufferTex : register(T0), + uniform float visibility : register(C1) +) +{ + Fragout OUT; + + // Vert Position + + // Diffuse Color + OUT.col = diffuseMaterialColor; + + // Deferred RT Lighting + float2 uvScene = IN.screenspacePos.xy / IN.screenspacePos.w; + uvScene = ( uvScene + 1.0 ) / 2.0; + uvScene.y = 1.0 - uvScene.y; + uvScene = ( uvScene * rtParamslightInfoBuffer.zw ) + rtParamslightInfoBuffer.xy; + float3 d_lightcolor; + float d_NL_Att; + float d_specular; + lightinfoUncondition(lightInfoBufferTex.Sample(lightInfoBuffer, uvScene), d_lightcolor, d_NL_Att, d_specular); + OUT.col *= float4(d_lightcolor, 1.0); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // HDR Output + OUT.col = hdrEncode( OUT.col ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl b/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl new file mode 100644 index 000000000..be8a848ef --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/8625023c97ea6cf9_V.hlsl @@ -0,0 +1,67 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Deferred RT Lighting +// Visibility +// HDR Output + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; + float2 texCoord2 : TEXCOORD1; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float4 screenspacePos : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Diffuse Color + + // Deferred RT Lighting + OUT.screenspacePos = OUT.hpos; + + // Visibility + + // HDR Output + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_P.hlsl b/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_P.hlsl new file mode 100644 index 000000000..2b0cb5f0e --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_P.hlsl @@ -0,0 +1,54 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// skybox +// Diffuse Color +// Reflect Cube +// HDR Output + +struct ConnectData +{ + float4 vpos : SV_Position; + float3 reflectVec : TEXCOORD0; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float4 diffuseMaterialColor : register(C0), + uniform SamplerState cubeMap : register(S0), + uniform TextureCube cubeMapTex : register(T0) +) +{ + Fragout OUT; + + // Vert Position + + // skybox + + // Diffuse Color + OUT.col = diffuseMaterialColor; + + // Reflect Cube + OUT.col *= cubeMapTex.Sample( cubeMap, IN.reflectVec ); + + // HDR Output + OUT.col = hdrEncode( OUT.col ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_V.hlsl b/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_V.hlsl new file mode 100644 index 000000000..f4e6f087d --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/a1a7a101cca9ce72_V.hlsl @@ -0,0 +1,58 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// skybox +// Diffuse Color +// Reflect Cube +// HDR Output + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float3 reflectVec : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4), + uniform float3 eyePosWorld : register(C8) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // skybox + + // Diffuse Color + + // Reflect Cube + float3 cubeVertPos = mul(objTrans, float4(IN.position,1)).xyz; + float3 cubeNormal = ( mul( (objTrans), float4(IN.normal, 0) ) ).xyz; + cubeNormal = bool(length(cubeNormal)) ? normalize(cubeNormal) : cubeNormal; + float3 eyeToVert = cubeVertPos - eyePosWorld; + OUT.reflectVec = reflect(eyeToVert, cubeNormal); + + // HDR Output + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/autogenConditioners.h b/Templates/BaseGame/game/data/shaderCache/autogenConditioners.h new file mode 100644 index 000000000..065cea6dc --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/autogenConditioners.h @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Condition Method +//------------------------------------------------------------------------------ +inline float4 autogenCondition_bde4cbab(in float3 lightColor, in float NL_att, in float specular, in float4 bufferSample) +{ + float4 rgbLightInfoOut = float4(lightColor, 0) * NL_att + float4(bufferSample.rgb, specular); + + return rgbLightInfoOut; +} + + +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +//------------------------------------------------------------------------------ +// Autogenerated 'GBuffer Conditioner' Condition Method +//------------------------------------------------------------------------------ +inline float4 autogenCondition_55070f7a(in float4 unconditionedOutput) +{ + // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo) + float4 _gbConditionedOutput = float4(sqrt(half(2.0/(1.0 - unconditionedOutput.y))) * half2(unconditionedOutput.xz), 0.0, unconditionedOutput.a); + + // Encode depth into hi/lo + float2 _tempDepth = frac(unconditionedOutput.a * float2(1.0, 65535.0)); + _gbConditionedOutput.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/65535.0, 0.0); + + + return _gbConditionedOutput; +} + + +//------------------------------------------------------------------------------ +// Autogenerated 'GBuffer Conditioner' Uncondition Method +//------------------------------------------------------------------------------ +inline float4 autogenUncondition_55070f7a(SamplerState deferredSamplerVar, Texture2D deferredTexVar, float2 screenUVVar) +{ + // Sampler g-buffer + float4 bufferSample = deferredTexVar.SampleLevel(deferredSamplerVar, screenUVVar,0); + // g-buffer unconditioner: float4(normal.X, normal.Y, depth Hi, depth Lo) + float2 _inpXY = bufferSample.xy; + float _xySQ = dot(_inpXY, _inpXY); + float4 _gbUnconditionedInput = float4( sqrt(half(1.0 - (_xySQ / 4.0))) * _inpXY, -1.0 + (_xySQ / 2.0), bufferSample.a).xzyw; + + // Decode depth + _gbUnconditionedInput.w = dot( bufferSample.zw, float2(1.0, 1.0/65535.0)); + + return _gbUnconditionedInput; +} + + diff --git a/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_P.hlsl b/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_P.hlsl new file mode 100644 index 000000000..e935e60ba --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_P.hlsl @@ -0,0 +1,80 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Base Texture +// Deferred RT Lighting +// Visibility +// HDR Output + +struct ConnectData +{ + float4 vpos : SV_Position; + float2 texCoord : TEXCOORD0; + float4 screenspacePos : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform SamplerState diffuseMap : register(S0), + uniform Texture2D diffuseMapTex : register(T0), + uniform float4 rtParamslightInfoBuffer : register(C1), + uniform SamplerState lightInfoBuffer : register(S1), + uniform Texture2D lightInfoBufferTex : register(T1), + uniform float visibility : register(C0) +) +{ + Fragout OUT; + + // Vert Position + + // Base Texture +float4 diffuseColor = diffuseMapTex.Sample(diffuseMap, IN.texCoord); + OUT.col = diffuseColor; + + // Deferred RT Lighting + float2 uvScene = IN.screenspacePos.xy / IN.screenspacePos.w; + uvScene = ( uvScene + 1.0 ) / 2.0; + uvScene.y = 1.0 - uvScene.y; + uvScene = ( uvScene * rtParamslightInfoBuffer.zw ) + rtParamslightInfoBuffer.xy; + float3 d_lightcolor; + float d_NL_Att; + float d_specular; + lightinfoUncondition(lightInfoBufferTex.Sample(lightInfoBuffer, uvScene), d_lightcolor, d_NL_Att, d_specular); + OUT.col *= float4(d_lightcolor, 1.0); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // HDR Output + OUT.col = hdrEncode( OUT.col ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_V.hlsl b/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_V.hlsl new file mode 100644 index 000000000..3d55cf201 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/b524839793fade4e_V.hlsl @@ -0,0 +1,57 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Base Texture +// Deferred RT Lighting +// Visibility +// HDR Output + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float2 out_texCoord : TEXCOORD0; + float4 screenspacePos : TEXCOORD1; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Base Texture + OUT.out_texCoord = (float2)IN.texCoord; + + // Deferred RT Lighting + OUT.screenspacePos = OUT.hpos; + + // Visibility + + // HDR Output + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_P.hlsl b/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_P.hlsl new file mode 100644 index 000000000..e85bd696f --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_P.hlsl @@ -0,0 +1,87 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Deferred Shading: Empty Specular +// Deferred Shading: Mat Info Flags +// Eye Space Depth (Out) +// Visibility +// GBuffer Conditioner +// Deferred Material + +struct ConnectData +{ + float4 vpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; + float3 gbNormal : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : SV_Target0; + float4 col1 : SV_Target1; + float4 col2 : SV_Target2; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float4 diffuseMaterialColor : register(C0), + uniform float matInfoFlags : register(C1), + uniform float3 vEye : register(C3), + uniform float4 oneOverFarplane : register(C4), + uniform float visibility : register(C2) +) +{ + Fragout OUT; + + // Vert Position + + // Diffuse Color + OUT.col1 = float4(1.0,1.0,1.0,1.0); + OUT.col1 = diffuseMaterialColor; + + // Deferred Shading: Empty Specular + OUT.col2.g = 1.0; + OUT.col2.ba = 0.0; + + // Deferred Shading: Mat Info Flags + OUT.col2.r = matInfoFlags; + + // Eye Space Depth (Out) +#ifndef CUBE_SHADOW_MAP + float eyeSpaceDepth = dot(vEye, (IN.wsEyeVec.xyz / IN.wsEyeVec.w)); +#else + float eyeSpaceDepth = length( IN.wsEyeVec.xyz / IN.wsEyeVec.w ) * oneOverFarplane.x; +#endif + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // GBuffer Conditioner + float4 normal_depth = float4(normalize(IN.gbNormal), eyeSpaceDepth); + + // output buffer format: GFXFormatR16G16B16A16F + // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo) + float4 _gbConditionedOutput = float4(sqrt(half(2.0/(1.0 - normal_depth.y))) * half2(normal_depth.xz), 0.0, normal_depth.a); + + // Encode depth into hi/lo + float2 _tempDepth = frac(normal_depth.a * float2(1.0, 65535.0)); + _gbConditionedOutput.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/65535.0, 0.0); + + OUT.col = _gbConditionedOutput; + + // Deferred Material + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_V.hlsl b/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_V.hlsl new file mode 100644 index 000000000..e27e33019 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/c5e4ec9bb49846a9_V.hlsl @@ -0,0 +1,70 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Deferred Shading: Empty Specular +// Deferred Shading: Mat Info Flags +// Eye Space Depth (Out) +// Visibility +// GBuffer Conditioner +// Deferred Material + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; + float2 texCoord2 : TEXCOORD1; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; + float3 gbNormal : TEXCOORD1; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4), + uniform float3 eyePosWorld : register(C12), + uniform float4x4 worldViewOnly : register(C8) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Diffuse Color + + // Deferred Shading: Empty Specular + + // Deferred Shading: Mat Info Flags + + // Eye Space Depth (Out) + float3 depthPos = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz; + OUT.wsEyeVec = float4( depthPos.xyz - eyePosWorld, 1 ); + + // Visibility + + // GBuffer Conditioner + OUT.gbNormal = mul(worldViewOnly, float4( normalize(IN.normal), 0.0 ) ).xyz; + + // Deferred Material + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/c74b275969540357_P.hlsl b/Templates/BaseGame/game/data/shaderCache/c74b275969540357_P.hlsl new file mode 100644 index 000000000..3933a59ca --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/c74b275969540357_P.hlsl @@ -0,0 +1,47 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Paraboloid Vert Transform +// Visibility +// Depth (Out) + +struct ConnectData +{ + float4 vpos : SV_Position; + float2 posXY : TEXCOORD0; + float depth : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float visibility : register(C0) +) +{ + Fragout OUT; + + // Paraboloid Vert Transform + clip( 1.0 - abs(IN.posXY.x) ); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // Depth (Out) + OUT.col = float4( IN.depth, 0, 0, 1 ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/c74b275969540357_V.hlsl b/Templates/BaseGame/game/data/shaderCache/c74b275969540357_V.hlsl new file mode 100644 index 000000000..be4cd1c15 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/c74b275969540357_V.hlsl @@ -0,0 +1,61 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Paraboloid Vert Transform +// Visibility +// Depth (Out) + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float2 posXY : TEXCOORD0; + float depth : TEXCOORD1; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float2 atlasScale : register(C4), + uniform float4x4 worldViewOnly : register(C0), + uniform float4 lightParams : register(C5), + uniform float2 atlasXOffset : register(C6) +) +{ + ConnectData OUT; + + // Paraboloid Vert Transform + OUT.hpos = mul(worldViewOnly, float4(IN.position.xyz,1)).xzyw; + float L = length(OUT.hpos.xyz); + OUT.hpos /= L; + OUT.hpos.z = OUT.hpos.z + 1.0; + OUT.hpos.xy /= OUT.hpos.z; + OUT.hpos.z = L / lightParams.x; + OUT.hpos.w = 1.0; + OUT.posXY = OUT.hpos.xy; + OUT.hpos.xy *= atlasScale.xy; + OUT.hpos.xy += atlasXOffset; + + // Visibility + + // Depth (Out) + OUT.depth = OUT.hpos.z / OUT.hpos.w; + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_P.hlsl b/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_P.hlsl new file mode 100644 index 000000000..2c0e0ccda --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_P.hlsl @@ -0,0 +1,52 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Eye Space Depth (Out) +// Visibility + +struct ConnectData +{ + float4 vpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float3 vEye : register(C1), + uniform float4 oneOverFarplane : register(C2), + uniform float visibility : register(C0) +) +{ + Fragout OUT; + + // Vert Position + + // Eye Space Depth (Out) +#ifndef CUBE_SHADOW_MAP + float eyeSpaceDepth = dot(vEye, (IN.wsEyeVec.xyz / IN.wsEyeVec.w)); +#else + float eyeSpaceDepth = length( IN.wsEyeVec.xyz / IN.wsEyeVec.w ) * oneOverFarplane.x; +#endif + OUT.col = float4(eyeSpaceDepth.rrr,1); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_V.hlsl b/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_V.hlsl new file mode 100644 index 000000000..f7db2ba1f --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/d653a08573e79020_V.hlsl @@ -0,0 +1,51 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Eye Space Depth (Out) +// Visibility + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float4 wsEyeVec : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4), + uniform float3 eyePosWorld : register(C8) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Eye Space Depth (Out) + float3 depthPos = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz; + OUT.wsEyeVec = float4( depthPos.xyz - eyePosWorld, 1 ); + + // Visibility + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_P.hlsl b/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_P.hlsl new file mode 100644 index 000000000..bc61ae75d --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_P.hlsl @@ -0,0 +1,69 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Diffuse Vertex Color +// Visibility +// Fog +// HDR Output +// Forward Shaded Material +// Translucent + +struct ConnectData +{ + float4 vpos : SV_Position; + float4 vertColor : COLOR; + float3 wsPosition : TEXCOORD0; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float4 diffuseMaterialColor : register(C0), + uniform float visibility : register(C1), + uniform float4 fogColor : register(C2), + uniform float3 eyePosWorld : register(C3), + uniform float3 fogData : register(C4) +) +{ + Fragout OUT; + + // Vert Position + + // Diffuse Color + OUT.col = diffuseMaterialColor; + + // Diffuse Vertex Color + OUT.col *= IN.vertColor; + + // Visibility + OUT.col.a *= visibility; + + // Fog + float fogAmount = saturate( computeSceneFog( eyePosWorld, IN.wsPosition, fogData.r, fogData.g, fogData.b ) ); + OUT.col.rgb = lerp( fogColor.rgb, OUT.col.rgb, fogAmount ); + + // HDR Output + OUT.col = hdrEncode( OUT.col ); + + // Forward Shaded Material + + // Translucent + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_V.hlsl b/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_V.hlsl new file mode 100644 index 000000000..b3f3e673f --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/efef832dc37c8755_V.hlsl @@ -0,0 +1,63 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Diffuse Color +// Diffuse Vertex Color +// Visibility +// Fog +// HDR Output +// Forward Shaded Material +// Translucent + +struct VertData +{ + float3 position : POSITION; + float4 diffuse : COLOR; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float4 vertColor : COLOR; + float3 outWsPosition : TEXCOORD0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float4x4 objTrans : register(C4) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Diffuse Color + + // Diffuse Vertex Color + OUT.vertColor = IN.diffuse; + + // Visibility + + // Fog + OUT.outWsPosition = mul( objTrans, float4( IN.position.xyz, 1 ) ).xyz; + + // HDR Output + + // Forward Shaded Material + + // Translucent + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_P.hlsl b/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_P.hlsl new file mode 100644 index 000000000..d549fabd2 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_P.hlsl @@ -0,0 +1,52 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Paraboloid Vert Transform +// Visibility +// Depth (Out) +// Single Pass Paraboloid + +struct ConnectData +{ + float4 vpos : SV_Position; + float isBack : TEXCOORD0; + float2 posXY : TEXCOORD1; + float depth : TEXCOORD2; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform float visibility : register(C0) +) +{ + Fragout OUT; + + // Paraboloid Vert Transform + clip( abs( IN.isBack ) - 0.999 ); + clip( 1.0 - abs(IN.posXY.x) ); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // Depth (Out) + OUT.col = float4( IN.depth, 0, 0, 1 ); + + // Single Pass Paraboloid + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_V.hlsl b/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_V.hlsl new file mode 100644 index 000000000..847482580 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/f04ad263e891c04c_V.hlsl @@ -0,0 +1,67 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Paraboloid Vert Transform +// Visibility +// Depth (Out) +// Single Pass Paraboloid + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float isBack : TEXCOORD0; + float2 posXY : TEXCOORD1; + float depth : TEXCOORD2; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float2 atlasScale : register(C4), + uniform float4x4 worldViewOnly : register(C0), + uniform float4 lightParams : register(C5) +) +{ + ConnectData OUT; + + // Paraboloid Vert Transform + OUT.hpos = mul(worldViewOnly, float4(IN.position.xyz,1)).xzyw; + float L = length(OUT.hpos.xyz); + bool isBack = OUT.hpos.z < 0.0; + OUT.isBack = isBack ? -1.0 : 1.0; + if ( isBack ) OUT.hpos.z = -OUT.hpos.z; + OUT.hpos /= L; + OUT.hpos.z = OUT.hpos.z + 1.0; + OUT.hpos.xy /= OUT.hpos.z; + OUT.hpos.z = L / lightParams.x; + OUT.hpos.w = 1.0; + OUT.posXY = OUT.hpos.xy; + OUT.hpos.xy *= atlasScale.xy; + OUT.hpos.x += isBack ? 0.5 : -0.5; + + // Visibility + + // Depth (Out) + OUT.depth = OUT.hpos.z / OUT.hpos.w; + + // Single Pass Paraboloid + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_P.hlsl b/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_P.hlsl new file mode 100644 index 000000000..e10b01aa1 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_P.hlsl @@ -0,0 +1,84 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Detail +// Diffuse Color +// Deferred RT Lighting +// Visibility +// HDR Output + +struct ConnectData +{ + float4 vpos : SV_Position; + float2 detCoord : TEXCOORD0; + float4 screenspacePos : TEXCOORD1; +}; + + +struct Fragout +{ + float4 col : SV_Target0; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ConnectData IN, + uniform SamplerState detailMap : register(S0), + uniform Texture2D detailMapTex : register(T0), + uniform float4 diffuseMaterialColor : register(C0), + uniform float4 rtParamslightInfoBuffer : register(C2), + uniform SamplerState lightInfoBuffer : register(S1), + uniform Texture2D lightInfoBufferTex : register(T1), + uniform float visibility : register(C1) +) +{ + Fragout OUT; + + // Vert Position + + // Detail + OUT.col = ( detailMapTex.Sample(detailMap, IN.detCoord) * 2.0 ) - 1.0; + + // Diffuse Color + OUT.col = diffuseMaterialColor; + + // Deferred RT Lighting + float2 uvScene = IN.screenspacePos.xy / IN.screenspacePos.w; + uvScene = ( uvScene + 1.0 ) / 2.0; + uvScene.y = 1.0 - uvScene.y; + uvScene = ( uvScene * rtParamslightInfoBuffer.zw ) + rtParamslightInfoBuffer.xy; + float3 d_lightcolor; + float d_NL_Att; + float d_specular; + lightinfoUncondition(lightInfoBufferTex.Sample(lightInfoBuffer, uvScene), d_lightcolor, d_NL_Att, d_specular); + OUT.col *= float4(d_lightcolor, 1.0); + + // Visibility + fizzle( IN.vpos.xy, visibility ); + + // HDR Output + OUT.col = hdrEncode( OUT.col ); + + + return OUT; +} diff --git a/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_V.hlsl b/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_V.hlsl new file mode 100644 index 000000000..ae63bd6d3 --- /dev/null +++ b/Templates/BaseGame/game/data/shaderCache/fd1301c841a0c80b_V.hlsl @@ -0,0 +1,73 @@ +//***************************************************************************** +// Torque -- HLSL procedural shader +//***************************************************************************** + +// Dependencies: +#include "core/rendering/shaders/lighting.hlsl" +//------------------------------------------------------------------------------ +// Autogenerated 'Light Buffer Conditioner [RGB]' Uncondition Method +//------------------------------------------------------------------------------ +inline void autogenUncondition_bde4cbab(in float4 bufferSample, out float3 lightColor, out float NL_att, out float specular) +{ + lightColor = bufferSample.rgb; + NL_att = dot(bufferSample.rgb, float3(0.3576, 0.7152, 0.1192)); + specular = bufferSample.a; +} + + +#include "core/rendering/shaders/torque.hlsl" + +// Features: +// Vert Position +// Detail +// Diffuse Color +// Deferred RT Lighting +// Visibility +// HDR Output + +struct VertData +{ + float3 position : POSITION; + float3 normal : NORMAL; + float3 T : TANGENT; + float3 B : BINORMAL; + float2 texCoord : TEXCOORD0; + float2 texCoord2 : TEXCOORD1; +}; + + +struct ConnectData +{ + float4 hpos : SV_Position; + float2 detCoord : TEXCOORD0; + float4 screenspacePos : TEXCOORD1; +}; + + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +ConnectData main( VertData IN, + uniform float4x4 modelview : register(C0), + uniform float2 detailScale : register(C4) +) +{ + ConnectData OUT; + + // Vert Position + OUT.hpos = mul(modelview, float4(IN.position.xyz,1)); + + // Detail + OUT.detCoord = IN.texCoord * detailScale; + + // Diffuse Color + + // Deferred RT Lighting + OUT.screenspacePos = OUT.hpos; + + // Visibility + + // HDR Output + + return OUT; +} diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_d.png b/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_d.png new file mode 100644 index 0000000000000000000000000000000000000000..aa5a1ead531fa25c317cbda847d0e4e714869589 GIT binary patch literal 3125 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 P00000NkvXXu0mjfb1TGY literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_h.png b/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_h.png new file mode 100644 index 0000000000000000000000000000000000000000..0636c3e149679c87b865d0ef5edb38c38c948005 GIT binary patch literal 3298 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_n.png b/Templates/BaseGame/game/tools/VPathEditor/GUI/Images/btn_Palette_n.png new file mode 100644 index 0000000000000000000000000000000000000000..1422b1db2e890534ebae1ea63f7365a3cbe0cb3f GIT binary patch literal 2928 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 abQ%D^y)k}ZJW^Ev0000<MNUMnLSTY0PHvL` literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/Profiles.cs b/Templates/BaseGame/game/tools/VPathEditor/GUI/Profiles.cs new file mode 100644 index 000000000..ae99719c6 --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/GUI/Profiles.cs @@ -0,0 +1,12 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VPathEditorProfile ) +{ + CanKeyFocus = true; + + FontType = "Arial Bold"; + FontColor = "0 0 0"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditor.gui b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditor.gui new file mode 100644 index 000000000..9deb0e197 --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditor.gui @@ -0,0 +1,434 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new VPathEditor(EVPathEditor) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VPathEditorProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "800 600"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "None"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + cameraZRot = "0"; + forceFOV = "0"; + renderMissionArea = "1"; + missionAreaFillColor = "255 0 0 20"; + missionAreaFrameColor = "255 0 0 128"; + allowBorderMove = "0"; + borderMovePixelSize = "20"; + borderMoveSpeed = "0.1"; + consoleFrameColor = "255 0 0 255"; + consoleFillColor = "0 0 0 0"; + consoleSphereLevel = "1"; + consoleCircleSegments = "32"; + consoleLineWidth = "1"; + GizmoProfile = "GlobalGizmoProfile"; + + new GuiWindowCollapseCtrl(VPathEditorTreeWindow) { + internalName = ""; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) - 1; + Extent = "210 167"; + MinExtent = "210 100"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + closeCommand = "EditorGui.setEditor( WorldEditorInspectorPlugin );"; + EdgeSnap = "1"; + text = "Path Editor"; + + new GuiContainer(){ + profile = GuiDefaultProfile; + Position = "5 25"; + Extent = "200 120"; + Docking = "Client"; + Margin = "3 1 3 3 "; + HorizSizing = "width"; + VertSizing = "height"; + isContainer = "1"; + + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "200 118"; + MinExtent = "8 8"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + + new GuiTreeViewCtrl(VPathTreeView) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "ToolsGuiTreeViewProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "193 21"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + tabSize = "16"; + textOffset = "2"; + fullRowSelect = "0"; + itemHeight = "21"; + destroyTreeOnSleep = "1"; + MouseDragging = "0"; + MultipleSelections = "0"; + DeleteObjectAllowed = "1"; + DragToItemAllowed = "0"; + showRoot = "1"; + internalNamesOnly = "0"; + }; + }; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + position = "193 4"; + Extent = "16 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "VPathTreeView.DeleteSelectedPaths();"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Delete Selected Path"; + hovertime = "1000"; + internalName = "deleteSelection"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "core/art/gui/images/new"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + position = "176 3"; + Extent = "17 17"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "VPathTreeView.CreatePath();"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Create New Path"; + hovertime = "1000"; + internalName = "CreateSelection"; + canSaveDynamicFields = "0"; + }; + }; + new GuiWindowCollapseCtrl(VPathEditorOptionsWindow) { + internalName = "Window"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) + getWord(VPathEditorTreeWindow.extent, 1) - 2; + Extent = "210 530"; + MinExtent = "210 298"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + closeCommand = "EditorGui.setEditor( WorldEditorPlugin );"; + EdgeSnap = "1"; + text = "Properties"; + + new GuiContainer(){ //Node Properties + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 24"; + Extent = "202 127"; + Docking = "Top"; + Margin = "3 3 3 3"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "86 18"; + text = "Node Properties"; + }; + new GuiTextCtrl(){ + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "7 21"; + Extent = "46 18"; + text = "Position"; + }; + new GuiTextEditCtrl(){ + internalName = "position"; + Profile = "GuiTextEditProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "57 21"; + Extent = "141 18"; + text = ""; + AltCommand = "EVPathEditor.setNodePosition( $ThisControl.getValue() );"; + }; + new GuiTextCtrl(){ + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "7 42"; + Extent = "46 18"; + text = "Rotation"; + }; + new GuiTextEditCtrl(){ + internalName = "rotation"; + Profile = "GuiTextEditProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "57 42"; + Extent = "141 18"; + text = ""; + AltCommand = "EVPathEditor.setNodeRotation( $ThisControl.getValue() );"; + }; + new GuiTextCtrl(){ + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "7 63"; + Extent = "46 18"; + text = "Weight"; + }; + new GuiTextEditCtrl(){ + internalName = "weight"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "57 63"; + Extent = "52 18"; + text = ""; + AltCommand = "EVPathEditor.setNodeWeight( $ThisControl.getValue() );"; + }; + new GuiTextCtrl(){ + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "7 84"; + Extent = "46 18"; + text = "Orientation"; + }; + new GuiPopUpMenuCtrl(EPathEditorNodeOrientationMode){ + internalName = "weight"; + Profile = "GuiPopUpMenuProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "57 84"; + Extent = "141 18"; + text = ""; + Command = "OnOrientationChanged();"; + }; + new GuiTextCtrl(){ + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "7 105"; + Extent = "46 18"; + text = "Lookat Pt"; + }; + new GuiTextEditCtrl(EPathEditorNodeOrientationData){ + internalName = "weight"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "57 105"; + Extent = "141 18"; + text = ""; + AltCommand = "OnOrientationChanged();"; + }; + }; + new GuiContainer(){ // Path Properties + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 112"; + Extent = "202 31"; + Docking = "Top"; + Margin = "0 0 3 3"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "121 18"; + text = "Path Properties"; + }; + }; + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "4 150"; + Extent = "223 315"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "-14 41 3 3"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + + new GuiInspector(VPathInspector) { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "1"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "179 16"; + MinExtent = "16 16"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + dividerMargin = "5"; + }; + }; + new GuiMLTextCtrl(VPathFieldInfoControl) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiInspectorFieldInfoMLTextProfile"; + HorizSizing = "width"; + VertSizing = "top"; + Position = "1 485"; + Extent = "202 42"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + lineSpacing = "2"; + allowColorChars = "0"; + maxChars = "-1"; + useURLMouseCursor = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +function EPathEditorNodeOrientationMode::onWake( %this ) +{ + if ( %this.size() == 0 ) + { + %this.add( "FREE", 0 ); + %this.add( "TOPOINT", 1 ); + } +} + +function OnOrientationChanged() +{ + %mode = EPathEditorNodeOrientationMode.getText(); + %data = EPathEditorNodeOrientationData.getText(); + EVPathEditor.setNodeOrientationMode( %mode, %data ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorPalette.gui b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorPalette.gui new file mode 100644 index 000000000..94f8102dc --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorPalette.gui @@ -0,0 +1,176 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +%paletteId = new GuiControl(VPathEditorPalette) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + + new GuiBitmapButtonCtrl(EVPathEditorSelectButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Select Path / Node (1)"; + hovertime = "1000"; + bitmap = "tools/gui/images/menubar/arrow"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(EVPathEditorMoveButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Move Point (2)"; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/road-river/move-point"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(EVPathEditorRotateButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "28 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Rotate Point (3)"; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/road-river/rotate-point"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(EVPathEditorScaleButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "56 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Scale Point (4)"; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/road-river/scale-point"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(EVPathEditorAddNodeButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "28 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Add Node (5)"; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/road-river/add-point"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(EVPathEditorDeleteNodeButton) { + canSaveDynamicFields = "0"; + internalName = ""; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "56 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Delete Node (6)"; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/road-river/subtract-point"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; +}; + +//----------------------------------------------------------------------------- + +function EVPathEditorSelectButton::onClick( %this ) +{ + EVPathEditor.EditMode = "Gizmo"; + GlobalGizmoProfile.Mode = "Select"; +} + +function EVPathEditorMoveButton::onClick( %this ) +{ + EVPathEditor.EditMode = "Gizmo"; + GlobalGizmoProfile.Mode = "Move"; +} + +function EVPathEditorRotateButton::onClick( %this ) +{ + EVPathEditor.EditMode = "Gizmo"; + GlobalGizmoProfile.Mode = "Rotate"; +} + +function EVPathEditorScaleButton::onClick( %this ) +{ + EVPathEditor.EditMode = "Gizmo"; + GlobalGizmoProfile.Mode = "Scale"; +} + +function EVPathEditorAddNodeButton::onClick( %this ) +{ + EVPathEditor.EditMode = "AddNode"; +} + +function EVPathEditorDeleteNodeButton::onClick( %this ) +{ + EVPathEditor.EditMode = "DeleteNode"; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorToolbar.gui b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorToolbar.gui new file mode 100644 index 000000000..76fa8aff7 --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/GUI/VPathEditorToolbar.gui @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +%guiContent = new GuiControl(VPathEditorToolbar) +{ + canSaveDynamicFields = "0"; + internalName = "VPathEditorToolbar"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "306 0"; + Extent = "800 32"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "0"; + hovertime = "1000"; + canMove = "0"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + resizeWidth = "0"; + resizeHeight = "0"; + EdgeSnap = "0"; + text =""; + + new GuiTextCtrl() + { + internalName = "ToolbarLabel"; + profile = "GuiTextProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "2 7"; + extent = "77 16"; + minExtent = "8 8"; + visible = "1"; + text = " VPath Settings"; + maxLength = "255"; + helpTag = "0"; + }; + + new GuiPopUpMenuCtrl(VPathEditorToolbarPathTypeMenu) + { + canSaveDynamicFields = "0"; + internalName = "PathTypeMenu"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiPopUpMenuProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "85 7"; + Extent = "70 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + maxLength = "1024"; + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + }; +}; diff --git a/Templates/BaseGame/game/tools/VPathEditor/Scripts/Editor.cs b/Templates/BaseGame/game/tools/VPathEditor/Scripts/Editor.cs new file mode 100644 index 000000000..c940eddcc --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/Scripts/Editor.cs @@ -0,0 +1,228 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function EVPathEditor::onDeleteKey( %this ) +{ + %editPath = EVPathEditor.getSelectedPath(); + %editNode = EVPathEditor.getSelectedNode(); + if ( isObject( %editPath ) && %editNode != -1 ) + { + // Delete the Node. + %this.deleteSelection(); + } + else + { + // Clear Selection. + %this.clearSelection(); + + // Delete the Path. + MEDeleteUndoAction::submit( %editPath ); + } +} + +function EVPathEditor::onUpdateSelection( %this, %editPath, %editNode ) +{ + // Clear World Editor Selection. + EWorldEditor.clearSelection(); + + %clearNode = true; + if ( isObject( %editPath ) ) + { + // Reset Type. + VPathEditorToolbarPathTypeMenu.setText( %editPath.PathType ); + + // Set World Editor Selection. + EWorldEditor.selectObject( %editPath ); + + // Inspect. + VPathInspector.inspect( %editPath ); + + // Update the Node Inspector. + if ( %editNode != -1 ) + { + // Valid Node. + %clearNode = false; + + VPathEditorOptionsWindow-->position.setActive( true ); + VPathEditorOptionsWindow-->position.setValue( %editPath.getNodeLocalPosition( %editNode ) ); + + VPathEditorOptionsWindow-->rotation.setActive( true ); + VPathEditorOptionsWindow-->rotation.setValue( %editPath.getNodeLocalRotation( %editNode ) ); + + VPathEditorOptionsWindow-->weight.setActive( true ); + VPathEditorOptionsWindow-->weight.setValue( %editPath.getNodeWeight( %editNode ) ); + + %orientationMode = %editPath.getNodeOrientationMode( %editNode ); + %orientationType = EPathEditorNodeOrientationMode.findText( strupr( getField( %orientationMode, 0 ) ) ); + %orientationData = getField( %orientationMode, 1 ); + + EPathEditorNodeOrientationMode.setSelected( %orientationType, false ); + EPathEditorNodeOrientationData.Text = %orientationData; + } + } + + // Invalid Node? + if ( %clearNode ) + { + VPathEditorOptionsWindow-->position.setActive( false ); + VPathEditorOptionsWindow-->position.setValue( "" ); + + VPathEditorOptionsWindow-->rotation.setActive( true ); + VPathEditorOptionsWindow-->rotation.setValue( "" ); + + VPathEditorOptionsWindow-->weight.setActive( true ); + VPathEditorOptionsWindow-->weight.setValue( "" ); + } +} + +function VPathEditorToolbarPathTypeMenu::onSelect( %this ) +{ + %editPath = EVPathEditor.getSelectedPath(); + if ( isObject( %editPath ) ) + { + // Apply Type. + %editPath.PathType = %this.getText(); + } +} + +function VPathTreeView::onInspect( %this, %object ) +{ + // VPath? + if ( !%object.isMemberOfClass( "VPath" ) ) + { + return; + } + + // Select Object. + EVPathEditor.setSelection( %object ); +} + +function VPathTreeView::DeleteSelectedPaths( %this ) +{ + // Clear the Selection. + EVPathEditor.clearSelection(); + + // Iterate over Selection. + %selectionList = %this.getSelectedItemList(); + %selectionCount = getWordCount( %selectionList ); + for ( %i = 0; %i < %selectionCount; %i++ ) + { + // Fetch Index. + %itemIndex = getWord( %selectionList, %i ); + + // Fetch Object. + %itemObject = %this.getItemValue( %itemIndex ); + + // Skip Non-Path Objects. + if ( !%itemObject.isMemberOfClass( "VPath" ) ) + { + continue; + } + + // Delete the Object. + MEDeleteUndoAction::submit( %itemObject ); + } + + // Clear the Selection. + %this.clearSelection(); + EVPathEditor.clearSelection(); + + // Build the Tree. + %this.open( GetServerPathSet(), true ); +} + +function VPathTreeView::CreatePath( %this ) +{ + // Create Path Object. + EWCreatorWindow.createObject( "ObjectBuilderGui.buildObject( \"VPath\" );" ); +} + +//----------------------------------------------------------------------------- +// +// Node Editing +// +//----------------------------------------------------------------------------- + +function EVPathEditor::onUpdateNode( %this, %editPath, %editNode, %selected ) +{ + if ( %selected ) + { + %this.onUpdateNodePosition( %editPath, %editNode, %selected ); + %this.onUpdateNodeRotation( %editPath, %editNode, %selected ); + %this.onUpdateNodeWeight( %editPath, %editNode, %selected ); + %this.onUpdateNodeOrientation( %editPath, %editNode, %selected ); + } +} + +function EVPathEditor::onUpdateNodePosition( %this, %editPath, %editNode, %selected ) +{ + if ( %selected ) + { + VPathEditorOptionsWindow-->position.setValue( %editPath.getNodeLocalPosition( %editNode ) ); + } +} + +function EVPathEditor::onUpdateNodeRotation( %this, %editPath, %editNode, %selected ) +{ + if ( %selected ) + { + VPathEditorOptionsWindow-->rotation.setValue( %editPath.getNodeLocalRotation( %editNode ) ); + } +} + +function EVPathEditor::onUpdateNodeWeight( %this, %editPath, %editNode, %selected ) +{ + if ( %selected ) + { + VPathEditorOptionsWindow-->weight.setValue( %editPath.getNodeWeight( %editNode ) ); + } +} + +function EVPathEditor::onUpdateNodeOrientation( %this, %editPath, %editNode, %selected ) +{ + if ( %selected ) + { + %orientationMode = %editPath.getNodeOrientationMode( %editNode ); + %orientationType = EPathEditorNodeOrientationMode.findText( strupr( getField( %orientationMode, 0 ) ) ); + %orientationData = getField( %orientationMode, 1 ); + + // Change? + if ( EPathEditorNodeOrientationMode.getSelected() != %orientationType ) + { + // Update. + EPathEditorNodeOrientationMode.setSelected( %orientationType ); + } + + // Change? + if ( EPathEditorNodeOrientationData.getText() !$= %orientationData ) + { + // Update. + EPathEditorNodeOrientationData.setText( %orientationData ); + } + } +} + +//----------------------------------------------------------------------------- +// +// Inspector +// +//----------------------------------------------------------------------------- + +function VPathInspector::inspect( %this, %obj ) +{ + VPathFieldInfoControl.setText( "" ); + Parent::inspect( %this, %obj ); +} + +function VPathInspector::onInspectorFieldModified( %this, %object, %fieldName, %arrayIndex, %oldValue, %newValue ) +{ + // Same work to do as for the regular WorldEditor Inspector. + Inspector::onInspectorFieldModified( %this, %object, %fieldName, %arrayIndex, %oldValue, %newValue ); +} + +function VPathInspector::onFieldSelected( %this, %fieldName, %fieldTypeStr, %fieldDoc ) +{ + VPathFieldInfoControl.setText( "<font:ArialBold:14>" @ %fieldName @ "<font:ArialItalic:14> (" @ %fieldTypeStr @ ") " NL "<font:Arial:14>" @ %fieldDoc ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VPathEditor/Scripts/Plugin.cs b/Templates/BaseGame/game/tools/VPathEditor/Scripts/Plugin.cs new file mode 100644 index 000000000..8af3a167a --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/Scripts/Plugin.cs @@ -0,0 +1,178 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VPathEditorPlugin ) +{ + SuperClass = "EditorPlugin"; +}; + +//----------------------------------------------------------------------------- + +function VPathEditorPlugin::onWorldEditorStartup( %this ) +{ + //---------------------------------------------------------------------- + // + // Editor Init + // + //---------------------------------------------------------------------- + + EditorGui.add( EVPathEditor ); + EVPathEditor.setVisible( false ); + + %this.EditorMap = new ActionMap(); + %this.EditorMap.bindCmd( keyboard, "backspace", "EVPathEditor.onDeleteKey();", "" ); + %this.EditorMap.bindCmd( keyboard, "delete", "EVPathEditor.onDeleteKey();", "" ); + %this.EditorMap.bindCmd( keyboard, "1", "EVPathEditorSelectButton.performClick();", "" ); + %this.EditorMap.bindCmd( keyboard, "2", "EVPathEditorMoveButton.performClick();", "" ); + %this.EditorMap.bindCmd( keyboard, "3", "EVPathEditorRotateButton.performClick();", "" ); + %this.EditorMap.bindCmd( keyboard, "4", "EVPathEditorScaleButton.performClick();", "" ); + + //---------------------------------------------------------------------- + // + // Editor Toggles + // + //---------------------------------------------------------------------- + + // Add ourselves to the window menu. + %accel = EditorGui.addToEditorsMenu( "Path Editor", "", VPathEditorPlugin ); + + // Add ourselves to the ToolsToolbar + %tooltip = "Path Editor (" @ %accel @ ")"; + EditorGui.addToToolsToolbar( "VPathEditorPlugin", "VPathEditorPalette", expandFilename( "tools/VPathEditor/GUI/Images/btn_Palette" ), %tooltip ); + + // Find and Store the Button. + %this.ToolbarButton = ToolsToolbarArray.findObjectByInternalName( "VPathEditorPalette", false ); + + // Extend Width. + %extent = EWToolsToolbar.getExtent(); + EWToolsToolbar.setExtent( ( getWord( %extent, 0 ) + 33 ) SPC getWord( %extent, 1 ) ); + + //---------------------------------------------------------------------- + // + // Initialise Toolbar + // + //---------------------------------------------------------------------- + + if ( !isObject( VPathEditorToolbar ) ) + { + exec( "~/VPathEditor/GUI/VPathEditorToolbar.gui" ); + } + + // Add Toolbar. + EditorGuiToolbar.add( VPathEditorToolbar ); + + // Populate Type Menu. + VPathEditorToolbarPathTypeMenu.clear(); + VPathEditorToolbarPathTypeMenu.add( "BEZIER", 0 ); + VPathEditorToolbarPathTypeMenu.add( "LINEAR", 1 ); + VPathEditorToolbarPathTypeMenu.setFirstSelected(); + + //---------------------------------------------------------------------- + // + // Initialise Editor Palette + // + //---------------------------------------------------------------------- + + if ( !isObject( VPathEditorPalette ) ) + { + exec( "~/VPathEditor/GUI/VPathEditorPalette.gui" ); + } + + // Use Existing Group Number + 1. + %groupNum = ToolsPaletteArray.getObject( ToolsPaletteArray.getCount() - 1 ).GroupNum + 1; + + %paletteGroup = VPathEditorPalette; + while ( VPathEditorPalette.getCount() > 0 ) + { + // Fetch Button. + %paletteButton = %paletteGroup.getObject( 0 ); + + // Setup. + %paletteButton.Visible = false; + %paletteButton.GroupNum = %groupNum; + %paletteButton.PaletteName = VPathEditorPalette; + + // Add To Palette Array. + ToolsPaletteArray.addGuiControl( %paletteButton ); + } + + //---------------------------------------------------------------------- + // + // Initialise Library + // + //---------------------------------------------------------------------- + + EWCreatorWindow.registerMissionObject( "VPath", "VPath", "", "Level" ); +} + +//EditorGui.setEditor(\"VPathEditorPlugin\"); +function VPathEditorPlugin::onActivated( %this ) +{ + if ( !isObject( EVPathEditor ) ) + { + return; + } + + // Display Editor. + EVPathEditor.setVisible( true ); + EVPathEditor.makeFirstResponder( true ); + EditorGui.bringToFront( EVPathEditor ); + VPathEditorToolbar.setVisible( true ); + VPathTreeView.open( GetServerPathSet(), true ); + + // Sync Gizmo. + %this.syncGizmo(); + + // Enable Map. + %this.EditorMap.push(); + + // Valid Selection? + if ( EWorldEditor.getSelectionSize() ) + { + %selection = EWorldEditor.getSelectedObject( 0 ); + if ( isObject( %selection ) && %selection.isMemberOfClass( "VPath" ) ) + { + // Select Object. + EVPathEditor.setSelection( %selection ); + } + } + + // Parent Call. + Parent::onActivated( %this ); +} + +function VPathEditorPlugin::onDeactivated( %this ) +{ + // Hide Editor. + EVPathEditor.setVisible( false ); + VPathEditorToolbar.setVisible( false ); + + // Disable Map. + %this.EditorMap.pop(); + + // Parent Call. + Parent::onDeactivated( %this ); +} + +function VPathEditorPlugin::isDirty( %this ) +{ + return EVPathEditor.isDirty; +} + +function VPathEditorPlugin::clearDirty( %this ) +{ + EVPathEditor.isDirty = false; +} + +function VPathEditorPlugin::syncGizmo( %this ) +{ + switch$( GlobalGizmoProfile.Mode ) + { + case "None" : EVPathEditorSelectButton.performClick(); + case "Move" : EVPathEditorMoveButton.performClick(); + case "Rotate" : EVPathEditorRotateButton.performClick(); + case "Scale" : EVPathEditorScaleButton.performClick(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VPathEditor/main.cs b/Templates/BaseGame/game/tools/VPathEditor/main.cs new file mode 100644 index 000000000..91b13ea47 --- /dev/null +++ b/Templates/BaseGame/game/tools/VPathEditor/main.cs @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function InitializeVPathEditor() +{ + // Gui. + exec( "./GUI/Profiles.cs" ); + exec( "./GUI/VPathEditor.gui" ); + + // Scripts. + exec( "./Scripts/Plugin.cs" ); + exec( "./Scripts/Editor.cs" ); +} + +function DestroyVPathEditor() +{ + // Void. +} diff --git a/Templates/BaseGame/game/tools/VerveEditor/DefaultPrefs.cs b/Templates/BaseGame/game/tools/VerveEditor/DefaultPrefs.cs new file mode 100644 index 000000000..f9a28fd04 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/DefaultPrefs.cs @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Recent Files +// +//----------------------------------------------------------------------------- + +$Pref::VerveEditor::RecentFileSize = 10; + +//----------------------------------------------------------------------------- +// +// Event Snap +// +//----------------------------------------------------------------------------- + +$Pref::VerveEditor::Event::SnapToTime = true; +$Pref::VerveEditor::Event::SnapToTimeThreshold = 100; +$Pref::VerveEditor::Event::SnapToSiblings = true; +$Pref::VerveEditor::Event::SnapToSiblingThreshold = 100; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Buttons.psd b/Templates/BaseGame/game/tools/VerveEditor/GUI/Buttons.psd new file mode 100644 index 0000000000000000000000000000000000000000..1f5aaab696a9d95130c513bec7e666660c09f88d GIT binary patch literal 120172 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/GuiProfiles.cs b/Templates/BaseGame/game/tools/VerveEditor/GUI/GuiProfiles.cs new file mode 100644 index 000000000..079bdaa68 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/GUI/GuiProfiles.cs @@ -0,0 +1,213 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VEditorDefaultProfile ) +{ + opaque = true; + fillColor = "70 70 70"; + fillColorHL = "90 90 90"; + fillColorNA = "70 70 70"; + + border = 1; + borderColor = "120 120 120"; + borderColorHL = "100 100 100"; + borderColorNA = "240 240 240"; + + fontType = "Arial"; + fontSize = 12; + fontCharset = ANSI; + + fontColor = "255 255 255"; + fontColorHL = "255 255 255"; + fontColorNA = "255 255 255"; + fontColorSEL = "255 255 255"; +}; + +singleton GuiControlProfile( VEditorTestProfile ) +{ + opaque = true; + fillColor = "255 255 0"; + fillColorHL = "255 255 0"; + fillColorNA = "255 255 0"; +}; + +singleton GuiControlProfile( VEditorNoFillProfile : VEditorDefaultProfile ) +{ + opaque = false; +}; + +singleton GuiControlProfile( VEditorNoBorderProfile : VEditorDefaultProfile ) +{ + border = false; +}; + +singleton GuiControlProfile( VEditorTransparentProfile : VEditorDefaultProfile ) +{ + opaque = false; + border = false; +}; + +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VEditorTextProfile : VEditorDefaultProfile ) +{ + border = false; + opaque = false; + + fontType = "Arial Bold"; +}; + +singleton GuiControlProfile( VEditorTextEditProfile : VEditorDefaultProfile ) +{ + fillColor = "70 70 70"; + fillColorHL = "90 90 90"; + fillColorSEL = "0 0 0"; + fillColorNA = "70 70 70"; + + fontColor = "255 255 255"; + fontColorHL = "0 0 0"; + fontColorSEL = "128 128 128"; + fontColorNA = "128 128 128"; + + textOffset = "4 2"; + autoSizeWidth = false; + autoSizeHeight = false; + justify = "left"; + tab = true; + canKeyFocus = true; +}; + +singleton GuiControlProfile( VEditorPopupMenuProfile : GuiPopUpMenuProfile ) +{ + FillColorHL = "90 90 90"; + FillColorSEL = "0 0 0"; + + FontColorHL = "255 255 255"; +}; + +singleton GuiControlProfile ( VEditorBitmapButtonProfile : VEditorDefaultProfile ) +{ + justify = "center"; + + hasBitmapArray = true; + bitmap = "./Images/Button"; +}; + +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VEditorGroupHeaderProfile : VEditorDefaultProfile ) +{ + CanKeyFocus = true; + TextOffset = "23 0"; + + fontColor = "70 70 70"; +}; + +singleton GuiControlProfile( VEditorGroupHeaderErrorProfile : VEditorGroupHeaderProfile ) +{ + fontColor = "255 70 70"; +}; + +singleton GuiControlProfile( VEditorGroupTrackProfile : VEditorTransparentProfile ) +{ + CanKeyFocus = true; +}; + +singleton GuiControlProfile( VEditorTrackProfile : VEditorDefaultProfile ) +{ + CanKeyFocus = true; + TextOffset = "33 0"; + + opaque = true; + fillColor = "255 255 255 15"; + fillColorHL = "151 166 191 60"; + + borderColor = "100 100 100"; +}; + +singleton GuiControlProfile( VEditorTrackErrorProfile : VEditorTrackProfile ) +{ + fontColor = "255 70 70"; +}; + +singleton GuiControlProfile( VEditorEventProfile : VEditorDefaultProfile ) +{ + CanKeyFocus = true; + Justify = "left"; + TextOffset = "6 1"; + + fillColor = "81 81 81"; + fillColorHL = "102 102 102"; + + borderColor = "255 255 255"; + borderColorHL = "255 255 255"; + borderColorNA = "100 100 100"; +}; + +singleton GuiControlProfile( VEditorTimeLineProfile : VEditorDefaultProfile ) +{ + CanKeyFocus = true; + + opaque = false; + fillColorHL = "255 255 255 15"; + + border = false; + borderColor = "100 100 100"; +}; + +singleton GuiControlProfile( VEditorPropertyProfile : VEditorDefaultProfile ) +{ + fillColor = "102 102 102"; +}; + +//----------------------------------------------------------------------------- + +singleton GuiControlProfile ( VEditorScrollProfile : VEditorDefaultProfile ) +{ + opaque = false; + border = false; + + hasBitmapArray = true; + bitmap = "./Images/ScrollBar"; +}; + +singleton GuiControlProfile ( VEditorCheckBoxProfile : GuiCheckBoxProfile ) +{ + // Void. +}; + +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VEditorPropertyRolloutProfile : GuiRolloutProfile ) +{ + border = 0; + hasBitmapArray = true; + bitmap = "./Images/PropertyRollout"; + + fontType = "Arial"; + fontSize = 12; + fontCharset = ANSI; + + fontColor = "255 255 255"; + fontColorHL = "255 255 255"; + fontColorNA = "255 255 255"; + fontColorSEL = "255 255 255"; +}; + +singleton GuiControlProfile( VEditorPropertyLabelProfile : VEditorTextProfile ) +{ + border = "1"; + justify = "center"; +}; + +//----------------------------------------------------------------------------- + +singleton GuiControlProfile( VEditorPreferenceLabelProfile : GuiTextProfile ) +{ + opaque = true; + fillColor = "242 241 240"; + fillColorHL = "242 241 240"; + fillColorNA = "242 241 240"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Button.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Button.png new file mode 100644 index 0000000000000000000000000000000000000000..fc420ad8a1d85222647af479d33c77785e86c314 GIT binary patch literal 1307 zcmV+$1?2jPP)<h;3K|Lk000e1NJLTq000{R003+V1^@s6oAb#m00004XF*Lt006JZ zHwB9600009a7bBm000id000id0mpBsWB>pF8FWQhbW?9;ba!ELWdK2BZ(?O2No`?g zWm08fWO;GPWjp`?1ei%gK~!i%?V8I@6hRb*Yq*AMxF<kR5&|q?sV^|@3=5(OYkex+ zxzey;t1qBSSg- XeM!!=x$@5H}TGs9FfZPJspePX5P>GS`mPu<R`vI@VQd-#`* z6pF=S(Ad{+-`uNWG59r4)oJiq?(gs2&CQLwyu5U0XJ_u@<iuW6hl+H-fQ19Da)~_S z<@NQoksco(N6J5c{c_KrJqvo~>ohbpxSpOK*WKOiT3T8h&j{YzUov!fc<A=__FQvw zvukZ_bzNOurbrzs(g6b&4!HPu-$OHYcXwwV9UUE+GR?r(4Gs>PG3ro}4j8a-zy&AV z5;JytduvVC-rjD%kB*L785$b0XX;Rqj&MA~1t;7k#;`7T<pJ$otAG(+-BaP2458f7 z(P15%RLVL0J}aa?sp-h=?QI)zG=usI?>>L|;@-Y_6Lhp(XLonkM&#+~sT&y?v1t$u z{iID+E3RY(sTEwSer~MR7JF1byUm#KNv!}!{5d~Aw>Xqk$~nXhpAC@4#>Ob3vdmDD z7z87{kv~LfxJyDzQ&W=#%ZrN(`+aL`%L;28LLDm75sqiL;Do!x7}i-VdwYAMNK4@3 zD-nHdwOTr06zSoDv%)jnB@XrV_1UUVXurC;vQ-<Q4i)Ku0SgCQe!_!JN#01HBeD|8 z6}`Xz_~Bl@co7^g(orALbpAL1ToGbWrWxAW+FWO6r!@mY9V*fR0~QW{6zWUUpVXl? zdTMI@lob6xOTS6yNPY$e2CRjtLq$4Zz&<(sCX;2^>F@7%!^6X7j5<`L0|qP{vFSI< z3o<@FZlzXZ!odMoZ2Bz^l4QkTgvX#3361t>%ft`bCM7W>La_85Trya{Nv-so5$87p zU-aSQNB92SyU@I^(AnA9ag_c2{XG2+wp^l@*-cWj>sk7dI@L+7<V5LPl5ALW0W4`B zTu3ne)>4ziAQ<6gsA~F6{6RK1H?06fL{P1kj&MA~6`OvOqZ1|$4i0KI1_mq~kEP$K zo;T*{ccN9k9F*PD?`YN6p)@rcxrvDhH#s?JEkPYB(g6e3=klA<HoSVt25@F(#?8&m znGR?4?$akXKR+Mtv%fm*&5)&~CAYG&V%f33`!r)1DHIB3XklT&0BdV&HnH`0+z3IR z^m}@GI^tMeT{Uj4k7kT*E$+*s<>h5FW}ZFB`ucjDEz`j>Ftf9>#>MFY=lkqLk?34s zTUw0xhGMOF3K$ZepW&=}`i(M8Cy#0|B;9h3`k#I?v>A0YgWpF<((kFMDH|w@i;He! zV<SKPPBKKQW3rp1X4kX&q~EDcYJ~t+ZNh}&Qj&pR&hcpat^WXLnV}>x2u6556iz?= zws^)dE9o*3mf%S|0;u50S{EniD0rd^7o7g-w;97aafeWj5ctN%#-dX>zBW$O8l>Jz z3*fErOsC)E41{tbtb*z52P>@JA@Ox|T>vBb>33WgC3>IT^gGqfV1D@|zkFg#lz)Mx z{^@sq`6SVz_!pGjyfOFeU&cj*txx)$+N91epH#bm!U*79e)+`aLZ&XC`~jW;EaqN_ R4$c4o002ovPDHLkV1ip3Z2tfN literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..12c703b9dc6cb787d491979ac1a8f26ccc721b14 GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DjSL74G){)!Z!;8IT)$B+p3qlX>YS{WEzFK+*@`^8fzQ=n6* zQ>1f=r;sXd)bYQkE7}*o|6OqH_dbi)m2z`R@0*|7wT?S|?(@#geUA@B{@(X^P44Z2 zYrEE2WJik4F+Fd5Zq_o+^xnrEo7)l(MAqJayk_0&g0S1$ELLYq%?Z73dT!M!uJoy? zotwKB9f+))_jrxY>4LCX%Ph1#h31GJH$2z1h$Fo<v14=He))4;O$^WNvp0U;YBlj7 Q2hhO`p00i_>zopr0M4gwwg3PC literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8b55fa7ed97609fce393843ce4412fdf8615468f GIT binary patch literal 2859 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 JPDHLkV1in%OA-J8 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_i.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/GroupBackground_i.png new file mode 100644 index 0000000000000000000000000000000000000000..5f23f7ca611486949ff9f7a060dd622b6f9b6f1a GIT binary patch literal 2865 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 P00000NkvXXu0mjfyUkBi literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/PropertyRollout.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/PropertyRollout.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab71d1c6be28c049e5a2a9bd6957802cf1a08ef GIT binary patch literal 3200 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar.png new file mode 100644 index 0000000000000000000000000000000000000000..dc231834305f548ec6fd3d1e8371bcd9d0728e75 GIT binary patch literal 3713 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar_.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/ScrollBar_.png new file mode 100644 index 0000000000000000000000000000000000000000..287ce57ebd0ac0d77fa101abfaf66856af1eb838 GIT binary patch literal 3884 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Spacer.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/Spacer.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2d24be1ef4ca6b6daaa044b138c94b11101882 GIT binary patch literal 1219 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WMyDrW(e>JaRrKxg3%Bdu_3V8;7bQEpD>gJ`33(U*?=MVJG&|{A#fIWL>4nJ z@ErzW#^d=bQh<UIC9V-A!TD(=<%vb93;~Imc_n&&t|1C##(KtPE1y3CX_WDFaSXBW uPyXT0V9=w*(0(Ap!a?XzhDFbc0tN>Aj6Zr&Kh=UkDb3T>&t;ucLK6Ti^fMv= literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent.png new file mode 100644 index 0000000000000000000000000000000000000000..7be6afbe8b92635c44a4fb02490d6bc2f442ecc0 GIT binary patch literal 3564 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_d.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e9f8df383d86081c2f94452937431d543c1e65 GIT binary patch literal 3626 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddEvent_h.png new file mode 100644 index 0000000000000000000000000000000000000000..b4b96029f9515e5af6b50f16379622057addc7aa GIT binary patch literal 3629 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup.png new file mode 100644 index 0000000000000000000000000000000000000000..27ae0e21d4992615fc229b20c1a7ff43640c35d9 GIT binary patch literal 3525 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_d.png new file mode 100644 index 0000000000000000000000000000000000000000..8877ceaa64d3a4a3c82da54067f196e95a94fd1b GIT binary patch literal 3553 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 b*8gt+>)Oscp&Hde00000NkvXXu0mjfGbo}{ literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddGroup_h.png new file mode 100644 index 0000000000000000000000000000000000000000..887080475d6d4fac2af6c7d6a2b26ac0cb6ca3c3 GIT binary patch literal 3574 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL.png new file mode 100644 index 0000000000000000000000000000000000000000..f2c5a01792014615e580ab2e0d534698064aac78 GIT binary patch literal 3560 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_d.png new file mode 100644 index 0000000000000000000000000000000000000000..6df64c5c88dd48cceba0ae2e6902cd1caada0a1a GIT binary patch literal 3623 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddL_h.png new file mode 100644 index 0000000000000000000000000000000000000000..d1302ed4af91ff1b5b6f9ef6f84be22a0d250e9e GIT binary patch literal 3626 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR.png new file mode 100644 index 0000000000000000000000000000000000000000..a69233788e9fac7797668ec2b8d07e7496495ed2 GIT binary patch literal 3561 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_d.png new file mode 100644 index 0000000000000000000000000000000000000000..392d196dc08464cf22c45c589a1beff58582b1d7 GIT binary patch literal 3615 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddR_h.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d80a2467548288900098bef0fe35da09f1ebb0 GIT binary patch literal 3632 zcmV-04$tw4P)<h;3K|Lk000e1NJLTq0015U0015c1^@s6J20-I00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_ zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0 zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a<fJbF^|4I#xQ~n$Dc= zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ zMBbZcF;6+KElM>iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000A9Nkl<Zc-ov-yG|=H5IugZ6C^q+8jwKnC!_&HMVSJ65J(8h4J8!?E${&p6ya~^ z$R8lYLe}=|Ezp=<uQxYgq{xp<=IxmiF&GRg)TpW&$C<>uLI^BMnm0rQ?>(GzkWwzB zJf)b8Qc4BmwAK(p{Onoj_xCpr4i1oI8Hfl()G3(nx|GI>wbroK;`#X*{eB-(N{GQ= zP+4oSySocx41^GnQZ^Jbv9dbV@7RdCVNyzDS%&F!3g;Zg<1vge&>Z3{%OHdR5uq$g zc<(!vr6^?pdrU+SLO>~ns;W>`)laB}5b)kZDFtgSthFGbMkrJJ)EXP1wFVKP*Xspm z8pXwh<-LdZz7^_};M5u$>6{CZtjpB(uy7cvssa(==;#P*YisxmeSCc2_V%_RubviJ zKX8RJGt>3;bz=p9(P-3IW1hMbEUPY4#!rB)t26PwZgngyCA{uL{Pe`m&Q4X9CHD9C z0RYqKG!)nI@iErd*Z&mi$z+22`+F#*kYySA{XU2YFE20X^?JX>6%!HR;o+fCEL&S! z7!HRZB0N4mVltVun#T6_HipAtD`G5zy_Ttbq(WX*6<%Lo0RUxL;_dA%@LXJ6gx@ev zJ=Ccg(8#fKu2q4v@*d|it^+<3QIOqw$3h5LYg=BY8U!o8y1EKy-rwBZB#pDyBFnO- zViwB7!de@;OxGaz{QN|o=iy0>MxzF=_Z~%2Kq&?19F~@r($A@$_^#d@4~+lu%$nOW z^)9>S>*nSr0Kgc7)z#JTn>^3Mo_SVQR$2q3Gskf*Pfkv-v9ZxILQ09t%gebyLRXaJ z|K=?KoS&aJRsc9VJ8RtWnb$adE#u=Mu_*S6^Or&^sq}@Gxwp56q9{-l1)Otm&f)a* zG#To7=>7d2d7eXS9a`q{@-oKbal2*4UFPoYE;-~=*ejK)xTxx$>lnUtg}&=9g~3w& zIhL)NNhuY89`9!r-aLqeF_)Awd;$Uq7HAD)OaNvKSr#d<)YIg#sI`XH`WIvKm)2Ss zW5PS-{XEs&l~*Yxgb*;sG@KGb{NQRL!q?Xq4i66@rG#@Xi8A9Hc6rHDiNnjV_UY-V z3Fw(I9$kN-*jQF7rELF&sfTygfS84`=QWDu{~G}LD>5#3qoJAr0000<MNUMnLSTZ~ C_|WA5 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml.png new file mode 100644 index 0000000000000000000000000000000000000000..fc32ee544bf6adf51fb54a29da007812cb427544 GIT binary patch literal 3216 zcmV;B3~%#^P)<h;3K|Lk000e1NJLTq000sI000sQ0ssI2*{m4=00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_ zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0 zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a<fJbF^|4I#xQ~n$Dc= zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ zMBbZcF;6+KElM>iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0005INkl<Zc-n+hy~^r95S>X@qlktGieO_YXqUzZu(Y$-)(7%Md;niTu(C<e%0{qJ zBqC~()tOt2>=!>S_nsn5X6DTQ;%qick^~U}fSE-Q8363B)eupm(NIZ}^m@H!vx$iR zr8$msxm@=9y+Xtw2wc|{t#}s+5>5m}^nD)@l}*jeMUKrZf_!Z(g@{BX=5DvEwXWCe z@QvH;wpc8V$D=J?i9xbyt=H@IZnq<%=ko~wl}e>tE)NC+t@V69w_PY3fSEnd+itg~ z(}|hGFl6S<W+SH2XvEA?*M~+#QYsM{W2DI-2*eK&(=-+9Pj3KVjBy-CRQLNm48tG@ zI-L$PkH_Qd^%_Ny<P`FU_IkbE@3(|W(=^X>V~m)MF<F+SX$k<3#{&SAQXiU~FEdxG z)zxZ+h?B{Lh?dJG0JK^yyPK~`3T&wWa6X@{YpGPSGZY6^yq!GH`~AM_x<nMmF#xpN zZKc$3IL!0hp3Bz)5OJ|sXsxHy>0j4v_w>0E+g=n!aU9!_7R5Z`??_9<y0L&?ufakQ zQI=(%=lx1zU5l>?5#=6~@B4?tp;*Sh!OXQ<?au&wBvZ%=f>96v0000<MNUMnLSTZ4 CZUJ)u literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_d.png new file mode 100644 index 0000000000000000000000000000000000000000..adfe16658badd6c05887dd2b51b75079ba1daa40 GIT binary patch literal 3244 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddSml_h.png new file mode 100644 index 0000000000000000000000000000000000000000..119f5df6d3480c6c3e8f715909c397c7e018cb3f GIT binary patch literal 3262 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack.png new file mode 100644 index 0000000000000000000000000000000000000000..4428e8ebc8f0674b6c26b7c393d1b7b6e9dd6d06 GIT binary patch literal 3577 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_d.png new file mode 100644 index 0000000000000000000000000000000000000000..3ef7d2a0f764bb2d4adfe81f63decefa513e20ba GIT binary patch literal 3637 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 Hu0mjf3x2!Y literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_AddTrack_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1b32c025960cd53f1edaa0b3b8fd0fbaeaac2ad9 GIT binary patch literal 3656 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 a{~G{7Qx8HE946KP0000<MNUMnLSTaZV&VS) literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete.png new file mode 100644 index 0000000000000000000000000000000000000000..a7a01eb500af72734ae0f639a33167bef129b410 GIT binary patch literal 3440 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 S6UF%e0000<MNUMnLSTYOws_J2 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml.png new file mode 100644 index 0000000000000000000000000000000000000000..63b67b3a16b91028d2e6dfa3166d864ca0289e5e GIT binary patch literal 3189 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%0AtJtru}8+X0y3kt+e&R)$8?q**~2W zQ>i`%0P6L+_E0Vue|M^?8jVJ^T8)TASQJIZn8{>PRh6#GuK^%pnx@v;`F#G@aqFBu zTcYJ<S+?11e0g7MsUia@$=8jZeZ2-XLqug+hGF=XM6dd<2@z!<OdQ9D!@-yFZ)4_G btMz99CDuvdZT!KO00000NkvXXu0mjf>$mwZ literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_d.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf78be02713b209815685766dde52b608d92856 GIT binary patch literal 3218 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 Eg0>|2ApigX literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_DeleteSml_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ef35233d2f2ff0595d9a75d7975043cd4315b67e GIT binary patch literal 3238 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 Y0J~Ou?DBE_wg3PC07*qoM6N<$g1YeumH+?% literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_d.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5aa8b098af727d82732264fa948ea13a73c1e5 GIT binary patch literal 3469 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Delete_h.png new file mode 100644 index 0000000000000000000000000000000000000000..17721dc230046b8c42196e3fbd515d36aaacfc5b GIT binary patch literal 3473 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward.png new file mode 100644 index 0000000000000000000000000000000000000000..c14fc173c0e0a1893ae99d022c432eb7b1ad4be8 GIT binary patch literal 3820 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_d.png new file mode 100644 index 0000000000000000000000000000000000000000..f0174272731f4ba148794c9bcd755174ac7a86be GIT binary patch literal 3898 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 IM6N<$f(6)9F8}}l literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Forward_h.png new file mode 100644 index 0000000000000000000000000000000000000000..24f3234de3b91a69950ad8decbcf9456d53394d1 GIT binary patch literal 3895 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 FV1j<CQO*DW literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_d.png new file mode 100644 index 0000000000000000000000000000000000000000..298764c09a3b7eca38fefeb6597858a8682bf648 GIT binary patch literal 3284 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 SL~gqP0000<MNUMnLSTZ6!YDNW literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7d7975f32c32426aefe8561402b5104a018b33b6 GIT binary patch literal 3683 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 B-%bDk literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_n.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Palette_n.png new file mode 100644 index 0000000000000000000000000000000000000000..881d9225091e061c87ec4caec44b4ad235a55868 GIT binary patch literal 2982 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d7a9dc1876fd56579263f30c8cc0fc3c6c86eb GIT binary patch literal 3606 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_d.png new file mode 100644 index 0000000000000000000000000000000000000000..62c5aeed32f77470db8e60a8d8eb0952023dfd88 GIT binary patch literal 3690 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 IM6N<$f@z-rX8-^I literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Pause_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7e510a9970045ae3adb908054922f900c23d3f4d GIT binary patch literal 3683 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 B;=%v` literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play.png new file mode 100644 index 0000000000000000000000000000000000000000..9163fa726db91d294fc2d7b82cf6ee33424eaf0c GIT binary patch literal 3774 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_d.png new file mode 100644 index 0000000000000000000000000000000000000000..5df9830f00e50c64a61d3f2f52411c4c0d6efb4b GIT binary patch literal 3817 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Play_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f24a859dec6228cb265b9aae256ad416b29c4335 GIT binary patch literal 3820 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf50891ea3a20a5a72a10384b3d72b1d9d7d60a GIT binary patch literal 3832 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_d.png new file mode 100644 index 0000000000000000000000000000000000000000..dc73431eac82e537a3a73f2aab0097528de82938 GIT binary patch literal 3906 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 QEC2ui07*qoM6N<$f?gM7CIA2c literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_Rewind_h.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd671ccbb8a81271d9459bd49d2b7e0b3a0d2ed GIT binary patch literal 3906 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 QssI2007*qoM6N<$g60KD+W-In literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB.png new file mode 100644 index 0000000000000000000000000000000000000000..fb3ad2a6a4b7018e1c1db935dfa81bb7782f7f22 GIT binary patch literal 3804 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 STQ7b90000<MNUMnLSTZU>=fPr literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_d.png new file mode 100644 index 0000000000000000000000000000000000000000..e1b0036c687174d0e08840cb69c886f46d2d237f GIT binary patch literal 3869 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepB_h.png new file mode 100644 index 0000000000000000000000000000000000000000..94fbfebcf14ddccfecccb3f96e06caae8ee08d2b GIT binary patch literal 3859 zcmV+u5A5)XP)<h;3K|Lk000e1NJLTq001%o0015c1^@s6Zc$DA00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_ zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0 zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a<fJbF^|4I#xQ~n$Dc= zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ zMBbZcF;6+KElM>iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000C&Nkl<Zc-pL3yGm<K6#nM2cTA_G^;o47EMjeAktRw&Naq9iDk2t=2N1;0fZ(O` z5hQ}vf?#K3rEW8~zmS<TnaoUf{7)cc_RM5mzqR&Si*&nP0|3St5JF&#!N2}knuL&r z{ujF+(z0@M|ALefN-3vMj`6(ny7y!I{+?3G?K8&QIb#frF;GeY;71XyHL9vYzu!ku z6wq2jYdx1yU1h?1F|Wtyg?xMkq?EY4yu{Md5-6o0-EP+iA<*mfP?jYKA)u5_DH1Y^ z2@r!s4z4N1{QEJbtOvB#5JKSU>I!99f*WI?ltNJyAcR0`jmc!<Tv|77Ld)f1!nb^E zo#IC+1tG-A$~lKI2F92lXc0o7lmcT6LI?;UptY{WFa?R2b#v=bffQfH7>qG!G#Zdn zy8ABJl~OL)l~Oa%$}vwVm5Q&r*(qimV~m5om2pZDd&z$NOEHD)*TONz(EctjFQeD% zq1|p{JRalv`Wm~ty8wWjo0}<GF~fyQg-QSb4Xt7!mBOhd;wu~~?=x9nU&q100sj2? z0|4lBI_|gA>11j7a`<~O@AA-kA(2?-NCl?<ToeU%c6P9_u>k=1{{BwF%NIDbd<>dl z{5nN^Z=~=X!pN>;I9^*@!`|K=R#sM$UQH?G(~m*b-}eo`Q|Z(S8RFMhDCUvv?QLvr zZMl43w|t51=K|iI*>fHX&M=r`mI)!zYPB#J46wSox{&ap2U5y}h?s$v{~)ED$yl+> z5khKnbJJA@zx6^2LZQLzT1pAd`E2?ngg^)p^++tR?RmT1M!(;$4W*bzVmxAK@c$!( zKv5L4idaunRRtl0D^YSUH9`oUo}Mrq4za(#k5;QyOZbnE54ZmO{9LG<VT_?HOEjC! zDVkI7k(32unDrUIyu9G(=m_`s_rLBlQgNEAy?i<}7Yi}Vq_Rj=RX9IC$LZ-Qs;c@` z1Lf0BDI2EWs7F#3NM)=TlgGzL93CFx`T4mP%u>bXqMoI>e#7@d40@pjt(D&2-!U8x zaeI3^)!{Ar9`QXjx5Q61I4Q5B8lD(T?(Xhza&m&Vx3^j`k}^!4IHM^G<a&ZsS`IA; z0I#pFI6gjhiQwVk0RS)_k1-yPlUA<NocSMKCl=~-eW`i~049?OMxzl%qmes1J3CAE z{keBaN=_cSYu=EcP9lh9mr&T;s3(PxRLoA5@r*Io+}m|75iHU%=B6aM^cu^k{uqc- zI$Qm6&QX@7D;cDewbNj#oXCxM>OP12_RY>Y2j~26^=rK#gm6V4rF3oq7;8yWW1@Mz zd~SFVqg$3G8jXfCIw9m|uBElc*Vh*Yg8?X|kWxmcC@I(H25s|bEIPPgjDd3wtu-z# zF3@Z?{|@Nv6h$djYlgMxxU?>f*j{X8YK_4;pB|Z7IN6!e{}FiJEbLzmvBUHK1^}IB V!PN-4>+=8r002ovPDHLkV1na^IotpM literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF.png new file mode 100644 index 0000000000000000000000000000000000000000..78a33a0cce73a527d205100380da16ff9ecab005 GIT binary patch literal 3808 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 Wku~H|I-b}70000<MNUMnLSTYioEp3U literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_d.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_d.png new file mode 100644 index 0000000000000000000000000000000000000000..d4ca592b6f7b23fef29b28d2587fa45d05c898fa GIT binary patch literal 3838 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 AQvd(} literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_h.png b/Templates/BaseGame/game/tools/VerveEditor/GUI/Images/btn_StepF_h.png new file mode 100644 index 0000000000000000000000000000000000000000..35749528d82b67bf6001d8872ed30bf5ee48e44d GIT binary patch literal 3848 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 KMNUMnLSTZS5=DCe literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/PropertyContainer.psd b/Templates/BaseGame/game/tools/VerveEditor/GUI/PropertyContainer.psd new file mode 100644 index 0000000000000000000000000000000000000000..6bc1aab40cc02953d1be20efdaf83f58cbf76e0a GIT binary patch literal 35698 zcmeHv2Yi#o|NlK%-FvWUD1|b*l5`{mTDsB}sD-vnK}eIQZ6HlblF}BDp$JO-iXt*q zhN$4cuY;+w5i1CSfC{J}(6THoPzqi7f9{erqa_r@|L?1>Jn3ETGwz<d_r33)%RPM_ zVdBVaL?QjbgfBjXVC0B!8jkTtgo)`HtUg5WB(YgUY(ZEtWar@c(jtj;8m;B#()n`b zkieT?><;A0WkUkTMrA}~6eZCG^0b+1I(z05IntTaq#{{he4O*((%90%qC#3L;g%LE zl$zMmA%PN^DwmFhG**WPa*2y}+K|8mY~YT|7|BgiscCLx7(a|3DvgL1aH9laf+&78 zKQe^NkBAV4N5q5+B0_n>SROx?C*&HAz&K|}4OYwYVzZLPh7*D`B(OlMEs6~fFDWSr zD-ndL)cN5&kw_FC!4K#2L%}0dQ>N5PN<)>J-ugm}<s{P@sajs7m8+CoT&^TnRjeHn z7>G~QdKg+(Sk!tVr6!EDGEAx}3@?=wh4aE9!dpv*jDrD{*d#SA(W=xrDwQHm-}aFO zDy>RWpeo`fWk+(y%9S!ziDq!PwX^B$rgG?HiI$E7bVQ-}FD8c<85<cB8z~&fi-?Vg zFe^mwX;nrB^o2~Km9$ezlrUBhX<mwjuXQ;pnLMwoL#3EJ4P^`t#}J!APWlt0Wu<>u zSIDHTJyBGwR*(*tNyBLcT}Ugn8t4t4WpBu&v3V+Wp+p-eDJoLPr4roX;WLynLpK%~ z`(<#r$@Ov98hSY+qqXAgQmC*nyglk^v?()yl?Il#n^TihRz!zq(Hd2;T1uzP031wI zHxM!-BQ{;B(Mpt3Iz2fKsuL!c%VGt5VG1uXAu>8fl$e~t<B6hp31TrXk)O=t33-Af z!Ys?ImYe`vvPxQvp*IvOgJSvOjumT`wN0^^YB@|r5`~!$uJxl7-%b&2PLn3rz%VT{ zvQa<o2`97Z>6Tg}Sru}^(ISajLu2HJ1R9|?p9S<K;XI@VV<l3|yErMH7iihwa0{)e zTGrX*Z9DDZ=<3Th%lhE*OA2VEt(iq%6!Cg+AsSVlwnU<)6Y_xvwx>INd6pTh3)asS z3i;mvzeY0SuYv#Y5%br;x0sOsFTgi3R$3rY=F_sca3fibijMV{z85V=k#Rn;8g-BD z;-Ho1nN|cAb0xO4y;5UsEKCzXTXI>5;|&gPqcb&kFtLrp!(CBKhI0&Dlp`X-c{ny? zH8)#l9dA3Ux!F3aDd%XVTpPzXoXtvYo$Co`)(kpXo=<BaPgHaWKPm=-5P~QK7F{9y zm`Dhq6Gnza2_hiyAPst<AcQZ94iQA~LIgY^1W`y7AA*1nIw&V50s{EPU^xox5Co9| z{-A^yL3DIXLIO{i5}BMVPKilKOiE0SPKx9w$0Ud&gocV+)XY%r$HoJ?RQ>=SU`tyb zU~TM3c`2<Jmn?^inFdeQ0@2{`b`54Ao9yFF8KZy-?Ha5zCaDxEbv7)$X-qtl#Y|=G zZGo5|S{NM}5*Z<ijvz7gQVfr;kNHHSj|HHQ;^}=NLvXGb5<`zdZ-EA4&_oKOB1jCq z32Ep{h@tmm1i%d(gFnO~91Fn{Vtg(EFa^i>ECOH<jv+6^BrotMk{1b997Am()@x!& zT8Lv2)DvRjBZ`7_3?J)bfNKx~BO`etC=<sxuSkgViiFrlB*Z=<5%Cf6NE(+WBBhB$ z_>3Y_rU=)BAHj<b0oH~9(?g;|VnT!=q7Z<F#|z={LwJG^UStTc7@T-9AwYRP_`*Pd zaR5Uk3PuZ%9mWOFeUMlv5Q-v235om&esnVMT+HVQqLPF$NhxA+3NOXbnHD|vxH;as zZf$>Y*lKRe_Eu9YVOxeuM#l*ThqtFT<Dki$o|H6Ft;&-t=r~PQY9cp1B`KOGijEHD zhXIY-^|RS{{ji6hb?}=qy!A(Ao2!58(&%v}ObvXTrCOC`KZz9}wnaN!w(+sD+TpSS z#I|UM%Qik%Ry$l)fY=u8aM{Mk%4&zp3J}|(9WLAWSXu3GSpi~Ow8Lc^A1kXJE-OH6 zi*~qd<6~vD!(|1CZP5;wZG5b(cDSqnu`Sx+vW<_G)ee^xAhtz2T(<GCvfAOY0>rjx zhs!oTR#rP)R)E+R?Qq$~$I5Dl%L)+Nq8%>V_*hx(a9IIjTeQPv8y_pH9WE<CY>Rfd zY~y2PwZmlvh;7jhmu-BktaiAp0I@CF;j)d7mDLWH6(F`nJ6yK$v9j9XvI4}mXot%- zK2}ycTvmYC7VU7^#>dKPhsz2O+oDaloK25u(@J<Yy96G>#!qoG{~(Wbd!jV>rVzvU zO`h=XOKk2WCQ<xcgowqBh%AUpiQJ`C?nz3$O=Kq$Lqw5W!TRUOom-zfXAs{y;+2NN z^YXx=fS5xxltHs@<*HT<eoCD}6CgJFL=jD>NkhuK2QorM2<h5Am{+j5U6byw*a#N5 zXaq=-*0C5wGQ$wd#4mza94P&v*Wq^Hw&5r9nZ(PHXfSf1V+_>?LkZEKMQ9@ggB^>? zVub>}NWL*@jZ&df=7UV0^{17R++2979Q!#biwhHJc)FQ3^Kb-ZLY|gZo9R$?k<`2t z=R&zM6P`PgYs(B?xc8k4C8d^H+*c@3q0BINIgs`Uu$F<D)3(me*k)B{r#!W!kj~c9 zMVYx%rC>L_w7}3z3@>g8t;SEx8_whlN*5WeR6$KmYQ{M1ONz_FkI|}%bBD%(N`J7l z@a$H{Pk}Q%;1rIsVyFx}1lHlwIu$**H0KhPdRn?N=W*4}1(%mutbL>cZB-DBNK$Ie z=;D#DP~}P#Icj(*#0YpmdW>R(Mh`J^Dv)S0R2UjULc)hgViQB$mJej?Sn<JEQ$W+C z_6oU@&LnSO&=}7_O6*BW#0=AqsjfK191D?t&cLGaeHRFMp^-?9R4`Z2@U2B<C<!Db zq$EfV-&os9I+D{E8Hh;4V2BCdjYj-!?qJln-$)L;JwhqdSP~{ns^vj8(vTc@^Me6n zQql-I&xkpZ6Sb;BgPl|(E5E>K$5rEK;N1nZ5hlvwJZxeECvON2L`Y9IJC{SgT2)+R zq2j2>^Yt{0JILdjl8sB(KQIrno1|E)N~M)}NYXM;ApD@a!P!~wj5XMjUYO5?ufMzf zOnBKtPRh6(IF;G-VX4W`<kJ=!jzpo&k>p$G+@-Wakwcei(=};186z-_ae<CTwS}`& zfl56yK_Smq8XE7RZ+x0j4LKcTbe^PGp@pQ=3|g&i$9;@ZZRzfkn@^s=GXvL4Uw&e0 zs{yj0Csay|wUbs=1mj*q8;OB!&I%w>8?9@uN(+Q)qj!OBFR*qeW3C@A47oyJ#Mh9t ze(ZS=bsCt`M#z;a2GGAysa4|#|Hh4<z;!qZ*GVTBmq2uhR8y3ZEyjI>;GsY+emYQJ z5{UukyQlTN_d{sfNG{jR){&%_v`7soQzOAyAcMEJKzcr;6(!mttjD$X&7FqR<m%+B zh6+NuGuG$p(;>u1pB{?SvO*;goPq0HBrBBR^Z`h}Fryd~pE&~33uega5=ftfbdaLB zP!4IlI`J)}B``0tFlIqoT3P_<2uQoCbFz{kJs4Q!ns1iQHA`!Of#8dhR7GW^Pq_W0 z{kibGs*syTmndkhHgqIRzY?_!-k4KZBvF<jq;E6Mg}mE5c}djz$fnWE&sGxmt=@in z6zMa{|A<Lv%4yQ6*28QKD?#QfCSC4Igtk48Q0FryUC>&DJmw>`^_W?E{4rn5UgaaF zrC}J**5jcLt)34~n4K>SpRe_)Rc^9=2y-#3rSMdCv6`#F&t-E%tx5c+Gn!S)tR5j* zbRMmy;k7K>F~BmpG9S8IDU;(XELX0yc(&H8gg=?htOT6Y^BNL98(NU><S^uU%oj2L zID%L{E{HktEwE6n{WijB3|was8XHih=RKssPGXCQu^2>#MoumZC@Cw4D=k*f(7Ukk z7aKVv59Euwpq{8V>W4z%x*LNAp`j=R4MUkI2aQKhAt@?Ag>dCAL9@_2v;dW(SJ3Nd z6<UKfpiO8q`V?(LU!uL}YjhZWk4~Yp=sdcNuA>@s7d66y+<|hVe5fu|0M&;YNbxBl z6-T8|Bd9EDJT-;Nr<7DNHH&(VDyNoEtEhF<Ch8Mv2ep@~ppH{NQx~YK)Gexk!DP5H zd>K6$eHq~lAtQk?oRPzr#K>n%XUt^GXS~c<!C24ukg=7qmvNYJigBKCol(a`Oc$m< zvllazDP$%wGno^Zc}z8PHggek8FM{zGjk{N5c3D-dFBn~eHMr1!{V|+S%X+<tkEnf zYdUK->m}AI)<)J=)&bTJtP89fRtwvW-JLy<9m`H<k7MVvOV|t8%h>O-x3CYgPq8nv z?{YXCe@-wbhLgq_&zZ`3n)4FpP0q)hJ)Gm5i<~+K2Zt^W109AqWI9M3v<?d#Ryus> zu-oB;!)1qijxLS?j(kV4;{->g<Fk&-9N%}`<#@ue%CXVO)2WYBtW&0w%&E+2vC{^p zoleJ`E;}_kdpQR?4{^?Mp6Wc$d4=<4=Y!7YoNv3hxCFY0Tt>ObUFN#1aQUyxH!c@k z?z?)s4scC!o#<NZ`m*bLu6ta6cD?Q9=GND3sM`cLt=r3Po80!h{pxnl-N!x5J>6aA zKF58v`&Rc8?$sVn9(_C#Jf8BH>9Ne?Gmm2)H$0s@`+6pMN<3$KuJ+vF`J-o@myZ|E zE7Pmc>m{%Ey(+w}csqFa^-l4YdC&KL+k3zFMIWY5Z=WO|sn2sh8+;D>T=wPo2K%P_ zPW3JK{mA#IZ;hX~U!>m{zf!-|eqZ^W_h<U|^-uR#_%HVV)c>@9L#G~{5<1bHUhK5F z(}_;?ox61&+L`XWsPo62PjznS!tIjMWm=b4yKL+7OIKFc0bNIRE$RAJ*MnVebo1>t zsGGFgqHdpdJJX%feL(lD?oW4ryZe#ubv=6aNbOP7V`Y#1J#O^$?>V&R)SgRw?&^6p zz$YLsKpwC(V0XYZt{*pntKhES9^lsW>fS4@S8=a(y^i*33=9q&9r$eE$AQ1}cJ3|g zo!5J5?|r>%f&zjvf@TGM5Ok)GQy*cUf<DXp9O_fwH@NTEz6<+q>w6`*b8vd_%-|1# z&-HWb7vFDszxDl2_UH5$_Mg`O&HmpHU<`;FP%vQifMWw01EUAZ2fjJ*cnBNbh@cEv zAM#_UYiL5~jL;84FNFDrjR<=-Y+G1$cu@F+@K?hRg||dRMJOURM4aV$^M>)B<?ZC% z;t$|U`K$RS1#SYdV2)tBpf++~Bpvxy<WEsPQ5jJSqxMBLN5@2~qc=xijR}gG67xpP zk3wJJNa0JuZ$xZSqG*ojOVRz<=vZy+r?EE&g$|lF=>0)g1_uwO2X7dBaY*10$&htJ z&c|`%ro^p{J0IUGUJ}1P{`aB1hsuV&JG3gHf5Oy+4-={rBNEk#TN3M&Vw0Xp+LO#o zPEB5vd^E*7Wpv7_lwZYx;(YN3;+oW`)TdMTq_NY6r@fl?V|tHtY5J!0nqe`+o*8yv zxa;uj;j4!KK4QQK^@yDrjErF!uVtKjqR$h`C$?px%=FCHGJhEvJaYQTFGg`jjU2Ul zRAm+~YgX2wY@h7O+3#oH%}LBzoO5<`ztP2`_l@xwGjYtOG4*4U$1WLreq8vtXT}{K z-*vov{PqbB6UIz<cS7BhDNnxs<mHJ`6BkT8Jt=rn>7<IMx;~|N>Z{2flO>Zso5G$l zcFOxxnk1Q$^^&^W^xQXcYotli<<jf2p|Yj2tMm|h30;*pByUOHmHZ+3ujOAYh%Z=H za6_IXUnQ@dnl^RK)cR?e)83n=Q;b!7T<BOhrErJRTRBa6K-E)KsybdYuxLTi`RTFK zU!Pv19<F{@Lun>ywrhQ1F?FQ4U-9$B7iPrGSUuxj$(WMQO1(;zrANvJl)YG1HB&tE zou^q(OP}61tJkb~vo1W7@XWf|)a=~Z`{wkXGk?zIxv6tE&U2nOZQgg!Mm)RZ**njT zeQxLc9`onUzxaIW^B*j5U!Y#_<HA7;*Sx@bLH@$g7X>e_e6eMbY|*#n5#`Iun_iN> z^zDCm|5@=L-OG6|A6*>1_^nqsuP9$R{c8NH8<%)3nYrZRYZ<R?UCLd$Xz88TC%;~? zEOObJ<<85Cm!DrTV#W5AK`UQb*|e%))v48qt3Q6D`x`I5QU9jw%@c18eQWcY9&5_i zG^~}c{b^n5x~=Q`u3z>x=j|D9S8f=y;m|w6cQ(D-_1*G!o8MEucYb5m#siyTHf?&p z`}>POV0=*g!PO5Ze)#=I$scXs9J+bk$NnFe{}=tY_`laanexf$PltcH?=#_Nn?LXK z`5Rk&wk+C8Z7thcv#ns;`R(JkAKx)-$G)9|c5eA1?2Grl?Dgg9ul&ARyvupl{9U@; zGk4eRDcW;mZ~oqk`zG%@yMNsNlLtl}IC^mS!Ee46f4%=u!lB*Y4Eg5Eir9)B-wMCo zb~yU*)+13zwtN@$-Ik-#N4Fk}Ikx?K(f2!#4?e!@MEr@pKP3O~^~v;;hfh6m>iFr= zr+@l!;*aNllKph$XT{I8XJ(vfJUjOs``n^mJbzjCYxiH*|JMJvkIzS+|LQ{Wg(JUb z|9<wO^y2kPnoCWW=U2K_E~^Tt+H{3~<;$z$tKVOH^4jI=Mb{f|EcnCgk2k9OReyeS z=*=TF<7zI~s%v$(Ub@}o_Ir0C@9e7^S@-MR!n=+2i|%!~xADI4{-K7k4ONXLO%6>f zn)^5JY#H8iPFJYYk>47=WHo>n10F=iD`><@h6t}GjK9Q75yHC`tbV97qI5s$&LhuZ z;&d^h7zp+_;TMVS59CT-t~fa<13apcJCTrVE-p!T7R^Vlj*gB_j;>Blu3j$AE?#~f zuC5+_oqc@#e0(~4xst>1r5CJY%FV^a&E3t@-QCmI-QC?6NAAA*EM6TcK(_~ZIl=-b zm`Md9h8M;3qIAE&jsR14fQpA&vJHEOP-8fl&^Q*G<KXDz>_S-^VQ-gdG<qV6MKKvH z2HSz-$Y#0<!05$f_44Mi6GlmV0;kX8b9`T2_eo;!Aiu1=xq?Xbv&WMh`Yg$=xlk+B zMES4(^trytujR;6_Pwo*?sQ`G@AR$D=I{TZ_~LDG@X`&>fByP`lb7ziv*qBa%XMS& zW-M6t?$)nQSKf_D9h+aWaQS=N4*ghF?}Zo)s4a`s$$`U;B30<c^JYN}rU&}4`SV`& z#WmQQb-YFplzTz_?2@ExKdC0Nwhsqaz@cx{z7tT1w>!yFMn`Mu-&?Ej;2H#*s-QcA zT$$vYUML<_uIOIBW$v}#(fti~zj`@j)<XBh(O=O2nKLMjSJS_GOZ_;-oZy;_^NXt& zf3o~$m)%E?HI?yR>;6vg!LW)~UXniPb}aKczp_#=-Q#rTr9%x_Iuykj`esE?+>&9t z9qXe5j{Nrf^{02lRn1cGzO&q|HsH0h_vh@?A>H?t`4#<diTCf?$?rygzAf;RJJ;s0 zW~Clie|GA#*x4!bzKZWGJ@ISR)$KYoaBSgJm1AwA?C{NFpU2mHIl2BnPCv|luL4&f zrTARk@|*n1@4|X*h#N8IQtg~o3+uXgY*><XHRyxy>tl6D@Y})D^?m9GZPcN&VF615 zDs||K+jA!Aj_>RIdg{&^k0R9j=DCx*DpDKf?3r`v)V9?n0n^Ij-<Wf2fFQqm+s*j< zzDIli)*@T|)am$Npoo_O>OWF_mfdI9*161xK{`|z{^_WeH8lbEqo#BllC*Y3k7MP# zm%OEDKHXfULxHQibp35pvr~!eyYc|fJ1q<1o4lTDIv4-`55=yo{?U6bR;XB+-}R9k z)FC?7@ysvzPd(YRbgBO{#~Kz_zg4}BHT&vl9a`QqylQ&WufN@#b1l3oKzCwY>g|k+ z^O~woB<s-DA6IQyvL-d)*r5Bn*Z;OKJX^0?-DB6MI<(>NnyP?vhaj=G{^x+>)9%Gw zsXcTrc{yXr$1T|{>l!C5Zer`uj`(IV^vBO+KIugU(`bk(JfV1?1SEqk!Ccr1<id}b z0!V8iXh;gC807O14=!veW}`@4png{*5R!-r%g8_jAmNA{C~xxKT^O{W?+U+huq#5j zRJYdjRH~oB2PQCz2m2-nb%&s)_#};I#g`Y#$#x;my8*)Y$hm1QOo^VxZyPU@MfeS| zvG^~B3vY-euM&hJ5OXbMs@qydYx%)znXPH#&L@Y0pD&Py!aJ>|c2GS{?V$Raw}U|$ z%b>y-rn2#Q@d2|m!GV0^zVTR#)s$nQL@7_t5@&(Xg!Ku^WW2|G4uU6kfB=W#76Gmi zN)Tt8?|UJ!I$delHMZOiHRi(jVlT248WretTQ4Uo^jo9)yF^fE`<tr9QpitMvBqNe z6zZZjZr0*Lkys;E8|#8gH=fOMV;#3MOJ%yZgL4v0*5MTDUYMtby(Pj0GYpJa^y>^f zxPcsquRg-P7EJmJp>K)bw<PzsxKt&)^;QR4a{wm3vf`s3zGK#r;G771Pk7fDHpg&T ziee?M8PouNyC=fFx)e=A`DE9<7<SlY#7C)7gPoO|uhh$Bav7E(P}nY2<SMX?yB5oG zWnQVlPULCIX)1GBp()BU$ZS%+RDsKPgg_3g(-aiqbF{KcTC5?vYM{e|)r6uWejzn} z2{LGL1)LO;GFpxApx~QG2`4u7p7~|*3Q~`}QZ=3uaNY+UdfZtUOTZlt#xh(g#K1Ym zGF&q~`na+b>;sac!{|GVz?I|jNUQb8<GH~BjR54!$o&j1-fty#1M1KoHIYrIle?FH z0d;-(e=q7Q4@^GrFw}z#_+ixhB0cKciS8un%aerjCm$2)e4D649Ug)@x##=8je5|o z$oX9@P~T%1RYSuJSnFpYJcHu<-Yy2zaSy<xOi))6)RiXG@vYxK&2@oI)CCVk-5KZq z-$uRnwTcy%T;GG&4sh(jHwi6|wlmCOj5<?*QD+jg^fSy~LOs$Z>M(;6`-5i~w|@ZY z^?fUUvf#QU&_u%P3s~<EuDcqzo=hysgzL$K>&dvadentrWE2pON4TmwWEV(^X#KpN ztxCdIJL8oGUz6Z4tapf%q)>A$Zu26zJCOuVWHpo}<8sOWKRgAa?mW(mP^wzlMwh6t z^uukKQK*>)?i(PGvPj!;0c{V%ywKJF8u+nFaIrQr(7+QtQ0lNzZN3?3=<EAX*!mCK zd^1od_cCI!`X&rCzXoQ*qFqAn^|!eOY5-p1Z@LD$V)=i2UI_9l+qlw#p}TAJkQ(p9 zf`nIIxUT{rcvvvBCt+w$(i7xAx6Bxd*H`%H@XEv0z)-jeRs=U3Nv$3mQ{`O5*#m{b z(aKaaT`N-!y8kasUAChh#p-q=>u&~nZuUjQopQX*x85@Pt&fPs?Awf~_*b1P{9rU^ zDi_ww_<vN&h@W9jZHKY${{Y51mTeTY%h;iK)r}84GyLtJGrGV3V{gf$_2b{)BWHB~ zvOaNzxx)5`@esQyx5?9#ay_G~79(99geD08^z^^0H67`VM{n_?=P<7a8DAz&Jt$?y zu!r!|<Y`K|o<VR<1gu2B%71+N-_@Fq^vt8T_|bEi*Tc@rM;|4B4RLey|0(H5Z}Fq& zFvkK|=>_`+?yyR7HhlCctn*@^DHXM_OI)X8!_Irf6oh8qBqBo1Iy4(qnMqY=QMJL= zq_drB-_x=*%QLmD2nDtEf?aM7sXeZ(KII8o=ju{eFF<H2Wt3{C*5-kf$JXWLP1TlC zr3E!aM!J?fs-Uz<cRLSiTYA%=Y|cZa9hV-S+xmQMDrBlF^o6}m|BQZmz;DBQy7oT^ zO`0@uA`TNLD)S(LkMiS6y{`P_9dog9QhE8L&97l=dHKXiZ@#P7Oj`93*viYLpT7*b zCzY?=rJM+sN#)z7;4e}zF4rJ{{I5RSzw4K|t6}!?f&VA=BOhP5neT1TvSD3{SDbiu z(|@|cPMSaX8a>?M?z}5<gP0ATIJQi&VI{o`W<Ll`5UTG&8bZrmhHjZnsiBT~;c9&y zxI<{E!|n}t7}Bv<?%e?$gqAx*cblo=kEyzU8<Y@QZWHA#X5}z`?)_V!gwS$}C~KLU z_;KIeuLUK9mRh2$W=P@=->U{4gqCWeyFn=`>TiGwLdy-Jx{7|idlfVgTCQSEbrnbu zTB?Y22_y(Dmxy!$BnT}RuyjsGfjhL_h`}QuV$u9+OUVL;=G%@{`}d!{eRlu;szwVe znrb;S`Ei@#_%j<UTHaWLX14Ir%=<M^GYBm;xUvn^j52<iB_8*$qj&1BgBOIB>!g8} zP*j2qLQ5sFT?7e2%S9sDhNAiyI74VY1{e{bNOZ<5{V*-D8<w_uindQ>w+>Jl`?!%0 z!|?3}q}FR7hK0^DSc*UZDkJC)1l&Y~o7U1Dut6XkMGbeTg;(k=Rks<rW2)}Ke^dZ# z5n(NAxW!cR$5aAq5wI2!)}n@5=4DLfT2MkDtVInq%#HlGBhYmSx(<=9L(p}4DkGpW zB2-2V*D1v}(02&>4w1e?4SFggpfVy<M%9&Ihd}xdRbK)L0--Xhz5o&gLgm)wRWnf9 z0*gP3Otl3l)fR9x-*T+nx9`lYGyC>cHd<g}L1{Bs8gHU9pmf>&n^0*8EjNLJsNoMr zDZljIAE1NK@(0%4zXp`P1{w%0*RZDg3P=!It`Nx*l8a!2Kq%c&NPyZ1sEshSt$=G? zz=8#kGZ#B3{JC5fh5w%n8O!drlq@>G;Wo9fs@_s{3x-VPJqsql=zt+}xy|Ufgoljf z=(vf8%;7fFki>m!Nsab~%oX&@-N(%jt07~Fg{5QxL$w6}mQr)A<K?}3f3E#`@7~Le z7Bfau4ZaF&|eSQ@JhLk6Y{vuWc788SCO2Z3Ay+Z!@fV2401fvEa2NDx{slL7Rv z95Uq23`E^X;%oAh^@X#3AYIU%@W8R|9UNZ*hYQ#6zhR#cU|0Ps4R8vM(!YHC&y<0e z!p?BbbRiG0GU`BNPHN0!OoD%rLsb0jW*zen5l{lLBdT<|s)!cUjF>?eE(A5BCZy}u zgy8aNwVbZ2F#r4|s~&EAH*lmxtHlydi!;c*d-#ue^517z%{R=2c%K&kdiRDEF#dRx z-}k27TeH1a@brUqupfANLfZ84Cb<}Jk6HiGr*N6xfR5hpAAXLG?Tt5x(eS%sSl&Uv zcTF0^RN;tv3k5?xeb_w<4O3mJO22QdD$Q%7(hRp$G1S^8EQ_L4BQ4K{GR><4TTrc4 zd(?Et0O&}m&0;ETM&nF0qtUE7O=2o<e{%)3M{2HZ6tgFPRZ;QPWB|6c<_%)zxSc!4 znPYKZtjjS+q9fJlhz~<NzOa_;YH@U>rG?|gI>uz<&K8I4Y)#ft8ndk}Mu7%yFPraV zQKgS2J}h^e)3vQp+gihQ7w(ok?5>G{y{&#m_L?aS>^0LE*=wmH?6p)8_L`{->^0Nq z*=wdC>}{1h(u4>3bPRw8<u=!wv$wTs7VK@+nzOf6X<~1y%D~=M+5B{WC2imVsw?Hd z1sK?i3|v8Vc^riIWhWy&oj?IstUO>Ztj!5~iKaP^f`10Wo3tGjAC|k#>Dtz)ZLK@j Td3N@8V2In<Ym3Z(3w!?`tYWDb literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditor.gui b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditor.gui new file mode 100644 index 000000000..a5259e821 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditor.gui @@ -0,0 +1,764 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(VerveEditorGui) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "728 714"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "VEditorDefaultProfile"; + hovertime = "1000"; + + new VEditorScrollControl(VerveEditorGroupScroll) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "right"; + VertSizing = "height"; + Position = "1 1"; + Extent = "212 663"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "alwaysOff"; + constantThumbHeight = "0"; + childMargin = "0 0"; + + new GuiScriptNotifyCtrl(VerveEditorGroupNotify) { + onChildAdded = "0"; + onChildRemoved = "0"; + onChildResized = "0"; + onParentResized = "1"; + onResize = "1"; + onLoseFirstResponder = "0"; + onGainFirstResponder = "0"; + canSaveDynamicFields = "0"; + class = "VerveEditorScrollNotifyV"; + className = "VerveEditorScrollNotifyV"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "212 1"; + MinExtent = "210 1"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new VEditorButton() { + class = "VerveEditorTimeLineBackground"; + canSaveDynamicFields = "1"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "0 0"; + Extent = "212 1"; + MinExtent = "210 1"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + text = ""; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + Context = "1"; + }; + new GuiStackControl(VerveEditorGroupStack) { + class = "VerveEditorStack"; + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "-1"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "212 1"; + MinExtent = "210 1"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + }; + }; + new VEditorScrollControl(VerveEditorTrackScroll) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "210 1"; + Extent = "516 663"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "alwaysOn"; + constantThumbHeight = "0"; + childMargin = "0 0"; + + new GuiScriptNotifyCtrl(VerveEditorTrackNotify) { + onChildAdded = "0"; + onChildRemoved = "0"; + onChildResized = "0"; + onParentResized = "1"; + onResize = "1"; + onLoseFirstResponder = "0"; + onGainFirstResponder = "0"; + canSaveDynamicFields = "0"; + class = "VerveEditorScrollNotify"; + className = "VerveEditorScrollNotify"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "516 32"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new VTimeLineControl(VerveEditorTrackTimeLine) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTimeLineProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "1100 32"; + MinExtent = "1100 32"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + IsController = "0"; + Controller = "VerveEditorController"; + Zoom = "0"; + + new VEditorButton() { + class = "VerveEditorTimeLineBackground"; + canSaveDynamicFields = "1"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "0 0"; + Extent = "516 32"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + text = ""; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + Context = "0"; + }; + new GuiStackControl(VerveEditorTrackStack) { + class = "VerveEditorStack"; + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "-1"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "516 32"; + MinExtent = "8 32"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + }; + }; + }; + new VEditorScrollControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "right"; + VertSizing = "top"; + Position = "1 661"; + Extent = "212 56"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiDefaultProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOn"; + vScrollBar = "alwaysOff"; + constantThumbHeight = "0"; + childMargin = "1 1"; + + new GuiControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "208 36"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiBitmapButtonCtrl(VerveEditorAddGroupButton) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + class = "VEditorAddGroupButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "3 3"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Add New Group"; + command = "$ThisControl.DisplayContextMenu();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_AddGroup"; + }; + new GuiBitmapButtonCtrl(VerveEditorAddTrackButton) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + class = "VEditorAddTrackButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "36 3"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Add New Track"; + command = "$ThisControl.DisplayContextMenu();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_AddTrack"; + }; + new GuiBitmapButtonCtrl(VerveEditorAddEventButton) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "69 3"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Add New Event"; + command = "VerveEditor::AddEvent();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_AddEvent"; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorBitmapButtonProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + Position = "175 3"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Delete Selected Object(s)"; + command = "VerveEditor::DeleteSelection();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_Delete"; + }; + }; + }; + new VEditorScrollControl(VerveEditorTimeScroll) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "top"; + Position = "210 661"; + Extent = "516 56"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOn"; + vScrollBar = "alwaysOn"; + constantThumbHeight = "0"; + childMargin = "0 0"; + + new GuiScriptNotifyCtrl(VerveEditorTimeNotify) { + onChildAdded = "0"; + onChildRemoved = "0"; + onChildResized = "0"; + onParentResized = "1"; + onResize = "1"; + onLoseFirstResponder = "0"; + onGainFirstResponder = "0"; + canSaveDynamicFields = "0"; + class = "VerveEditorScrollNotifyH"; + className = "VerveEditorScrollNotifyH"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "516 41"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new VTimeLineControl(VerveEditorTimeLine) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTimeLineProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1100 41"; + MinExtent = "1100 41"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + IsController = "1"; + Controller = "VerveEditorController"; + Zoom = "0"; + }; + }; + }; + }; + new VEditorScrollControl(VerveEditorPropertyScroll) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "left"; + VertSizing = "height"; + Position = "723 1"; + Extent = "300 766"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "alwaysOn"; + constantThumbHeight = "0"; + childMargin = "3 3"; + + new GuiStackControl(VerveEditorPropertyStack) { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "2"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "3 3"; + Extent = "279 256"; + MinExtent = "16 16"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + }; + new VEditorScrollControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "right"; + VertSizing = "top"; + Position = "1 713"; + Extent = "212 54"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiDefaultProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "alwaysOff"; + constantThumbHeight = "0"; + childMargin = "1 1"; + + new GuiControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "208 36"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + }; + new VEditorScrollControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "top"; + Position = "210 713"; + Extent = "516 54"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiDefaultProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "alwaysOn"; + constantThumbHeight = "0"; + childMargin = "1 1"; + + new GuiControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "2 2"; + Extent = "500 50"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiControl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "center"; + VertSizing = "bottom"; + Position = "114 10"; + Extent = "258 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorBitmapButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "50 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Jump Backwards"; + command = "VerveEditor::Rewind();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_Rewind"; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "52 0"; + Extent = "50 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Step Backwards 1 Frame"; + command = "VerveEditor::StepB();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_StepB"; + }; + new GuiBitmapButtonCtrl(VerveEditorPlayButton) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "104 0"; + Extent = "50 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Play / Pause"; + command = "VerveEditor::TogglePlay( $ThisControl );"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_Play"; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "156 0"; + Extent = "50 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Step Forward 1 Frame"; + command = "VerveEditor::StepF();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_StepF"; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorBitmapButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "208 0"; + Extent = "50 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Jump Forward"; + command = "VerveEditor::Forward();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_Forward"; + }; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "10 10"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Insert Time (Front)"; + command = "VerveEditor::InsertTimeFront();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_AddL"; + }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "VEditorTransparentProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + Position = "460 10"; + Extent = "30 30"; + MinExtent = "8 2"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + tooltip = "Insert Time (Back)"; + command = "VerveEditor::InsertTimeBack();"; + hovertime = "1000"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "./Images/btn_AddR"; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorGroupBuilder.gui b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorGroupBuilder.gui new file mode 100644 index 000000000..c1cf41dc7 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorGroupBuilder.gui @@ -0,0 +1,434 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(VerveEditorGroupBuilderGUI) { + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiWindowCtrl(VerveEditorGroupBuilderWindow) { + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Create Group"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "center"; + VertSizing = "center"; + position = "268 181"; + Extent = "280 178"; + MinExtent = "256 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Label:"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "14 30"; + Extent = "84 16"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(VerveEditorGroupBuilderNameField) { + historySize = "0"; + password = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + passwordMask = "*"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + position = "79 29"; + Extent = "191 18"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapBorderCtrl() { + isContainer = "0"; + Profile = "GuiGroupBorderProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + position = "7 55"; + Extent = "267 70"; + MinExtent = "1 1"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiStackControl(VerveEditorGroupBuilderFieldStack) { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "2"; + ChangeChildSizeToFit = "1"; + ChangeChildPosition = "1"; + isContainer = "1"; + Profile = "GuiTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "3 3"; + Extent = "261 20"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiControl() { + isContainer = "1"; + Profile = "GuiTransparentProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 0"; + Extent = "261 20"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Scene Object:"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "center"; + position = "4 1"; + Extent = "100 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiPopUpMenuCtrl() { + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "VEditorPopupMenuProfile"; + HorizSizing = "left"; + VertSizing = "center"; + position = "104 1"; + Extent = "156 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + internalName = "SceneObjectList"; + canSaveDynamicFields = "0"; + }; + }; + }; + }; + new GuiButtonCtrl() { + text = "Create"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "top"; + position = "66 139"; + Extent = "96 24"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + Command = "VerveEditorGroupBuilderGUI._Build( VerveEditorGroupBuilderNameField.getText() );"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Cancel"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "top"; + position = "174 139"; + Extent = "96 24"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + Command = "VerveEditorGroupBuilderGUI.Close();"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +function VerveEditorGroupBuilderGUI::Build( %this, %groupType, %callbackMethod ) +{ + if ( %callbackMethod $= "" ) + { + return; + } + + // Store Info. + %this.GroupType = %groupType; + %this.CallbackMethod = %callbackMethod; + + // Clear Text. + VerveEditorGroupBuilderNameField.setText( "" ); + + // Clear Stack. + VerveEditorGroupBuilderFieldStack.clear(); + + // Populate the Field Stack. + eval( %groupType @ "::PopulateBuildStack( 0, " @ VerveEditorGroupBuilderFieldStack @ ");" ); + + // Display. + if($Verve::UseSeparateWindow) + VerveEditorWindow.pushDialog( %this ); + else + Canvas.pushDialog( %this ); + + + // Resize Everything. + %container = VerveEditorGroupBuilderFieldStack.getParent(); + %stackExtent = VerveEditorGroupBuilderFieldStack.getExtent(); + %stackPosition = VerveEditorGroupBuilderFieldStack.getPosition(); + %containerExtent = %container.getExtent(); + %containerHeight = ( VerveEditorGroupBuilderFieldStack.getCount() > 0 ) ? getWord( %stackExtent, 1 ) + 2 * getWord( %stackPosition, 1 ) : 1; + %containerHeightDelta = %containerHeight - getWord( %containerExtent, 1 ); + %container.setExtent( getWord( %containerExtent, 0 ), %containerHeight ); + + %windowExtent = VerveEditorGroupBuilderWindow.getExtent(); + VerveEditorGroupBuilderWindow.setExtent( getWord( %windowExtent, 0 ), getWord( %windowExtent, 1 ) + %containerHeightDelta ); +} + +function VerveEditorGroupBuilderGUI::Close( %this ) +{ + if($Verve::UseSeparateWindow) + VerveEditorWindow.popDialog( %this ); + else + Canvas.popDialog( %this ); +} + +function VerveEditorGroupBuilderGUI::_Build( %this, %groupLabel ) +{ + if ( %groupLabel $= "" ) + { + messageBox( "Warning", "You must provide a Valid Group Label.", "Ok" ); + return; + } + + if ( %this.CallbackMethod $= "" ) + { + // Close Dialog. + if($Verve::UseSeparateWindow) + VerveEditorWindow.popDialog( %this ); + else + Canvas.popDialog( %this ); + return; + } + + // Eval Method. + eval( %this.CallbackMethod @ "(" @ %this.GroupType @ "," @ %groupLabel @ ");" ); + + // Clear. + %this.CallbackMethod = ""; + + // Close Dialog. + if($Verve::UseSeparateWindow) + VerveEditorWindow.popDialog( %this ); + else + Canvas.popDialog( %this ); +} + +//----------------------------------------------------------------------------- + +function VerveEditorGroupBuilderFieldStack::CreateObjectList( %this, %objectType, %internalName, %label ) +{ + %container = new GuiControl() + { + Profile = "GuiTransparentProfile"; + + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "261 20"; + }; + + %label = new GuiTextCtrl() + { + Profile = "GuiTextProfile"; + + HorizSizing = "right"; + VertSizing = "center"; + Position = "4 1"; + Extent = "100 18"; + + Text = %label; + }; + %container.add( %label ); + + %listObject = new GuiPopUpMenuCtrl() + { + Class = "VerveEditorGroupBuilderObjectList"; + Profile = "VEditorPopupMenuProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = "104 1"; + Extent = "156 18"; + + InternalName = %internalName; + }; + %container.add( %listObject ); + + // Create NULL Entry. + %listObject.add( "", 0 ); + + // Populate List. + %listObject.CheckGroup( MissionGroup, %objectType ); + + // Sort the List. + %listObject.sort(); + + %this.add( %container ); + + return %listObject; +} + +function VerveEditorGroupBuilderObjectList::CheckGroup( %this, %group, %objectType ) +{ + // Populate List. + %groupSize = %group.getCount(); + for ( %i = 0; %i < %groupSize; %i++ ) + { + %groupObject = %group.getObject( %i ); + if ( %groupObject.getName() $= "" ) + { + continue; + } + + if ( %groupObject.isMemberOfClass( %objectType ) ) + { + %this.add( %groupObject.getName(), %this.size() ); + } + else if ( %groupObject.isMemberOfClass( "SimSet" ) ) + { + %this.CheckGroup( %groupObject, %objectType ); + } + } +} + +function VerveEditorGroupBuilderFieldStack::CreateCheckbox( %this, %internalName, %label ) +{ + %container = new GuiControl() + { + Profile = "GuiTransparentProfile"; + + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "261 20"; + }; + + %label = new GuiTextCtrl() + { + Profile = "GuiTextProfile"; + + HorizSizing = "right"; + VertSizing = "center"; + Position = "4 1"; + Extent = "100 18"; + + Text = %label; + }; + %container.add( %label ); + + %checkBox = new GuiCheckBoxCtrl() + { + Profile = "GuiCheckboxProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = "104 1"; + Extent = "156 18"; + + InternalName = %internalName; + + Text = ""; + }; + %container.add( %checkBox ); + + %this.add( %container ); + + return %checkBox; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorImportPathNodes.gui b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorImportPathNodes.gui new file mode 100644 index 000000000..6ec7b430c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorImportPathNodes.gui @@ -0,0 +1,133 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(VerveEditorImportPathNodesGUI) { + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "1"; + + new GuiWindowCtrl() { + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Import Path Nodes"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "center"; + VertSizing = "center"; + Position = "268 181"; + Extent = "280 98"; + MinExtent = "256 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Speed:"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "14 30"; + Extent = "84 16"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(VerveEditorImportPathNodesSpeed) { + historySize = "0"; + password = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + passwordMask = "*"; + maxLength = "1024"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "79 29"; + Extent = "191 18"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Create"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "top"; + Position = "66 62"; + Extent = "96 24"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + Command = "VMotionTrack::_ImportPathNodes( VerveEditorImportPathNodesSpeed.getText() );"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Cancel"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "left"; + VertSizing = "top"; + Position = "174 62"; + Extent = "96 24"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + Command = "VerveEditorWindow.popDialog( VerveEditorImportPathNodesGUI );"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorPreferences.gui b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorPreferences.gui new file mode 100644 index 000000000..31579a5fb --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/GUI/VerveEditorPreferences.gui @@ -0,0 +1,367 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(VerveEditorPreferenceGui) { + canSaveDynamicFields = "0"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiWindowCtrl() { + canSaveDynamicFields = "0"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "center"; + VertSizing = "center"; + position = "392 253"; + Extent = "240 262"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "None"; + Margin = "4 24 4 4"; + Padding = "4 24 4 4"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "0"; + canClose = "1"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + closeCommand = "VerveEditor::CloseEditorPreferences();"; + EdgeSnap = "1"; + canCollapse = "0"; + CollapseGroup = "-1"; + CollapseGroupNum = "-1"; + text = "Verve Editor - Preferences"; + + new GuiControl() { + canSaveDynamicFields = "0"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "10 93"; + Extent = "220 125"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiBitmapBorderCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiBitmapBorderProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "0 10"; + Extent = "221 116"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + class = "VerveEditorPreferenceLabel"; + Profile = "VEditorPreferenceLabelProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "10 2"; + Extent = "66 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = " Event Snap "; + maxLength = "1024"; + }; + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "30 50"; + Extent = "110 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Threshold:"; + maxLength = "1024"; + }; + new GuiCheckBoxCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiCheckBoxProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "6 30"; + Extent = "128 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Variable = "$Pref::VerveEditor::Event::SnapToTime"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + text = " Snap to Time"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + useInactiveState = "0"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "150 50"; + Extent = "64 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Variable = "$Pref::VerveEditor::Event::SnapToTimeThreshold"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + maxLength = "1024"; + historySize = "0"; + password = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + passwordMask = "*"; + }; + new GuiCheckBoxCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiCheckBoxProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "6 80"; + Extent = "128 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Variable = "$Pref::VerveEditor::Event::SnapToSiblings"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + text = " Snap to Siblings"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + useInactiveState = "0"; + }; + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "30 100"; + Extent = "110 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Threshold:"; + maxLength = "1024"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "150 100"; + Extent = "64 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Variable = "$Pref::VerveEditor::Event::SnapToSiblingThreshold"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + maxLength = "1024"; + historySize = "0"; + password = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + passwordMask = "*"; + }; + }; + new GuiControl() { + canSaveDynamicFields = "0"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "10 30"; + Extent = "220 53"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiBitmapBorderCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiBitmapBorderProfile"; + HorizSizing = "width"; + VertSizing = "height"; + position = "0 10"; + Extent = "221 44"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + class = "VerveEditorPreferenceLabel"; + Profile = "VEditorPreferenceLabelProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "10 2"; + Extent = "70 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = " Recent Files "; + maxLength = "1024"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "6 30"; + Extent = "40 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Variable = "$Pref::VerveEditor::RecentFileSize"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + maxLength = "1024"; + historySize = "0"; + password = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + passwordMask = "*"; + }; + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiTextProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "56 30"; + Extent = "158 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "items shown in Window Menu"; + maxLength = "1024"; + }; + }; + new GuiButtonCtrl() { + canSaveDynamicFields = "0"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "151 228"; + Extent = "80 24"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "VerveEditor::CloseEditorPreferences();"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + text = "OK"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +function VerveEditorPreferenceLabel::onWake( %this ) +{ + %this.setActive( false ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/btn_AddSml.psd b/Templates/BaseGame/game/tools/VerveEditor/GUI/btn_AddSml.psd new file mode 100644 index 0000000000000000000000000000000000000000..20ce53d2e24df199c3530a0a54569f7df11bc6e9 GIT binary patch literal 29278 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/GUI/btn_Palette.psd b/Templates/BaseGame/game/tools/VerveEditor/GUI/btn_Palette.psd new file mode 100644 index 0000000000000000000000000000000000000000..52b4a1f32fd7048345934f4365d975bf087c7995 GIT binary patch literal 30228 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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VController.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VController.cs new file mode 100644 index 000000000..99e8cc04c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VController.cs @@ -0,0 +1,362 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VControllerPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + + Group[0] = "VController"; + Field[0, 0] = "Duration"; + Field[0, 1] = "TimeScale"; + + Field[0, 2] = "SPACER 6"; + + Field[0, 3] = "Loop"; + Field[0, 4] = "LoopBackwards"; + Field[0, 5] = "LoopCount"; + Field[0, 6] = "LoopDelay"; + + Field[0, 7] = "SPACER 6"; + + Field[0, 8] = "ResetOnCompletion"; +}; + +//----------------------------------------------------------------------------- + +function VerveEditor::TogglePlay() +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + // No Controller. + return; + } + + if ( !$VerveEditor::Controller.isPlaying() ) + { + // Play. + VerveEditor::Play(); + } + else + { + // Pause. + VerveEditor::Pause(); + } +} + +function VerveEditor::Play() +{ + // Start Playing. + $VerveEditor::Controller.play(); +} + +function VerveEditor::Pause() +{ + // Stop but do not Reset. + $VerveEditor::Controller.stop( false ); +} + +function VerveEditor::StepF() +{ + // Determine the time to step towards. + %time = mClamp( $VerveEditor::Controller.Time + ( 32 * $VerveEditor::Controller.TimeScale ), 0.0, $VerveEditor::Controller.Duration ); + // Reset. + $VerveEditor::Controller.reset( %time ); +} + +function VerveEditor::StepB() +{ + // Switch TimeScale. + $VerveEditor::Controller.TimeScale *= -1.0; + // Step. + VerveEditor::StepF(); + // Switch Back TimeScale. + $VerveEditor::Controller.TimeScale *= -1.0; +} + +function VerveEditor::Rewind() +{ + if ( $VerveEditor::Controller.TimeScale > 0 ) + { + // Front. + $VerveEditor::Controller.reset( 0 ); + } + else + { + // Back. + $VerveEditor::Controller.reset( $VerveEditor::Controller.Duration ); + } +} + +function VerveEditor::Forward() +{ + if ( $VerveEditor::Controller.TimeScale < 0 ) + { + // Front. + $VerveEditor::Controller.reset( 0 ); + } + else + { + // Back. + $VerveEditor::Controller.reset( $VerveEditor::Controller.Duration ); + } +} + +function VerveEditor::InsertTimeFront() +{ + %time = 0; + %length = 1000; + + VerveEditor::InsertTime( %time, %length ); +} + +function VerveEditor::InsertTimeBack() +{ + %time = $VerveEditor::Controller.Duration; + %length = 1000; + + VerveEditor::InsertTime( %time, %length ); +} + +function VerveEditor::InsertTime( %time, %length ) +{ + if ( %length <= 0 ) + { + return; + } + + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + // Increase Duration. + $VerveEditor::Controller.setFieldValue( "Duration", $VerveEditor::Controller.Duration + %length ); + + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %trackSet = %groupSet.getObject( %i ); + %trackCount = %trackSet.getCount(); + for ( %j = 0; %j < %trackCount; %j++ ) + { + %eventSet = %trackSet.getObject( %j ); + %eventCount = %eventSet.getCount(); + for ( %k = 0; %k < %eventCount; %k++ ) + { + %eventSet.getObject( %k ).InsertTime( %time, %length ); + } + } + } + + if ( %time < $VerveEditor::Controller.Time ) + { + // Update Time. + $VerveEditor::Controller.setFieldValue( "Time", $VerveEditor::Controller.Time + %length ); + } + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); +} + +function VerveEditor::DeleteTime( %time, %length ) +{ + if ( %length <= 0 ) + { + return; + } + + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %trackSet = %groupSet.getObject( %i ); + %trackCount = %trackSet.getCount(); + for ( %j = 0; %j < %trackCount; %j++ ) + { + %eventSet = %trackSet.getObject( %j ); + %eventCount = %eventSet.getCount(); + for ( %k = 0; %k < %eventCount; %k++ ) + { + %eventObject = %eventSet.getObject( %k ); + if ( %eventObject.DeleteTime( %time, %length ) ) + { + // Delete. + %eventObject.delete(); + + // Backstep. + %k -= 1; + %eventCount -= 1; + } + } + } + } + + // Decrease Duration. + $VerveEditor::Controller.setFieldValue( "Duration", $VerveEditor::Controller.Duration - %length ); + + if ( $VerveEditor::Controller.Time > %time && $VerveEditor::Controller.Time < ( %time + %length ) ) + { + // Clamp. + $VerveEditor::Controller.setFieldValue( "Time", %time ); + } + else if ( $VerveEditor::Controller.Time >= ( %time + %length ) ) + { + // Push Back. + $VerveEditor::Controller.setFieldValue( "Time", $VerveEditor::Controller.Time - %length ); + } + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + // Refresh Editor. + VerveEditor::Refresh(); +} + +function VEvent::InsertTime( %this, %time, %length ) +{ + %triggerTime = %this.getFieldValue( "TriggerTime" ); + %triggerDuration = %this.getFieldValue( "Duration" ); + + if ( %time <= %triggerTime ) + { + %this.setFieldValue( "TriggerTime", %triggerTime + %length ); + } + else if ( %time > %triggerTime && %time < %triggerTime + %triggerDuration ) + { + %this.setFieldValue( "Duration", %triggerDuration + %length ); + } +} + +function VEvent::DeleteTime( %this, %time, %length ) +{ + %triggerTime = %this.getFieldValue( "TriggerTime" ); + %triggerDuration = %this.getFieldValue( "Duration" ); + + if ( %triggerTime >= %time && %triggerTime <= ( %time + %length ) ) + { + %tail = ( %triggerTime + %triggerDuration ) - ( %time + %length ); + if ( %tail > 0 ) + { + // Trim Duration. + %this.setFieldValue( "TriggerTime", %time ); + %this.setFieldValue( "Duration", %tail ); + } + else + { + // Delete This Event. + return true; + } + } + else if ( %triggerTime > %time ) + { + // Shuffle Back. + %this.setFieldValue( "TriggerTime", %triggerTime - %length ); + } + else if ( %triggerTime < %time && ( %triggerTime + %triggerDuration ) > %time ) + { + // Trim Duration. + %this.setFieldValue( "Duration", ( %triggerTime + %triggerDuration ) - %time ); + } + + // No Delete. + return false; +} + +//------------------------------------------------------------------------ + +function VerveEditorController::CanPaste( %this, %targetObject ) +{ + if ( !isObject( %targetObject ) ) + { + // Nope! + return false; + } + + if ( !%this.CanAdd( %targetObject.getClassName() ) ) + { + // Nope! + return false; + } + + return %targetObject.isMemberOfClass( "VGroup" ); +} + +function VerveEditorController::CanAdd( %this, %targetClass ) +{ + if ( !isWordInList( %targetClass, $VerveEditor::UniqueGroupList ) ) + { + // Not a Unique Group. + return true; + } + + %groupCount = %this.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %groupObject = %this.getObject( %i ); + if ( %groupObject.isMemberOfClass( %targetClass ) ) + { + // Invalid. + return false; + } + } + + // All Good. + return true; +} + +function VerveEditorController::onPlay( %this ) +{ + // Update Play Button. + VerveEditorPlayButton.setBitmap( "tools/VerveEditor/GUI/Images/btn_Pause" ); + + // Start Update Event. + VerveEditorTimeLine.ControllerUpdate(); +} + +function VerveEditorController::onPause( %this ) +{ + // Update Play Button. + VerveEditorPlayButton.setBitmap( "tools/VerveEditor/GUI/Images/btn_Play" ); + + // Stop Update Event. + VerveEditorTimeLine.StopUpdate(); +} + +function VerveEditorController::onStop( %this ) +{ + // Update Play Button. + VerveEditorPlayButton.setBitmap( "tools/VerveEditor/GUI/Images/btn_Play" ); + + // Stop Update Event. + VerveEditorTimeLine.StopUpdate(); +} + +function VerveEditorController::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + if ( !VerveEditorHistoryManager.Locked ) + { + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryChangeProperty"; + SuperClass = "VerveEditorHistoryObject"; + + ActionName = "Change Property (" @ %fieldName @ ")"; + + // Store References. + Object = %this; + FieldName = %fieldName; + OldValue = %oldValue; + NewValue = %newValue; + }; + } + + switch$ ( %fieldName ) + { + case "Duration" : VerveEditor::UpdateDuration(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VControllerProperties.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VControllerProperties.cs new file mode 100644 index 000000000..b3bd39d5c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/VControllerProperties.cs @@ -0,0 +1,217 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VControllerPropertyList::CreateInspectorGroup( %this, %targetStack ) +{ + %baseGroup = Parent::CreateInspectorGroup( %this, %targetStack ); + if ( %baseGroup.getClassName() !$= "ScriptGroup" ) + { + // Temp Store. + %temp = %baseGroup; + + // Create SimSet. + %baseGroup = new SimSet(); + + // Add Original Control. + %baseGroup.add( %temp ); + } + + // Create Data Table Group. + %groupRollout = %targetStack.CreatePropertyRollout( "VController DataTable" ); + %propertyStack = %groupRollout.Stack; + + // Reference. + %propertyStack.InternalName = "DataTableStack"; + + // Store. + %baseGroup.add( %groupRollout ); + + // Return. + return %baseGroup; +} + +function VControllerPropertyList::InspectObject( %this, %object ) +{ + if ( !%object.isMemberOfClass( "VController" ) ) + { + // Invalid Object. + return; + } + + // Default Inspect. + Parent::InspectObject( %this, %object ); + + // Update Data Table. + %dataTableStack = %this.ControlCache.findObjectByInternalName( "DataTableStack", true ); + if ( !isObject( %dataTableStack ) ) + { + // Invalid Table. + return; + } + + // Clear Stack. + while ( %dataTableStack.getCount() > 1 ) + { + // Delete Object. + %dataTableStack.getObject( 1 ).delete(); + } + + %dataFieldCount = %object.getDataFieldCount(); + for ( %i = 0; %i < %dataFieldCount; %i++ ) + { + // Add To List. + %dataFieldList = trim( %dataFieldList SPC %object.getDataFieldName( %i ) ); + } + + // Sort Word List. + %dataFieldList = sortWordList( %dataFieldList ); + + for ( %i = 0; %i < %dataFieldCount; %i++ ) + { + // Fetch Field Name. + %dataFieldName = getWord( %dataFieldList, %i ); + + // Create Field. + VerveEditor::CreateField( %dataTableStack, %dataFieldName, "Data" ); + } + + // Create Add Field. + VerveEditor::CreateAddDataField( %dataTableStack ); + + // Update. + %dataTableStack.InspectObject( %object ); +} + +function VController::DisplayContextMenu( %this, %x, %y ) +{ + %contextMenu = $VerveEditor::VController::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VControllerContextMenu"; + Position = 0; + + Item[0] = "Add Group" TAB ""; + + Item[1] = "" TAB ""; + + Item[2] = "Cu&t" TAB "" TAB ""; + Item[3] = "&Copy" TAB "" TAB ""; + Item[4] = "&Paste" TAB "" TAB "VerveEditor::Paste();"; + + Item[5] = "" TAB ""; + + Item[6] = "&Delete" TAB "" TAB ""; + + PasteIndex = 4; + }; + %contextMenu.Init(); + + // Disable Cut, Copy & Delete. + %contextMenu.enableItem( 2, false ); + %contextMenu.enableItem( 3, false ); + %contextMenu.enableItem( 6, false ); + + // Cache. + $VerveEditor::VController::ContextMenu = %contextMenu; + } + + // Remove Add Menu. + %contextMenu.removeItem( %contextMenu.AddIndex ); + + // Insert Menu. + %contextMenu.insertSubMenu( %contextMenu.AddIndex, getField( %contextMenu.Item[0], 0 ), %this.GetAddGroupMenu() ); + + // Enable/Disable Pasting. + %contextMenu.enableItem( %contextMenu.PasteIndex, VerveEditor::CanPaste() ); + + if ( %x $= "" || %y $= "" ) + { + %position = %this.getGlobalPosition(); + %extent = %this.getExtent(); + + %x = getWord( %position, 0 ) + getWord( %extent, 0 ); + %y = getWord( %position, 1 ); + } + + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); +} + +function VController::GetAddGroupMenu( %this ) +{ + %contextMenu = $VerveEditor::VController::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %customTemplateMenu = new PopupMenu() + { + Class = "VerveCustomTemplateMenu"; + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VGroupAddGroupMenu"; + Position = 0; + }; + %customTemplateMenu.Init(); + + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VGroupAddGroupMenu"; + Position = 0; + + Item[0] = "Add Camera Group" TAB "" TAB "VerveEditor::AddGroup(\"VCameraGroup\");"; + Item[1] = "Add Director Group" TAB "" TAB "VerveEditor::AddGroup(\"VDirectorGroup\");"; + Item[2] = "Add Light Object Group" TAB "" TAB "VerveEditor::AddGroup(\"VLightObjectGroup\");"; + Item[3] = "Add Particle Effect Group" TAB "" TAB "VerveEditor::AddGroup(\"VParticleEffectGroup\");"; + Item[4] = "Add Scene Object Group" TAB "" TAB "VerveEditor::AddGroup(\"VSceneObjectGroup\");"; + Item[5] = "Add Spawn Sphere Group" TAB "" TAB "VerveEditor::AddGroup(\"VSpawnSphereGroup\");"; + + Item[6] = "" TAB ""; + + Item[7] = "Add Custom Group" TAB %customTemplateMenu; + + DirectorIndex = 1; + CustomIndex = 7; + CustomMenu = %customTemplateMenu; + }; + %contextMenu.Init(); + + // Refresh Menu. + %customTemplateMenu = %contextMenu.CustomMenu; + if ( %customTemplateMenu.getItemCount() == 0 ) + { + // Remove Item. + %contextMenu.removeItem( %contextMenu.CustomIndex ); + + // Add Dummy. + %contextMenu.insertItem( %contextMenu.CustomIndex, getField( %contextMenu.Item[%contextMenu.CustomIndex], 0 ) ); + + // Disable Custom Menu. + %contextMenu.enableItem( %contextMenu.CustomIndex, false ); + } + + // Cache. + $VerveEditor::VController::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable / Disable Director Group. + %contextMenu.enableItem( %contextMenu.DirectorIndex, %this.CanAdd( "VDirectorGroup" ) ); + + // Return Menu. + return %contextMenu; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/main.cs new file mode 100644 index 000000000..7410f038c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Controller/main.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitControllerScripts() +{ + // Core. + exec( "./VController.cs" ); + exec( "./VControllerProperties.cs" ); + + // Custom. + // Exec Custom Controller Scripts. +} +VerveEditor::InitControllerScripts(); diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorControls.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorControls.cs new file mode 100644 index 000000000..499133eed --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorControls.cs @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::DeleteControls() +{ + while ( VerveEditorGroupStack.getCount() > 0 ) + { + VerveEditorGroupStack.getObject( 0 ).delete(); + } + + while ( VerveEditorTrackStack.getCount() > 0 ) + { + VerveEditorTrackStack.getObject( 0 ).delete(); + } +} + +function VerveEditorStack::FindControl( %this, %object ) +{ + %trackCount = %this.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %track = %this.getObject( %i ); + if ( %track.Proxy.getId() == %object.getId() ) + { + return %track; + } + } + + return -1; +} + +function VerveEditorStack::FindControlIndex( %this, %object ) +{ + %trackCount = %this.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %track = %this.getObject( %i ); + if ( %track.Proxy.getId() == %object.getId() ) + { + return %i; + } + } + + return -1; +} + +//------------------------------------------------------------------------- + +function VerveEditorTimeLine::onLoseFirstResponder( %this ) +{ + // Clear Selection. + %this.setSelection( false ); + + // Force OnSelectionUpdate. + %this.onSelectionUpdate(); +} + +function VerveEditorTimeLine::StopUpdate( %this ) +{ + // Cancel Event. + cancel( $VerveEditor::Controller::TickEvent ); +} + +function VerveEditorTimeLine::ControllerUpdate( %this ) +{ + // Cancel Event. + cancel( $VerveEditor::Controller::TickEvent ); + + %scrollParent = %this.getParentOfType( "VEditorScrollControl" ); + if ( !isObject( %scrollParent ) ) + { + // Woops! + return; + } + + // Fetch Point. + %point = %this.toPoint( $VerveEditor::Controller.Time ); + + // Fetch Scroll Point. + %scrollPoint = %scrollParent.getScrollPositionX(); + %scrollWidth = getWord( %scrollParent.getExtent(), 0 ) - 19; + + if ( ( %point < %scrollPoint ) || ( %point > ( %scrollPoint + %scrollWidth ) ) ) + { + // Scroll To View Time. + %scrollParent.setScrollPosition( %point - %scrollWidth * 0.50, 0 ); + } + + // Schedule Next Event. + $VerveEditor::Controller::TickEvent = %this.schedule( 100, "ControllerUpdate" ); +} + +function VerveEditorTimeLine::onSelectionUpdate( %this ) +{ + // Fetch Selection. + %selectionString = %this.getSelection(); + + %selectionActive = getWord( %selectionString, 0 ); + if ( !%selectionActive ) + { + // Clear Selection. + VerveEditorTrackTimeLine.setSelection( false ); + } + else + { + if ( !getWord( VerveEditorTrackTimeLine.getSelection(), 0 ) ) + { + // Clear Editor Selection. + VerveEditor::ClearSelection(); + } + + // Set Selection. + VerveEditorTrackTimeLine.setSelection( true, getWord( %selectionString, 1 ), getWord( %selectionString, 2 ) ); + } +} + +function VerveEditorTimeLine::onSelectionRightClick( %this, %point, %modifiers, %clickCount ) +{ + %this.DisplayContextMenu( getWord( %point, 0 ), getWord( %point, 1 ) ); +} + +function VerveEditorTimeLine::DisplayContextMenu( %this, %x, %y ) +{ + %contextMenu = $VerveEditor::VTimeLine::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VTimeLineMenu"; + Position = 0; + + Item[0] = "Insert Time Before" TAB "" TAB "VerveEditorTimeLine.InsertTimeBefore();"; + Item[1] = "Insert Time After" TAB "" TAB "VerveEditorTimeLine.InsertTimeAfter();"; + + Item[2] = "" TAB ""; + + Item[3] = "Delete Time" TAB "" TAB "VerveEditorTimeLine.DeleteTime();"; + + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VTimeLine::ContextMenu = %contextMenu; + } + + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); + +} + +function VerveEditorTimeLine::InsertTimeBefore( %this ) +{ + // Fetch Selection. + %selectionString = %this.getSelection(); + %selectionActive = getWord( %selectionString, 0 ); + if ( !%selectionActive ) + { + // Woops! + return; + } + + // Determine Position. + %selectionPosition = getWord( %selectionString, 1 ); + + // Insert Time. + VerveEditor::InsertTime( %selectionPosition, getWord( %selectionString, 2 ) ); +} + +function VerveEditorTimeLine::InsertTimeAfter( %this ) +{ + // Fetch Selection. + %selectionString = %this.getSelection(); + %selectionActive = getWord( %selectionString, 0 ); + if ( !%selectionActive ) + { + // Woops! + return; + } + + // Determine Position. + %selectionPosition = getWord( %selectionString, 1 ) + getWord( %selectionString, 2 ); + + // Insert Time. + VerveEditor::InsertTime( %selectionPosition, getWord( %selectionString, 2 ) ); +} + +function VerveEditorTimeLine::DeleteTime( %this ) +{ + // Fetch Selection. + %selectionString = %this.getSelection(); + %selectionActive = getWord( %selectionString, 0 ); + if ( !%selectionActive ) + { + // Woops! + return; + } + + // Determine Position. + %selectionPosition = getWord( %selectionString, 1 ); + + // Delete Time. + VerveEditor::DeleteTime( %selectionPosition, getWord( %selectionString, 2 ) ); + + // Clear Selection. + %this.setSelection( false ); + + // Force OnSelectionUpdate. + %this.onSelectionUpdate(); +} + +//------------------------------------------------------------------------- + +function VerveEditorTimeLineBackground::onMouseUp( %this, %point, %modifiers, %clickCount ) +{ + // Clear Selection. + VerveEditor::ClearSelection(); +} + +function VerveEditorTimeLineBackground::onRightMouseUp( %this, %point, %modifiers, %clickCount ) +{ + // Clear Selection. + VerveEditor::ClearSelection(); + + if ( !%this.Context ) + { + // Return. + return; + } + + // Display Context Menu. + $VerveEditor::Controller.schedule( 32, "DisplayContextMenu", getWord( %point, 0 ), getWord( %point, 1 ) ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorHistory.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorHistory.cs new file mode 100644 index 000000000..80866fcb8 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorHistory.cs @@ -0,0 +1,265 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +$VerveEditor::HistoryManager = new UndoManager( VerveEditorHistoryManager ); +$VerveEditor::UndoCount = 0; +$VerveEditor::RedoCount = 0; + +//----------------------------------------------------------------------------- + +function VerveEditor::IsDirty() +{ + if ( !isObject( VerveEditorHistoryManager ) ) + { + // Woops! + return false; + } + + return !( ( VerveEditorHistoryManager.getUndoCount() == $VerveEditor::UndoCount ) + && ( VerveEditorHistoryManager.getRedoCount() == $VerveEditor::RedoCount ) ); +} + +function VerveEditor::ClearDirty() +{ + // Reset. + $VerveEditor::UndoCount = VerveEditorHistoryManager.getUndoCount(); + $VerveEditor::RedoCount = VerveEditorHistoryManager.getRedoCount(); +} + +function VerveEditor::ClearHistory() +{ + // Clear History. + VerveEditorHistoryManager.clearAll(); + + // Clear Dirty. + VerveEditor::ClearDirty(); +} + +function VerveEditor::CanUndo() +{ + return ( VerveEditorHistoryManager.getUndoCount() > 0 ); +} + +function VerveEditor::Undo() +{ + VerveEditorHistoryManager.Undo(); + + // Refresh. + VerveEditor::Refresh(); +} + +function VerveEditor::CanRedo() +{ + return ( VerveEditorHistoryManager.getRedoCount() > 0 ); +} + +function VerveEditor::Redo() +{ + VerveEditorHistoryManager.Redo(); + + // Refresh. + VerveEditor::Refresh(); +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryObject::onAdd( %this ) +{ + %historyManager = VerveEditorHistoryManager; + if ( %historyManager.Locked ) + { + // Delete. + %this.schedule( 0, delete ); + return; + } + + if ( isObject( %historyManager.HistoryGroup ) ) + { + // Add To Group. + %historyManager.HistoryGroup.Group.add( %this ); + return; + } + + // Add To Manager. + %this.addToManager( %historyManager ); + + // Update Window. + VerveEditorWindow.UpdateWindowTitle(); +} + +//------------------------------------------------------------------------- + +function VerveEditor::ToggleHistoryGroup() +{ + %historyManager = VerveEditorHistoryManager; + if ( isObject( %historyManager.HistoryGroup ) ) + { + // Clear. + %historyManager.HistoryGroup = 0; + + // Update Window. + VerveEditorWindow.UpdateWindowTitle(); + + return; + } + + if ( VerveEditorHistoryManager.Locked ) + { + // Locked. + return; + } + + %historyManager.HistoryGroup = new UndoScriptAction() + { + Class = "VerveEditorHistoryGroup"; + + ActionName = "History Group"; + + // Store Object References. + Group = new SimGroup(); + }; + + // Add To Manager. + %historyManager.HistoryGroup.addToManager( %historyManager ); +} + +function VerveEditorHistoryGroup::onRemove( %this ) +{ + if ( isObject( %this.Group ) ) + { + // Delete Group. + %this.Group.delete(); + } +} + +function VerveEditorHistoryGroup::Undo( %this ) +{ + // Undo In Reverse Order. + + %undoCount = %this.Group.getCount(); + for ( %i = ( %undoCount - 1 ); %i >= 0; %i-- ) + { + %this.Group.getObject( %i ).Undo(); + } +} + +function VerveEditorHistoryGroup::Redo( %this ) +{ + %undoCount = %this.Group.getCount(); + for ( %i = 0; %i < %undoCount; %i++ ) + { + %this.Group.getObject( %i ).Redo(); + } +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryCreateObject::Undo( %this ) +{ + // Undo Delete. + %parentObject = %this.Parent; + %object = %this.Object; + + // Detach Object. + %parentObject.removeObject( %object ); +} + +function VerveEditorHistoryCreateObject::Redo( %this ) +{ + // Redo Delete. + %parentObject = %this.Parent; + %object = %this.Object; + + // Attach Object. + %parentObject.addObject( %object ); +} + +function VerveEditorHistoryCreateObject::onRemove( %this ) +{ + /* + if ( !isObject( %this.Object.getParent() ) || %this.Object.getParent().getId() != %this.Parent.getId() ) + { + SimObject::Delete( %this.Object ); + } + */ +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryDeleteObject::Undo( %this ) +{ + // Undo Delete. + %parentObject = %this.Parent; + %object = %this.Object; + + // Attach Object. + %parentObject.addObject( %object ); +} + +function VerveEditorHistoryDeleteObject::Redo( %this ) +{ + // Redo Delete. + %parentObject = %this.Parent; + %object = %this.Object; + + // Detach Object. + %parentObject.removeObject( %object ); +} + +function VerveEditorHistoryDeleteObject::onRemove( %this ) +{ + /* + if ( !isObject( %this.Object.getParent() ) || %this.Object.getParent().getId() != %this.Parent.getId() ) + { + SimObject::Delete( %this.Object ); + } + */ +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryChangeProperty::Undo( %this ) +{ + // Undo Change. + %object = %this.Object; + %fieldName = %this.FieldName; + %oldValue = %this.OldValue; + + // Lock History. + VerveEditorHistoryManager.Locked = true; + + // Attach Object. + %object.setFieldValue( %fieldName, %oldValue, false ); + + // Unlock History. + VerveEditorHistoryManager.Locked = false; +} + +function VerveEditorHistoryChangeProperty::Redo( %this ) +{ + // Redo Change. + %object = %this.Object; + %fieldName = %this.FieldName; + %newValue = %this.NewValue; + + // Lock History. + VerveEditorHistoryManager.Locked = true; + + // Attach Object. + %object.setFieldValue( %fieldName, %newValue, false ); + + // Unlock History. + VerveEditorHistoryManager.Locked = false; +} + +function VerveEditorHistoryManager::Lock( %this ) +{ + %this.Locked = true; +} + +function VerveEditorHistoryManager::UnLock( %this ) +{ + %this.Locked = false; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorMenu.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorMenu.cs new file mode 100644 index 000000000..20bcfe3a3 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorMenu.cs @@ -0,0 +1,261 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveWindowMenu::Clear( %this ) +{ + while ( %this.getItemCount() > 0 ) + { + %this.removeItem( 0 ); + } +} + +function VerveWindowMenu::Init( %this ) +{ + // Clear Items. + %this.Clear(); + + %i = 0; + while ( %this.Item[%i] !$= "" ) + { + %itemString = %this.Item[%i]; + %itemLabel = getField( %itemString, 0 ); + %itemAccel = getField( %itemString, 1 ); + %itemMethod = getField( %itemString, 2 ); + %itemMap = getField( %itemString, 3 ); + + if ( !isObject( %itemMap ) ) + { + %itemMap = VerveEditorMap; + } + + if ( isObject( %itemAccel ) ) + { + %this.insertSubMenu( %i, %itemLabel, %itemAccel ); + } + else + { + // Insert Item. + %this.insertItem( %i, %itemLabel, %itemAccel ); + + if ( !%this.IsPopup && %itemAccel !$= "" && isObject( %itemMap ) ) + { + // Label Hack... + switch$( %itemAccel ) + { + case "DEL" : %itemAccel = "DELETE"; + case "ESC" : %itemAccel = "ESCAPE"; + } + + // Perform Keybind. + %itemMap.bindCmd( "keyboard", strreplace( %itemAccel, "+", " " ), %itemMethod, "" ); + } + } + + %i++; + } +} + +function VerveWindowMenu::onSelectItem( %this, %id, %text ) +{ + %command = getField( %this.item[%id], 2 ); + if ( %command !$= "" ) + { + eval( %command ); + return true; + } + + return false; +} + +//------------------------------------------------------------------------- + +function VerveEditorWindow::onCreateMenu( %this ) +{ + // Store Menu Bars. + if ( !isObject( %this.MenuSet ) ) + { + %this.MenuSet = new SimSet(); + } + + // CMD Key. + %cmdKey = $platform $= "macos" ? "Cmd" : "Ctrl"; + + //--------------------------------------------------------------------- + // + // File Menu + // + //--------------------------------------------------------------------- + + %recentSequenceMenu = new PopupMenu() + { + Class = "VerveRecentFileMenu"; + SuperClass = "VerveWindowMenu"; + + Label = "Recent Files"; + Position = 0; + + Item[0] = "None"; + }; + + %fileMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + Label = "&File"; + Position = 0; + + Item[0] = "&New" TAB %cmdKey @ "+N" TAB "VerveEditor::NewFile();"; + Item[1] = "&Open" TAB %cmdKey @ "+O" TAB "VerveEditor::LoadFile();"; + Item[2] = "" TAB ""; + Item[3] = "&Save" TAB %cmdKey @ "+S" TAB "VerveEditor::SaveFile();"; + Item[4] = "Save &As" TAB %cmdKey @ "-Shift+S" TAB "VerveEditor::SaveFile( true );"; + Item[5] = "" TAB ""; + Item[6] = "Recent Files" TAB %recentSequenceMenu; + }; + %this.MenuSet.add( %fileMenu ); + + if ( $platform !$= "macos" ) + { + %fileMenu.Item[7] = "" TAB ""; + %fileMenu.Item[8] = "&Close" TAB %cmdKey @ "+F4" TAB "ToggleVerveEditor( true );"; + } + + //--------------------------------------------------------------------- + // + // Edit Menu + // + //--------------------------------------------------------------------- + + %editMenu = new PopupMenu() + { + Class = "VerveWindowEditMenu"; + SuperClass = "VerveWindowMenu"; + + Label = "&Edit"; + Position = 1; + + Item[0] = "&Undo" TAB %cmdKey @ "+Z" TAB "VerveEditor::Undo();"; + Item[1] = "&Redo" TAB %cmdKey @ "+Y" TAB "VerveEditor::Redo();"; + Item[2] = "" TAB ""; + Item[3] = "Cu&t" TAB %cmdKey @ "+X" TAB "VerveEditor::CutSelection();" TAB VerveEditorEditMap; + Item[4] = "&Copy" TAB %cmdKey @ "+C" TAB "VerveEditor::CopySelection();" TAB VerveEditorEditMap; + Item[5] = "&Paste" TAB %cmdKey @ "+V" TAB "VerveEditor::Paste();" TAB VerveEditorEditMap; + + Item[6] = "" TAB ""; + Item[7] = "&Delete" TAB "Del" TAB "VerveEditor::DeleteSelection();" TAB VerveEditorEditMap; + + Item[8] = "" TAB ""; + Item[9] = "&Clear Selection" TAB "Esc" TAB "VerveEditor::ClearSelection();"; + + Item[10] = "" TAB ""; + Item[11] = "&Preferences" TAB %cmdKey @ "+P" TAB "VerveEditor::LaunchEditorPreferences();"; + }; + %this.MenuSet.add( %editMenu ); + + // Init Popups. + %fileMenu.Init(); + %editMenu.Init(); + + // Attach. + %fileMenu.attachToMenuBar( %this, %fileMenu.Position, %fileMenu.Label ); + %editMenu.attachToMenuBar( %this, %editMenu.Position, %editMenu.Label ); +} + +function VerveEditorWindow::ClearMenu( %this ) +{ + if ( isObject( %this.MenuSet ) ) + { + while( %this.MenuSet.getCount() > 0 ) + { + // Fetch Object. + %menuObject = %this.MenuSet.getObject( 0 ); + + // Detach. + %menuObject.removeFromMenuBar(); + + // Delete. + %menuObject.delete(); + } + } +} + +function VerveEditorWindow::onDestroyMenu( %this ) +{ + // Clear the Menu. + %this.ClearMenu(); + + // Delete the Menu Set. + if ( isObject( %this.MenuSet ) ) + { + %this.MenuSet.delete(); + } +} + +function VerveRecentFileMenu::onMenuSelect( %this ) +{ + %this.Refresh(); +} + +function VerveRecentFileMenu::onSelectItem( %this, %index, %text ) +{ + // Load the File. + VerveEditor::LoadFile( $Pref::VerveEditor::RecentFile[ %index ] ); + + return false; +} + +function VerveRecentFileMenu::Refresh( %this ) +{ + // Clear The List. + %this.Clear(); + + // Populate Menu. + if ( $Pref::VerveEditor::RecentFileSize == 0 || $Pref::VerveEditor::RecentFile[0] $= "" ) + { + // Insert Default Item. + %this.insertItem( 0, %this.Item[0], "" ); + + // Disable. + %this.enableItem( 0, false ); + } + else + { + for ( %i = 0; %i < $Pref::VerveEditor::RecentFileSize; %i++ ) + { + // Valid? + if ( $Pref::VerveEditor::RecentFile[%i] $= "" ) + { + // Nope! + break; + } + + // Insert Item. + %this.insertItem( %i, makeRelativePath( $Pref::VerveEditor::RecentFile[%i], $VerveEditor::FilePath ), "" ); + } + } +} + +function VerveWindowEditMenu::onMenuSelect( %this ) +{ + %this.Refresh(); +} + +function VerveWindowEditMenu::Refresh( %this ) +{ + // Undo & Redo. + %this.enableItem( 0, VerveEditor::CanUndo() ); + %this.enableItem( 1, VerveEditor::CanRedo() ); + + // Cut, Copy & Paste. + %this.enableItem( 3, VerveEditor::CanCopy() ); + %this.enableItem( 4, VerveEditor::CanCopy() ); + %this.enableItem( 5, VerveEditor::CanPaste() ); + + // Delete. + %this.enableItem( 7, VerveEditor::CanCopy() ); + + // Clear Selection. + %this.enableItem( 9, VerveEditor::CanCopy() ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorPreferences.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorPreferences.cs new file mode 100644 index 000000000..923c89c5b --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorPreferences.cs @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::LaunchEditorPreferences() +{ + if ( !isObject( VerveEditorPreferenceGui ) ) + { + // Load the GUI. + exec ( "~/VerveEditor/GUI/VerveEditorPreferences.gui" ); + } + + // Awake? + if ( VerveEditorPreferenceGui.isAwake() ) + { + // Sanity!. + return; + } + + // Launch. + VerveEditorWindow.pushDialog( VerveEditorPreferenceGui ); +} + +function VerveEditor::CloseEditorPreferences() +{ + // Close. + VerveEditorWindow.popDialog( VerveEditorPreferenceGui ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorWindow.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorWindow.cs new file mode 100644 index 000000000..22baa8e95 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/EditorWindow.cs @@ -0,0 +1,215 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +$VerveEditor::MapStore = new SimSet(); + +//----------------------------------------------------------------------------- + +function VerveEditorWindow::Open() +{ + if ( isObject( VerveEditorWindow ) ) + { + return; + } + + // Create the Controller. + VerveEditor::CreateController(); + + // Create ActionMap. + %actionMap = new ActionMap( VerveEditorMap ); + %actionMap.pop(); + + // Create Edit ActionMap. + %editActionMap = new ActionMap( VerveEditorEditMap ); + %editActionMap.pop(); + + // Create Window. + if($Verve::UseSeparateWindow) + { + %editorWindow = new VEditorWindow( VerveEditorWindow ); + + // Init Window? + if ( $Pref::VerveEditor::WindowSize $= "" ) + { + // Default Window Size. + %editorWindow.setVideoMode( 800, 253, false ); + } + else + { + // Last Known Window Size. + %editorWindow.setVideoMode( getWord( $Pref::VerveEditor::WindowSize, 0 ), + getWord( $Pref::VerveEditor::WindowSize, 1 ), + false ); + } + + return %editorWindow; + } + else + { + %editorWindow = new guiWindowCtrl(VerveEditorWindow) + { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + }; + return %editorWindow; + } +} + +function VerveEditorWindow::UpdateWindowTitle( %this ) +{ + %fileName = fileName( $VerveEditor::Controller.FileName ); + if ( %fileName $= "" ) + { + %fileName = "Untitled.vsf"; + } + + if ( VerveEditor::IsDirty() ) + { + // Signify Unsaved Work. + %fileName = %fileName @ "*"; + } + + // Set Title. + %this.setWindowTitle( %fileName SPC "- Verve" ); +} + +function VerveEditorWindow::onGainFocus( %this ) +{ + if($Verve::UseSeparateWindow) + return; + + %activeSet = ActiveActionMapSet; + while ( %activeSet.getCount() > 0 ) + { + // Get Object. + %activeMap = %activeSet.getObject( 0 ); + + // Pop It. + %activeMap.pop(); + + if ( %activeMap != GlobalActionMap.getId() ) + { + // Store It. + $VerveEditor::MapStore.add( %activeMap ); + } + } + + // Give Our Commands Preference. + GlobalActionMap.pop(); + VerveEditorMap.push(); + VerveEditorEditMap.push(); + GlobalActionMap.push(); + + // Reset Cursor. + %this.resetCursor(); +} + +function VerveEditorWindow::onLoseFocus( %this ) +{ + %activeSet = $VerveEditor::MapStore; + // Active Set? + if ( isObject( %activeSet ) ) + { + while ( %activeSet.getCount() > 0 ) + { + // Get Object. + %activeMap = %activeSet.getObject( 0 ); + + // Push It. + %activeMap.push(); + + // Remove It. + $VerveEditor::MapStore.remove( %activeMap ); + } + } + + // Valid Map? + if ( isObject( VerveEditorMap ) ) + { + VerveEditorMap.pop(); + } + + // Valid Map? + if ( isObject( VerveEditorEditMap ) ) + { + VerveEditorEditMap.pop(); + } +} + +function VerveEditorWindow::onRemove( %this ) +{ + // Save? + // Note: This crashes the game! + // At this stage, if the editor is dirty a save prompt should have + // been made already... Lets hope! + //VerveEditor::SavePrompt(); + + // Clear Inspector. + VerveEditorPropertyStack.ClearStack(); + + if ( isObject( VerveEditorMap ) ) + { + VerveEditorMap.delete(); + } + + if ( isObject( VerveEditorEditMap ) ) + { + VerveEditorEditMap.delete(); + } + + // Clear the Menu. + %this.ClearMenu(); + + // Force Reset. + %this.onLoseFocus(); + + // Store the Window Extents on Shutdown. + $Pref::VerveEditor::WindowSize = getWords( %this.getVideoMode(), 0, 1 ); + + // Playing? + if ( $VerveEditor::Controller.isPlaying() ) + { + // Stop, but do not reset. + $VerveEditor::Controller.stop( false ); + } + + // Clear the Current Sequence. + $VerveEditor::Controller.clear(); + // Clear the File Name. + $VerveEditor::Controller.FileName = ""; + + /* + // Delete the Controller. + VerveEditor::DeleteController(); + */ + + if ( isFile( $VerveEditor::TemplateVClipboard ) ) + { + // Clear Clipboard. + fileDelete( $VerveEditor::TemplateVClipboard ); + } + + // World Editor Initialised? + if ( isObject( VerveEditorPlugin.ToolbarButton ) ) + { + // Toggle Off the Plugin Button. + VerveEditorPlugin.ToolbarButton.setStateOn( false ); + } +} + +function VerveEditorWindow::onWindowClose( %this ) +{ + if ( !VerveEditor::SavePromptCancel() ) + { + // Don't Close. + return; + } + + // Delete Window. + %this.schedule( 0, delete ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VCameraShakeEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VCameraShakeEvent.cs new file mode 100644 index 000000000..d61b241aa --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VCameraShakeEvent.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VCameraShakeEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventDPropertyList"; + + Group[0] = "VCameraShakeEvent"; + Field[0, 0] = "Falloff"; + Field[0, 1] = "Amplitude"; + Field[0, 2] = "Frequency"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VDirectorEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VDirectorEvent.cs new file mode 100644 index 000000000..6eb5bf331 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VDirectorEvent.cs @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VDirectorEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VDirectorEvent"; + Field[0, 0] = "Label"; + Field[0, 1] = "Target"; + Type[0, 1] = "VCameraGroupEnum"; +}; + +//----------------------------------------------------------------------------- + +function VDirectorEvent::onRemove( %this ) +{ + // Schedule Update. + %this.getParent().schedule( 0, "update" ); +} + +function VDirectorEvent::Refresh( %this, %trackContainer ) +{ + // Create Control. + %eventButton = Parent::Refresh( %this, %trackContainer ); + + // Reference Label. + %eventButton.LabelField = "EventLabel"; + + // Add Field Notify. + %this.AddFieldNotify( "EventLabel", %eventButton ); + + // Update Label. + %this.UpdateLabel(); +} + +function VDirectorEvent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + // Parent Callback. + Parent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ); + + // Fetch Parent. + %parent = %this.getParent(); + if ( !isObject( %parent ) ) + { + return; + } + + switch$( %fieldName ) + { + case "TriggerTime" : %parent.Update(); + + case "Duration" : %parent.Update(); + + case "Target" : %this.UpdateLabel(); + + case "Label" : %this.UpdateLabel(); + } +} + +function VDirectorEvent::UpdateLabel( %this ) +{ + // Valid Target Camera? + %targetLabel = %this.Target; + if ( %targetLabel $= "" ) + { + %targetLabel = "Invalid Target"; + } + + // Valid Scene Label? + if ( %this.Label !$= "" ) + { + %eventLabel = %this.Label @ ": " @ %targetLabel; + } + else + { + %eventLabel = %targetLabel; + } + + // Set Value. + %this.setFieldValue( "EventLabel", %eventLabel ); +} + +function VDirectorEvent::getSnapTime( %this, %targetTime ) +{ + // Don't Snap to Other Events. + + if ( $VerveEditor::Event::SnapTime > 0 ) + { + // Snap. + return mRound( %targetTime, $VerveEditor::Event::SnapTime ); + } + + // No Snap! + return %targetTime; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VEvent.cs new file mode 100644 index 000000000..57ec6ce85 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VEvent.cs @@ -0,0 +1,314 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + //Parent = "VObjectPropertyList"; + + Group[0] = "VEvent"; + Field[0, 0] = "TriggerTime"; +}; + +new ScriptObject( VEventDPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + //Parent = "VObjectPropertyList"; + + Group[0] = "VEvent"; + Field[0, 0] = "TriggerTime"; + Field[0, 1] = "Duration"; +}; + +//----------------------------------------------------------------------------- + +function VEvent::CanCopy( %this, %targetObject ) +{ + return false; +} + +function VEvent::CanPaste( %this, %targetObject ) +{ + return false; +} + +function VEvent::Refresh( %this, %trackContainer ) +{ + // Store Container Reference. + %this.TrackContainer = %trackContainer; + + // Create Control. + return VerveEditor::CreateEventControl( %this ); +} + +//------------------------------------------------------------------------- + +function VerveEditor::CreateEventControl( %object ) +{ + %eventButton = new VEditorButton() + { + SuperClass = "VEditorSelectable"; + Class = "VEditorSelectableEvent"; + Profile = "VEditorEventProfile"; + + HorizSizing = "right"; + VertSizing = "center"; + Position = "0 2"; + Extent = "5 22"; + MinExtent = "1 22"; + + ButtonType = "ToggleButton"; + GroupNum = "-1"; + + // No Text. + Text = ""; + + // Draggable. + IsDraggable = "1"; + }; + %object.TrackContainer.add( %eventButton ); + + // Reference Proxy. + %eventButton.Proxy = %object; + + // Reference Control. + %object.Control = %eventButton; + + // Field Notify. + %object.AddFieldNotify( "TriggerTime", %eventButton ); + %object.AddFieldNotify( "Duration", %eventButton ); + + return %eventButton; +} + +function VEditorSelectableEvent::onMouseDown( %this, %point, %modifiers, %clickCount ) +{ + // Fetch Global Position. + %globalPosition = %this.getGlobalPosition(); + + // Get Local Points. + %x = getWord( %point, 0 ) - getWord( %globalPosition, 0 ); + %y = getWord( %point, 1 ) - getWord( %globalPosition, 1 ); + + // Store Mouse Down Point. + %this.MouseDown = %x SPC %y; + + // Reset. + %this.Proxy.DragModify = false; +} + +function VEditorSelectableEvent::onMouseDragged( %this, %point, %modifiers, %clickCount ) +{ + if ( !%this.Proxy.DragModify ) + { + // Store Original Time. + %this.Proxy.DragTime = %this.Proxy.TriggerTime; + + // Set Selection. + VerveEditor::SetSelection( %this ); + } + + // Fetch Track. + %trackControl = %this.Proxy.getParent().Control.SiblingControl; + + // Mouse Position. + %mousePosition = getWord( %point, 0 ) - getWord( %trackControl.getGlobalPosition(), 0 ) - getWord( %this.MouseDown, 0 ); + + // Fetch Time. + %time = mClamp( VerveEditorTimeLine.toTime( %mousePosition ), 0, $VerveEditor::Controller.Duration ); + + // Apply. + %this.Proxy.SnapToTime( %time, true ); +} + +function VEditorSelectableEvent::onMouseUp( %this, %point, %modifiers, %clickCount ) +{ + Parent::onMouseUp( %this, %point, %modifiers, %clickCount ); + + if ( %this.Proxy.DragModify ) + { + // Store New Time. + %newTime = %this.Proxy.TriggerTime; + + // Reset Value. + %this.Proxy.TriggerTime = %this.Proxy.DragTime; + + // Set Value. + %this.Proxy.setFieldValue( "TriggerTime", %newTime ); + + // Clear Modify. + %this.Proxy.DragModify = false; + } +} + +function VEvent::getSnapTime( %this, %targetTime ) +{ + if ( $Pref::VerveEditor::Event::SnapToSiblings && $Pref::VerveEditor::Event::SnapToSiblingThreshold > 0 ) + { + // Iterate Over Sibling Events. + %trackObject = %this.getParent(); + %eventCount = %trackObject.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + %eventObject = %trackObject.getObject( %i ); + if ( %eventObject.getId() == %this.getId() ) + { + continue; + } + + // Snap Back -> Front. + %snapTime = %eventObject.TriggerTime - %this.Duration; + if ( mAbs( %targetTime - %snapTime ) < $Pref::VerveEditor::Event::SnapToSiblingThreshold / 2 ) + { + // Snap. + return %snapTime; + } + +/* + // Overlaping? + if ( ( %this.TriggerTime + %this.Duration ) > %eventObject.TriggerTime ) + { + // Snap. + return %snapTime; + } +*/ + + // Snap Front -> Back + %snapTime = %eventObject.TriggerTime + %eventObject.Duration; + if ( mAbs( %targetTime - %snapTime ) < $Pref::VerveEditor::Event::SnapToSiblingThreshold / 2 ) + { + // Snap. + return %snapTime; + } + +/* + // Overlaping? + if ( %this.TriggerTime < ( %eventObject.TriggerTime + %eventObject.Duration ) ) + { + // Snap. + return %snapTime; + } +*/ + } + } + + if ( $Pref::VerveEditor::Event::SnapToTime && $Pref::VerveEditor::Event::SnapToTimeThreshold > 0 ) + { + // Snap. + return mRound( %targetTime, $Pref::VerveEditor::Event::SnapToTimeThreshold ); + } + + // No Snap! + return %targetTime; +} + +function VEvent::SnapToTime( %this, %targetTime, %dragged ) +{ + // Fetch Duration. + %duration = %this.Duration; + + // Nasty Hack. + if ( %this.isMemberOfClass( "VDirectorEvent" ) + || %this.isMemberOfClass( "VShapeAnimationEvent" ) ) + { + // Clear Duration. + %duration = 0; + } + + // Snap. + %targetTime = %this.getSnapTime( %targetTime ); + + if ( %dragged ) + { + if ( %targetTime != %this.TriggerTime ) + { + // Flag Modified. + %this.DragModify = true; + } + + // Lock History. + VerveEditorHistoryManager.Locked = true; + + // Set Time. + %this.setFieldValue( "TriggerTime", %targetTime ); + + // UnLock History. + VerveEditorHistoryManager.Locked = false; + } + else + { + // Set Time. + %this.setFieldValue( "TriggerTime", %targetTime ); + } +} + +function VEditorSelectableEvent::Update( %this, %fieldName, %fieldValue ) +{ + if ( %this.LabelField !$= "" && %this.LabelField $= %fieldName ) + { + // Apply Text. + %this.Text = %fieldValue; + + // Return. + return; + } + + %eventTime = %this.Proxy.getFieldValue( "TriggerTime" ); + %eventDuration = %this.Proxy.getFieldValue( "Duration" ); + switch$ ( %fieldName ) + { + case "TriggerTime" : %eventTime = %fieldValue; + + case "Duration" : %eventDuration = %fieldValue; + } + + // Update Position + %controlPositionX = VerveEditorTimeLine.toPoint( %eventTime ); + %controlPositionX += ( %eventDuration == 0 ) ? ( -2 ) : 0; + + // Update Extent. + %controlExtentX = ( %eventDuration == 0 ) ? 5 : ( VerveEditorTimeLine.toPoint( %eventTime + %eventDuration ) - %controlPositionX ); + + %this.setPosition( %controlPositionX, getWord( %this.getPosition(), 1 ) ); + %this.setExtent( %controlExtentX, getWord( %this.getExtent(), 1 ) ); +} + +function VEvent::DisplayContextMenu( %this, %x, %y ) +{ + %contextMenu = $VerveEditor::VEvent::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VEventContextMenu"; + Position = 0; + + Item[0] = "Cu&t" TAB "" TAB "VerveEditor::CutSelection();"; + Item[1] = "&Copy" TAB "" TAB "VerveEditor::CopySelection( true );"; + + Item[2] = "" TAB ""; + + Item[3] = "&Delete" TAB "" TAB "VerveEditor::DeleteSelection();"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VEvent::ContextMenu = %contextMenu; + } + + // Enable/Disable Cut & Copy. + %contextMenu.enableItem( 0, VerveEditor::CanCopy() ); + %contextMenu.enableItem( 1, VerveEditor::CanCopy() ); + + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); +} diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VFadeEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VFadeEvent.cs new file mode 100644 index 000000000..b612e90d5 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VFadeEvent.cs @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VFadeEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventDPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VFadeEvent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + // Parent Callback. + Parent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ); + + // Fetch Parent. + %parent = %this.getParent(); + if ( !isObject( %parent ) ) + { + return; + } + + switch$( %fieldName ) + { + case "TriggerTime" : %parent.Update(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectAnimationEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectAnimationEvent.cs new file mode 100644 index 000000000..bead9a877 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectAnimationEvent.cs @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VLightObjectAnimationEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventDPropertyList"; + + Group[0] = "VLightObjectAnimationEvent"; + Field[0, 0] = "AnimationData"; + Type[0, 0] = "VLightAnimationDataEnum"; +}; + +//----------------------------------------------------------------------------- + +function VLightObjectAnimationEvent::Refresh( %this, %trackContainer ) +{ + // Create Control. + %eventButton = Parent::Refresh( %this, %trackContainer ); + + // Reference Label. + %eventButton.LabelField = "AnimationData"; + + // Add Field Notify. + %this.AddFieldNotify( "AnimationData", %eventButton ); + + // Return Button. + return %eventButton; +} + +function VLightObjectAnimationEvent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + // Parent Callback. + Parent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ); + + // Fetch Parent. + %parent = %this.getParent(); + if ( !isObject( %parent ) ) + { + return; + } + + switch$( %fieldName ) + { + case "AnimationData" : %parent.Update(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectToggleEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectToggleEvent.cs new file mode 100644 index 000000000..ddb7d8a18 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VLightObjectToggleEvent.cs @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VLightObjectToggleEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VLightObjectToggleEvent"; + Field[0, 0] = "Action"; + Type[0, 0] = "ToggleEnum"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VMotionEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VMotionEvent.cs new file mode 100644 index 000000000..75680cf04 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VMotionEvent.cs @@ -0,0 +1,183 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VMotionEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VMotionEvent::CreatePathNode( %this, %transform ) +{ + // Fetch Track & Group. + %track = %this.getParent(); + %group = %track.getParent(); + + // Fetch Object References. + %object = %group.getSceneObject(); + %path = %track.getPath(); + + // Fetch Index. + %nodeIndex = %this.getIndex(); + + // Create New Node. + %path.addNode( %transform, 10, %nodeIndex ); + + // Update Transform. + %object.setTransform( %transform ); + + if ( !VerveEditorHistoryManager.Locked ) + { + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryCreateMotionEvent"; + SuperClass = "VerveEditorHistoryCreateObject"; + + ActionName = "Create Object"; + + // Store Object References. + Parent = %track; + Object = %this; + + // Store Node Information. + PathObject = %path; + NodeIndex = %nodeIndex; + NodeTransform = %path.getNodeWorldTransform( %nodeIndex ); + NodeWeight = %path.getNodeWeight( %nodeIndex ); + }; + + // Force OnAdd. + VerveEditorHistoryObject::onAdd( %historyObject ); + } + + // Reset the Controller. + $VerveEditor::Controller.reset( $VerveEditor::Controller.Time ); +} + +function VMotionEvent::Delete( %this ) +{ + // Fetch Parent. + %parentObject = %this.getParent(); + %rootObject = %this.getRoot(); + if ( !%parentObject || ( %rootObject.getId() != $VerveEditor::Controller.getId() ) ) + { + // Not Editing, Delete. + Parent::delete( %this ); + return; + } + + if ( !VerveEditorHistoryManager.Locked ) + { + %path = %parentObject.getPath(); + %nodeIndex = %this.getIndex(); + + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryDeleteMotionEvent"; + SuperClass = "VerveEditorHistoryDeleteObject"; + + ActionName = "Delete Object"; + + // Store Object References. + Parent = %parentObject; + Object = %this; + + // Store Node Information. + PathObject = %path; + NodeIndex = %nodeIndex; + NodeTransform = %path.getNodeWorldTransform( %nodeIndex ); + NodeWeight = %path.getNodeWeight( %nodeIndex ); + }; + + // Force OnAdd. + VerveEditorHistoryObject::onAdd( %historyObject ); + } + + // Detach Object. + %parentObject.removeObject( %this ); +} + +function VMotionEvent::OnRemove( %this ) +{ + // Fetch Path. + %path = %this.getParent().getPath(); + if ( !isObject( %path ) ) + { + return; + } + + // Delete Node. + %path.deleteNode( %this.getIndex() ); +} + +function VMotionEvent::OnSelect( %this ) +{ + // Fetch Path. + %path = %this.getParent().getPath(); + if ( !isObject( EVPathEditor ) || !isObject( %path ) ) + { + // No Editor. + return; + } + + // Update Selection. + EVPathEditor.setSelection( %path, %this.getIndex() ); +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryCreateMotionEvent::Undo( %this ) +{ + // Delete Node. + %this.PathObject.DeleteNode( %this.NodeIndex ); + + // Dirty. + EVPathEditor.isDirty = true; + + // Regular Undo. + Parent::Undo( %this ); +} + +function VerveEditorHistoryCreateMotionEvent::Redo( %this ) +{ + // Create Node. + %this.PathObject.AddNode( %this.NodeTransform, %this.NodeWeight, %this.NodeIndex ); + + // Dirty. + EVPathEditor.isDirty = true; + + // Regular Redo. + Parent::Redo( %this ); +} + +//------------------------------------------------------------------------- + +function VerveEditorHistoryDeleteMotionEvent::Undo( %this ) +{ + // Create Node. + %this.PathObject.AddNode( %this.NodeTransform, %this.NodeWeight, %this.NodeIndex ); + + // Dirty. + EVPathEditor.isDirty = true; + + // Regular Undo. + Parent::Undo( %this ); +} + +function VerveEditorHistoryDeleteMotionEvent::Redo( %this ) +{ + // Delete Node. + %this.PathObject.DeleteNode( %this.NodeIndex ); + + // Dirty. + EVPathEditor.isDirty = true; + + // Regular Redo. + Parent::Redo( %this ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VParticleEffectToggleEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VParticleEffectToggleEvent.cs new file mode 100644 index 000000000..c95f7c30d --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VParticleEffectToggleEvent.cs @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VParticleEffectToggleEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VParticleEffectToggleEvent"; + Field[0, 0] = "Action"; + Type[0, 0] = "ToggleEnum"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VPostEffectToggleEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VPostEffectToggleEvent.cs new file mode 100644 index 000000000..f803cc2b8 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VPostEffectToggleEvent.cs @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VPostEffectToggleEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VPostEffectToggleEvent"; + Field[0, 0] = "Action"; + Type[0, 0] = "ToggleEnum"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSceneJumpEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSceneJumpEvent.cs new file mode 100644 index 000000000..089bfa3bb --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSceneJumpEvent.cs @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSceneJumpEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VSceneJumpEvent"; + Field[0, 0] = "Target"; + Type[0, 0] = "VSceneEnum"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VScriptEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VScriptEvent.cs new file mode 100644 index 000000000..e7c4472ba --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VScriptEvent.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VScriptEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VScriptEvent"; + Field[0, 0] = "CommandType"; + Type[0, 0] = "VCommandEnum"; + Field[0, 1] = "Command"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VShapeAnimationEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VShapeAnimationEvent.cs new file mode 100644 index 000000000..dc0e3b52d --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VShapeAnimationEvent.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VShapeAnimationEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventDPropertyList"; + + Group[0] = "VShapeAnimationEvent"; + Field[0, 0] = "AnimationData"; + Type[0, 0] = "VShapeAnimationEnum"; + Field[0, 1] = "AutoDuration"; +}; + +//----------------------------------------------------------------------------- + +function VShapeAnimationEvent::Refresh( %this, %trackContainer ) +{ + // Create Control. + %eventButton = Parent::Refresh( %this, %trackContainer ); + + // Reference Label. + %eventButton.LabelField = "AnimationData"; + + // Add Field Notify. + %this.AddFieldNotify( "AnimationData", %eventButton ); + %this.AddFieldNotify( "AutoDuration", %eventButton ); + + // Return Button. + return %eventButton; +} + +function VShapeAnimationEvent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + // Parent Callback. + Parent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ); + + // Fetch Parent. + %parent = %this.getParent(); + if ( !isObject( %parent ) ) + { + return; + } + + switch$( %fieldName ) + { + case "AnimationData" : %parent.Update(); + + case "AutoDuration" : %parent.Update(); + + case "TriggerTime" : %parent.Update(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSlowMoEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSlowMoEvent.cs new file mode 100644 index 000000000..9385f02e1 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSlowMoEvent.cs @@ -0,0 +1,13 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSlowMoEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventDPropertyList"; + + Group[0] = "VSlowMoEvent"; + Field[0, 0] = "TimeScale"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSoundEffectEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSoundEffectEvent.cs new file mode 100644 index 000000000..6ceecfc14 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSoundEffectEvent.cs @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSoundEffectEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; + + Group[0] = "VSoundEffectEvent"; + Field[0, 0] = "SoundEffect"; + Type[0, 0] = "VSFXProfileEnum"; +}; + +//----------------------------------------------------------------------------- + +function VSoundEffectEvent::Refresh( %this, %trackContainer ) +{ + // Create Control. + %eventButton = Parent::Refresh( %this, %trackContainer ); + + // Reference Label. + %eventButton.LabelField = "SoundEffect"; + + // Add Field Notify. + %this.AddFieldNotify( "SoundEffect", %eventButton ); + + // Return Button. + return %eventButton; +} + +function VSoundEffectEvent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + switch$ ( %fieldName ) + { + case "SoundEffect" : %this.NotifyFieldChange( "Duration", 0 ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSpawnSphereSpawnTargetEvent.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSpawnSphereSpawnTargetEvent.cs new file mode 100644 index 000000000..6262bb23d --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/VSpawnSphereSpawnTargetEvent.cs @@ -0,0 +1,10 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSpawnSphereSpawnTargetEventPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VEventPropertyList"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/main.cs new file mode 100644 index 000000000..a456a5e38 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Events/main.cs @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitEventScripts() +{ + // Core. + exec( "./VEvent.cs" ); + + // Built-In. + exec( "./VCameraShakeEvent.cs" ); + exec( "./VDirectorEvent.cs" ); + exec( "./VFadeEvent.cs" ); + exec( "./VLightObjectAnimationEvent.cs" ); + exec( "./VLightObjectToggleEvent.cs" ); + exec( "./VMotionEvent.cs" ); + exec( "./VParticleEffectToggleEvent.cs" ); + exec( "./VPostEffectToggleEvent.cs" ); + exec( "./VSceneJumpEvent.cs" ); + exec( "./VScriptEvent.cs" ); + exec( "./VShapeAnimationEvent.cs" ); + exec( "./VSlowMoEvent.cs" ); + exec( "./VSoundEffectEvent.cs" ); + exec( "./VSpawnSphereSpawnTargetEvent.cs" ); + + // Custom. + // Exec Custom Event Scripts. +} +VerveEditor::InitEventScripts(); diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VCameraGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VCameraGroup.cs new file mode 100644 index 000000000..164d3d306 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VCameraGroup.cs @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VCameraGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VSceneObjectGroupPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VCameraGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VCameraGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Animation Track" TAB "" TAB "VerveEditor::AddTrack( \"VShapeAnimationTrack\" );"; + Item[1] = "Add Camera Shake Track" TAB "" TAB "VerveEditor::AddTrack( \"VCameraShakeTrack\" );"; + Item[2] = "Add Motion Track" TAB "" TAB "VerveEditor::AddTrack( \"VMotionTrack\" );"; + Item[3] = "Add Post Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VPostEffectToggleTrack\" );"; + Item[4] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[5] = "Add Sound Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VSoundEffectTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VShapeAnimationTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VCameraShakeTrack" ) ); + %contextMenu.enableItem( 2, %this.CanAdd( "VMotionTrack" ) ); + %contextMenu.enableItem( 3, %this.CanAdd( "VPostEffectToggleTrack" ) ); + %contextMenu.enableItem( 4, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 5, %this.CanAdd( "VSoundEffectTrack" ) ); + + // Return Menu. + return %contextMenu; +} + +function VCameraGroup::isValid( %this ) +{ + // Valid? + return VTorque::isCameraObject( %this.getSceneObject() ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VDirectorGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VDirectorGroup.cs new file mode 100644 index 000000000..9360f22d0 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VDirectorGroup.cs @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VDirectorGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VGroupPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VDirectorGroup::PopulateBuildStack( %this, %stack ) +{ + Parent::PopulateBuildStack( %this, %stack ); + + // Create Director Track Checkbox. + %directorTrackCheckBox = %stack.CreateCheckbox( "DirectorTrackToggle", "Add Director Track:" ); + %directorTrackCheckBox.setStateOn( true ); +} + +function VDirectorGroup::ResolveBuildStack( %this, %stack ) +{ + Parent::ResolveBuildStack( %this, %stack, %groupObject ); + + // Find the Track Toggle. + %directorTrackCheckBox = %stack.findObjectByInternalName( "DirectorTrackToggle", true ); + if ( isObject( %directorTrackCheckBox ) && %directorTrackCheckBox.getValue() == true ) + { + // Create the Director Track. + %directorTrackCheckBox = VerveEditor::AddTrack( "VDirectorTrack", %this, false ); + } +} + +//----------------------------------------------------------------------------- + +function VDirectorGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Director Track" TAB "" TAB "VerveEditor::AddTrack( \"VDirectorTrack\" );"; + Item[1] = "Add Fade Track" TAB "" TAB "VerveEditor::AddTrack( \"VFadeTrack\" );"; + Item[2] = "Add Scene Jump Track" TAB "" TAB "VerveEditor::AddTrack( \"VSceneJumpTrack\" );"; + Item[3] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[4] = "Add Slow Mo Track" TAB "" TAB "VerveEditor::AddTrack( \"VSlowMoTrack\" );"; + Item[5] = "Add Sound Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VSoundEffectTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VDirectorTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VFadeTrack" ) ); + %contextMenu.enableItem( 2, %this.CanAdd( "VSceneJumpTrack" ) ); + %contextMenu.enableItem( 3, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 4, %this.CanAdd( "VSlowMoTrack" ) ); + %contextMenu.enableItem( 5, %this.CanAdd( "VSoundEffectTrack" ) ); + + // Return Menu. + return %contextMenu; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VGroup.cs new file mode 100644 index 000000000..554f583c3 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VGroup.cs @@ -0,0 +1,360 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VGroup::OnAdd( %this ) +{ + %ourClass = %this.getClassName(); + if ( isWordInList( %ourClass, $VerveEditor::UniqueGroupList ) ) + { + %controller = $VerveEditor::Controller; + %groupCount = %controller.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %groupObject = %controller.getObject( %i ); + if ( %groupObject.getId() == %this.getId() ) + { + // Skip. + continue; + } + + if ( %groupObject.isMemberOfClass( %ourClass ) ) + { + // Alert Message. + messageBox( "Verve Editor", "You cannot have more than one \"" @ %ourClass @ "\" in your sequence.", "Ok", "Warning" ); + + // Invalid. + return false; + } + } + } + + // Regular Add. + return Parent::OnAdd( %this ); +} + +function VGroup::OnAttach( %this ) +{ + // Add Event Notify. + VerveEditor::AddEventNotify( %this, "VGroupObjectUpdate", "OnGroupObjectUpdate" ); +} + +function VGroup::OnDetach( %this ) +{ + // Remove Event Notify. + VerveEditor::RemoveEventNotify( %this, "VGroupObjectUpdate" ); +} + +function VGroup::CanPaste( %this, %targetObject ) +{ + if ( !isObject( %targetObject ) ) + { + // Nope! + return false; + } + + if ( !%this.CanAdd( %targetObject.getClassName() ) ) + { + // Nope! + return false; + } + + return %targetObject.isMemberOfClass( "VTrack" ); +} + +function VGroup::CanAdd( %this, %targetClass ) +{ + if ( isWordInList( %targetClass, $VerveEditor::NonUniqueTrackList ) ) + { + // Non-Unique Class. + return true; + } + + // All Tracks are Unique. + %trackCount = %this.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %trackObject = %this.getObject( %i ); + if ( %trackObject.isMemberOfClass( %targetClass ) ) + { + // Invalid. + return false; + } + } + + // All Good. + return true; +} + +function VGroup::isValid( %this ) +{ + // Yup. + return true; +} + +function VGroup::Refresh( %this ) +{ + // Create Control. + %groupControl = VerveEditor::CreateGroupControl( %this ); + + // Update Validity. + %this.OnGroupObjectUpdate(); + + %trackCount = %this.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %this.getObject( %i ).Refresh(); + } + + // Return Control. + return %groupControl; +} + +function VGroup::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + // Parent Callback. + Parent::OnFieldChange( %this, %fieldName, %oldValue, %newValue ); + + switch$ ( %fieldName ) + { + case "Reference" : + + if ( $VerveEditor::InspectorObject.getId() == %this.getId() ) + { + // Post Event. + VerveEditor::PostEvent( "VGroupObjectUpdate", %this ); + } + } +} + +function VGroup::OnGroupObjectUpdate( %this, %refObject ) +{ + if ( !isObject( %this.Control ) ) + { + return; + } + + // Update Validity. + if ( %this.isValid() ) + { + // Valid. + %this.Control.setProfile( "VEditorGroupHeaderProfile" ); + } + else + { + // Invalid. + %this.Control.setProfile( "VEditorGroupHeaderErrorProfile" ); + } +} + +//----------------------------------------------------------------------------- + +function VGroup::PopulateBuildStack( %this, %stack ) +{ + // Void. +} + +function VGroup::ResolveBuildStack( %this, %stack ) +{ + // Void. +} + +//----------------------------------------------------------------------------- + +function VGroup::DisplayContextMenu( %this, %x, %y ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VGroupContextMenu"; + Position = 0; + + Item[0] = "Add Track" TAB ""; + + Item[1] = "" TAB ""; + + Item[2] = "Cu&t" TAB "" TAB "VerveEditor::CutSelection();"; + Item[3] = "&Copy" TAB "" TAB "VerveEditor::CopySelection();"; + Item[4] = "&Paste" TAB "" TAB "VerveEditor::Paste();"; + + Item[5] = "" TAB ""; + + Item[6] = "&Delete" TAB "" TAB "VerveEditor::DeleteSelection();"; + + AddIndex = 0; + PasteIndex = 4; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu = %contextMenu; + } + + // Remove Add Menu. + %contextMenu.removeItem( %contextMenu.AddIndex ); + + // Available Tracks Menu. + %groupMenu = 0; + if ( %this.isMethod( "GetAddTrackMenu" ) ) + { + %groupMenu = %this.GetAddTrackMenu(); + } + + if ( isObject( %groupMenu ) ) + { + // Insert Menu. + %contextMenu.insertSubMenu( %contextMenu.AddIndex, getField( %contextMenu.Item[0], 0 ), %groupMenu ); + + // Enable. + %contextMenu.enableItem( %contextMenu.AddIndex, true ); + } + else + { + // Add Dummy. + %contextMenu.insertItem( %contextMenu.AddIndex, getField( %contextMenu.Item[0], 0 ) ); + + // Disable. + %contextMenu.enableItem( %contextMenu.AddIndex, false ); + } + + // Enable/Disable Pasting. + %contextMenu.enableItem( %contextMenu.PasteIndex, VerveEditor::CanPaste() ); + + // Display. + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); +} + +function VGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Track" TAB "" TAB "VerveEditor::AddTrack( \"VTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VTrack" ) ); + + // Return Menu. + return %contextMenu; +} + +//----------------------------------------------------------------------------- + +function VerveEditor::CreateGroupControl( %object ) +{ + %groupWidth = getWord( VerveEditorGroupStack.getExtent(), 0 ); + %groupHeight = 26; + %trackWidth = getWord( VerveEditorTrackStack.getExtent(), 0 ); + %trackHeight = %groupHeight; + + %groupContainer = new VEditorButton() + { + SuperClass = "VEditorSelectable"; + Class = "VEditorSelectableGroup"; + Profile = "VEditorGroupHeaderProfile"; + + Bitmap = "~/VerveEditor/GUI/Images/GroupBackground"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %groupWidth SPC %groupHeight; + + ButtonType = "ToggleButton"; + GroupNum = "-1"; + + IsContainer = "1"; + }; + VerveEditorGroupStack.add( %groupContainer ); + + %groupCheckbox = new GuiCheckBoxCtrl() + { + Class = "VEditorBoolPropertyField"; + InternalName = "Enabled"; + Profile = "VEditorCheckBoxProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 0"; + Extent = "14" SPC %groupHeight; + + Object = %object; + FieldName = "Enabled"; + Command = "$ThisControl.ApplyValue();"; + + Text = ""; + }; + %groupContainer.add( %groupCheckbox ); + + %trackContainer = new VEditorButton() + { + SuperClass = "VEditorSelectable"; + Class = "VEditorSelectableGroup"; + Profile = "VEditorGroupTrackProfile"; + + Bitmap = "~/VerveEditor/GUI/Images/GroupBackground"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %trackWidth SPC %trackHeight; + + ButtonType = "ToggleButton"; + GroupNum = "-1"; + + IsContainer = "1"; + }; + VerveEditorTrackStack.add( %trackContainer ); + + // Field Notify. + %object.AddFieldNotify( "Label", %groupContainer ); + %object.AddFieldNotify( "Enabled", %groupCheckbox ); + + // Reference Siblings. + %trackContainer.SiblingControl = %groupContainer; + %groupContainer.SiblingControl = %trackContainer; + + // Reference Proxy. + %groupContainer.Proxy = %object; + %trackContainer.Proxy = %object; + + // Reference Control. + %object.Control = %groupContainer; + + return %trackContainer; +} + +function VEditorSelectableGroup::Update( %this, %fieldName, %fieldValue ) +{ + %this.setText( %fieldValue ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VLightObjectGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VLightObjectGroup.cs new file mode 100644 index 000000000..0a674a33c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VLightObjectGroup.cs @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VLightObjectGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VSceneObjectGroupPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VLightObjectGroup::PopulateBuildStack( %this, %stack ) +{ + // Ignore Parent Fields. + //Parent::PopulateBuildStack( %this, %stack ); + + // Object Reference. + %lightObjectList = %stack.CreateObjectList( VTorque::getLightObjectClass(), "LightObjectList", "Light Object:" ); + + if ( VTorque::GetSelectedCount() ) + { + %selection = VTorque::GetSelectedObject(); + if ( %selection.getName() !$= "" && VTorque::isLightObject( %selection ) ) + { + // Select Object. + %lightObjectList.setText( %selection.getName() ); + } + } + + // Create Toggle Track Checkbox. + %toggleTrackCheckBox = %stack.CreateCheckbox( "ToggleTrackToggle", "Add Toggle Track:" ); + %toggleTrackCheckBox.setStateOn( true ); +} + +function VLightObjectGroup::ResolveBuildStack( %this, %stack ) +{ + // Ignore Parent Fields. + //Parent::ResolveBuildStack( %this, %stack, %groupObject ); + + // Fetch the Controller. + %controller = %this.getRoot(); + + // Find the Particle Effect List. + %lightObjectList = %stack.findObjectByInternalName( "LightObjectList", true ); + if ( isObject( %lightObjectList ) ) + { + // Fetch Selected Object. + %lightObject = %lightObjectList.getText(); + + // Data Field Name. + %dataFieldName = strreplace( %this.Label, " ", "_" ); + + // Create a New Data Field. + %controller.addDataField( "STATIC", %dataFieldName ); + + if ( %lightObject !$= "" ) + { + // Set the Field Value. + %controller.setFieldValue( %dataFieldName, %lightObject ); + } + + // Reference the Data Field. + %this.Reference = %dataFieldName; + } + + // Find the Track Toggle. + %toggleTrackCheckBox = %stack.findObjectByInternalName( "ToggleTrackToggle", true ); + if ( %toggleTrackCheckBox.getValue() ) + { + // Create the Toggle Track. + %toggleTrackCheckBox = VerveEditor::AddTrack( "VLightObjectToggleTrack", %this, false ); + } +} + +//----------------------------------------------------------------------------- + +function VLightObjectGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VLightObjectGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Animation Track" TAB "" TAB "VerveEditor::AddTrack( \"VLightObjectAnimationTrack\" );"; + Item[1] = "Add Motion Track" TAB "" TAB "VerveEditor::AddTrack( \"VMotionTrack\" );"; + Item[2] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[3] = "Add Sound Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VSoundEffectTrack\" );"; + Item[4] = "Add Toggle Track" TAB "" TAB "VerveEditor::AddTrack( \"VLightObjectToggleTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VLightObjectAnimationTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VMotionTrack" ) ); + %contextMenu.enableItem( 2, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 3, %this.CanAdd( "VSoundEffectTrack" ) ); + %contextMenu.enableItem( 4, %this.CanAdd( "VLightObjectToggleTrack" ) ); + + // Return Menu. + return %contextMenu; +} + +function VLightObjectGroup::isValid( %this ) +{ + // Valid? + return VTorque::isLightObject( %this.getSceneObject() ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VParticleEffectGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VParticleEffectGroup.cs new file mode 100644 index 000000000..f30cca71e --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VParticleEffectGroup.cs @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VParticleEffectGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VSceneObjectGroupPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VParticleEffectGroup::PopulateBuildStack( %this, %stack ) +{ + // Ignore Parent Fields. + //Parent::PopulateBuildStack( %this, %stack ); + + // Object Reference. + %particleEffectList = %stack.CreateObjectList( VTorque::getParticleEffectClass(), "ParticleEffectList", "Particle Effect:" ); + + if ( VTorque::GetSelectedCount() ) + { + %selection = VTorque::GetSelectedObject(); + if ( %selection.getName() !$= "" && VTorque::isParticleEffect( %selection ) ) + { + // Select Object. + %particleEffectList.setText( %selection.getName() ); + } + } + + // Create Toggle Track Checkbox. + %toggleTrackCheckBox = %stack.CreateCheckbox( "ToggleTrackToggle", "Add Toggle Track:" ); + %toggleTrackCheckBox.setStateOn( true ); +} + +function VParticleEffectGroup::ResolveBuildStack( %this, %stack ) +{ + // Ignore Parent Fields. + //Parent::ResolveBuildStack( %this, %stack, %groupObject ); + + // Fetch the Controller. + %controller = %this.getRoot(); + + // Find the Particle Effect List. + %particleEffectList = %stack.findObjectByInternalName( "ParticleEffectList", true ); + if ( isObject( %particleEffectList ) ) + { + // Fetch Selected Object. + %particlEffect = %particleEffectList.getText(); + + // Data Field Name. + %dataFieldName = strreplace( %this.Label, " ", "_" ); + + // Create a New Data Field. + %controller.addDataField( "STATIC", %dataFieldName ); + + if ( %particlEffect !$= "" ) + { + // Set the Field Value. + %controller.setFieldValue( %dataFieldName, %particlEffect ); + } + + // Reference the Data Field. + %this.Reference = %dataFieldName; + } + + // Find the Track Toggle. + %toggleTrackCheckBox = %stack.findObjectByInternalName( "ToggleTrackToggle", true ); + if ( %toggleTrackCheckBox.getValue() ) + { + // Create the Toggle Track. + %toggleTrackCheckBox = VerveEditor::AddTrack( "VParticleEffectToggleTrack", %this, false ); + } +} + +//----------------------------------------------------------------------------- + +function VParticleEffectGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VParticleEffectGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Motion Track" TAB "" TAB "VerveEditor::AddTrack( \"VMotionTrack\" );"; + Item[1] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[2] = "Add Sound Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VSoundEffectTrack\" );"; + Item[3] = "Add Toggle Track" TAB "" TAB "VerveEditor::AddTrack( \"VParticleEffectToggleTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VMotionTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 2, %this.CanAdd( "VSoundEffectTrack" ) ); + %contextMenu.enableItem( 3, %this.CanAdd( "VParticleEffectToggleTrack" ) ); + + // Return Menu. + return %contextMenu; +} + +function VParticleEffectGroup::isValid( %this ) +{ + // Valid? + return VTorque::isParticleEffect( %this.getSceneObject() ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSceneObjectGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSceneObjectGroup.cs new file mode 100644 index 000000000..7483ea209 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSceneObjectGroup.cs @@ -0,0 +1,159 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSceneObjectGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VGroupPropertyList"; + + Group[0] = "VGroup"; + Field[0, 0] = "Reference"; + Type[0, 0] = "VControllerDataEnum"; +}; + +//----------------------------------------------------------------------------- + +function VSceneObjectGroup::OnSelect( %this ) +{ + if ( !%this.isValid() ) + { + // Invalid Object. + return; + } + + // Update Selection. + VTorque::SetSelectedObject( %this.getSceneObject() ); +} + +function VSceneObjectGroup::isValid( %this ) +{ + // Valid? + return VTorque::isSceneObject( %this.getSceneObject() ); +} + +//----------------------------------------------------------------------------- + +function VSceneObjectGroup::PopulateBuildStack( %this, %stack ) +{ + Parent::PopulateBuildStack( %this, %stack ); + + // Object Reference. + %sceneObjectList = %stack.CreateObjectList( "SceneObject", "SceneObjectList", "Scene Object:" ); + + if ( VTorque::GetSelectedCount() ) + { + %selection = VTorque::GetSelectedObject(); + if ( %selection.getName() !$= "" && %selection.isMemberOfClass( "SceneObject" ) ) + { + // Select Object. + %sceneObjectList.setText( %selection.getName() ); + } + } + + // Create Motion Track Checkbox. + %motionTrackCheckBox = %stack.CreateCheckbox( "MotionTrackToggle", "Add Motion Track:" ); + %motionTrackCheckBox.setStateOn( true ); + + // Object Reference. + %pathObjectList = %stack.CreateObjectList( "VPath", "PathObjectList", "Path Object:" ); +} + +function VSceneObjectGroup::ResolveBuildStack( %this, %stack ) +{ + Parent::ResolveBuildStack( %this, %stack, %groupObject ); + + // Fetch the Controller. + %controller = %this.getRoot(); + + // Find the Scene Object List. + %sceneObjectList = %stack.findObjectByInternalName( "SceneObjectList", true ); + if ( isObject( %sceneObjectList ) ) + { + // Fetch Selected Object. + %sceneObject = %sceneObjectList.getText(); + + // Data Field Name. + %dataFieldName = strreplace( %this.Label, " ", "_" ); + + // Create a New Data Field. + %controller.addDataField( "STATIC", %dataFieldName ); + + if ( %sceneObject !$= "" ) + { + // Set the Field Value. + %controller.setFieldValue( %dataFieldName, %sceneObject ); + } + + // Reference the Data Field. + %this.Reference = %dataFieldName; + } + + // Find the Path Toggle. + %motionTrackCheckBox = %stack.findObjectByInternalName( "MotionTrackToggle", true ); + if ( %motionTrackCheckBox.getValue() ) + { + // Create the Motion Track. + %motionTrack = VerveEditor::AddTrack( "VMotionTrack", %this, false ); + + %pathObjectList = %stack.findObjectByInternalName( "PathObjectList", true ); + if ( isObject( %pathObjectList ) ) + { + // Fetch Selected Object. + %pathObject = %pathObjectList.getText(); + + // Data Field Name. + %dataFieldName = strreplace( %this.Label @ "Path", " ", "_" ); + + // Create a New Data Field. + %controller.addDataField( "STATIC", %dataFieldName ); + + if ( %pathObject !$= "" ) + { + // Set the Field Value. + %controller.setFieldValue( %dataFieldName, %pathObject ); + } + + // Reference the Data Field. + %motionTrack.Reference = %dataFieldName; + } + } +} + +//----------------------------------------------------------------------------- + +function VSceneObjectGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VSceneObjectGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Animation Track" TAB "" TAB "VerveEditor::AddTrack( \"VShapeAnimationTrack\" );"; + Item[1] = "Add Motion Track" TAB "" TAB "VerveEditor::AddTrack( \"VMotionTrack\" );"; + Item[2] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[3] = "Add Sound Effect Track" TAB "" TAB "VerveEditor::AddTrack( \"VSoundEffectTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VShapeAnimationTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VMotionTrack" ) ); + %contextMenu.enableItem( 2, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 3, %this.CanAdd( "VSoundEffectTrack" ) ); + + // Return Menu. + return %contextMenu; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSpawnSphereGroup.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSpawnSphereGroup.cs new file mode 100644 index 000000000..cd2913ad9 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/VSpawnSphereGroup.cs @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSpawnSphereGroupPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VSceneObjectGroupPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VSceneObjectGroup::PopulateBuildStack( %this, %stack ) +{ + VGroup::PopulateBuildStack( %this, %stack ); + + // Object Reference. + %sceneObjectList = %stack.CreateObjectList( "SceneObject", "SceneObjectList", "Scene Object:" ); + + if ( VTorque::GetSelectedCount() ) + { + %selection = VTorque::GetSelectedObject(); + if ( %selection.getName() !$= "" && %selection.isMemberOfClass( "SceneObject" ) ) + { + // Select Object. + %sceneObjectList.setText( %selection.getName() ); + } + } +} + +function VSceneObjectGroup::ResolveBuildStack( %this, %stack ) +{ + VGroup::ResolveBuildStack( %this, %stack, %groupObject ); + + // Fetch the Controller. + %controller = %this.getRoot(); + + // Find the Scene Object List. + %sceneObjectList = %stack.findObjectByInternalName( "SceneObjectList", true ); + if ( isObject( %sceneObjectList ) ) + { + // Fetch Selected Object. + %sceneObject = %sceneObjectList.getText(); + + // Data Field Name. + %dataFieldName = strreplace( %this.Label, " ", "_" ); + + // Create a New Data Field. + %controller.addDataField( "STATIC", %dataFieldName ); + + if ( %sceneObject !$= "" ) + { + // Set the Field Value. + %controller.setFieldValue( %dataFieldName, %sceneObject ); + } + + // Reference the Data Field. + %this.Reference = %dataFieldName; + } +} + +//----------------------------------------------------------------------------- + +function VSpawnSphereGroup::GetAddTrackMenu( %this ) +{ + %contextMenu = $VerveEditor::VGroup::ContextMenu[%this.getClassName()]; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VSpawnSphereGroupAddTrackMenu"; + Position = 0; + + Item[0] = "Add Script Event Track" TAB "" TAB "VerveEditor::AddTrack( \"VScriptEventTrack\" );"; + Item[1] = "Add Spawn Target Track" TAB "" TAB "VerveEditor::AddTrack( \"VSpawnSphereSpawnTargetTrack\" );"; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VGroup::ContextMenu[%this.getClassName()] = %contextMenu; + } + + // Enable/Disable Adding Tracks. + %contextMenu.enableItem( 0, %this.CanAdd( "VScriptEventTrack" ) ); + %contextMenu.enableItem( 1, %this.CanAdd( "VSpawnSphereSpawnTargetTrack" ) ); + + // Return Menu. + return %contextMenu; +} + +function VSpawnSphereGroup::isValid( %this ) +{ + // Valid? + return VTorque::isSpawnSphereObject( %this.getSceneObject() ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/main.cs new file mode 100644 index 000000000..e8cac3c10 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Groups/main.cs @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitGroupScripts() +{ + // Core. + exec( "./VGroup.cs" ); + + // Built In. + exec( "./VCameraGroup.cs" ); + exec( "./VDirectorGroup.cs" ); + exec( "./VLightObjectGroup.cs" ); + exec( "./VParticleEffectGroup.cs" ); + exec( "./VSceneObjectGroup.cs" ); + exec( "./VSpawnSphereGroup.cs" ); + + // Custom. + // Exec Custom Group Scripts. + + // Unique Group List. + $VerveEditor::UniqueGroupList = "VDirectorGroup"; +} +VerveEditor::InitGroupScripts(); diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Controls.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Controls.cs new file mode 100644 index 000000000..b2b64f858 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Controls.cs @@ -0,0 +1,163 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditorPropertyStack::ClearStack( %this ) +{ + while ( %this.getCount() > 0 ) + { + // Remove Object. + %this.remove( %this.getObject( 0 ) ); + } +} + +function VerveEditorPropertyStack::CreatePropertyRollout( %this, %groupLabel ) +{ + %groupWidth = getWord( %this.getExtent(), 0 ); + %groupHeight = 32; + + %propertyRollout = new GuiRolloutCtrl() + { + Class = "VEditorPropertyRollout"; + Profile = "VEditorPropertyRolloutProfile"; + + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %groupWidth SPC 18; + + Caption = %groupLabel; + }; + + %propertyStack = new GuiStackControl() + { + Class = "VEditorPropertyStack"; + Profile = "GuiTransparentProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %groupWidth SPC %groupHeight; + + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "0"; + }; + %propertyRollout.add( %propertyStack ); + + // Add Spacer. + VerveEditor::CreateSpacer( %propertyStack, 4 ); + + // Reference Stack. + %propertyRollout.Stack = %propertyStack; + + return %propertyRollout; +} + +function VEditorPropertyRollout::InspectObject( %this, %object ) +{ + %this.Stack.InspectObject( %object ); +} + +function VEditorPropertyStack::InspectObject( %this, %object ) +{ + %fieldCount = %this.getCount(); + for ( %i = 1; %i < %fieldCount; %i++ ) + { + %fieldContainer = %this.getObject( %i ); + %fieldControl = %fieldContainer.findObjectByInternalName( "FieldControl" ); + if ( !isObject( %fieldControl ) ) + { + // Nothing to Update. + continue; + } + + // Store Object. + %fieldControl.Object = %object; + + // Get Values. + %fieldName = %fieldControl.FieldName; + %fieldValue = %object.getFieldValue( %fieldName ); + + // Update Control? + if ( %fieldControl.isMethod( "Update" ) ) + { + // Update. + %fieldControl.Update( %fieldName, %fieldValue ); + } + } +} + +function VerveEditor::CreateField( %targetStack, %fieldName, %fieldType ) +{ + %fieldWidth = getWord( %targetStack.getExtent(), 0 ); + %fieldHeight = 20; + + %fieldContainer = new GuiControl() + { + Profile = "VEditorTransparentProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %fieldWidth SPC %fieldHeight; + }; + %targetStack.add( %fieldContainer ); + + %fieldLabel = new GuiTextCtrl() + { + Profile = "VEditorTextProfile"; + + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "6 2"; + Extent = %fieldWidth SPC 18; + + Text = %fieldName; + MaxLength = "1024"; + }; + %fieldContainer.add( %fieldLabel ); + + if ( isMethod( "VerveEditor", "Create" @ %fieldType @ "Field" ) ) + { + // Create the Input Control. + eval( "%fieldInput = VerveEditor::Create" @ %fieldType @ "Field( %fieldContainer, %fieldName );" ); + } + else + { + // Default To String Control. + %fieldInput = VerveEditor::CreateStringField( %fieldContainer, %fieldName ); + } + + return %fieldContainer; +} + +function VEditorPropertyField::ApplyValue( %this, %fieldName, %fieldValue ) +{ + // Apply Value. + %this.Object.setFieldValue( %fieldName, %fieldValue ); + + // Update Control. + %this.Update( %fieldName, %this.Object.getFieldValue( %fieldName ) ); +} + +function VerveEditor::CreateSpacer( %targetStack, %spacerHeight ) +{ + %fieldWidth = getWord( %targetStack.getExtent(), 0 ); + %fieldHeight = %spacerHeight; + + %fieldContainer = new GuiControl() + { + Profile = "VEditorTransparentProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %fieldWidth SPC %fieldHeight; + }; + %targetStack.add( %fieldContainer ); + + return %fieldContainer; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/CutCopyPaste.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/CutCopyPaste.cs new file mode 100644 index 000000000..c88fdbf21 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/CutCopyPaste.cs @@ -0,0 +1,152 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CanCut() +{ + return VerveEditor::CanCopy(); +} + +function VerveEditor::CutSelection() +{ + if ( !isObject( $VerveEditor::Controller ) || !VerveEditor::HasSelection() ) + { + return; + } + + %targetObject = $VerveEditor::InspectorObject; + if ( isObject( %targetObject ) ) + { + // Write To File. + %targetObject.writeFile( $VerveEditor::TemplateVClipboard ); + + // Store Object Type. + $VerveEditor::TemplateVClipboardObject = %targetObject; + + // Delete Object. + %targetObject.Delete(); + + // Refresh Editor. + VerveEditor::Refresh(); + } +} + +function VerveEditor::CanCopy() +{ + if ( VerveEditor::HasSelection() ) + { + if ( $VerveEditor::InspectorObject == $VerveEditor::Controller ) + { + return false; + } + } + + if ( $VerveEditor::InspectorObject.isMethod( "CanCopy" ) ) + { + if ( !$VerveEditor::InspectorObject.CanCopy() ) + { + return false; + } + } + + return ActiveActionMapSet.isMember( VerveEditorEditMap ); +} + +function VerveEditor::CopySelection() +{ + if ( !isObject( $VerveEditor::Controller ) || !VerveEditor::CanCopy() ) + { + return; + } + + %targetObject = $VerveEditor::InspectorObject; + if ( isObject( %targetObject ) ) + { + // Write To File. + %targetObject.writeFile( $VerveEditor::TemplateVClipboard ); + + // Reference Object. + $VerveEditor::TemplateVClipboardObject = %targetObject; + } +} + +function VerveEditor::CanPaste() +{ + if ( !VerveEditor::HasSelection() || !isFile( $VerveEditor::TemplateVClipboard ) ) + { + return false; + } + + return $VerveEditor::InspectorObject.CanPaste( $VerveEditor::TemplateVClipboardObject ); +} + +function VerveEditor::Paste() +{ + if ( !isObject( $VerveEditor::Controller ) || !VerveEditor::CanPaste() ) + { + return; + } + + if ( $VerveEditor::InspectorObject.getId() == $VerveEditor::Controller.getId() ) + { + // Special Paste. + VerveEditor::AddTemplateGroup( $VerveEditor::TemplateVClipboard ); + + return; + } + + if ( isObject( $VerveEditor::InspectorObject ) ) + { + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + // Read From File. + $VerveEditor::InspectorObject.readFile( $VerveEditor::TemplateVClipboard ); + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + // Refresh Editor. + VerveEditor::Refresh(); + } +} + +function VerveEditor::DeleteSelection() +{ + if ( !isObject( $VerveEditor::Controller ) || !VerveEditor::HasSelection() ) + { + return; + } + + %selectionSet = $VerveEditor::SelectionSet; + while ( %selectionSet.getCount() > 0 ) + { + %selection = %selectionSet.getObject( 0 ); + + if ( isObject( %selection.SiblingControl ) ) + { + // Delete Sibling Control. + %selection.SiblingControl.delete(); + } + + if ( isObject( %selection.Proxy ) ) + { + // Do Callback? + if ( %selection.Proxy.isMethod( "onRemove" ) ) + { + // Quick Callback. + %selection.Proxy.onRemove(); + } + + // Delete Reference Object. + %selection.Proxy.delete(); + } + + // Delete Control. + %selection.delete(); + } + + // Refresh. + VerveEditor::Refresh(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/EventNotify.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/EventNotify.cs new file mode 100644 index 000000000..fdfb5276e --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/EventNotify.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::GetEventManager() +{ + if ( !isObject( $VerveEditor::EventManager ) ) + { + $VerveEditor::EventManager = new EventManager() + { + Queue = "ProjectEventManager"; + }; + } + + return $VerveEditor::EventManager; +} + +function VerveEditor::RegisterEvent( %eventName ) +{ + if ( !VerveEditor::GetEventManager().isRegisteredEvent( %eventName ) ) + { + // Register Event. + VerveEditor::GetEventManager().RegisterEvent( %eventName ); + } +} + +function VerveEditor::AddEventNotify( %object, %eventName, %callback ) +{ + if ( isObject( $VerveEditor::EventManager ) ) + { + // Subscribe To Event. + $VerveEditor::EventManager.SubScribe( %object, %eventName, %callback ); + } +} + +function VerveEditor::RemoveEventNotify( %object, %eventName ) +{ + if ( isObject( $VerveEditor::EventManager ) ) + { + // Remove Event. + $VerveEditor::EventManager.Remove( %object, %eventName ); + } +} + +function VerveEditor::PostEvent( %eventName, %refObject ) +{ + if ( isObject( $VerveEditor::EventManager ) ) + { + // Notify Event. + $VerveEditor::EventManager.PostEvent( %eventName, %refObject ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Factory.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Factory.cs new file mode 100644 index 000000000..d96b10330 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Factory.cs @@ -0,0 +1,248 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::AddGroup( %groupType ) +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + // No Controller. + return; + } + + if ( %groupType $= "" ) + { + // Default. + %groupType = "VGroup"; + } + + /* + // Add Template Group. + VerveEditor::AddTemplateGroup( $VerveEditor::TemplateFolder @ "/" @ %groupType @ ".vsf" ); + */ + + // Get the Name of the Target Group. + VerveEditorGroupBuilderGUI.Build( %groupType, "VerveEditor::_AddGroup" ); +} + +function VerveEditor::_AddGroup( %groupType, %groupLabel ) +{ + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + // Create the Group. + %groupObject = new ( %groupType )(); + + // Add to Group. + $VerveEditor::Controller.addObject( %groupObject ); + + // Apply the Label. + %groupObject.setLabelUnique( %groupLabel ); + + // Callback. + if ( !%groupObject.OnAdd() ) + { + // Remove Object. + $VerveEditor::Controller.removeObject( %groupObject ); + + // Delete Object. + %groupObject.delete(); + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + return; + } + + // Resolve the Field Stack. + %groupObject.ResolveBuildStack( VerveEditorGroupBuilderFieldStack ); + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + // Refresh Editor. + VerveEditor::Refresh(); + + // Set Selection. + VerveEditor::SetSelection( %groupObject.Control ); +} + +function VerveEditor::AddTemplateGroup( %templateFile ) +{ + if ( !isObject( $VerveEditor::Controller ) || !isFile( %templateFile ) ) + { + // No Controller. + return; + } + + // Fetch Current Count. + %groupCount = $VerveEditor::Controller.getCount(); + + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + // Load Template. + $VerveEditor::Controller.readTemplate( %templateFile ); + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + %newCount = $VerveEditor::Controller.getCount(); + if ( %groupCount != %newCount ) + { + if ( %newCount > %groupCount ) + { + // Select New Object. + %selectedObject = $VerveEditor::Controller.getObject( %newCount - 1 ); + } + + // Refresh Editor. + VerveEditor::Refresh(); + + if ( isObject( %selectedObject ) ) + { + // Set Selection. + VerveEditor::SetSelection( %selectedObject.Control ); + } + } +} + +function VerveEditor::AddTrack( %trackType, %targetGroup, %refresh ) +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + // No Controller. + return; + } + + if ( !isObject( %targetGroup ) ) + { + if ( !isObject( $VerveEditor::InspectorObject ) ) + { + // No Controller or Selection. + return; + } + + // Use Current Selection. + %targetGroup = $VerveEditor::InspectorObject; + } + + if ( !%targetGroup.isMemberOfClass( "VGroup" ) ) + { + // Invalid Target. + return; + } + + if ( %trackType $= "" ) + { + // Default. + %trackType = "VTrack"; + } + + // Create Track. + %trackObject = new ( %trackType )(); + + // Add to Group. + %targetGroup.addObject( %trackObject ); + + // Refresh Label. + %trackObject.setLabelUnique( %trackObject.Label ); + + // Callback. + if ( !%trackObject.OnAdd() ) + { + // Remove Object. + %targetGroup.removeObject( %trackObject ); + + // Delete Object. + %trackObject.delete(); + + // Return. + return 0; + } + + if ( %refresh $= "" || %refresh == true ) + { + // Refresh. + VerveEditor::Refresh(); + + // Select New Object. + VerveEditor::SetSelection( %trackObject.Control ); + } + + // Return Track. + return %trackObject; +} + +function VerveEditor::AddEvent( %targetTrack, %targetTime, %refresh ) +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + // No Controller. + return; + } + + if ( !isObject( %targetTrack ) ) + { + if ( !isObject( $VerveEditor::InspectorObject ) ) + { + // No Controller or Selection. + return; + } + + // Use Current Selection. + %targetTrack = $VerveEditor::InspectorObject; + } + + if ( !%targetTrack.isMemberOfClass( "VTrack" ) ) + { + // Invalid Target. + return; + } + + // Create Event. + %eventObject = %targetTrack.CreateEvent(); + if ( !isObject( %eventObject ) ) + { + // Return. + return; + } + + // Add to Track. + %targetTrack.addObject( %eventObject ); + + if ( %targetTime $= "" ) + { + // User Controller Time. + %targetTime = $VerveEditor::Controller.Time; + } + + // Apply Time. + %eventObject.SnapToTime( %targetTime, true ); + + // Callback. + if ( !%eventObject.OnAdd() ) + { + // Remove Object. + %targetTrack.removeObject( %eventObject ); + + // Delete Object. + %eventObject.delete(); + + // Return. + return 0; + } + + if ( %refresh $= "" || %refresh == true ) + { + // Refresh. + VerveEditor::Refresh(); + + // Select Existing Track. + VerveEditor::SetSelection( %targetTrack.Control ); + } + + // Return Event. + return %eventObject; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FactoryControls.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FactoryControls.cs new file mode 100644 index 000000000..4a6893494 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FactoryControls.cs @@ -0,0 +1,115 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +$VerveEditor::TemplateFolder = getMainDotCsDir() @ "/" @ expandFileName( "tools/VerveEditor/Templates" ); +$VerveEditor::TemplateCustomFolder = $VerveEditor::TemplateFolder @ "/Custom"; +$VerveEditor::TemplateVClipboard = $VerveEditor::TemplateFolder @ "/VClipboard.vsf"; +$VerveEditor::TemplateVClipboardObject = ""; + +//----------------------------------------------------------------------------- + +function VerveCustomTemplateMenu::Init( %this ) +{ + %fieldCount = 0; + %fileSpec = $VerveEditor::TemplateCustomFolder @ "/*.vsf"; + for ( %file = findFirstFile( %fileSpec ); %file !$= ""; %file = findNextFile( %fileSpec ) ) + { + // Create Item. + %this.Item[%fieldCount] = "Add" SPC fileBase( %file ) TAB "" TAB "VerveEditor::AddTemplateGroup(\"" @ %file @ "\");"; + + // Increment. + %fieldCount += 1; + } + + // Sort By File Name. + for ( %j = 0; %j < %fieldCount; %j++ ) + { + for ( %i = %fieldCount - 1; %i > %j; %i-- ) + { + %itemA = getField( %this.Item[%i - 0], 0 ); + %itemB = getField( %this.Item[%i - 1], 0 ); + + if ( strcmp( strlwr( %itemA ), strlwr( %itemB ) ) < 0 ) + { + // Swap. + %itemTmp = %this.Item[%i]; + %this.Item[%i - 0] = %this.Item[%i - 1]; + %this.Item[%i - 1] = %itemTmp; + } + } + } + + // Parent Init. + Parent::Init( %this ); +} + +function VEditorAddGroupButton::DisplayContextMenu( %this, %x, %y ) +{ + // Use Current Controller. + %targetController = $VerveEditor::Controller; + + // Get Context Menu. + %contextMenu = %targetController.GetAddGroupMenu(); + if ( !isObject( %contextMenu ) ) + { + return; + } + + if ( %x $= "" || %y $= "" ) + { + %position = %this.getGlobalPosition(); + %extent = %this.getExtent(); + + %x = getWord( %position, 0 ) + getWord( %extent, 0 ); + %y = getWord( %position, 1 ); + } + + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); +} + +function VEditorAddTrackButton::DisplayContextMenu( %this, %x, %y ) +{ + if ( !isObject( $VerveEditor::InspectorObject ) ) + { + // No Controller or Selection. + return; + } + + // Use Current Selection. + %targetGroup = $VerveEditor::InspectorObject; + + if ( !%targetGroup.isMemberOfClass( "VGroup" ) ) + { + // Invalid Target. + return; + } + + // Get Context Menu. + %contextMenu = %targetGroup.GetAddTrackMenu(); + if ( !isObject( %contextMenu ) ) + { + return; + } + + if ( %x $= "" || %y $= "" ) + { + %position = %this.getGlobalPosition(); + %extent = %this.getExtent(); + + %x = getWord( %position, 0 ) + getWord( %extent, 0 ); + %y = getWord( %position, 1 ); + } + + // Display. + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FieldNotify.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FieldNotify.cs new file mode 100644 index 000000000..5e87678ec --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/FieldNotify.cs @@ -0,0 +1,136 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::AddInspectorFieldNotify( %fieldName, %refObject ) +{ + if ( !isObject( $VerveEditor::InspectorFieldNotifySet ) ) + { + $VerveEditor::InspectorFieldNotifySet = new SimSet(); + } + + %inspectorSet = $VerveEditor::InspectorFieldNotifySet; + if ( isObject( %refObject ) && !%inspectorSet.isMember( %refObject ) ) + { + // Add The Object. + %inspectorSet.add( %refObject ); + } + + // Add Field Reference. + %refObject.InspectorFieldNotifyList = rtrim( %fieldName SPC %refObject.InspectorFieldNotifyList ); +} + +function VObject::AddFieldNotify( %this, %fieldName, %refObject ) +{ + if ( isObject( %refObject ) ) + { + // Store. + %this.FieldNotify[%fieldName] = trim( %this.FieldNotify[%fieldName] SPC %refObject ); + + // Update. + %refObject.Update( %fieldName, %this.getFieldValue( %fieldName ) ); + } +} + +function VObject::setFieldValue( %this, %fieldName, %fieldValue ) +{ + // Fetch Old Value. + %oldValue = %this.getFieldValue( %fieldName ); + + if ( stricmp( %oldValue , %fieldValue ) == 0 ) + { + // No Update. + return; + } + + // Update Value. + Parent::setFieldValue( %this, %fieldName, %fieldValue ); + + // Notify Change. + %this.NotifyFieldChange( %fieldName, %oldValue ); +} + +function VObject::NotifyFieldChange( %this, %fieldName, %oldValue ) +{ + // Get Field Value. + %newValue = %this.getFieldValue( %fieldName ); + + %controlList = %this.FieldNotify[%fieldName]; + %controlCount = getWordCount( %controlList ); + for ( %i = 0; %i < %controlCount; %i++ ) + { + // Fetch the Control. + %control = getWord( %controlList, %i ); + + if ( !isObject( %control ) ) + { + // Remove Deleted Controls. + %controlList = removeWord( %controlList, %i ); + %controlCount -= 1; + + %i -= 1; + continue; + } + + // Update. + %control.Update( %fieldName, %newValue ); + } + + // Updated List? + %this.FieldNotify[%fieldName] = %controlList; + + // Update Inspector Fields? + if ( isObject( $VerveEditor::InspectorObject ) && $VerveEditor::InspectorObject.getId() == %this.getId() ) + { + %refObjectSet = $VerveEditor::InspectorFieldNotifySet; + %refObjectCount = %refObjectSet.getCount(); + for ( %i = 0; %i < %controlCount; %i++ ) + { + // Fetch the Object. + %refObject = %refObjectSet.getObject( %i ); + if ( !isWordInList( %fieldName, %refObject.InspectorFieldNotifyList ) ) + { + // Skip. + continue; + } + + if ( %refObject.isMethod( "Update" ) ) + { + // Update. + %refObject.Update( %fieldName, %newValue ); + } + } + } + + // Update Object? + if ( %this.isMethod( "onFieldChange" ) ) + { + // Notify. + %this.onFieldChange( %fieldName, %oldValue, %newValue ); + } +} + +function VController::setFieldValue( %this, %fieldName, %fieldValue ) +{ + // Fetch Old Value. + %oldValue = %this.getFieldValue( %fieldName ); + + if ( stricmp( %oldValue , %fieldValue ) == 0 ) + { + // No Update. + return; + } + + // Update Value. + Parent::setFieldValue( %this, %fieldName, %fieldValue ); + + // Notify Change. + %this.NotifyFieldChange( %fieldName, %oldValue ); +} + +function VController::NotifyFieldChange( %this, %fieldName, %oldValue ) +{ + // Use Default Callback. + VObject::NotifyFieldChange( %this, %fieldName, %oldValue ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeBool.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeBool.cs new file mode 100644 index 000000000..d3fd3e04b --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeBool.cs @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateBoolField( %fieldContainer, %fieldName ) +{ + %fieldWidth = getWord( %fieldContainer.getExtent(), 0 ); + + %fieldInput = new GuiCheckBoxCtrl() + { + Class = "VEditorBoolPropertyField"; + InternalName = "FieldControl"; + Profile = "VEditorCheckBoxProfile"; + + HorizSizing = "width"; + VertSizing = "center"; + Position = %fieldWidth - 156 SPC 0; + Extent = "150 18"; + + Text = ""; + + Command = "$ThisControl.ApplyValue();"; + + // Store Field Properties. + FieldName = %fieldName; + }; + %fieldContainer.add( %fieldInput ); + + // Field Notify. + VerveEditor::AddInspectorFieldNotify( %fieldName, %fieldInput ); + + return %fieldInput; +} + +function VEditorBoolPropertyField::ApplyValue( %this ) +{ + VEditorPropertyField::ApplyValue( %this, %this.FieldName, %this.getValue() ); +} + +function VEditorBoolPropertyField::Update( %this, %fieldName, %fieldValue ) +{ + if ( %this.getValue() !$= %fieldValue ) + { + %this.setValue( %fieldValue ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeData.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeData.cs new file mode 100644 index 000000000..93fe911fc --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeData.cs @@ -0,0 +1,336 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateDataField( %fieldContainer, %fieldName ) +{ + %fieldWidth = getWord( %fieldContainer.getExtent(), 0 ); + + %fieldType = new GuiPopUpMenuCtrl() + { + Class = "VEditorDataTypePropertyField"; + Profile = "VEditorPopupMenuProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 72 SPC 0; + Extent = 44 SPC 18; + + Command = "$ThisControl.ApplyValue();"; + + // Store Field Properties. + FieldName = %fieldName; + }; + %fieldContainer.add( %fieldType ); + + %fieldInput = new GuiTextEditCtrl() + { + Class = "VEditorDataPropertyField"; + SuperClass = "VEditorStringPropertyField"; + InternalName = "FieldControl"; + Profile = "VEditorTextEditProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 156 SPC 0; + Extent = 80 SPC 18; + + AltCommand = "$ThisControl.ApplyValue();"; + Validate = "$ThisControl.ApplyValue();"; + + // Store Field Properties. + FieldName = %fieldName; + FieldType = %fieldType; + }; + %fieldContainer.add( %fieldInput ); + + %fieldButton = new GuiBitmapButtonCtrl() + { + Class = "VEditorDataPropertyButton"; + InternalName = "FieldButton"; + Profile = "VEditorBitmapButtonProfile"; + + HorizSizing = "left"; + VertSizing = "bottom"; + Position = %fieldWidth - 24 SPC 0; + Extent = "18 18"; + + Bitmap = "tools/VerveEditor/GUI/Images/btn_DeleteSml"; + + Command = %fieldInput @ ".Remove();"; + }; + %fieldContainer.add( %fieldButton ); + + // Apply Enum Content. + %fieldType.add( "EXP", 0 ); + %fieldType.add( "STA", 1 ); + %fieldType.add( "VAR", 2 ); + + return %fieldInput; +} + +function VEditorDataPropertyField::Update( %this, %fieldName, %fieldValue ) +{ + // Fetch Object. + %controller = $VerveEditor::Controller; + if ( !isObject( %controller ) ) + { + // No Object! + return; + } + + if ( %fieldName $= "" ) + { + return; + } + + Parent::Update( %this, %fieldName, %fieldValue ); + + // Update Type. + %fieldType = %controller.getDataFieldType( %fieldName ); + switch$( %fieldType ) + { + case "EXPRESSION" : %fieldType = "EXP"; + case "STATIC" : %fieldType = "STA"; + case "VARIABLE" : %fieldType = "VAR"; + } + + // Apply. + %this.FieldType.setText( %fieldType ); +} + +function VEditorDataPropertyField::ApplyValue( %this ) +{ + // Fetch Object. + %controller = $VerveEditor::Controller; + if ( !isObject( %controller ) ) + { + // No Object! + return; + } + + // Update? + %update = stricmp( %controller.getFieldValue( %this.FieldName ), %this.getText() ); + + // Parent Update. + Parent::ApplyValue( %this ); + + if ( %update ) + { + // Post Event. + VerveEditor::PostEvent( "VGroupObjectUpdate", %controller ); + } +} + +function VEditorDataTypePropertyField::ApplyValue( %this ) +{ + // Fetch Object. + %controller = $VerveEditor::Controller; + if ( !isObject( %controller ) ) + { + // No Object! + return; + } + + // Update Type. + %fieldType = %this.getText(); + switch$( %fieldType ) + { + case "EXP" : %fieldType = "EXPRESSION"; + case "STA" : %fieldType = "STATIC"; + case "VAR" : %fieldType = "VARIABLE"; + } + + if ( %controller.getDataFieldType( %this.FieldName ) !$= %fieldType ) + { + // Apply. + %controller.addDataField( %fieldType, %this.FieldName ); + + // Post Event. + VerveEditor::PostEvent( "VGroupObjectUpdate", %controller ); + } +} + +//------------------------------------------------------------------------- + +function VEditorDataPropertyField::Insert( %fieldType, %fieldName, %fieldValue ) +{ + %controller = $VerveEditor::Controller; + if ( !isObject( %controller ) ) + { + // No Object! + return; + } + + if ( %fieldName $= "" ) + { + // Invalid Field Name. + return; + } + + switch$( %fieldType ) + { + case "EXP" : %fieldType = "EXPRESSION"; + case "STA" : %fieldType = "STATIC"; + case "VAR" : %fieldType = "VARIABLE"; + } + + // Add Data Field. + %controller.addDataField( %fieldType, strReplace( %fieldName, " ", "" ) ); + + // Apply Value. + %controller.setFieldValue( %fieldName, %fieldValue ); + + // Refresh Inspection. + schedule( 0, 0, "VerveEditor::OnSelectionUpdate" ); +} + +function VEditorDataPropertyField::Remove( %this ) +{ + %controller = $VerveEditor::Controller; + if ( !isObject( %controller ) ) + { + // No Object! + return; + } + + // Clear Data. + %controller.removeDataField( %this.FieldName ); + + // Refresh Inspection. + schedule( 0, 0, "VerveEditor::OnSelectionUpdate" ); +} + +//------------------------------------------------------------------------- + +function VerveEditor::CreateAddDataField( %targetStack ) +{ + %fieldWidth = getWord( %targetStack.getExtent(), 0 ); + %fieldHeight = 18; + + %fieldContainer = new GuiControl() + { + Profile = "VEditorTransparentProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %fieldWidth SPC %fieldHeight; + }; + %targetStack.add( %fieldContainer ); + + %fieldName = new GuiTextEditCtrl() + { + Class = "VEditorAddDataNameField"; + InternalName = "FieldControl"; + Profile = "VEditorTextEditProfile"; + + HorizSizing = "right"; + VertSizing = "center"; + Position = "6 0"; + Extent = "106" SPC 18; + + Text = "FieldName"; + }; + %fieldContainer.add( %fieldName ); + + %fieldValue = new GuiTextEditCtrl() + { + Class = "VEditorAddDataValueField"; + InternalName = "FieldValue"; + Profile = "VEditorTextEditProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 156 SPC 0; + Extent = 80 SPC 18; + + Text = "FieldValue"; + }; + %fieldContainer.add( %fieldValue ); + + %fieldType = new GuiPopUpMenuCtrl() + { + Class = "VEditorDataTypePropertyField"; + InternalName = "FieldType"; + Profile = "VEditorPopupMenuProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 72 SPC 0; + Extent = 44 SPC 18; + }; + %fieldContainer.add( %fieldType ); + + %fieldButton = new GuiBitmapButtonCtrl() + { + Class = "VEditorDataPropertyButton"; + InternalName = "FieldButton"; + Profile = "VEditorBitmapButtonProfile"; + + HorizSizing = "left"; + VertSizing = "bottom"; + Position = %fieldWidth - 24 SPC 0; + Extent = "18 18"; + + Bitmap = "tools/VerveEditor/GUI/Images/btn_AddSml"; + + Command = "VEditorDataPropertyField::Insert(" @ %fieldType @ ".getText(), " @ %fieldName @ ".getText(), " @ %fieldValue @ ".getText() );"; + }; + %fieldContainer.add( %fieldButton ); + + // Apply Enum Content. + %fieldType.add( "EXP", 0 ); + %fieldType.add( "STA", 1 ); + %fieldType.add( "VAR", 2 ); + + // Set Default. + %fieldType.setFirstSelected(); + + return %fieldContainer; +} + +function VEditorAddDataNameField::onGainFirstResponder( %this ) +{ + VEditorStringPropertyField::onGainFirstResponder( %this ); + + if ( %this.getText() $= "FieldName" ) + { + // Clear. + %this.setText( "" ); + } +} + +function VEditorAddDataNameField::onLoseFirstResponder( %this ) +{ + VEditorStringPropertyField::onLoseFirstResponder( %this ); + + if ( %this.getText() $= "" ) + { + // Clear. + %this.setText( "FieldName" ); + } +} + +function VEditorAddDataValueField::onGainFirstResponder( %this ) +{ + VEditorStringPropertyField::onGainFirstResponder( %this ); + + if ( %this.getText() $= "FieldValue" ) + { + // Clear. + %this.setText( "" ); + } +} + +function VEditorAddDataValueField::onLoseFirstResponder( %this ) +{ + VEditorStringPropertyField::onLoseFirstResponder( %this ); + + if ( %this.getText() $= "" ) + { + // Clear. + %this.setText( "FieldValue" ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeEnum.cs new file mode 100644 index 000000000..e83224d08 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeEnum.cs @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateEnumField( %fieldContainer, %fieldName, %class ) +{ + %fieldWidth = getWord( %fieldContainer.getExtent(), 0 ); + + %fieldInput = new GuiPopupMenuCtrl() + { + Class = %class; + SuperClass = "VEditorEnumPropertyField"; + InternalName = "FieldControl"; + Profile = "VEditorPopupMenuProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 156 SPC 0; + Extent = "150 18"; + + Command = "$ThisControl.ApplyValue();"; + + // Store Field Properties. + FieldName = %fieldName; + }; + %fieldContainer.add( %fieldInput ); + + // Field Notify. + VerveEditor::AddInspectorFieldNotify( %fieldName, %fieldInput ); + + return %fieldInput; +} + +function VEditorEnumPropertyField::ApplyValue( %this ) +{ + // Apply Value. + VEditorPropertyField::ApplyValue( %this, %this.FieldName, %this.getText() ); +} + +function VEditorEnumPropertyField::Update( %this, %fieldName, %fieldValue ) +{ + if ( %this.getText() !$= %fieldValue ) + { + // Apply Text. + %this.setText( %fieldValue ); + } +} + +function VEditorEnumPropertyField::PopulateFromDatablockGroup( %this, %className ) +{ + // Clear List. + %this.clear(); + + // Iterate Over Datablocks. + %dataSet = DataBlockGroup; + %dataCount = %dataSet.getCount(); + for ( %i = 0; %i < %dataCount; %i++ ) + { + // Fetch Item. + %dataObject = %dataSet.getObject( %i ); + if ( %dataObject.isMemberOfClass( %className ) ) + { + // Add Item. + %this.add( %dataObject.getName(), %i ); + } + } + + // Sort. + %this.sort(); +} + +function VEditorEnumPropertyField::PopulateFromRootGroup( %this, %className ) +{ + // Clear List. + %this.clear(); + + // Iterate Over RootGroup. + %dataSet = RootGroup; + %dataCount = %dataSet.getCount(); + for ( %i = 0; %i < %dataCount; %i++ ) + { + // Fetch Item. + %dataObject = %dataSet.getObject( %i ); + if ( %dataObject.isMemberOfClass( %className ) ) + { + // Add Item. + %this.add( %dataObject.getName(), %i ); + } + } + + // Sort. + %this.sort(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeString.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeString.cs new file mode 100644 index 000000000..17dc2d6f0 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeString.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateStringField( %fieldContainer, %fieldName ) +{ + %fieldWidth = getWord( %fieldContainer.getExtent(), 0 ); + + %fieldInput = new GuiTextEditCtrl() + { + Class = "VEditorStringPropertyField"; + InternalName = "FieldControl"; + Profile = "VEditorTextEditProfile"; + + HorizSizing = "left"; + VertSizing = "center"; + Position = %fieldWidth - 156 SPC 0; + Extent = "150 18"; + + AltCommand = "$ThisControl.ApplyValue();"; + Validate = "$ThisControl.ApplyValue();"; + + // Store Field Properties. + FieldName = %fieldName; + }; + %fieldContainer.add( %fieldInput ); + + // Field Notify. + VerveEditor::AddInspectorFieldNotify( %fieldName, %fieldInput ); + + return %fieldInput; +} + +function VEditorStringPropertyField::ApplyValue( %this ) +{ + VEditorPropertyField::ApplyValue( %this, %this.FieldName, %this.getText() ); +} + +function VEditorStringPropertyField::Update( %this, %fieldName, %fieldValue ) +{ + if ( %this.getText() !$= %fieldValue ) + { + %this.setText( %fieldValue ); + } +} + +function VEditorStringPropertyField::onGainFirstResponder( %this ) +{ + // Disable Cut, Copy & Paste. + VerveEditorEditMap.pop(); +} + +function VEditorStringPropertyField::onLoseFirstResponder( %this ) +{ + // Enable Cut, Copy & Paste. + VerveEditorEditMap.push(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeToggleEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeToggleEnum.cs new file mode 100644 index 000000000..1235cbaf1 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeToggleEnum.cs @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateToggleEnumField( %fieldContainer, %fieldName, %class ) +{ + // Create Enum Menu. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName ); + + // Populate Menu. + %fieldInput.add( "On", 0 ); + %fieldInput.add( "Off", 1 ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCameraGroupEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCameraGroupEnum.cs new file mode 100644 index 000000000..6c8cfae85 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCameraGroupEnum.cs @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVCameraGroupEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + return VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVCameraGroupEnumPropertyField" ); +} + +function VEditorVCameraGroupEnumPropertyField::OnWake( %this ) +{ + // Clear List. + %this.clear(); + + // Iterate Over Groups. + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %group = %groupSet.getObject( %i ); + if ( %group.isMemberOfClass( "VCameraGroup" ) ) + { + // Add Item. + %this.add( %group.Label, %i ); + } + } + + // Sort. + %this.sort(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCommandEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCommandEnum.cs new file mode 100644 index 000000000..7b0a902ac --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVCommandEnum.cs @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVCommandEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVCommandEnumPropertyField" ); + + // Populate Menu. + %fieldInput.add( "EXPRESSION", 0 ); + %fieldInput.add( "METHOD", 1 ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVControllerDataEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVControllerDataEnum.cs new file mode 100644 index 000000000..1e2d68c27 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVControllerDataEnum.cs @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVControllerDataEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + return VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVControllerDataEnumPropertyField" ); +} + +function VEditorVControllerDataEnumPropertyField::OnWake( %this, %eventName ) +{ + // Clear List. + %this.clear(); + + // Iterate Over Data Items. + %dataObject = $VerveEditor::Controller; + %dataFieldCount = %dataObject.getDataFieldCount(); + for ( %i = 0; %i < %dataFieldCount; %i++ ) + { + // Add Field Name. + %this.add( %dataObject.getDataFieldName( %i ), %i ); + } + + // Sort. + %this.sort(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVGroupEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVGroupEnum.cs new file mode 100644 index 000000000..810bd08c0 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVGroupEnum.cs @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVGroupEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + return VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVGroupEnumPropertyField" ); +} + +function VEditorVGroupEnumPropertyField::OnWake( %this ) +{ + // Clear List. + %this.clear(); + + // Iterate Over Groups. + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + // Add Item. + %this.add( %groupSet.getObject( %i ).Label, %i ); + } + + // Sort. + %this.sort(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVLightAnimationDataEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVLightAnimationDataEnum.cs new file mode 100644 index 000000000..6b390ebfb --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVLightAnimationDataEnum.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVLightAnimationDataEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum List. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName ); + + // Populate Enum. + %fieldInput.PopulateFromDatablockGroup( "LightAnimData" ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPathOrientationModeEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPathOrientationModeEnum.cs new file mode 100644 index 000000000..a9f85353c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPathOrientationModeEnum.cs @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVPathOrientationModeEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVPathOrientationModeEnumPropertyField" ); + + // Populate Menu. + %fieldInput.add( "FREE", 0 ); + %fieldInput.add( "INTERPOLATE", 1 ); + %fieldInput.add( "TOOBJECT", 2 ); + %fieldInput.add( "TOPATH", 3 ); + %fieldInput.add( "TOPOINT", 4 ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPostEffectEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPostEffectEnum.cs new file mode 100644 index 000000000..60f951257 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVPostEffectEnum.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVPostEffectEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum List. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName ); + + // Populate Enum. + %fieldInput.PopulateFromRootGroup( "PostEffect" ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSFXProfileEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSFXProfileEnum.cs new file mode 100644 index 000000000..ecbd1fcdb --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSFXProfileEnum.cs @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVSFXProfileEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum List. + %fieldInput = VerveEditor::CreateEnumField( %fieldContainer, %fieldName ); + + // Populate Enum. + %fieldInput.PopulateFromDatablockGroup( "SFXProfile" ); + + return %fieldInput; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSceneEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSceneEnum.cs new file mode 100644 index 000000000..d7102e376 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVSceneEnum.cs @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVSceneEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + return VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVSceneEnumPropertyField" ); +} + +function VEditorVSceneEnumPropertyField::OnWake( %this ) +{ + // Clear List. + %this.clear(); + + // Iterate Over Groups. + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + %groupObject = %groupSet.getObject( %i ); + if ( %groupObject.isMemberOfClass( "VDirectorGroup" ) ) + { + break; + } + + // Clear. + %groupObject = 0; + } + + if ( !isObject( %groupObject ) ) + { + return; + } + + %trackSet = %groupObject; + %trackCount = %trackSet.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %trackObject = %trackSet.getObject( %i ); + if ( %trackObject.isMemberOfClass( "VDirectorTrack" ) ) + { + break; + } + + // Clear. + %trackObject = 0; + } + + if ( !isObject( %groupObject ) ) + { + return; + } + + %eventSet = %trackObject; + %eventCount = %eventSet.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + %eventObject = %eventSet.getObject( %i ); + if ( %eventObject.Label !$= "" && %this.findText( %eventObject.Label ) == -1 ) + { + %this.add( %eventObject.Label, %this.Size() ); + } + } + + // Sort. + %this.sort(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVShapeAnimationEnum.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVShapeAnimationEnum.cs new file mode 100644 index 000000000..eb3c320a9 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/TypeVShapeAnimationEnum.cs @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::CreateVShapeAnimationEnumField( %fieldContainer, %fieldName ) +{ + // Create Enum Menu. + return VerveEditor::CreateEnumField( %fieldContainer, %fieldName, "VEditorVShapeAnimationEnumPropertyField" ); +} + +function VEditorVShapeAnimationEnumPropertyField::OnWake( %this ) +{ + // Clear List. + %this.clear(); + + // Valid Target? + if ( !$VerveEditor::InspectorObject.isMethod( "getSceneObject" ) ) + { + return; + } + + // Fetch Scene Object. + %objectReference = $VerveEditor::InspectorObject.getSceneObject(); + + // Valid Object? + if ( !isObject( %objectReference ) || !%objectReference.isMemberOfClass( "ShapeBase" ) ) + { + return; + } + + // Find the Constructor for this Shape. + %objectConstructor = %this.FindConstructor( %objectReference ); + if ( !isObject( %objectConstructor ) ) + { + // Invalid Shape Constructor. + return; + } + + // Iterate Over Sequences. + %sequenceCount = %objectConstructor.getSequenceCount(); + for ( %i = 0; %i < %sequenceCount; %i++ ) + { + %sequenceName = %objectConstructor.getSequenceName( %i ); + if ( %this.FindText( %sequenceName ) == -1 ) + { + // Add Item. + %this.add( %sequenceName, %this.Size() ); + } + } + + // Sort. + %this.sort(); +} + +function VEditorVShapeAnimationEnumPropertyField::FindConstructor( %this, %objectReference ) +{ + %datablock = %objectReference.getDataBlock(); + if ( !isObject( %datablock ) ) + { + return 0; + } + + // Fetch the Shape File. + %shapeFile = %datablock.shapeFile; + + %count = TSShapeConstructorGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %obj = TSShapeConstructorGroup.getObject(%i); + if ( %obj.baseShape $= %shapeFile ) + { + return %obj; + } + } + + return 0; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/main.cs new file mode 100644 index 000000000..d85bac4b2 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Fields/main.cs @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitInspectorFieldScripts() +{ + exec( "./TypeBool.cs" ); + exec( "./TypeData.cs" ); + exec( "./TypeEnum.cs" ); + exec( "./TypeString.cs" ); + + exec( "./TypeVCameraGroupEnum.cs" ); + exec( "./TypeVCommandEnum.cs" ); + exec( "./TypeVControllerDataEnum.cs" ); + exec( "./TypeVGroupEnum.cs" ); + exec( "./TypeVLightAnimationDataEnum.cs" ); + exec( "./TypeVPathOrientationModeEnum.cs" ); + exec( "./TypeVPostEffectEnum.cs" ); + exec( "./TypeVSceneEnum.cs" ); + exec( "./TypeVSFXProfileEnum.cs" ); + exec( "./TypeVShapeAnimationEnum.cs" ); + exec( "./TypeToggleEnum.cs" ); +} +VerveEditor::InitInspectorFieldScripts(); \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Lists.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Lists.cs new file mode 100644 index 000000000..23869e2ef --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Lists.cs @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VEditorPropertyList::onAdd( %this ) +{ + if ( !VEditorObjectPropertySet.isMember( %this ) ) + { + // Add Reference List. + VEditorObjectPropertySet.add( %this ); + } +} + +function VEditorPropertyList::onRemove( %this ) +{ + if ( isObject( %this.ControlCache ) ) + { + if ( %this.ControlCache.getClassName() !$= "SimSet" ) + { + // Clear Set. + while ( %this.ControlCache.getCount() > 0 ) + { + // Delete Control. + %this.ControlCache.getObject( 0 ).delete(); + } + } + + // Delete Cache. + %this.ControlCache.delete(); + } +} + +new ScriptGroup( VEditorObjectPropertySet ) +{ + //------------------------------------------------------------------------- + // + // VObject + // + //------------------------------------------------------------------------- + + new ScriptObject( VObjectPropertyList ) + { + SuperClass = "VEditorPropertyList"; + + Group[0] = "VObject"; + Field[0, 0] = "Label"; + Field[0, 1] = "Enabled"; + }; +}; diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Properties.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Properties.cs new file mode 100644 index 000000000..de715b50a --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Properties.cs @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VEditorPropertyList::CreateInspector( %this ) +{ + // Target Stack. + %targetStack = VerveEditorPropertyStack; + + // Clear Stack. + %targetStack.ClearStack(); + + %propertyList = %this; + while ( isObject( %propertyList ) ) + { + if ( !isObject( %propertyList.ControlCache ) ) + { + // Create and Store Cache. + %propertyList.ControlCache = %propertyList.CreateInspectorGroup( %targetStack ); + } + + if ( %propertyList.ControlCache.getClassName() !$= "SimSet" ) + { + // Single Control. + %targetStack.add( %propertyList.ControlCache ); + } + else + { + // Multiple Controls. + %controlSet = %propertyList.ControlCache; + %controlCount = %controlSet.getCount(); + for ( %i = 0; %i < %controlCount; %i++ ) + { + %targetStack.add( %controlSet.getObject( %i ) ); + } + } + + // Get the Parent. + %propertyList = %propertyList.Parent; + } +} + +function VEditorPropertyList::CreateInspectorGroup( %this, %targetStack ) +{ + %controlSet = new SimSet(); + + %i = 0; + while ( %this.Group[%i] !$= "" ) + { + %groupName = %this.Group[%i]; + %groupRollout = %targetStack.CreatePropertyRollout( %groupName ); + %propertyStack = %groupRollout.Stack; + + %j = 0; + while ( %this.Field[%i, %j] !$= "" ) + { + %fieldName = %this.Field[%i, %j]; + %fieldType = %this.Type[%i, %j]; + + if ( %fieldType $= "" ) + { + // Use ConsoleObject Field Type. + %fieldType = $VerveEditor::InspectorObject.getFieldType( %fieldName ); + %fieldType = getSubStr( %fieldType, 4, strlen( %fieldType ) - 4 ); + } + + if ( getWordCount( %fieldName ) == 1 ) + { + VerveEditor::CreateField( %propertyStack, %fieldName, %fieldType ); + } + else + { + %fieldType = getWord( %fieldName, 0 ); + switch$ ( %fieldType ) + { + case "SPACER" : VerveEditor::CreateSpacer( %propertyStack, getWord( %fieldName, 1 ) ); + } + } + + // Next Field. + %j++; + } + + // Store. + %controlSet.add( %groupRollout ); + + // Next Group. + %i++; + } + + %controlCount = %controlSet.getCount(); + if ( %controlCount == 1 ) + { + %control = %controlSet.getObject( 0 ); + %controlSet.delete(); + + return %control; + } + + return %controlSet; +} + +function VEditorPropertyList::InspectObject( %this, %object ) +{ + if ( %this.InspectorLocked ) + { + return; + } + + // Prevent Infinite Loops. + %this.InspectorLocked = true; + + %propertyList = %this; + while ( isObject( %propertyList ) ) + { + if ( !isObject( %propertyList.ControlCache ) ) + { + continue; + } + + if ( %propertyList.ControlCache.getClassName() !$= "SimSet" ) + { + // Single Control. + %targetStack = %propertyList.ControlCache.InspectObject( %object ); + } + else + { + // Multiple Controls. + %controlSet = %propertyList.ControlCache; + %controlCount = %controlSet.getCount(); + for ( %i = 0; %i < %controlCount; %i++ ) + { + %controlSet.getObject( %i ).InspectObject( %object ); + } + } + + // Get the Parent. + %propertyList = %propertyList.Parent; + } + + // All Done. + %this.InspectorLocked = false; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Selection.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Selection.cs new file mode 100644 index 000000000..1034044a2 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/Selection.cs @@ -0,0 +1,224 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +$VerveEditor::InspectorObject = 0; +$VerveEditor::SelectionSet = new SimSet(); + +//----------------------------------------------------------------------------- + +function VerveEditor::HasSelection() +{ + return ( isObject( $VerveEditor::InspectorObject ) || $VerveEditor::SelectionSet.getCount() > 0 ); +} + +//------------------------------------------------------------------------- + +function VerveEditor::OnSelectionUpdate() +{ + // Clear Inspector. + VerveEditorPropertyStack.ClearStack(); + + %selectionSet = $VerveEditor::SelectionSet; + %selectionCount = %selectionSet.getCount(); + if ( %selectionCount == 1 ) + { + // Fetch Object. + %selection = %selectionSet.getObject( 0 ); + + // Highlight + %selection.setStateOn( true ); + if ( isObject( %selection.SiblingControl ) ) + { + %selection.SiblingControl.setStateOn( true ); + } + + if ( isObject( %selection.Proxy ) ) + { + // Change Selection. + %selection = %selection.Proxy; + } + + if ( isObject( %selection ) ) + { + // Inspector Property List. + %selectionList = %selection.getClassName() @ "PropertyList"; + if ( isObject( %selectionList ) ) + { + // Inspect Object. + VerveEditor::InspectObject( %selection, %selectionList ); + } + + // Callback? + if ( %selection.isMethod( "onSelect" ) ) + { + %selection.onSelect(); + } + } + } + else + { + %selection = $VerveEditor::InspectorObject; + if ( isObject( %selection ) ) + { + // Callback? + if ( %selection.isMethod( "onDeselect" ) ) + { + %selection.onDeselect(); + } + } + + // Clear Inspector Object. + $VerveEditor::InspectorObject = 0; + + if ( %selectionCount == 0 ) + { + // Inspect Controller. + VerveEditor::InspectObject( $VerveEditor::Controller, VControllerPropertyList ); + } + } +} + +function VerveEditor::InspectObject( %object, %propertyList ) +{ + // Reference Inspected Object. + $VerveEditor::InspectorObject = %object; + + // Create Lists. + %propertyList.CreateInspector(); + + // Update Fields. + %propertyList.InspectObject( %object ); +} + +function VEditorSelectable::OnMouseEnter( %this, %position, %modifiers, %clickCount ) +{ + if ( isObject( %this.SiblingControl ) ) + { + %this.SiblingControl.setStateOn( true ); + } +} + +function VEditorSelectable::OnMouseLeave( %this, %position, %modifiers, %clickCount ) +{ + if ( isObject( %this.SiblingControl ) ) + { + %this.SiblingControl.setStateOn( %this.getState() ); + } +} + +function VEditorSelectable::OnRightMouseUp( %this, %position, %modifiers, %clickCount ) +{ + // Set Selection. + VerveEditor::SetSelection( %this ); + + // Repaint. + VerveEditorWindow.Repaint(); + + if ( %this.Proxy.isMethod( "DisplayContextMenu" ) ) + { + // Display Context Menu. + %this.Proxy.schedule( 32, "DisplayContextMenu", getWord( %position, 0 ), getWord( %position, 1 ) ); + } +} + +function VEditorSelectable::OnMouseUp( %this, %position, %modifiers, %clickCount ) +{ + switch ( %modifiers ) + { + case 0 : VerveEditor::SetSelection( %this ); + + case 4 : VerveEditor::ToggleSelection( %this ); + } +} + +function VEditorSelectable::OnAddSelection( %this ) +{ + %this.setStateOn( true ); + + if ( isObject( %this.SiblingControl ) ) + { + %this.SiblingControl.setStateOn( true ); + } + + // Set First Responder. + %this.setFirstResponder(); +} + +function VEditorSelectable::OnRemoveSelection( %this ) +{ + %this.setStateOn( false ); + + if ( isObject( %this.SiblingControl ) ) + { + %this.SiblingControl.setStateOn( false ); + } +} + +//------------------------------------------------------------------------- + +function VerveEditor::SetSelection( %object ) +{ + VerveEditor::ClearSelection(); + + VerveEditor::AddSelection( %object ); +} + +function VerveEditor::ClearSelection() +{ + $VerveEditor::Selection::SurpressCallback = true; + while ( $VerveEditor::SelectionSet.getCount() > 0 ) + { + VerveEditor::RemoveSelection( $VerveEditor::SelectionSet.getObject( 0 ) ); + } + + if ( $VerveEditor::Selection::SurpressCallback ) + { + VerveEditor::OnSelectionUpdate(); + } + + $VerveEditor::Selection::SurpressCallback = false; +} + +function VerveEditor::AddSelection( %object ) +{ + $VerveEditor::SelectionSet.add( %object ); + + if ( %object.isMethod( "OnAddSelection" ) ) + { + %object.OnAddSelection(); + } + + if ( !$VerveEditor::Selection::SurpressCallback ) + { + VerveEditor::OnSelectionUpdate(); + } +} + +function VerveEditor::RemoveSelection( %object ) +{ + $VerveEditor::SelectionSet.remove( %object ); + + if ( %object.isMethod( "OnRemoveSelection" ) ) + { + %object.OnRemoveSelection(); + } + + if ( !$VerveEditor::Selection::SurpressCallback ) + { + VerveEditor::OnSelectionUpdate(); + } +} + +function VerveEditor::ToggleSelection( %object ) +{ + if ( !$VerveEditor::SelectionSet.isMember( %object ) ) + { + VerveEditor::AddSelection( %object ); + } + else + { + VerveEditor::RemoveSelection( %object ); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/main.cs new file mode 100644 index 000000000..f8a840d02 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Inspector/main.cs @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitInspectorScripts() +{ + exec( "./Controls.cs" ); + exec( "./CutCopyPaste.cs" ); + exec( "./EventNotify.cs" ); + exec( "./Factory.cs" ); + exec( "./FactoryControls.cs" ); + exec( "./FieldNotify.cs" ); + exec( "./Lists.cs" ); + exec( "./Properties.cs" ); + exec( "./Selection.cs" ); + + exec( "./Fields/main.cs" ); +} +VerveEditor::InitInspectorScripts(); \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Persistence.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Persistence.cs new file mode 100644 index 000000000..7064061d6 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Persistence.cs @@ -0,0 +1,232 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +$VerveEditor::FilePath = "sequences"; +$VerveEditor::FileSpec = "Verve Sequence Files (*.vsf)|*.vsf|All Files (*.*)|*.*|"; + +//----------------------------------------------------------------------------- + +function VerveEditor::GetFileTarget( %type ) +{ + %filePath = $VerveEditor::FilePath; + if ( strlen( $Pref::VerveEditor::FilePath ) > 0 ) + { + %filePath = $Pref::VerveEditor::FilePath; + } + + %fileDialog = new ( %type @ "FileDialog" )() + { + Filters = $VerveEditor::FileSpec; + DefaultPath = %filePath; + ChangePath = false; + MustExist = true; + }; + + // Record the file name + %filename = ""; + if ( %fileDialog.Execute() ) + { + %filename = %fileDialog.FileName; + + // Store the preference + $Pref::VerveEditor::FilePath = makeRelativePath( filePath( %filename ), getMainDotCsDir() ); + } + + // Delete the dialog + %fileDialog.delete(); + + // Return the filename + return %filename; +} + +function VerveEditor::NewFile() +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + return; + } + + // Save? + if ( !VerveEditor::SavePrompt() ) + { + return; + } + + // Clear Sequence Lists. + $VerveEditor::Controller.clear(); + + // Clear File. + $VerveEditor::Controller.FileName = ""; + + // Reset Properties. + $VerveEditor::Controller.Time = 0; + $VerveEditor::Controller.Duration = 5000; + $VerveEditor::Controller.TimeScale = 1.0; + + // Clear Editor History. + VerveEditor::ClearHistory(); + + // Refresh Editor. + VerveEditor::Refresh(); +} + +function VerveEditor::LoadFile( %fileName ) +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + return; + } + + // Save? + if ( !VerveEditor::SavePrompt() ) + { + return; + } + + if ( %fileName $= "" ) + { + %fileName = VerveEditor::GetFileTarget( "Open" ); + } + + // Clear File. + $VerveEditor::Controller.FileName = ""; + + if ( $VerveEditor::Controller.readFile( %fileName ) ) + { + // Pause. + VerveEditor::Pause(); + + // Store the File. + $VerveEditor::Controller.FileName = %fileName; + + // Update File History. + VerveEditor::UpdateFileHistory( %fileName ); + + // Clear Editor History. + VerveEditor::ClearHistory(); + + // Refresh Editor. + VerveEditor::Refresh(); + + return true; + } + + // Argh! + // Attempting to load a file which results in failure means the existing + // sequence is messed up, ouch! Do something better than creating a new + // sequence... + VerveEditor::NewFile(); + + return false; +} + +function VerveEditor::SaveFile( %forceSaveAs ) +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + return false; + } + + %fileName = $VerveEditor::Controller.FileName; + if ( %forceSaveAs || %fileName $= "" ) + { + %fileName = VerveEditor::GetFileTarget( "Save" ); + if ( %fileName $= "" ) + { + // No Save. + return false; + } + } + + if ( fileExt( fileName( %fileName ) ) $= "" ) + { + // Add Extension. + %fileName = %fileName @ ".vsf"; + } + + // Write. + $VerveEditor::Controller.writeFile( %fileName ); + + // Store the File. + $VerveEditor::Controller.FileName = %fileName; + + // Update File History. + VerveEditor::UpdateFileHistory( %fileName ); + + // Clear Dirty. + VerveEditor::ClearDirty(); + + // Update Window Title. + VerveEditorWindow.UpdateWindowTitle(); + + // Valid Save. + return true; +} + +function VerveEditor::SavePrompt() +{ + if ( !VerveEditor::IsDirty() ) + { + return true; + } + + %result = messageBox( "Verve Editor", "Save Changes to your sequence?", "SaveDontSave", "Warning" ); + if ( %result $= $MROk ) + { + // Save. + return VerveEditor::SaveFile(); + } + + return true; +} + +function VerveEditor::SavePromptCancel() +{ + if ( !VerveEditor::IsDirty() ) + { + return true; + } + + %result = messageBox( "Verve Editor", "Save Changes to your sequence?", "SaveDontSaveCancel", "Warning" ); + if ( %result $= $MRCancel ) + { + return false; + } + + if ( %result $= $MROk ) + { + // Save. + return VerveEditor::SaveFile(); + } + + return true; +} + +function VerveEditor::UpdateFileHistory( %filePath ) +{ + // Make Relative. + %fileLabel = makeRelativePath( %filePath, getMainDotCsDir() ); + + // Select an Index. + %initIndex = $Pref::VerveEditor::RecentFileSize; + for ( %i = 0; %i < %initIndex; %i++ ) + { + %prefFile = $Pref::VerveEditor::RecentFile[%i]; + if ( %prefFile $= %fileLabel ) + { + %initIndex = %i; + break; + } + } + + // Push Others Down. + for ( %i = %initIndex; %i > 0; %i-- ) + { + $Pref::VerveEditor::RecentFile[%i] = $Pref::VerveEditor::RecentFile[%i - 1]; + } + + // Push to the Front. + $Pref::VerveEditor::RecentFile[0] = %fileLabel; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Plugin.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Plugin.cs new file mode 100644 index 000000000..df7c4efcc --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Plugin.cs @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +// Verve Editor +new ScriptObject( VerveEditorPlugin ) +{ + SuperClass = "EditorPlugin"; +}; + +//----------------------------------------------------------------------------- + +function VerveEditorPlugin::onWorldEditorStartup( %this ) +{ + //---------------------------------------------------------------------- + // + // Editor Toggles + // + //---------------------------------------------------------------------- + + // Add ourselves to the window menu. + %accel = EditorGui.addToEditorsMenu( "Verve Editor", "", VerveEditorPlugin ); + + // Add ourselves to the ToolsToolbar + %tooltip = "Verve Editor (" @ %accel @ ")"; + + // Add ourselves to the ToolsToolbar + EditorGui.addToToolsToolbar( "VerveEditorPlugin", "VerveEditorPluginPalette", expandFilename( "tools/VerveEditor/GUI/Images/btn_Palette" ), %tooltip ); + + // Find and Store the Button. + %this.ToolbarButton = ToolsToolbarArray.findObjectByInternalName( "VerveEditorPluginPalette", false ); + %this.ToolbarButton.ButtonType = "ToggleButton"; + + // Extend Width. + %extent = EWToolsToolbar.getExtent(); + EWToolsToolbar.setExtent( ( getWord( %extent, 0 ) + 33 ) SPC getWord( %extent, 1 ) ); +} + +function VerveEditorPlugin::setEditorFunction( %this ) +{ + if ( %this.ToolbarButton.getValue() ) + { + // Launch Editor. + VerveEditor::LaunchEditor(); + } + else + { + VerveEditorWindow.onWindowClose(); + } + + // Maintain Last Editor. + return false; +} + +function VerveEditorPlugin::onDeactivated( %this ) +{ + // Unchecked Box? + if ( %this.ToolbarButton.getValue() ) + { + return; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/ScrollNotify.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/ScrollNotify.cs new file mode 100644 index 000000000..11a522256 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/ScrollNotify.cs @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VEditorScrollControl::onScroll( %this ) +{ + %notifyObj = %this.getObject( 0 ); + if ( %notifyObj.isMethod( "onScroll" ) ) + { + %notifyObj.onScroll(); + } +} + +function VerveEditorScrollNotify::onWake( %this ) +{ + VerveEditorScrollNotifyV::onWake( %this ); + VerveEditorScrollNotifyH::onWake( %this ); +} + +function VerveEditorScrollNotify::onScroll( %this ) +{ + %this.onResize(); +} + +function VerveEditorScrollNotify::onResize( %this ) +{ + VerveEditorScrollNotifyV::onResize( %this ); + VerveEditorScrollNotifyH::onResize( %this ); +} + +function VerveEditorScrollNotify::onParentResized( %this ) +{ + %this.schedule( 32, "updateSize" ); +} + +function VerveEditorScrollNotify::updateSize( %this ) +{ + VerveEditorScrollNotifyH::updateSize( %this ); + VerveEditorScrollNotifyV::updateSize( %this ); +} + +//------------------------------------------------------------------------- + +function VerveEditorScrollNotifyV::onWake( %this ) +{ + if ( !isObject( $VerveEditor::ScrollNotifyVSet ) ) + { + $VerveEditor::ScrollNotifyVSet = new SimSet(); + } + + $VerveEditor::ScrollNotifyVSet.add( %this ); +} + +function VerveEditorScrollNotifyV::onScroll( %this ) +{ + %this.onResize(); +} + +function VerveEditorScrollNotifyV::onResize( %this ) +{ + if ( !isObject( $VerveEditor::ScrollNotifyVSet ) ) + { + // Not Awake Yet! + return; + } + + %scrollPosition = %this.getParent().getScrollPositionY(); + if ( !%this.SurpressUpdate ) + { + %refSet = $VerveEditor::ScrollNotifyVSet; + %refCount = %refSet.getCount(); + for ( %i = 0; %i < %refCount; %i++ ) + { + %refObject = %refSet.getObject( %i ).getParent(); + %refObject.SurpressUpdate = true; + %refObject.setScrollPosition( %refObject.getScrollPositionX(), %scrollPosition ); + %refObject.SurpressUpdate = false; + } + } +} + +function VerveEditorScrollNotifyV::onParentResized( %this ) +{ + %this.schedule( 32, "updateSize" ); +} + +function VerveEditorScrollNotifyV::updateSize( %this ) +{ + %minX = getWord( %this.getObject( 0 ).MinExtent, 0 ); + %minY = getWord( %this.getParent().getExtent(), 1 ) - 3; + %this.MinExtent = %minX SPC %minY; + + %newX = getWord( %this.getExtent(), 0 ); + %newY = getWord( VerveEditorTrackStack.getExtent(), 1 ); + %this.setExtent( %newX, %newY ); + + // The onResize callback isn't called if all we did was move around + %this.onResize(); +} + +//------------------------------------------------------------------------- + +function VerveEditorScrollNotifyH::onWake( %this ) +{ + if ( !isObject( $VerveEditor::ScrollNotifyHSet ) ) + { + $VerveEditor::ScrollNotifyHSet = new SimSet(); + } + + $VerveEditor::ScrollNotifyHSet.add( %this ); +} + +function VerveEditorScrollNotifyH::onScroll( %this ) +{ + %this.onResize(); +} + +function VerveEditorScrollNotifyH::onResize( %this ) +{ + if ( !isObject( $VerveEditor::ScrollNotifyHSet ) ) + { + // Not Awake Yet! + return; + } + + %scrollPosition = %this.getParent().getScrollPositionX(); + if ( !%this.SurpressUpdate ) + { + %refSet = $VerveEditor::ScrollNotifyHSet; + %refCount = %refSet.getCount(); + for ( %i = 0; %i < %refCount; %i++ ) + { + %refObject = %refSet.getObject( %i ).getParent(); + %refObject.SurpressUpdate = true; + %refObject.setScrollPosition( %scrollPosition, %refObject.getScrollPositionY() ); + %refObject.SurpressUpdate = false; + } + } +} + +function VerveEditorScrollNotifyH::onParentResized( %this ) +{ + %this.schedule( 32, "updateSize" ); +} + +function VerveEditorScrollNotifyH::updateSize( %this ) +{ + %this.MinExtent = %this.getObject( 0 ).MinExtent; + %this.setExtent( getWord( %this.getParent().getExtent(), 0 ) - 19, getWord( %this.getExtent(), 1 ) ); + + // The onResize callback isn't called if all we did was move around + %this.onResize(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VCameraShakeTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VCameraShakeTrack.cs new file mode 100644 index 000000000..c524d8421 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VCameraShakeTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VCameraShakeTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VCameraShakeTrack::CreateEvent( %this ) +{ + // Create Event. + return new VCameraShakeEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VDirectorTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VDirectorTrack.cs new file mode 100644 index 000000000..7bc197391 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VDirectorTrack.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VDirectorTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VDirectorTrack::Refresh( %this ) +{ + // Create Control. + %trackControl = Parent::Refresh( %this ); + + // Add Field Notify. + VObject::AddFieldNotify( $VerveEditor::Controller, "Duration", %this ); + + // Return Control. + return %trackControl; +} + +function VDirectorTrack::CreateEvent( %this ) +{ + // Create Event. + return new VDirectorEvent(); +} + +//------------------------------------------------------------------------- + +function VDirectorTrack::Update( %this ) +{ + // Root Update. + %this.UpdateTrack(); + + %trackControl = %this.Control.SiblingControl; + if ( !isObject( %trackControl ) ) + { + return; + } + + // Update GUI Elements. + %eventCount = %trackControl.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + // Get Control. + %eventControl = %trackControl.getObject( %i ); + + // Update. + %eventControl.Update(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VFadeTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VFadeTrack.cs new file mode 100644 index 000000000..54424180f --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VFadeTrack.cs @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VFadeTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VFadeTrack::CreateEvent( %this ) +{ + // Create Event. + return new VFadeEvent(); +} + +function VFadeTrack::Refresh( %this ) +{ + // Create Control. + %trackControl = Parent::Refresh( %this ); + + // Update Labels. + %this.Update(); + + // Return Track. + return %trackControl; +} + +function VFadeTrack::Update( %this ) +{ + %eventCount = %this.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + %eventObject = %this.getObject( %i ); + %eventButton = %eventObject.Control; + + // Set The Label. + %eventButton.Text = ( ( %i % 2 ) == 0 ) ? "Fade In" : "Fade Out"; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectAnimationTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectAnimationTrack.cs new file mode 100644 index 000000000..58b1e784a --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectAnimationTrack.cs @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VLightObjectAnimationTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; + + Group[0] = "Animation Track"; + Field[0, 0] = "AnimationData"; + Type[0, 0] = "VLightAnimationDataEnum"; +}; + +//----------------------------------------------------------------------------- + +function VLightObjectAnimationTrack::CreateEvent( %this ) +{ + // Create Event. + return new VLightObjectAnimationEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectToggleTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectToggleTrack.cs new file mode 100644 index 000000000..cde9e0c24 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VLightObjectToggleTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VLightObjectToggleTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VLightObjectToggleTrack::CreateEvent( %this ) +{ + // Create Event. + return new VLightObjectToggleEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VMotionTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VMotionTrack.cs new file mode 100644 index 000000000..2341988e9 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VMotionTrack.cs @@ -0,0 +1,264 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VMotionTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; + + Group[0] = "VMotionTrack"; + Field[0, 0] = "Reference"; + Type[0, 0] = "VControllerDataEnum"; + Field[0, 1] = "OrientationMode"; + Type[0, 1] = "VPathOrientationModeEnum"; + Field[0, 2] = "OrientationData"; + Field[0, 3] = "Relative"; +}; + +//----------------------------------------------------------------------------- + +function VMotionTrack::CreateEvent( %this, %canCreateNode ) +{ + if ( %canCreateNode $= "" ) %canCreateNode = true; + + // Fetch Object References. + %object = %this.getParent().getSceneObject(); + %path = %this.getPath(); + + if ( isObject( %object ) && isObject( %path ) ) + { + // Create Event. + %event = new VMotionEvent(); + + // Create a Node? + %createNode = ( %this.getCount() >= %path.getNodeCount() ); + if ( !%canCreateNode || !%createNode ) + { + // Return Event. + return %event; + } + + // Use Transform. + %transform = %object.getTransform(); + + // Object Attached? + if ( %path.isObjectAttached( %object ) ) + { + // Get Offset. + %positionOffset = %path.getPathObjectOffset( %object ); + + // Determine Real Position. + %newPosition = VectorSub( %object.getPosition(), %positionOffset ); + + // Set Transform. + %transform = %newPosition SPC getWords( %transform, 3 ); + } + else if ( %this.Relative && %path.getNodeCount() > 0 ) + { + // Fetch Node Position. + %nodePosition = %path.getNodeWorldPosition( 0 ); + + // Set Position. + %object.setTransform( %nodePosition SPC getWords( %transform, 3 ) ); + } + + // Create New Node. + %event.schedule( 32, "CreatePathNode", %transform ); + + // Return Event. + return %event; + } + + // No Object. + return 0; +} + +function VMotionTrack::OnSelect( %this ) +{ + // Fetch Path. + %path = %this.getPath(); + if ( !isObject( EVPathEditor ) || !isObject( %path ) ) + { + // No Editor. + return; + } + + // Update Selection. + EVPathEditor.setSelection( %path ); +} + +//----------------------------------------------------------------------------- + +function VMotionTrack::GetContextMenu( %this ) +{ + %contextMenu = $VerveEditor::VMotionTrack::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VTrackContextMenu"; + Position = 0; + + Item[0] = "&Add Event" TAB "" TAB "VEditorSelectableTrack::AddEvent();"; + + Item[1] = "" TAB ""; + + Item[2] = "&Import Path Nodes" TAB "" TAB "VMotionTrack::ImportPathNodes();"; + + Item[3] = "" TAB ""; + + Item[4] = "Cu&t" TAB "" TAB "VerveEditor::CutSelection();"; + Item[5] = "&Copy" TAB "" TAB "VerveEditor::CopySelection();"; + Item[6] = "&Paste" TAB "" TAB "VEditorSelectableTrack::PasteEvent();"; + + Item[7] = "" TAB ""; + + Item[8] = "&Delete" TAB "" TAB "VerveEditor::DeleteSelection();"; + + AddIndex = 0; + PasteIndex = 4; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VMotionTrack::ContextMenu = %contextMenu; + } + + // Return Menu. + return %contextMenu; +} + +function VMotionTrack::ImportPathNodes() +{ + if ( !VerveEditor::HasSelection() ) + { + // Invalid Selection. + return; + } + + %trackObject = $VerveEditor::InspectorObject; + if ( !%trackObject.isMemberOfClass( "VMotionTrack" ) ) + { + // Invalid Selection. + return; + } + + // Load the Import Options Dialog. + if($Verve::UseSeparateWindow) + VerveEditorWindow.pushDialog( VerveEditorImportPathNodesGUI ); + else + Canvas.pushDialog( VerveEditorImportPathNodesGUI ); +} + +function VMotionTrack::_ImportPathNodes( %speed ) +{ + // Awake? + if ( VerveEditorImportPathNodesGUI.isAwake() ) + { + // Close the GUI. + if($Verve::UseSeparateWindow) + VerveEditorWindow.popDialog( VerveEditorImportPathNodesGUI ); + else + Canvas.popDialog( VerveEditorImportPathNodesGUI ); + } + + if ( !VerveEditor::HasSelection() ) + { + // Invalid Selection. + return; + } + + %trackObject = $VerveEditor::InspectorObject; + if ( !%trackObject.isMemberOfClass( "VMotionTrack" ) ) + { + // Invalid Selection. + return; + } + + // Fetch the Controller. + %controller = %trackObject.getRoot(); + + // Group History Actions. + VerveEditor::ToggleHistoryGroup(); + + // Clear the Track. + while( %trackObject.getCount() > 0 ) + { + // Fetch Object. + %event = %trackObject.getObject( 0 ); + + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryDeleteObject"; + SuperClass = "VerveEditorHistoryObject"; + + ActionName = "Delete Object"; + + // Store Object References. + Parent = %trackObject; + Object = %event; + }; + + // Detach Object. + %trackObject.removeObject( %event ); + } + + // Fetch the Path. + %pathObject = %trackObject.getPath(); + + // New Duration. + %controllerDuration = 0; + // Last Event Time. + %lastEventTime = 0; + // Fetch the Node Count. + %nodeCount = %pathObject.getNodeCount(); + for ( %i = 0; %i < ( %nodeCount + %controller.Loop ); %i++ ) + { + // Create a new Event. + %newEvent = %trackObject.CreateEvent( false ); + + if ( %i > 0 ) + { + // Fetch the Node Length. + %nodeLength = %pathObject.getNodeLength( %i - 1 ); + // Determine the Trigger Time. + %triggerInterval = 1000 * ( %nodeLength / %speed ); + + // Determine the Trigger Time. + %lastEventTime = ( %lastEventTime + %triggerInterval ); + + // Update Duration. + %controllerDuration = %lastEventTime; + // Set the Event's Trigger Time. + %newEvent.TriggerTime = %lastEventTime; + } + + if ( %i < %nodeCount ) + { + // Add the Event. + %trackObject.addObject( %newEvent ); + } + + // Do Event Callback. + %newEvent.OnAdd(); + } + + // Set the Controller Duration. + %controller.setFieldValue( "Duration", %controllerDuration ); + + // Finish Up. + VerveEditor::ToggleHistoryGroup(); + + // Refresh the Editor. + VerveEditor::Refresh(); + + // Set Selection. + VerveEditor::SetSelection( %trackObject.Control ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VParticleEffectToggleTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VParticleEffectToggleTrack.cs new file mode 100644 index 000000000..9e0bc894a --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VParticleEffectToggleTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VParticleEffectToggleTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VParticleEffectToggleTrack::CreateEvent( %this ) +{ + // Create Event. + return new VParticleEffectToggleEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VPostEffectToggleTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VPostEffectToggleTrack.cs new file mode 100644 index 000000000..3d3618c65 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VPostEffectToggleTrack.cs @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VPostEffectToggleTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; + + Group[0] = "VPostEffectToggleTrack"; + Field[0, 0] = "PostEffect"; + Type[0, 0] = "VPostEffectEnum"; +}; + +//----------------------------------------------------------------------------- + +function VPostEffectToggleTrack::CreateEvent( %this ) +{ + // Create Event. + return new VPostEffectToggleEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSceneJumpTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSceneJumpTrack.cs new file mode 100644 index 000000000..59e5dd645 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSceneJumpTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSceneJumpTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VSceneJumpTrack::CreateEvent( %this ) +{ + // Create Event. + return new VSceneJumpEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VScriptEventTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VScriptEventTrack.cs new file mode 100644 index 000000000..eb891dcbf --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VScriptEventTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VScriptEventTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VScriptEventTrack::CreateEvent( %this ) +{ + // Create Event. + return new VScriptEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VShapeAnimationTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VShapeAnimationTrack.cs new file mode 100644 index 000000000..13ea7a0c8 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VShapeAnimationTrack.cs @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VShapeAnimationTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; + + Group[0] = "VShapeAnimationTrack"; + Field[0, 0] = "ThreadIndex"; +}; + +//----------------------------------------------------------------------------- + +function VShapeAnimationTrack::Refresh( %this ) +{ + // Create Control. + %trackControl = Parent::Refresh( %this ); + + // Add Field Notify. + VObject::AddFieldNotify( $VerveEditor::Controller, "Duration", %this ); + + // Object Reference Notify. + VObject::AddFieldNotify( %this.getParent(), "Reference", %this ); + + // Return Control. + return %trackControl; +} + +function VShapeAnimationTrack::CreateEvent( %this ) +{ + // Create Event. + return new VShapeAnimationEvent(); +} + +//------------------------------------------------------------------------- + +function VShapeAnimationTrack::Update( %this ) +{ + // Root Update. + %this.UpdateTrack(); + + %trackControl = %this.Control.SiblingControl; + if ( !isObject( %trackControl ) ) + { + return; + } + + // Update GUI Elements. + %eventCount = %trackControl.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + // Get Control. + %eventControl = %trackControl.getObject( %i ); + + // Update. + %eventControl.Update(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSlowMoTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSlowMoTrack.cs new file mode 100644 index 000000000..4afc92d6b --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSlowMoTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSlowMoTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VSlowMoTrack::CreateEvent( %this ) +{ + // Create Event. + return new VSlowMoEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSoundEffectTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSoundEffectTrack.cs new file mode 100644 index 000000000..ede0ef05c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSoundEffectTrack.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSoundEffectTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VSoundEffectTrack::CreateEvent( %this ) +{ + // Create Event. + return new VSoundEffectEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSpawnSphereSpawnTargetTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSpawnSphereSpawnTargetTrack.cs new file mode 100644 index 000000000..40ee01009 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VSpawnSphereSpawnTargetTrack.cs @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VSpawnSphereSpawnTargetTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; + + Group[0] = "Spawn Target Track"; + Field[0, 0] = "DespawnOnLoop"; + Field[0, 1] = "DespawnOnStop"; +}; + +//----------------------------------------------------------------------------- + +function VSpawnSphereSpawnTargetTrack::CreateEvent( %this ) +{ + // Create Event. + return new VSpawnSphereSpawnTargetEvent(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VTrack.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VTrack.cs new file mode 100644 index 000000000..a3cfb240c --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/VTrack.cs @@ -0,0 +1,266 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +new ScriptObject( VTrackPropertyList ) +{ + SuperClass = "VEditorPropertyList"; + Parent = "VObjectPropertyList"; +}; + +//----------------------------------------------------------------------------- + +function VTrack::OnAdd( %this ) +{ + %ourClass = %this.getClassName(); + if ( !isWordInList( %ourClass, $VerveEditor::NonUniqueTrackList ) ) + { + %group = %this.getParent(); + %trackCount = %group.getCount(); + for ( %i = 0; %i < %trackCount; %i++ ) + { + %trackObject = %group.getObject( %i ); + if ( %trackObject.getId() == %this.getId() ) + { + // Skip. + continue; + } + + if ( %trackObject.isMemberOfClass( %ourClass ) ) + { + // Alert Message. + messageBox( "Verve Editor", "You cannot have more than one \"" @ %ourClass @ "\" in a group.", "Ok", "Warning" ); + + // Invalid. + return false; + } + } + } + + // Regular Add. + return Parent::OnAdd( %this ); +} + +function VTrack::CanPaste( %this, %targetObject ) +{ + if ( !isObject( %targetObject ) ) + { + // Nope! + return false; + } + + return %targetObject.isMemberOfClass( "VEvent" ); +} + +function VTrack::Refresh( %this ) +{ + // Create Control. + %trackControl = VerveEditor::CreateTrackControl( %this ); + + %eventCount = %this.getCount(); + for ( %i = 0; %i < %eventCount; %i++ ) + { + %this.getObject( %i ).Refresh( %trackControl ); + } + + // Return Control. + return %trackControl; +} + +function VTrack::CreateEvent( %this ) +{ + // Create Event. + return new VEvent(); +} + +//------------------------------------------------------------------------- + +function VerveEditor::CreateTrackControl( %object ) +{ + %groupWidth = getWord( VerveEditorGroupStack.getExtent(), 0 ); + %groupHeight = 26; + %trackWidth = getWord( VerveEditorTrackStack.getExtent(), 0 ); + %trackHeight = %groupHeight; + + %groupContainer = new VEditorButton() + { + SuperClass = "VEditorSelectable"; + Class = "VEditorSelectableTrack"; + Profile = "VEditorTrackProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %groupWidth SPC %groupHeight; + + ButtonType = "ToggleButton"; + GroupNum = "-1"; + + IsContainer = "1"; + }; + VerveEditorGroupStack.add( %groupContainer ); + + %groupCheckbox = new GuiCheckBoxCtrl() + { + Class = "VEditorBoolPropertyField"; + InternalName = "Enabled"; + Profile = "VEditorCheckBoxProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 0"; + Extent = "14" SPC %trackHeight; + + Object = %object; + FieldName = "Enabled"; + Command = "$ThisControl.ApplyValue();"; + + Text = ""; + }; + %groupContainer.add( %groupCheckbox ); + + %trackContainer = new VEditorButton() + { + SuperClass = "VEditorSelectable"; + Class = "VEditorSelectableTrack"; + Profile = "VEditorTrackProfile"; + + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = %trackWidth SPC %trackHeight; + + ButtonType = "ToggleButton"; + GroupNum = "-1"; + + IsContainer = "1"; + }; + VerveEditorTrackStack.add( %trackContainer ); + + // Field Notify. + %object.AddFieldNotify( "Label", %groupContainer ); + %object.AddFieldNotify( "Enabled", %groupCheckbox ); + + // Reference Siblings. + %trackContainer.SiblingControl = %groupContainer; + %groupContainer.SiblingControl = %trackContainer; + + // Reference Proxy. + %groupContainer.Proxy = %object; + %trackContainer.Proxy = %object; + + // Reference Control. + %object.Control = %groupContainer; + + return %trackContainer; +} + +function VEditorSelectableTrack::Update( %this, %fieldName, %fieldValue ) +{ + %this.setText( %fieldValue ); +} + +function VTrack::GetContextMenu( %this ) +{ + %contextMenu = $VerveEditor::VTrack::ContextMenu; + if ( !isObject( %contextMenu ) ) + { + %contextMenu = new PopupMenu() + { + SuperClass = "VerveWindowMenu"; + + IsPopup = true; + + Label = "VTrackContextMenu"; + Position = 0; + + Item[0] = "&Add Event" TAB "" TAB "VEditorSelectableTrack::AddEvent();"; + + Item[1] = "" TAB ""; + + Item[2] = "Cu&t" TAB "" TAB "VerveEditor::CutSelection();"; + Item[3] = "&Copy" TAB "" TAB "VerveEditor::CopySelection();"; + Item[4] = "&Paste" TAB "" TAB "VEditorSelectableTrack::PasteEvent();"; + + Item[5] = "" TAB ""; + + Item[6] = "&Delete" TAB "" TAB "VerveEditor::DeleteSelection();"; + + AddIndex = 0; + PasteIndex = 4; + }; + %contextMenu.Init(); + + // Cache. + $VerveEditor::VTrack::ContextMenu = %contextMenu; + } + + // Return Menu. + return %contextMenu; +} + +function VTrack::DisplayContextMenu( %this, %x, %y ) +{ + // Fetch the Context Menu. + %contextMenu = %this.GetContextMenu(); + + // Fetch Track Control. + %trackControl = %this.Control.SiblingControl; + + // Enable If Track Stack Member. + %enableAdd = VerveEditorTrackStack.isMember( %trackControl ); + + if ( %enableAdd ) + { + // Time. + %time = VerveEditorTimeLine.toTime( %x - getWord( %trackControl.getGlobalPosition(), 0 ) ); + if ( %time < 0 || %time > $VerveEditor::Controller.Duration ) + { + // Disable. + %enableAdd = false; + } + + // Store Time. + %this.MouseTime = %time; + } + + // Enable/Disable Adding Events. + %contextMenu.enableItem( %contextMenu.AddIndex , %enableAdd ); + + // Enable/Disable Pasting. + %contextMenu.enableItem( %contextMenu.PasteIndex, %enableAdd & VerveEditor::CanPaste() ); + + // Display. + if($Verve::UseSeparateWindow) + %contextMenu.showPopup( VerveEditorWindow, %x, %y ); + else + %contextMenu.showPopup( Canvas, %x, %y ); +} + +function VEditorSelectableTrack::AddEvent() +{ + if ( !VerveEditor::HasSelection() ) + { + // Invalid Selection. + return; + } + + %trackObject = $VerveEditor::InspectorObject; + if ( !%trackObject.isMemberOfClass( "VTrack" ) ) + { + // Invalid Selection. + return; + } + + // Create Event. + VerveEditor::AddEvent( %trackObject, %trackObject.MouseTime ); + + // Clear. + %trackObject.MouseTime = ""; +} + +function VEditorSelectableTrack::PasteEvent() +{ + // Void. +} diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/main.cs new file mode 100644 index 000000000..7460e1364 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Tracks/main.cs @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VerveEditor::InitTrackScripts() +{ + // Core. + exec( "./VTrack.cs" ); + + // Built-In. + exec( "./VCameraShakeTrack.cs" ); + exec( "./VDirectorTrack.cs" ); + exec( "./VFadeTrack.cs" ); + exec( "./VLightObjectAnimationTrack.cs" ); + exec( "./VLightObjectToggleTrack.cs" ); + exec( "./VMotionTrack.cs" ); + exec( "./VParticleEffectToggleTrack.cs" ); + exec( "./VPostEffectToggleTrack.cs" ); + exec( "./VSceneJumpTrack.cs" ); + exec( "./VScriptEventTrack.cs" ); + exec( "./VShapeAnimationTrack.cs" ); + exec( "./VSlowMoTrack.cs" ); + exec( "./VSoundEffectTrack.cs" ); + exec( "./VSpawnSphereSpawnTargetTrack.cs" ); + + // Custom. + // Exec Custom Track Scripts. + + // Non-Unique Group List. + $VerveEditor::NonUniqueTrackList = "VTrack VPostEffectToggleTrack VSoundEffectTrack"; +} +VerveEditor::InitTrackScripts(); diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/Utility.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Utility.cs new file mode 100644 index 000000000..4a63d6484 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/Utility.cs @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Class +// +//----------------------------------------------------------------------------- + +function SimObject::isMemberOfClassList( %this, %typeList ) +{ + %typeCount = getWordCount( %typeList ); + for ( %i = 0; %i < %typeCount; %i++ ) + { + if ( %this.isMemberOfClass( getWord( %typeList, %i ) ) ) + { + return true; + } + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// GUI +// +//----------------------------------------------------------------------------- + +function GuiControl::getParentOfType( %this, %className ) +{ + %parent = %this.getParent(); + while ( isObject( %parent ) ) + { + if ( %parent.isMemberOfClass( %className ) ) + { + return %parent; + } + + %parent = %parent.getParent(); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// MATH +// +//----------------------------------------------------------------------------- + +function mRound( %number, %delta ) +{ + return ( mFloor( %number / %delta + 0.5 ) * %delta ); +} + +//----------------------------------------------------------------------------- +// +// STRING +// +//----------------------------------------------------------------------------- + +function isWordInList( %word, %list ) +{ + %wordCount = getWordCount( %list ); + for ( %i = 0; %i < %wordCount; %i++ ) + { + if ( getWord( %list, %i ) $= %word ) + { + return true; + } + } + + return false; +} + +function sortWordList( %list ) +{ + %wordCount = getWordCount( %list ); + for ( %j = 0; %j < %wordCount; %j++ ) + { + for ( %i = %wordCount - 1; %i > %j; %i-- ) + { + %wordA = getWord( %list, %i - 0 ); + %wordB = getWord( %list, %i - 1 ); + + // Compare and swap if needed + if ( strcmp( strlwr( %wordA ), strlwr( %wordB ) ) < 0 ) + { + %list = setWord( %list, %i - 1, %wordA ); + %list = setWord( %list, %i - 0, %wordB ); + } + } + } + + return %list; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Scripts/VObject.cs b/Templates/BaseGame/game/tools/VerveEditor/Scripts/VObject.cs new file mode 100644 index 000000000..689b0a478 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Scripts/VObject.cs @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function VObject::OnAdd( %this ) +{ + // Fetch Parent. + %parentObject = %this.getParent(); + %rootObject = %this.getRoot(); + if ( !%parentObject || ( %rootObject.getId() != $VerveEditor::Controller.getId() ) ) + { + return true; + } + + if ( !VerveEditorHistoryManager.Locked ) + { + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryCreateObject"; + SuperClass = "VerveEditorHistoryObject"; + + ActionName = "Create Object"; + + // Store Object References. + Parent = %parentObject; + Object = %this; + }; + } + + // Valid. + return true; +} + +function VObject::OnRemove( %this ) +{ + // Void. +} + +function VObject::Delete( %this ) +{ + // Fetch Parent. + %parentObject = %this.getParent(); + %rootObject = %this.getRoot(); + if ( !%parentObject || ( %rootObject.getId() != $VerveEditor::Controller.getId() ) ) + { + // Callback. + %this.OnRemove(); + + // Not Editing, Delete. + Parent::delete( %this ); + return; + } + + if ( !VerveEditorHistoryManager.Locked ) + { + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryDeleteObject"; + SuperClass = "VerveEditorHistoryObject"; + + ActionName = "Delete Object"; + + // Store Object References. + Parent = %parentObject; + Object = %this; + }; + } + + // Callback. + %this.OnRemove(); + + // Detach Object. + %parentObject.removeObject( %this ); +} + +function VObject::OnFieldChange( %this, %fieldName, %oldValue, %newValue ) +{ + if ( !VerveEditorHistoryManager.Locked ) + { + // Add History Item. + %historyObject = new UndoScriptAction() + { + Class = "VerveEditorHistoryChangeProperty"; + SuperClass = "VerveEditorHistoryObject"; + + ActionName = "Change Property (" @ %fieldName @ ")"; + + // Store References. + Object = %this; + FieldName = %fieldName; + OldValue = %oldValue; + NewValue = %newValue; + }; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VCameraGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VCameraGroup.vsf new file mode 100644 index 000000000..f39e0da62 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VCameraGroup.vsf @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VCameraGroup"> + <Properties> + <Label>CameraGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Label>MotionTrack</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + </VObject> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VDirectorGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VDirectorGroup.vsf new file mode 100644 index 000000000..cecc7f685 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VDirectorGroup.vsf @@ -0,0 +1,16 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VDirectorGroup"> + <Properties> + <Label>DirectorGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + <VObject Type="VDirectorTrack"> + <Properties> + <Label>DirectorTrack</Label> + <Enabled>1</Enabled> + </Properties> + </VObject> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VGroup.vsf new file mode 100644 index 000000000..320de6a88 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VGroup.vsf @@ -0,0 +1,10 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VGroup"> + <Properties> + <Label>EmptyGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VLightObjectGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VLightObjectGroup.vsf new file mode 100644 index 000000000..009b73919 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VLightObjectGroup.vsf @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VLightObjectGroup"> + <Properties> + <Label>LightObjectGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + <VObject Type="VLightObjectToggleTrack"> + <Properties> + <Label>ToggleTrack</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + </VObject> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VParticleEffectGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VParticleEffectGroup.vsf new file mode 100644 index 000000000..f199f8ddc --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VParticleEffectGroup.vsf @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VParticleEffectGroup"> + <Properties> + <Label>ParticleEffectGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + <VObject Type="VParticleEffectToggleTrack"> + <Properties> + <Label>ToggleTrack</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + </VObject> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Templates/VSceneObjectGroup.vsf b/Templates/BaseGame/game/tools/VerveEditor/Templates/VSceneObjectGroup.vsf new file mode 100644 index 000000000..2010c3eef --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Templates/VSceneObjectGroup.vsf @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> +<VerveControllerSequence Version="0.0.0a"> + <VObject Type="VSceneObjectGroup"> + <Properties> + <Label>SceneObjectGroup</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + <VObject Type="VMotionTrack"> + <Properties> + <Label>MotionTrack</Label> + <Enabled>1</Enabled> + <Reference /> + </Properties> + </VObject> + </VObject> +</VerveControllerSequence> \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Torque/ObjectClasses.cs b/Templates/BaseGame/game/tools/VerveEditor/Torque/ObjectClasses.cs new file mode 100644 index 000000000..58bd02bba --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Torque/ObjectClasses.cs @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Torque3D +// +//----------------------------------------------------------------------------- + +function VTorque::isSceneObject( %object ) +{ + return ( isObject( %object ) && %object.isMemberOfClass( "SceneObject" ) ); +} + +function VTorque::isCameraObject( %object ) +{ + return ( isObject( %object ) && %object.isMemberOfClass( "GameBase" ) ); +} + +function VTorque::getLightObjectClass() +{ + return "LightBase"; +} + +function VTorque::isLightObject( %object ) +{ + return ( isObject( %object ) && %object.isMemberOfClass( "LightBase" ) ); +} + +function VTorque::isSpawnSphereObject( %object ) +{ + return ( isObject( %object ) && %object.isMemberOfClass( "SpawnSphere" ) ); +} + +function VTorque::getParticleEffectClass() +{ + return "ParticleEmitterNode"; +} + +function VTorque::isParticleEffect( %object ) +{ + return ( isObject( %object ) && %object.isMemberOfClass( "ParticleEmitterNode" ) ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Torque/Selection.cs b/Templates/BaseGame/game/tools/VerveEditor/Torque/Selection.cs new file mode 100644 index 000000000..1bd934e58 --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Torque/Selection.cs @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Torque3D +// +//----------------------------------------------------------------------------- + +function VTorque::GetSelectedCount() +{ + if ( !isObject( EWorldEditor ) ) + { + // Null. + return 0; + } + + // Return Count. + return EWorldEditor.getSelectionSize(); +} + +function VTorque::GetSelectedObject( %index ) +{ + if ( !isObject( EWorldEditor ) ) + { + // Null. + return 0; + } + + // Init Index. + if ( %index $= "" ) + { + %index = 0; + } + + // Return Object. + return EWorldEditor.getSelectedObject( %index ); +} + +function VTorque::SetSelectedObject( %object ) +{ + if ( !isObject( EWorldEditor ) ) + { + return; + } + + EWorldEditor.selectObject( %object ); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/VerveEditor/Torque/main.cs b/Templates/BaseGame/game/tools/VerveEditor/Torque/main.cs new file mode 100644 index 000000000..468707b4b --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/Torque/main.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Torque3D +// +//----------------------------------------------------------------------------- + +function VerveEditor::InitTorqueScripts() +{ + // Core. + exec( "./ObjectClasses.cs" ); + exec( "./Selection.cs" ); +} +VerveEditor::InitTorqueScripts(); diff --git a/Templates/BaseGame/game/tools/VerveEditor/main.cs b/Templates/BaseGame/game/tools/VerveEditor/main.cs new file mode 100644 index 000000000..6fcc802db --- /dev/null +++ b/Templates/BaseGame/game/tools/VerveEditor/main.cs @@ -0,0 +1,234 @@ +//----------------------------------------------------------------------------- +// Verve +// Copyright (C) - Violent Tulip +//----------------------------------------------------------------------------- + +function InitializeVerveEditor() +{ + $Verve::UseSeparateWindow = false; + + // Preferences. + exec( "./DefaultPrefs.cs" ); + + // GUI. + exec( "./GUI/GuiProfiles.cs" ); + exec( "./GUI/VerveEditorGroupBuilder.gui" ); + exec( "./GUI/VerveEditorImportPathNodes.gui" ); + + // Scripts. + exec( "./Scripts/Plugin.cs" ); + exec( "./Scripts/Utility.cs" ); + + exec( "./Scripts/EditorControls.cs" ); + exec( "./Scripts/EditorHistory.cs" ); + exec( "./Scripts/EditorMenu.cs" ); + exec( "./Scripts/EditorPreferences.cs" ); + exec( "./Scripts/EditorWindow.cs" ); + exec( "./Scripts/Persistence.cs" ); + exec( "./Scripts/ScrollNotify.cs" ); + exec( "./Scripts/VObject.cs" ); + + exec( "./Scripts/Inspector/main.cs" ); + + exec( "./Scripts/Controller/main.cs" ); + exec( "./Scripts/Groups/main.cs" ); + exec( "./Scripts/Tracks/main.cs" ); + exec( "./Scripts/Events/main.cs" ); + + exec( "./Torque/main.cs" ); + + // Register Events. + VerveEditor::RegisterEvent( "VGroupObjectUpdate" ); +} + +function DestroyVerveEditor() +{ + // Ensure the Editor has Shutdown. + if ( isObject( VerveEditorWindow ) ) + { + // Prompt for Save. + VerveEditor::SavePrompt(); + + // Reset. + VerveEditor::Reset(); + + // Delete the Window. + VerveEditorWindow.delete(); + } +} + +function ToggleVerveEditor( %value ) +{ + if ( %value && $Verve::UseSeparateWindow ) + { + if ( !isObject( VerveEditorWindow ) ) + { + VerveEditor::LaunchEditor(); + } + else + { + VerveEditorWindow.onWindowClose(); + } + } +} + +function VerveEditor::LaunchEditor() +{ + // Launch Window. + %mainScreen = VerveEditorWindow::Open(); + + if ( !isObject( VerveEditorGui ) ) + { + // Load the GUI. + exec ( "./GUI/VerveEditor.gui" ); + } + + // Apply GUI. + if($Verve::UseSeparateWindow) + %mainScreen.setContent( VerveEditorGUI ); + else + { + %mainScreen.add(VerveEditorGUI); + VerveEditorGUI.position.y = VerveEditorGUI.Position.y + 20; + EditorGUI.add(%mainScreen); + } + + // Clear History. + VerveEditor::ClearHistory(); + + // Update Window Title. + if($Verve::UseSeparateWindow) + VerveEditorWindow.UpdateWindowTitle(); + + // Update Selection. + VerveEditor::OnSelectionUpdate(); + + // Update Sizes. + VerveEditor::UpdateSizes(); +} + +function VerveEditor::ResetController() +{ + // Delete. + VerveEditor::DeleteController(); + // Create. + return VerveEditor::CreateController(); +} + +function VerveEditor::DeleteController() +{ + // Current Controller? + if ( isObject( $VerveEditor::Controller ) ) + { + // Stop but do not Reset. + $VerveEditor::Controller.stop( false ); + // Delete the Controller. + $VerveEditor::Controller.delete(); + // Deleted? + return !isObject( $VerveEditor::Controller ); + } + + // No Deletion. + return false; +} + +function VerveEditor::CreateController() +{ + // Current Controller? + if ( !isObject( VerveEditorController ) ) + { + // Create Controller. + $VerveEditor::Controller = new VController( VerveEditorController ); + } + + // Return ID. + return $VerveEditor::Controller; +} + +function VerveEditor::Refresh() +{ + if ( !isObject( $VerveEditor::Controller ) ) + { + return; + } + + // Clear Selection. + VerveEditor::ClearSelection(); + + // Delete Existing Controls. + VerveEditor::DeleteControls(); + + // Sort Groups & Tracks. + $VerveEditor::Controller.sortGroups(); + $VerveEditor::Controller.sortTracks(); + + %groupSet = $VerveEditor::Controller; + %groupCount = %groupSet.getCount(); + for ( %i = 0; %i < %groupCount; %i++ ) + { + // Update Controls. + %groupSet.getObject( %i ).Refresh(); + } + + // Update Window Title. + VerveEditorWindow.UpdateWindowTitle(); + + // Update Duration. + VerveEditor::UpdateDuration(); + + // Update Sizes. + VerveEditor::UpdateSizes(); + + // Update Selection. + VerveEditor::OnSelectionUpdate(); +} + +function VerveEditor::UpdateSizes() +{ + VerveEditorGroupNotify.UpdateSize(); + VerveEditorTrackNotify.UpdateSize(); + VerveEditorTimeNotify.UpdateSize(); +} + +function VerveEditor::UpdateDuration( %duration ) +{ + if ( %duration !$= "" ) + { + // Update Duration. + $VerveEditor::Controller.setFieldValue( "Duration", %duration ); + } + + // Update Duration. + VerveEditorTimeLine.updateDuration(); + VerveEditorTrackTimeLine.updateDuration(); + + // Update Sizes. + VerveEditorGroupNotify.UpdateSize(); + VerveEditorTrackNotify.UpdateSize(); + VerveEditorTimeNotify.UpdateSize(); +} + +package VerveEditorSaveIntercept +{ + function EditorSaveMission() + { + // Reset. + VerveEditor::Reset(); + + // Perform the Save. + Parent::EditorSaveMission(); + } +}; + +function VerveEditor::Reset() +{ + // Valid Controller? + if ( isObject( $VerveEditor::Controller ) ) + { + // Reset. + $VerveEditor::Controller.Reset(); + + // Stop. + $VerveEditor::Controller.Stop(); + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/settings.xml b/Templates/BaseGame/game/tools/settings.xml index 761b16978..65cbd220b 100644 --- a/Templates/BaseGame/game/tools/settings.xml +++ b/Templates/BaseGame/game/tools/settings.xml @@ -1,80 +1,116 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <EditorSettings> <Group name="AxisGizmo"> - <Setting name="axisGizmoMaxScreenLen">100</Setting> - <Setting name="snapRotations">0</Setting> <Setting name="mouseScaleScalar">0.8</Setting> <Setting name="renderInfoText">1</Setting> <Setting name="rotationSnap">15</Setting> <Setting name="mouseRotateScalar">0.8</Setting> <Setting name="renderWhenUsed">0</Setting> + <Setting name="axisGizmoMaxScreenLen">100</Setting> + <Setting name="snapRotations">0</Setting> <Group name="Grid"> - <Setting name="planeDim">500</Setting> - <Setting name="gridColor">255 255 255 20</Setting> <Setting name="snapToGrid">0</Setting> - <Setting name="renderPlaneHashes">0</Setting> <Setting name="gridSize">10 10 10</Setting> <Setting name="renderPlane">0</Setting> + <Setting name="gridColor">255 255 255 20</Setting> + <Setting name="planeDim">500</Setting> + <Setting name="renderPlaneHashes">0</Setting> </Group> </Group> <Group name="WorldEditor"> + <Setting name="orthoShowGrid">1</Setting> <Setting name="dropType">screenCenter</Setting> <Setting name="forceLoadDAE">0</Setting> <Setting name="orthoFOV">50</Setting> <Setting name="currentEditor">WorldEditorInspectorPlugin</Setting> <Setting name="undoLimit">40</Setting> <Setting name="displayType">6</Setting> - <Setting name="orthoShowGrid">1</Setting> - <Group name="Tools"> - <Setting name="snapSoft">0</Setting> - <Setting name="boundingBoxCollision">0</Setting> - <Setting name="snapGround">0</Setting> - <Setting name="dropAtScreenCenterMax">100</Setting> - <Setting name="snapSoftSize">2</Setting> - <Setting name="dropAtScreenCenterScalar">1</Setting> - <Setting name="objectsUseBoxCenter">1</Setting> - </Group> - <Group name="Docs"> - <Setting name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting> - <Setting name="documentationLocal">../../../Documentation/Official Documentation.html</Setting> - <Setting name="forumURL">http://www.garagegames.com/products/torque-3d/forums</Setting> - <Setting name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting> - </Group> - <Group name="Grid"> - <Setting name="gridOriginColor">255 255 255 100</Setting> - <Setting name="gridSize">1</Setting> - <Setting name="gridColor">102 102 102 100</Setting> - <Setting name="gridMinorColor">51 51 51 100</Setting> - <Setting name="gridSnap">0</Setting> + <Group name="Color"> + <Setting name="popupBackgroundColor">100 100 100 255</Setting> + <Setting name="objMouseOverColor">0 255 0 255</Setting> + <Setting name="dragRectColor">255 255 0 255</Setting> + <Setting name="objMouseOverSelectColor">0 0 255 255</Setting> + <Setting name="selectionBoxColor">255 255 0 255</Setting> + <Setting name="objSelectColor">255 0 0 255</Setting> + <Setting name="objectTextColor">255 255 255 255</Setting> </Group> <Group name="Images"> - <Setting name="lockedHandle">tools/worldEditor/images/LockedHandle</Setting> <Setting name="defaultHandle">tools/worldEditor/images/DefaultHandle</Setting> + <Setting name="lockedHandle">tools/worldEditor/images/LockedHandle</Setting> <Setting name="selectHandle">tools/worldEditor/images/SelectHandle</Setting> </Group> <Group name="Render"> - <Setting name="showMousePopupInfo">1</Setting> - <Setting name="renderObjHandle">1</Setting> <Setting name="renderSelectionBox">1</Setting> <Setting name="renderPopupBackground">1</Setting> + <Setting name="renderObjHandle">1</Setting> + <Setting name="showMousePopupInfo">1</Setting> <Setting name="renderObjText">1</Setting> </Group> - <Group name="Color"> - <Setting name="objMouseOverColor">0 255 0 255</Setting> - <Setting name="popupBackgroundColor">100 100 100 255</Setting> - <Setting name="objectTextColor">255 255 255 255</Setting> - <Setting name="objSelectColor">255 0 0 255</Setting> - <Setting name="selectionBoxColor">255 255 0 255</Setting> - <Setting name="objMouseOverSelectColor">0 0 255 255</Setting> - <Setting name="dragRectColor">255 255 0 255</Setting> + <Group name="Grid"> + <Setting name="gridSize">1</Setting> + <Setting name="gridSnap">0</Setting> + <Setting name="gridColor">102 102 102 100</Setting> + <Setting name="gridOriginColor">255 255 255 100</Setting> + <Setting name="gridMinorColor">51 51 51 100</Setting> + </Group> + <Group name="Tools"> + <Setting name="snapGround">0</Setting> + <Setting name="snapSoftSize">2</Setting> + <Setting name="objectsUseBoxCenter">1</Setting> + <Setting name="snapSoft">0</Setting> + <Setting name="dropAtScreenCenterScalar">1</Setting> + <Setting name="boundingBoxCollision">0</Setting> + <Setting name="dropAtScreenCenterMax">100</Setting> </Group> <Group name="ObjectIcons"> - <Setting name="fadeIconsStartDist">8</Setting> - <Setting name="fadeIcons">1</Setting> <Setting name="fadeIconsEndAlpha">0</Setting> - <Setting name="fadeIconsStartAlpha">255</Setting> + <Setting name="fadeIcons">1</Setting> + <Setting name="fadeIconsStartDist">8</Setting> <Setting name="fadeIconsEndDist">20</Setting> + <Setting name="fadeIconsStartAlpha">255</Setting> </Group> + <Group name="Docs"> + <Setting name="forumURL">http://www.garagegames.com/products/torque-3d/forums</Setting> + <Setting name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting> + <Setting name="documentationLocal">../../../Documentation/Official Documentation.html</Setting> + <Setting name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting> + </Group> + </Group> + <Group name="GuiEditor"> + <Setting name="previewResolution">1024 768</Setting> + <Group name="EngineDevelopment"> + <Setting name="showEditorGuis">0</Setting> + <Setting name="toggleIntoEditor">0</Setting> + <Setting name="showEditorProfiles">0</Setting> + </Group> + <Group name="Snapping"> + <Setting name="snapToCanvas">1</Setting> + <Setting name="snapToEdges">1</Setting> + <Setting name="snapToCenters">1</Setting> + <Setting name="sensitivity">2</Setting> + <Setting name="snap2Grid">0</Setting> + <Setting name="snap2GridSize">8</Setting> + <Setting name="snapToGuides">1</Setting> + <Setting name="snapToControls">1</Setting> + </Group> + <Group name="Help"> + <Setting name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting> + <Setting name="documentationLocal">../../../Documentation/Official Documentation.html</Setting> + <Setting name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting> + </Group> + <Group name="Rendering"> + <Setting name="drawGuides">1</Setting> + <Setting name="drawBorderLines">1</Setting> + </Group> + <Group name="Library"> + <Setting name="viewType">Categorized</Setting> + </Group> + <Group name="Selection"> + <Setting name="fullBox">0</Setting> + </Group> + </Group> + <Group name="NavEditor"> + <Setting name="SpawnClass">AIPlayer</Setting> </Group> <Group name="LevelInformation"> <Setting name="levelsDirectory">data/FPSGameplay/levels</Setting> @@ -84,7 +120,4 @@ </Group> </Group> </Group> - <Group name="NavEditor"> - <Setting name="SpawnClass">AIPlayer</Setting> - </Group> </EditorSettings> diff --git a/Templates/Full/game/art/datablocks/datablockExec.cs b/Templates/Full/game/art/datablocks/datablockExec.cs index 0c66f7df7..f1b874159 100644 --- a/Templates/Full/game/art/datablocks/datablockExec.cs +++ b/Templates/Full/game/art/datablocks/datablockExec.cs @@ -64,4 +64,11 @@ exec("./aiPlayer.cs"); exec("./vehicles/cheetahCar.cs"); // Physics objects -exec("./physics.cs"); \ No newline at end of file +exec("./physics.cs"); + +if(isFile("./verve/VerveActorData.cs")) +{ + // Load Verve Data. + exec("./verve/VerveActorData.cs"); + exec("./verve/VervePathTutorialData.cs"); +} \ No newline at end of file diff --git a/Tools/CMake/modules/module_verve.cmake b/Tools/CMake/modules/module_verve.cmake new file mode 100644 index 000000000..e789f4a68 --- /dev/null +++ b/Tools/CMake/modules/module_verve.cmake @@ -0,0 +1,31 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +option(TORQUE_VERVE_ENABLED "Enable Verve module" ON) +option(TORQUE_VERVE_TOOLS_ENABLED "Enable Verve's Tools" ON) +if(TORQUE_VERVE_ENABLED) + addPathRec( "${srcDir}/Verve" ) +endif() + +if(TORQUE_VERVE_ENABLED) + addDef(VT_EDITOR) +endif() \ No newline at end of file diff --git a/Tools/CMake/torque3d.cmake b/Tools/CMake/torque3d.cmake index d827663f5..f425a89fa 100644 --- a/Tools/CMake/torque3d.cmake +++ b/Tools/CMake/torque3d.cmake @@ -348,6 +348,14 @@ addPathRec("${srcDir}/ts/collada") addPathRec("${srcDir}/ts/loader") addPathRec("${projectSrcDir}") +# Load module-based files +if(EXISTS ${TORQUE_APP_DIR}/game/data) + message("Reading modules in ${TORQUE_APP_DIR}/game/data path...") + + addInclude("${TORQUE_APP_DIR}/game/data") + addPathRec("${TORQUE_APP_DIR}/game/data") +endif() + ############################################################################### # modular paths ###############################################################################